blob: 82b82974fe45585b22a6bb0b790cab1a2d625531 [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_interface_type_builder;
import 'package:kernel/ast.dart' show DartType, InvalidType, Supertype;
import '../fasta_codes.dart' show Message;
import '../messages.dart'
show noLength, templateSupertypeIsIllegal, templateSupertypeIsTypeVariable;
import '../source/outline_listener.dart';
import 'kernel_builder.dart'
show
KernelClassBuilder,
KernelInvalidTypeBuilder,
KernelTypeBuilder,
LibraryBuilder,
NamedTypeBuilder,
QualifiedName,
TypeBuilder,
TypeDeclarationBuilder,
TypeVariableBuilder;
class KernelNamedTypeBuilder
extends NamedTypeBuilder<KernelTypeBuilder, DartType>
implements KernelTypeBuilder {
final int charOffset;
KernelNamedTypeBuilder(OutlineListener outlineListener, this.charOffset,
Object name, List<KernelTypeBuilder> arguments)
: super(outlineListener, name, arguments);
KernelInvalidTypeBuilder buildInvalidType(int charOffset, Uri fileUri,
[Message message]) {
// TODO(ahe): Consider if it makes sense to pass a QualifiedName to
// KernelInvalidTypeBuilder?
return new KernelInvalidTypeBuilder("$name", charOffset, fileUri, message);
}
Supertype handleInvalidSupertype(
LibraryBuilder library, int charOffset, Uri fileUri) {
var template = declaration.isTypeVariable
? templateSupertypeIsTypeVariable
: templateSupertypeIsIllegal;
library.addCompileTimeError(
template.withArguments("$name"), charOffset, noLength, fileUri);
return null;
}
DartType build(LibraryBuilder library) {
DartType type = declaration.buildType(library, arguments);
_storeType(library, type);
return type;
}
Supertype buildSupertype(
LibraryBuilder library, int charOffset, Uri fileUri) {
TypeDeclarationBuilder declaration = this.declaration;
if (declaration is KernelClassBuilder) {
var supertype = declaration.buildSupertype(library, arguments);
_storeType(library, supertype.asInterfaceType);
return supertype;
} else if (declaration is KernelInvalidTypeBuilder) {
library.addCompileTimeError(
declaration.message.messageObject,
declaration.message.charOffset,
declaration.message.length,
declaration.message.uri);
_storeType(library, const InvalidType());
return null;
} else {
_storeType(library, const InvalidType());
return handleInvalidSupertype(library, charOffset, fileUri);
}
}
Supertype buildMixedInType(
LibraryBuilder library, int charOffset, Uri fileUri) {
TypeDeclarationBuilder declaration = this.declaration;
if (declaration is KernelClassBuilder) {
var supertype = declaration.buildMixedInType(library, arguments);
_storeType(library, supertype.asInterfaceType);
return supertype;
} else if (declaration is KernelInvalidTypeBuilder) {
library.addCompileTimeError(
declaration.message.messageObject,
declaration.message.charOffset,
declaration.message.length,
declaration.message.uri);
_storeType(library, const InvalidType());
return null;
} else {
_storeType(library, const InvalidType());
return handleInvalidSupertype(library, charOffset, fileUri);
}
}
TypeBuilder subst(Map<TypeVariableBuilder, TypeBuilder> substitution) {
TypeBuilder result = substitution[declaration];
if (result != null) {
assert(declaration is TypeVariableBuilder);
return result;
} else if (arguments != null) {
List<KernelTypeBuilder> arguments;
int i = 0;
for (KernelTypeBuilder argument in this.arguments) {
KernelTypeBuilder type = argument.subst(substitution);
if (type != argument) {
arguments ??= this.arguments.toList();
arguments[i] = type;
}
i++;
}
if (arguments != null) {
return new KernelNamedTypeBuilder(
outlineListener, charOffset, name, arguments)
..bind(declaration);
}
}
return this;
}
KernelNamedTypeBuilder clone(List<TypeBuilder> newTypes) {
List<KernelTypeBuilder> clonedArguments;
if (arguments != null) {
clonedArguments = new List<KernelTypeBuilder>(arguments.length);
for (int i = 0; i < clonedArguments.length; i++) {
clonedArguments[i] = arguments[i].clone(newTypes);
}
}
KernelNamedTypeBuilder newType = new KernelNamedTypeBuilder(
outlineListener, charOffset, name, clonedArguments);
newTypes.add(newType);
return newType;
}
int get _storeOffset {
// TODO(scheglov) Can we always make charOffset the "suffix" offset?
var name = this.name;
return name is QualifiedName ? name.charOffset : charOffset;
}
void _storeType(LibraryBuilder library, DartType type) {
if (outlineListener != null) {
if (arguments != null && !this.declaration.buildsArguments) {
for (var argument in arguments) {
argument.build(library);
}
}
TypeDeclarationBuilder<KernelTypeBuilder, DartType> storeDeclaration;
if (actualDeclaration != null) {
storeDeclaration = actualDeclaration;
type = storeDeclaration.buildType(library, null);
} else {
storeDeclaration = declaration;
}
var target = storeDeclaration.hasTarget ? storeDeclaration.target : null;
outlineListener.store(_storeOffset, false, reference: target, type: type);
}
}
}