@@ -13,6 +13,7 @@ import 'package:analyzer/src/generated/source.dart';
13
13
import 'package:analyzer/src/services/lint.dart' ;
14
14
import 'package:analyzer/src/string_source.dart' ;
15
15
import 'package:linter/src/analysis.dart' ;
16
+ import 'package:linter/src/io.dart' ;
16
17
import 'package:linter/src/pub.dart' ;
17
18
import 'package:linter/src/rules.dart' ;
18
19
@@ -69,12 +70,15 @@ abstract class DartLinter {
69
70
Iterable <AnalysisErrorInfo > lintLibrarySource (
70
71
{String libraryName, String libraryContents});
71
72
72
- Iterable <AnalysisErrorInfo > lintPubSpecSource ({String contents});
73
+ Iterable <AnalysisErrorInfo > lintPubspecSource ({String contents});
73
74
}
74
75
75
76
class Group {
76
77
77
78
/// Defined rule groups.
79
+ static const Group PUB = const Group ._('Pub' ,
80
+ link: const Hyperlink ('See the <strong>Pubspec Format</strong>' ,
81
+ 'https://www.dartlang.org/tools/pub/pubspec.html' ));
78
82
static const Group STYLE_GUIDE = const Group ._('Style Guide' ,
79
83
link: const Hyperlink ('See the <strong>Style Guide</strong>' ,
80
84
'https://www.dartlang.org/articles/style-guide/' ));
@@ -89,6 +93,8 @@ class Group {
89
93
case 'Styleguide' :
90
94
case 'Style Guide' :
91
95
return STYLE_GUIDE ;
96
+ case 'Pub' :
97
+ return PUB ;
92
98
default :
93
99
return new Group ._(name,
94
100
custom: true , description: description, link: link);
@@ -211,6 +217,11 @@ abstract class LintRule extends Linter implements Comparable<LintRule> {
211
217
/// Lint name.
212
218
final CamelCaseString name;
213
219
220
+ /// Until pubspec analysis is pushed into the analyzer proper, we need to
221
+ /// do some extra book-keeping to keep track of details that will help us
222
+ /// constitute AnalysisErrorInfos.
223
+ final List <AnalysisErrorInfo > _locationInfo = < AnalysisErrorInfo > [];
224
+
214
225
LintRule ({String name, this .group, this .kind, this .description, this .details,
215
226
this .maturity: Maturity .STABLE })
216
227
: name = new CamelCaseString (name);
@@ -227,16 +238,25 @@ abstract class LintRule extends Linter implements Comparable<LintRule> {
227
238
/// Return a visitor to be passed to pubspecs to perform lint
228
239
/// analysis.
229
240
/// Lint errors are reported via this [Linter] 's error [reporter] .
230
- PubSpecVisitor getPubSpecVisitor () => null ;
241
+ PubSpecVisitor getPubspecVisitor () => null ;
242
+
243
+ @override
244
+ AstVisitor getVisitor () => null ;
231
245
232
246
void reportLint (AstNode node) {
233
247
reporter.reportErrorForNode (
234
248
new LintCode (name.value, description), node, []);
235
249
}
236
250
237
251
void reportPubLint (PSNode node) {
238
- reporter.reportErrorForOffset (new LintCode (name.value, description),
239
- node.span.start.offset, node.span.length);
252
+ // Cache error and location info for creating AnalysisErrorInfos
253
+ var error = new AnalysisError .con2 (reporter.source, node.span.start.offset,
254
+ node.span.length, new LintCode (name.value, description));
255
+
256
+ _locationInfo.add (new AnalysisErrorInfoImpl ([error], new _LineInfo (node)));
257
+
258
+ // Then do the reporting
259
+ reporter.reportError (error);
240
260
}
241
261
}
242
262
@@ -317,7 +337,9 @@ class SourceLinter implements DartLinter, AnalysisErrorListener {
317
337
318
338
@override
319
339
Iterable <AnalysisErrorInfo > lintFile (File sourceFile) =>
320
- _registerAndRun (() => new AnalysisDriver .forFile (sourceFile, options));
340
+ isPubspecFile (sourceFile)
341
+ ? _lintPubspecFile (sourceFile)
342
+ : _lintDartFile (sourceFile);
321
343
322
344
@override
323
345
Iterable <AnalysisErrorInfo > lintLibrarySource (
@@ -326,31 +348,39 @@ class SourceLinter implements DartLinter, AnalysisErrorListener {
326
348
new _StringSource (libraryContents, libraryName), options));
327
349
328
350
@override
329
- Iterable <AnalysisErrorInfo > lintPubSpecSource ({String contents}) {
351
+ Iterable <AnalysisErrorInfo > lintPubspecSource ({String contents}) {
352
+ var results = < AnalysisErrorInfo > [];
330
353
331
354
//TODO: error handling
332
355
var spec = new PubSpec .parse (contents);
333
356
334
357
for (Linter lint in options.enabledLints) {
335
358
if (lint is LintRule ) {
336
359
LintRule rule = lint;
337
- var visitor = rule.getPubSpecVisitor ();
360
+ var visitor = rule.getPubspecVisitor ();
338
361
if (visitor != null ) {
339
362
try {
340
363
spec.accept (visitor);
341
364
} on Exception catch (e) {
342
365
reporter.exception (new LinterException (e.toString ()));
343
366
}
367
+ results.addAll (rule._locationInfo);
344
368
}
345
369
}
346
370
}
347
- //TODO: collect and return errors
348
- return null ;
371
+
372
+ return results ;
349
373
}
350
374
351
375
@override
352
376
onError (AnalysisError error) => errors.add (error);
353
377
378
+ Iterable <AnalysisErrorInfo > _lintDartFile (File sourceFile) =>
379
+ _registerAndRun (() => new AnalysisDriver .forFile (sourceFile, options));
380
+
381
+ Iterable <AnalysisErrorInfo > _lintPubspecFile (File sourceFile) =>
382
+ lintPubspecSource (contents: sourceFile.readAsStringSync ());
383
+
354
384
Iterable <AnalysisErrorInfo > _registerAndRun (_DriverFactory createDriver) {
355
385
_registerLinters (options.enabledLints);
356
386
return createDriver ().getErrors ();
@@ -360,6 +390,15 @@ class SourceLinter implements DartLinter, AnalysisErrorListener {
360
390
new LinterOptions (() => ruleMap.values);
361
391
}
362
392
393
+ class _LineInfo implements LineInfo {
394
+ PSNode node;
395
+ _LineInfo (this .node);
396
+
397
+ @override
398
+ LineInfo_Location getLocation (int offset) =>
399
+ new LineInfo_Location (node.span.start.line + 1 , node.span.start.column);
400
+ }
401
+
363
402
class _StringSource extends StringSource {
364
403
_StringSource (String contents, String fullName) : super (contents, fullName);
365
404
0 commit comments