• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

dart-lang / linter / 3690449303

pending completion
3690449303

push

github

GitHub
Fix `unnecessary_parenthesis` with postfix bang operator. (#3904)

2 of 2 new or added lines in 1 file covered. (100.0%)

8263 of 8640 relevant lines covered (95.64%)

1.47 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

80.0
/lib/src/rules/test_types_in_equals.dart
1
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
2
// for details. All rights reserved. Use of this source code is governed by a
3
// BSD-style license that can be found in the LICENSE file.
4

5
import 'package:analyzer/dart/ast/ast.dart';
6
import 'package:analyzer/dart/ast/visitor.dart';
7

8
import '../analyzer.dart';
9

10
const _desc = r'Test type arguments in operator ==(Object other).';
11

12
const _details = r'''
13
**DO** test type arguments in operator ==(Object other).
14

15
Not testing types might result in null pointer exceptions which will be
16
unexpected for consumers of your class.
17

18
**BAD:**
19
```dart
20
class Field {
21
}
22

23
class Bad {
24
  final Field someField;
25

26
  Bad(this.someField);
27

28
  @override
29
  bool operator ==(Object other) {
30
    Bad otherBad = other as Bad; // LINT
31
    bool areEqual = otherBad != null && otherBad.someField == someField;
32
    return areEqual;
33
  }
34

35
  @override
36
  int get hashCode {
37
    return someField.hashCode;
38
  }
39
}
40
```
41

42
**GOOD:**
43
```dart
44
class Field {
45
}
46

47
class Good {
48
  final Field someField;
49

50
  Good(this.someField);
51

52
  @override
53
  bool operator ==(Object other) {
54
    if (identical(this, other)) {
55
      return true;
56
    }
57
    return other is Good &&
58
        this.someField == other.someField;
59
  }
60

61
  @override
62
  int get hashCode {
63
    return someField.hashCode;
64
  }
65
}
66
```
67

68
''';
69

70
class TestTypesInEquals extends LintRule {
71
  static const LintCode code = LintCode(
72
      'test_types_in_equals', "Missing type test for '{0}' in '=='.",
73
      correctionMessage: "Try testing the type of '{0}'.");
74

75
  TestTypesInEquals()
76
      : super(
77
            name: 'test_types_in_equals',
78
            description: _desc,
79
            details: _details,
80
            group: Group.errors);
81

82
  @override
83
  LintCode get lintCode => code;
84

85
  @override
86
  void registerNodeProcessors(
87
      NodeLintRegistry registry, LinterContext context) {
88
    var visitor = _Visitor(this);
89
    registry.addAsExpression(this, visitor);
90
  }
91
}
92

93
class _Visitor extends SimpleAstVisitor<void> {
94
  final LintRule rule;
95

96
  _Visitor(this.rule);
97

98
  @override
99
  void visitAsExpression(AsExpression node) {
100
    var declaration = node.thisOrAncestorOfType<MethodDeclaration>();
101
    var expression = node.expression;
102
    if (!_isEqualsOverride(declaration) || expression is! SimpleIdentifier) {
103
      return;
104
    }
105

106
    var parameters = declaration?.parameters;
107
    var parameterName = parameters?.parameterElements.first?.name;
108
    if (expression.name == parameterName) {
109
      var typeName = _getTypeName(declaration!);
110
      rule.reportLint(node, arguments: [typeName]);
111
    }
112
  }
113

114
  String _getTypeName(MethodDeclaration method) {
115
    var parent = method.parent;
116
    if (parent is ClassOrAugmentationDeclaration) {
117
      return parent.name.lexeme;
118
    } else if (parent is EnumDeclaration) {
119
      return parent.name.lexeme;
120
    } else if (parent is MixinOrAugmentationDeclaration) {
121
      return parent.name.lexeme;
122
    } else if (parent is ExtensionDeclaration) {
123
      return parent.extendedType.toSource();
124
    }
125
    return 'unknown';
126
  }
127

128
  bool _isEqualsOverride(MethodDeclaration? declaration) =>
129
      declaration != null &&
130
      declaration.isOperator &&
131
      declaration.name.lexeme == '==' &&
132
      declaration.parameters?.parameterElements.length == 1;
133
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc