11// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
22// SPDX-License-Identifier: Apache-2.0
33
4- import 'package:analyzer/analysis_rule/analysis_rule.dart' ;
5- import 'package:analyzer/analysis_rule/rule_context.dart' ;
6- import 'package:analyzer/analysis_rule/rule_visitor_registry.dart' ;
7- import 'package:analyzer/dart/ast/ast.dart' ;
8- import 'package:analyzer/dart/ast/visitor.dart' ;
9- import 'package:analyzer/error/error.dart' ;
4+ import 'dart:io' ;
5+
6+ import 'package:analyzer/error/error.dart' show AnalysisError, ErrorSeverity;
7+ import 'package:analyzer/error/listener.dart' ;
8+ import 'package:custom_lint_builder/custom_lint_builder.dart' ;
109
1110/// The expected license header lines.
12- const licenseHeader = [
11+ const _licenseHeader = [
1312 '// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.' ,
1413 '// SPDX-License-Identifier: Apache-2.0' ,
1514];
@@ -29,64 +28,82 @@ const licenseHeader = [
2928/// ```dart
3029/// library my_library;
3130/// ```
32- class MissingLicenseHeader extends AnalysisRule {
31+ class MissingLicenseHeader extends DartLintRule {
3332 /// Creates a new [MissingLicenseHeader] lint rule.
34- MissingLicenseHeader ()
35- : super (
36- name: 'missing_license_header' ,
37- description:
38- 'Dart files must start with the Amazon copyright and '
39- 'Apache-2.0 license header.' ,
40- );
33+ const MissingLicenseHeader () : super (code: _code);
4134
42- /// The lint code reported by this rule.
43- static const LintCode code = LintCode (
44- 'missing_license_header' ,
45- 'Dart files must start with the Amazon copyright and Apache-2.0 '
46- 'license header.' ,
35+ static const _code = LintCode (
36+ name : 'missing_license_header' ,
37+ problemMessage :
38+ 'Dart files must start with the Amazon copyright and Apache-2.0 '
39+ 'license header.' ,
4740 correctionMessage: 'Add the license header to the top of this file.' ,
41+ errorSeverity: ErrorSeverity .WARNING ,
4842 );
4943
5044 @override
51- LintCode get diagnosticCode => code;
52-
53- @override
54- void registerNodeProcessors (
55- RuleVisitorRegistry registry,
56- RuleContext context,
45+ void run (
46+ CustomLintResolver resolver,
47+ ErrorReporter reporter,
48+ CustomLintContext context,
5749 ) {
58- final visitor = _Visitor (this , context);
59- registry.addCompilationUnit (this , visitor);
60- }
61- }
62-
63- class _Visitor extends SimpleAstVisitor <void > {
64- _Visitor (this .rule, this .context);
50+ context.registry.addCompilationUnit ((node) {
51+ final path = resolver.path;
6552
66- final AnalysisRule rule;
67- final RuleContext context;
53+ // Read the raw file content to check for comments (which are not
54+ // present in the AST returned by toSource()).
55+ final file = File (path);
56+ if (! file.existsSync ()) return ;
6857
69- @override
70- void visitCompilationUnit (CompilationUnit node) {
71- final unit = context.currentUnit;
72- if (unit == null ) return ;
58+ final content = file.readAsStringSync ();
59+ if (_hasLicenseHeader (content)) return ;
7360
74- // Use the content provided by the analysis context (no need to read
75- // the file from disk).
76- if (_hasLicenseHeader (unit.content)) return ;
77-
78- // Report the lint on the first token in the file.
79- rule.reportAtToken (node.beginToken);
61+ // Report the lint on the first token in the file.
62+ final firstToken = node.beginToken;
63+ reporter.atToken (firstToken, _code);
64+ });
8065 }
66+
67+ @override
68+ List <Fix > getFixes () => [_AddLicenseHeaderFix ()];
8169}
8270
8371/// Returns `true` if [content] starts with the expected license header.
8472bool _hasLicenseHeader (String content) {
8573 final lines = content.split ('\n ' );
86- if (lines.length < licenseHeader .length) return false ;
74+ if (lines.length < _licenseHeader .length) return false ;
8775
88- for (var i = 0 ; i < licenseHeader .length; i++ ) {
89- if (lines[i].trimRight () != licenseHeader [i]) return false ;
76+ for (var i = 0 ; i < _licenseHeader .length; i++ ) {
77+ if (lines[i].trimRight () != _licenseHeader [i]) return false ;
9078 }
9179 return true ;
9280}
81+
82+ class _AddLicenseHeaderFix extends DartFix {
83+ @override
84+ void run (
85+ CustomLintResolver resolver,
86+ ChangeReporter reporter,
87+ CustomLintContext context,
88+ AnalysisError analysisError,
89+ List <AnalysisError > others,
90+ ) {
91+ context.registry.addCompilationUnit ((node) {
92+ if (! analysisError.sourceRange.intersects (node.beginToken.sourceRange)) {
93+ return ;
94+ }
95+
96+ final changeBuilder = reporter.createChangeBuilder (
97+ message: 'Add license header' ,
98+ priority: 100 ,
99+ );
100+
101+ changeBuilder.addDartFileEdit ((builder) {
102+ builder.addSimpleInsertion (
103+ 0 ,
104+ '${_licenseHeader .join ('\n ' )}\n\n ' ,
105+ );
106+ });
107+ });
108+ }
109+ }
0 commit comments