Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(108)

Unified Diff: pkg/compiler/lib/src/compiler.dart

Issue 588183002: Emit warning on import of dart:mirrors. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Optimize and limit import chain processing Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: pkg/compiler/lib/src/compiler.dart
diff --git a/pkg/compiler/lib/src/compiler.dart b/pkg/compiler/lib/src/compiler.dart
index c60a44cc268c589ed69d451c89caa30e17a00e85..772b03670a533030e497c0bfdd9071a475287ee0 100644
--- a/pkg/compiler/lib/src/compiler.dart
+++ b/pkg/compiler/lib/src/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();
}
@@ -921,6 +921,7 @@ abstract class Compiler implements DiagnosticListener {
bool enabledFunctionApply = false;
bool enabledInvokeOn = false;
bool hasIsolateSupport = false;
+ final bool enableExperimentalMirrors;
Stopwatch progress;
@@ -969,6 +970,7 @@ abstract class Compiler implements DiagnosticListener {
this.useContentSecurityPolicy: false,
this.suppressWarnings: false,
bool hasIncrementalSupport: false,
+ this.enableExperimentalMirrors: false,
this.enableAsyncAwait: false,
this.enableEnums: false,
api.CompilerOutputProvider outputProvider,
@@ -1223,9 +1225,67 @@ 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 null;
+ }
+ if (!enableExperimentalMirrors &&
+ loadedLibraries.containsLibrary(DART_MIRRORS)) {
+ // TODO(johnniwinther): Move computation of dependencies to the library
+ // loader.
+ Uri rootUri = loadedLibraries.rootUri;
+ Set<String> importChains = new Set<String>();
+ // The maximum number of full imports chains to process.
+ final int chainLimit = 10000;
+ // The maximum number of imports chains to show.
+ final int compactChainLimit = verbose ? 20 : 10;
+ int chainCount = 0;
+ bool limitExceeded = false;
+ loadedLibraries.forEachImportChain(DART_MIRRORS,
+ callback:(Link<Uri> importChainReversed) {
floitsch 2014/11/18 15:50:01 space after ':'.
Johnni Winther 2014/11/19 08:52:19 Done.
+ Link<CodeLocation> compactImportChain = const Link<CodeLocation>();
+ CodeLocation currentCodeLocation =
+ new UriLocation(importChainReversed.head);
+ compactImportChain = compactImportChain.prepend(currentCodeLocation);
+ for (Link<Uri> link = importChainReversed.tail;
+ !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);
+ }
+ }
+ String importChain =
+ compactImportChain.map((CodeLocation codeLocation) {
+ return codeLocation.relativize(rootUri);
floitsch 2014/11/18 15:50:01 This indentation just doesn't work for me... (even
Johnni Winther 2014/11/19 08:52:19 Done. Didn't like it either.
+ }).join(' => ');
+
+ if (!importChains.contains(importChain)) {
+ if (importChains.length > compactChainLimit) {
+ importChains.add('...');
+ return false;
+ } else {
+ importChains.add(importChain);
+ }
+ }
+
+ chainCount++;
+ if (chainCount > chainLimit) {
+ // Assume there are more import chains.
+ importChains.add('...');
+ return false;
+ }
+ return true;
+ });
+ reportWarning(NO_LOCATION_SPANNABLE,
+ MessageKind.IMPORT_EXPERIMENTAL_MIRRORS,
+ {'importChain': importChains.join(
+ MessageKind.IMPORT_EXPERIMENTAL_MIRRORS_PADDING)});
+ }
functionClass.ensureResolved(this);
functionApplyMethod = functionClass.lookupLocalMember('apply');
@@ -1235,8 +1295,8 @@ abstract class Compiler implements DiagnosticListener {
coreLibrary.find('proxy')).value;
// 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')).value;
@@ -1963,40 +2023,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;
+ userCodeLocations.add(const AnyLocation());
}
- 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;
- }
- }
- return false;
+ return userCodeLocations;
}
/// Return a canonical URI for the source of [element].
@@ -2188,3 +2237,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';
+}

Powered by Google App Engine
This is Rietveld 408576698