| 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 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 import 'dart:collection'; | 8 import 'dart:collection'; |
| 9 import 'dart:math' as math; | 9 import 'dart:math' as math; |
| 10 import 'dart:io'; | 10 import 'dart:io'; |
| 11 | 11 |
| 12 import 'package:analyzer/dart/ast/ast.dart' show CompilationUnit; | 12 import 'package:analyzer/dart/ast/ast.dart' show CompilationUnit; |
| 13 import 'package:analyzer/dart/element/element.dart'; | 13 import 'package:analyzer/dart/element/element.dart'; |
| 14 import 'package:analyzer/src/generated/engine.dart' | 14 import 'package:analyzer/src/generated/engine.dart' |
| 15 show AnalysisEngine, AnalysisContext, ChangeSet, ParseDartTask; | 15 show AnalysisEngine, AnalysisContext, ChangeSet, ParseDartTask; |
| 16 import 'package:analyzer/src/generated/error.dart' | 16 import 'package:analyzer/src/generated/error.dart' |
| 17 show AnalysisError, ErrorSeverity, ErrorType; | 17 show AnalysisError, ErrorSeverity, ErrorType; |
| 18 import 'package:analyzer/src/generated/error.dart'; | 18 import 'package:analyzer/src/generated/error.dart'; |
| 19 import 'package:analyzer/src/generated/source.dart' show Source; | 19 import 'package:analyzer/src/generated/source.dart' show Source; |
| 20 import 'package:analyzer/src/task/html.dart'; | 20 import 'package:analyzer/src/task/html.dart'; |
| 21 import 'package:html/dom.dart' as html; | 21 import 'package:html/dom.dart' as html; |
| 22 import 'package:html/parser.dart' as html; | 22 import 'package:html/parser.dart' as html; |
| 23 import 'package:logging/logging.dart' show Level, Logger, LogRecord; | 23 import 'package:logging/logging.dart' show Level, Logger, LogRecord; |
| 24 import 'package:path/path.dart' as path; | 24 import 'package:path/path.dart' as path; |
| 25 | 25 |
| 26 import 'analysis_context.dart'; | 26 import 'analysis_context.dart'; |
| 27 import 'codegen/html_codegen.dart' as html_codegen; | 27 import 'codegen/html_codegen.dart' as html_codegen; |
| 28 import 'codegen/js_codegen.dart'; | 28 import 'codegen/js_codegen.dart'; |
| 29 import 'info.dart' | |
| 30 show AnalyzerMessage, CheckerResults, LibraryInfo, LibraryUnit; | |
| 31 import 'options.dart'; | 29 import 'options.dart'; |
| 32 import 'report.dart'; | 30 import 'report.dart'; |
| 33 import 'report/html_reporter.dart'; | |
| 34 import 'utils.dart' show FileSystem, isStrongModeError; | 31 import 'utils.dart' show FileSystem, isStrongModeError; |
| 35 | 32 |
| 36 /// Sets up the type checker logger to print a span that highlights error | 33 /// Sets up the type checker logger to print a span that highlights error |
| 37 /// messages. | 34 /// messages. |
| 38 StreamSubscription setupLogger(Level level, printFn) { | 35 StreamSubscription setupLogger(Level level, printFn) { |
| 39 Logger.root.level = level; | 36 Logger.root.level = level; |
| 40 return Logger.root.onRecord.listen((LogRecord rec) { | 37 return Logger.root.onRecord.listen((LogRecord rec) { |
| 41 printFn('${rec.level.name.toLowerCase()}: ${rec.message}'); | 38 printFn('${rec.level.name.toLowerCase()}: ${rec.message}'); |
| 42 }); | 39 }); |
| 43 } | 40 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 54 if (options.inputs.length == 0) { | 51 if (options.inputs.length == 0) { |
| 55 print('Expected filename.'); | 52 print('Expected filename.'); |
| 56 return null; | 53 return null; |
| 57 } | 54 } |
| 58 } | 55 } |
| 59 return options; | 56 return options; |
| 60 } | 57 } |
| 61 | 58 |
| 62 /// Compile with the given options and return success or failure. | 59 /// Compile with the given options and return success or failure. |
| 63 bool compile(CompilerOptions options) { | 60 bool compile(CompilerOptions options) { |
| 64 assert(!options.serverMode); | |
| 65 | |
| 66 var context = createAnalysisContextWithSources(options.sourceOptions); | 61 var context = createAnalysisContextWithSources(options.sourceOptions); |
| 67 var reporter = createErrorReporter(context, options); | 62 var reporter = new LogReporter(context, useColors: options.useColors); |
| 68 bool status = new BatchCompiler(context, options, reporter: reporter).run(); | 63 return new BatchCompiler(context, options, reporter: reporter).run(); |
| 69 | |
| 70 if (reporter is HtmlReporter) { | |
| 71 reporter.finish(options); | |
| 72 } else if (reporter is SummaryReporter) { | |
| 73 var result = reporter.result; | |
| 74 print(summaryToString(result)); | |
| 75 } | |
| 76 | |
| 77 return status; | |
| 78 } | 64 } |
| 79 | 65 |
| 80 // Callback on each individual compiled library | 66 // Callback on each individual compiled library |
| 81 typedef void CompilationNotifier(String path); | 67 typedef void CompilationNotifier(String path); |
| 82 | 68 |
| 83 class BatchCompiler extends AbstractCompiler { | 69 class BatchCompiler extends AbstractCompiler { |
| 84 JSGenerator _jsGen; | 70 JSGenerator _jsGen; |
| 85 LibraryElement _dartCore; | 71 LibraryElement _dartCore; |
| 86 String _runtimeOutputDir; | 72 String _runtimeOutputDir; |
| 87 | 73 |
| 88 /// Already compiled sources, so we don't check or compile them again. | 74 /// Already compiled sources, so we don't check or compile them again. |
| 89 final _compilationRecord = <LibraryElement, bool>{}; | 75 final _compilationRecord = <LibraryElement, bool>{}; |
| 90 bool _sdkCopied = false; | 76 bool _sdkCopied = false; |
| 91 | 77 |
| 92 bool _failure = false; | 78 bool _failure = false; |
| 93 bool get failure => _failure; | 79 bool get failure => _failure; |
| 94 | 80 |
| 95 final _pendingLibraries = <LibraryUnit>[]; | 81 final _pendingLibraries = <List<CompilationUnit>>[]; |
| 96 | 82 |
| 97 BatchCompiler(AnalysisContext context, CompilerOptions options, | 83 BatchCompiler(AnalysisContext context, CompilerOptions options, |
| 98 {AnalysisErrorListener reporter, | 84 {AnalysisErrorListener reporter, |
| 99 FileSystem fileSystem: const FileSystem()}) | 85 FileSystem fileSystem: const FileSystem()}) |
| 100 : super( | 86 : super( |
| 101 context, | 87 context, |
| 102 options, | 88 options, |
| 103 new ErrorCollector(reporter ?? AnalysisErrorListener.NULL_LISTENER), | 89 new ErrorCollector(reporter ?? AnalysisErrorListener.NULL_LISTENER), |
| 104 fileSystem) { | 90 fileSystem) { |
| 105 _inputBaseDir = options.inputBaseDir; | 91 _inputBaseDir = options.inputBaseDir; |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 150 reporter.flush(); | 136 reporter.flush(); |
| 151 } | 137 } |
| 152 | 138 |
| 153 void _processPending() { | 139 void _processPending() { |
| 154 // _pendingLibraries was recorded in post-order. Process from the end | 140 // _pendingLibraries was recorded in post-order. Process from the end |
| 155 // to ensure reverse post-order. This will ensure that we handle back | 141 // to ensure reverse post-order. This will ensure that we handle back |
| 156 // edges from the original depth-first search correctly. | 142 // edges from the original depth-first search correctly. |
| 157 | 143 |
| 158 while (_pendingLibraries.isNotEmpty) { | 144 while (_pendingLibraries.isNotEmpty) { |
| 159 var unit = _pendingLibraries.removeLast(); | 145 var unit = _pendingLibraries.removeLast(); |
| 160 var library = unit.library.element.enclosingElement; | 146 var library = unit.first.element.library; |
| 161 assert(_compilationRecord[library] == true || | 147 assert(_compilationRecord[library] == true || |
| 162 options.codegenOptions.forceCompile); | 148 options.codegenOptions.forceCompile); |
| 163 | 149 |
| 164 // Process dependencies one more time to propagate failure from cycles | 150 // Process dependencies one more time to propagate failure from cycles |
| 165 for (var import in library.imports) { | 151 for (var import in library.imports) { |
| 166 if (!_compilationRecord[import.importedLibrary]) { | 152 if (!_compilationRecord[import.importedLibrary]) { |
| 167 _compilationRecord[library] = false; | 153 _compilationRecord[library] = false; |
| 168 } | 154 } |
| 169 } | 155 } |
| 170 for (var export in library.exports) { | 156 for (var export in library.exports) { |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 207 _compilationRecord[library] = false; | 193 _compilationRecord[library] = false; |
| 208 } | 194 } |
| 209 } | 195 } |
| 210 for (var export in library.exports) { | 196 for (var export in library.exports) { |
| 211 if (!_compileLibrary(export.exportedLibrary, notifier)) { | 197 if (!_compileLibrary(export.exportedLibrary, notifier)) { |
| 212 _compilationRecord[library] = false; | 198 _compilationRecord[library] = false; |
| 213 } | 199 } |
| 214 } | 200 } |
| 215 | 201 |
| 216 // Check this library's own code | 202 // Check this library's own code |
| 217 var unitElements = [library.definingCompilationUnit]..addAll(library.parts); | 203 var unitElements = new List.from(library.parts) |
| 204 ..add(library.definingCompilationUnit); |
| 218 var units = <CompilationUnit>[]; | 205 var units = <CompilationUnit>[]; |
| 219 | 206 |
| 220 bool failureInLib = false; | 207 bool failureInLib = false; |
| 221 for (var element in unitElements) { | 208 for (var element in unitElements) { |
| 222 var unit = context.resolveCompilationUnit(element.source, library); | 209 var unit = context.resolveCompilationUnit(element.source, library); |
| 223 units.add(unit); | 210 units.add(unit); |
| 224 failureInLib = computeErrors(element.source) || failureInLib; | 211 failureInLib = computeErrors(element.source) || failureInLib; |
| 225 } | 212 } |
| 226 if (failureInLib) _compilationRecord[library] = false; | 213 if (failureInLib) _compilationRecord[library] = false; |
| 227 | 214 |
| 228 // Notifier framework if requested | 215 // Notifier framework if requested |
| 229 if (notifier != null) { | 216 if (notifier != null) { |
| 230 reporter.flush(); | 217 reporter.flush(); |
| 231 notifier(getOutputPath(library.source.uri)); | 218 notifier(getOutputPath(library.source.uri)); |
| 232 } | 219 } |
| 233 | 220 |
| 234 // Record valid libraries for further dependence checking (cycles) and | 221 // Record valid libraries for further dependence checking (cycles) and |
| 235 // codegen. | 222 // codegen. |
| 236 | 223 |
| 237 // TODO(vsm): Restructure this to not delay code generation more than | 224 // TODO(vsm): Restructure this to not delay code generation more than |
| 238 // necessary. We'd like to process the AST before there is any chance | 225 // necessary. We'd like to process the AST before there is any chance |
| 239 // it's cached out. We should refactor common logic in | 226 // it's cached out. We should refactor common logic in |
| 240 // server/dependency_graph and perhaps the analyzer itself. | 227 // server/dependency_graph and perhaps the analyzer itself. |
| 241 success = _compilationRecord[library]; | 228 success = _compilationRecord[library]; |
| 242 if (success || options.codegenOptions.forceCompile) { | 229 if (success || options.codegenOptions.forceCompile) { |
| 243 var unit = units.first; | 230 _pendingLibraries.add(units); |
| 244 var parts = units.skip(1).toList(); | |
| 245 _pendingLibraries.add(new LibraryUnit(unit, parts)); | |
| 246 } | 231 } |
| 247 | 232 |
| 248 // Return tentative success status. | 233 // Return tentative success status. |
| 249 if (!success) _failure = true; | 234 if (!success) _failure = true; |
| 250 return success; | 235 return success; |
| 251 } | 236 } |
| 252 | 237 |
| 253 void _copyDartRuntime() { | 238 void _copyDartRuntime() { |
| 254 if (_sdkCopied) return; | 239 if (_sdkCopied) return; |
| 255 _sdkCopied = true; | 240 _sdkCopied = true; |
| (...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 472 failure = true; | 457 failure = true; |
| 473 reporter.onError(error); | 458 reporter.onError(error); |
| 474 } else { | 459 } else { |
| 475 // Skip hints for now. | 460 // Skip hints for now. |
| 476 } | 461 } |
| 477 } | 462 } |
| 478 return failure; | 463 return failure; |
| 479 } | 464 } |
| 480 } | 465 } |
| 481 | 466 |
| 482 AnalysisErrorListener createErrorReporter( | |
| 483 AnalysisContext context, CompilerOptions options) { | |
| 484 return options.htmlReport | |
| 485 ? new HtmlReporter(context) | |
| 486 : options.serverMode | |
| 487 ? new SummaryReporter(context, options.logLevel) | |
| 488 : new LogReporter(context, useColors: options.useColors); | |
| 489 } | |
| 490 | |
| 491 // TODO(jmesserly): find a better home for these. | 467 // TODO(jmesserly): find a better home for these. |
| 492 /// Curated order to minimize lazy classes needed by dart:core and its | 468 /// Curated order to minimize lazy classes needed by dart:core and its |
| 493 /// transitive SDK imports. | 469 /// transitive SDK imports. |
| 494 final corelibOrder = [ | 470 final corelibOrder = [ |
| 495 'dart:core', | 471 'dart:core', |
| 496 'dart:collection', | 472 'dart:collection', |
| 497 'dart:_internal', | 473 'dart:_internal', |
| 498 'dart:math', | 474 'dart:math', |
| 499 'dart:_interceptors', | 475 'dart:_interceptors', |
| 500 'dart:async', | 476 'dart:async', |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 535 var files = [ | 511 var files = [ |
| 536 'harmony_feature_check.js', | 512 'harmony_feature_check.js', |
| 537 'dart_library.js', | 513 'dart_library.js', |
| 538 'dart/_runtime.js', | 514 'dart/_runtime.js', |
| 539 ]; | 515 ]; |
| 540 files.addAll(corelibOrder.map(coreToFile)); | 516 files.addAll(corelibOrder.map(coreToFile)); |
| 541 return files; | 517 return files; |
| 542 }(); | 518 }(); |
| 543 | 519 |
| 544 final _log = new Logger('dev_compiler.src.compiler'); | 520 final _log = new Logger('dev_compiler.src.compiler'); |
| OLD | NEW |