allow LINT to reference a relative line (#2007)
diff --git a/pubspec.yaml b/pubspec.yaml
index cb16a87..c1c8c96 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -9,7 +9,7 @@
documentation: https://dart-lang.github.io/linter/lints
environment:
- sdk: '>=2.2.2 <3.0.0'
+ sdk: '>=2.6.0 <3.0.0'
dependencies:
analyzer: ^0.39.3
diff --git a/test/rule_test.dart b/test/rule_test.dart
index e0ddffe..ff7bcb8 100644
--- a/test/rule_test.dart
+++ b/test/rule_test.dart
@@ -247,9 +247,8 @@
var lineNumber = 1;
for (var line in file.readAsLinesSync()) {
- var annotation = extractAnnotation(line);
+ var annotation = extractAnnotation(lineNumber, line);
if (annotation != null) {
- annotation.lineNumber = lineNumber;
expected.add(AnnotationMatcher(annotation));
}
++lineNumber;
diff --git a/test/util/annotation.dart b/test/util/annotation.dart
index 396dc4a..dd2e521 100644
--- a/test/util/annotation.dart
+++ b/test/util/annotation.dart
@@ -6,49 +6,28 @@
import 'package:analyzer/src/generated/source.dart';
import 'package:linter/src/analyzer.dart';
-Annotation extractAnnotation(String line) {
- final index = line.indexOf(RegExp(r'(//|#)[ ]?LINT'));
+Annotation extractAnnotation(int lineNumber, String line) {
+ final regexp =
+ RegExp(r'(//|#) ?LINT( \[([\-+]\d+)?(,?(\d+):(\d+))?\])?( (.*))?$');
+ final match = regexp.firstMatch(line);
+ if (match == null) return null;
- if (index == -1) {
- return null;
- }
+ // ignore lints on commented out lines
+ final index = match.start;
+ final comment = match[1];
+ if (line.indexOf(comment) != index) return null;
- // Grab the first comment to see if there's one preceding the annotation.
- // Check for '#' first to allow for lints on dartdocs.
- var comment = line.indexOf('#');
- if (comment == -1) {
- comment = line.indexOf('//');
- }
+ final relativeLine = match[3].toInt() ?? 0;
+ final column = match[5].toInt();
+ final length = match[6].toInt();
+ final message = match[8].toNullIfBlank();
+ return Annotation.forLint(message, column, length)
+ ..lineNumber = lineNumber + relativeLine;
+}
- // If the offset of the comment is not the offset of the annotation (for
- // example, `"My phone #" # LINT`), do not proceed.
- if (comment != index) {
- return null;
- }
-
- int column;
- int length;
- var annotation = line.substring(index);
- var leftBrace = annotation.indexOf('[');
- if (leftBrace != -1) {
- var sep = annotation.indexOf(':');
- column = int.parse(annotation.substring(leftBrace + 1, sep));
- var rightBrace = annotation.indexOf(']');
- length = int.parse(annotation.substring(sep + 1, rightBrace));
- }
-
- var msgIndex = annotation.indexOf(']') + 1;
- if (msgIndex < 1) {
- msgIndex = annotation.indexOf('T') + 1;
- }
- String msg;
- if (msgIndex < line.length) {
- msg = line.substring(index + msgIndex).trim();
- if (msg.isEmpty) {
- msg = null;
- }
- }
- return Annotation.forLint(msg, column, length);
+extension on String {
+ int toInt() => this == null ? null : int.parse(this);
+ String toNullIfBlank() => this == null || trim().isEmpty ? null : this;
}
/// Information about a 'LINT' annotation/comment.
diff --git a/test/util/annotation_test.dart b/test/util/annotation_test.dart
index 75feea2..ae1bd9a 100644
--- a/test/util/annotation_test.dart
+++ b/test/util/annotation_test.dart
@@ -10,22 +10,37 @@
void main() {
test('extraction', () {
- expect(extractAnnotation('int x; // LINT [1:3]'), isNotNull);
- expect(extractAnnotation('int x; //LINT'), isNotNull);
- expect(extractAnnotation('int x; // OK'), isNull);
- expect(extractAnnotation('int x;'), isNull);
- expect(extractAnnotation('dynamic x; // LINT dynamic is bad').message,
+ expect(extractAnnotation(1, 'int x; // LINT [1:3]'), isNotNull);
+ expect(extractAnnotation(1, 'int x; //LINT'), isNotNull);
+ expect(extractAnnotation(1, 'int x; // OK'), isNull);
+ expect(extractAnnotation(1, 'int x;'), isNull);
+ expect(extractAnnotation(1, 'dynamic x; // LINT dynamic is bad').message,
'dynamic is bad');
- expect(extractAnnotation('dynamic x; // LINT [1:3] dynamic is bad').message,
+ expect(extractAnnotation(1, 'dynamic x; // LINT dynamic is bad').lineNumber,
+ 1);
+ expect(
+ extractAnnotation(1, 'dynamic x; // LINT [1:3] dynamic is bad').message,
'dynamic is bad');
expect(
- extractAnnotation('dynamic x; // LINT [1:3] dynamic is bad').column, 1);
+ extractAnnotation(1, 'dynamic x; // LINT [1:3] dynamic is bad').column,
+ 1);
expect(
- extractAnnotation('dynamic x; // LINT [1:3] dynamic is bad').length, 3);
- expect(extractAnnotation('dynamic x; //LINT').message, isNull);
- expect(extractAnnotation('dynamic x; //LINT ').message, isNull);
+ extractAnnotation(1, 'dynamic x; // LINT [1:3] dynamic is bad').length,
+ 3);
+ expect(extractAnnotation(1, 'dynamic x; //LINT').message, isNull);
+ expect(extractAnnotation(1, 'dynamic x; //LINT ').message, isNull);
// Commented out lines shouldn't get linted.
- expect(extractAnnotation('// dynamic x; //LINT '), isNull);
+ expect(extractAnnotation(1, '// dynamic x; //LINT '), isNull);
+ expect(extractAnnotation(1, 'int x; // LINT [2:3]').lineNumber, 1);
+ expect(extractAnnotation(1, 'int x; // LINT [2:3]').column, 2);
+ expect(extractAnnotation(1, 'int x; // LINT [2:3]').length, 3);
+ expect(extractAnnotation(1, 'int x; // LINT [+2]').lineNumber, 3);
+ expect(extractAnnotation(1, 'int x; // LINT [+2]').column, isNull);
+ expect(extractAnnotation(1, 'int x; // LINT [+2]').length, isNull);
+ expect(extractAnnotation(1, 'int x; // LINT [+2,4:5]').lineNumber, 3);
+ expect(extractAnnotation(1, 'int x; // LINT [+2,4:5]').column, 4);
+ expect(extractAnnotation(1, 'int x; // LINT [+2,4:5]').length, 5);
+ expect(extractAnnotation(10, 'int x; // LINT [-2]').lineNumber, 8);
});
test('equality', () {