Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ON HOLD] Create rule S7082: Contains should be preferred to indexOf (prefer_contains) #4298

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff 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 @@
{
}
Loading