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

Unified Diff: pkg/analyzer/lib/src/generated/element.dart

Issue 137863002: Issue 8742. Preserve leading line comments during java2dart translation. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Test for block-style comment translation. 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
« no previous file with comments | « pkg/analyzer/lib/src/generated/constant.dart ('k') | pkg/analyzer/lib/src/generated/engine.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/analyzer/lib/src/generated/element.dart
diff --git a/pkg/analyzer/lib/src/generated/element.dart b/pkg/analyzer/lib/src/generated/element.dart
index 6aa2113869235fbec4cbc324274e3dcb40c9d1b5..92c67cd3212320c5016c893121d1031549c19c7f 100644
--- a/pkg/analyzer/lib/src/generated/element.dart
+++ b/pkg/analyzer/lib/src/generated/element.dart
@@ -1989,13 +1989,29 @@ class AngularPropertyKind extends Enum<AngularPropertyKind> {
* `<=>` - Treat the DOM attribute value as an expression. Set up a watch on both outside as well
* as component scope to keep the source and destination in sync. (cost: 2 watches)
*/
- static final AngularPropertyKind TWO_WAY = new AngularPropertyKind('TWO_WAY', 4);
+ static final AngularPropertyKind TWO_WAY = new AngularPropertyKind_TWO_WAY('TWO_WAY', 4);
static final List<AngularPropertyKind> values = [ATTR, CALLBACK, ONE_WAY, ONE_WAY_ONE_TIME, TWO_WAY];
+ /**
+ * Returns `true` if property of this kind calls field getter.
+ */
+ bool callsGetter() => false;
+
+ /**
+ * Returns `true` if property of this kind calls field setter.
+ */
+ bool callsSetter() => true;
+
AngularPropertyKind(String name, int ordinal) : super(name, ordinal);
}
+class AngularPropertyKind_TWO_WAY extends AngularPropertyKind {
+ AngularPropertyKind_TWO_WAY(String name, int ordinal) : super(name, ordinal);
+
+ bool callsGetter() => true;
+}
+
/**
* [AngularSelectorElement] is used to decide when Angular object should be applied.
*
@@ -2495,6 +2511,10 @@ class ClassElementImpl extends ElementImpl implements ClassElement {
}
ElementImpl getChild(String identifier) {
+ //
+ // The casts in this method are safe because the set methods would have thrown a CCE if any of
+ // the elements in the arrays were not of the expected types.
+ //
for (PropertyAccessorElement accessor in _accessors) {
if ((accessor as PropertyAccessorElementImpl).identifier == identifier) {
return accessor as PropertyAccessorElementImpl;
@@ -2571,6 +2591,8 @@ class ClassElementImpl extends ElementImpl implements ClassElement {
ClassDeclaration get node => getNode2(ClassDeclaration);
PropertyAccessorElement getSetter(String setterName) {
+ // TODO (jwren) revisit- should we append '=' here or require clients to include it?
+ // Do we need the check for isSetter below?
if (!setterName.endsWith("=")) {
setterName += '=';
}
@@ -2603,15 +2625,18 @@ class ClassElementImpl extends ElementImpl implements ClassElement {
while (!classesToVisit.isEmpty) {
ClassElement currentElement = classesToVisit.removeAt(0);
if (visitedClasses.add(currentElement)) {
+ // check fields
for (FieldElement field in currentElement.fields) {
if (!field.isFinal && !field.isConst && !field.isStatic && !field.isSynthetic) {
return true;
}
}
+ // check mixins
for (InterfaceType mixinType in currentElement.mixins) {
ClassElement mixinElement = mixinType.element;
classesToVisit.add(mixinElement);
}
+ // check super
InterfaceType supertype = currentElement.supertype;
if (supertype != null) {
ClassElement superElement = supertype.element;
@@ -2621,6 +2646,7 @@ class ClassElementImpl extends ElementImpl implements ClassElement {
}
}
}
+ // not found
return false;
}
@@ -2958,6 +2984,10 @@ class CompilationUnitElementImpl extends ElementImpl implements CompilationUnitE
List<PropertyAccessorElement> get accessors => _accessors;
ElementImpl getChild(String identifier) {
+ //
+ // The casts in this method are safe because the set methods would have thrown a CCE if any of
+ // the elements in the arrays were not of the expected types.
+ //
for (PropertyAccessorElement accessor in _accessors) {
if ((accessor as PropertyAccessorElementImpl).identifier == identifier) {
return accessor as PropertyAccessorElementImpl;
@@ -3227,15 +3257,18 @@ class ConstructorElementImpl extends ExecutableElementImpl implements Constructo
bool get isConst => hasModifier(Modifier.CONST);
bool get isDefaultConstructor {
+ // unnamed
String name = this.name;
if (name != null && name.length != 0) {
return false;
}
+ // no required parameters
for (ParameterElement parameter in parameters) {
if (identical(parameter.parameterKind, ParameterKind.REQUIRED)) {
return false;
}
}
+ // OK, can be used as default constructor
return true;
}
@@ -3567,6 +3600,8 @@ abstract class ElementImpl implements Element {
CompilationUnit get unit => context.resolveCompilationUnit(source, library);
int get hashCode {
+ // TODO: We might want to re-visit this optimization in the future.
+ // We cache the hash code value as this is a very frequently called method.
if (_cachedHashCode == 0) {
_cachedHashCode = location.hashCode;
}
@@ -3884,6 +3919,7 @@ class ElementLocationImpl implements ElementLocation {
* @return `true` if the given components are equal when the source type's are ignored
*/
bool equalSourceComponents(String left, String right) {
+ // TODO(brianwilkerson) This method can go away when sources no longer have a URI kind.
if (left == null) {
return right == null;
} else if (right == null) {
@@ -3906,6 +3942,7 @@ class ElementLocationImpl implements ElementLocation {
* @return the hash code of the given encoded source component
*/
int hashSourceComponent(String sourceComponent) {
+ // TODO(brianwilkerson) This method can go away when sources no longer have a URI kind.
if (sourceComponent.length <= 1) {
return sourceComponent.hashCode;
}
@@ -4812,19 +4849,23 @@ class LibraryElementImpl extends ElementImpl implements LibraryElement {
static bool isUpToDate(LibraryElement library, int timeStamp, Set<LibraryElement> visitedLibraries) {
if (!visitedLibraries.contains(library)) {
visitedLibraries.add(library);
+ // Check the defining compilation unit.
if (timeStamp < library.definingCompilationUnit.source.modificationStamp) {
return false;
}
+ // Check the parted compilation units.
for (CompilationUnitElement element in library.parts) {
if (timeStamp < element.source.modificationStamp) {
return false;
}
}
+ // Check the imported libraries.
for (LibraryElement importedLibrary in library.importedLibraries) {
if (!isUpToDate(importedLibrary, timeStamp, visitedLibraries)) {
return false;
}
}
+ // Check the exported libraries.
for (LibraryElement exportedLibrary in library.exportedLibraries) {
if (!isUpToDate(exportedLibrary, timeStamp, visitedLibraries)) {
return false;
@@ -5049,15 +5090,18 @@ class LibraryElementImpl extends ElementImpl implements LibraryElement {
* Recursively fills set of visible libraries for [getVisibleElementsLibraries].
*/
void addVisibleLibraries(Set<LibraryElement> visibleLibraries, bool includeExports) {
+ // maybe already processed
if (!visibleLibraries.add(this)) {
return;
}
+ // add imported libraries
for (ImportElement importElement in _imports) {
LibraryElement importedLibrary = importElement.importedLibrary;
if (importedLibrary != null) {
(importedLibrary as LibraryElementImpl).addVisibleLibraries(visibleLibraries, true);
}
}
+ // add exported libraries
if (includeExports) {
for (ExportElement exportElement in _exports) {
LibraryElement exportedLibrary = exportElement.exportedLibrary;
@@ -6487,6 +6531,7 @@ class ConstructorMember extends ExecutableMember implements ConstructorElement {
}
FunctionType baseType = baseConstructor.type;
if (baseType == null) {
+ // TODO(brianwilkerson) We need to understand when this can happen.
return baseConstructor;
}
List<Type2> argumentTypes = definingType.typeArguments;
@@ -6495,6 +6540,8 @@ class ConstructorMember extends ExecutableMember implements ConstructorElement {
if (baseType == substitutedType) {
return baseConstructor;
}
+ // TODO(brianwilkerson) Consider caching the substituted type in the instance. It would use more
+ // memory but speed up some operations. We need to see how often the type is being re-computed.
return new ConstructorMember(baseConstructor, definingType);
}
@@ -6570,12 +6617,18 @@ abstract class ExecutableMember extends Member implements ExecutableElement {
ExecutableElement get baseElement => super.baseElement as ExecutableElement;
List<FunctionElement> get functions {
+ //
+ // Elements within this element should have type parameters substituted, just like this element.
+ //
throw new UnsupportedOperationException();
}
List<LabelElement> get labels => baseElement.labels;
List<LocalVariableElement> get localVariables {
+ //
+ // Elements within this element should have type parameters substituted, just like this element.
+ //
throw new UnsupportedOperationException();
}
@@ -6601,6 +6654,8 @@ abstract class ExecutableMember extends Member implements ExecutableElement {
bool get isStatic => baseElement.isStatic;
void visitChildren(ElementVisitor visitor) {
+ // TODO(brianwilkerson) We need to finish implementing the accessors used below so that we can
+ // safely invoke them.
super.visitChildren(visitor);
safelyVisitChildren(baseElement.functions, visitor);
safelyVisitChildren(labels, visitor);
@@ -6657,6 +6712,8 @@ class FieldMember extends VariableMember implements FieldElement {
if (baseType == substitutedType) {
return baseField;
}
+ // TODO(brianwilkerson) Consider caching the substituted type in the instance. It would use more
+ // memory but speed up some operations. We need to see how often the type is being re-computed.
return new FieldMember(baseField, definingType);
}
@@ -6845,6 +6902,8 @@ class MethodMember extends ExecutableMember implements MethodElement {
if (baseType == substitutedType) {
return baseMethod;
}
+ // TODO(brianwilkerson) Consider caching the substituted type in the instance. It would use more
+ // memory but speed up some operations. We need to see how often the type is being re-computed.
return new MethodMember(baseMethod, definingType);
}
@@ -6911,6 +6970,8 @@ class ParameterMember extends VariableMember implements ParameterElement {
if (baseParameter == null || definingType.typeArguments.length == 0) {
return baseParameter;
}
+ // Check if parameter type depends on defining type type arguments.
+ // It is possible that we did not resolve field formal parameter yet, so skip this check for it.
bool isFieldFormal = baseParameter is FieldFormalParameterElement;
if (!isFieldFormal) {
Type2 baseType = baseParameter.type;
@@ -6921,6 +6982,8 @@ class ParameterMember extends VariableMember implements ParameterElement {
return baseParameter;
}
}
+ // TODO(brianwilkerson) Consider caching the substituted type in the instance. It would use more
+ // memory but speed up some operations. We need to see how often the type is being re-computed.
if (isFieldFormal) {
return new FieldFormalParameterMember(baseParameter as FieldFormalParameterElement, definingType);
}
@@ -7034,6 +7097,8 @@ class PropertyAccessorMember extends ExecutableMember implements PropertyAccesso
if (baseType == substitutedType) {
return baseAccessor;
}
+ // TODO(brianwilkerson) Consider caching the substituted type in the instance. It would use more
+ // memory but speed up some operations. We need to see how often the type is being re-computed.
return new PropertyAccessorMember(baseAccessor, definingType);
}
@@ -7120,6 +7185,9 @@ abstract class VariableMember extends Member implements VariableElement {
VariableElement get baseElement => super.baseElement as VariableElement;
FunctionElement get initializer {
+ //
+ // Elements within this element should have type parameters substituted, just like this element.
+ //
throw new UnsupportedOperationException();
}
@@ -7132,6 +7200,8 @@ abstract class VariableMember extends Member implements VariableElement {
bool get isFinal => baseElement.isFinal;
void visitChildren(ElementVisitor visitor) {
+ // TODO(brianwilkerson) We need to finish implementing the accessors used below so that we can
+ // safely invoke them.
super.visitChildren(visitor);
safelyVisitChild(baseElement.initializer, visitor);
}
@@ -7223,9 +7293,11 @@ class DynamicTypeImpl extends TypeImpl {
bool internalEquals(Object object, Set<ElementPair> visitedElementPairs) => identical(object, this);
bool internalIsMoreSpecificThan(Type2 type, bool withDynamic, Set<TypeImpl_TypePair> visitedTypePairs) {
+ // T is S
if (identical(this, type)) {
return true;
}
+ // else
return withDynamic;
}
@@ -7292,6 +7364,7 @@ class FunctionTypeImpl extends TypeImpl implements FunctionType {
String get displayName {
String name = this.name;
if (name == null || name.length == 0) {
+ // TODO(brianwilkerson) Determine whether function types should ever have an empty name.
List<Type2> normalParameterTypes = this.normalParameterTypes;
List<Type2> optionalParameterTypes = this.optionalParameterTypes;
Map<String, Type2> namedParameterTypes = this.namedParameterTypes;
@@ -7404,10 +7477,12 @@ class FunctionTypeImpl extends TypeImpl implements FunctionType {
List<ParameterElement> get parameters {
List<ParameterElement> baseParameters = this.baseParameters;
+ // no parameters, quick return
int parameterCount = baseParameters.length;
if (parameterCount == 0) {
return baseParameters;
}
+ // create specialized parameters
List<ParameterElement> specializedParameters = new List<ParameterElement>(parameterCount);
for (int i = 0; i < parameterCount; i++) {
specializedParameters[i] = ParameterMember.from(baseParameters[i], this);
@@ -7418,6 +7493,8 @@ class FunctionTypeImpl extends TypeImpl implements FunctionType {
Type2 get returnType {
Type2 baseReturnType = this.baseReturnType;
if (baseReturnType == null) {
+ // TODO(brianwilkerson) This is a patch. The return type should never be null and we need to
+ // understand why it is and fix it.
return DynamicTypeImpl.instance;
}
return baseReturnType.substitute2(typeArguments, TypeParameterTypeImpl.getTypes(typeParameters));
@@ -7439,9 +7516,11 @@ class FunctionTypeImpl extends TypeImpl implements FunctionType {
if (element == null) {
return 0;
}
+ // Reference the arrays of parameters
List<Type2> normalParameterTypes = this.normalParameterTypes;
List<Type2> optionalParameterTypes = this.optionalParameterTypes;
Iterable<Type2> namedParameterTypes = this.namedParameterTypes.values;
+ // Generate the hashCode
int hashCode = returnType.hashCode;
for (int i = 0; i < normalParameterTypes.length; i++) {
hashCode = (hashCode << 1) + normalParameterTypes[i].hashCode;
@@ -7456,6 +7535,7 @@ class FunctionTypeImpl extends TypeImpl implements FunctionType {
}
bool internalIsMoreSpecificThan(Type2 type, bool withDynamic, Set<TypeImpl_TypePair> visitedTypePairs) {
+ // trivial base cases
if (type == null) {
return false;
} else if (identical(this, type) || type.isDynamic || type.isDartCoreFunction || type.isObject) {
@@ -7471,10 +7551,14 @@ class FunctionTypeImpl extends TypeImpl implements FunctionType {
List<Type2> tOpTypes = t.optionalParameterTypes;
List<Type2> sTypes = s.normalParameterTypes;
List<Type2> sOpTypes = s.optionalParameterTypes;
+ // If one function has positional and the other has named parameters, return false.
if ((sOpTypes.length > 0 && t.namedParameterTypes.length > 0) || (tOpTypes.length > 0 && s.namedParameterTypes.length > 0)) {
return false;
}
+ // named parameters case
if (t.namedParameterTypes.length > 0) {
+ // check that the number of required parameters are equal, and check that every t_i is
+ // more specific than every s_i
if (t.normalParameterTypes.length != s.normalParameterTypes.length) {
return false;
} else if (t.normalParameterTypes.length > 0) {
@@ -7486,9 +7570,12 @@ class FunctionTypeImpl extends TypeImpl implements FunctionType {
}
Map<String, Type2> namedTypesT = t.namedParameterTypes;
Map<String, Type2> namedTypesS = s.namedParameterTypes;
+ // if k >= m is false, return false: the passed function type has more named parameter types than this
if (namedTypesT.length < namedTypesS.length) {
return false;
}
+ // Loop through each element in S verifying that T has a matching parameter name and that the
+ // corresponding type is more specific then the type in S.
JavaIterator<MapEntry<String, Type2>> iteratorS = new JavaIterator(getMapEntrySet(namedTypesS));
while (iteratorS.hasNext) {
MapEntry<String, Type2> entryS = iteratorS.next();
@@ -7503,18 +7590,25 @@ class FunctionTypeImpl extends TypeImpl implements FunctionType {
} else if (s.namedParameterTypes.length > 0) {
return false;
} else {
+ // positional parameter case
int tArgLength = tTypes.length + tOpTypes.length;
int sArgLength = sTypes.length + sOpTypes.length;
+ // Check that the total number of parameters in t is greater than or equal to the number of
+ // parameters in s and that the number of required parameters in s is greater than or equal to
+ // the number of required parameters in t.
if (tArgLength < sArgLength || sTypes.length < tTypes.length) {
return false;
}
if (tOpTypes.length == 0 && sOpTypes.length == 0) {
+ // No positional arguments, don't copy contents to new array
for (int i = 0; i < sTypes.length; i++) {
if (!(tTypes[i] as TypeImpl).isMoreSpecificThan3(sTypes[i], withDynamic, visitedTypePairs)) {
return false;
}
}
} else {
+ // Else, we do have positional parameters, copy required and positional parameter types into
+ // arrays to do the compare (for loop below).
List<Type2> tAllTypes = new List<Type2>(sArgLength);
for (int i = 0; i < tTypes.length; i++) {
tAllTypes[i] = tTypes[i];
@@ -7637,16 +7731,21 @@ class FunctionTypeImpl extends TypeImpl implements FunctionType {
return false;
}
FunctionTypeImpl otherType = object as FunctionTypeImpl;
+ // If the visitedTypePairs already has the pair (this, type), use the elements to determine equality
ElementPair elementPair = new ElementPair(element, otherType.element);
if (!visitedElementPairs.add(elementPair)) {
return elementPair.firstElt == elementPair.secondElt;
}
+ // Compute the result
bool result = TypeImpl.equalArrays(normalParameterTypes, otherType.normalParameterTypes, visitedElementPairs) && TypeImpl.equalArrays(optionalParameterTypes, otherType.optionalParameterTypes, visitedElementPairs) && equals2(namedParameterTypes, otherType.namedParameterTypes, visitedElementPairs) && (returnType as TypeImpl).internalEquals(otherType.returnType, visitedElementPairs);
+ // Remove the pair from our visited pairs list
visitedElementPairs.remove(elementPair);
+ // Return the result
return result;
}
bool internalIsSubtypeOf(Type2 type, Set<TypeImpl_TypePair> visitedTypePairs) {
+ // trivial base cases
if (type == null) {
return false;
} else if (identical(this, type) || type.isDynamic || type.isDartCoreFunction || type.isObject) {
@@ -7662,10 +7761,14 @@ class FunctionTypeImpl extends TypeImpl implements FunctionType {
List<Type2> tOpTypes = t.optionalParameterTypes;
List<Type2> sTypes = s.normalParameterTypes;
List<Type2> sOpTypes = s.optionalParameterTypes;
+ // If one function has positional and the other has named parameters, return false.
if ((sOpTypes.length > 0 && t.namedParameterTypes.length > 0) || (tOpTypes.length > 0 && s.namedParameterTypes.length > 0)) {
return false;
}
+ // named parameters case
if (t.namedParameterTypes.length > 0) {
+ // check that the number of required parameters are equal, and check that every t_i is
+ // assignable to every s_i
if (t.normalParameterTypes.length != s.normalParameterTypes.length) {
return false;
} else if (t.normalParameterTypes.length > 0) {
@@ -7677,9 +7780,12 @@ class FunctionTypeImpl extends TypeImpl implements FunctionType {
}
Map<String, Type2> namedTypesT = t.namedParameterTypes;
Map<String, Type2> namedTypesS = s.namedParameterTypes;
+ // if k >= m is false, return false: the passed function type has more named parameter types than this
if (namedTypesT.length < namedTypesS.length) {
return false;
}
+ // Loop through each element in S verifying that T has a matching parameter name and that the
+ // corresponding type is assignable to the type in S.
JavaIterator<MapEntry<String, Type2>> iteratorS = new JavaIterator(getMapEntrySet(namedTypesS));
while (iteratorS.hasNext) {
MapEntry<String, Type2> entryS = iteratorS.next();
@@ -7694,18 +7800,25 @@ class FunctionTypeImpl extends TypeImpl implements FunctionType {
} else if (s.namedParameterTypes.length > 0) {
return false;
} else {
+ // positional parameter case
int tArgLength = tTypes.length + tOpTypes.length;
int sArgLength = sTypes.length + sOpTypes.length;
+ // Check that the total number of parameters in t is greater than or equal to the number of
+ // parameters in s and that the number of required parameters in s is greater than or equal to
+ // the number of required parameters in t.
if (tArgLength < sArgLength || sTypes.length < tTypes.length) {
return false;
}
if (tOpTypes.length == 0 && sOpTypes.length == 0) {
+ // No positional arguments, don't copy contents to new array
for (int i = 0; i < sTypes.length; i++) {
if (!(tTypes[i] as TypeImpl).isAssignableTo2(sTypes[i], visitedTypePairs)) {
return false;
}
}
} else {
+ // Else, we do have positional parameters, copy required and positional parameter types into
+ // arrays to do the compare (for loop below).
List<Type2> tAllTypes = new List<Type2>(sArgLength);
for (int i = 0; i < tTypes.length; i++) {
tAllTypes[i] = tTypes[i];
@@ -7794,6 +7907,7 @@ class InterfaceTypeImpl extends TypeImpl implements InterfaceType {
*/
static int computeLongestInheritancePathToObject2(InterfaceType type, int depth, Set<ClassElement> visitedClasses) {
ClassElement classElement = type.element;
+ // Object case
if (classElement.supertype == null || visitedClasses.contains(classElement)) {
return depth;
}
@@ -7803,6 +7917,8 @@ class InterfaceTypeImpl extends TypeImpl implements InterfaceType {
List<InterfaceType> superinterfaces = classElement.interfaces;
int pathLength;
if (superinterfaces.length > 0) {
+ // loop through each of the superinterfaces recursively calling this method and keeping track
+ // of the longest path to return
for (InterfaceType superinterface in superinterfaces) {
pathLength = computeLongestInheritancePathToObject2(superinterface, depth + 1, visitedClasses);
if (pathLength > longestPath) {
@@ -7810,6 +7926,8 @@ class InterfaceTypeImpl extends TypeImpl implements InterfaceType {
}
}
}
+ // finally, perform this same check on the super type
+ // TODO(brianwilkerson) Does this also need to add in the number of mixin classes?
InterfaceType supertype = classElement.supertype;
pathLength = computeLongestInheritancePathToObject2(supertype, depth + 1, visitedClasses);
if (pathLength > longestPath) {
@@ -7899,6 +8017,10 @@ class InterfaceTypeImpl extends TypeImpl implements InterfaceType {
}
List<Type2> lubArguments = new List<Type2>(argumentCount);
for (int i = 0; i < argumentCount; i++) {
+ //
+ // Ideally we would take the least upper bound of the two argument types, but this can cause
+ // an infinite recursion (such as when finding the least upper bound of String and num).
+ //
if (firstArguments[i] == secondArguments[i]) {
lubArguments[i] = firstArguments[i];
}
@@ -7952,6 +8074,7 @@ class InterfaceTypeImpl extends TypeImpl implements InterfaceType {
break;
}
}
+ // If there is at least one non-dynamic type, then list them out
if (!allDynamic) {
JavaStringBuilder builder = new JavaStringBuilder();
builder.append(name);
@@ -7990,23 +8113,31 @@ class InterfaceTypeImpl extends TypeImpl implements InterfaceType {
}
Type2 getLeastUpperBound(Type2 type) {
+ // quick check for self
if (identical(type, this)) {
return this;
}
+ // dynamic
Type2 dynamicType = DynamicTypeImpl.instance;
if (identical(this, dynamicType) || identical(type, dynamicType)) {
return dynamicType;
}
+ // TODO (jwren) opportunity here for a better, faster algorithm if this turns out to be a bottle-neck
if (type is! InterfaceType) {
return null;
}
+ // new names to match up with the spec
InterfaceType i = this;
InterfaceType j = type as InterfaceType;
+ // compute set of supertypes
Set<InterfaceType> si = computeSuperinterfaceSet(i);
Set<InterfaceType> sj = computeSuperinterfaceSet(j);
+ // union si with i and sj with j
si.add(i);
sj.add(j);
+ // compute intersection, reference as set 's'
List<InterfaceType> s = intersection(si, sj);
+ // for each element in Set s, compute the largest inheritance path to Object
List<int> depths = new List<int>.filled(s.length, 0);
int maxDepth = 0;
for (int n = 0; n < s.length; n++) {
@@ -8015,6 +8146,8 @@ class InterfaceTypeImpl extends TypeImpl implements InterfaceType {
maxDepth = depths[n];
}
}
+ // ensure that the currently computed maxDepth is unique,
+ // otherwise, decrement and test for uniqueness again
for (; maxDepth >= 0; maxDepth--) {
int indexOfLeastUpperBound = -1;
int numberOfTypesAtMaxDepth = 0;
@@ -8028,6 +8161,9 @@ class InterfaceTypeImpl extends TypeImpl implements InterfaceType {
return s[indexOfLeastUpperBound];
}
}
+ // illegal state, log and return null- Object at maxDepth == 0 should always return itself as
+ // the least upper bound.
+ // TODO (jwren) log the error state
return null;
}
@@ -8092,42 +8228,62 @@ class InterfaceTypeImpl extends TypeImpl implements InterfaceType {
InterfaceType j = type;
ClassElement jElement = j.element;
InterfaceType supertype = jElement.supertype;
+ //
+ // If J has no direct supertype then it is Object, and Object has no direct supertypes.
+ //
if (supertype == null) {
return false;
}
+ //
+ // I is listed in the extends clause of J.
+ //
List<Type2> jArgs = j.typeArguments;
List<Type2> jVars = jElement.type.typeArguments;
supertype = supertype.substitute2(jArgs, jVars);
if (supertype == i) {
return true;
}
+ //
+ // I is listed in the implements clause of J.
+ //
for (InterfaceType interfaceType in jElement.interfaces) {
interfaceType = interfaceType.substitute2(jArgs, jVars);
if (interfaceType == i) {
return true;
}
}
+ //
+ // I is listed in the with clause of J.
+ //
for (InterfaceType mixinType in jElement.mixins) {
mixinType = mixinType.substitute2(jArgs, jVars);
if (mixinType == i) {
return true;
}
}
+ //
+ // J is a mixin application of the mixin of I.
+ //
+ // TODO(brianwilkerson) Determine whether this needs to be implemented or whether it is covered
+ // by the case above.
return false;
}
bool get isObject => element.supertype == null;
ConstructorElement lookUpConstructor(String constructorName, LibraryElement library) {
+ // prepare base ConstructorElement
ConstructorElement constructorElement;
if (constructorName == null) {
constructorElement = element.unnamedConstructor;
} else {
constructorElement = element.getNamedConstructor(constructorName);
}
+ // not found or not accessible
if (constructorElement == null || !constructorElement.isAccessibleIn(library)) {
return null;
}
+ // return member
return ConstructorMember.from(constructorElement, this);
}
@@ -8281,6 +8437,11 @@ class InterfaceTypeImpl extends TypeImpl implements InterfaceType {
}
bool internalIsMoreSpecificThan(Type2 type, bool withDynamic, Set<TypeImpl_TypePair> visitedTypePairs) {
+ //
+ // S is dynamic.
+ // The test to determine whether S is dynamic is done here because dynamic is not an instance of
+ // InterfaceType.
+ //
if (identical(type, DynamicTypeImpl.instance)) {
return true;
} else if (type is! InterfaceType) {
@@ -8290,6 +8451,9 @@ class InterfaceTypeImpl extends TypeImpl implements InterfaceType {
}
bool internalIsSubtypeOf(Type2 type, Set<TypeImpl_TypePair> visitedTypePairs) {
+ //
+ // T is a subtype of S, written T <: S, iff [bottom/dynamic]T << S
+ //
if (identical(type, DynamicTypeImpl.instance)) {
return true;
} else if (type is TypeParameterType) {
@@ -8310,12 +8474,26 @@ class InterfaceTypeImpl extends TypeImpl implements InterfaceType {
}
bool isMoreSpecificThan2(InterfaceType s, Set<ClassElement> visitedClasses, bool withDynamic, Set<TypeImpl_TypePair> visitedTypePairs) {
+ //
+ // A type T is more specific than a type S, written T << S, if one of the following conditions
+ // is met:
+ //
+ // Reflexivity: T is S.
+ //
if (this == s) {
return true;
}
+ //
+ // T is bottom. (This case is handled by the class BottomTypeImpl.)
+ //
+ // Direct supertype: S is a direct supertype of T.
+ //
if (s.isDirectSupertypeOf(this)) {
return true;
}
+ //
+ // Covariance: T is of the form I<T1, ..., Tn> and S is of the form I<S1, ..., Sn> and Ti << Si, 1 <= i <= n.
+ //
ClassElement tElement = this.element;
ClassElement sElement = s.element;
if (tElement == sElement) {
@@ -8331,11 +8509,17 @@ class InterfaceTypeImpl extends TypeImpl implements InterfaceType {
}
return true;
}
+ //
+ // Transitivity: T << U and U << S.
+ //
+ // First check for infinite loops
ClassElement element = this.element;
if (element == null || visitedClasses.contains(element)) {
return false;
}
visitedClasses.add(element);
+ // Iterate over all of the types U that are more specific than T because they are direct
+ // supertypes of T and return true if any of them are more specific than S.
InterfaceType supertype = superclass;
if (supertype != null && (supertype as InterfaceTypeImpl).isMoreSpecificThan2(s, visitedClasses, withDynamic, visitedTypePairs)) {
return true;
@@ -8364,12 +8548,18 @@ class InterfaceTypeImpl extends TypeImpl implements InterfaceType {
if (typeT == typeS) {
return true;
} else if (elementT == typeS.element) {
+ // For each of the type arguments return true if all type args from T is a subtype of all
+ // types from S.
List<Type2> typeTArgs = typeT.typeArguments;
List<Type2> typeSArgs = typeS.typeArguments;
if (typeTArgs.length != typeSArgs.length) {
+ // This case covers the case where two objects are being compared that have a different
+ // number of parameterized types.
return false;
}
for (int i = 0; i < typeTArgs.length; i++) {
+ // Recursively call isSubtypeOf the type arguments and return false if the T argument is not
+ // a subtype of the S argument.
if (!(typeTArgs[i] as TypeImpl).isSubtypeOf3(typeSArgs[i], visitedTypePairs)) {
return false;
}
@@ -8379,6 +8569,7 @@ class InterfaceTypeImpl extends TypeImpl implements InterfaceType {
return true;
}
InterfaceType supertype = superclass;
+ // The type is Object, return false.
if (supertype != null && (supertype as InterfaceTypeImpl).isSubtypeOf2(typeS, visitedClasses, visitedTypePairs)) {
return true;
}
@@ -8508,6 +8699,7 @@ abstract class TypeImpl implements Type2 {
* @return `true` if this type is more specific than the given type
*/
bool isMoreSpecificThan3(Type2 type, bool withDynamic, Set<TypeImpl_TypePair> visitedTypePairs) {
+ // If the visitedTypePairs already has the pair (this, type), return false
TypeImpl_TypePair typePair = new TypeImpl_TypePair(this, type);
if (!visitedTypePairs.add(typePair)) {
return false;
@@ -8533,6 +8725,7 @@ abstract class TypeImpl implements Type2 {
* @return `true` if this type is a subtype of the given type
*/
bool isSubtypeOf3(Type2 type, Set<TypeImpl_TypePair> visitedTypePairs) {
+ // If the visitedTypePairs already has the pair (this, type), return false
TypeImpl_TypePair typePair = new TypeImpl_TypePair(this, type);
if (!visitedTypePairs.add(typePair)) {
return false;
@@ -8665,12 +8858,22 @@ class TypeParameterTypeImpl extends TypeImpl implements TypeParameterType {
bool internalEquals(Object object, Set<ElementPair> visitedElementPairs) => this == object;
bool internalIsMoreSpecificThan(Type2 s, bool withDynamic, Set<TypeImpl_TypePair> visitedTypePairs) {
+ //
+ // A type T is more specific than a type S, written T << S, if one of the following conditions
+ // is met:
+ //
+ // Reflexivity: T is S.
+ //
if (this == s) {
return true;
}
+ // S is bottom.
+ //
if (s.isBottom) {
return true;
}
+ // S is dynamic.
+ //
if (s.isDynamic) {
return true;
}
@@ -8680,24 +8883,35 @@ class TypeParameterTypeImpl extends TypeImpl implements TypeParameterType {
bool internalIsSubtypeOf(Type2 type, Set<TypeImpl_TypePair> visitedTypePairs) => isMoreSpecificThan3(type, true, new Set<TypeImpl_TypePair>());
bool isMoreSpecificThan4(Type2 s, Set<Type2> visitedTypes, bool withDynamic, Set<TypeImpl_TypePair> visitedTypePairs) {
+ // T is a type parameter and S is the upper bound of T.
+ //
Type2 bound = element.bound;
if (s == bound) {
return true;
}
+ // T is a type parameter and S is Object.
+ //
if (s.isObject) {
return true;
}
+ // We need upper bound to continue.
if (bound == null) {
return false;
}
+ //
+ // Transitivity: T << U and U << S.
+ //
if (bound is TypeParameterTypeImpl) {
TypeParameterTypeImpl boundTypeParameter = bound;
+ // First check for infinite loops
if (visitedTypes.contains(bound)) {
return false;
}
visitedTypes.add(bound);
+ // Then check upper bound.
return boundTypeParameter.isMoreSpecificThan4(s, visitedTypes, withDynamic, visitedTypePairs);
}
+ // Check interface type.
return (bound as TypeImpl).isMoreSpecificThan3(s, withDynamic, visitedTypePairs);
}
}
« no previous file with comments | « pkg/analyzer/lib/src/generated/constant.dart ('k') | pkg/analyzer/lib/src/generated/engine.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698