Index: frog/library.dart |
diff --git a/frog/library.dart b/frog/library.dart |
index 1276ebbca7bd33e79aa40d1ff38b11342a730077..b7ac372bc0e2ae6ca4ffbac34ca7d3a0a20166a4 100644 |
--- a/frog/library.dart |
+++ b/frog/library.dart |
@@ -1,11 +1,18 @@ |
-// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
+// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
// for details. All rights reserved. Use of this source code is governed by a |
// BSD-style license that can be found in the LICENSE file. |
class LibraryImport { |
- String prefix; |
- Library library; |
- LibraryImport(this.library, [this.prefix = null]); |
+ final String prefix; |
+ final Library library; |
+ final SourceSpan span; |
+ LibraryImport(this.library, [this.prefix, this.span]); |
+} |
+ |
+// TODO(jimhug): Make this more useful for good error messages. |
+class AmbiguousMember extends Member { |
+ List<Member> members; |
+ AmbiguousMember(String name, this.members): super(name, null); |
} |
@@ -18,6 +25,7 @@ class Library extends Element { |
List<SourceFile> natives; |
List<SourceFile> sources; |
+ Map<String, Member> _topNames; |
Map<String, MemberSet> _privateMembers; |
/** The type that holds top level types in the library. */ |
@@ -59,9 +67,11 @@ class Library extends Element { |
} |
/** Adds an import to the library. */ |
- addImport(String fullname, String prefix) { |
+ addImport(String fullname, String prefix, SourceSpan span) { |
var newLib = world.getOrAddLibrary(fullname); |
- imports.add(new LibraryImport(newLib, prefix)); |
+ // Special exemption in spec to ensure core is only imported once |
Jennifer Messerly
2012/01/12 01:58:33
Is this to avoid our implicit import of dart:core
|
+ if (newLib.isCore) return; |
+ imports.add(new LibraryImport(newLib, prefix, span)); |
return newLib; |
} |
@@ -163,6 +173,7 @@ class Library extends Element { |
return result; |
} |
+ // TODO(jimhug): Should be merged with new lookup method's logic. |
Type findTypeByName(String name) { |
var ret = types[name]; |
@@ -217,40 +228,7 @@ class Library extends Element { |
} |
Member lookup(String name, SourceSpan span) { |
Jennifer Messerly
2012/01/12 01:58:33
Member lookup(String name, SourceSpan span) => _to
|
- var retType = findTypeByName(name); |
- var ret = null; |
- |
- if (retType != null) { |
- ret = retType.typeMember; |
- } |
- |
- var newRet = topType.getMember(name); |
- // TODO(jimhug): Shares too much code with body of loop. |
- if (newRet != null) { |
- if (ret != null && ret != newRet) { |
- world.error('conflicting members for "$name"', |
- span, ret.span, newRet.span); |
- } else { |
- ret = newRet; |
- } |
- } |
- |
- // Check all imports even if ret != null to detect conflicting names. |
- // TODO(jimhug): Only do this on first lookup. |
- for (var imported in imports) { |
- if (imported.prefix == null) { |
- newRet = imported.library.topType.getMember(name); |
- if (newRet != null) { |
- if (ret != null && ret != newRet) { |
- world.error('conflicting members for "$name"', |
- span, ret.span, newRet.span); |
- } else { |
- ret = newRet; |
- } |
- } |
- } |
- } |
- return ret; |
+ return _topNames[name]; |
} |
resolve() { |
@@ -275,6 +253,55 @@ class Library extends Element { |
} |
} |
+ _addTopName(String name, Member member, [SourceSpan localSpan]) { |
+ var existing = _topNames[name]; |
+ if (existing === null) { |
+ _topNames[name] = member; |
+ } else { |
+ if (existing is AmbiguousMember) { |
+ existing.members.add(member); |
+ } else { |
+ var newMember = new AmbiguousMember(name, [existing, member]); |
+ world.error('conflicting members for "$name"', |
+ existing.span, member.span, localSpan); |
+ _topNames[name] = newMember; |
+ } |
+ } |
+ } |
+ |
+ _addTopNames(Library lib) { |
+ for (var member in lib.topType.members.getValues()) { |
+ if (member.isPrivate && lib != this) continue; |
+ _addTopName(member.name, member); |
+ } |
+ for (var type in lib.types.getValues()) { |
+ if (!type.isTop) { |
+ if (lib != this && type.typeMember.isPrivate) continue; |
+ _addTopName(type.name, type.typeMember); |
+ } |
+ } |
+ } |
+ |
+ /** |
+ * This method will check for any conflicts in top-level names in this |
+ * library. It will also build up a map from top-level names to a single |
+ * member to be used for future lookups both to keep error messages clean |
+ * and as a minor perf optimization. |
+ */ |
+ postResolveChecks() { |
+ _topNames = {}; |
+ // check for conflicts between top-level names |
+ _addTopNames(this); |
+ for (var imported in imports) { |
+ if (imported.prefix == null) { |
+ _addTopNames(imported.library); |
+ } else { |
+ _addTopName(imported.prefix, imported.library.topType.typeMember, |
+ imported.span); |
+ } |
+ } |
+ } |
+ |
visitSources() { |
var visitor = new _LibraryVisitor(this); |
visitor.addSource(baseSource); |
@@ -390,7 +417,7 @@ class _LibraryVisitor implements TreeVisitor { |
return; |
} |
- var newLib = library.addImport(filename, prefix); |
+ var newLib = library.addImport(filename, prefix, node.span); |
// TODO(jimhug): Add check that imported library has a #library |
break; |