Create a new Dart project:
dart create my_lint
Enter it:
cd my_lint
Remove what we don't need:
rm -rf bin/ test/ CHANGELOG.md
Then add a few packages:
dart pub add analyzer
dart pub add analyzer_plugin
dart pub add custom_lint_builder
In lib/my_lint.dart
, create a new plugin that will implement your very own linter rule. I will create a rule that disallows the usage of foo
or bar
as variable names. The plugin must inherit from PluginBase
and implement at least one method, that returns all custom rules:
class MyLintPlugin extends PluginBase {
@override
List<LintRule> getLintRules(CustomLintConfigs configs) {
return [
MyLintRule(),
];
}
}
Next implement MyLintRule
, which is, because I want to analyze Dart code, a subclass of DartLintRule
and needs to be initialized with the issue it can raise. We need at least a unique name (which can be used to disable the rule) and a message that describes the issue. I also change the severity to ERROR
. The rule must implement a run
method (more on that later):
class MyLintRule extends DartLintRule {
MyLintRule() : super(code: _code);
static const _code = LintCode(
name: 'my_lint_be_no_fool',
problemMessage: 'do not use `foo` or `bar` as variable names',
errorSeverity: ErrorSeverity.ERROR,
);
@override
void run(CustomLintResolver resolver, ErrorReporter reporter, CustomLintContext context) {}
}
Let's implement run
. We need to register a callback that will automatically be called if a Dart file is modified and the plugin framework did already all the heavy lifting of parsing the source code into an AST and resolving all types (I hope). So all we need to do is checking the name of a variable declaration:
@override
void run(CustomLintResolver resolver, ErrorReporter reporter, CustomLintContext context) {
context.registry.addVariableDeclaration((node) {
final name = node.name.lexeme;
if (name == 'foo' || name == 'bar') {
reporter.reportErrorForNode(_code, node);
}
});
}
Next, we need to create an example project where we can use our custom linter:
dart create example
cd example
rm -rf bin/ test/ CHANGELOG.md
Add my_lint
as a development dependency in pubspec.yaml
:
dart pub add 'dev:my_lint:{path: ..}'
Next, modify analysis_options.yaml
to add custom_lint
as a plugin:
analyzer:
plugins:
- custom_lint
To test the new linter rule, go to lib/example.dart
and write:
var foo = 42;
You should get an error
example.dart (example/lib):
do not use `foo` or `bar` as variable names
dart(my_lint_be_no_fool) [Ln 1, Col 7]
Changing foo
to fool
should clear the error.
Alternatively, you could add // ignore: my_lint_be_no_fool
.