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

Unified Diff: pkg/analyzer/lib/src/summary/prelink.dart

Issue 2668423003: Fix for resynthesizing with multiply defined names. (Closed)
Patch Set: Created 3 years, 11 months 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 | pkg/analyzer/test/src/dart/analysis/driver_test.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/analyzer/lib/src/summary/prelink.dart
diff --git a/pkg/analyzer/lib/src/summary/prelink.dart b/pkg/analyzer/lib/src/summary/prelink.dart
index 489bd351d7af7e9574137196db1123316db41c13..31fa6a5fe098ee1cab431e4752e2bb8ad40d467b 100644
--- a/pkg/analyzer/lib/src/summary/prelink.dart
+++ b/pkg/analyzer/lib/src/summary/prelink.dart
@@ -53,7 +53,7 @@ typedef UnlinkedUnit GetPartCallback(String relativeUri);
* A [_Meaning] representing a class.
*/
class _ClassMeaning extends _Meaning {
- final Map<String, _Meaning> namespace;
+ final _Namespace namespace;
_ClassMeaning(int unit, int dependency, int numTypeParameters, this.namespace)
: super(unit, ReferenceKind.classOrEnum, dependency, numTypeParameters);
@@ -109,10 +109,74 @@ class _Meaning {
}
/**
+ * Mapping from names to corresponding unique [_Meaning]s.
+ */
+class _Namespace {
+ final Set<String> namesWithConflictingDefinitions = new Set<String>();
+ final Set<String> libraryNames = new Set<String>();
+ final Map<String, _Meaning> map = <String, _Meaning>{};
+
+ /**
+ * Return the [_Meaning] of the name, or `null` is not defined.
+ */
+ _Meaning operator [](String name) {
+ return map[name];
+ }
+
+ /**
+ * Define that the [name] has the given [value]. If the [name] already been
+ * defined with a different value, then it becomes undefined.
+ */
+ void add(String name, _Meaning value) {
+ // Already determined to be a conflict.
+ if (namesWithConflictingDefinitions.contains(name)) {
+ return;
+ }
+
+ _Meaning currentValue = map[name];
+ if (currentValue == null) {
+ map[name] = value;
+ } else if (currentValue == value) {
+ // The same value, ignore.
+ } else {
+ // A conflict, remember it, and un-define the name.
+ namesWithConflictingDefinitions.add(name);
+ map.remove(name);
+ }
+ }
+
+ /**
+ * Return `true` if the [name] was defined before [rememberLibraryNames]
+ * invocation.
+ */
+ bool definesLibraryName(String name) => libraryNames.contains(name);
+
+ /**
+ * Return `true` if the [name] is already defined.
+ */
+ bool definesName(String name) => map.containsKey(name);
+
+ /**
+ * Apply [f] to each name-meaning pair.
+ */
+ void forEach(void f(String key, _Meaning value)) {
+ map.forEach(f);
+ }
+
+ /**
+ * This method should be invoked after defining all names that are defined
+ * in a library, before defining imported names.
+ */
+ void rememberLibraryNames() {
+ libraryNames.addAll(map.keys);
+ }
+}
+
+/**
* A [_Meaning] representing a prefix introduced by an import directive.
*/
class _PrefixMeaning extends _Meaning {
- final Map<String, _Meaning> namespace = <String, _Meaning>{};
+ final _Namespace namespace = new _Namespace();
_PrefixMeaning() : super(0, ReferenceKind.prefix, 0, 0);
}
@@ -144,10 +208,9 @@ class _Prelinker {
/**
* Names defined inside the library being prelinked.
*/
- final Map<String, _Meaning> privateNamespace = <String, _Meaning>{
- 'dynamic': new _Meaning(0, ReferenceKind.classOrEnum, 0, 0),
- 'void': new _Meaning(0, ReferenceKind.classOrEnum, 0, 0)
- };
+ final _Namespace privateNamespace = new _Namespace()
+ ..add('dynamic', new _Meaning(0, ReferenceKind.classOrEnum, 0, 0))
+ ..add('void', new _Meaning(0, ReferenceKind.classOrEnum, 0, 0));
/**
* List of dependencies of the library being prelinked. This will be output
@@ -166,8 +229,7 @@ class _Prelinker {
/**
* List of public namespaces corresponding to each entry in [dependencies].
*/
- final List<Map<String, _Meaning>> dependencyToPublicNamespace =
- <Map<String, _Meaning>>[null];
+ final List<_Namespace> dependencyToPublicNamespace = <_Namespace>[null];
_Prelinker(this.definingUnit, this.getPart, this.getImport,
this.getDeclaredVariable) {
@@ -180,7 +242,7 @@ class _Prelinker {
* [definingUnit] via [relativeUri], by aggregating together public namespace
* information from all of its parts.
*/
- Map<String, _Meaning> aggregatePublicNamespace(String relativeUri) {
+ _Namespace aggregatePublicNamespace(String relativeUri) {
if (uriToDependency.containsKey(relativeUri)) {
return dependencyToPublicNamespace[uriToDependency[relativeUri]];
}
@@ -192,7 +254,7 @@ class _Prelinker {
uri: relativeUri, parts: unitUris.sublist(1));
dependencies.add(linkedDependency);
- Map<String, _Meaning> aggregated = <String, _Meaning>{};
+ _Namespace aggregated = new _Namespace();
for (int unitNum = 0; unitNum < unitUris.length; unitNum++) {
String unitUri = unitUris[unitNum];
@@ -201,19 +263,24 @@ class _Prelinker {
continue;
}
for (UnlinkedPublicName name in importedNamespace.names) {
- aggregated.putIfAbsent(name.name, () {
- if (name.kind == ReferenceKind.classOrEnum) {
- Map<String, _Meaning> namespace = <String, _Meaning>{};
- name.members.forEach((executable) {
- namespace[executable.name] = new _Meaning(
- unitNum, executable.kind, 0, executable.numTypeParameters);
- });
- return new _ClassMeaning(
- unitNum, dependency, name.numTypeParameters, namespace);
- }
- return new _Meaning(
- unitNum, name.kind, dependency, name.numTypeParameters);
- });
+ if (name.kind == ReferenceKind.classOrEnum) {
+ _Namespace namespace = new _Namespace();
+ name.members.forEach((executable) {
+ namespace.add(
+ executable.name,
+ new _Meaning(
+ unitNum, executable.kind, 0, executable.numTypeParameters));
+ });
+ aggregated.add(
+ name.name,
+ new _ClassMeaning(
+ unitNum, dependency, name.numTypeParameters, namespace));
+ } else {
+ aggregated.add(
+ name.name,
+ new _Meaning(
+ unitNum, name.kind, dependency, name.numTypeParameters));
+ }
}
}
@@ -229,9 +296,9 @@ class _Prelinker {
* If [relativeUri] is `null` (meaning the export namespace of [definingUnit]
* should be computed), then names defined in [definingUnit] are ignored.
*/
- Map<String, _Meaning> computeExportNamespace(String relativeUri) {
- Map<String, _Meaning> exportNamespace = relativeUri == null
- ? <String, _Meaning>{}
+ _Namespace computeExportNamespace(String relativeUri) {
+ _Namespace exportNamespace = relativeUri == null
+ ? new _Namespace()
: aggregatePublicNamespace(relativeUri);
void chaseExports(
NameFilter filter, String relativeUri, Set<String> seenUris) {
@@ -247,9 +314,8 @@ class _Prelinker {
new NameFilter.forUnlinkedCombinators(export.combinators));
aggregatePublicNamespace(exportUri)
.forEach((String name, _Meaning meaning) {
- if (newFilter.accepts(name) &&
- !exportNamespace.containsKey(name)) {
- exportNamespace[name] = meaning;
+ if (newFilter.accepts(name)) {
+ exportNamespace.add(name, meaning);
}
});
chaseExports(newFilter, exportUri, seenUris);
@@ -270,51 +336,47 @@ class _Prelinker {
*/
void extractPrivateNames(UnlinkedUnit unit, int unitNum) {
for (UnlinkedClass cls in unit.classes) {
- privateNamespace.putIfAbsent(cls.name, () {
- Map<String, _Meaning> namespace = <String, _Meaning>{};
- cls.fields.forEach((field) {
- if (field.isStatic && field.isConst) {
- namespace[field.name] =
- new _Meaning(unitNum, ReferenceKind.propertyAccessor, 0, 0);
- }
- });
- cls.executables.forEach((executable) {
- ReferenceKind kind = null;
- if (executable.kind == UnlinkedExecutableKind.constructor) {
- kind = ReferenceKind.constructor;
- } else if (executable.kind ==
- UnlinkedExecutableKind.functionOrMethod &&
- executable.isStatic) {
- kind = ReferenceKind.method;
- } else if (executable.kind == UnlinkedExecutableKind.getter &&
- executable.isStatic) {
- kind = ReferenceKind.propertyAccessor;
- }
- if (kind != null && executable.name.isNotEmpty) {
- namespace[executable.name] = new _Meaning(
- unitNum, kind, 0, executable.typeParameters.length);
- }
- });
- return new _ClassMeaning(
- unitNum, 0, cls.typeParameters.length, namespace);
+ _Namespace namespace = new _Namespace();
+ cls.fields.forEach((field) {
+ if (field.isStatic && field.isConst) {
+ namespace.add(field.name,
+ new _Meaning(unitNum, ReferenceKind.propertyAccessor, 0, 0));
+ }
});
+ cls.executables.forEach((executable) {
+ ReferenceKind kind = null;
+ if (executable.kind == UnlinkedExecutableKind.constructor) {
+ kind = ReferenceKind.constructor;
+ } else if (executable.kind == UnlinkedExecutableKind.functionOrMethod &&
+ executable.isStatic) {
+ kind = ReferenceKind.method;
+ } else if (executable.kind == UnlinkedExecutableKind.getter &&
+ executable.isStatic) {
+ kind = ReferenceKind.propertyAccessor;
+ }
+ if (kind != null && executable.name.isNotEmpty) {
+ namespace.add(executable.name,
+ new _Meaning(unitNum, kind, 0, executable.typeParameters.length));
+ }
+ });
+ privateNamespace.add(cls.name,
+ new _ClassMeaning(unitNum, 0, cls.typeParameters.length, namespace));
}
for (UnlinkedEnum enm in unit.enums) {
- privateNamespace.putIfAbsent(enm.name, () {
- Map<String, _Meaning> namespace = <String, _Meaning>{};
- enm.values.forEach((UnlinkedEnumValue value) {
- namespace[value.name] =
- new _Meaning(unitNum, ReferenceKind.propertyAccessor, 0, 0);
- });
- namespace['values'] =
- new _Meaning(unitNum, ReferenceKind.propertyAccessor, 0, 0);
- return new _ClassMeaning(unitNum, 0, 0, namespace);
+ _Namespace namespace = new _Namespace();
+ enm.values.forEach((UnlinkedEnumValue value) {
+ namespace.add(value.name,
+ new _Meaning(unitNum, ReferenceKind.propertyAccessor, 0, 0));
});
+ namespace.add('values',
+ new _Meaning(unitNum, ReferenceKind.propertyAccessor, 0, 0));
+ privateNamespace.add(
+ enm.name, new _ClassMeaning(unitNum, 0, 0, namespace));
}
for (UnlinkedExecutable executable in unit.executables) {
- privateNamespace.putIfAbsent(
+ privateNamespace.add(
executable.name,
- () => new _Meaning(
+ new _Meaning(
unitNum,
executable.kind == UnlinkedExecutableKind.functionOrMethod
? ReferenceKind.topLevelFunction
@@ -323,20 +385,18 @@ class _Prelinker {
executable.typeParameters.length));
}
for (UnlinkedTypedef typedef in unit.typedefs) {
- privateNamespace.putIfAbsent(
+ privateNamespace.add(
typedef.name,
- () => new _Meaning(unitNum, ReferenceKind.typedef, 0,
+ new _Meaning(unitNum, ReferenceKind.typedef, 0,
typedef.typeParameters.length));
}
for (UnlinkedVariable variable in unit.variables) {
- privateNamespace.putIfAbsent(
- variable.name,
- () => new _Meaning(
- unitNum, ReferenceKind.topLevelPropertyAccessor, 0, 0));
+ privateNamespace.add(variable.name,
+ new _Meaning(unitNum, ReferenceKind.topLevelPropertyAccessor, 0, 0));
if (!(variable.isConst || variable.isFinal)) {
- privateNamespace.putIfAbsent(
+ privateNamespace.add(
variable.name + '=',
- () => new _Meaning(
+ new _Meaning(
unitNum, ReferenceKind.topLevelPropertyAccessor, 0, 0));
}
}
@@ -349,8 +409,8 @@ class _Prelinker {
* already exist in [result] are not overwritten.
*/
void filterExportNamespace(String relativeUri,
- List<UnlinkedCombinator> combinators, Map<String, _Meaning> result) {
- Map<String, _Meaning> exportNamespace = computeExportNamespace(relativeUri);
+ List<UnlinkedCombinator> combinators, _Namespace result) {
+ _Namespace exportNamespace = computeExportNamespace(relativeUri);
if (result == null) {
// This can happen if the import prefix was shadowed by a local name, so
// the imported symbols are inaccessible.
@@ -358,8 +418,8 @@ class _Prelinker {
}
NameFilter filter = new NameFilter.forUnlinkedCombinators(combinators);
exportNamespace.forEach((String name, _Meaning meaning) {
- if (filter.accepts(name) && !result.containsKey(name)) {
- result[name] = meaning;
+ if (filter.accepts(name) && !result.definesLibraryName(name)) {
+ result.add(name, meaning);
}
});
}
@@ -405,7 +465,7 @@ class _Prelinker {
String uri = import.isImplicit
? 'dart:core'
: _selectUri(import.uri, import.configurations);
- Map<String, _Meaning> targetNamespace = null;
+ _Namespace targetNamespace = null;
if (import.prefixReference != 0) {
// The name introduced by an import declaration can't have a prefix of
// its own.
@@ -431,12 +491,11 @@ class _Prelinker {
if (unit == null) {
return new LinkedUnitBuilder();
}
- Map<int, Map<String, _Meaning>> prefixNamespaces =
- <int, Map<String, _Meaning>>{};
+ Map<int, _Namespace> prefixNamespaces = <int, _Namespace>{};
List<LinkedReferenceBuilder> references = <LinkedReferenceBuilder>[];
for (int i = 0; i < unit.references.length; i++) {
UnlinkedReference reference = unit.references[i];
- Map<String, _Meaning> namespace;
+ _Namespace namespace;
if (reference.prefixReference == 0) {
namespace = privateNamespace;
} else {
@@ -444,7 +503,7 @@ class _Prelinker {
assert(reference.prefixReference < i);
namespace = prefixNamespaces[reference.prefixReference];
// Expressions like 'a.b.c.d' cannot be prelinked.
- namespace ??= const <String, _Meaning>{};
+ namespace ??= new _Namespace();
}
_Meaning meaning = namespace[reference.name];
if (meaning != null) {
@@ -485,7 +544,7 @@ class _Prelinker {
// exports.
List<LinkedExportNameBuilder> exportNames = <LinkedExportNameBuilder>[];
computeExportNamespace(null).forEach((String name, _Meaning meaning) {
- if (!privateNamespace.containsKey(name)) {
+ if (!privateNamespace.definesName(name)) {
exportNames.add(meaning.encodeExportName(name));
}
});
@@ -493,12 +552,17 @@ class _Prelinker {
// Fill in prefixes defined in import declarations.
for (UnlinkedImport import in units[0].imports) {
if (import.prefixReference != 0) {
- privateNamespace.putIfAbsent(
- units[0].references[import.prefixReference].name,
- () => new _PrefixMeaning());
+ String name = units[0].references[import.prefixReference].name;
+ if (!privateNamespace.definesName(name)) {
+ privateNamespace.add(name, new _PrefixMeaning());
+ }
}
}
+ // All the names defined so far are library local, they take precedence
+ // over anything imported from other libraries.
+ privateNamespace.rememberLibraryNames();
+
// Fill in imported and exported names.
List<int> importDependencies =
definingUnit.imports.map(handleImport).toList();
« no previous file with comments | « no previous file | pkg/analyzer/test/src/dart/analysis/driver_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698