mirror of
https://github.com/dart-lang/sdk
synced 2024-11-02 12:24:24 +00:00
Add typedef AST node boilerplate.
This adds the Typedef and TypedefType to the kernel AST,
with the relevant boilerplate.
Typedefs are not implemented in frontend or backend.
R=ahe@google.com, kmillikin@google.com
Committed: d1c3ee4b35
Review-Url: https://codereview.chromium.org/2825053002 .
This commit is contained in:
parent
3f1aa32183
commit
ac40d0bb8e
20 changed files with 709 additions and 8 deletions
|
@ -44,7 +44,8 @@ class FastaVerifyingVisitor extends VerifyingVisitor
|
|||
}
|
||||
|
||||
@override
|
||||
problem(TreeNode node, String details) {
|
||||
problem(TreeNode node, String details, {TreeNode context}) {
|
||||
context ??= this.context;
|
||||
VerificationError error = new VerificationError(context, node, details);
|
||||
printUnexpected(Uri.parse(fileUri), node?.fileOffset ?? -1, "$error");
|
||||
errors.add(error);
|
||||
|
|
|
@ -228,6 +228,13 @@ class Reference {
|
|||
}
|
||||
return node as Procedure;
|
||||
}
|
||||
|
||||
Typedef get asTypedef {
|
||||
if (node == null) {
|
||||
throw '$this is not bound to an AST node. A typedef was expected';
|
||||
}
|
||||
return node as Typedef;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
@ -258,6 +265,7 @@ class Library extends NamedNode implements Comparable<Library> {
|
|||
|
||||
String name;
|
||||
final List<DeferredImport> deferredImports;
|
||||
final List<Typedef> typedefs;
|
||||
final List<Class> classes;
|
||||
final List<Procedure> procedures;
|
||||
final List<Field> fields;
|
||||
|
@ -266,16 +274,20 @@ class Library extends NamedNode implements Comparable<Library> {
|
|||
{this.name,
|
||||
this.isExternal: false,
|
||||
List<DeferredImport> imports,
|
||||
List<Typedef> typedefs,
|
||||
List<Class> classes,
|
||||
List<Procedure> procedures,
|
||||
List<Field> fields,
|
||||
this.fileUri,
|
||||
Reference reference})
|
||||
: this.deferredImports = imports ?? <DeferredImport>[],
|
||||
this.typedefs = typedefs ?? <Typedef>[],
|
||||
this.classes = classes ?? <Class>[],
|
||||
this.procedures = procedures ?? <Procedure>[],
|
||||
this.fields = fields ?? <Field>[],
|
||||
super(reference) {
|
||||
setParents(this.deferredImports, this);
|
||||
setParents(this.typedefs, this);
|
||||
setParents(this.classes, this);
|
||||
setParents(this.procedures, this);
|
||||
setParents(this.fields, this);
|
||||
|
@ -304,8 +316,16 @@ class Library extends NamedNode implements Comparable<Library> {
|
|||
classes.add(class_);
|
||||
}
|
||||
|
||||
void addTypedef(Typedef typedef_) {
|
||||
typedef_.parent = this;
|
||||
typedefs.add(typedef_);
|
||||
}
|
||||
|
||||
void computeCanonicalNames() {
|
||||
assert(canonicalName != null);
|
||||
for (var typedef_ in typedefs) {
|
||||
canonicalName.getChildFromTypedef(typedef_).bindTo(typedef_.reference);
|
||||
}
|
||||
for (var field in fields) {
|
||||
canonicalName.getChildFromMember(field).bindTo(field.reference);
|
||||
}
|
||||
|
@ -321,12 +341,16 @@ class Library extends NamedNode implements Comparable<Library> {
|
|||
accept(TreeVisitor v) => v.visitLibrary(this);
|
||||
|
||||
visitChildren(Visitor v) {
|
||||
visitList(deferredImports, v);
|
||||
visitList(typedefs, v);
|
||||
visitList(classes, v);
|
||||
visitList(procedures, v);
|
||||
visitList(fields, v);
|
||||
}
|
||||
|
||||
transformChildren(Transformer v) {
|
||||
transformList(deferredImports, v, this);
|
||||
transformList(typedefs, v, this);
|
||||
transformList(classes, v, this);
|
||||
transformList(procedures, v, this);
|
||||
transformList(fields, v, this);
|
||||
|
@ -366,6 +390,51 @@ class DeferredImport extends TreeNode {
|
|||
transformChildren(Transformer v) {}
|
||||
}
|
||||
|
||||
/// Declaration of a type alias.
|
||||
class Typedef extends NamedNode {
|
||||
/// The uri of the source file that contains the declaration of this typedef.
|
||||
String fileUri;
|
||||
List<Expression> annotations = const <Expression>[];
|
||||
String name;
|
||||
final List<TypeParameter> typeParameters;
|
||||
DartType type;
|
||||
|
||||
Typedef(this.name, this.type,
|
||||
{Reference reference, this.fileUri, List<TypeParameter> typeParameters})
|
||||
: this.typeParameters = typeParameters ?? <TypeParameter>[],
|
||||
super(reference) {
|
||||
setParents(this.typeParameters, this);
|
||||
}
|
||||
|
||||
Library get enclosingLibrary => parent;
|
||||
|
||||
accept(TreeVisitor v) {
|
||||
return v.visitTypedef(this);
|
||||
}
|
||||
|
||||
transformChildren(Transformer v) {
|
||||
transformList(annotations, v, this);
|
||||
transformList(typeParameters, v, this);
|
||||
if (type != null) {
|
||||
type = v.visitDartType(type);
|
||||
}
|
||||
}
|
||||
|
||||
visitChildren(Visitor v) {
|
||||
visitList(annotations, v);
|
||||
visitList(typeParameters, v);
|
||||
type?.accept(v);
|
||||
}
|
||||
|
||||
void addAnnotation(Expression node) {
|
||||
if (annotations.isEmpty) {
|
||||
annotations = <Expression>[];
|
||||
}
|
||||
annotations.add(node);
|
||||
node.parent = this;
|
||||
}
|
||||
}
|
||||
|
||||
/// The degree to which the contents of a class have been loaded into memory.
|
||||
///
|
||||
/// Each level imply the requirements of the previous ones.
|
||||
|
@ -3695,6 +3764,16 @@ abstract class DartType extends Node {
|
|||
accept(DartTypeVisitor v);
|
||||
|
||||
bool operator ==(Object other);
|
||||
|
||||
/// If this is a typedef type, repeatedly unfolds its type definition until
|
||||
/// the root term is not a typedef type, otherwise returns the type itself.
|
||||
///
|
||||
/// Will never return a typedef type.
|
||||
DartType get unalias => this;
|
||||
|
||||
/// If this is a typedef type, unfolds its type definition once, otherwise
|
||||
/// returns the type itself.
|
||||
DartType get unaliasOnce => this;
|
||||
}
|
||||
|
||||
/// The type arising from invalid type annotations.
|
||||
|
@ -3924,6 +4003,60 @@ class FunctionType extends DartType {
|
|||
}
|
||||
}
|
||||
|
||||
/// A use of a [Typedef] as a type.
|
||||
///
|
||||
/// The underlying type can be extracted using [unalias].
|
||||
class TypedefType extends DartType {
|
||||
final Reference typedefReference;
|
||||
final List<DartType> typeArguments;
|
||||
|
||||
TypedefType(Typedef typedefNode, [List<DartType> typeArguments])
|
||||
: this.byReference(
|
||||
typedefNode.reference, typeArguments ?? const <DartType>[]);
|
||||
|
||||
TypedefType.byReference(this.typedefReference, this.typeArguments);
|
||||
|
||||
Typedef get typedefNode => typedefReference.asTypedef;
|
||||
|
||||
accept(DartTypeVisitor v) => v.visitTypedefType(this);
|
||||
|
||||
visitChildren(Visitor v) {
|
||||
visitList(typeArguments, v);
|
||||
v.visitTypedefReference(typedefNode);
|
||||
}
|
||||
|
||||
DartType get unaliasOnce {
|
||||
return Substitution.fromTypedefType(this).substituteType(typedefNode.type);
|
||||
}
|
||||
|
||||
DartType get unalias {
|
||||
return unaliasOnce.unalias;
|
||||
}
|
||||
|
||||
bool operator ==(Object other) {
|
||||
if (identical(this, other)) return true;
|
||||
if (other is TypedefType) {
|
||||
if (typedefReference != other.typedefReference ||
|
||||
typeArguments.length != other.typeArguments.length) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < typeArguments.length; ++i) {
|
||||
if (typeArguments[i] != other.typeArguments[i]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int get hashCode {
|
||||
int hash = 0x3fffffff & typedefNode.hashCode;
|
||||
for (int i = 0; i < typeArguments.length; ++i) {
|
||||
hash = 0x3fffffff & (hash * 31 + (hash ^ typeArguments[i].hashCode));
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
|
||||
/// A named parameter in [FunctionType].
|
||||
class NamedType extends Node implements Comparable<NamedType> {
|
||||
final String name;
|
||||
|
@ -4323,3 +4456,15 @@ CanonicalName getCanonicalNameOfLibrary(Library library) {
|
|||
}
|
||||
return library.canonicalName;
|
||||
}
|
||||
|
||||
/// Returns the canonical name of [typedef_], or throws an exception if the
|
||||
/// typedef has not been assigned a canonical name yet.
|
||||
///
|
||||
/// Returns `null` if the typedef is `null`.
|
||||
CanonicalName getCanonicalNameOfTypedef(Typedef typedef_) {
|
||||
if (typedef_ == null) return null;
|
||||
if (typedef_.canonicalName == null) {
|
||||
throw '$typedef_ has no canonical name';
|
||||
}
|
||||
return typedef_.canonicalName;
|
||||
}
|
||||
|
|
|
@ -313,6 +313,10 @@ class BinaryBuilder {
|
|||
return name?.getReference();
|
||||
}
|
||||
|
||||
Reference readTypedefReference() {
|
||||
return readCanonicalNameReference().getReference();
|
||||
}
|
||||
|
||||
Name readName() {
|
||||
String text = readStringReference();
|
||||
if (text.isNotEmpty && text[0] == '_') {
|
||||
|
@ -350,6 +354,7 @@ class BinaryBuilder {
|
|||
|
||||
debugPath.add(library.name ?? library.importUri?.toString() ?? 'library');
|
||||
|
||||
_mergeNamedNodeList(library.typedefs, readTypedef, library);
|
||||
_mergeNamedNodeList(library.classes, readClass, library);
|
||||
_mergeNamedNodeList(library.fields, readField, library);
|
||||
_mergeNamedNodeList(library.procedures, readProcedure, library);
|
||||
|
@ -373,6 +378,29 @@ class BinaryBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
Typedef readTypedef() {
|
||||
var canonicalName = readCanonicalNameReference();
|
||||
var reference = canonicalName.getReference();
|
||||
Typedef node = reference.node;
|
||||
bool shouldWriteData = node == null || _isReadingLibraryImplementation;
|
||||
if (node == null) {
|
||||
node = new Typedef(null, null, reference: reference);
|
||||
}
|
||||
int fileOffset = readOffset();
|
||||
String name = readStringReference();
|
||||
String fileUri = readUriReference();
|
||||
readAndPushTypeParameterList(node.typeParameters, node);
|
||||
var type = readDartType();
|
||||
typeParameterStack.length = 0;
|
||||
if (shouldWriteData) {
|
||||
node.fileOffset = fileOffset;
|
||||
node.name = name;
|
||||
node.fileUri = fileUri;
|
||||
node.type = type;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
Class readClass() {
|
||||
int tag = readByte();
|
||||
assert(tag == Tag.Class);
|
||||
|
@ -1019,6 +1047,9 @@ class BinaryBuilder {
|
|||
DartType readDartType() {
|
||||
int tag = readByte();
|
||||
switch (tag) {
|
||||
case Tag.TypedefType:
|
||||
return new TypedefType.byReference(
|
||||
readTypedefReference(), readDartTypeList());
|
||||
case Tag.VectorType:
|
||||
return const VectorType();
|
||||
case Tag.BottomType:
|
||||
|
|
|
@ -251,6 +251,7 @@ class BinaryPrinter extends Visitor {
|
|||
// TODO(jensj): We save (almost) the same URI twice.
|
||||
writeUriReference(node.fileUri ?? '');
|
||||
writeDeferredImports(node);
|
||||
writeNodeList(node.typedefs);
|
||||
writeNodeList(node.classes);
|
||||
writeNodeList(node.fields);
|
||||
writeNodeList(node.procedures);
|
||||
|
@ -273,6 +274,15 @@ class BinaryPrinter extends Visitor {
|
|||
writeStringReference(node.name);
|
||||
}
|
||||
|
||||
void visitTypedef(Typedef node) {
|
||||
writeCanonicalNameReference(getCanonicalNameOfTypedef(node));
|
||||
writeOffset(node.fileOffset);
|
||||
writeStringReference(node.name);
|
||||
writeUriReference(node.fileUri ?? '');
|
||||
writeNodeList(node.typeParameters);
|
||||
writeNode(node.type);
|
||||
}
|
||||
|
||||
void writeAnnotation(Expression annotation) {
|
||||
_variableIndexer ??= new VariableIndexer();
|
||||
writeNode(annotation);
|
||||
|
@ -1009,6 +1019,12 @@ class BinaryPrinter extends Visitor {
|
|||
writeByte(Tag.VectorType);
|
||||
}
|
||||
|
||||
visitTypedefType(TypedefType node) {
|
||||
writeByte(Tag.TypedefType);
|
||||
writeReference(node.typedefReference);
|
||||
writeNodeList(node.typeArguments);
|
||||
}
|
||||
|
||||
visitTypeParameter(TypeParameter node) {
|
||||
writeStringReference(node.name ?? '');
|
||||
writeNode(node.bound);
|
||||
|
|
|
@ -88,6 +88,7 @@ class Tag {
|
|||
static const int FunctionDeclaration = 79;
|
||||
static const int AsyncForInStatement = 80;
|
||||
|
||||
static const int TypedefType = 87;
|
||||
static const int VectorType = 88;
|
||||
static const int BottomType = 89;
|
||||
static const int InvalidType = 90;
|
||||
|
|
|
@ -104,6 +104,10 @@ class CanonicalName {
|
|||
.getChildFromQualifiedName(member.name);
|
||||
}
|
||||
|
||||
CanonicalName getChildFromTypedef(Typedef typedef_) {
|
||||
return getChild('@typedefs').getChild(typedef_.name);
|
||||
}
|
||||
|
||||
void bindTo(Reference target) {
|
||||
if (reference == target) return;
|
||||
if (reference != null) {
|
||||
|
|
|
@ -210,6 +210,12 @@ class Printer extends Visitor<Null> {
|
|||
return '$library::$name';
|
||||
}
|
||||
|
||||
String getTypedefReference(Typedef node) {
|
||||
if (node == null) return '<No Typedef>';
|
||||
String library = getLibraryReference(node.enclosingLibrary);
|
||||
return '$library::${node.name}';
|
||||
}
|
||||
|
||||
static final String emptyNameString = '•';
|
||||
static final Name emptyName = new Name(emptyNameString);
|
||||
|
||||
|
@ -281,6 +287,7 @@ class Printer extends Visitor<Null> {
|
|||
}
|
||||
endLine();
|
||||
var inner = new Printer._inner(this, imports);
|
||||
library.typedefs.forEach(inner.writeNode);
|
||||
library.classes.forEach(inner.writeNode);
|
||||
library.fields.forEach(inner.writeNode);
|
||||
library.procedures.forEach(inner.writeNode);
|
||||
|
@ -313,6 +320,7 @@ class Printer extends Visitor<Null> {
|
|||
writeWord(prefix);
|
||||
endLine(' {');
|
||||
++inner.indentation;
|
||||
library.typedefs.forEach(inner.writeNode);
|
||||
library.classes.forEach(inner.writeNode);
|
||||
library.fields.forEach(inner.writeNode);
|
||||
library.procedures.forEach(inner.writeNode);
|
||||
|
@ -429,6 +437,15 @@ class Printer extends Visitor<Null> {
|
|||
writeWord('Vector');
|
||||
}
|
||||
|
||||
visitTypedefType(TypedefType type) {
|
||||
writeTypedefReference(type.typedefNode);
|
||||
if (type.typeArguments.isNotEmpty) {
|
||||
writeSymbol('<');
|
||||
writeList(type.typeArguments, writeType);
|
||||
writeSymbol('>');
|
||||
}
|
||||
}
|
||||
|
||||
void writeModifier(bool isThere, String name) {
|
||||
if (isThere) {
|
||||
writeWord(name);
|
||||
|
@ -610,6 +627,10 @@ class Printer extends Visitor<Null> {
|
|||
writeWord(getClassReference(classNode));
|
||||
}
|
||||
|
||||
void writeTypedefReference(Typedef typedefNode) {
|
||||
writeWord(getTypedefReference(typedefNode));
|
||||
}
|
||||
|
||||
void writeLibraryReference(Library library) {
|
||||
writeWord(getLibraryReference(library));
|
||||
}
|
||||
|
@ -751,6 +772,16 @@ class Printer extends Visitor<Null> {
|
|||
endLine('}');
|
||||
}
|
||||
|
||||
visitTypedef(Typedef node) {
|
||||
writeIndentation();
|
||||
writeWord('typedef');
|
||||
writeWord(node.name);
|
||||
writeTypeParameterList(node.typeParameters);
|
||||
writeSpaced('=');
|
||||
writeNode(node.type);
|
||||
endLine(';');
|
||||
}
|
||||
|
||||
visitInvalidExpression(InvalidExpression node) {
|
||||
writeWord('invalid-expression');
|
||||
}
|
||||
|
|
|
@ -59,6 +59,11 @@ class Erasure extends Transformer with DartTypeVisitor<DartType> {
|
|||
return type;
|
||||
}
|
||||
|
||||
@override
|
||||
TypedefType visitTypedefType(TypedefType type) {
|
||||
throw 'Typedef types not implemented in erasure';
|
||||
}
|
||||
|
||||
@override
|
||||
Supertype visitSupertype(Supertype type) {
|
||||
if (removeTypeParameters(type.classNode)) {
|
||||
|
|
|
@ -1056,6 +1056,10 @@ class _ExternalTypeVisitor extends DartTypeVisitor {
|
|||
}
|
||||
}
|
||||
|
||||
visitTypedefType(TypedefType node) {
|
||||
throw 'TypedefType is not implemented in tree shaker';
|
||||
}
|
||||
|
||||
visitFunctionType(FunctionType node) {
|
||||
visit(node.returnType);
|
||||
for (int i = 0; i < node.positionalParameters.length; ++i) {
|
||||
|
|
|
@ -173,6 +173,14 @@ abstract class Substitution {
|
|||
type.classNode.typeParameters, type.typeArguments));
|
||||
}
|
||||
|
||||
/// Substitutes the type parameters on the typedef of [type] with the
|
||||
/// type arguments provided in [type].
|
||||
static Substitution fromTypedefType(TypedefType type) {
|
||||
if (type.typeArguments.isEmpty) return _NullSubstitution.instance;
|
||||
return fromMap(new Map<TypeParameter, DartType>.fromIterables(
|
||||
type.typedefNode.typeParameters, type.typeArguments));
|
||||
}
|
||||
|
||||
/// Substitutes the Nth parameter in [parameters] with the Nth type in
|
||||
/// [types].
|
||||
static Substitution fromPairs(
|
||||
|
@ -375,6 +383,14 @@ abstract class _TypeSubstitutor extends DartTypeVisitor<DartType> {
|
|||
return new InterfaceType(node.classNode, typeArguments);
|
||||
}
|
||||
|
||||
DartType visitTypedefType(TypedefType node) {
|
||||
if (node.typeArguments.isEmpty) return node;
|
||||
int before = useCounter;
|
||||
var typeArguments = node.typeArguments.map(visit).toList();
|
||||
if (useCounter == before) return node;
|
||||
return new TypedefType(node.typedefNode, typeArguments);
|
||||
}
|
||||
|
||||
List<TypeParameter> freshTypeParameters(List<TypeParameter> parameters) {
|
||||
if (parameters.isEmpty) return const <TypeParameter>[];
|
||||
return parameters.map(freshTypeParameter).toList();
|
||||
|
@ -655,6 +671,10 @@ class _OccurrenceVisitor extends DartTypeVisitor<bool> {
|
|||
return node.typeArguments.any(visit);
|
||||
}
|
||||
|
||||
bool visitTypedefType(TypedefType node) {
|
||||
return node.typeArguments.any(visit);
|
||||
}
|
||||
|
||||
bool visitFunctionType(FunctionType node) {
|
||||
return node.typeParameters.any(handleTypeParameter) ||
|
||||
node.positionalParameters.any(visit) ||
|
||||
|
|
|
@ -145,6 +145,8 @@ abstract class SubtypeTester {
|
|||
|
||||
/// Returns true if [subtype] is a subtype of [supertype].
|
||||
bool isSubtypeOf(DartType subtype, DartType supertype) {
|
||||
subtype = subtype.unalias;
|
||||
supertype = supertype.unalias;
|
||||
if (identical(subtype, supertype)) return true;
|
||||
if (subtype is BottomType) return true;
|
||||
if (supertype is DynamicType ||
|
||||
|
|
|
@ -38,13 +38,17 @@ class VerificationError {
|
|||
}
|
||||
}
|
||||
|
||||
enum TypedefState { Done, BeingChecked }
|
||||
|
||||
/// Checks that a kernel program is well-formed.
|
||||
///
|
||||
/// This does not include any kind of type checking.
|
||||
class VerifyingVisitor extends RecursiveVisitor {
|
||||
final Set<Class> classes = new Set<Class>();
|
||||
final Set<TypeParameter> typeParameters = new Set<TypeParameter>();
|
||||
final Set<Typedef> typedefs = new Set<Typedef>();
|
||||
Set<TypeParameter> typeParametersInScope = new Set<TypeParameter>();
|
||||
final List<VariableDeclaration> variableStack = <VariableDeclaration>[];
|
||||
final Map<Typedef, TypedefState> typedefState = <Typedef, TypedefState>{};
|
||||
bool classTypeParametersAreInScope = false;
|
||||
|
||||
/// If true, relax certain checks for *outline* mode. For example, don't
|
||||
|
@ -67,7 +71,8 @@ class VerifyingVisitor extends RecursiveVisitor {
|
|||
visitChildren(node);
|
||||
}
|
||||
|
||||
problem(TreeNode node, String details) {
|
||||
problem(TreeNode node, String details, {TreeNode context}) {
|
||||
context ??= this.context;
|
||||
throw new VerificationError(context, node, details);
|
||||
}
|
||||
|
||||
|
@ -75,7 +80,8 @@ class VerifyingVisitor extends RecursiveVisitor {
|
|||
if (!identical(node.parent, currentParent)) {
|
||||
problem(
|
||||
node,
|
||||
"Incorrect parent pointer: expected '${node.parent.runtimeType}',"
|
||||
"Incorrect parent pointer on ${node.runtimeType}:"
|
||||
" expected '${node.parent.runtimeType}',"
|
||||
" but found: '${currentParent.runtimeType}'.");
|
||||
}
|
||||
var oldParent = currentParent;
|
||||
|
@ -135,14 +141,14 @@ class VerifyingVisitor extends RecursiveVisitor {
|
|||
void declareTypeParameters(List<TypeParameter> parameters) {
|
||||
for (int i = 0; i < parameters.length; ++i) {
|
||||
var parameter = parameters[i];
|
||||
if (!typeParameters.add(parameter)) {
|
||||
if (!typeParametersInScope.add(parameter)) {
|
||||
problem(parameter, "Type parameter '$parameter' redeclared.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void undeclareTypeParameters(List<TypeParameter> parameters) {
|
||||
typeParameters.removeAll(parameters);
|
||||
typeParametersInScope.removeAll(parameters);
|
||||
}
|
||||
|
||||
void checkVariableInScope(VariableDeclaration variable, TreeNode where) {
|
||||
|
@ -159,6 +165,11 @@ class VerifyingVisitor extends RecursiveVisitor {
|
|||
problem(class_, "Class '$class_' declared more than once.");
|
||||
}
|
||||
}
|
||||
for (var typedef_ in library.typedefs) {
|
||||
if (!typedefs.add(typedef_)) {
|
||||
problem(typedef_, "Typedef '$typedef_' declared more than once.");
|
||||
}
|
||||
}
|
||||
library.members.forEach(declareMember);
|
||||
for (var class_ in library.classes) {
|
||||
class_.members.forEach(declareMember);
|
||||
|
@ -176,6 +187,32 @@ class VerifyingVisitor extends RecursiveVisitor {
|
|||
}
|
||||
}
|
||||
|
||||
void checkTypedef(Typedef node) {
|
||||
var state = typedefState[node];
|
||||
if (state == TypedefState.Done) return;
|
||||
if (state == TypedefState.BeingChecked) {
|
||||
problem(node, "The typedef '$node' refers to itself", context: node);
|
||||
}
|
||||
assert(state == null);
|
||||
typedefState[node] = TypedefState.BeingChecked;
|
||||
var savedTypeParameters = typeParametersInScope;
|
||||
typeParametersInScope = node.typeParameters.toSet();
|
||||
var savedParent = currentParent;
|
||||
currentParent = node;
|
||||
// Visit children without checking the parent pointer on the typedef itself
|
||||
// since this can be called from a context other than its true parent.
|
||||
node.visitChildren(this);
|
||||
currentParent = savedParent;
|
||||
typeParametersInScope = savedTypeParameters;
|
||||
typedefState[node] = TypedefState.Done;
|
||||
}
|
||||
|
||||
visitTypedef(Typedef node) {
|
||||
checkTypedef(node);
|
||||
// Enter and exit the node to check the parent pointer on the typedef node.
|
||||
exitParent(enterParent(node));
|
||||
}
|
||||
|
||||
visitField(Field node) {
|
||||
currentMember = node;
|
||||
var oldParent = enterParent(node);
|
||||
|
@ -184,6 +221,7 @@ class VerifyingVisitor extends RecursiveVisitor {
|
|||
classTypeParametersAreInScope = false;
|
||||
visitList(node.annotations, this);
|
||||
exitParent(oldParent);
|
||||
node.type.accept(this);
|
||||
currentMember = null;
|
||||
}
|
||||
|
||||
|
@ -491,10 +529,18 @@ class VerifyingVisitor extends RecursiveVisitor {
|
|||
}
|
||||
}
|
||||
|
||||
@override
|
||||
visitTypedefReference(Typedef node) {
|
||||
if (!typedefs.contains(node)) {
|
||||
problem(
|
||||
node, "Dangling reference to '$node', parent is: '${node.parent}'");
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
visitTypeParameterType(TypeParameterType node) {
|
||||
var parameter = node.parameter;
|
||||
if (!typeParameters.contains(parameter)) {
|
||||
if (!typeParametersInScope.contains(parameter)) {
|
||||
problem(
|
||||
currentParent,
|
||||
"Type parameter '$parameter' referenced out of"
|
||||
|
@ -519,6 +565,19 @@ class VerifyingVisitor extends RecursiveVisitor {
|
|||
" ${node.classNode.typeParameters.length} parameters.");
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
visitTypedefType(TypedefType node) {
|
||||
checkTypedef(node.typedefNode);
|
||||
node.visitChildren(this);
|
||||
if (node.typeArguments.length != node.typedefNode.typeParameters.length) {
|
||||
problem(
|
||||
currentParent,
|
||||
"The typedef type $node provides ${node.typeArguments.length}"
|
||||
" type arguments but the typedef declares"
|
||||
" ${node.typedefNode.typeParameters.length} parameters.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class CheckParentPointers extends Visitor {
|
||||
|
|
|
@ -221,6 +221,7 @@ class TreeVisitor<R>
|
|||
// Other tree nodes
|
||||
R visitLibrary(Library node) => defaultTreeNode(node);
|
||||
R visitDeferredImport(DeferredImport node) => defaultTreeNode(node);
|
||||
R visitTypedef(Typedef node) => defaultTreeNode(node);
|
||||
R visitTypeParameter(TypeParameter node) => defaultTreeNode(node);
|
||||
R visitFunctionNode(FunctionNode node) => defaultTreeNode(node);
|
||||
R visitArguments(Arguments node) => defaultTreeNode(node);
|
||||
|
@ -242,6 +243,7 @@ class DartTypeVisitor<R> {
|
|||
R visitVectorType(VectorType node) => defaultDartType(node);
|
||||
R visitFunctionType(FunctionType node) => defaultDartType(node);
|
||||
R visitTypeParameterType(TypeParameterType node) => defaultDartType(node);
|
||||
R visitTypedefType(TypedefType node) => defaultDartType(node);
|
||||
}
|
||||
|
||||
class MemberReferenceVisitor<R> {
|
||||
|
@ -268,9 +270,11 @@ class Visitor<R> extends TreeVisitor<R>
|
|||
R visitVectorType(VectorType node) => defaultDartType(node);
|
||||
R visitFunctionType(FunctionType node) => defaultDartType(node);
|
||||
R visitTypeParameterType(TypeParameterType node) => defaultDartType(node);
|
||||
R visitTypedefType(TypedefType node) => defaultDartType(node);
|
||||
|
||||
// Class references
|
||||
R visitClassReference(Class node) => null;
|
||||
R visitTypedefReference(Typedef node) => null;
|
||||
|
||||
// Member references
|
||||
R defaultMemberReference(Member node) => null;
|
||||
|
|
|
@ -141,6 +141,8 @@ class DartTypeParser {
|
|||
return fail('Unresolved type $name');
|
||||
} else if (target is Class) {
|
||||
return new InterfaceType(target, parseOptionalTypeArgumentList());
|
||||
} else if (target is Typedef) {
|
||||
return new TypedefType(target, parseOptionalTypeArgumentList());
|
||||
} else if (target is TypeParameter) {
|
||||
if (peekToken() == Token.LeftAngle) {
|
||||
return fail('Attempt to apply type arguments to a type variable');
|
||||
|
|
68
pkg/kernel/test/typedef_unalias_test.dart
Normal file
68
pkg/kernel/test/typedef_unalias_test.dart
Normal file
|
@ -0,0 +1,68 @@
|
|||
// 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 kernel.typedef_unalias_test;
|
||||
|
||||
import 'package:kernel/ast.dart';
|
||||
import 'package:test/test.dart';
|
||||
import 'verify_test.dart' show TestHarness;
|
||||
|
||||
void harnessTest(String name, void doTest(TestHarness harness)) {
|
||||
test(name, () {
|
||||
doTest(new TestHarness());
|
||||
});
|
||||
}
|
||||
|
||||
main() {
|
||||
harnessTest('`Foo` where typedef Foo = C', (TestHarness harness) {
|
||||
var foo = new Typedef('Foo', harness.otherClass.rawType);
|
||||
harness.enclosingLibrary.addTypedef(foo);
|
||||
var type = new TypedefType(foo);
|
||||
expect(type.unalias, equals(harness.otherClass.rawType));
|
||||
});
|
||||
harnessTest('`Foo<Obj>` where typedef Foo<T> = C<T>', (TestHarness harness) {
|
||||
var param = harness.makeTypeParameter('T');
|
||||
var foo = new Typedef('Foo',
|
||||
new InterfaceType(harness.otherClass, [new TypeParameterType(param)]),
|
||||
typeParameters: [param]);
|
||||
harness.enclosingLibrary.addTypedef(foo);
|
||||
var input = new TypedefType(foo, [harness.objectClass.rawType]);
|
||||
var expected =
|
||||
new InterfaceType(harness.otherClass, [harness.objectClass.rawType]);
|
||||
expect(input.unalias, equals(expected));
|
||||
});
|
||||
harnessTest('`Bar<Obj>` where typedef Bar<T> = Foo<T>, Foo<T> = C<T>',
|
||||
(TestHarness harness) {
|
||||
var fooParam = harness.makeTypeParameter('T');
|
||||
var foo = new Typedef(
|
||||
'Foo',
|
||||
new InterfaceType(
|
||||
harness.otherClass, [new TypeParameterType(fooParam)]),
|
||||
typeParameters: [fooParam]);
|
||||
var barParam = harness.makeTypeParameter('T');
|
||||
var bar = new Typedef(
|
||||
'Bar', new TypedefType(foo, [new TypeParameterType(barParam)]),
|
||||
typeParameters: [barParam]);
|
||||
harness.enclosingLibrary.addTypedef(foo);
|
||||
harness.enclosingLibrary.addTypedef(bar);
|
||||
var input = new TypedefType(bar, [harness.objectClass.rawType]);
|
||||
var expected =
|
||||
new InterfaceType(harness.otherClass, [harness.objectClass.rawType]);
|
||||
expect(input.unalias, equals(expected));
|
||||
});
|
||||
harnessTest('`Foo<Foo<C>>` where typedef Foo<T> = C<T>',
|
||||
(TestHarness harness) {
|
||||
var param = harness.makeTypeParameter('T');
|
||||
var foo = new Typedef('Foo',
|
||||
new InterfaceType(harness.otherClass, [new TypeParameterType(param)]),
|
||||
typeParameters: [param]);
|
||||
harness.enclosingLibrary.addTypedef(foo);
|
||||
var input = new TypedefType(foo, [
|
||||
new TypedefType(foo, [harness.objectClass.rawType])
|
||||
]);
|
||||
var expected = new InterfaceType(harness.otherClass, [
|
||||
new TypedefType(foo, [harness.objectClass.rawType])
|
||||
]);
|
||||
expect(input.unalias, equals(expected));
|
||||
});
|
||||
}
|
|
@ -199,6 +199,171 @@ main() {
|
|||
test.enclosingClass.addMember(constructor);
|
||||
return new ConstructorInvocation(constructor, new Arguments.empty());
|
||||
});
|
||||
positiveTest('Valid typedef Foo = `(C) => void`', (TestHarness test) {
|
||||
var typedef_ = new Typedef(
|
||||
'Foo', new FunctionType([test.otherClass.rawType], const VoidType()));
|
||||
test.enclosingLibrary.addTypedef(typedef_);
|
||||
});
|
||||
positiveTest('Valid typedef Foo = C<dynamic>', (TestHarness test) {
|
||||
var typedef_ = new Typedef(
|
||||
'Foo', new InterfaceType(test.otherClass, [const DynamicType()]));
|
||||
test.enclosingLibrary.addTypedef(typedef_);
|
||||
});
|
||||
positiveTest('Valid typedefs Foo = Bar, Bar = C', (TestHarness test) {
|
||||
var foo = new Typedef('Foo', null);
|
||||
var bar = new Typedef('Bar', null);
|
||||
foo.type = new TypedefType(bar);
|
||||
bar.type = test.otherClass.rawType;
|
||||
test.enclosingLibrary.addTypedef(foo);
|
||||
test.enclosingLibrary.addTypedef(bar);
|
||||
});
|
||||
positiveTest('Valid typedefs Foo = C<Bar>, Bar = C', (TestHarness test) {
|
||||
var foo = new Typedef('Foo', null);
|
||||
var bar = new Typedef('Bar', null);
|
||||
foo.type = new InterfaceType(test.otherClass, [new TypedefType(bar)]);
|
||||
bar.type = test.otherClass.rawType;
|
||||
test.enclosingLibrary.addTypedef(foo);
|
||||
test.enclosingLibrary.addTypedef(bar);
|
||||
});
|
||||
positiveTest('Valid typedef type in field', (TestHarness test) {
|
||||
var typedef_ = new Typedef(
|
||||
'Foo', new FunctionType([test.otherClass.rawType], const VoidType()));
|
||||
var field = new Field(new Name('field'), type: new TypedefType(typedef_));
|
||||
test.enclosingLibrary.addTypedef(typedef_);
|
||||
test.enclosingLibrary.addMember(field);
|
||||
});
|
||||
negativeTest('Invalid typedef Foo = Foo', (TestHarness test) {
|
||||
var typedef_ = new Typedef('Foo', null);
|
||||
typedef_.type = new TypedefType(typedef_);
|
||||
test.enclosingLibrary.addTypedef(typedef_);
|
||||
});
|
||||
negativeTest('Invalid typedef Foo = `(Foo) => void`', (TestHarness test) {
|
||||
var typedef_ = new Typedef('Foo', null);
|
||||
typedef_.type =
|
||||
new FunctionType([new TypedefType(typedef_)], const VoidType());
|
||||
test.enclosingLibrary.addTypedef(typedef_);
|
||||
});
|
||||
negativeTest('Invalid typedef Foo = `() => Foo`', (TestHarness test) {
|
||||
var typedef_ = new Typedef('Foo', null);
|
||||
typedef_.type = new FunctionType([], new TypedefType(typedef_));
|
||||
test.enclosingLibrary.addTypedef(typedef_);
|
||||
});
|
||||
negativeTest('Invalid typedef Foo = C<Foo>', (TestHarness test) {
|
||||
var typedef_ = new Typedef('Foo', null);
|
||||
typedef_.type =
|
||||
new InterfaceType(test.otherClass, [new TypedefType(typedef_)]);
|
||||
test.enclosingLibrary.addTypedef(typedef_);
|
||||
});
|
||||
negativeTest('Invalid typedefs Foo = Bar, Bar = Foo', (TestHarness test) {
|
||||
var foo = new Typedef('Foo', null);
|
||||
var bar = new Typedef('Bar', null);
|
||||
foo.type = new TypedefType(bar);
|
||||
bar.type = new TypedefType(foo);
|
||||
test.enclosingLibrary.addTypedef(foo);
|
||||
test.enclosingLibrary.addTypedef(bar);
|
||||
});
|
||||
negativeTest('Invalid typedefs Foo = Bar, Bar = C<Foo>', (TestHarness test) {
|
||||
var foo = new Typedef('Foo', null);
|
||||
var bar = new Typedef('Bar', null);
|
||||
foo.type = new TypedefType(bar);
|
||||
bar.type = new InterfaceType(test.otherClass, [new TypedefType(foo)]);
|
||||
test.enclosingLibrary.addTypedef(foo);
|
||||
test.enclosingLibrary.addTypedef(bar);
|
||||
});
|
||||
negativeTest('Invalid typedefs Foo = C<Bar>, Bar = C<Foo>',
|
||||
(TestHarness test) {
|
||||
var foo = new Typedef('Foo', null);
|
||||
var bar = new Typedef('Bar', null);
|
||||
foo.type = new InterfaceType(test.otherClass, [new TypedefType(bar)]);
|
||||
bar.type = new InterfaceType(test.otherClass, [new TypedefType(foo)]);
|
||||
test.enclosingLibrary.addTypedef(foo);
|
||||
test.enclosingLibrary.addTypedef(bar);
|
||||
});
|
||||
positiveTest('Valid long typedefs C20 = C19 = ... = C1 = C0 = dynamic',
|
||||
(TestHarness test) {
|
||||
var typedef_ = new Typedef('C0', const DynamicType());
|
||||
test.enclosingLibrary.addTypedef(typedef_);
|
||||
for (int i = 1; i < 20; ++i) {
|
||||
typedef_ = new Typedef('C$i', new TypedefType(typedef_));
|
||||
test.enclosingLibrary.addTypedef(typedef_);
|
||||
}
|
||||
});
|
||||
negativeTest('Invalid long typedefs C20 = C19 = ... = C1 = C0 = C20',
|
||||
(TestHarness test) {
|
||||
var typedef_ = new Typedef('C0', null);
|
||||
test.enclosingLibrary.addTypedef(typedef_);
|
||||
var first = typedef_;
|
||||
for (int i = 1; i < 20; ++i) {
|
||||
typedef_ = new Typedef('C$i', new TypedefType(typedef_));
|
||||
test.enclosingLibrary.addTypedef(typedef_);
|
||||
}
|
||||
first.type = new TypedefType(typedef_);
|
||||
});
|
||||
positiveTest('Valid typedef Foo<T extends C> = C<T>', (TestHarness test) {
|
||||
var param = new TypeParameter('T', test.otherClass.rawType);
|
||||
var foo = new Typedef('Foo',
|
||||
new InterfaceType(test.otherClass, [new TypeParameterType(param)]),
|
||||
typeParameters: [param]);
|
||||
test.enclosingLibrary.addTypedef(foo);
|
||||
});
|
||||
positiveTest('Valid typedef Foo<T extends C<T>> = C<T>', (TestHarness test) {
|
||||
var param = new TypeParameter('T', test.otherClass.rawType);
|
||||
param.bound =
|
||||
new InterfaceType(test.otherClass, [new TypeParameterType(param)]);
|
||||
var foo = new Typedef('Foo',
|
||||
new InterfaceType(test.otherClass, [new TypeParameterType(param)]),
|
||||
typeParameters: [param]);
|
||||
test.enclosingLibrary.addTypedef(foo);
|
||||
});
|
||||
positiveTest('Valid typedef Foo<T> = dynamic, Bar<T extends Foo<T>> = C<T>',
|
||||
(TestHarness test) {
|
||||
var fooParam = test.makeTypeParameter('T');
|
||||
var foo =
|
||||
new Typedef('Foo', const DynamicType(), typeParameters: [fooParam]);
|
||||
var barParam = new TypeParameter('T', null);
|
||||
barParam.bound = new TypedefType(foo, [new TypeParameterType(barParam)]);
|
||||
var bar = new Typedef('Bar',
|
||||
new InterfaceType(test.otherClass, [new TypeParameterType(barParam)]),
|
||||
typeParameters: [barParam]);
|
||||
test.enclosingLibrary.addTypedef(foo);
|
||||
test.enclosingLibrary.addTypedef(bar);
|
||||
});
|
||||
negativeTest('Invalid typedefs Foo<T extends Bar<T>>, Bar<T extends Foo<T>>',
|
||||
(TestHarness test) {
|
||||
var fooParam = test.makeTypeParameter('T');
|
||||
var foo =
|
||||
new Typedef('Foo', const DynamicType(), typeParameters: [fooParam]);
|
||||
var barParam = new TypeParameter('T', null);
|
||||
barParam.bound = new TypedefType(foo, [new TypeParameterType(barParam)]);
|
||||
var bar = new Typedef('Bar',
|
||||
new InterfaceType(test.otherClass, [new TypeParameterType(barParam)]),
|
||||
typeParameters: [barParam]);
|
||||
fooParam.bound = new TypedefType(bar, [new TypeParameterType(fooParam)]);
|
||||
test.enclosingLibrary.addTypedef(foo);
|
||||
test.enclosingLibrary.addTypedef(bar);
|
||||
});
|
||||
negativeTest('Invalid typedef Foo<T extends Foo<dynamic> = C<T>',
|
||||
(TestHarness test) {
|
||||
var param = new TypeParameter('T', null);
|
||||
var foo = new Typedef('Foo',
|
||||
new InterfaceType(test.otherClass, [new TypeParameterType(param)]),
|
||||
typeParameters: [param]);
|
||||
param.bound = new TypedefType(foo, [const DynamicType()]);
|
||||
test.enclosingLibrary.addTypedef(foo);
|
||||
});
|
||||
negativeTest('Typedef arity error', (TestHarness test) {
|
||||
var param = test.makeTypeParameter('T');
|
||||
var foo =
|
||||
new Typedef('Foo', test.otherClass.rawType, typeParameters: [param]);
|
||||
var field = new Field(new Name('field'), type: new TypedefType(foo, []));
|
||||
test.enclosingLibrary.addTypedef(foo);
|
||||
test.enclosingLibrary.addMember(field);
|
||||
});
|
||||
negativeTest('Dangling typedef reference', (TestHarness test) {
|
||||
var foo = new Typedef('Foo', test.otherClass.rawType, typeParameters: []);
|
||||
var field = new Field(new Name('field'), type: new TypedefType(foo, []));
|
||||
test.enclosingLibrary.addMember(field);
|
||||
});
|
||||
}
|
||||
|
||||
checkHasError(Program program) {
|
||||
|
|
|
@ -84,6 +84,20 @@ void Library::VisitChildren(Visitor* visitor) {
|
|||
}
|
||||
|
||||
|
||||
Typedef::~Typedef() {}
|
||||
|
||||
|
||||
void Typedef::AcceptTreeVisitor(TreeVisitor* visitor) {
|
||||
visitor->VisitTypedef(this);
|
||||
}
|
||||
|
||||
|
||||
void Typedef::VisitChildren(Visitor* visitor) {
|
||||
VisitList(&type_parameters(), visitor);
|
||||
type()->AcceptDartTypeVisitor(visitor);
|
||||
}
|
||||
|
||||
|
||||
Class::~Class() {}
|
||||
|
||||
|
||||
|
@ -1192,6 +1206,19 @@ void InterfaceType::VisitChildren(Visitor* visitor) {
|
|||
}
|
||||
|
||||
|
||||
TypedefType::~TypedefType() {}
|
||||
|
||||
|
||||
void TypedefType::AcceptDartTypeVisitor(DartTypeVisitor* visitor) {
|
||||
visitor->VisitTypedefType(this);
|
||||
}
|
||||
|
||||
|
||||
void TypedefType::VisitChildren(Visitor* visitor) {
|
||||
VisitList(&type_arguments(), visitor);
|
||||
}
|
||||
|
||||
|
||||
FunctionType::~FunctionType() {}
|
||||
|
||||
|
||||
|
|
|
@ -22,10 +22,12 @@
|
|||
M(InterfaceType) \
|
||||
M(FunctionType) \
|
||||
M(TypeParameterType) \
|
||||
M(VectorType)
|
||||
M(VectorType) \
|
||||
M(TypedefType)
|
||||
|
||||
#define KERNEL_TREE_NODES_DO(M) \
|
||||
M(Library) \
|
||||
M(Typedef) \
|
||||
M(Class) \
|
||||
M(NormalClass) \
|
||||
M(MixinClass) \
|
||||
|
@ -375,6 +377,7 @@ KERNEL_VISITORS_DO(DO)
|
|||
DEFINE_IS_OPERATION(TreeNode) \
|
||||
KERNEL_TREE_NODES_DO(DEFINE_IS_OPERATION)
|
||||
|
||||
class Typedef;
|
||||
class Class;
|
||||
class Constructor;
|
||||
class Field;
|
||||
|
@ -488,6 +491,7 @@ class Library : public LinkedNode {
|
|||
String* import_uri() { return import_uri_; }
|
||||
intptr_t source_uri_index() { return source_uri_index_; }
|
||||
String* name() { return name_; }
|
||||
List<Typedef>& typedefs() { return typedefs_; }
|
||||
List<Class>& classes() { return classes_; }
|
||||
List<Field>& fields() { return fields_; }
|
||||
List<Procedure>& procedures() { return procedures_; }
|
||||
|
@ -504,6 +508,7 @@ class Library : public LinkedNode {
|
|||
Ref<String> name_;
|
||||
Ref<String> import_uri_;
|
||||
intptr_t source_uri_index_;
|
||||
List<Typedef> typedefs_;
|
||||
List<Class> classes_;
|
||||
List<Field> fields_;
|
||||
List<Procedure> procedures_;
|
||||
|
@ -514,6 +519,40 @@ class Library : public LinkedNode {
|
|||
};
|
||||
|
||||
|
||||
class Typedef : public LinkedNode {
|
||||
public:
|
||||
Typedef* ReadFrom(Reader* reader);
|
||||
|
||||
virtual ~Typedef();
|
||||
|
||||
DEFINE_CASTING_OPERATIONS(Typedef);
|
||||
|
||||
virtual void AcceptTreeVisitor(TreeVisitor* visitor);
|
||||
virtual void VisitChildren(Visitor* visitor);
|
||||
|
||||
Library* parent() { return parent_; }
|
||||
String* name() { return name_; }
|
||||
intptr_t source_uri_index() { return source_uri_index_; }
|
||||
TokenPosition position() { return position_; }
|
||||
TypeParameterList& type_parameters() { return type_parameters_; }
|
||||
DartType* type() { return type_; }
|
||||
|
||||
protected:
|
||||
Typedef() : position_(TokenPosition::kNoSource) {}
|
||||
|
||||
private:
|
||||
template <typename T>
|
||||
friend class List;
|
||||
|
||||
Ref<Library> parent_;
|
||||
Ref<String> name_;
|
||||
intptr_t source_uri_index_;
|
||||
TokenPosition position_;
|
||||
TypeParameterList type_parameters_;
|
||||
Child<DartType> type_;
|
||||
};
|
||||
|
||||
|
||||
class Class : public LinkedNode {
|
||||
public:
|
||||
Class* ReadFrom(Reader* reader);
|
||||
|
@ -2755,6 +2794,32 @@ class InterfaceType : public DartType {
|
|||
};
|
||||
|
||||
|
||||
class TypedefType : public DartType {
|
||||
public:
|
||||
static TypedefType* ReadFrom(Reader* reader);
|
||||
|
||||
explicit TypedefType(CanonicalName* class_reference)
|
||||
: typedef_reference_(class_reference) {}
|
||||
virtual ~TypedefType();
|
||||
|
||||
DEFINE_CASTING_OPERATIONS(TypedefType);
|
||||
|
||||
virtual void AcceptDartTypeVisitor(DartTypeVisitor* visitor);
|
||||
virtual void VisitChildren(Visitor* visitor);
|
||||
|
||||
CanonicalName* typedef_reference() { return typedef_reference_; }
|
||||
List<DartType>& type_arguments() { return type_arguments_; }
|
||||
|
||||
private:
|
||||
TypedefType() {}
|
||||
|
||||
Ref<CanonicalName> typedef_reference_; // Typedef.
|
||||
List<DartType> type_arguments_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(TypedefType);
|
||||
};
|
||||
|
||||
|
||||
class FunctionType : public DartType {
|
||||
public:
|
||||
static FunctionType* ReadFrom(Reader* reader);
|
||||
|
@ -2899,6 +2964,8 @@ class Reference : public AllStatic {
|
|||
|
||||
static CanonicalName* ReadClassFrom(Reader* reader, bool allow_null = false);
|
||||
|
||||
static CanonicalName* ReadTypedefFrom(Reader* reader);
|
||||
|
||||
static String* ReadStringFrom(Reader* reader);
|
||||
};
|
||||
|
||||
|
@ -3148,6 +3215,9 @@ class DartTypeVisitor {
|
|||
VisitDefaultDartType(node);
|
||||
}
|
||||
virtual void VisitVectorType(VectorType* node) { VisitDefaultDartType(node); }
|
||||
virtual void VisitTypedefType(TypedefType* node) {
|
||||
VisitDefaultDartType(node);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
@ -3187,6 +3257,7 @@ class TreeVisitor : public ExpressionVisitor,
|
|||
virtual void VisitCatch(Catch* node) { VisitDefaultTreeNode(node); }
|
||||
virtual void VisitMapEntry(MapEntry* node) { VisitDefaultTreeNode(node); }
|
||||
virtual void VisitProgram(Program* node) { VisitDefaultTreeNode(node); }
|
||||
virtual void VisitTypedef(Typedef* node) { VisitDefaultTreeNode(node); }
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -215,6 +215,11 @@ Library* Library::ReadFrom(Reader* reader) {
|
|||
if (num_imports != 0) {
|
||||
FATAL("Deferred imports not implemented in VM");
|
||||
}
|
||||
int num_typedefs = reader->ReadUInt();
|
||||
typedefs().EnsureInitialized(num_typedefs);
|
||||
for (intptr_t i = 0; i < num_typedefs; i++) {
|
||||
typedefs().GetOrCreate<Typedef>(i, this)->ReadFrom(reader);
|
||||
}
|
||||
int num_classes = reader->ReadUInt();
|
||||
classes().EnsureInitialized(num_classes);
|
||||
for (intptr_t i = 0; i < num_classes; i++) {
|
||||
|
@ -230,6 +235,20 @@ Library* Library::ReadFrom(Reader* reader) {
|
|||
}
|
||||
|
||||
|
||||
Typedef* Typedef::ReadFrom(Reader* reader) {
|
||||
TRACE_READ_OFFSET();
|
||||
|
||||
canonical_name_ = reader->ReadCanonicalNameReference();
|
||||
position_ = reader->ReadPosition(false);
|
||||
name_ = Reference::ReadStringFrom(reader);
|
||||
source_uri_index_ = reader->ReadUInt();
|
||||
type_parameters_.ReadFrom(reader);
|
||||
type_ = DartType::ReadFrom(reader);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
Class* Class::ReadFrom(Reader* reader) {
|
||||
TRACE_READ_OFFSET();
|
||||
|
||||
|
@ -313,6 +332,20 @@ CanonicalName* Reference::ReadClassFrom(Reader* reader, bool allow_null) {
|
|||
}
|
||||
|
||||
|
||||
CanonicalName* Reference::ReadTypedefFrom(Reader* reader) {
|
||||
TRACE_READ_OFFSET();
|
||||
|
||||
CanonicalName* canonical_name = reader->ReadCanonicalNameReference();
|
||||
if (canonical_name == NULL) {
|
||||
FATAL("Expected a valid typedef reference, but got `null`");
|
||||
}
|
||||
|
||||
canonical_name->set_referenced(true);
|
||||
|
||||
return canonical_name;
|
||||
}
|
||||
|
||||
|
||||
String* Reference::ReadStringFrom(Reader* reader) {
|
||||
int index = reader->ReadUInt();
|
||||
return reader->helper()->program()->string_table().strings()[index];
|
||||
|
@ -1411,6 +1444,8 @@ DartType* DartType::ReadFrom(Reader* reader) {
|
|||
return TypeParameterType::ReadFrom(reader);
|
||||
case kVectorType:
|
||||
return VectorType::ReadFrom(reader);
|
||||
case kTypedefType:
|
||||
return TypedefType::ReadFrom(reader);
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
@ -1456,6 +1491,15 @@ InterfaceType* InterfaceType::ReadFrom(Reader* reader,
|
|||
}
|
||||
|
||||
|
||||
TypedefType* TypedefType::ReadFrom(Reader* reader) {
|
||||
TRACE_READ_OFFSET();
|
||||
CanonicalName* typedef_name = Reference::ReadTypedefFrom(reader);
|
||||
TypedefType* type = new TypedefType(typedef_name);
|
||||
type->type_arguments().ReadFromStatic<DartType>(reader);
|
||||
return type;
|
||||
}
|
||||
|
||||
|
||||
FunctionType* FunctionType::ReadFrom(Reader* reader) {
|
||||
TRACE_READ_OFFSET();
|
||||
FunctionType* type = new FunctionType();
|
||||
|
|
|
@ -105,6 +105,7 @@ enum Tag {
|
|||
kFunctionDeclaration = 79,
|
||||
kAsyncForInStatement = 80,
|
||||
|
||||
kTypedefType = 87,
|
||||
kVectorType = 88,
|
||||
kInvalidType = 90,
|
||||
kDynamicType = 91,
|
||||
|
|
Loading…
Reference in a new issue