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 |