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
25 changes: 25 additions & 0 deletions lib/main.dart
Comment thread
Islam-Shaaban-Ibrahim marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import 'package:analysis_server_plugin/plugin.dart';
import 'package:analysis_server_plugin/registry.dart';
import 'package:solid_lints/src/lints/avoid_global_state/avoid_global_state_rule.dart';

/// The entry point for the Solid Lints analyser server plugin.
///
/// This plugin integrates custom lint rules into the Dart analysis server,
/// allowing them to run during static analysis.
final plugin = SolidLintsPlugin();

/// An analysis server plugin that provides Solid lint rules.
///
/// This plugin registers custom lint rules and enables them to be executed
/// by the Dart analyzer during code analysis.
class SolidLintsPlugin extends Plugin {
@override
String get name => 'solid_lints';

@override
void register(PluginRegistry registry) {
registry.registerLintRule(
AvoidGlobalStateRule(),
);
}
}
77 changes: 0 additions & 77 deletions lib/solid_lints.dart

This file was deleted.

74 changes: 30 additions & 44 deletions lib/src/lints/avoid_global_state/avoid_global_state_rule.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
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/src/models/rule_config.dart';
import 'package:solid_lints/src/models/solid_lint_rule.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_global_state/visitors/avoid_global_state_visitor.dart';

/// Avoid top-level and static mutable variables.
///
Expand All @@ -23,7 +23,6 @@ import 'package:solid_lints/src/models/solid_lint_rule.dart';
/// }
/// ```
///
///
/// #### GOOD:
///
/// ```dart
Expand All @@ -35,49 +34,36 @@ import 'package:solid_lints/src/models/solid_lint_rule.dart';
/// static final int globalFinal = 1;
/// }
/// ```
class AvoidGlobalStateRule extends SolidLintRule {
/// This lint rule represents
/// the error whether we use global state.
static const lintName = 'avoid_global_state';
class AvoidGlobalStateRule extends AnalysisRule {
/// Lint name used for suppression and reporting.
static const String lintName = 'avoid_global_state';

AvoidGlobalStateRule._(super.config);
/// Lint code used for suppression and reporting.
static const LintCode code = LintCode(
lintName,
'Avoid variables that can be globally mutated.',
correctionMessage:
'Prefer using final/const or a state management solution.',
);

/// Creates a new instance of [AvoidGlobalStateRule]
/// based on the lint configuration.
factory AvoidGlobalStateRule.createRule(CustomLintConfigs configs) {
final rule = RuleConfig(
configs: configs,
name: lintName,
problemMessage: (_) => 'Avoid variables that can be globally mutated.',
);
/// Creates an instance of [AvoidGlobalStateRule].
AvoidGlobalStateRule()
: super(
name: lintName,
description: 'Avoid top-level or static mutable variables ',
);

return AvoidGlobalStateRule._(rule);
}
@override
LintCode get diagnosticCode => code;

@override
void run(
CustomLintResolver resolver,
DiagnosticReporter reporter,
CustomLintContext context,
void registerNodeProcessors(
RuleVisitorRegistry registry,
RuleContext context,
) {
context.registry.addTopLevelVariableDeclaration(
(node) => node.variables.variables
.where((variable) => variable.isPublicMutable)
.forEach((node) => reporter.atNode(node, code)),
);
context.registry.addFieldDeclaration((node) {
if (!node.isStatic) return;
node.fields.variables
.where((variable) => variable.isPublicMutable)
.forEach((node) => reporter.atNode(node, code));
});
}
}

extension on VariableDeclaration {
bool get isMutable => !isFinal && !isConst;
final visitor = AvoidGlobalStateVisitor(this);

bool get isPrivate => declaredFragment?.element.isPrivate ?? false;

bool get isPublicMutable => isMutable && !isPrivate;
registry.addTopLevelVariableDeclaration(this, visitor);
registry.addFieldDeclaration(this, visitor);
Comment thread
solid-vovabeloded marked this conversation as resolved.
}
}
Comment thread
Islam-Shaaban-Ibrahim marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:solid_lints/src/lints/avoid_global_state/avoid_global_state_rule.dart';

/// Visitor for [AvoidGlobalStateRule].
class AvoidGlobalStateVisitor extends SimpleAstVisitor<void> {
/// The rule this visitor is associated with.
final AvoidGlobalStateRule rule;

/// Creates an instance of [AvoidGlobalStateVisitor].
AvoidGlobalStateVisitor(this.rule);

@override
void visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
for (final variable in node.variables.variables) {
if (_isPublicMutable(variable)) {
rule.reportAtNode(variable);
}
}
}

@override
void visitFieldDeclaration(FieldDeclaration node) {
if (!node.isStatic) return;

for (final variable in node.fields.variables) {
if (_isPublicMutable(variable)) {
rule.reportAtNode(variable);
}
}
}

/// Returns true if the variable is mutable and not private.
bool _isPublicMutable(VariableDeclaration variable) {
return _isMutable(variable) && !_isPrivate(variable);
}

/// A variable is mutable if it is not final or const.
bool _isMutable(VariableDeclaration variable) {
final parent = variable.parent;
return parent is VariableDeclarationList &&
!parent.isFinal &&
!parent.isConst;
}

/// A variable is private if its element is private.
bool _isPrivate(VariableDeclaration variable) {
final element = variable.declaredFragment?.element;
return element?.isPrivate ?? false;
}
}
45 changes: 45 additions & 0 deletions lint_test/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.build/
.buildlog/
.history
.svn/
.swiftpm/
migrate_working_dir/

