Skip to content

Commit

Permalink
Refactor avoid_final_with_getter_rule.dart and avoid_final_with_gette…
Browse files Browse the repository at this point in the history
…r_visitor.dart
  • Loading branch information
4akloon committed Apr 18, 2024
1 parent d505db7 commit 8ca5222
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 79 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import 'package:analyzer/error/listener.dart';
import 'package:custom_lint_builder/custom_lint_builder.dart';
import 'package:solid_lints/src/lints/avoid_final_with_getter/avoid_final_with_getter_visitor.dart';
import 'package:solid_lints/src/lints/avoid_final_with_getter/visitors/avoid_final_with_getter_visitor.dart';
import 'package:solid_lints/src/models/rule_config.dart';
import 'package:solid_lints/src/models/solid_lint_rule.dart';

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
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';

/// 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>[];

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

@override
void visitVariableDeclaration(VariableDeclaration node) {
final isPrivate = node.declaredElement?.isPrivate ?? false;
final isFinalPrivate = node.isFinal && isPrivate;

if (!isFinalPrivate) return;

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

if (visitor.getter != null) {
_variables.add(node);
}
super.visitVariableDeclaration(node);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
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 for final private fields with getters.
class VariableGetterVisitor extends RecursiveAstVisitor<void> {
final VariableDeclaration _variable;
final String _fieldName;
MethodDeclaration? _getter;

/// Creates a new instance of [VariableGetterVisitor]
VariableGetterVisitor(this._variable)
: _fieldName = _variable.name.toString().replaceFirst('_', '');

/// The getter of the variable
MethodDeclaration? get getter => _getter;

@override
void visitMethodDeclaration(MethodDeclaration node) {
final name = node.name.toString();

if (name == _fieldName && node.isGetter) {
final nodeId = node.getterReferenceId;

final variableId = _variable.variableId;

if (nodeId == variableId) {
_getter = node;
}
}
super.visitMethodDeclaration(node);
}
}

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

extension on VariableDeclaration {
int? get variableId => switch (declaredElement) {
VariableElement(id: final int id) => id,
_ => null,
};
}
6 changes: 5 additions & 1 deletion lint_test/avoid_final_with_getter_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,12 @@ class Fail {
final int _myField = 0;

int get myField => _myField;
}

class Skipped {
final int _myField = 0;

int get myField2 => _myField + 1;
int get myField => _myField + 1;
}

class Good {
Expand Down

0 comments on commit 8ca5222

Please sign in to comment.