Chromium Code Reviews| 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:math' as math; | 10 import 'dart:math' as math; |
| 11 import 'dart:io'; | 11 import 'dart:io'; |
| 12 | 12 |
| 13 import 'package:analyzer/src/generated/ast.dart' show CompilationUnit; | 13 import 'package:analyzer/src/generated/ast.dart' |
| 14 import 'package:analyzer/src/generated/element.dart'; | 14 show CompilationUnit, NamespaceDirective, PartDirective, UriBasedDirective; |
| 15 import 'package:analyzer/src/generated/engine.dart' | 15 import 'package:analyzer/src/generated/engine.dart' |
| 16 show AnalysisEngine, AnalysisContext, ChangeSet, ParseDartTask; | 16 show AnalysisEngine, AnalysisContext, ChangeSet, ParseDartTask; |
| 17 import 'package:analyzer/src/generated/error.dart' | 17 import 'package:analyzer/src/generated/error.dart' |
| 18 show AnalysisError, ErrorSeverity, ErrorType; | 18 show AnalysisError, ErrorSeverity, ErrorType; |
| 19 import 'package:analyzer/src/generated/error.dart'; | 19 import 'package:analyzer/src/generated/error.dart'; |
| 20 import 'package:analyzer/src/generated/resolver.dart' show TypeProvider; | |
| 21 import 'package:analyzer/src/generated/source.dart' show Source; | 20 import 'package:analyzer/src/generated/source.dart' show Source; |
| 22 import 'package:analyzer/src/task/html.dart'; | 21 import 'package:analyzer/src/task/html.dart'; |
| 23 import 'package:html/dom.dart' as html; | 22 import 'package:html/dom.dart' as html; |
| 24 import 'package:html/parser.dart' as html; | 23 import 'package:html/parser.dart' as html; |
| 25 import 'package:logging/logging.dart' show Level, Logger, LogRecord; | 24 import 'package:logging/logging.dart' show Level, Logger, LogRecord; |
| 26 import 'package:path/path.dart' as path; | 25 import 'package:path/path.dart' as path; |
| 27 | 26 |
| 28 import 'package:dev_compiler/strong_mode.dart' show StrongModeOptions; | |
| 29 | |
| 30 import 'analysis_context.dart'; | 27 import 'analysis_context.dart'; |
| 31 import 'checker/checker.dart'; | 28 import 'checker/checker.dart'; |
| 32 import 'checker/rules.dart'; | 29 import 'checker/rules.dart'; |
| 33 import 'codegen/html_codegen.dart' as html_codegen; | 30 import 'codegen/html_codegen.dart' as html_codegen; |
| 34 import 'codegen/js_codegen.dart'; | 31 import 'codegen/js_codegen.dart'; |
| 35 import 'info.dart' | 32 import 'info.dart' |
| 36 show AnalyzerMessage, CheckerResults, LibraryInfo, LibraryUnit; | 33 show AnalyzerMessage, CheckerResults, LibraryInfo, LibraryUnit; |
| 37 import 'options.dart'; | 34 import 'options.dart'; |
| 38 import 'report.dart'; | 35 import 'report.dart'; |
| 39 | 36 |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 66 bool compile(CompilerOptions options) { | 63 bool compile(CompilerOptions options) { |
| 67 assert(!options.serverMode); | 64 assert(!options.serverMode); |
| 68 var context = createAnalysisContextWithSources( | 65 var context = createAnalysisContextWithSources( |
| 69 options.strongOptions, options.sourceOptions); | 66 options.strongOptions, options.sourceOptions); |
| 70 var reporter = createErrorReporter(context, options); | 67 var reporter = createErrorReporter(context, options); |
| 71 return new BatchCompiler(context, options, reporter: reporter).run(); | 68 return new BatchCompiler(context, options, reporter: reporter).run(); |
| 72 } | 69 } |
| 73 | 70 |
| 74 class BatchCompiler extends AbstractCompiler { | 71 class BatchCompiler extends AbstractCompiler { |
| 75 JSGenerator _jsGen; | 72 JSGenerator _jsGen; |
| 76 LibraryElement _dartCore; | 73 Source _dartCore; |
| 77 String _runtimeOutputDir; | 74 String _runtimeOutputDir; |
| 78 | 75 |
| 79 /// Already compiled sources, so we don't compile them again. | 76 /// Already compiled sources, so we don't compile them again. |
| 80 final _compiled = new HashSet<LibraryElement>(); | 77 final _compiled = new HashSet<Uri>(); |
| 81 bool _sdkCopied = false; | 78 bool _sdkCopied = false; |
| 82 | 79 |
| 83 bool _failure = false; | 80 bool _failure = false; |
| 84 bool get failure => _failure; | 81 bool get failure => _failure; |
| 85 | 82 |
| 86 BatchCompiler(AnalysisContext context, CompilerOptions options, | 83 BatchCompiler(AnalysisContext context, CompilerOptions options, |
| 87 {AnalysisErrorListener reporter}) | 84 {AnalysisErrorListener reporter}) |
| 88 : super( | 85 : super( |
| 89 context, | 86 context, |
| 90 options, | 87 options, |
| 91 new ErrorCollector( | 88 new ErrorCollector(context, reporter, options.logLevel, |
| 92 reporter ?? AnalysisErrorListener.NULL_LISTENER)) { | 89 saveMessages: options.saveMessages)) { |
| 93 _inputBaseDir = options.inputBaseDir; | |
| 94 if (outputDir != null) { | 90 if (outputDir != null) { |
| 95 _jsGen = new JSGenerator(this); | |
| 96 _runtimeOutputDir = path.join(outputDir, 'dev_compiler', 'runtime'); | 91 _runtimeOutputDir = path.join(outputDir, 'dev_compiler', 'runtime'); |
| 97 } | 92 } |
| 98 _dartCore = context.typeProvider.objectType.element.library; | 93 _dartCore = context.sourceFactory.forUri('dart:core'); |
| 99 } | 94 } |
| 100 | 95 |
| 101 ErrorCollector get reporter => checker.reporter; | 96 ErrorCollector get reporter => super.reporter; |
| 102 | 97 |
| 103 void reset() { | 98 void reset() { |
| 104 _compiled.clear(); | 99 _compiled.clear(); |
| 105 _sdkCopied = false; | 100 _sdkCopied = false; |
| 106 } | 101 } |
| 107 | 102 |
| 108 /// Compiles every file in [options.inputs]. | 103 /// Compiles every file in [options.inputs]. |
| 109 /// Returns true on successful compile. | 104 /// Returns true on successful compile. |
| 110 bool run() { | 105 bool run() { |
| 111 var clock = new Stopwatch()..start(); | 106 var clock = new Stopwatch()..start(); |
| 112 options.inputs.forEach(compileFromUriString); | 107 options.inputs.forEach(compileFromUriString); |
| 113 clock.stop(); | 108 clock.stop(); |
| 114 var time = (clock.elapsedMilliseconds / 1000).toStringAsFixed(2); | 109 var time = (clock.elapsedMilliseconds / 1000).toStringAsFixed(2); |
| 115 _log.fine('Compiled ${_compiled.length} libraries in ${time} s\n'); | 110 _log.fine('Compiled ${_compiled.length} libraries in ${time} s\n'); |
| 116 | |
| 117 return !_failure; | 111 return !_failure; |
| 118 } | 112 } |
| 119 | 113 |
| 120 void compileFromUriString(String uriString) { | 114 void compileFromUriString(String uriString) { |
| 121 _compileFromUri(stringToUri(uriString)); | 115 _compileFromUri(stringToUri(uriString)); |
| 122 } | 116 } |
| 123 | 117 |
| 124 void _compileFromUri(Uri uri) { | 118 void _compileFromUri(Uri uri) { |
| 125 if (!uri.isAbsolute) { | 119 if (!uri.isAbsolute) { |
| 126 throw new ArgumentError.value('$uri', 'uri', 'must be absolute'); | 120 throw new ArgumentError.value('$uri', 'uri', 'must be absolute'); |
| 127 } | 121 } |
| 128 var source = context.sourceFactory.forUri(Uri.encodeFull('$uri')); | 122 var source = context.sourceFactory.forUri(Uri.encodeFull('$uri')); |
| 129 if (source == null) { | 123 if (source == null) { |
| 130 throw new ArgumentError.value('$uri', 'uri', 'could not find source for'); | 124 throw new ArgumentError.value('$uri', 'uri', 'could not find source for'); |
| 131 } | 125 } |
| 132 compileSource(source); | 126 compileSource(source); |
| 133 } | 127 } |
| 134 | 128 |
| 135 void compileSource(Source source) { | 129 void compileSource(Source source) { |
| 136 if (AnalysisEngine.isHtmlFileName(source.uri.path)) { | 130 if (AnalysisEngine.isHtmlFileName(source.uri.path)) { |
| 137 _compileHtml(source); | 131 _compileHtml(source); |
| 138 } else { | 132 } else { |
| 139 _compileLibrary(context.computeLibraryElement(source)); | 133 _compileLibrary(source); |
| 140 } | |
| 141 reporter.flush(); | |
| 142 } | |
| 143 | |
| 144 void _compileLibrary(LibraryElement library) { | |
| 145 if (!_compiled.add(library)) return; | |
| 146 | |
| 147 if (!options.checkSdk && library.source.uri.scheme == 'dart') { | |
| 148 if (_jsGen != null) _copyDartRuntime(); | |
| 149 return; | |
| 150 } | |
| 151 | |
| 152 // TODO(jmesserly): in incremental mode, we can skip the transitive | |
| 153 // compile of imports/exports. | |
| 154 _compileLibrary(_dartCore); // implicit dart:core dependency | |
| 155 library.importedLibraries.forEach(_compileLibrary); | |
| 156 library.exportedLibraries.forEach(_compileLibrary); | |
| 157 | |
| 158 var unitElements = [library.definingCompilationUnit]..addAll(library.parts); | |
| 159 var units = <CompilationUnit>[]; | |
| 160 | |
| 161 bool failureInLib = false; | |
| 162 for (var element in unitElements) { | |
| 163 var unit = context.resolveCompilationUnit(element.source, library); | |
| 164 units.add(unit); | |
| 165 failureInLib = logErrors(element.source) || failureInLib; | |
| 166 checker.visitCompilationUnit(unit); | |
| 167 if (checker.failure) failureInLib = true; | |
| 168 } | |
| 169 | |
| 170 if (failureInLib) { | |
| 171 _failure = true; | |
| 172 if (!options.codegenOptions.forceCompile) return; | |
| 173 } | |
| 174 | |
| 175 if (_jsGen != null) { | |
| 176 // TODO(jmesserly): full incremental support would avoid checking as well, | |
| 177 // however, we'd lose compiler messages in that case. | |
| 178 | |
| 179 // Note: analyzer's modification stamp is millisecondsSinceEpoch | |
| 180 int lastModifyTime = unitElements | |
| 181 .map((e) => context.getModificationStamp(e.source)) | |
| 182 .reduce(math.max); | |
| 183 var outFile = new File(getOutputPath(library.source.uri)); | |
| 184 if (outFile.existsSync() && | |
| 185 outFile.lastModifiedSync().millisecondsSinceEpoch >= lastModifyTime) { | |
| 186 // Output already up to date. | |
| 187 return; | |
| 188 } | |
| 189 | |
| 190 var unit = units.first; | |
| 191 var parts = units.skip(1).toList(); | |
| 192 _jsGen.generateLibrary(new LibraryUnit(unit, parts)); | |
| 193 } | 134 } |
| 194 } | 135 } |
| 195 | 136 |
| 196 void _copyDartRuntime() { | 137 bool _compileLibrary(Source source) { |
| 197 if (_sdkCopied) return; | 138 if (!_compiled.add(source.uri)) return false; |
|
Leaf
2015/09/04 21:46:31
I'm worried about this doing the right thing in th
| |
| 139 | |
| 140 if (!options.checkSdk && source.uri.scheme == 'dart') { | |
| 141 return outputDir != null && _copyDartRuntime(); | |
| 142 } | |
| 143 | |
| 144 var sources = <Source>[source]; | |
| 145 if (!source.exists()) return false; | |
| 146 | |
| 147 int lastEdit = context.getModificationStamp(source); | |
| 148 | |
| 149 // implicit dart:core dependency | |
| 150 bool changed = _compileLibrary(_dartCore); | |
| 151 | |
| 152 var definingUnit = context.parseCompilationUnit(source); | |
| 153 for (var d in definingUnit.directives) { | |
| 154 if (d is UriBasedDirective) { | |
| 155 var src = context.sourceFactory.resolveUri(source, d.uri.stringValue); | |
| 156 if (src == null) continue; | |
| 157 | |
| 158 if (d is NamespaceDirective) { | |
| 159 if (_compileLibrary(src)) { | |
| 160 changed = true; | |
| 161 } | |
| 162 } else if (d is PartDirective) { | |
| 163 sources.add(src); | |
| 164 lastEdit = math.max(lastEdit, context.getModificationStamp(src)); | |
| 165 } | |
| 166 } | |
| 167 } | |
| 168 | |
| 169 // Take into account if the compiler itself was edited. | |
| 170 if (compilerLastModified != null) { | |
| 171 lastEdit = | |
| 172 math.max(lastEdit, compilerLastModified.millisecondsSinceEpoch); | |
| 173 } | |
| 174 | |
| 175 String messageFilePath; | |
| 176 File outFile; | |
| 177 if (outputDir != null) { | |
| 178 messageFilePath = | |
| 179 path.withoutExtension(getOutputPath(source.uri)) + '.txt'; | |
| 180 outFile = new File(getOutputPath(source.uri)); | |
| 181 } else { | |
| 182 // if no output directory is specified, we're in checker mode, and should | |
| 183 // run the full compilation. | |
| 184 // TODO(jmesserly): deprecate check only mode; this should go through | |
| 185 // analyzer_cli instead. BatchCompiler would be simpler if it was always | |
| 186 // a compiler that produced output. | |
| 187 changed = true; | |
| 188 } | |
| 189 if (!changed) { | |
| 190 var msgFile = new File(messageFilePath); | |
| 191 | |
| 192 if (outFile.existsSync()) { | |
| 193 changed = outFile.lastModifiedSync().millisecondsSinceEpoch < lastEdit; | |
| 194 } else if (msgFile.existsSync()) { | |
| 195 changed = msgFile.lastModifiedSync().millisecondsSinceEpoch < lastEdit; | |
| 196 } else { | |
| 197 // Output files do not exist. | |
| 198 changed = true; | |
| 199 } | |
| 200 // If output is already up to date, we can skip remaining steps. | |
| 201 if (!changed) return false; | |
| 202 } | |
| 203 | |
| 204 var units = <CompilationUnit>[]; | |
| 205 for (var src in sources) { | |
| 206 var unit = context.resolveCompilationUnit2(src, source); | |
| 207 units.add(unit); | |
| 208 if (logErrors(src)) _failure = true; | |
| 209 checker.visitCompilationUnit(unit); | |
| 210 if (checker.failure) _failure = true; | |
| 211 } | |
| 212 | |
| 213 if (outputDir != null) { | |
| 214 if (!_failure || options.codegenOptions.forceCompile) { | |
| 215 if (_jsGen == null) _jsGen = new JSGenerator(this); | |
| 216 var unit = units.first; | |
| 217 var parts = units.skip(1).toList(); | |
| 218 _jsGen.generateLibrary(new LibraryUnit(unit, parts)); | |
| 219 } else { | |
| 220 // Delete stale output. | |
| 221 if (outFile.existsSync()) outFile.deleteSync(); | |
| 222 } | |
| 223 } | |
| 224 | |
| 225 reporter.flush(messageFilePath); | |
| 226 return true; | |
| 227 } | |
| 228 | |
| 229 bool _copyDartRuntime() { | |
| 230 if (_sdkCopied) return false; | |
| 231 if (options.runtimeDir == null) return false; | |
| 232 | |
| 198 _sdkCopied = true; | 233 _sdkCopied = true; |
| 234 | |
| 235 bool changed = false; | |
| 199 for (var file in defaultRuntimeFiles) { | 236 for (var file in defaultRuntimeFiles) { |
| 200 var input = new File(path.join(options.runtimeDir, file)); | 237 var input = new File(path.join(options.runtimeDir, file)); |
| 201 var output = new File(path.join(_runtimeOutputDir, file)); | 238 var output = new File(path.join(_runtimeOutputDir, file)); |
| 202 if (output.existsSync() && | 239 if (output.existsSync() && |
| 203 output.lastModifiedSync() == input.lastModifiedSync()) { | 240 output.lastModifiedSync() == input.lastModifiedSync()) { |
| 204 continue; | 241 continue; |
| 205 } | 242 } |
| 243 | |
| 244 changed = true; | |
| 206 new Directory(path.dirname(output.path)).createSync(recursive: true); | 245 new Directory(path.dirname(output.path)).createSync(recursive: true); |
| 207 input.copySync(output.path); | 246 input.copySync(output.path); |
| 208 } | 247 } |
| 248 return changed; | |
| 209 } | 249 } |
| 210 | 250 |
| 211 void _compileHtml(Source source) { | 251 bool _compileHtml(Source source) { |
| 212 // TODO(jmesserly): reuse DartScriptsTask instead of copy/paste. | 252 // TODO(jmesserly): reuse DartScriptsTask instead of copy/paste. |
| 213 var contents = context.getContents(source); | 253 var contents = context.getContents(source); |
| 214 var document = html.parse(contents.data, generateSpans: true); | 254 var document = html.parse(contents.data, generateSpans: true); |
| 215 var scripts = document.querySelectorAll('script[type="application/dart"]'); | 255 var scripts = document.querySelectorAll('script[type="application/dart"]'); |
| 216 | 256 |
| 217 var loadedLibs = new LinkedHashSet<Uri>(); | 257 var outFile = new File(getOutputPath(source.uri)); |
| 218 | 258 |
| 259 bool changed = !outFile.existsSync() || | |
| 260 context.getModificationStamp(source) > | |
| 261 outFile.lastModifiedSync().millisecondsSinceEpoch; | |
| 262 | |
| 263 var scriptSources = <Source>[]; | |
| 219 var htmlOutDir = path.dirname(getOutputPath(source.uri)); | 264 var htmlOutDir = path.dirname(getOutputPath(source.uri)); |
| 220 for (var script in scripts) { | 265 for (var script in scripts) { |
| 221 Source scriptSource = null; | 266 Source scriptSource = null; |
| 222 var srcAttr = script.attributes['src']; | 267 var srcAttr = script.attributes['src']; |
| 223 if (srcAttr == null) { | 268 if (srcAttr == null) { |
| 224 if (script.hasContent()) { | 269 if (script.hasContent()) { |
| 225 var fragments = <ScriptFragment>[]; | 270 var fragments = <ScriptFragment>[]; |
| 226 for (var node in script.nodes) { | 271 for (var node in script.nodes) { |
| 227 if (node is html.Text) { | 272 if (node is html.Text) { |
| 228 var start = node.sourceSpan.start; | 273 var start = node.sourceSpan.start; |
| 229 fragments.add(new ScriptFragment( | 274 fragments.add(new ScriptFragment( |
| 230 start.offset, start.line, start.column, node.data)); | 275 start.offset, start.line, start.column, node.data)); |
| 231 } | 276 } |
| 232 } | 277 } |
| 233 scriptSource = new DartScript(source, fragments); | 278 scriptSource = new DartScript(source, fragments); |
| 234 } | 279 } |
| 235 } else if (AnalysisEngine.isDartFileName(srcAttr)) { | 280 } else if (AnalysisEngine.isDartFileName(srcAttr)) { |
| 236 scriptSource = context.sourceFactory.resolveUri(source, srcAttr); | 281 scriptSource = context.sourceFactory.resolveUri(source, srcAttr); |
| 237 } | 282 } |
| 283 scriptSources.add(scriptSource); | |
| 238 | 284 |
| 239 if (scriptSource != null) { | 285 if (scriptSource != null && _compileLibrary(scriptSource)) changed = true; |
| 240 var lib = context.computeLibraryElement(scriptSource); | |
| 241 _compileLibrary(lib); | |
| 242 script.replaceWith(_linkLibraries(lib, loadedLibs, from: htmlOutDir)); | |
| 243 } | |
| 244 } | 286 } |
| 245 | 287 |
| 246 new File(getOutputPath(source.uri)).openSync(mode: FileMode.WRITE) | 288 if (!changed) { |
| 289 return false; | |
| 290 } | |
| 291 | |
| 292 var loadedLibs = new LinkedHashSet<Uri>(); | |
| 293 for (int i = 0; i < scripts.length; i++) { | |
| 294 var src = scriptSources[i]; | |
| 295 if (src == null) continue; | |
| 296 scripts[i].replaceWith(_linkLibraries(src, loadedLibs, from: htmlOutDir)); | |
| 297 } | |
| 298 | |
| 299 outFile.openSync(mode: FileMode.WRITE) | |
| 247 ..writeStringSync(document.outerHtml) | 300 ..writeStringSync(document.outerHtml) |
| 248 ..writeStringSync('\n') | 301 ..writeStringSync('\n') |
| 249 ..closeSync(); | 302 ..closeSync(); |
| 303 | |
| 304 reporter.flush(getOutputPath(source.uri) + '.txt'); | |
| 305 return true; | |
| 250 } | 306 } |
| 251 | 307 |
| 252 html.DocumentFragment _linkLibraries( | 308 html.DocumentFragment _linkLibraries( |
| 253 LibraryElement mainLib, LinkedHashSet<Uri> loaded, | 309 Source mainLib, LinkedHashSet<Uri> loaded, |
| 254 {String from}) { | 310 {String from}) { |
| 255 assert(from != null); | 311 assert(from != null); |
| 256 var alreadyLoaded = loaded.length; | 312 var alreadyLoaded = loaded.length; |
| 257 _collectLibraries(mainLib, loaded); | 313 _collectLibraries(mainLib, loaded); |
| 258 | 314 |
| 259 var newLibs = loaded.skip(alreadyLoaded); | 315 var newLibs = loaded.skip(alreadyLoaded); |
| 260 var df = new html.DocumentFragment(); | 316 var df = new html.DocumentFragment(); |
| 261 | 317 |
| 262 for (var uri in newLibs) { | 318 for (var uri in newLibs) { |
| 263 if (uri.scheme == 'dart') { | 319 if (uri.scheme == 'dart') { |
| 264 if (uri.path == 'core') { | 320 if (uri.path == 'core') { |
| 265 // TODO(jmesserly): it would be nice to not special case these. | 321 // TODO(jmesserly): it would be nice to not special case these. |
| 266 for (var file in defaultRuntimeFiles) { | 322 for (var file in defaultRuntimeFiles) { |
| 267 file = path.join(_runtimeOutputDir, file); | 323 file = path.join(_runtimeOutputDir, file); |
| 268 df.append( | 324 df.append( |
| 269 html_codegen.libraryInclude(path.relative(file, from: from))); | 325 html_codegen.libraryInclude(path.relative(file, from: from))); |
| 270 } | 326 } |
| 271 } | 327 } |
| 272 } else { | 328 } else { |
| 273 var file = path.join(outputDir, getModulePath(uri)); | 329 var file = path.join(outputDir, getModulePath(uri)); |
| 274 df.append(html_codegen.libraryInclude(path.relative(file, from: from))); | 330 df.append(html_codegen.libraryInclude(path.relative(file, from: from))); |
| 275 } | 331 } |
| 276 } | 332 } |
| 277 | 333 |
| 278 df.append(html_codegen.invokeMain(getModuleName(mainLib.source.uri))); | 334 df.append(html_codegen.invokeMain(getModuleName(mainLib.source.uri))); |
| 279 return df; | 335 return df; |
| 280 } | 336 } |
| 281 | 337 |
| 282 void _collectLibraries(LibraryElement lib, LinkedHashSet<Uri> loaded) { | 338 void _collectLibraries(Source source, LinkedHashSet<Uri> loaded) { |
| 283 var uri = lib.source.uri; | 339 var uri = source.uri; |
| 284 if (!loaded.add(uri)) return; | 340 if (!loaded.add(uri)) return; |
| 285 _collectLibraries(_dartCore, loaded); | 341 _collectLibraries(_dartCore, loaded); |
| 286 for (var l in lib.importedLibraries) _collectLibraries(l, loaded); | 342 |
| 287 for (var l in lib.exportedLibraries) _collectLibraries(l, loaded); | 343 var definingUnit = context.parseCompilationUnit(source); |
| 344 for (var d in definingUnit.directives) { | |
| 345 if (d is NamespaceDirective) { | |
| 346 var src = context.sourceFactory.resolveUri(source, d.uri.stringValue); | |
| 347 if (src != null) _collectLibraries(src, loaded); | |
| 348 } | |
| 349 } | |
| 350 | |
| 288 // Move the item to the end of the list. | 351 // Move the item to the end of the list. |
| 289 loaded.remove(uri); | 352 loaded.remove(uri); |
| 290 loaded.add(uri); | 353 loaded.add(uri); |
| 291 } | 354 } |
| 292 } | 355 } |
| 293 | 356 |
| 294 abstract class AbstractCompiler { | 357 abstract class AbstractCompiler { |
| 295 final CompilerOptions options; | 358 final CompilerOptions options; |
| 296 final AnalysisContext context; | 359 final AnalysisContext context; |
| 297 final CodeChecker checker; | 360 final AnalysisErrorListener reporter; |
| 361 CodeChecker _checker; | |
| 298 | 362 |
| 299 AbstractCompiler(AnalysisContext context, CompilerOptions options, | 363 AbstractCompiler(this.context, CompilerOptions options, |
| 300 [AnalysisErrorListener reporter]) | 364 [AnalysisErrorListener reporter]) |
| 301 : context = context, | 365 : reporter = reporter ?? AnalysisErrorListener.NULL_LISTENER, |
| 302 options = options, | 366 options = options, |
| 303 checker = createChecker(context.typeProvider, options.strongOptions, | 367 _inputBaseDir = options.inputBaseDir { |
| 304 reporter ?? AnalysisErrorListener.NULL_LISTENER) { | |
| 305 enableDevCompilerInference(context, options.strongOptions); | 368 enableDevCompilerInference(context, options.strongOptions); |
| 306 } | 369 } |
| 307 | 370 |
| 308 static CodeChecker createChecker(TypeProvider typeProvider, | 371 CodeChecker get checker { |
| 309 StrongModeOptions options, AnalysisErrorListener reporter) { | 372 if (_checker == null) { |
| 310 return new CodeChecker( | 373 var opts = options.strongOptions; |
| 311 new RestrictedRules(typeProvider, options: options), reporter, options); | 374 _checker = new CodeChecker( |
| 375 new RestrictedRules(context.typeProvider, options: opts), | |
| 376 reporter, | |
| 377 opts); | |
| 378 } | |
| 379 return _checker; | |
| 312 } | 380 } |
| 313 | 381 |
| 314 String get outputDir => options.codegenOptions.outputDir; | 382 String get outputDir => options.codegenOptions.outputDir; |
| 315 TypeRules get rules => checker.rules; | 383 TypeRules get rules => checker.rules; |
| 316 AnalysisErrorListener get reporter => checker.reporter; | |
| 317 | 384 |
| 318 Uri stringToUri(String uriString) { | 385 Uri stringToUri(String uriString) { |
| 319 var uri = uriString.startsWith('dart:') || uriString.startsWith('package:') | 386 var uri = uriString.startsWith('dart:') || uriString.startsWith('package:') |
| 320 ? Uri.parse(uriString) | 387 ? Uri.parse(uriString) |
| 321 : new Uri.file(path.absolute(uriString)); | 388 : new Uri.file(path.absolute(uriString)); |
| 322 return uri; | 389 return uri; |
| 323 } | 390 } |
| 324 | 391 |
| 325 /// Directory presumed to be the common prefix for all input file:// URIs. | 392 /// Directory presumed to be the common prefix for all input file:// URIs. |
| 326 /// Used when computing output paths. | 393 /// Used when computing output paths. |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 414 failure = true; | 481 failure = true; |
| 415 reporter.onError(error); | 482 reporter.onError(error); |
| 416 } | 483 } |
| 417 } | 484 } |
| 418 return failure; | 485 return failure; |
| 419 } | 486 } |
| 420 } | 487 } |
| 421 | 488 |
| 422 AnalysisErrorListener createErrorReporter( | 489 AnalysisErrorListener createErrorReporter( |
| 423 AnalysisContext context, CompilerOptions options) { | 490 AnalysisContext context, CompilerOptions options) { |
| 424 return options.dumpInfo | 491 if (options.dumpInfo) return new SummaryReporter(context, options.logLevel); |
| 425 ? new SummaryReporter(context, options.logLevel) | 492 return new LogReporter(context); |
| 426 : new LogReporter(context, useColors: options.useColors); | |
| 427 } | 493 } |
| 428 | 494 |
| 429 // TODO(jmesserly): find a better home for these. | 495 // TODO(jmesserly): find a better home for these. |
| 430 /// Curated order to minimize lazy classes needed by dart:core and its | 496 /// Curated order to minimize lazy classes needed by dart:core and its |
| 431 /// transitive SDK imports. | 497 /// transitive SDK imports. |
| 432 const corelibOrder = const [ | 498 const corelibOrder = const [ |
| 433 'dart.core', | 499 'dart.core', |
| 434 'dart.collection', | 500 'dart.collection', |
| 435 'dart._internal', | 501 'dart._internal', |
| 436 'dart.math', | 502 'dart.math', |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 468 '_rtti.js', | 534 '_rtti.js', |
| 469 '_classes.js', | 535 '_classes.js', |
| 470 '_operations.js', | 536 '_operations.js', |
| 471 'dart_runtime.js', | 537 'dart_runtime.js', |
| 472 ]; | 538 ]; |
| 473 files.addAll(corelibOrder.map((l) => l.replaceAll('.', '/') + '.js')); | 539 files.addAll(corelibOrder.map((l) => l.replaceAll('.', '/') + '.js')); |
| 474 return files; | 540 return files; |
| 475 }(); | 541 }(); |
| 476 | 542 |
| 477 final _log = new Logger('dev_compiler.src.compiler'); | 543 final _log = new Logger('dev_compiler.src.compiler'); |
| OLD | NEW |