OLD | NEW |
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 /// Command line tool to run the checker on a Dart program. | 5 /// Command line tool to run the checker on a Dart program. |
6 library dev_compiler.src.compiler; | 6 library dev_compiler.src.compiler; |
7 | 7 |
8 import 'dart:async'; | 8 import 'dart:async'; |
9 import 'dart:collection'; | 9 import 'dart:collection'; |
10 import 'dart:convert' show JSON; | 10 import 'dart:convert' show JSON; |
11 import 'dart:math' as math; | 11 import 'dart:math' as math; |
12 import 'dart:io'; | 12 import 'dart:io'; |
13 | 13 |
14 import 'package:analyzer/src/generated/ast.dart' show CompilationUnit; | 14 import 'package:analyzer/src/generated/ast.dart' show CompilationUnit; |
15 import 'package:analyzer/src/generated/element.dart'; | 15 import 'package:analyzer/src/generated/element.dart'; |
16 import 'package:analyzer/src/generated/engine.dart' | 16 import 'package:analyzer/src/generated/engine.dart' |
17 show AnalysisEngine, AnalysisContext, ChangeSet, ParseDartTask; | 17 show AnalysisEngine, AnalysisContext, ChangeSet, ParseDartTask; |
18 import 'package:analyzer/src/generated/error.dart' | 18 import 'package:analyzer/src/generated/error.dart' |
19 show AnalysisError, ErrorSeverity, ErrorType; | 19 show AnalysisError, ErrorSeverity, ErrorType; |
20 import 'package:analyzer/src/generated/error.dart'; | 20 import 'package:analyzer/src/generated/error.dart'; |
21 import 'package:analyzer/src/generated/source.dart' show Source; | 21 import 'package:analyzer/src/generated/source.dart' show Source; |
22 import 'package:analyzer/src/task/html.dart'; | 22 import 'package:analyzer/src/task/html.dart'; |
23 import 'package:html/dom.dart' as html; | 23 import 'package:html/dom.dart' as html; |
24 import 'package:html/parser.dart' as html; | 24 import 'package:html/parser.dart' as html; |
25 import 'package:logging/logging.dart' show Level, Logger, LogRecord; | 25 import 'package:logging/logging.dart' show Level, Logger, LogRecord; |
26 import 'package:path/path.dart' as path; | 26 import 'package:path/path.dart' as path; |
27 | 27 |
28 import 'analysis_context.dart'; | 28 import 'analysis_context.dart'; |
29 import 'checker/checker.dart'; | |
30 import 'checker/rules.dart'; | |
31 import 'codegen/html_codegen.dart' as html_codegen; | 29 import 'codegen/html_codegen.dart' as html_codegen; |
32 import 'codegen/js_codegen.dart'; | 30 import 'codegen/js_codegen.dart'; |
33 import 'info.dart' | 31 import 'info.dart' |
34 show AnalyzerMessage, CheckerResults, LibraryInfo, LibraryUnit; | 32 show AnalyzerMessage, CheckerResults, LibraryInfo, LibraryUnit; |
35 import 'options.dart'; | 33 import 'options.dart'; |
36 import 'report.dart'; | 34 import 'report.dart'; |
37 | 35 |
38 /// Sets up the type checker logger to print a span that highlights error | 36 /// Sets up the type checker logger to print a span that highlights error |
39 /// messages. | 37 /// messages. |
40 StreamSubscription setupLogger(Level level, printFn) { | 38 StreamSubscription setupLogger(Level level, printFn) { |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
107 new ErrorCollector( | 105 new ErrorCollector( |
108 reporter ?? AnalysisErrorListener.NULL_LISTENER)) { | 106 reporter ?? AnalysisErrorListener.NULL_LISTENER)) { |
109 _inputBaseDir = options.inputBaseDir; | 107 _inputBaseDir = options.inputBaseDir; |
110 if (outputDir != null) { | 108 if (outputDir != null) { |
111 _jsGen = new JSGenerator(this); | 109 _jsGen = new JSGenerator(this); |
112 _runtimeOutputDir = path.join(outputDir, 'dev_compiler', 'runtime'); | 110 _runtimeOutputDir = path.join(outputDir, 'dev_compiler', 'runtime'); |
113 } | 111 } |
114 _dartCore = context.typeProvider.objectType.element.library; | 112 _dartCore = context.typeProvider.objectType.element.library; |
115 } | 113 } |
116 | 114 |
117 ErrorCollector get reporter => checker.reporter; | 115 ErrorCollector get reporter => super.reporter; |
118 | 116 |
119 /// Compiles every file in [options.inputs]. | 117 /// Compiles every file in [options.inputs]. |
120 /// Returns true on successful compile. | 118 /// Returns true on successful compile. |
121 bool run() { | 119 bool run() { |
122 var clock = new Stopwatch()..start(); | 120 var clock = new Stopwatch()..start(); |
123 options.inputs.forEach(compileFromUriString); | 121 options.inputs.forEach(compileFromUriString); |
124 clock.stop(); | 122 clock.stop(); |
125 var time = (clock.elapsedMilliseconds / 1000).toStringAsFixed(2); | 123 var time = (clock.elapsedMilliseconds / 1000).toStringAsFixed(2); |
126 _log.fine('Compiled ${_compilationRecord.length} libraries in ${time} s\n'); | 124 _log.fine('Compiled ${_compilationRecord.length} libraries in ${time} s\n'); |
127 | 125 |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
218 } | 216 } |
219 | 217 |
220 // Check this library's own code | 218 // Check this library's own code |
221 var unitElements = [library.definingCompilationUnit]..addAll(library.parts); | 219 var unitElements = [library.definingCompilationUnit]..addAll(library.parts); |
222 var units = <CompilationUnit>[]; | 220 var units = <CompilationUnit>[]; |
223 | 221 |
224 bool failureInLib = false; | 222 bool failureInLib = false; |
225 for (var element in unitElements) { | 223 for (var element in unitElements) { |
226 var unit = context.resolveCompilationUnit(element.source, library); | 224 var unit = context.resolveCompilationUnit(element.source, library); |
227 units.add(unit); | 225 units.add(unit); |
228 failureInLib = logErrors(element.source) || failureInLib; | 226 failureInLib = computeErrors(element.source) || failureInLib; |
229 checker.reset(); | |
230 checker.visitCompilationUnit(unit); | |
231 if (checker.failure) failureInLib = true; | |
232 } | 227 } |
233 if (failureInLib) _compilationRecord[library] = false; | 228 if (failureInLib) _compilationRecord[library] = false; |
234 | 229 |
235 // Notifier framework if requested | 230 // Notifier framework if requested |
236 if (notifier != null) { | 231 if (notifier != null) { |
237 reporter.flush(); | 232 reporter.flush(); |
238 notifier(getOutputPath(library.source.uri)); | 233 notifier(getOutputPath(library.source.uri)); |
239 } | 234 } |
240 | 235 |
241 // Record valid libraries for further dependence checking (cycles) and | 236 // Record valid libraries for further dependence checking (cycles) and |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
352 for (var l in lib.exports) _collectLibraries(l.exportedLibrary, loaded); | 347 for (var l in lib.exports) _collectLibraries(l.exportedLibrary, loaded); |
353 // Move the item to the end of the list. | 348 // Move the item to the end of the list. |
354 loaded.remove(uri); | 349 loaded.remove(uri); |
355 loaded.add(uri); | 350 loaded.add(uri); |
356 } | 351 } |
357 } | 352 } |
358 | 353 |
359 abstract class AbstractCompiler { | 354 abstract class AbstractCompiler { |
360 final CompilerOptions options; | 355 final CompilerOptions options; |
361 final AnalysisContext context; | 356 final AnalysisContext context; |
362 final CodeChecker checker; | 357 final AnalysisErrorListener reporter; |
363 | 358 |
364 AbstractCompiler(AnalysisContext context, CompilerOptions options, | 359 AbstractCompiler(this.context, this.options, [this.reporter]); |
365 [AnalysisErrorListener reporter]) | |
366 : context = context, | |
367 options = options, | |
368 checker = new CodeChecker( | |
369 new TypeRules(context.typeProvider, options: options.strongOptions), | |
370 reporter ?? AnalysisErrorListener.NULL_LISTENER); | |
371 | 360 |
372 String get outputDir => options.codegenOptions.outputDir; | 361 String get outputDir => options.codegenOptions.outputDir; |
373 TypeRules get rules => checker.rules; | |
374 AnalysisErrorListener get reporter => checker.reporter; | |
375 | 362 |
376 Uri stringToUri(String uriString) { | 363 Uri stringToUri(String uriString) { |
377 var uri = uriString.startsWith('dart:') || uriString.startsWith('package:') | 364 var uri = uriString.startsWith('dart:') || uriString.startsWith('package:') |
378 ? Uri.parse(uriString) | 365 ? Uri.parse(uriString) |
379 : new Uri.file(path.absolute(uriString)); | 366 : new Uri.file(path.absolute(uriString)); |
380 return uri; | 367 return uri; |
381 } | 368 } |
382 | 369 |
383 /// Directory presumed to be the common prefix for all input file:// URIs. | 370 /// Directory presumed to be the common prefix for all input file:// URIs. |
384 /// Used when computing output paths. | 371 /// Used when computing output paths. |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
447 } else { | 434 } else { |
448 assert(uri.scheme == 'package'); | 435 assert(uri.scheme == 'package'); |
449 // filepath is good here, we want the output to start with a directory | 436 // filepath is good here, we want the output to start with a directory |
450 // matching the package name. | 437 // matching the package name. |
451 return filepath; | 438 return filepath; |
452 } | 439 } |
453 } | 440 } |
454 | 441 |
455 /// Log any errors encountered when resolving [source] and return whether any | 442 /// Log any errors encountered when resolving [source] and return whether any |
456 /// errors were found. | 443 /// errors were found. |
457 bool logErrors(Source source) { | 444 bool computeErrors(Source source) { |
458 List<AnalysisError> errors = context.computeErrors(source); | 445 AnalysisContext errorContext = context; |
| 446 // TODO(jmesserly): should this be a fix somewhere in analyzer? |
| 447 // otherwise we fail to find the parts. |
| 448 if (source.uri.scheme == 'dart') { |
| 449 errorContext = context.sourceFactory.dartSdk.context; |
| 450 } |
| 451 List<AnalysisError> errors = errorContext.computeErrors(source); |
459 bool failure = false; | 452 bool failure = false; |
460 if (errors.isNotEmpty) { | 453 for (var error in errors) { |
461 for (var error in errors) { | 454 // Always skip TODOs. |
462 // Always skip TODOs. | 455 if (error.errorCode.type == ErrorType.TODO) continue; |
463 if (error.errorCode.type == ErrorType.TODO) continue; | |
464 | 456 |
465 // Skip hints for now. In the future these could be turned on via flags. | 457 // TODO(jmesserly): for now, treat DDC errors as having a different |
466 if (error.errorCode.errorSeverity.ordinal < | 458 // error level from Analayzer ones. |
467 ErrorSeverity.WARNING.ordinal) { | 459 if (error.errorCode.name.startsWith('dev_compiler')) { |
468 continue; | 460 reporter.onError(error); |
| 461 if (error.errorCode.errorSeverity == ErrorSeverity.ERROR) { |
| 462 failure = true; |
469 } | 463 } |
470 | 464 } else if (error.errorCode.errorSeverity.ordinal >= |
| 465 ErrorSeverity.WARNING.ordinal) { |
471 // All analyzer warnings or errors are errors for DDC. | 466 // All analyzer warnings or errors are errors for DDC. |
472 failure = true; | 467 failure = true; |
473 reporter.onError(error); | 468 reporter.onError(error); |
| 469 } else { |
| 470 // Skip hints for now. |
474 } | 471 } |
475 } | 472 } |
476 return failure; | 473 return failure; |
477 } | 474 } |
478 } | 475 } |
479 | 476 |
480 AnalysisErrorListener createErrorReporter( | 477 AnalysisErrorListener createErrorReporter( |
481 AnalysisContext context, CompilerOptions options) { | 478 AnalysisContext context, CompilerOptions options) { |
482 return options.dumpInfo | 479 return options.dumpInfo |
483 ? new SummaryReporter(context, options.logLevel) | 480 ? new SummaryReporter(context, options.logLevel) |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
526 '_rtti.js', | 523 '_rtti.js', |
527 '_classes.js', | 524 '_classes.js', |
528 '_operations.js', | 525 '_operations.js', |
529 'dart_runtime.js', | 526 'dart_runtime.js', |
530 ]; | 527 ]; |
531 files.addAll(corelibOrder.map((l) => l.replaceAll('.', '/') + '.js')); | 528 files.addAll(corelibOrder.map((l) => l.replaceAll('.', '/') + '.js')); |
532 return files; | 529 return files; |
533 }(); | 530 }(); |
534 | 531 |
535 final _log = new Logger('dev_compiler.src.compiler'); | 532 final _log = new Logger('dev_compiler.src.compiler'); |
OLD | NEW |