Skip to content
Merged
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
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import 'package:analyzer/error/listener.dart';
import 'package:custom_lint_builder/custom_lint_builder.dart';
import 'package:analyzer/analysis_rule/analysis_rule.dart';
import 'package:analyzer/analysis_rule/rule_context.dart';
import 'package:analyzer/analysis_rule/rule_visitor_registry.dart';
import 'package:analyzer/error/error.dart';
import 'package:solid_lints/src/lints/avoid_unnecessary_setstate/visitors/avoid_unnecessary_set_state_visitor.dart';
import 'package:solid_lints/src/models/rule_config.dart';
import 'package:solid_lints/src/models/solid_lint_rule.dart';

/// A rule which warns when setState is called inside initState, didUpdateWidget
/// or build methods and when it's called from a sync method that is called
Expand Down Expand Up @@ -55,37 +55,36 @@ import 'package:solid_lints/src/models/solid_lint_rule.dart';
/// if (mounted) setState(() => foo = 'bar');
/// }
/// ```
class AvoidUnnecessarySetStateRule extends SolidLintRule {
/// The lint name of this lint rule that represents
/// the error whether we use setState in inappropriate way.
static const lintName = 'avoid_unnecessary_setstate';
class AvoidUnnecessarySetStateRule extends AnalysisRule {
/// The name of the lint rule.
static const _lintName = 'avoid_unnecessary_setstate';

AvoidUnnecessarySetStateRule._(super.config);
/// The message shown when the lint rule is triggered.
static const _lintMessage = 'Avoid calling unnecessary setState. '
'Consider changing the state directly.';

/// Creates a new instance of [AvoidUnnecessarySetStateRule]
/// based on the lint configuration.
factory AvoidUnnecessarySetStateRule.createRule(CustomLintConfigs configs) {
final rule = RuleConfig(
name: lintName,
configs: configs,
problemMessage: (_) => 'Avoid calling unnecessary setState. '
'Consider changing the state directly.',
);
return AvoidUnnecessarySetStateRule._(rule);
}
/// The lint code for this rule.
static const _code = LintCode(
_lintName,
_lintMessage,
);

/// Creates a new instance of [AvoidUnnecessarySetStateRule].
AvoidUnnecessarySetStateRule()
: super(
name: _lintName,
description: _lintMessage,
);

@override
LintCode get diagnosticCode => _code;

@override
void run(
CustomLintResolver resolver,
DiagnosticReporter reporter,
CustomLintContext context,
void registerNodeProcessors(
RuleVisitorRegistry registry,
RuleContext context,
) {
context.registry.addClassDeclaration((node) {
final visitor = AvoidUnnecessarySetStateVisitor();
visitor.visitClassDeclaration(node);
for (final element in visitor.setStateInvocations) {
reporter.atNode(element, code);
}
});
final visitor = AvoidUnnecessarySetStateVisitor(this);
registry.addClassDeclaration(this, visitor);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,22 +24,26 @@
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:collection/collection.dart';
import 'package:solid_lints/src/lints/avoid_unnecessary_setstate/avoid_unnecessary_set_state_rule.dart';
import 'package:solid_lints/src/lints/avoid_unnecessary_setstate/visitors/avoid_unnecessary_set_state_method_visitor.dart';
import 'package:solid_lints/src/utils/types_utils.dart';

/// AST visitor which checks if class is State, in case yes checks its methods
class AvoidUnnecessarySetStateVisitor extends RecursiveAstVisitor<void> {
/// Visitor for [AvoidUnnecessarySetStateRule].
class AvoidUnnecessarySetStateVisitor extends SimpleAstVisitor<void> {
static const _checkedMethods = [
'initState',
'didUpdateWidget',
'didChangeDependencies',
'build',
];

/// The rule associated with this visitor.
final AvoidUnnecessarySetStateRule _rule;

final _setStateInvocations = <MethodInvocation>[];

/// Unnecessary setState invocations
Iterable<MethodInvocation> get setStateInvocations => _setStateInvocations;
/// Creates an instance of [AvoidUnnecessarySetStateVisitor].
AvoidUnnecessarySetStateVisitor(this._rule);

@override
void visitClassDeclaration(ClassDeclaration node) {
Expand All @@ -50,9 +54,16 @@ class AvoidUnnecessarySetStateVisitor extends RecursiveAstVisitor<void> {
return;
}

final methods = node.members.whereType<MethodDeclaration>();
final classMethodsNames =
methods.map((declaration) => declaration.name.lexeme).toSet();
final body = node.body;

if (body is! BlockClassBody) {
return;
}

final methods = body.members.whereType<MethodDeclaration>();
final classMethodsNames = methods
.map((declaration) => declaration.name.lexeme)
.toSet();
final methodBodies = methods.map((declaration) => declaration.body).toSet();

final checkedMethods = methods.where(_isMethodChecked);
Expand Down Expand Up @@ -83,6 +94,10 @@ class AvoidUnnecessarySetStateVisitor extends RecursiveAstVisitor<void> {
)
.toList(),
);

for (final element in _setStateInvocations) {
_rule.reportAtNode(element);
}
}
}

Expand All @@ -105,8 +120,10 @@ class AvoidUnnecessarySetStateVisitor extends RecursiveAstVisitor<void> {
return true;
}

final visitor =
AvoidUnnecessarySetStateMethodVisitor(classMethodsNames, bodies);
final visitor = AvoidUnnecessarySetStateMethodVisitor(
classMethodsNames,
bodies,
);
declaration.visitChildren(visitor);

final hasSetState = visitor.setStateInvocations.isNotEmpty;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,14 @@ class NewLineBeforeReturnVisitor extends RecursiveAstVisitor<void> {
ReturnStatement node,
LineInfo lineInfo,
) {
final previousTokenLineNumber =
lineInfo.getLocation(node.returnKeyword.previous!.end).lineNumber;
final previousTokenLineNumber = lineInfo
.getLocation(node.returnKeyword.previous!.end)
.lineNumber;

final lastNotEmptyLineToken = _optimalToken(node.returnKeyword, lineInfo);
final tokenLineNumber =
lineInfo.getLocation(lastNotEmptyLineToken.offset).lineNumber;
final tokenLineNumber = lineInfo
.getLocation(lastNotEmptyLineToken.offset)
.lineNumber;

return tokenLineNumber > previousTokenLineNumber + 1;
}
Expand Down
108 changes: 0 additions & 108 deletions lint_test/avoid_unnecessary_setstate_test.dart

This file was deleted.

2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ documentation: https://solid-software.github.io/solid_lints/docs/intro
topics: [lints, linter, lint, analysis, analyzer]

environment:
sdk: ">=3.5.0 <4.0.0"
sdk: ">=3.9.0 <4.0.0"

dependencies:
analyzer: ^10.0.1
Expand Down
Loading
Loading