-
Notifications
You must be signed in to change notification settings - Fork 30
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Create rule S7083: For elements should be preferred to Map.fromIterab…
…le (prefer_for_elements_to_map_fromIterable) Co-authored-by: Antonio Aversa <[email protected]>
- Loading branch information
1 parent
b9bf820
commit 4172eb0
Showing
3 changed files
with
132 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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[] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
{ | ||
} |