Skip to content

Commit

Permalink
change avoid_final_with_getter, now it lints getter, no getter name e…
Browse files Browse the repository at this point in the history
…quality
  • Loading branch information
4akloon committed Apr 18, 2024
1 parent 429fa30 commit 4db89a6
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 78 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ class AvoidFinalWithGetterRule extends SolidLintRule {
final visitor = AvoidFinalWithGetterVisitor();
node.accept(visitor);

for (final variable in visitor.variables) {
reporter.reportErrorForNode(code, variable);
for (final getter in visitor.getters) {
reporter.reportErrorForNode(code, getter);
}
});
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,28 +1,34 @@
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:solid_lints/src/lints/avoid_final_with_getter/visitors/variable_getter_visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:solid_lints/src/lints/avoid_final_with_getter/visitors/getter_variable_visitor.dart';

/// A visitor that checks for final private fields with getters.
/// If a final private field has a getter, it is considered as a public field.
class AvoidFinalWithGetterVisitor extends RecursiveAstVisitor<void> {
final _variables = <VariableDeclaration>[];
final _getters = <MethodDeclaration>[];

/// List of final private fields with getters
Iterable<VariableDeclaration> get variables => _variables;
/// List of getters
Iterable<MethodDeclaration> get getters => _getters;

@override
void visitVariableDeclaration(VariableDeclaration node) {
final isPrivate = node.declaredElement?.isPrivate ?? false;
final isFinalPrivate = node.isFinal && isPrivate;
void visitMethodDeclaration(MethodDeclaration node) {
if (node
case MethodDeclaration(
isGetter: true,
declaredElement: ExecutableElement(
isAbstract: false,
isStatic: false,
isPublic: true,
)
)) {
final visitor = GetterVariableVisitor(node);
node.parent?.accept(visitor);

if (!isFinalPrivate) return;

final visitor = VariableGetterVisitor(node);
node.parent?.parent?.parent?.accept(visitor);

if (visitor.getter != null) {
_variables.add(node);
if (visitor.hasVariable) {
_getters.add(node);
}
}
super.visitVariableDeclaration(node);
super.visitMethodDeclaration(node);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';

/// A visitor that checks the association of the getter with
/// the final private variable
class GetterVariableVisitor extends RecursiveAstVisitor<void> {
final int? _getterId;
VariableDeclaration? _variable;

/// Creates a new instance of [GetterVariableVisitor]
GetterVariableVisitor(MethodDeclaration getter)
: _getterId = getter.getterReferenceId;

/// Is there a variable associated with the getter
bool get hasVariable => _variable != null;

@override
void visitVariableDeclaration(VariableDeclaration node) {
if (node
case VariableDeclaration(
isFinal: true,
declaredElement: VariableElement(id: final id, isPrivate: true)
) when id == _getterId) {
_variable = node;
}

super.visitVariableDeclaration(node);
}
}

extension on MethodDeclaration {
int? get getterReferenceId => switch (body) {
ExpressionFunctionBody(
expression: SimpleIdentifier(
staticElement: Element(
declaration: PropertyAccessorElement(
variable: PropertyInducingElement(:final id)
)
)
)
) =>
id,
_ => null,
};
}

This file was deleted.

11 changes: 6 additions & 5 deletions lint_test/avoid_final_with_getter_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,23 @@
/// `avoid_final_with_getter`
class Fail {
// expect_lint: avoid_final_with_getter
final int _myField = 0;

// expect_lint: avoid_final_with_getter
int get myField => _myField;
}

class Skipped {
class Fail2 {
final int _myField = 0;

int get myField => _myField + 1; // it is not a getter for the field
// expect_lint: avoid_final_with_getter
int get myFieldInt => _myField;
}

class Skipped2 {
class Skipped {
final int _myField = 0;

int get myFieldInt => _myField; // it is not a getter for the field too
int get myField => _myField + 1; // it is not a getter for the field
}

class Good {
Expand Down

0 comments on commit 4db89a6

Please sign in to comment.