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

Unified Diff: dart/pkg/dart2js_incremental/lib/library_updater.dart

Issue 724843002: Rewrite, document, and test qualifiedNamesIn. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge
Patch Set: Address Johnni's comments. 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
« no previous file with comments | « no previous file | dart/tests/try/poi/qualified_names_test.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: dart/pkg/dart2js_incremental/lib/library_updater.dart
diff --git a/dart/pkg/dart2js_incremental/lib/library_updater.dart b/dart/pkg/dart2js_incremental/lib/library_updater.dart
index df7a85a6dd04a75da8259e242ff5e442e044f3da..532b5840ee166302c263819fed6e90f298d8fe8d 100644
--- a/dart/pkg/dart2js_incremental/lib/library_updater.dart
+++ b/dart/pkg/dart2js_incremental/lib/library_updater.dart
@@ -232,12 +232,12 @@ class LibraryUpdater extends JsFeatures {
bool canReuseRemovedFunction(PartialFunctionElement element) {
logVerbose("Removed method $element.");
- PartialClassElement cls = element.enclosingClass;
- for (ScopeContainerElement scope in scopesAffectedBy(element, cls)) {
+ ScopeContainerElement container = element.enclosingElement;
+ for (ScopeContainerElement scope in scopesAffectedBy(element, container)) {
scanSites(scope, (Element member, DeclarationSite site) {
// TODO(ahe): Cache qualifiedNamesIn to avoid quadratic behavior.
Map<String, List<String>> names = qualifiedNamesIn(site);
- if (canNamesResolveTo(names, element, cls)) {
+ if (canNamesResolveStaticallyTo(names, element, container)) {
_elementsToInvalidate.add(member);
}
});
@@ -250,6 +250,8 @@ class LibraryUpdater extends JsFeatures {
return true;
}
+ /// Invoke [f] on each [DeclarationSite] in [element]. If [element] is a
+ /// [ScopeContainerElement], invoke f on all local members as well.
void scanSites(
Element element,
void f(ElementX element, DeclarationSite site)) {
@@ -262,15 +264,19 @@ class LibraryUpdater extends JsFeatures {
}
}
+ /// Assume [element] is either removed from or added to [container], and
+ /// return all [ScopeContainerElement] that can see this change.
List<ScopeContainerElement> scopesAffectedBy(
Element element,
- ClassElement cls) {
+ ScopeContainerElement container) {
// TODO(ahe): Use library export graph to compute this.
// TODO(ahe): Should return all user-defined libraries and packages.
- LibraryElement library = element.library;
+ LibraryElement library = container.library;
List<ScopeContainerElement> result = <ScopeContainerElement>[library];
- if (cls == null) return result;
+ if (!container.isClass) return result;
+
+ ClassElement cls = container;
var externalSubtypes =
compiler.world.subtypesOf(cls).where((e) => e.library != library);
@@ -660,7 +666,16 @@ class RemovedFunctionUpdate extends Update with JsFeatures, ReuseFunction {
}
}
-Map<String, List<String>> qualifiedNamesIn(PartialElement element) {
+/// Returns all qualified names in [element] with less than four identifiers. A
+/// qualified name is an identifier followed by a sequence of dots and
+/// identifiers, for example, "x", and "x.y.z". But not "x.y.z.w" ("w" is the
+/// fourth identifier).
+///
+/// The longest possible name that can be resolved is three identifiers, for
+/// example, "prefix.MyClass.staticMethod". Since four or more identifiers
+/// cannot resolve to anything statically, they're not included in the returned
+/// value of this method.
+Set<String> qualifiedNamesIn(PartialElement element) {
Token beginToken = element.beginToken;
Token endToken = element.endToken;
Token token = beginToken;
@@ -673,15 +688,33 @@ Map<String, List<String>> qualifiedNamesIn(PartialElement element) {
}
}
}
- Map<String, List<String>> names = new Map<String, List<String>>();
- List<List<Token>> qualifieds = <List<Token>>[];
+ Set<String> names = new Set<String>();
do {
if (token.isIdentifier()) {
- List<String> name = names.putIfAbsent(token.value, () => <String>[]);
- while (identical('.', token.next.stringValue) &&
- token.next.next.isIdentifier()) {
+ String name = token.value;
+ // [name] is a single "identifier".
+ names.add(name);
+ if (identical('.', token.next.stringValue) &&
+ token.next.next.isIdentifier()) {
token = token.next.next;
- name.add(token.value);
+ name += '.${token.value}';
+ // [name] is "idenfifier.idenfifier".
+ names.add(name);
+
+ if (identical('.', token.next.stringValue) &&
+ token.next.next.isIdentifier()) {
+ token = token.next.next;
+ name += '.${token.value}';
+ // [name] is "idenfifier.idenfifier.idenfifier".
+ names.add(name);
+
+ while (identical('.', token.next.stringValue) &&
+ token.next.next.isIdentifier()) {
+ // Skip remaining identifiers, they cannot statically resolve to
+ // anything, and must be dynamic sends.
+ token = token.next.next;
+ }
+ }
}
}
token = token.next;
@@ -689,21 +722,19 @@ Map<String, List<String>> qualifiedNamesIn(PartialElement element) {
return names;
}
-bool canNamesResolveTo(
- Map<String, List<String>> names,
+/// Returns true if one of the qualified names in names (as computed by
+/// [qualifiedNamesIn]) could be a static reference to [element].
+bool canNamesResolveStaticallyTo(
+ Set<String> names,
Element element,
- ClassElement cls) {
- if (names.containsKey(element.name)) {
- return true;
- }
- if (cls != null) {
- List<String> rest = names[cls.name];
- if (rest != null && rest.contains(element.name)) {
- // [names] contains C.m, where C is the name of [cls], and m is the name
- // of [element].
- return true;
- }
- }
+ ScopeContainerElement container) {
+ if (names.contains(element.name)) return true;
+ if (container != null && container.isClass) {
+ // [names] contains C.m, where C is the name of [container], and m is the
+ // name of [element].
+ if (names.contains("${container.name}.${element.name}")) return true;
+ }
+ // TODO(ahe): Check for prefixes as well.
return false;
}
« no previous file with comments | « no previous file | dart/tests/try/poi/qualified_names_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698