Skip to content

Commit

Permalink
Create rule S7082: Contains should be preferred to indexOf (prefer_co…
Browse files Browse the repository at this point in the history
…ntains)
  • Loading branch information
antonioaversa committed Sep 19, 2024
1 parent 839ddbc commit 1c48d71
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 3 deletions.
6 changes: 3 additions & 3 deletions rules/S5856/dart/rule.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@ RegExp(r'(\\w+)-(\\d+)');

== Resources

=== Documentation

* Dart Docs - https://dart.dev/tools/linter-rules/valid_regexps[Dart Lint rule - valid_regexps]
* Dart Docs - https://api.dart.dev/stable/3.4.4/dart-core/RegExp-class.html[Dart RegExp]
* Dart API Reference - https://api.dart.dev/stable/3.4.4/dart-core/RegExp-class.html[Dart RegExp]

ifdef::env-github,rspecator-view[]

Expand All @@ -34,10 +36,8 @@ ifdef::env-github,rspecator-view[]

Invalid regular expression syntax.


=== Highlighting

The error inside the regular expression


endif::env-github,rspecator-view[]
24 changes: 24 additions & 0 deletions rules/S7082/dart/metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"title": "Contains should be preferred to indexOf",
"type": "CODE_SMELL",
"status": "ready",
"remediation": {
"func": "Constant\/Issue",
"constantCost": "5min"
},
"tags": [
"performance"
],
"defaultSeverity": "Major",
"ruleSpecification": "RSPEC-7082",
"sqKey": "S7082",
"scope": "All",
"defaultQualityProfiles": ["Sonar way"],
"quickfix": "unknown",
"code": {
"impacts": {
"MAINTAINABILITY": "HIGH"
},
"attribute": "EFFICIENT"
}
}
82 changes: 82 additions & 0 deletions rules/S7082/dart/rule.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
The `contains` method should be preferred to `indexOf` when looking for an item in a `List` instance or a pattern in a `String` instance.

== Why is this an issue?

The `indexOf` method returns the index of the first occurrence of the specified element in the list, or `-1` if the list does not contain the element.

This means that the method returns an integer, which then needs to be compared to `-1` to determine if the element is present in the list.

[source,dart]
----
if (aList.indexOf(anElement) != -1) {
// Do something
}
----

Depending on the internals of the collection, finding out the position of the element in the list may be more expensive than just checking if the element is present in the list, which is exactly what the `contains` method does.

[source,dart]
----
if (aList.contains(anElement)) {
// Do something
}
----

Moreover, the resulting code is unnecessarily complicated and not as readable as using the `contains` method, which returns a boolean that can be directly consumed in a conditional statement, and that doesn't need to be compared against the special value `-1`.

=== Exceptions

If the search should be carried out starting from a specific element of the list, or if the index of the found element is needed, then the `indexOf` method is the appropriate choice.

== How to fix it

Replace each call to `indexOf` with a call to `contains`.

* If the result is compared for disequality with `-1`, remove the comparison and use the result directly in the conditional statement.
* If the result is compared for equality with `-1`, replace the comparison with a negation.

=== Code examples

==== Noncompliant code example

[source,dart,diff-id=1,diff-type=noncompliant]
----
if (aList.indexOf(anElement) != -1) {
// Do something
}
----

==== Compliant solution

[source,dart,diff-id=1,diff-type=compliant]
----
if (aList.contains(anElement)) {
// Do something
}
----

== Resources

=== Documentation

* Dart Docs - https://dart.dev/tools/linter-rules/prefer_contains[Linter Rule - prefer_contains]
* Dart API Reference - https://api.dart.dev/stable/dart-core/List/indexOf.html[List.indexOf method]
* Dart API Reference - https://api.dart.dev/stable/dart-core/Iterable/contains.html[List.contains method]
* Dart API Reference - https://api.dart.dev/stable/3.5.3/dart-core/String/indexOf.html[String.indexOf method]
* Dart API Reference - https://api.dart.dev/stable/dart-core/String/contains.html[String.contains method]

ifdef::env-github,rspecator-view[]

'''
== Implementation Specification
(visible only on this page)

=== Message

* Unnecessary use of 'indexOf' to test for containment.

=== Highlighting

* The call to 'indexOf' that should be replaced with 'contains' and the comparison with '-1' that should be removed: e.g. `aList.indexOf(anElement) != -1`.

endif::env-github,rspecator-view[]
2 changes: 2 additions & 0 deletions rules/S7082/metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
{
}

0 comments on commit 1c48d71

Please sign in to comment.