Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(89)

Unified Diff: sdk/lib/_internal/compiler/implementation/dart_types.dart

Issue 141753002: Reapply "Implement new model for class members." and "Implement new model for interface members." (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Fix dart2dart bug. Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: sdk/lib/_internal/compiler/implementation/dart_types.dart
diff --git a/sdk/lib/_internal/compiler/implementation/dart_types.dart b/sdk/lib/_internal/compiler/implementation/dart_types.dart
index 5f14cc2ccd40144b62d26137bc1495141d9f6ecc..2698f8956fa5cfd8173b9083f810810620fa3e5d 100644
--- a/sdk/lib/_internal/compiler/implementation/dart_types.dart
+++ b/sdk/lib/_internal/compiler/implementation/dart_types.dart
@@ -121,6 +121,12 @@ abstract class DartType {
/// Is [: true :] if this type contains any type variables.
bool get containsTypeVariables => typeVariableOccurrence != null;
+ /// Returns a textual representation of this type as if it was the type
+ /// of a member named [name].
+ String getStringAsDeclared(String name) {
+ return new TypeDeclarationFormatter().format(this, name);
+ }
+
accept(DartTypeVisitor visitor, var argument);
void visitChildren(DartTypeVisitor visitor, var argument) {}
@@ -421,6 +427,9 @@ abstract class GenericType extends DartType {
&& typeArguments == other.typeArguments;
}
+ /// Returns `true` if the declaration of this type has type variables.
+ bool get isGeneric => !typeArguments.isEmpty;
+
bool get isRaw => typeArguments.isEmpty || identical(this, element.rawType);
GenericType asRaw() => element.rawType;
@@ -485,13 +494,14 @@ class InterfaceType extends GenericType {
* Finds the method, field or property named [name] declared or inherited
* on this interface type.
*/
- Member lookupMember(String name, {bool isSetter: false}) {
+ InterfaceTypeMember lookupMember(String name, {bool isSetter: false}) {
// Abstract field returned when setter was needed but only a getter was
// present and vice-versa.
- Member fallbackAbstractField;
+ InterfaceTypeMember fallbackAbstractField;
- Member createMember(ClassElement classElement,
- InterfaceType receiver, InterfaceType declarer) {
+ InterfaceTypeMember createMember(ClassElement classElement,
+ InterfaceType receiver,
+ InterfaceType declarer) {
Element member = classElement.implementation.lookupLocalMember(name);
if (member == null) return null;
if (member.isConstructor() || member.isPrefix()) return null;
@@ -503,7 +513,8 @@ class InterfaceType extends GenericType {
AbstractFieldElement abstractFieldElement = member;
if (fallbackAbstractField == null) {
fallbackAbstractField =
- new Member(receiver, declarer, member, isSetter: isSetter);
+ new InterfaceTypeMember(receiver, declarer, member,
+ isSetter: isSetter);
}
if (isSetter && abstractFieldElement.setter == null) {
// Keep searching further up the hierarchy.
@@ -514,7 +525,9 @@ class InterfaceType extends GenericType {
}
}
return member != null
- ? new Member(receiver, declarer, member, isSetter: isSetter) : null;
+ ? new InterfaceTypeMember(receiver, declarer, member,
+ isSetter: isSetter)
+ : null;
}
ClassElement classElement = element;
@@ -522,7 +535,7 @@ class InterfaceType extends GenericType {
InterfaceType declarer = receiver;
// TODO(johnniwinther): Lookup and callers should handle private members and
// injected members.
- Member member = createMember(classElement, receiver, declarer);
+ InterfaceTypeMember member = createMember(classElement, receiver, declarer);
if (member != null) return member;
assert(invariant(element, classElement.allSupertypes != null,
@@ -533,7 +546,8 @@ class InterfaceType extends GenericType {
if (supertype.element.isMixinApplication) continue;
declarer = supertype;
ClassElement lookupTarget = declarer.element;
- Member member = createMember(lookupTarget, receiver, declarer);
+ InterfaceTypeMember member =
+ createMember(lookupTarget, receiver, declarer);
if (member != null) return member;
}
@@ -605,10 +619,10 @@ class FunctionType extends DartType {
FunctionType(Element this.element,
DartType this.returnType,
- Link<DartType> this.parameterTypes,
- Link<DartType> this.optionalParameterTypes,
- Link<String> this.namedParameters,
- Link<DartType> this.namedParameterTypes) {
+ [this.parameterTypes = const Link<DartType>(),
+ this.optionalParameterTypes = const Link<DartType>(),
+ this.namedParameters = const Link<String>(),
+ this.namedParameterTypes = const Link<DartType>()]) {
assert(invariant(element, element.isDeclaration));
// Assert that optional and named parameters are not used at the same time.
assert(optionalParameterTypes.isEmpty || namedParameterTypes.isEmpty);
@@ -833,37 +847,38 @@ class DynamicType extends InterfaceType {
}
/**
- * Member encapsulates a member (method, field, property) with the types of the
- * declarer and receiver in order to do substitution on the member type.
+ * [InterfaceTypeMember] encapsulates a member (method, field, property) with
+ * the types of the declarer and receiver in order to do substitution on the
+ * member type.
*
- * Consider for instance these classes and the variable [: B<String> b :]:
+ * Consider for instance these classes and the variable `B<String> b`:
*
* class A<E> {
* E field;
* }
* class B<F> extends A<F> {}
*
- * In a [Member] for [: b.field :] the [receiver] is the type [: B<String> :]
- * and the declarer is the type [: A<F> :], which is the supertype of [: B<F> :]
- * from which [: field :] has been inherited. To compute the type of
- * [: b.field :] we must first substitute [: E :] by [: F :] using the relation
- * between [: A<E> :] and [: A<F> :], and then [: F :] by [: String :] using the
- * relation between [: B<F> :] and [: B<String> :].
+ * In an [InterfaceTypeMember] for `b.field` the [receiver] is the type
+ * `B<String>` and the declarer is the type `A<F>`, which is the supertype of
+ * `B<F>` from which `field` has been inherited. To compute the type of
+ * `b.field` we must first substitute `E` by `F` using the relation between
+ * `A<E>` and `A<F>`, and then `F` by `String` using the relation between
+ * `B<F>` and `B<String>`.
*/
// TODO(johnniwinther): Add [isReadable] and [isWritable] predicates.
-class Member {
+class InterfaceTypeMember {
final InterfaceType receiver;
final InterfaceType declarer;
final Element element;
DartType cachedType;
final bool isSetter;
- Member(this.receiver, this.declarer, this.element,
+ InterfaceTypeMember(this.receiver, this.declarer, this.element,
{bool this.isSetter: false}) {
assert(invariant(element, element.isAbstractField() ||
- element.isField() ||
- element.isFunction(),
- message: "Unsupported Member element: $element"));
+ element.isField() ||
+ element.isFunction(),
+ message: "Unsupported InterfaceTypeMember element: $element"));
}
DartType computeType(Compiler compiler) {
@@ -1204,7 +1219,7 @@ class SubtypeVisitor extends MoreSpecificVisitor {
lookupCall(t) != null) {
return true;
} else if (s is FunctionType) {
- Member call = lookupCall(t);
+ InterfaceTypeMember call = lookupCall(t);
if (call == null) return false;
return isSubtype(call.computeType(compiler), s);
}
@@ -1757,4 +1772,116 @@ class MoreSpecificSubtypeVisitor extends DartTypeVisitor<bool, DartType> {
}
return false;
}
-}
+}
+
+/// Visitor used to print type annotation like they used in the source code.
+/// The visitor is especially for printing a function type like
+/// `(Foo,[Bar])->Baz` as `Baz m(Foo a1, [Bar a2])`.
+class TypeDeclarationFormatter extends DartTypeVisitor<dynamic, String> {
+ Set<String> usedNames;
+ StringBuffer sb;
+
+ /// Creates textual representation of [type] as if a member by the [name] were
+ /// declared. For instance 'String foo' for `format(String, 'foo')`.
+ String format(DartType type, String name) {
+ sb = new StringBuffer();
+ usedNames = new Set<String>();
+ type.accept(this, name);
+ usedNames = null;
+ return sb.toString();
+ }
+
+ String createName(String name) {
+ if (name != null && !usedNames.contains(name)) {
+ usedNames.add(name);
+ return name;
+ }
+ int index = usedNames.length;
+ String proposal;
+ do {
+ proposal = '${name}${index++}';
+ } while (usedNames.contains(proposal));
+ usedNames.add(proposal);
+ return proposal;
+ }
+
+ void visit(DartType type) {
+ type.accept(this, null);
+ }
+
+ void visitTypes(Link<DartType> types, String prefix) {
+ bool needsComma = false;
+ for (Link<DartType> link = types;
+ !link.isEmpty;
+ link = link.tail) {
+ if (needsComma) {
+ sb.write(', ');
+ }
+ link.head.accept(this, prefix);
+ needsComma = true;
+ } }
+
+ void visitType(DartType type, String name) {
+ if (name == null) {
+ sb.write(type);
+ } else {
+ sb.write('$type ${createName(name)}');
+ }
+ }
+
+ void visitGenericType(GenericType type, String name) {
+ sb.write(type.name);
+ if (!type.treatAsRaw) {
+ sb.write('<');
+ visitTypes(type.typeArguments, null);
+ sb.write('>');
+ }
+ if (name != null) {
+ sb.write(' ');
+ sb.write(createName(name));
+ }
+ }
+
+ void visitFunctionType(FunctionType type, String name) {
+ visit(type.returnType);
+ sb.write(' ');
+ if (name != null) {
+ sb.write(name);
+ } else {
+ sb.write(createName('f'));
+ }
+ sb.write('(');
+ visitTypes(type.parameterTypes, 'a');
+ bool needsComma = !type.parameterTypes.isEmpty;
+ if (!type.optionalParameterTypes.isEmpty) {
+ if (needsComma) {
+ sb.write(', ');
+ }
+ sb.write('[');
+ visitTypes(type.optionalParameterTypes, 'a');
+ sb.write(']');
+ needsComma = true;
+ }
+ if (!type.namedParameterTypes.isEmpty) {
+ if (needsComma) {
+ sb.write(', ');
+ }
+ sb.write('{');
+ Link<String> namedParameter = type.namedParameters;
+ Link<DartType> namedParameterType = type.namedParameterTypes;
+ needsComma = false;
+ while (!namedParameter.isEmpty && !namedParameterType.isEmpty) {
+ if (needsComma) {
+ sb.write(', ');
+ }
+ namedParameterType.head.accept(this, namedParameter.head);
+ namedParameter = namedParameter.tail;
+ namedParameterType = namedParameterType.tail;
+ needsComma = true;
+ }
+ sb.write('}');
+ }
+ sb.write(')');
+ }
+}
+

Powered by Google App Engine
This is Rietveld 408576698