Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(7)

Unified Diff: pkg/analyzer/lib/src/task/dart.dart

Issue 2011183004: Precompute `IgnoreInfo` in Scanner. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: review_fixes Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | pkg/analyzer/test/src/task/dart_test.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/analyzer/lib/src/task/dart.dart
diff --git a/pkg/analyzer/lib/src/task/dart.dart b/pkg/analyzer/lib/src/task/dart.dart
index 3d9d552329932b3980bcfe8b95d5800764b49440..5eb259081e105c00890ee26bd60fcbca9d4d0561 100644
--- a/pkg/analyzer/lib/src/task/dart.dart
+++ b/pkg/analyzer/lib/src/task/dart.dart
@@ -335,6 +335,12 @@ final ListResultDescriptor<AnalysisError> HINTS =
'HINT_ERRORS', AnalysisError.NO_ERRORS);
/**
+ * The ignore information for a [Source].
+ */
+final ResultDescriptor<IgnoreInfo> IGNORE_INFO =
+ new ResultDescriptor<IgnoreInfo>('IGNORE_INFO', null);
+
+/**
* A list of the [VariableElement]s whose type should be inferred that another
* inferable static variable (the target) depends on.
*
@@ -2520,8 +2526,6 @@ class DartDelta extends Delta {
* of errors.
*/
class DartErrorsTask extends SourceBasedAnalysisTask {
- static final RegExp spacesRegExp = new RegExp(r'\s+');
-
/**
* The task descriptor describing this kind of task.
*/
@@ -2529,17 +2533,14 @@ class DartErrorsTask extends SourceBasedAnalysisTask {
createTask, buildInputs, <ResultDescriptor>[DART_ERRORS]);
/**
- * The name of the [LINE_INFO_INPUT] input.
+ * The name of the [IGNORE_INFO_INPUT] input.
*/
- static const String LINE_INFO_INPUT = 'LINE_INFO_INPUT';
+ static const String IGNORE_INFO_INPUT = 'IGNORE_INFO_INPUT';
/**
- * The name of the [PARSED_UNIT_INPUT] input.
+ * The name of the [LINE_INFO_INPUT] input.
*/
- static const String PARSED_UNIT_INPUT = 'PARSED_UNIT_INPUT';
-
- // Prefix for comments ignoring error codes.
- static const String _normalizedIgnorePrefix = '//ignore:';
+ static const String LINE_INFO_INPUT = 'LINE_INFO_INPUT';
DartErrorsTask(InternalAnalysisContext context, AnalysisTarget target)
: super(context, target);
@@ -2584,71 +2585,29 @@ class DartErrorsTask extends SourceBasedAnalysisTask {
outputs[DART_ERRORS] = errors;
}
- Token _advanceToLine(Token token, LineInfo lineInfo, int line) {
- int offset = lineInfo.getOffsetOfLine(line - 1); // 0-based
- while (token.offset < offset) {
- token = token.next;
- }
- return token;
- }
-
List<AnalysisError> _filterIgnores(List<AnalysisError> errors) {
if (errors.isEmpty) {
return errors;
}
- // Sort errors.
- errors.sort((AnalysisError e1, AnalysisError e2) => e1.offset - e2.offset);
+ IgnoreInfo ignoreInfo = getRequiredInput(IGNORE_INFO_INPUT);
+ if (!ignoreInfo.hasIgnores) {
+ return errors;
+ }
- CompilationUnit cu = getRequiredInput(PARSED_UNIT_INPUT);
- Token token = cu.beginToken;
LineInfo lineInfo = getRequiredInput(LINE_INFO_INPUT);
bool isIgnored(AnalysisError error) {
int errorLine = lineInfo.getLocation(error.offset).lineNumber;
- token = _advanceToLine(token, lineInfo, errorLine);
-
- //Check for leading comment.
- Token comments = token.precedingComments;
- while (comments?.next != null) {
- comments = comments.next;
- }
- if (_isIgnoredBy(error, comments)) {
- return true;
- }
-
- //Check for trailing comment.
- int lineNumber = errorLine + 1;
- if (lineNumber <= lineInfo.lineCount) {
- Token nextLine = _advanceToLine(token, lineInfo, lineNumber);
- comments = nextLine.precedingComments;
- if (comments != null && nextLine.previous.type != TokenType.EOF) {
- int commentLine = lineInfo.getLocation(comments.offset).lineNumber;
- if (commentLine == errorLine) {
- return _isIgnoredBy(error, comments);
- }
- }
- }
-
- return false;
+ String errorCode = error.errorCode.name.toLowerCase();
+ // Ignores can be on the line or just preceding the error.
+ return ignoreInfo.ignoredAt(errorCode, errorLine) ||
+ ignoreInfo.ignoredAt(errorCode, errorLine - 1);
}
return errors.where((AnalysisError e) => !isIgnored(e)).toList();
}
- bool _isIgnoredBy(AnalysisError error, Token comment) {
- //Normalize first.
- String contents =
- comment?.lexeme?.toLowerCase()?.replaceAll(spacesRegExp, '');
- if (contents == null || !contents.startsWith(_normalizedIgnorePrefix)) {
- return false;
- }
- return contents
- .substring(_normalizedIgnorePrefix.length)
- .split(',')
- .contains(error.errorCode.name.toLowerCase());
- }
-
/**
* Return a map from the names of the inputs of this kind of task to the task
* input descriptors describing those inputs for a task with the
@@ -2658,7 +2617,7 @@ class DartErrorsTask extends SourceBasedAnalysisTask {
Source source = target;
Map<String, TaskInput> inputs = <String, TaskInput>{};
inputs[LINE_INFO_INPUT] = LINE_INFO.of(source);
- inputs[PARSED_UNIT_INPUT] = PARSED_UNIT.of(source);
+ inputs[IGNORE_INFO_INPUT] = IGNORE_INFO.of(source);
EnginePlugin enginePlugin = AnalysisEngine.instance.enginePlugin;
// for Source
List<ResultDescriptor> errorsForSource = enginePlugin.dartErrorsForSource;
@@ -3100,6 +3059,78 @@ class GenerateLintsTask extends SourceBasedAnalysisTask {
}
/**
+ * Information about analysis `//ignore:` comments within a source file.
+ */
+class IgnoreInfo {
+ /**
+ * Instance shared by all cases without matches.
+ */
+ static final IgnoreInfo _EMPTY_INFO = new IgnoreInfo();
+
+ /**
+ * A regular expression for matching 'ignore' comments. Produces matches
+ * containing 2 groups. For example:
+ *
+ * * ['//ignore: error_code', 'error_code']
+ *
+ * Resulting codes may be in a list ('error_code_1,error_code2').
+ */
+ static final RegExp _IGNORE_MATCHER =
+ new RegExp(r'//[ ]*ignore:(.*)$', multiLine: true);
+
+ final Map<int, List<String>> _ignoreMap = new HashMap<int, List<String>>();
+
+ /**
+ * Whether this info object defines any ignores.
+ */
+ bool get hasIgnores => ignores.isNotEmpty;
+
+ /**
+ * Map of line numbers to associated ignored error codes.
+ */
+ Map<int, Iterable<String>> get ignores => _ignoreMap;
+
+ /**
+ * Ignore this [errorCode] at [line].
+ */
+ void add(int line, String errorCode) {
+ _ignoreMap.putIfAbsent(line, () => new List<String>()).add(errorCode);
+ }
+
+ /**
+ * Ignore these [errorCodes] at [line].
+ */
+ void addAll(int line, Iterable<String> errorCodes) {
+ _ignoreMap.putIfAbsent(line, () => new List<String>()).addAll(errorCodes);
+ }
+
+ /**
+ * Test whether this [errorCode] is ignored at the given [line].
+ */
+ bool ignoredAt(String errorCode, int line) =>
+ _ignoreMap[line]?.contains(errorCode) == true;
+
+ /**
+ * Calculate ignores for the given [content] with line [info].
+ */
+ static IgnoreInfo calculateIgnores(String content, LineInfo info) {
+ Iterable<Match> matches = _IGNORE_MATCHER.allMatches(content);
+ if (matches.isEmpty) {
+ return _EMPTY_INFO;
+ }
+
+ IgnoreInfo ignoreInfo = new IgnoreInfo();
+ for (Match match in matches) {
+ // See _IGNORE_MATCHER for format --- note the possibility of error lists.
+ Iterable<String> codes =
+ match.group(1).split(',').map((String code) => code.trim());
+ ignoreInfo.addAll(info.getLocation(match.start).lineNumber, codes);
+ }
+ return ignoreInfo;
+ }
+}
+
+/**
* A task that ensures that all of the inferable instance members in a
* compilation unit have had their type inferred.
*/
@@ -5429,7 +5460,7 @@ class ScanDartTask extends SourceBasedAnalysisTask {
'ScanDartTask',
createTask,
buildInputs,
- <ResultDescriptor>[LINE_INFO, SCAN_ERRORS, TOKEN_STREAM],
+ <ResultDescriptor>[IGNORE_INFO, LINE_INFO, SCAN_ERRORS, TOKEN_STREAM],
suitabilityFor: suitabilityFor);
/**
@@ -5482,8 +5513,12 @@ class ScanDartTask extends SourceBasedAnalysisTask {
scanner.preserveComments = context.analysisOptions.preserveComments;
scanner.scanGenericMethodComments = context.analysisOptions.strongMode;
+ LineInfo lineInfo = new LineInfo(scanner.lineStarts);
+
outputs[TOKEN_STREAM] = scanner.tokenize();
- outputs[LINE_INFO] = new LineInfo(scanner.lineStarts);
+ outputs[LINE_INFO] = lineInfo;
+ outputs[IGNORE_INFO] =
+ IgnoreInfo.calculateIgnores(fragment.content, lineInfo);
outputs[SCAN_ERRORS] = getUniqueErrors(errorListener.errors);
} else if (target is Source) {
String content = getRequiredInput(CONTENT_INPUT_NAME);
@@ -5493,8 +5528,11 @@ class ScanDartTask extends SourceBasedAnalysisTask {
scanner.preserveComments = context.analysisOptions.preserveComments;
scanner.scanGenericMethodComments = context.analysisOptions.strongMode;
+ LineInfo lineInfo = new LineInfo(scanner.lineStarts);
+
outputs[TOKEN_STREAM] = scanner.tokenize();
- outputs[LINE_INFO] = new LineInfo(scanner.lineStarts);
+ outputs[LINE_INFO] = lineInfo;
+ outputs[IGNORE_INFO] = IgnoreInfo.calculateIgnores(content, lineInfo);
outputs[SCAN_ERRORS] = getUniqueErrors(errorListener.errors);
} else {
throw new AnalysisException(
« no previous file with comments | « no previous file | pkg/analyzer/test/src/task/dart_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698