-
Notifications
You must be signed in to change notification settings - Fork 18
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Fix avoid-late if initialized * Update lint_test/avoid_late_keyword_test.dart Co-authored-by: Yurii Prykhodko <[email protected]> * Apply suggestions from code review Co-authored-by: Yurii Prykhodko <[email protected]> * Custom avoid-late * Fix naming * Apply suggestions from code review Co-authored-by: Yurii Prykhodko <[email protected]> * Avoid late simplified * Update lib/lints/avoid_late_keyword/models/avoid_late_keyword_parameters.dart Co-authored-by: Yurii Prykhodko <[email protected]> * Avoid-late ignored_types * Avoid-late ignored_types formatted * Update lib/lints/avoid_late_keyword/models/avoid_late_keyword_parameters.dart Co-authored-by: Yurii Prykhodko <[email protected]> * Avoid-late ignored_types fix * Avoid-late ignored_types Fix * Avoid-late allow_initialized testcases * Update lint_test/avoid_late_keyword_allow_initialized_test/pubspec.yaml Co-authored-by: Yurii Prykhodko <[email protected]> * Update lib/lints/avoid_late_keyword/models/avoid_late_keyword_parameters.dart Co-authored-by: Yurii Prykhodko <[email protected]> * Allow subclasses for avoid-late whitelist * Fix naming * Short-circuit of there's no ignored types * Short-circuit earlier * Update lib/lints/avoid_late_keyword/avoid_late_keyword_rule.dart Co-authored-by: Yurii Prykhodko <[email protected]> * Avoid-late ignored_types tests * Avoid-late add testcases * Proper-super-calls impl * Proper-super-calls format * Apply suggestions from code review Co-authored-by: Yurii Prykhodko <[email protected]> * Proper-super-calls refactoring * Update lib/lints/proper_super_calls/proper_super_calls_rule.dart Co-authored-by: Yurii Prykhodko <[email protected]> * Proper-super-keyword annotation check * Proper-super-keyword format * Proper-super-calls cleanup --------- Co-authored-by: Yurii Prykhodko <[email protected]> Co-authored-by: Yurii Prykhodko <[email protected]>
- Loading branch information
1 parent
6aae62c
commit 414a14e
Showing
5 changed files
with
215 additions
and
1 deletion.
There are no files selected for viewing
134 changes: 134 additions & 0 deletions
134
lib/lints/proper_super_calls/proper_super_calls_rule.dart
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,134 @@ | ||
import 'package:analyzer/dart/ast/ast.dart'; | ||
import 'package:analyzer/error/listener.dart'; | ||
import 'package:custom_lint_builder/custom_lint_builder.dart'; | ||
import 'package:solid_lints/models/rule_config.dart'; | ||
import 'package:solid_lints/models/solid_lint_rule.dart'; | ||
|
||
/// Checks that `super` calls in the initState and | ||
/// dispose methods are called in the correct order. | ||
class ProperSuperCallsRule extends SolidLintRule { | ||
/// The [LintCode] of this lint rule that represents | ||
/// the error whether the initState and dispose methods | ||
/// are called in the incorrect order | ||
static const lintName = 'proper_super_calls'; | ||
static const _initState = 'initState'; | ||
static const _dispose = 'dispose'; | ||
static const _override = 'override'; | ||
|
||
/// The [LintCode] of this lint rule that represents | ||
/// the error whether super.initState() should be called first | ||
static const _superInitStateCode = LintCode( | ||
name: lintName, | ||
problemMessage: "super.initState() should be first", | ||
); | ||
|
||
/// The [LintCode] of this lint rule that represents | ||
/// the error whether super.dispose() should be called last | ||
static const _superDisposeCode = LintCode( | ||
name: lintName, | ||
problemMessage: "super.dispose() should be last", | ||
); | ||
|
||
ProperSuperCallsRule._(super.config); | ||
|
||
/// Creates a new instance of [ProperSuperCallsRule] | ||
/// based on the lint configuration. | ||
factory ProperSuperCallsRule.createRule(CustomLintConfigs configs) { | ||
final rule = RuleConfig( | ||
name: lintName, | ||
configs: configs, | ||
problemMessage: (_) => 'Proper super calls issue', | ||
); | ||
|
||
return ProperSuperCallsRule._(rule); | ||
} | ||
|
||
@override | ||
void run( | ||
CustomLintResolver resolver, | ||
ErrorReporter reporter, | ||
CustomLintContext context, | ||
) { | ||
context.registry.addMethodDeclaration( | ||
(node) { | ||
final methodName = node.name.toString(); | ||
|
||
if (methodName == _initState || methodName == _dispose) { | ||
final statements = (node.body as BlockFunctionBody).block.statements; | ||
|
||
_checkSuperCalls( | ||
node, | ||
methodName, | ||
statements, | ||
reporter, | ||
); | ||
} | ||
}, | ||
); | ||
} | ||
|
||
/// This method report an error whether `super.initState()` | ||
/// or `super.dispose()` are called incorrect | ||
void _checkSuperCalls( | ||
MethodDeclaration node, | ||
String methodName, | ||
List<Statement> statements, | ||
ErrorReporter reporter, | ||
) { | ||
final hasOverrideAnnotation = | ||
node.metadata.any((annotation) => annotation.name.name == _override); | ||
|
||
if (!hasOverrideAnnotation) return; | ||
if (methodName == _initState && !_isSuperInitStateCalledFirst(statements)) { | ||
reporter.reportErrorForNode( | ||
_superInitStateCode, | ||
node, | ||
); | ||
} | ||
if (methodName == _dispose && !_isSuperDisposeCalledLast(statements)) { | ||
reporter.reportErrorForNode( | ||
_superDisposeCode, | ||
node, | ||
); | ||
} | ||
} | ||
|
||
/// Returns `true` if `super.initState()` is called before other code in the | ||
/// `initState` method, `false` otherwise. | ||
bool _isSuperInitStateCalledFirst(List<Statement> statements) { | ||
if (statements.isEmpty) return false; | ||
final firstStatement = statements.first; | ||
|
||
if (firstStatement is ExpressionStatement) { | ||
final expression = firstStatement.expression; | ||
|
||
final isSuperInitStateCalledFirst = expression is MethodInvocation && | ||
expression.target is SuperExpression && | ||
expression.methodName.toString() == _initState; | ||
|
||
return isSuperInitStateCalledFirst; | ||
} | ||
|
||
return false; | ||
} | ||
|
||
/// Returns `true` if `super.dispose()` is called at the end of the `dispose` | ||
/// method, `false` otherwise. | ||
bool _isSuperDisposeCalledLast(List<Statement> statements) { | ||
if (statements.isEmpty) return false; | ||
final lastStatement = statements.last; | ||
|
||
if (lastStatement is ExpressionStatement) { | ||
final expression = lastStatement.expression; | ||
|
||
final lastStatementIsSuperDispose = expression is MethodInvocation && | ||
expression.target is SuperExpression && | ||
expression.methodName.toString() == _dispose; | ||
|
||
return lastStatementIsSuperDispose; | ||
} | ||
|
||
return false; | ||
} | ||
} |
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
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 |
---|---|---|
|
@@ -57,3 +57,4 @@ custom_lint: | |
- prefer_first | ||
- prefer_last | ||
- prefer_match_file_name | ||
- proper_super_calls |
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
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,77 @@ | ||
// ignore_for_file: prefer_match_file_name, no_empty_block | ||
|
||
class Widget {} | ||
|
||
abstract class State<T> { | ||
build(); | ||
dispose() {} | ||
initState() {} | ||
} | ||
|
||
abstract class StatefulWidget extends Widget { | ||
State createState(); | ||
|
||
StatefulWidget(); | ||
} | ||
|
||
/// Check "check super" keyword fail | ||
/// | ||
/// `proper_super_calls` | ||
class ProperSuperCallsTest1 extends StatefulWidget { | ||
@override | ||
State<ProperSuperCallsTest1> createState() => _ProperSuperCallsTest1State(); | ||
|
||
ProperSuperCallsTest1(); | ||
} | ||
|
||
class _ProperSuperCallsTest1State extends State<ProperSuperCallsTest1> { | ||
@override | ||
Widget build() { | ||
return Widget(); | ||
} | ||
|
||
// expect_lint: proper_super_calls | ||
@override | ||
void initState() { | ||
print(''); | ||
super.initState(); | ||
} | ||
|
||
// expect_lint: proper_super_calls | ||
@override | ||
void dispose() { | ||
super.dispose(); | ||
print(''); | ||
} | ||
} | ||
|
||
class ProperSuperCallsTest2 extends StatefulWidget { | ||
@override | ||
State<ProperSuperCallsTest2> createState() => _ProperSuperCallsTest2State(); | ||
|
||
ProperSuperCallsTest2(); | ||
} | ||
|
||
class _ProperSuperCallsTest2State extends State<ProperSuperCallsTest2> { | ||
@override | ||
Widget build() { | ||
return Widget(); | ||
} | ||
|
||
@override | ||
void initState() { | ||
super.initState(); | ||
print(''); | ||
} | ||
|
||
@override | ||
void dispose() { | ||
print(''); | ||
super.dispose(); | ||
} | ||
} | ||
|
||
class MyClass { | ||
dispose() {} | ||
initState() {} | ||
} |