| 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 |