| 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 JSON; | 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/driver.dart'; |
| 19 import 'package:analyzer/src/dart/analysis/file_state.dart'; |
| 17 import 'package:analyzer/src/error/codes.dart' show StaticTypeWarningCode; | 20 import 'package:analyzer/src/error/codes.dart' show StaticTypeWarningCode; |
| 18 import 'package:analyzer/src/generated/engine.dart' | 21 import 'package:analyzer/src/generated/engine.dart' show AnalysisEngine; |
| 19 show AnalysisContext, AnalysisEngine; | 22 import 'package:analyzer/src/generated/resolver.dart'; |
| 20 import 'package:analyzer/src/generated/sdk.dart' show DartSdkManager; | 23 import 'package:analyzer/src/generated/sdk.dart' show DartSdkManager; |
| 21 import 'package:analyzer/src/generated/source.dart' | 24 import 'package:analyzer/src/generated/source.dart' |
| 22 show ContentCache, DartUriResolver; | 25 show ContentCache, DartUriResolver, LineInfo; |
| 23 import 'package:analyzer/src/generated/source_io.dart' | 26 import 'package:analyzer/src/generated/source_io.dart' |
| 24 show Source, SourceKind, UriResolver; | 27 show Source, SourceKind, UriResolver; |
| 25 import 'package:analyzer/src/summary/package_bundle_reader.dart' | 28 import 'package:analyzer/src/summary/package_bundle_reader.dart' |
| 26 show InSummarySource, InputPackagesResultProvider, SummaryDataStore; | 29 show InSummarySource, SummaryDataStore; |
| 27 import 'package:args/args.dart' show ArgParser, ArgResults; | 30 import 'package:args/args.dart' show ArgParser, ArgResults; |
| 28 import 'package:args/src/usage_exception.dart' show UsageException; | 31 import 'package:args/src/usage_exception.dart' show UsageException; |
| 32 import 'package:front_end/src/base/performace_logger.dart'; |
| 33 import 'package:front_end/src/incremental/byte_store.dart'; |
| 29 import 'package:func/func.dart' show Func1; | 34 import 'package:func/func.dart' show Func1; |
| 30 import 'package:path/path.dart' as path; | 35 import 'package:path/path.dart' as path; |
| 31 import 'package:source_maps/source_maps.dart'; | 36 import 'package:source_maps/source_maps.dart'; |
| 32 | 37 |
| 33 import '../analyzer/context.dart' show AnalyzerOptions, createSourceFactory; | 38 import '../analyzer/context.dart' show AnalyzerOptions, createSourceFactory; |
| 34 import '../js_ast/js_ast.dart' as JS; | 39 import '../js_ast/js_ast.dart' as JS; |
| 35 import '../js_ast/js_ast.dart' show js; | 40 import '../js_ast/js_ast.dart' show js; |
| 36 import 'code_generator.dart' show CodeGenerator; | 41 import 'code_generator.dart' show CodeGenerator; |
| 37 import 'error_helpers.dart' show errorSeverity, formatError, sortErrors; | 42 import 'error_helpers.dart' show errorSeverity, formatError, sortErrors; |
| 38 import 'extension_types.dart' show ExtensionTypeSet; | 43 import 'extension_types.dart' show ExtensionTypeSet; |
| 39 import 'js_names.dart' as JS; | 44 import 'js_names.dart' as JS; |
| 40 import 'module_builder.dart' show transformModuleFormat, ModuleFormat; | 45 import 'module_builder.dart' show transformModuleFormat, ModuleFormat; |
| 41 import 'source_map_printer.dart' show SourceMapPrintingContext; | 46 import 'source_map_printer.dart' show SourceMapPrintingContext; |
| 42 | 47 |
| 43 /// Compiles a set of Dart files into a single JavaScript module. | 48 /// Compiles a set of Dart files into a single JavaScript module. |
| 44 /// | 49 /// |
| 45 /// For a single [BuildUnit] definition, this will produce a [JSModuleFile]. | 50 /// For a single [BuildUnit] definition, this will produce a [JSModuleFile]. |
| 46 /// Those objects are record types that record the data consumed and produced | 51 /// Those objects are record types that record the data consumed and produced |
| 47 /// for a single compile. | 52 /// for a single compile. |
| 48 /// | 53 /// |
| 49 /// This class exists to cache global state associated with a single in-memory | 54 /// This class exists to cache global state associated with a single in-memory |
| 50 /// AnalysisContext, such as information about extension types in the Dart SDK. | 55 /// [AnalysisDriver], such as information about extension types in the Dart SDK. |
| 51 /// It can be used once to produce a single module, or reused to save warm-up | 56 /// It can be used once to produce a single module, or reused to save warm-up |
| 52 /// time. (Currently there is no warm up, but there may be in the future.) | 57 /// time. (Currently there is no warm up, but there may be in the future.) |
| 53 /// | 58 /// |
| 54 /// The SDK source code is assumed to be immutable for the life of this class. | 59 /// The SDK source code is assumed to be immutable for the life of this class. |
| 55 /// | 60 /// |
| 56 /// For all other files, it is up to the [AnalysisContext] to decide whether or | 61 /// For all other files, it is up to the [AnalysisDriver] to decide whether or |
| 57 /// not any caching is performed. By default an analysis context will assume | 62 /// not any caching is performed. By default an analysis context will assume |
| 58 /// sources are immutable for the life of the context, and cache information | 63 /// sources are immutable for the life of the context, and cache information |
| 59 /// about them. | 64 /// about them. |
| 60 class ModuleCompiler { | 65 class ModuleCompiler { |
| 61 final AnalysisContext context; | 66 final AnalysisDriver driver; |
| 62 final SummaryDataStore summaryData; | 67 final SummaryDataStore summaryData; |
| 63 final ExtensionTypeSet _extensionTypes; | |
| 64 | 68 |
| 65 ModuleCompiler._(AnalysisContext context, this.summaryData) | 69 final Map<String, LibraryElement> _dartLibraries = {}; |
| 66 : context = context, | 70 TypeProviderImpl _typeProvider; |
| 67 _extensionTypes = new ExtensionTypeSet(context); | 71 |
| 72 ExtensionTypeSet _extensionTypes; |
| 73 |
| 74 ModuleCompiler._(this.driver, this.summaryData); |
| 68 | 75 |
| 69 factory ModuleCompiler(AnalyzerOptions options, | 76 factory ModuleCompiler(AnalyzerOptions options, |
| 70 {ResourceProvider resourceProvider, | 77 {ResourceProvider resourceProvider, |
| 71 String analysisRoot, | 78 String analysisRoot, |
| 72 List<UriResolver> fileResolvers, | 79 List<UriResolver> fileResolvers, |
| 73 SummaryDataStore summaryData}) { | 80 SummaryDataStore summaryData}) { |
| 74 // TODO(danrubel): refactor with analyzer CLI into analyzer common code | 81 // TODO(danrubel): refactor with analyzer CLI into analyzer common code |
| 75 AnalysisEngine.instance.processRequiredPlugins(); | 82 AnalysisEngine.instance.processRequiredPlugins(); |
| 76 | 83 |
| 77 resourceProvider ??= PhysicalResourceProvider.INSTANCE; | 84 resourceProvider ??= PhysicalResourceProvider.INSTANCE; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 97 if (sdkSummaryBundle != null) { | 104 if (sdkSummaryBundle != null) { |
| 98 summaryData.addBundle(null, sdkSummaryBundle); | 105 summaryData.addBundle(null, sdkSummaryBundle); |
| 99 } | 106 } |
| 100 | 107 |
| 101 var srcFactory = createSourceFactory(options, | 108 var srcFactory = createSourceFactory(options, |
| 102 sdkResolver: sdkResolver, | 109 sdkResolver: sdkResolver, |
| 103 fileResolvers: fileResolvers, | 110 fileResolvers: fileResolvers, |
| 104 summaryData: summaryData, | 111 summaryData: summaryData, |
| 105 resourceProvider: resourceProvider); | 112 resourceProvider: resourceProvider); |
| 106 | 113 |
| 107 var context = | 114 var declaredVariables = new DeclaredVariables(); |
| 108 AnalysisEngine.instance.createAnalysisContext() as AnalysisContextImpl; | 115 options.declaredVariables.forEach(declaredVariables.define); |
| 109 context.analysisOptions = analysisOptions; | 116 declaredVariables.define('dart.isVM', 'false'); |
| 110 context.sourceFactory = srcFactory; | 117 // TODO(vsm): Should this be hardcoded? |
| 111 if (sdkSummaryBundle != null) { | 118 declaredVariables.define('dart.library.html', 'true'); |
| 112 context.resultProvider = | 119 declaredVariables.define('dart.library.io', 'false'); |
| 113 new InputPackagesResultProvider(context, summaryData); | 120 |
| 121 if (!analysisOptions.strongMode) { |
| 122 throw new ArgumentError('AnalysisOptions must be strong mode'); |
| 114 } | 123 } |
| 115 options.declaredVariables.forEach(context.declaredVariables.define); | 124 if (!srcFactory.dartSdk.context.analysisOptions.strongMode) { |
| 116 context.declaredVariables.define('dart.isVM', 'false'); | 125 throw new ArgumentError('AnalysisOptions must have strong mode SDK'); |
| 117 | |
| 118 // TODO(vsm): Should this be hardcoded? | |
| 119 context.declaredVariables.define('dart.library.html', 'true'); | |
| 120 context.declaredVariables.define('dart.library.io', 'false'); | |
| 121 | |
| 122 if (!context.analysisOptions.strongMode) { | |
| 123 throw new ArgumentError('AnalysisContext must be strong mode'); | |
| 124 } | |
| 125 if (!context.sourceFactory.dartSdk.context.analysisOptions.strongMode) { | |
| 126 throw new ArgumentError('AnalysisContext must have strong mode SDK'); | |
| 127 } | 126 } |
| 128 | 127 |
| 129 return new ModuleCompiler._(context, summaryData); | 128 AnalysisDriver driver; |
| 129 { |
| 130 var logger = new PerformanceLog(new StringBuffer()); |
| 131 var scheduler = new AnalysisDriverScheduler(logger); |
| 132 driver = new AnalysisDriver( |
| 133 scheduler, |
| 134 logger, |
| 135 resourceProvider, |
| 136 new MemoryByteStore(), |
| 137 new FileContentOverlay(), |
| 138 null, |
| 139 srcFactory, |
| 140 analysisOptions, |
| 141 disableChangesAndCacheAllResults: true, |
| 142 externalSummaries: summaryData); |
| 143 scheduler.start(); |
| 144 } |
| 145 |
| 146 return new ModuleCompiler._(driver, summaryData); |
| 130 } | 147 } |
| 131 | 148 |
| 132 bool _isFatalError(AnalysisError e, CompilerOptions options) { | 149 bool _isFatalError(AnalysisError e, CompilerOptions options) { |
| 133 if (errorSeverity(context, e) != ErrorSeverity.ERROR) return false; | 150 if (errorSeverity(driver.analysisOptions, e) != ErrorSeverity.ERROR) |
| 151 return false; |
| 134 | 152 |
| 135 // These errors are not fatal in the REPL compile mode as we | 153 // These errors are not fatal in the REPL compile mode as we |
| 136 // allow access to private members across library boundaries | 154 // allow access to private members across library boundaries |
| 137 // and those accesses will show up as undefined members unless | 155 // and those accesses will show up as undefined members unless |
| 138 // additional analyzer changes are made to support them. | 156 // additional analyzer changes are made to support them. |
| 139 // TODO(jacobr): consider checking that the identifier name | 157 // TODO(jacobr): consider checking that the identifier name |
| 140 // referenced by the error is private. | 158 // referenced by the error is private. |
| 141 return !options.replCompile || | 159 return !options.replCompile || |
| 142 (e.errorCode != StaticTypeWarningCode.UNDEFINED_GETTER && | 160 (e.errorCode != StaticTypeWarningCode.UNDEFINED_GETTER && |
| 143 e.errorCode != StaticTypeWarningCode.UNDEFINED_SETTER && | 161 e.errorCode != StaticTypeWarningCode.UNDEFINED_SETTER && |
| 144 e.errorCode != StaticTypeWarningCode.UNDEFINED_METHOD); | 162 e.errorCode != StaticTypeWarningCode.UNDEFINED_METHOD); |
| 145 } | 163 } |
| 146 | 164 |
| 147 /// Compiles a single Dart build unit into a JavaScript module. | 165 /// Compiles a single Dart build unit into a JavaScript module. |
| 148 /// | 166 /// |
| 149 /// *Warning* - this may require resolving the entire world. | 167 /// *Warning* - this may require resolving the entire world. |
| 150 /// If that is not desired, the analysis context must be pre-configured using | 168 /// If that is not desired, the analysis context must be pre-configured using |
| 151 /// summaries before calling this method. | 169 /// summaries before calling this method. |
| 152 JSModuleFile compile(BuildUnit unit, CompilerOptions options) { | 170 Future<JSModuleFile> compile(BuildUnit unit, CompilerOptions options) async { |
| 153 var trees = <CompilationUnit>[]; | 171 var trees = <CompilationUnit>[]; |
| 154 var errors = <AnalysisError>[]; | 172 var errors = <AnalysisError>[]; |
| 173 var lineInfoMap = <String, LineInfo>{}; |
| 155 | 174 |
| 156 var librariesToCompile = new Queue<LibraryElement>(); | 175 var librariesToCompile = new Queue<LibraryElement>(); |
| 157 | 176 |
| 158 var compilingSdk = false; | 177 var compilingSdk = false; |
| 159 for (var sourcePath in unit.sources) { | 178 for (var sourceUriStr in unit.sources) { |
| 160 var sourceUri = _sourceToUri(sourcePath); | 179 var sourceUri = _sourceToUri(sourceUriStr); |
| 161 if (sourceUri.scheme == "dart") { | 180 if (sourceUri.scheme == "dart") { |
| 162 compilingSdk = true; | 181 compilingSdk = true; |
| 163 } | 182 } |
| 164 var source = context.sourceFactory.forUri2(sourceUri); | 183 var source = driver.sourceFactory.forUri2(sourceUri); |
| 184 String sourcePath = source.fullName; |
| 165 | 185 |
| 166 var fileUsage = 'You need to pass at least one existing .dart file as an' | 186 var fileUsage = 'You need to pass at least one existing .dart file as an' |
| 167 ' argument.'; | 187 ' argument.'; |
| 168 if (source == null) { | 188 if (source == null) { |
| 169 throw new UsageException( | 189 throw new UsageException( |
| 170 'Could not create a source for "$sourcePath". The file name is in' | 190 'Could not create a source for "$sourceUriStr". The file name is in' |
| 171 ' the wrong format or was not found.', | 191 ' the wrong format or was not found.', |
| 172 fileUsage); | 192 fileUsage); |
| 173 } else if (!source.exists()) { | 193 } else if (!source.exists()) { |
| 174 throw new UsageException( | 194 throw new UsageException( |
| 175 'Given file "$sourcePath" does not exist.', fileUsage); | 195 'Given file "$sourceUriStr" does not exist.', fileUsage); |
| 176 } | 196 } |
| 177 | 197 |
| 178 // Ignore parts. They need to be handled in the context of their library. | 198 // Ignore parts. They need to be handled in the context of their library. |
| 179 if (context.computeKindOf(source) == SourceKind.PART) { | 199 SourceKind sourceKind = await driver.getSourceKind(sourcePath); |
| 200 if (sourceKind == SourceKind.PART) { |
| 180 continue; | 201 continue; |
| 181 } | 202 } |
| 182 | 203 |
| 183 librariesToCompile.add(context.computeLibraryElement(source)); | 204 UnitElementResult unitResult = await driver.getUnitElement(sourcePath); |
| 205 LibraryElement library = unitResult.element.library; |
| 206 librariesToCompile.add(library); |
| 184 } | 207 } |
| 185 | 208 |
| 186 var libraries = new HashSet<LibraryElement>(); | 209 var libraries = new HashSet<LibraryElement>(); |
| 187 while (librariesToCompile.isNotEmpty) { | 210 while (librariesToCompile.isNotEmpty) { |
| 188 var library = librariesToCompile.removeFirst(); | 211 var library = librariesToCompile.removeFirst(); |
| 189 if (library.source is InSummarySource) continue; | 212 if (library.source is InSummarySource) continue; |
| 190 if (!compilingSdk && library.source.isInSystemLibrary) continue; | 213 if (!compilingSdk && library.source.isInSystemLibrary) continue; |
| 191 if (!libraries.add(library)) continue; | 214 if (!libraries.add(library)) continue; |
| 192 | 215 |
| 193 librariesToCompile.addAll(library.importedLibraries); | 216 librariesToCompile.addAll(library.importedLibraries); |
| 194 librariesToCompile.addAll(library.exportedLibraries); | 217 librariesToCompile.addAll(library.exportedLibraries); |
| 195 | 218 |
| 196 var tree = context.resolveCompilationUnit(library.source, library); | 219 var definingResult = await driver.getResult(library.source.fullName); |
| 197 trees.add(tree); | 220 trees.add(definingResult.unit); |
| 198 errors.addAll(context.computeErrors(library.source)); | 221 errors.addAll(definingResult.errors); |
| 222 lineInfoMap[definingResult.path] = definingResult.lineInfo; |
| 199 | 223 |
| 200 for (var part in library.parts) { | 224 for (var part in library.parts) { |
| 201 trees.add(context.resolveCompilationUnit(part.source, library)); | 225 var partResult = await driver.getResult(part.source.fullName); |
| 202 errors.addAll(context.computeErrors(part.source)); | 226 trees.add(partResult.unit); |
| 227 errors.addAll(partResult.errors); |
| 228 lineInfoMap[partResult.path] = partResult.lineInfo; |
| 203 } | 229 } |
| 204 } | 230 } |
| 205 | 231 |
| 206 sortErrors(context, errors); | 232 sortErrors(driver.analysisOptions, errors); |
| 233 |
| 234 LibraryElement coreLibrary = await _getDartLibrary('dart:core'); |
| 235 LibraryElement asyncLibrary = await _getDartLibrary('dart:async'); |
| 236 _typeProvider ??= new TypeProviderImpl(coreLibrary, asyncLibrary); |
| 237 _extensionTypes ??= await _newExtensionTypeSet(); |
| 207 | 238 |
| 208 var messages = <String>[]; | 239 var messages = <String>[]; |
| 209 for (var e in errors) { | 240 for (AnalysisError e in errors) { |
| 210 var m = formatError(context, e); | 241 var lineInfo = lineInfoMap[e.source.fullName]; |
| 242 var m = formatError(driver.analysisOptions, lineInfo, e); |
| 211 if (m != null) messages.add(m); | 243 if (m != null) messages.add(m); |
| 212 } | 244 } |
| 213 | 245 |
| 214 if (!options.unsafeForceCompile && | 246 if (!options.unsafeForceCompile && |
| 215 errors.any((e) => _isFatalError(e, options))) { | 247 errors.any((e) => _isFatalError(e, options))) { |
| 216 return new JSModuleFile.invalid(unit.name, messages, options); | 248 return new JSModuleFile.invalid(unit.name, messages, options); |
| 217 } | 249 } |
| 218 | 250 |
| 219 try { | 251 try { |
| 220 var codeGenerator = | 252 var codeGenerator = new CodeGenerator( |
| 221 new CodeGenerator(context, summaryData, options, _extensionTypes); | 253 driver, summaryData, options, _extensionTypes, |
| 254 types: _typeProvider, |
| 255 coreLibrary: coreLibrary, |
| 256 asyncLibrary: asyncLibrary, |
| 257 interceptorsLibrary: await _getDartLibrary('dart:_interceptors'), |
| 258 internalLibrary: await _getDartLibrary('dart:_internal'), |
| 259 jsLibrary: await _getDartLibrary('dart:js')); |
| 222 return codeGenerator.compile(unit, trees, messages); | 260 return codeGenerator.compile(unit, trees, messages); |
| 223 } catch (e) { | 261 } catch (e) { |
| 224 if (errors.any((e) => _isFatalError(e, options))) { | 262 if (errors.any((e) => _isFatalError(e, options))) { |
| 225 // Force compilation failed. Suppress the exception and report | 263 // Force compilation failed. Suppress the exception and report |
| 226 // the static errors instead. | 264 // the static errors instead. |
| 227 assert(options.unsafeForceCompile); | 265 assert(options.unsafeForceCompile); |
| 228 return new JSModuleFile.invalid(unit.name, messages, options); | 266 return new JSModuleFile.invalid(unit.name, messages, options); |
| 229 } | 267 } |
| 230 rethrow; | 268 rethrow; |
| 231 } | 269 } |
| 232 } | 270 } |
| 271 |
| 272 Future<LibraryElement> _getDartLibrary(String uri) async { |
| 273 assert(uri.startsWith('dart:')); |
| 274 LibraryElement library = _dartLibraries[uri]; |
| 275 if (library == null) { |
| 276 library = await driver.getLibraryByUri(uri); |
| 277 _dartLibraries[uri] = library; |
| 278 } |
| 279 return library; |
| 280 } |
| 281 |
| 282 Future<ExtensionTypeSet> _newExtensionTypeSet() async { |
| 283 return new ExtensionTypeSet( |
| 284 coreLibrary: await _getDartLibrary('dart:core'), |
| 285 collectionLibrary: await _getDartLibrary('dart:collection'), |
| 286 mathLibrary: await _getDartLibrary('dart:math'), |
| 287 htmlLibrary: await _getDartLibrary('dart:html'), |
| 288 indexedDbLibrary: await _getDartLibrary('dart:indexed_db'), |
| 289 svgLibrary: await _getDartLibrary('dart:svg'), |
| 290 webAudioLibrary: await _getDartLibrary('dart:web_audio'), |
| 291 webGlLibrary: await _getDartLibrary('dart:web_gl'), |
| 292 webSqlLibrary: await _getDartLibrary('dart:web_sql'), |
| 293 interceptorsLibrary: await _getDartLibrary('dart:_interceptors'), |
| 294 nativeTypedDataLibrary: |
| 295 await _getDartLibrary('dart:_native_typed_data')); |
| 296 } |
| 233 } | 297 } |
| 234 | 298 |
| 235 class CompilerOptions { | 299 class CompilerOptions { |
| 236 /// Whether to emit the source mapping file. | 300 /// Whether to emit the source mapping file. |
| 237 /// | 301 /// |
| 238 /// This supports debugging the original source code instead of the generated | 302 /// This supports debugging the original source code instead of the generated |
| 239 /// code. | 303 /// code. |
| 240 final bool sourceMap; | 304 final bool sourceMap; |
| 241 | 305 |
| 242 /// If [sourceMap] is emitted, this will emit a `sourceMappingUrl` comment | 306 /// If [sourceMap] is emitted, this will emit a `sourceMappingUrl` comment |
| (...skipping 384 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 627 case "dart": | 691 case "dart": |
| 628 case "package": | 692 case "package": |
| 629 case "file": | 693 case "file": |
| 630 // A valid URI. | 694 // A valid URI. |
| 631 return uri; | 695 return uri; |
| 632 default: | 696 default: |
| 633 // Assume a file path. | 697 // Assume a file path. |
| 634 return new Uri.file(path.absolute(source)); | 698 return new Uri.file(path.absolute(source)); |
| 635 } | 699 } |
| 636 } | 700 } |
| OLD | NEW |