blob: 9c46ba8cda3ab35465af3bf0eb4ceed25abf0233 [file] [log] [blame]
// 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.kernel_mixin_application_builder;
import 'package:kernel/ast.dart' show InterfaceType, Supertype, setParents;
import '../modifier.dart' show abstractMask;
import '../source/source_class_builder.dart' show SourceClassBuilder;
import '../util/relativize.dart' show relativizeUri;
import 'kernel_builder.dart'
show
ConstructorReferenceBuilder,
KernelLibraryBuilder,
KernelNamedTypeBuilder,
KernelTypeBuilder,
KernelTypeVariableBuilder,
LibraryBuilder,
MemberBuilder,
MixinApplicationBuilder,
Scope,
TypeBuilder,
TypeVariableBuilder;
class KernelMixinApplicationBuilder
extends MixinApplicationBuilder<KernelTypeBuilder>
implements KernelTypeBuilder {
final int charOffset;
final String relativeFileUri;
final KernelLibraryBuilder library;
Supertype builtType;
List<TypeVariableBuilder> typeVariables;
String subclassName;
KernelMixinApplicationBuilder(KernelTypeBuilder supertype,
List<KernelTypeBuilder> mixins, this.library, int charOffset, Uri fileUri)
: charOffset = charOffset,
relativeFileUri = relativizeUri(fileUri),
super(supertype, mixins, charOffset, fileUri);
InterfaceType build(LibraryBuilder library) {
return buildSupertype(library)?.asInterfaceType;
}
Supertype buildSupertype(LibraryBuilder library) {
if (builtType != null) return builtType;
KernelTypeBuilder s = this.supertype;
for (KernelTypeBuilder builder in mixins) {
s = applyMixin(s, builder);
}
builtType = s.buildSupertype(library);
return builtType;
}
TypeBuilder applyMixin(TypeBuilder supertype, TypeBuilder mixin) {
KernelLibraryBuilder library = this.library.partOfLibrary ?? this.library;
List<KernelTypeBuilder> typeArguments;
List<TypeVariableBuilder> newTypeVariables;
if (typeVariables != null) {
assert(subclassName != null);
newTypeVariables = library.copyTypeVariables(typeVariables);
Map<TypeVariableBuilder, TypeBuilder> substitution =
<TypeVariableBuilder, TypeBuilder>{};
typeArguments = <KernelTypeBuilder>[];
for (int i = 0; i < typeVariables.length; i++) {
substitution[typeVariables[i]] = newTypeVariables[i].asTypeBuilder();
typeArguments.add(typeVariables[i].asTypeBuilder());
}
supertype = supertype.subst(substitution);
mixin = mixin.subst(substitution);
}
// To reduce diff against dartk, we create a different name for mixin
// applications that have free type variables. We do this by setting
// [subclassName] when setting typeVariables.
String name = subclassName != null
? "${subclassName}^${mixin.name}"
: "${supertype.name}&${mixin.name}";
SourceClassBuilder cls =
library.mixinApplicationClasses.putIfAbsent(name, () {
SourceClassBuilder cls = new SourceClassBuilder(
null,
abstractMask,
name,
newTypeVariables,
supertype,
null,
new Scope(<String, MemberBuilder>{}, <String, MemberBuilder>{},
library.scope.withTypeVariables(newTypeVariables),
isModifiable: false),
new Scope(<String, MemberBuilder>{}, null, null, isModifiable: false),
library,
<ConstructorReferenceBuilder>[],
charOffset,
null,
mixin);
library.addImplementationBuilder(name, cls, charOffset);
if (newTypeVariables != null) {
for (KernelTypeVariableBuilder t in newTypeVariables) {
cls.cls.typeParameters.add(t.parameter);
}
setParents(cls.cls.typeParameters, cls.cls);
}
return cls;
});
return new KernelNamedTypeBuilder(
name, typeArguments, charOffset, library.fileUri)
..builder = cls;
}
}