123 lines
4.0 KiB
Plaintext
123 lines
4.0 KiB
Plaintext
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[]
|