Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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 import 'dart:async'; | |
| 5 import 'dart:collection' show HashSet, Queue; | 6 import 'dart:collection' show HashSet, Queue; |
| 6 import 'dart:convert' show BASE64, JSON, UTF8; | 7 import 'dart:convert' show JSON; |
| 7 import 'dart:io' show File; | 8 import 'dart:io' show File; |
| 8 | 9 |
| 9 import 'package:analyzer/analyzer.dart' | 10 import 'package:analyzer/analyzer.dart' |
| 10 show AnalysisError, CompilationUnit, ErrorSeverity; | 11 show AnalysisError, CompilationUnit, ErrorSeverity; |
| 12 import 'package:analyzer/context/declared_variables.dart'; | |
| 11 import 'package:analyzer/dart/element/element.dart' show LibraryElement; | 13 import 'package:analyzer/dart/element/element.dart' show LibraryElement; |
| 12 import 'package:analyzer/file_system/file_system.dart' show ResourceProvider; | 14 import 'package:analyzer/file_system/file_system.dart' show ResourceProvider; |
| 13 import 'package:analyzer/file_system/physical_file_system.dart' | 15 import 'package:analyzer/file_system/physical_file_system.dart' |
| 14 show PhysicalResourceProvider; | 16 show PhysicalResourceProvider; |
| 15 import 'package:analyzer/src/context/builder.dart' show ContextBuilder; | 17 import 'package:analyzer/src/context/builder.dart' show ContextBuilder; |
| 16 import 'package:analyzer/src/context/context.dart' show AnalysisContextImpl; | 18 import 'package:analyzer/src/dart/analysis/byte_store.dart'; |
| 19 import 'package:analyzer/src/dart/analysis/driver.dart'; | |
| 20 import 'package:analyzer/src/dart/analysis/file_state.dart'; | |
| 17 import 'package:analyzer/src/error/codes.dart' show StaticTypeWarningCode; | 21 import 'package:analyzer/src/error/codes.dart' show StaticTypeWarningCode; |
| 18 import 'package:analyzer/src/generated/engine.dart' | 22 import 'package:analyzer/src/generated/engine.dart' |
| 19 show AnalysisContext, AnalysisEngine; | 23 show AnalysisContext, AnalysisEngine; |
| 20 import 'package:analyzer/src/generated/sdk.dart' show DartSdkManager; | 24 import 'package:analyzer/src/generated/sdk.dart' show DartSdkManager; |
| 21 import 'package:analyzer/src/generated/source.dart' | 25 import 'package:analyzer/src/generated/source.dart' |
| 22 show ContentCache, DartUriResolver; | 26 show ContentCache, DartUriResolver, LineInfo; |
| 23 import 'package:analyzer/src/generated/source_io.dart' | 27 import 'package:analyzer/src/generated/source_io.dart' |
| 24 show Source, SourceKind, UriResolver; | 28 show Source, SourceKind, UriResolver; |
| 25 import 'package:analyzer/src/summary/package_bundle_reader.dart' | 29 import 'package:analyzer/src/summary/package_bundle_reader.dart' |
| 26 show InSummarySource, InputPackagesResultProvider, SummaryDataStore; | 30 show InSummarySource, SummaryDataStore; |
| 27 import 'package:args/args.dart' show ArgParser, ArgResults; | 31 import 'package:args/args.dart' show ArgParser, ArgResults; |
| 28 import 'package:args/src/usage_exception.dart' show UsageException; | 32 import 'package:args/src/usage_exception.dart' show UsageException; |
| 29 import 'package:func/func.dart' show Func1; | 33 import 'package:func/func.dart' show Func1; |
| 30 import 'package:path/path.dart' as path; | 34 import 'package:path/path.dart' as path; |
| 31 import 'package:source_maps/source_maps.dart'; | 35 import 'package:source_maps/source_maps.dart'; |
| 32 | 36 |
| 33 import '../analyzer/context.dart' show AnalyzerOptions, createSourceFactory; | 37 import '../analyzer/context.dart' show AnalyzerOptions, createSourceFactory; |
| 34 import '../js_ast/js_ast.dart' as JS; | 38 import '../js_ast/js_ast.dart' as JS; |
| 35 import 'code_generator.dart' show CodeGenerator; | 39 import 'code_generator.dart' show CodeGenerator; |
| 36 import 'error_helpers.dart' show errorSeverity, formatError, sortErrors; | 40 import 'error_helpers.dart' show errorSeverity, formatError, sortErrors; |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 50 /// It can be used once to produce a single module, or reused to save warm-up | 54 /// It can be used once to produce a single module, or reused to save warm-up |
| 51 /// time. (Currently there is no warm up, but there may be in the future.) | 55 /// time. (Currently there is no warm up, but there may be in the future.) |
| 52 /// | 56 /// |
| 53 /// The SDK source code is assumed to be immutable for the life of this class. | 57 /// The SDK source code is assumed to be immutable for the life of this class. |
| 54 /// | 58 /// |
| 55 /// For all other files, it is up to the [AnalysisContext] to decide whether or | 59 /// For all other files, it is up to the [AnalysisContext] to decide whether or |
| 56 /// not any caching is performed. By default an analysis context will assume | 60 /// not any caching is performed. By default an analysis context will assume |
| 57 /// sources are immutable for the life of the context, and cache information | 61 /// sources are immutable for the life of the context, and cache information |
| 58 /// about them. | 62 /// about them. |
| 59 class ModuleCompiler { | 63 class ModuleCompiler { |
| 60 final AnalysisContext context; | 64 final AnalysisDriver driver; |
| 61 final SummaryDataStore summaryData; | 65 final SummaryDataStore summaryData; |
| 62 final ExtensionTypeSet _extensionTypes; | 66 ExtensionTypeSet _extensionTypes; |
| 63 | 67 |
| 64 ModuleCompiler._(AnalysisContext context, this.summaryData) | 68 ModuleCompiler._(this.driver, this.summaryData); |
| 65 : context = context, | |
| 66 _extensionTypes = new ExtensionTypeSet(context); | |
| 67 | 69 |
| 68 factory ModuleCompiler(AnalyzerOptions options, | 70 factory ModuleCompiler(AnalyzerOptions options, |
| 69 {ResourceProvider resourceProvider, | 71 {ResourceProvider resourceProvider, |
| 70 String analysisRoot, | 72 String analysisRoot, |
| 71 List<UriResolver> fileResolvers, | 73 List<UriResolver> fileResolvers, |
| 72 SummaryDataStore summaryData}) { | 74 SummaryDataStore summaryData}) { |
| 73 // TODO(danrubel): refactor with analyzer CLI into analyzer common code | 75 // TODO(danrubel): refactor with analyzer CLI into analyzer common code |
| 74 AnalysisEngine.instance.processRequiredPlugins(); | 76 AnalysisEngine.instance.processRequiredPlugins(); |
| 75 | 77 |
| 76 resourceProvider ??= PhysicalResourceProvider.INSTANCE; | 78 resourceProvider ??= PhysicalResourceProvider.INSTANCE; |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 92 if (sdkSummaryBundle != null) { | 94 if (sdkSummaryBundle != null) { |
| 93 summaryData.addBundle(null, sdkSummaryBundle); | 95 summaryData.addBundle(null, sdkSummaryBundle); |
| 94 } | 96 } |
| 95 | 97 |
| 96 var srcFactory = createSourceFactory(options, | 98 var srcFactory = createSourceFactory(options, |
| 97 sdkResolver: sdkResolver, | 99 sdkResolver: sdkResolver, |
| 98 fileResolvers: fileResolvers, | 100 fileResolvers: fileResolvers, |
| 99 summaryData: summaryData, | 101 summaryData: summaryData, |
| 100 resourceProvider: resourceProvider); | 102 resourceProvider: resourceProvider); |
| 101 | 103 |
| 102 var context = | 104 var declaredVariables = new DeclaredVariables(); |
| 103 AnalysisEngine.instance.createAnalysisContext() as AnalysisContextImpl; | 105 options.declaredVariables.forEach(declaredVariables.define); |
| 104 context.analysisOptions = analysisOptions; | 106 declaredVariables.define('dart.isVM', 'false'); |
| 105 context.sourceFactory = srcFactory; | 107 // TODO(vsm): Should this be hardcoded? |
| 106 if (sdkSummaryBundle != null) { | 108 declaredVariables.define('dart.library.html', 'true'); |
| 107 context.resultProvider = | 109 declaredVariables.define('dart.library.io', 'false'); |
| 108 new InputPackagesResultProvider(context, summaryData); | 110 |
| 111 if (!analysisOptions.strongMode) { | |
| 112 throw new ArgumentError('AnalysisOptions must be strong mode'); | |
| 109 } | 113 } |
| 110 options.declaredVariables.forEach(context.declaredVariables.define); | 114 if (!srcFactory.dartSdk.context.analysisOptions.strongMode) { |
| 111 context.declaredVariables.define('dart.isVM', 'false'); | 115 throw new ArgumentError('AnalysisOptions must have strong mode SDK'); |
| 112 | |
| 113 // TODO(vsm): Should this be hardcoded? | |
| 114 context.declaredVariables.define('dart.library.html', 'true'); | |
| 115 context.declaredVariables.define('dart.library.io', 'false'); | |
| 116 | |
| 117 if (!context.analysisOptions.strongMode) { | |
| 118 throw new ArgumentError('AnalysisContext must be strong mode'); | |
| 119 } | |
| 120 if (!context.sourceFactory.dartSdk.context.analysisOptions.strongMode) { | |
| 121 throw new ArgumentError('AnalysisContext must have strong mode SDK'); | |
| 122 } | 116 } |
| 123 | 117 |
| 124 return new ModuleCompiler._(context, summaryData); | 118 AnalysisDriver driver; |
| 119 { | |
|
Jennifer Messerly
2017/03/17 18:33:37
i'm not sure this block is necessary
scheglov
2017/04/25 17:07:35
We defined a couple of variables that are not usef
| |
| 120 var logger = new PerformanceLog(new StringBuffer()); | |
| 121 // var logger = new PerformanceLog(stdout); | |
|
Jennifer Messerly
2017/03/17 18:33:38
remove?
scheglov
2017/04/25 17:07:35
Done.
| |
| 122 var scheduler = new AnalysisDriverScheduler(logger); | |
| 123 driver = new AnalysisDriver( | |
| 124 scheduler, | |
| 125 logger, | |
| 126 resourceProvider, | |
| 127 new MemoryByteStore(), | |
| 128 new FileContentOverlay(), | |
| 129 'DDC', | |
| 130 srcFactory, | |
| 131 analysisOptions, | |
| 132 externalSummaries: summaryData); | |
| 133 scheduler.start(); | |
| 134 } | |
| 135 | |
| 136 return new ModuleCompiler._(driver, summaryData); | |
| 125 } | 137 } |
| 126 | 138 |
| 127 bool _isFatalError(AnalysisError e, CompilerOptions options) { | 139 bool _isFatalError(AnalysisError e, CompilerOptions options) { |
| 128 if (errorSeverity(context, e) != ErrorSeverity.ERROR) return false; | 140 if (errorSeverity(driver.analysisOptions, e) != ErrorSeverity.ERROR) |
| 141 return false; | |
| 129 | 142 |
| 130 // These errors are not fatal in the REPL compile mode as we | 143 // These errors are not fatal in the REPL compile mode as we |
| 131 // allow access to private members across library boundaries | 144 // allow access to private members across library boundaries |
| 132 // and those accesses will show up as undefined members unless | 145 // and those accesses will show up as undefined members unless |
| 133 // additional analyzer changes are made to support them. | 146 // additional analyzer changes are made to support them. |
| 134 // TODO(jacobr): consider checking that the identifier name | 147 // TODO(jacobr): consider checking that the identifier name |
| 135 // referenced by the error is private. | 148 // referenced by the error is private. |
| 136 return !options.replCompile || | 149 return !options.replCompile || |
| 137 (e.errorCode != StaticTypeWarningCode.UNDEFINED_GETTER && | 150 (e.errorCode != StaticTypeWarningCode.UNDEFINED_GETTER && |
| 138 e.errorCode != StaticTypeWarningCode.UNDEFINED_SETTER && | 151 e.errorCode != StaticTypeWarningCode.UNDEFINED_SETTER && |
| 139 e.errorCode != StaticTypeWarningCode.UNDEFINED_METHOD); | 152 e.errorCode != StaticTypeWarningCode.UNDEFINED_METHOD); |
| 140 } | 153 } |
| 141 | 154 |
| 142 /// Compiles a single Dart build unit into a JavaScript module. | 155 /// Compiles a single Dart build unit into a JavaScript module. |
| 143 /// | 156 /// |
| 144 /// *Warning* - this may require resolving the entire world. | 157 /// *Warning* - this may require resolving the entire world. |
| 145 /// If that is not desired, the analysis context must be pre-configured using | 158 /// If that is not desired, the analysis context must be pre-configured using |
| 146 /// summaries before calling this method. | 159 /// summaries before calling this method. |
| 147 JSModuleFile compile(BuildUnit unit, CompilerOptions options) { | 160 Future<JSModuleFile> compile(BuildUnit unit, CompilerOptions options) async { |
| 148 var trees = <CompilationUnit>[]; | 161 var trees = <CompilationUnit>[]; |
| 149 var errors = <AnalysisError>[]; | 162 var errors = <AnalysisError>[]; |
| 163 var lineInfoMap = <String, LineInfo>{}; | |
| 150 | 164 |
| 151 var librariesToCompile = new Queue<LibraryElement>(); | 165 var librariesToCompile = new Queue<LibraryElement>(); |
| 152 | 166 |
| 153 var compilingSdk = false; | 167 var compilingSdk = false; |
| 154 for (var sourcePath in unit.sources) { | 168 for (var sourceUriStr in unit.sources) { |
| 155 var sourceUri = Uri.parse(sourcePath); | 169 var sourceUri = Uri.parse(sourceUriStr); |
| 156 if (sourceUri.scheme == '') { | 170 if (sourceUri.scheme == '') { |
| 157 sourceUri = path.toUri(path.absolute(sourcePath)); | 171 sourceUri = path.toUri(path.absolute(sourceUriStr)); |
| 158 } else if (sourceUri.scheme == 'dart') { | 172 } else if (sourceUri.scheme == 'dart') { |
| 159 compilingSdk = true; | 173 compilingSdk = true; |
| 160 } | 174 } |
| 161 Source source = context.sourceFactory.forUri2(sourceUri); | 175 Source source = driver.sourceFactory.forUri2(sourceUri); |
| 176 String sourcePath = source.fullName; | |
| 162 | 177 |
| 163 var fileUsage = 'You need to pass at least one existing .dart file as an' | 178 var fileUsage = 'You need to pass at least one existing .dart file as an' |
| 164 ' argument.'; | 179 ' argument.'; |
| 165 if (source == null) { | 180 if (source == null) { |
| 166 throw new UsageException( | 181 throw new UsageException( |
| 167 'Could not create a source for "$sourcePath". The file name is in' | 182 'Could not create a source for "$sourceUriStr". The file name is in' |
| 168 ' the wrong format or was not found.', | 183 ' the wrong format or was not found.', |
| 169 fileUsage); | 184 fileUsage); |
| 170 } else if (!source.exists()) { | 185 } else if (!source.exists()) { |
| 171 throw new UsageException( | 186 throw new UsageException( |
| 172 'Given file "$sourcePath" does not exist.', fileUsage); | 187 'Given file "$sourceUriStr" does not exist.', fileUsage); |
| 173 } | 188 } |
| 174 | 189 |
| 175 // Ignore parts. They need to be handled in the context of their library. | 190 // Ignore parts. They need to be handled in the context of their library. |
| 176 if (context.computeKindOf(source) == SourceKind.PART) { | 191 SourceKind sourceKind = await driver.getSourceKind(sourcePath); |
| 192 if (sourceKind == SourceKind.PART) { | |
| 177 continue; | 193 continue; |
| 178 } | 194 } |
| 179 | 195 |
| 180 librariesToCompile.add(context.computeLibraryElement(source)); | 196 UnitElementResult unitResult = await driver.getUnitElement(sourcePath); |
| 197 LibraryElement library = unitResult.element.library; | |
| 198 librariesToCompile.add(library); | |
| 181 } | 199 } |
| 182 | 200 |
| 183 var libraries = new HashSet<LibraryElement>(); | 201 var libraries = new HashSet<LibraryElement>(); |
| 184 while (librariesToCompile.isNotEmpty) { | 202 while (librariesToCompile.isNotEmpty) { |
| 185 var library = librariesToCompile.removeFirst(); | 203 var library = librariesToCompile.removeFirst(); |
| 186 if (library.source is InSummarySource) continue; | 204 if (library.source is InSummarySource) continue; |
| 187 if (!compilingSdk && library.source.isInSystemLibrary) continue; | 205 if (!compilingSdk && library.source.isInSystemLibrary) continue; |
| 188 if (!libraries.add(library)) continue; | 206 if (!libraries.add(library)) continue; |
| 189 | 207 |
| 190 librariesToCompile.addAll(library.importedLibraries); | 208 librariesToCompile.addAll(library.importedLibraries); |
| 191 librariesToCompile.addAll(library.exportedLibraries); | 209 librariesToCompile.addAll(library.exportedLibraries); |
| 192 | 210 |
| 193 var tree = context.resolveCompilationUnit(library.source, library); | 211 var definingResult = await driver.getResult(library.source.fullName); |
| 194 trees.add(tree); | 212 trees.add(definingResult.unit); |
| 195 errors.addAll(context.computeErrors(library.source)); | 213 errors.addAll(definingResult.errors); |
| 214 lineInfoMap[definingResult.path] = definingResult.lineInfo; | |
| 196 | 215 |
| 197 for (var part in library.parts) { | 216 for (var part in library.parts) { |
| 198 trees.add(context.resolveCompilationUnit(part.source, library)); | 217 var partResult = await driver.getResult(part.source.fullName); |
| 199 errors.addAll(context.computeErrors(part.source)); | 218 trees.add(partResult.unit); |
| 219 errors.addAll(partResult.errors); | |
| 220 lineInfoMap[partResult.path] = partResult.lineInfo; | |
| 200 } | 221 } |
| 201 } | 222 } |
| 202 | 223 |
| 203 sortErrors(context, errors); | 224 sortErrors(driver.analysisOptions, errors); |
| 225 | |
| 226 _extensionTypes ??= await ExtensionTypeSet.create(driver); | |
| 204 | 227 |
| 205 var messages = <String>[]; | 228 var messages = <String>[]; |
| 206 for (var e in errors) { | 229 for (AnalysisError e in errors) { |
| 207 var m = formatError(context, e); | 230 var lineInfo = lineInfoMap[e.source.fullName]; |
| 231 var m = formatError(driver.analysisOptions, lineInfo, e); | |
| 208 if (m != null) messages.add(m); | 232 if (m != null) messages.add(m); |
| 209 } | 233 } |
| 210 | 234 |
| 211 if (!options.unsafeForceCompile && | 235 if (!options.unsafeForceCompile && |
| 212 errors.any((e) => _isFatalError(e, options))) { | 236 errors.any((e) => _isFatalError(e, options))) { |
| 213 return new JSModuleFile.invalid(unit.name, messages, options); | 237 return new JSModuleFile.invalid(unit.name, messages, options); |
| 214 } | 238 } |
| 215 var codeGenerator = | 239 var codeGenerator = await CodeGenerator.create( |
|
Jennifer Messerly
2017/03/17 18:33:38
I would rather keep async out of CodeGenerator, an
scheglov
2017/04/25 17:07:35
Done.
| |
| 216 new CodeGenerator(context, summaryData, options, _extensionTypes); | 240 driver, summaryData, options, _extensionTypes); |
| 217 return codeGenerator.compile(unit, trees, messages); | 241 return codeGenerator.compile(unit, trees, messages); |
| 218 } | 242 } |
| 219 } | 243 } |
| 220 | 244 |
| 221 class CompilerOptions { | 245 class CompilerOptions { |
| 222 /// Whether to emit the source mapping file. | 246 /// Whether to emit the source mapping file. |
| 223 /// | 247 /// |
| 224 /// This supports debugging the original source code instead of the generated | 248 /// This supports debugging the original source code instead of the generated |
| 225 /// code. | 249 /// code. |
| 226 final bool sourceMap; | 250 final bool sourceMap; |
| (...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 599 /// are implementation details that would just confuse users. | 623 /// are implementation details that would just confuse users. |
| 600 /// Normalize sdk urls to use "dart:" for more understandable stack traces. | 624 /// Normalize sdk urls to use "dart:" for more understandable stack traces. |
| 601 Map cleanupSdkSourcemap(Map sourceMap) { | 625 Map cleanupSdkSourcemap(Map sourceMap) { |
| 602 var map = new Map.from(sourceMap); | 626 var map = new Map.from(sourceMap); |
| 603 var list = new List.from(map['sources']); | 627 var list = new List.from(map['sources']); |
| 604 map['sources'] = map['sources'] | 628 map['sources'] = map['sources'] |
| 605 .map((url) => url.contains('/_internal/') ? null : url) | 629 .map((url) => url.contains('/_internal/') ? null : url) |
| 606 .toList(); | 630 .toList(); |
| 607 return map; | 631 return map; |
| 608 } | 632 } |
| OLD | NEW |