Chromium Code Reviews| Index: pkg/fasta/lib/src/source/source_class_builder.dart |
| diff --git a/pkg/fasta/lib/src/source/source_class_builder.dart b/pkg/fasta/lib/src/source/source_class_builder.dart |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..5746e81de501b5d5dd8670c1dc7b66560e83d684 |
| --- /dev/null |
| +++ b/pkg/fasta/lib/src/source/source_class_builder.dart |
| @@ -0,0 +1,165 @@ |
| +// Copyright (c) 2016, 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. |
| + |
| +library fasta.source_class_builder; |
| + |
| +import 'package:kernel/ast.dart' show |
| + Class, |
| + Constructor, |
| + Supertype, |
| + setParents; |
| + |
| +import '../errors.dart' show |
| + internalError, |
| + inputError; |
| + |
| +import '../kernel/kernel_builder.dart' show |
| + Builder, |
| + ConstructorReferenceBuilder, |
| + KernelClassBuilder, |
| + KernelFieldBuilder, |
| + KernelFunctionBuilder, |
| + KernelLibraryBuilder, |
| + KernelProcedureBuilder, |
| + KernelTypeBuilder, |
| + KernelTypeVariableBuilder, |
| + LibraryBuilder, |
| + MemberBuilder, |
| + MetadataBuilder, |
| + ProcedureBuilder, |
| + TypeVariableBuilder; |
| + |
| +import '../dill/dill_member_builder.dart' show |
| + DillMemberBuilder; |
| + |
| +class SourceClassBuilder extends KernelClassBuilder { |
| + final Class cls; |
| + |
| + final Map<String, Builder> constructors = <String, Builder>{}; |
| + |
| + final Map<String, Builder> membersInScope; |
| + |
| + final List<ConstructorReferenceBuilder> constructorReferences; |
| + |
| + SourceClassBuilder(List<MetadataBuilder> metadata, int modifiers, |
| + String name, List<TypeVariableBuilder> typeVariables, |
| + KernelTypeBuilder supertype, List<KernelTypeBuilder>interfaces, |
| + Map<String, Builder> members, List<KernelTypeBuilder> types, |
| + LibraryBuilder parent, this.constructorReferences, [Class cls]) |
| + : cls = cls ?? new Class(name: name), |
| + membersInScope = computeMembersInScope(members, name), |
| + super(metadata, modifiers, name, typeVariables, supertype, interfaces, |
| + members, types, parent); |
| + |
| + int resolveTypes(LibraryBuilder library) { |
| + int count = 0; |
| + if (typeVariables != null) { |
| + for (KernelTypeVariableBuilder t in typeVariables) { |
| + cls.typeParameters.add(t.parameter); |
| + } |
| + setParents(cls.typeParameters, cls); |
| + count += cls.typeParameters.length; |
| + } |
| + return count + super.resolveTypes(library); |
| + } |
| + |
| + Class build(KernelLibraryBuilder library) { |
| + void buildBuilder(Builder builder) { |
| + if (builder is KernelFieldBuilder) { |
| + cls.addMember(builder.build(library.library)); |
| + } else if (builder is KernelFunctionBuilder) { |
| + cls.addMember(builder.build(library.library)); |
|
Johnni Winther
2017/01/16 15:12:45
Why not join these two cases?
ahe
2017/01/16 15:32:17
I don't have a common interface for the build meth
|
| + } else { |
| + internalError("Unhandled builder: ${builder.runtimeType}"); |
| + } |
| + } |
| + members.forEach((String name, Builder builder) { |
| + do { |
| + buildBuilder(builder); |
| + builder = builder.next; |
| + } while (builder != null); |
| + }); |
| + cls.supertype = supertype?.buildSupertype(); |
| + // TODO(ahe): If `cls.supertype` is null, and this isn't Object, report a |
| + // compile-time error. |
| + cls.isAbstract = isAbstract; |
| + if (interfaces != null) { |
| + for (KernelTypeBuilder interface in interfaces) { |
| + Supertype supertype = interface.buildSupertype(); |
| + if (supertype != null) { |
| + // TODO(ahe): Report an error if supertype is null. |
| + cls.implementedTypes.add(supertype); |
| + } |
| + } |
| + } |
| + return cls; |
| + } |
| + |
| + int convertConstructors(KernelLibraryBuilder library) { |
| + List<String> oldConstructorNames = <String>[]; |
| + members.forEach((String name, MemberBuilder builder) { |
| + if (isConstructorName(name, this.name)) { |
| + oldConstructorNames.add(name); |
| + String newName = ""; |
| + int index = name.indexOf("."); |
| + if (index != -1) { |
| + newName = name.substring(index + 1); |
| + } |
| + if (builder is KernelProcedureBuilder) { |
| + Builder constructor = builder.toConstructor(newName, typeVariables); |
| + Builder other = members[newName]; |
| + if (other != null) { |
| + return inputError(null, null, "Constructor name '$newName' " |
| + "conflicts with other declaration."); |
| + } |
| + constructors[newName] = constructor; |
| + } else { |
| + return inputError(null, null, "Expected a constructor or factory."); |
| + } |
| + } |
| + }); |
| + for (String name in oldConstructorNames) { |
| + members.remove(name); |
| + } |
| + constructors.forEach((String name, Builder builder) { |
| + members[name] = builder; |
| + }); |
| + return oldConstructorNames.length; |
| + } |
| + |
| + Builder findConstructorOrFactory(String name) => constructors[name]; |
| + |
| + void addSyntheticConstructor(Constructor constructor) { |
| + String name = constructor.name.name; |
| + cls.constructors.add(constructor); |
| + constructor.parent = cls; |
| + DillMemberBuilder memberBuilder = new DillMemberBuilder(constructor, this); |
| + memberBuilder.next = constructors[name]; |
| + constructors[name] = memberBuilder; |
| + } |
| +} |
| + |
| +bool isConstructorName(String name, String className) { |
| + if (name.startsWith(className)) { |
| + if (name.length == className.length) return true; |
| + if (name.startsWith(".", className.length)) return true; |
| + } |
| + return false; |
| +} |
| + |
| +Map<String, Builder> computeMembersInScope(Map<String, Builder> members, |
| + String className) { |
| + Map<String, Builder> membersInScope = <String, Builder>{}; |
| + members.forEach((String name, Builder builder) { |
| + if (builder is ProcedureBuilder) { |
| + if (isConstructorName(builder.name, className)) return; |
| + } |
| + if (name.indexOf(".") != -1) { |
| + inputError(null, null, "Only constructors and factories can have names " |
| + "containing a period ('.'): $name"); |
| + } |
| + membersInScope[name] = builder; |
| + }); |
| + return membersInScope; |
| +} |