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

Side by Side Diff: pkg/analyzer/lib/src/task/dart.dart

Issue 1702733002: Support for line-level error suppression (#25685). (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: review nits Created 4 years, 10 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 unified diff | Download patch
« no previous file with comments | « no previous file | pkg/analyzer/test/generated/error_suppression_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library analyzer.src.task.dart; 5 library analyzer.src.task.dart;
6 6
7 import 'dart:collection'; 7 import 'dart:collection';
8 8
9 import 'package:analyzer/dart/ast/ast.dart'; 9 import 'package:analyzer/dart/ast/ast.dart';
10 import 'package:analyzer/dart/ast/token.dart';
10 import 'package:analyzer/dart/ast/visitor.dart'; 11 import 'package:analyzer/dart/ast/visitor.dart';
11 import 'package:analyzer/dart/element/element.dart'; 12 import 'package:analyzer/dart/element/element.dart';
12 import 'package:analyzer/dart/element/type.dart'; 13 import 'package:analyzer/dart/element/type.dart';
13 import 'package:analyzer/src/context/cache.dart'; 14 import 'package:analyzer/src/context/cache.dart';
14 import 'package:analyzer/src/context/context.dart'; 15 import 'package:analyzer/src/context/context.dart';
15 import 'package:analyzer/src/dart/ast/utilities.dart'; 16 import 'package:analyzer/src/dart/ast/utilities.dart';
16 import 'package:analyzer/src/dart/element/builder.dart'; 17 import 'package:analyzer/src/dart/element/builder.dart';
17 import 'package:analyzer/src/dart/element/element.dart'; 18 import 'package:analyzer/src/dart/element/element.dart';
19 import 'package:analyzer/src/dart/scanner/reader.dart';
20 import 'package:analyzer/src/dart/scanner/scanner.dart';
18 import 'package:analyzer/src/generated/constant.dart'; 21 import 'package:analyzer/src/generated/constant.dart';
19 import 'package:analyzer/src/generated/engine.dart'; 22 import 'package:analyzer/src/generated/engine.dart';
20 import 'package:analyzer/src/generated/error.dart'; 23 import 'package:analyzer/src/generated/error.dart';
21 import 'package:analyzer/src/generated/error_verifier.dart'; 24 import 'package:analyzer/src/generated/error_verifier.dart';
22 import 'package:analyzer/src/generated/incremental_resolver.dart'; 25 import 'package:analyzer/src/generated/incremental_resolver.dart';
23 import 'package:analyzer/src/generated/java_engine.dart'; 26 import 'package:analyzer/src/generated/java_engine.dart';
24 import 'package:analyzer/src/generated/parser.dart'; 27 import 'package:analyzer/src/generated/parser.dart';
25 import 'package:analyzer/src/generated/resolver.dart'; 28 import 'package:analyzer/src/generated/resolver.dart';
26 import 'package:analyzer/dart/ast/token.dart';
27 import 'package:analyzer/src/dart/scanner/scanner.dart';
28 import 'package:analyzer/src/dart/scanner/reader.dart';
29 import 'package:analyzer/src/generated/sdk.dart'; 29 import 'package:analyzer/src/generated/sdk.dart';
30 import 'package:analyzer/src/generated/source.dart'; 30 import 'package:analyzer/src/generated/source.dart';
31 import 'package:analyzer/src/generated/utilities_dart.dart';
31 import 'package:analyzer/src/generated/visitors.dart'; 32 import 'package:analyzer/src/generated/visitors.dart';
32 import 'package:analyzer/src/plugin/engine_plugin.dart'; 33 import 'package:analyzer/src/plugin/engine_plugin.dart';
33 import 'package:analyzer/src/services/lint.dart'; 34 import 'package:analyzer/src/services/lint.dart';
34 import 'package:analyzer/src/task/driver.dart'; 35 import 'package:analyzer/src/task/driver.dart';
35 import 'package:analyzer/src/task/general.dart'; 36 import 'package:analyzer/src/task/general.dart';
36 import 'package:analyzer/src/task/html.dart'; 37 import 'package:analyzer/src/task/html.dart';
37 import 'package:analyzer/src/task/inputs.dart'; 38 import 'package:analyzer/src/task/inputs.dart';
38 import 'package:analyzer/src/task/model.dart'; 39 import 'package:analyzer/src/task/model.dart';
39 import 'package:analyzer/src/task/strong/checker.dart'; 40 import 'package:analyzer/src/task/strong/checker.dart';
40 import 'package:analyzer/src/task/strong_mode.dart'; 41 import 'package:analyzer/src/task/strong_mode.dart';
41 import 'package:analyzer/task/dart.dart'; 42 import 'package:analyzer/task/dart.dart';
42 import 'package:analyzer/task/general.dart'; 43 import 'package:analyzer/task/general.dart';
43 import 'package:analyzer/task/model.dart'; 44 import 'package:analyzer/task/model.dart';
44 import 'package:analyzer/src/generated/utilities_dart.dart';
45 45
46 /** 46 /**
47 * The [ResultCachingPolicy] for ASTs. 47 * The [ResultCachingPolicy] for ASTs.
48 */ 48 */
49 const ResultCachingPolicy AST_CACHING_POLICY = 49 const ResultCachingPolicy AST_CACHING_POLICY =
50 const SimpleResultCachingPolicy(8192, 8192); 50 const SimpleResultCachingPolicy(8192, 8192);
51 51
52 /** 52 /**
53 * The [ResultCachingPolicy] for [Element]s. 53 * The [ResultCachingPolicy] for [Element]s.
54 */ 54 */
(...skipping 2162 matching lines...) Expand 10 before | Expand all | Expand 10 after
2217 * A task that merges all of the errors for a single source into a single list 2217 * A task that merges all of the errors for a single source into a single list
2218 * of errors. 2218 * of errors.
2219 */ 2219 */
2220 class DartErrorsTask extends SourceBasedAnalysisTask { 2220 class DartErrorsTask extends SourceBasedAnalysisTask {
2221 /** 2221 /**
2222 * The task descriptor describing this kind of task. 2222 * The task descriptor describing this kind of task.
2223 */ 2223 */
2224 static final TaskDescriptor DESCRIPTOR = new TaskDescriptor('DartErrorsTask', 2224 static final TaskDescriptor DESCRIPTOR = new TaskDescriptor('DartErrorsTask',
2225 createTask, buildInputs, <ResultDescriptor>[DART_ERRORS]); 2225 createTask, buildInputs, <ResultDescriptor>[DART_ERRORS]);
2226 2226
2227 // Prefix for comments ignoring error codes.
2228 static const String _normalizedIgnorePrefix = '//#ignore:';
2229
2227 DartErrorsTask(InternalAnalysisContext context, AnalysisTarget target) 2230 DartErrorsTask(InternalAnalysisContext context, AnalysisTarget target)
2228 : super(context, target); 2231 : super(context, target);
2229 2232
2230 @override 2233 @override
2231 TaskDescriptor get descriptor => DESCRIPTOR; 2234 TaskDescriptor get descriptor => DESCRIPTOR;
2232 2235
2233 @override 2236 @override
2234 void internalPerform() { 2237 void internalPerform() {
2235 List<List<AnalysisError>> errorLists = <List<AnalysisError>>[]; 2238 List<List<AnalysisError>> errorLists = <List<AnalysisError>>[];
2236 // 2239 //
2237 // Prepare inputs. 2240 // Prepare inputs.
2238 // 2241 //
2239 EnginePlugin enginePlugin = AnalysisEngine.instance.enginePlugin; 2242 EnginePlugin enginePlugin = AnalysisEngine.instance.enginePlugin;
2240 for (ResultDescriptor result in enginePlugin.dartErrorsForSource) { 2243 for (ResultDescriptor result in enginePlugin.dartErrorsForSource) {
2241 String inputName = result.name + '_input'; 2244 String inputName = result.name + '_input';
2242 errorLists.add(getRequiredInput(inputName)); 2245 errorLists.add(getRequiredInput(inputName));
2243 } 2246 }
2244 for (ResultDescriptor result in enginePlugin.dartErrorsForUnit) { 2247 for (ResultDescriptor result in enginePlugin.dartErrorsForUnit) {
2245 String inputName = result.name + '_input'; 2248 String inputName = result.name + '_input';
2246 Map<Source, List<AnalysisError>> errorMap = getRequiredInput(inputName); 2249 Map<Source, List<AnalysisError>> errorMap = getRequiredInput(inputName);
2247 for (List<AnalysisError> errors in errorMap.values) { 2250 for (List<AnalysisError> errors in errorMap.values) {
2248 errorLists.add(errors); 2251 errorLists.add(errors);
2249 } 2252 }
2250 } 2253 }
2254
2255 //
2256 // Filter ignored errors.
2257 //
2258 List<AnalysisError> errors =
2259 _filterIgnores(AnalysisError.mergeLists(errorLists));
2260
2251 // 2261 //
2252 // Record outputs. 2262 // Record outputs.
2253 // 2263 //
2254 outputs[DART_ERRORS] = AnalysisError.mergeLists(errorLists); 2264 outputs[DART_ERRORS] = errors;
2255 } 2265 }
2256 2266
2267 List<AnalysisError> _filterIgnores(List<AnalysisError> errors) {
2268 if (errors.isEmpty) {
2269 return errors;
2270 }
2271
2272 List<AnalysisError> filtered = <AnalysisError>[];
2273
2274 // Sort errors.
2275 errors.sort((AnalysisError e1, AnalysisError e2) => e1.offset - e2.offset);
2276
2277 Source source = target;
2278 String contents = context.getContents(source).data;
2279 Scanner scanner = new Scanner(source, new CharSequenceReader(contents),
2280 AnalysisErrorListener.NULL_LISTENER);
2281
2282 // Scan.
2283 Token token = scanner.tokenize();
2284 LineInfo lineInfo = new LineInfo(scanner.lineStarts);
2285
2286 int errorIndex = 0;
2287
2288 // Step through tokens looking for comments.
2289 while (errorIndex < errors.length && token.type != TokenType.EOF) {
2290 // Find leading comment.
2291 Token comments = token.precedingComments;
2292 while (comments?.next != null) {
2293 comments = comments.next;
2294 }
2295
2296 // Normalize content.
2297 String comment =
2298 comments?.lexeme?.toLowerCase()?.replaceAll(new RegExp(r'\s+'), '');
2299
2300 // Check for ignores.
2301 if (comment != null && comment.startsWith(_normalizedIgnorePrefix)) {
2302 int affectedLine = lineInfo.getLocation(token.offset).lineNumber;
2303
2304 // Process all affected errors.
2305 while (errorIndex < errors.length) {
2306 AnalysisError currentError = errors[errorIndex++];
2307 int errorLine = lineInfo.getLocation(currentError.offset).lineNumber;
2308 if (errorLine < affectedLine) {
2309 filtered.add(currentError);
2310 } else if (errorLine == affectedLine) {
2311 // Check for an ignore.
2312 if (!_isIgnoredBy(currentError, comment)) {
2313 filtered.add(currentError);
2314 }
2315 } else {
2316 // Back up index and break.
2317 --errorIndex;
2318 break;
2319 }
2320 }
2321 }
2322
2323 token = token.next;
2324 }
2325
2326 // Add remaining errors.
2327 if (errorIndex < errors.length) {
2328 filtered.addAll(errors.sublist(errorIndex));
2329 }
2330
2331 return filtered;
2332 }
2333
2334 bool _isIgnoredBy(AnalysisError error, String comment) => comment
2335 .substring(_normalizedIgnorePrefix.length)
2336 .split(',')
2337 .contains(error.errorCode.name.toLowerCase());
2338
2257 /** 2339 /**
2258 * Return a map from the names of the inputs of this kind of task to the task 2340 * Return a map from the names of the inputs of this kind of task to the task
2259 * input descriptors describing those inputs for a task with the 2341 * input descriptors describing those inputs for a task with the
2260 * given [target]. 2342 * given [target].
2261 */ 2343 */
2262 static Map<String, TaskInput> buildInputs(AnalysisTarget target) { 2344 static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
2263 Source source = target; 2345 Source source = target;
2264 Map<String, TaskInput> inputs = <String, TaskInput>{}; 2346 Map<String, TaskInput> inputs = <String, TaskInput>{};
2265 EnginePlugin enginePlugin = AnalysisEngine.instance.enginePlugin; 2347 EnginePlugin enginePlugin = AnalysisEngine.instance.enginePlugin;
2266 // for Source 2348 // for Source
(...skipping 3025 matching lines...) Expand 10 before | Expand all | Expand 10 after
5292 5374
5293 @override 5375 @override
5294 bool moveNext() { 5376 bool moveNext() {
5295 if (_newSources.isEmpty) { 5377 if (_newSources.isEmpty) {
5296 return false; 5378 return false;
5297 } 5379 }
5298 currentTarget = _newSources.removeLast(); 5380 currentTarget = _newSources.removeLast();
5299 return true; 5381 return true;
5300 } 5382 }
5301 } 5383 }
OLDNEW
« no previous file with comments | « no previous file | pkg/analyzer/test/generated/error_suppression_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698