Chromium Code Reviews| Index: sdk/lib/_internal/compiler/implementation/compiler.dart |
| diff --git a/sdk/lib/_internal/compiler/implementation/compiler.dart b/sdk/lib/_internal/compiler/implementation/compiler.dart |
| index 646fefecd6b0f666607a99264ee00966b0b53697..59a79ee249a38ea3cb9dcbbda2c043bd31db2113 100644 |
| --- a/sdk/lib/_internal/compiler/implementation/compiler.dart |
| +++ b/sdk/lib/_internal/compiler/implementation/compiler.dart |
| @@ -428,7 +428,7 @@ abstract class Backend { |
| /// This method is called when all new libraries loaded through |
| /// [LibraryLoader.loadLibrary] has been loaded and their imports/exports |
| /// have been computed. |
| - Future onLibrariesLoaded(Map<Uri, LibraryElement> loadedLibraries) { |
| + Future onLibrariesLoaded(LoadedLibraries loadedLibraries) { |
| return new Future.value(); |
| } |
| @@ -903,6 +903,7 @@ abstract class Compiler implements DiagnosticListener { |
| bool enabledFunctionApply = false; |
| bool enabledInvokeOn = false; |
| bool hasIsolateSupport = false; |
| + final bool enableExperimentalMirrors; |
| Stopwatch progress; |
| @@ -949,6 +950,7 @@ abstract class Compiler implements DiagnosticListener { |
| this.useContentSecurityPolicy: false, |
| this.suppressWarnings: false, |
| bool hasIncrementalSupport: false, |
| + this.enableExperimentalMirrors: false, |
| api.CompilerOutputProvider outputProvider, |
| List<String> strips: const []}) |
| : this.disableTypeInferenceFlag = |
| @@ -1192,9 +1194,41 @@ abstract class Compiler implements DiagnosticListener { |
| /// |
| /// The method returns a [Future] allowing for the loading of additional |
| /// libraries. |
| - Future onLibrariesLoaded(Map<Uri, LibraryElement> loadedLibraries) { |
| + Future onLibrariesLoaded(LoadedLibraries loadedLibraries) { |
| return new Future.sync(() { |
| - if (!loadedLibraries.containsKey(DART_CORE)) return new Future.value(); |
| + if (!loadedLibraries.containsLibrary(DART_CORE)) { |
| + return new Future.value(); |
|
floitsch
2014/09/22 20:52:59
return null is the same, since we are already in a
Johnni Winther
2014/11/12 13:06:26
Done.
|
| + } |
| + if (!enableExperimentalMirrors && |
| + loadedLibraries.containsLibrary(DART_MIRRORS)) { |
| + Uri rootUri = loadedLibraries.rootUri; |
| + Set<String> importChains = new Set<String>(); |
| + loadedLibraries.forEachImportChain( |
|
floitsch
2014/09/22 20:52:59
I would make this a function on LoadedLibraries:
Johnni Winther
2014/11/12 13:06:26
Added a TODO. We need to store the libraries for i
|
| + (LibraryElement library, Link<Uri> importChainReversed) { |
| + if (library.canonicalUri != DART_MIRRORS) return; |
| + Link<CodeLocation> compactImportChain = const Link<CodeLocation>(); |
| + CodeLocation currentCodeLocation = new UriLocation(DART_MIRRORS); |
| + compactImportChain = compactImportChain.prepend(currentCodeLocation); |
| + for (Link<Uri> link = importChainReversed; |
| + !link.isEmpty; |
| + link = link.tail) { |
| + Uri uri = link.head; |
| + if (!currentCodeLocation.inSameLocation(uri)) { |
| + currentCodeLocation = |
| + verbose ? new UriLocation(uri) : new CodeLocation(uri); |
| + compactImportChain = |
| + compactImportChain.prepend(currentCodeLocation); |
| + } |
| + } |
| + importChains.add(compactImportChain.map((CodeLocation codeLocation) { |
| + return codeLocation.relativize(rootUri); |
| + }).join(' => ')); |
| + }); |
| + reportWarning(NO_LOCATION_SPANNABLE, |
| + MessageKind.IMPORT_EXPERIMENTAL_MIRRORS, |
| + {'importChain': importChains.join( |
| + MessageKind.IMPORT_EXPERIMENTAL_MIRRORS_PADDING)}); |
| + } |
| functionClass.ensureResolved(this); |
| functionApplyMethod = functionClass.lookupLocalMember('apply'); |
| @@ -1203,8 +1237,8 @@ abstract class Compiler implements DiagnosticListener { |
| resolver.constantCompiler.compileConstant(coreLibrary.find('proxy')); |
| // TODO(johnniwinther): Move this to the JavaScript backend. |
| - LibraryElement jsHelperLibrary = |
| - loadedLibraries[js_backend.JavaScriptBackend.DART_JS_HELPER]; |
| + LibraryElement jsHelperLibrary = loadedLibraries.getLibrary( |
| + js_backend.JavaScriptBackend.DART_JS_HELPER); |
| if (jsHelperLibrary != null) { |
| patchConstant = resolver.constantCompiler.compileConstant( |
| jsHelperLibrary.find('patch')); |
| @@ -1934,40 +1968,29 @@ abstract class Compiler implements DiagnosticListener { |
| /// If [assumeInUserCode] is `true`, [element] is assumed to be in user code |
| /// if no entrypoints have been set. |
| bool inUserCode(Element element, {bool assumeInUserCode: false}) { |
| - List<Uri> entrypoints = <Uri>[]; |
| + if (element == null) return false; |
| + Iterable<CodeLocation> userCodeLocations = |
| + computeUserCodeLocations(assumeInUserCode: assumeInUserCode); |
| + Uri libraryUri = element.library.canonicalUri; |
| + return userCodeLocations.any( |
| + (CodeLocation codeLocation) => codeLocation.inSameLocation(libraryUri)); |
| + } |
| + |
| + Iterable<CodeLocation> computeUserCodeLocations( |
| + {bool assumeInUserCode: false}) { |
| + List<CodeLocation> userCodeLocations = <CodeLocation>[]; |
| if (mainApp != null) { |
| - entrypoints.add(mainApp.canonicalUri); |
| + userCodeLocations.add(new CodeLocation(mainApp.canonicalUri)); |
| } |
| if (librariesToAnalyzeWhenRun != null) { |
| - entrypoints.addAll(librariesToAnalyzeWhenRun); |
| + userCodeLocations.addAll(librariesToAnalyzeWhenRun.map( |
| + (Uri uri) => new CodeLocation(uri))); |
| } |
| - if (entrypoints.isEmpty && assumeInUserCode) { |
| + if (userCodeLocations.isEmpty && assumeInUserCode) { |
| // Assume in user code since [mainApp] has not been set yet. |
| - return true; |
| - } |
| - if (element == null) return false; |
| - Uri libraryUri = element.library.canonicalUri; |
| - if (libraryUri.scheme == 'package') { |
| - for (Uri uri in entrypoints) { |
| - if (uri.scheme != 'package') continue; |
| - int slashPos = libraryUri.path.indexOf('/'); |
| - if (slashPos != -1) { |
| - String packageName = libraryUri.path.substring(0, slashPos + 1); |
| - if (uri.path.startsWith(packageName)) { |
| - return true; |
| - } |
| - } else { |
| - if (libraryUri.path == uri.path) { |
| - return true; |
| - } |
| - } |
| - } |
| - } else { |
| - for (Uri uri in entrypoints) { |
| - if (libraryUri.scheme == uri.scheme) return true; |
| - } |
| + userCodeLocations.add(const AnyLocation()); |
| } |
| - return false; |
| + return userCodeLocations; |
| } |
| /// Return a canonical URI for the source of [element]. |
| @@ -2136,3 +2159,86 @@ class GenericTask extends CompilerTask { |
| GenericTask(this.name, Compiler compiler) |
| : super(compiler); |
| } |
| + |
| +/// [CodeLocation] divides uris into different classes. |
| +/// |
| +/// These are used to group uris from user code, platform libraries and |
| +/// packages. |
| +abstract class CodeLocation { |
| + /// Returns `true` if [uri] is in this code location. |
| + bool inSameLocation(Uri uri); |
| + |
| + /// Returns the uri of this location relative to [baseUri]. |
| + String relativize(Uri baseUri); |
| + |
| + factory CodeLocation(Uri uri) { |
| + if (uri.scheme == 'package') { |
| + int slashPos = uri.path.indexOf('/'); |
| + if (slashPos != -1) { |
| + String packageName = uri.path.substring(0, slashPos); |
| + return new PackageLocation(packageName); |
| + } else { |
| + return new UriLocation(uri); |
| + } |
| + } else { |
| + return new SchemeLocation(uri); |
| + } |
| + } |
| +} |
| + |
| +/// A code location defined by the scheme of the uri. |
| +/// |
| +/// Used for non-package uris, such as 'dart', 'file', and 'http'. |
| +class SchemeLocation implements CodeLocation { |
| + final Uri uri; |
| + |
| + SchemeLocation(this.uri); |
| + |
| + bool inSameLocation(Uri uri) { |
| + return this.uri.scheme == uri.scheme; |
| + } |
| + |
| + String relativize(Uri baseUri) { |
| + return uri_extras.relativize(baseUri, uri, false); |
| + } |
| +} |
| + |
| +/// A code location defined by the package name. |
| +/// |
| +/// Used for package uris, separated by their `package names`, that is, the |
| +/// 'foo' of 'package:foo/bar.dart'. |
| +class PackageLocation implements CodeLocation { |
| + final String packageName; |
| + |
| + PackageLocation(this.packageName); |
| + |
| + bool inSameLocation(Uri uri) { |
| + return uri.scheme == 'package' && uri.path.startsWith('$packageName/'); |
| + } |
| + |
| + String relativize(Uri baseUri) => 'package:$packageName'; |
| +} |
| + |
| +/// A code location defined by the whole uri. |
| +/// |
| +/// Used for package uris with no package name. For instance 'package:foo.dart'. |
| +class UriLocation implements CodeLocation { |
| + final Uri uri; |
| + |
| + UriLocation(this.uri); |
| + |
| + bool inSameLocation(Uri uri) => this.uri == uri; |
| + |
| + String relativize(Uri baseUri) { |
| + return uri_extras.relativize(baseUri, uri, false); |
| + } |
| +} |
| + |
| +/// A code location that contains any uri. |
| +class AnyLocation implements CodeLocation { |
| + const AnyLocation(); |
| + |
| + bool inSameLocation(Uri uri) => true; |
| + |
| + String relativize(Uri baseUri) => '$baseUri'; |
| +} |