Skip to content

Commit

Permalink
Create rule S7094: Constant patterns should not be used with type lit…
Browse files Browse the repository at this point in the history
…erals (type_literal_in_constant_pattern) (#4323)

Co-authored-by: antonioaversa <[email protected]>
  • Loading branch information
github-actions[bot] and antonioaversa authored Sep 26, 2024
1 parent 4f54acf commit 68ff677
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 0 deletions.
24 changes: 24 additions & 0 deletions rules/S7094/dart/metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"title": "Constant patterns should not be used with type literals",
"type": "BUG",
"status": "ready",
"remediation": {
"func": "Constant\/Issue",
"constantCost": "1min"
},
"tags": [
"pitfall"
],
"defaultSeverity": "Major",
"ruleSpecification": "RSPEC-7094",
"sqKey": "S7094",
"scope": "All",
"defaultQualityProfiles": ["Sonar way"],
"quickfix": "unknown",
"code": {
"impacts": {
"RELIABILITY": "HIGH"
},
"attribute": "LOGICAL"
}
}
100 changes: 100 additions & 0 deletions rules/S7094/dart/rule.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
https://dart.dev/language/pattern-types#constant[Constant patterns] should not be used with type literals.

== Why is this an issue?

Using constant patterns with type literals is most likely a mistake.

For example, the following code

[source,dart]
----
bool isANumber(Object? o) {
if (o case num) { // Checks if `o` is `num`, not if it is a `num`
return true;
}
return false;
}
----

will always return `false` for any input *value* of type `num` (as in `isANumber(42)`), and will returns `true` only when the input is the *type* `num` (as in `isANumber(int)`).

This is because a constant pattern compares the value of the provided constant against the value being matched, and not against its type.

The original intent of checking whether an `Object? o` is a `num` or not, should be expressed via a https://dart.dev/language/pattern-types#variable[typed variable pattern]:

[source,dart]
----
bool isANumber(Object? o) {
if (o case num n) { // Checks if `o` is a `num` and assigns the cast value to n
return true;
}
return false;
}
----

If the intent of the code is to only check whether the input is a `num` or not, then the `n` variable is not necessary, and a value discard can be used:

[source,dart]
----
bool isANumber(Object? o) {
if (o case num _) { // Checks if `o` is a `num`, and discards the cast value
return true;
}
return false;
}
----

== How to fix it

Convert the https://dart.dev/language/pattern-types#constant[constant pattern] to a https://dart.dev/language/pattern-types#variable[typed variable pattern] by adding a ``++_++`` (value discard) to the type.

=== Code examples

==== Noncompliant code example

[source,dart,diff-id=1,diff-type=noncompliant]
----
bool isANumber(Object? o) {
if (o case num) {
return true;
}
return false;
}
----

==== Compliant solution

[source,dart,diff-id=1,diff-type=compliant]
----
bool isANumber(Object? o) {
if (o case num _) {
return true;
}
return false;
}
----

== Resources

* Dart Docs - https://dart.dev/tools/linter-rules/type_literal_in_constant_pattern[Dart Linter rule - type_literal_in_constant_pattern]
* Dart Docs - https://dart.dev/language/pattern-types[Language - Pattern types]

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

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

=== Message

Use 'TypeName _' instead of a type literal.

=== Highlighting

The type literal: e.g. `num` in `if (o1 case num) { }`.

'''
== Comments And Links
(visible only on this page)

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

0 comments on commit 68ff677

Please sign in to comment.