Create rule S7104: Generic function type syntax should be preferred for parameters (use_function_type_syntax_for_parameters) (#4344)
Co-authored-by: antonioaversa <antonioaversa@users.noreply.github.com>
This commit is contained in:
parent
b7cd8c2b52
commit
b7b99233f3
24
rules/S7104/dart/metadata.json
Normal file
24
rules/S7104/dart/metadata.json
Normal file
@ -0,0 +1,24 @@
|
||||
{
|
||||
"title": "Generic function type syntax should be preferred for parameters",
|
||||
"type": "CODE_SMELL",
|
||||
"status": "ready",
|
||||
"remediation": {
|
||||
"func": "Constant\/Issue",
|
||||
"constantCost": "3min"
|
||||
},
|
||||
"tags": [
|
||||
"brain-overload"
|
||||
],
|
||||
"defaultSeverity": "Major",
|
||||
"ruleSpecification": "RSPEC-7104",
|
||||
"sqKey": "S7104",
|
||||
"scope": "All",
|
||||
"defaultQualityProfiles": ["Sonar way"],
|
||||
"quickfix": "unknown",
|
||||
"code": {
|
||||
"impacts": {
|
||||
"MAINTAINABILITY": "HIGH"
|
||||
},
|
||||
"attribute": "CLEAR"
|
||||
}
|
||||
}
|
122
rules/S7104/dart/rule.adoc
Normal file
122
rules/S7104/dart/rule.adoc
Normal file
@ -0,0 +1,122 @@
|
||||
Function parameters of type "function" should be declared using generic function type syntax.
|
||||
|
||||
== Why is this an issue?
|
||||
|
||||
There are two ways of defining a function or method parameter type, when such type is a flavor of `Function` that needs to be defined inline:
|
||||
|
||||
* using the *generic function syntax*: `void Function(int) parameterName`
|
||||
* using the *legacy function syntax*: `void parameterName(int)`
|
||||
|
||||
The first option should be preferred in all circumstances, for the following reasons:
|
||||
|
||||
* readability
|
||||
* consistency
|
||||
|
||||
=== Readability
|
||||
|
||||
Unlike non-`Function` type, which always preceed the parameter name (e.g. `int x`, `List<int> y`, `Map<String, double>? z`, etc.), `Function` types expressed using the legacy syntax are intermingled with the parameter name.
|
||||
Specifically, part of the type, namely the return type of the `Function`, is placed before the parameter name, whereas the list of formal parameters of the `Function` is placed after.
|
||||
|
||||
[source,dart]
|
||||
----
|
||||
void aFunction(void parameterName(int functionParameterName)) {
|
||||
// ...
|
||||
}
|
||||
----
|
||||
|
||||
That makes the code harder to read and understand. For instance, it's not easy to tell at a first glance that `functionParameterName` is _not_ a parameter of `aFunction`, but a parameter of the `Function` parameter `parameterName` of `aFunction`.
|
||||
|
||||
=== Consistency
|
||||
|
||||
Pretty much like the function syntax, also the `typedef` syntax has two forms:
|
||||
|
||||
* the *generic `typedef` syntax*: `typedef void MyFunction(int);`
|
||||
* the *legacy `typedef` syntax*: `typedef MyFunction = void Function(int);`
|
||||
|
||||
The first option is more powerful and flexible, as explained in S5416.
|
||||
|
||||
The generic `typedef` syntax matches syntactically the generic function syntax defined inline. Using syntaxes consistently allows easier code maintenance and refactoring.
|
||||
|
||||
For example if an inline generic function syntax needs to be extracted into a generic `typedef` syntax, for its complexity, number of occurrences, or to be exposed outside the current library, the refactoring is easier and less error-prone, since the right-end side of the `typedef` is the same as the inline type definition.
|
||||
|
||||
[source,dart]
|
||||
----
|
||||
// Before extraction of typedef using generic syntax
|
||||
void aFunction(void Function(int functionParameterName) parameterName) {
|
||||
// ...
|
||||
}
|
||||
|
||||
// After extraction of typedef using generic syntax
|
||||
typedef MyFunction = void Function(int functionParameterName);
|
||||
void aFunction(MyFunction parameterName) {
|
||||
// ...
|
||||
}
|
||||
----
|
||||
|
||||
The same is not true for the legacy syntax:
|
||||
|
||||
[source,dart]
|
||||
----
|
||||
// Before extraction of typedef using legacy syntax
|
||||
void aFunction(void parameterName(int functionParameterName)) {
|
||||
// ...
|
||||
}
|
||||
|
||||
// After extraction of typedef using legacy syntax
|
||||
typedef void MyFunction(int functionParameterName);
|
||||
void aFunction(MyFunction parameterName) {
|
||||
// ...
|
||||
}
|
||||
----
|
||||
|
||||
== How to fix it
|
||||
|
||||
Replace the parameter name with the `Function` identifier. Move the parameter name after the list of formal parameters of the `Function`.
|
||||
|
||||
=== Code examples
|
||||
|
||||
==== Noncompliant code example
|
||||
|
||||
[source,dart,diff-id=1,diff-type=noncompliant]
|
||||
----
|
||||
void aFunction(void parameterName(int functionParameterName)) {
|
||||
// ...
|
||||
}
|
||||
----
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,dart,diff-id=1,diff-type=compliant]
|
||||
----
|
||||
void aFunction(void Function(int functionParameterName) parameterName) {
|
||||
// ...
|
||||
}
|
||||
----
|
||||
|
||||
== Resources
|
||||
|
||||
=== Documentation
|
||||
|
||||
* Dart Docs - https://dart.dev/tools/linter-rules/use_function_type_syntax_for_parameters[Dart Linter rule - use_function_type_syntax_for_parameters]
|
||||
* Dart Docs - https://dart.dev/language/typedefs[Language - Typedefs]
|
||||
|
||||
=== Related rules
|
||||
|
||||
* S5416 - Generic function type aliases should be preferred
|
||||
|
||||
|
||||
ifdef::env-github,rspecator-view[]
|
||||
|
||||
'''
|
||||
== Implementation Specification
|
||||
(visible only on this page)
|
||||
|
||||
=== Message
|
||||
|
||||
Use the generic function type syntax to declare the parameter '<parameterName>'.
|
||||
|
||||
=== Highlighting
|
||||
|
||||
The entire parameter declaration, comprising the type and the name of the parameter: e.g. `bool p(T)` in `Iterable<T> f1(bool p(T), int i1) => [];`.
|
||||
|
||||
endif::env-github,rspecator-view[]
|
2
rules/S7104/metadata.json
Normal file
2
rules/S7104/metadata.json
Normal file
@ -0,0 +1,2 @@
|
||||
{
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user