Chromium Code Reviews| Index: pkg/front_end/lib/src/fasta/source/source_library_builder.dart |
| diff --git a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart |
| index 630b90239b93cadfb746c79b77a52a2f5cb43f85..6c4fdcb1087580434eb0745c8b740cf748b747e1 100644 |
| --- a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart |
| +++ b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart |
| @@ -38,8 +38,7 @@ abstract class SourceLibraryBuilder<T extends TypeBuilder, R> |
| extends LibraryBuilder<T, R> { |
| final SourceLoader loader; |
| - final DeclarationBuilder<T> libraryDeclaration = |
| - new DeclarationBuilder<T>(<String, Builder>{}, null); |
| + final DeclarationBuilder<T> libraryDeclaration; |
| final List<ConstructorReferenceBuilder> constructorReferences = |
| <ConstructorReferenceBuilder>[]; |
| @@ -48,9 +47,7 @@ abstract class SourceLibraryBuilder<T extends TypeBuilder, R> |
| final List<Import> imports = <Import>[]; |
| - final Map<String, Builder> exports = <String, Builder>{}; |
| - |
| - final Scope scope = new Scope.top(); |
| + final Scope importScope; |
| final Uri fileUri; |
| @@ -72,18 +69,20 @@ abstract class SourceLibraryBuilder<T extends TypeBuilder, R> |
| bool canAddImplementationBuilders = false; |
| - SourceLibraryBuilder(this.loader, Uri fileUri) |
| - : fileUri = fileUri, |
| - super(fileUri) { |
| - currentDeclaration = libraryDeclaration; |
| - } |
| + SourceLibraryBuilder(SourceLoader loader, Uri fileUri) |
| + : this.fromScopes(loader, fileUri, new DeclarationBuilder<T>.library(), |
| + new Scope.top()); |
| + |
| + SourceLibraryBuilder.fromScopes( |
| + this.loader, this.fileUri, this.libraryDeclaration, this.importScope) |
| + : currentDeclaration = libraryDeclaration, |
| + super( |
| + fileUri, libraryDeclaration.toScope(importScope), new Scope.top()); |
| Uri get uri; |
| bool get isPart => partOfName != null || partOfUri != null; |
| - Map<String, Builder> get members => libraryDeclaration.members; |
| - |
| List<T> get types => libraryDeclaration.types; |
| T addNamedType(String name, List<T> arguments, int charOffset); |
| @@ -105,9 +104,8 @@ abstract class SourceLibraryBuilder<T extends TypeBuilder, R> |
| return ref; |
| } |
| - void beginNestedDeclaration(String name, {bool hasMembers}) { |
| - currentDeclaration = new DeclarationBuilder( |
| - <String, MemberBuilder>{}, name, currentDeclaration); |
| + void beginNestedDeclaration(String name, {bool hasMembers: true}) { |
| + currentDeclaration = currentDeclaration.createNested(name, hasMembers); |
| } |
| DeclarationBuilder<T> endNestedDeclaration() { |
| @@ -234,12 +232,6 @@ abstract class SourceLibraryBuilder<T extends TypeBuilder, R> |
| TypeVariableBuilder addTypeVariable(String name, T bound, int charOffset); |
| Builder addBuilder(String name, Builder builder, int charOffset) { |
| - if (name.indexOf(".") != -1 && name.indexOf("&") == -1) { |
| - addCompileTimeError( |
| - charOffset, |
| - "Only constructors and factories can have" |
| - " names containing a period ('.'): $name"); |
| - } |
| // TODO(ahe): Set the parent correctly here. Could then change the |
| // implementation of MemberBuilder.isTopLevel to test explicitly for a |
| // LibraryBuilder. |
| @@ -256,19 +248,22 @@ abstract class SourceLibraryBuilder<T extends TypeBuilder, R> |
| } else { |
| assert(currentDeclaration.parent == libraryDeclaration); |
| } |
| - Map<String, Builder> members = currentDeclaration.members; |
| + bool isConstructor = builder is ProcedureBuilder && |
| + (builder.isConstructor || builder.isFactory); |
|
karlklose
2017/04/03 08:05:37
It feels wrong that 'isConstructor' has two differ
ahe
2017/04/04 09:54:51
Perhaps, but on the other hand, kernel uses the na
|
| + Map<String, Builder> members = isConstructor |
| + ? currentDeclaration.constructors |
| + : (builder.isSetter |
| + ? currentDeclaration.setters |
| + : currentDeclaration.members); |
| Builder existing = members[name]; |
| builder.next = existing; |
| if (builder is PrefixBuilder && existing is PrefixBuilder) { |
| assert(existing.next == null); |
| - builder.exports.forEach((String name, Builder builder) { |
| - Builder other = existing.exports.putIfAbsent(name, () => builder); |
| - if (other != builder) { |
| - existing.exports[name] = |
| - buildAmbiguousBuilder(name, other, builder, charOffset); |
| - } |
| - }); |
| - return existing; |
| + return existing |
| + ..exports.merge(builder.exports, |
| + (String name, Builder existing, Builder member) { |
| + return buildAmbiguousBuilder(name, existing, member, charOffset); |
| + }); |
| } else if (isDuplicatedDefinition(existing, builder)) { |
| addCompileTimeError(charOffset, "Duplicated definition of '$name'."); |
| } |
| @@ -313,6 +308,17 @@ abstract class SourceLibraryBuilder<T extends TypeBuilder, R> |
| buildBuilder(builder); |
| } |
| canAddImplementationBuilders = false; |
| + |
| + scope.setters.forEach((String name, Builder setter) { |
| + Builder member = scopeBuilder[name]; |
| + if (member == null || !member.isField || member.isFinal) return; |
| + // TODO(ahe): charOffset is missing. |
| + addCompileTimeError( |
| + setter.charOffset, "Conflicts with member '${name}'."); |
| + addCompileTimeError( |
| + member.charOffset, "Conflicts with setter '${name}'."); |
| + }); |
| + |
| return null; |
| } |
| @@ -377,14 +383,12 @@ abstract class SourceLibraryBuilder<T extends TypeBuilder, R> |
| types.addAll(part.types); |
| constructorReferences.addAll(part.constructorReferences); |
| part.partOfLibrary = this; |
| + part.scope.becomePartOf(scope); |
| // TODO(ahe): Include metadata from part? |
| } |
| void buildInitialScopes() { |
| forEach(addToExportScope); |
| - forEach((String name, Builder member) { |
| - addToScope(name, member, member.charOffset, false); |
| - }); |
| } |
| void addImportsToScope() { |
| @@ -404,15 +408,16 @@ abstract class SourceLibraryBuilder<T extends TypeBuilder, R> |
| @override |
| void addToScope(String name, Builder member, int charOffset, bool isImport) { |
| - Builder existing = scope.lookup(name, member.charOffset, fileUri); |
| + Map<String, Builder> map = |
| + member.isSetter ? importScope.setters : importScope.local; |
| + Builder existing = map[name]; |
| if (existing != null) { |
| if (existing != member) { |
| - scope.local[name] = buildAmbiguousBuilder( |
| - name, existing, member, charOffset, |
| + map[name] = buildAmbiguousBuilder(name, existing, member, charOffset, |
| isImport: isImport); |
| } |
| } else { |
| - scope.local[name] = member; |
| + map[name] = member; |
| } |
| } |
| @@ -420,15 +425,17 @@ abstract class SourceLibraryBuilder<T extends TypeBuilder, R> |
| bool addToExportScope(String name, Builder member) { |
| if (name.startsWith("_")) return false; |
| if (member is PrefixBuilder) return false; |
| - Builder existing = exports[name]; |
| + Map<String, Builder> map = |
| + member.isSetter ? exports.setters : exports.local; |
| + Builder existing = map[name]; |
| if (existing == member) return false; |
| if (existing != null) { |
| Builder result = |
| buildAmbiguousBuilder(name, existing, member, -1, isExport: true); |
| - exports[name] = result; |
| + map[name] = result; |
| return result != existing; |
| } else { |
| - exports[name] = member; |
| + map[name] = member; |
| } |
| return true; |
| } |
| @@ -466,25 +473,30 @@ class DeclarationBuilder<T extends TypeBuilder> { |
| final Map<String, Builder> members; |
| + final Map<String, Builder> constructors; |
| + |
| + final Map<String, Builder> setters; |
| + |
| final List<T> types = <T>[]; |
| final String name; |
| - final Map<ProcedureBuilder, DeclarationBuilder<T>> factoryDeclarations = |
| - <ProcedureBuilder, DeclarationBuilder<T>>{}; |
| + final Map<ProcedureBuilder, DeclarationBuilder<T>> factoryDeclarations; |
| - DeclarationBuilder(this.members, this.name, [this.parent]); |
| + DeclarationBuilder(this.members, this.setters, this.constructors, |
| + this.factoryDeclarations, this.name, this.parent); |
| - void addMember(String name, MemberBuilder builder) { |
| - if (members == null) { |
| - parent.addMember(name, builder); |
| - } else { |
| - members[name] = builder; |
| - } |
| - } |
| + DeclarationBuilder.library() |
| + : this(<String, Builder>{}, <String, Builder>{}, null, null, null, null); |
| - MemberBuilder lookupMember(String name) { |
| - return members == null ? parent.lookupMember(name) : members[name]; |
| + DeclarationBuilder createNested(String name, bool hasMembers) { |
| + return new DeclarationBuilder<T>( |
| + hasMembers ? <String, MemberBuilder>{} : null, |
| + hasMembers ? <String, MemberBuilder>{} : null, |
| + hasMembers ? <String, MemberBuilder>{} : null, |
| + <ProcedureBuilder, DeclarationBuilder<T>>{}, |
| + name, |
| + this); |
| } |
| void addType(T type) { |
| @@ -541,4 +553,8 @@ class DeclarationBuilder<T extends TypeBuilder> { |
| ProcedureBuilder procedure, DeclarationBuilder<T> factoryDeclaration) { |
| factoryDeclarations[procedure] = factoryDeclaration; |
| } |
| + |
| + Scope toScope(Scope parent) { |
| + return new Scope(members, setters, parent, isModifiable: false); |
| + } |
| } |