Compare commits
1 Commits
master
...
rule/add-R
Author | SHA1 | Date | |
---|---|---|---|
![]() |
c4f87888bd |
24
rules/S7083/dart/metadata.json
Normal file
24
rules/S7083/dart/metadata.json
Normal file
@ -0,0 +1,24 @@
|
||||
{
|
||||
"title": "For elements should be preferred to Map.fromIterable",
|
||||
"type": "CODE_SMELL",
|
||||
"status": "ready",
|
||||
"remediation": {
|
||||
"func": "Constant\/Issue",
|
||||
"constantCost": "5min"
|
||||
},
|
||||
"tags": [
|
||||
"performance"
|
||||
],
|
||||
"defaultSeverity": "Major",
|
||||
"ruleSpecification": "RSPEC-7083",
|
||||
"sqKey": "S7083",
|
||||
"scope": "All",
|
||||
"defaultQualityProfiles": ["Sonar way"],
|
||||
"quickfix": "unknown",
|
||||
"code": {
|
||||
"impacts": {
|
||||
"MAINTAINABILITY": "HIGH"
|
||||
},
|
||||
"attribute": "EFFICIENT"
|
||||
}
|
||||
}
|
106
rules/S7083/dart/rule.adoc
Normal file
106
rules/S7083/dart/rule.adoc
Normal file
@ -0,0 +1,106 @@
|
||||
https://dart.dev/language/collections#control-flow-operators[`for` elements] should be preferred to https://api.dart.dev/stable/dart-core/Map/Map.fromIterable.html[`fromIterable`] when building a https://api.dart.dev/stable/dart-core/Map/Map.html[`Map`] from an https://api.dart.dev/stable/dart-core/Iterable-class.html[`Iterable`].
|
||||
|
||||
== Why is this an issue?
|
||||
|
||||
While it is possible to build a `Map` from an `Iterable` using `Map.fromIterable`, writing an explicit `for` loop with `for` elements should be used instead.
|
||||
|
||||
The main reason to prefer `for` elements is that it can be optimized by the Dart compiler for performance, depending on the iterable being visited.
|
||||
|
||||
Moreover, `for` elements are more idiomatic and generally easier to understand than `Map.fromIterable`, which requires explicit map type upfront, as well as the input iterable and two different lambda functions as parameters.
|
||||
|
||||
[source,dart]
|
||||
----
|
||||
Map<String, int>.fromIterable( // Explicit Map<String, int> type required
|
||||
inputIterable,
|
||||
key: (item) => ..., // Key generator
|
||||
value: (item) => ..., // Value generator
|
||||
);
|
||||
----
|
||||
|
||||
On the other hand, `for` elements are more flexible, look like normal `for` loops, and support better inference of the resulting `Map` type.
|
||||
|
||||
[source,dart]
|
||||
----
|
||||
{
|
||||
for (final item in inputIterable)
|
||||
'The value is $v': v // Implicit Map<String, int> type inference
|
||||
}
|
||||
----
|
||||
|
||||
=== Exceptions
|
||||
|
||||
The rule only applies to the `fromIterable` factory method of `Map`. It does not apply to other `fromIterable` methods, such as the one from `LinkedHashMap<T, U>` in `dart:collection`.
|
||||
|
||||
Moreover, it only applies when all the arguments of the `Map.fromIterable` call are provided. If either the `key` or the `value` parameter is omitted, the rule does not apply.
|
||||
|
||||
[source,dart]
|
||||
----
|
||||
Map<int, int>.fromIterable(l1, key: (item) => ...); // OK
|
||||
Map<int, int>.fromIterable(l1, value: (item) => ...); // OK
|
||||
----
|
||||
|
||||
The rule also does not apply when the `key` and `value` parameters are not inline function expressions, but variables defined elesewhere in the code.
|
||||
|
||||
[source,dart]
|
||||
----
|
||||
final key = (item) => ...;
|
||||
final value = (item) => ...;
|
||||
Map<int, int>.fromIterable(l1, key: key, value: value);
|
||||
----
|
||||
|
||||
== How to fix it
|
||||
|
||||
In order to replace `Map.fromIterable` with `for` elements:
|
||||
|
||||
* replace the `Map<String, int>.fromIterable` call with a `for` loop over the input iterable, that is the first argument of the call
|
||||
* define the body of the `for` elements as a `key: value` pair, where `key` is the body of the key generator lambda, and `value` is body of the value generator lambda
|
||||
|
||||
=== Code examples
|
||||
|
||||
==== Noncompliant code example
|
||||
|
||||
[source,dart,diff-id=1,diff-type=noncompliant]
|
||||
----
|
||||
Map<String, int>.fromIterable(
|
||||
[1, 2, 3],
|
||||
key: (v) => 'The value is $v',
|
||||
value: (v) => v,
|
||||
);
|
||||
----
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,dart,diff-id=1,diff-type=compliant]
|
||||
----
|
||||
{
|
||||
for (final v in [1, 2, 3])
|
||||
'The value is $v': v
|
||||
}
|
||||
----
|
||||
|
||||
== Resources
|
||||
|
||||
=== Documentation
|
||||
|
||||
* Dart Docs - https://dart.dev/tools/linter-rules/prefer_for_elements_to_map_fromIterable[Linter rule - prefer_for_elements_to_map_fromIterable]
|
||||
* Dart Docs - https://dart.dev/language/collections#control-flow-operators[Language - Control-flow operators]
|
||||
* Dart API Reference - https://api.dart.dev/stable/dart-core/Map/Map.html[Map<K, V> class]
|
||||
* Dart API Reference - https://api.dart.dev/stable/dart-core/Iterable-class.html[Iterable<E> class]
|
||||
* Dart API Reference - https://api.dart.dev/stable/dart-core/Map/Map.fromIterable.html[Map<K, V>.fromIterable constructor]
|
||||
|
||||
|
||||
ifdef::env-github,rspecator-view[]
|
||||
|
||||
'''
|
||||
== Implementation Specification
|
||||
(visible only on this page)
|
||||
|
||||
=== Message
|
||||
|
||||
Use 'for' elements when building maps from iterables.
|
||||
|
||||
=== Highlighting
|
||||
|
||||
The entire `Map.fromIterable` call, including parentheses and arguments: e.g. `Map<String, int>.fromIterable([1, 2, 3], key: (v) => 'The value is $v', value: (v) => v);`.
|
||||
|
||||
endif::env-github,rspecator-view[]
|
2
rules/S7083/metadata.json
Normal file
2
rules/S7083/metadata.json
Normal file
@ -0,0 +1,2 @@
|
||||
{
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user