# IntelliJ related
*.iml
*.ipr
*.iws
.idea/

# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/

# Flutter/Dart/Pub related
**/doc/api/
**/ios/Flutter/.last_build_id
.dart_tool/
.flutter-plugins-dependencies
.pub-cache/
.pub/
/build/
/coverage/

# Symbolication related
app.*.symbols

# Obfuscation related
app.*.map.json

# Android Studio will place build artifacts here
/android/app/debug
/android/app/profile
/android/app/release
30 changes: 30 additions & 0 deletions lint_test/.metadata
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.

version:
revision: "05db9689081f091050f01aed79f04dce0c750154"
channel: "stable"

project_type: app

# Tracks metadata for the flutter migrate command
migration:
platforms:
- platform: root
create_revision: 05db9689081f091050f01aed79f04dce0c750154
base_revision: 05db9689081f091050f01aed79f04dce0c750154
- platform: web
create_revision: 05db9689081f091050f01aed79f04dce0c750154
base_revision: 05db9689081f091050f01aed79f04dce0c750154

# User provided section

# List of Local paths (relative to this file) that should be
# ignored by the migrate tool.
#
# Files that are not part of the templates will be ignored by default.
unmanaged_files:
- 'lib/main.dart'
- 'ios/Runner.xcodeproj/project.pbxproj'
3 changes: 3 additions & 0 deletions lint_test/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# solid_lints_test

A new Flutter project.
30 changes: 0 additions & 30 deletions lint_test/avoid_global_state_test.dart

This file was deleted.

4 changes: 2 additions & 2 deletions lint_test/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
name: solid_lints_test
description: A starting point for Dart libraries or applications.
description: Test project for solid_lints rules
publish_to: none

environment:
sdk: '>=3.0.0 <4.0.0'
sdk: ">=3.5.0 <4.0.0"

dependencies:
flutter:
Expand Down
6 changes: 4 additions & 2 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ environment:
sdk: ">=3.5.0 <4.0.0"

dependencies:
analyzer: ^8.4.0
analyzer: ^10.0.1
collection: ^1.19.0
custom_lint_builder: ^0.8.1
Comment thread
Islam-Shaaban-Ibrahim marked this conversation as resolved.
analysis_server_plugin: ^0.3.3
glob: ^2.1.3
path: ^1.9.1
yaml: ^3.1.3
Expand All @@ -24,3 +24,5 @@ dependencies:

dev_dependencies:
args: ^2.6.0
analyzer_testing: ^0.1.9
test_reflective_loader: ^0.3.0
Loading
Loading