Issue 25218. The reference type of 'A' in 'A..foo' is 'Type'.

R=brianwilkerson@google.com
BUG= https://github.com/dart-lang/sdk/issues/25218

Review URL: https://codereview.chromium.org/1519583002 .
This commit is contained in:
Konstantin Shcheglov 2015-12-10 10:20:40 -08:00
parent 1a5a9a7247
commit 0f95992770
2 changed files with 68 additions and 22 deletions

View file

@ -102,7 +102,7 @@ class ElementResolver extends SimpleAstVisitor<Object> {
/**
* The type representing the type 'type'.
*/
DartType _typeType;
InterfaceType _typeType;
/**
* A utility class for the resolver to answer the question of "what are my
@ -594,8 +594,6 @@ class ElementResolver extends SimpleAstVisitor<Object> {
}
Element staticElement;
Element propagatedElement;
DartType staticType = null;
DartType propagatedType = null;
if (target == null) {
staticElement = _resolveInvokedElement(methodName);
propagatedElement = null;
@ -611,8 +609,6 @@ class ElementResolver extends SimpleAstVisitor<Object> {
methodName.staticElement = importedLibrary.loadLibraryFunction;
return null;
} else {
staticType = _getStaticType(target);
propagatedType = _getPropagatedType(target);
//
// If this method invocation is of the form 'C.m' where 'C' is a class,
// then we don't call resolveInvokedElement(...) which walks up the class
@ -622,8 +618,13 @@ class ElementResolver extends SimpleAstVisitor<Object> {
bool isConditional = node.operator.type == sc.TokenType.QUESTION_PERIOD;
ClassElementImpl typeReference = getTypeReference(target);
if (typeReference != null) {
if (node.isCascaded) {
typeReference = _typeType.element;
}
staticElement = _resolveElement(typeReference, methodName);
} else {
DartType staticType = _getStaticType(target);
DartType propagatedType = _getPropagatedType(target);
staticElement = _resolveInvokedElementWithTarget(
target, staticType, methodName, isConditional);
// If we have propagated type information use it (since it should
@ -773,17 +774,19 @@ class ElementResolver extends SimpleAstVisitor<Object> {
// resolveArgumentsToParameters(node.getArgumentList(), invokedFunction);
return null;
}
ClassElementImpl typeReference = getTypeReference(target);
if (typeReference != null) {
ConstructorElement constructor =
typeReference.getNamedConstructor(methodName.name);
if (constructor != null) {
_recordUndefinedNode(
typeReference,
StaticTypeWarningCode.UNDEFINED_METHOD_WITH_CONSTRUCTOR,
methodName,
[methodName.name, typeReference.name]);
return null;
if (!node.isCascaded) {
ClassElementImpl typeReference = getTypeReference(target);
if (typeReference != null) {
ConstructorElement constructor =
typeReference.getNamedConstructor(methodName.name);
if (constructor != null) {
_recordUndefinedNode(
typeReference,
StaticTypeWarningCode.UNDEFINED_METHOD_WITH_CONSTRUCTOR,
methodName,
[methodName.name, typeReference.name]);
return null;
}
}
}
targetTypeName = targetType == null ? null : targetType.displayName;
@ -923,7 +926,7 @@ class ElementResolver extends SimpleAstVisitor<Object> {
// Otherwise, the prefix is really an expression that happens to be a simple
// identifier and this is really equivalent to a property access node.
//
_resolvePropertyAccess(prefix, identifier);
_resolvePropertyAccess(prefix, identifier, false);
return null;
}
@ -979,7 +982,7 @@ class ElementResolver extends SimpleAstVisitor<Object> {
return null;
}
SimpleIdentifier propertyName = node.propertyName;
_resolvePropertyAccess(target, propertyName);
_resolvePropertyAccess(target, propertyName, node.isCascaded);
return null;
}
@ -2251,7 +2254,7 @@ class ElementResolver extends SimpleAstVisitor<Object> {
}
void _resolvePropertyAccess(
Expression target, SimpleIdentifier propertyName) {
Expression target, SimpleIdentifier propertyName, bool isCascaded) {
DartType staticType = _getStaticType(target);
DartType propagatedType = _getPropagatedType(target);
Element staticElement = null;
@ -2264,6 +2267,9 @@ class ElementResolver extends SimpleAstVisitor<Object> {
//
ClassElementImpl typeReference = getTypeReference(target);
if (typeReference != null) {
if (isCascaded) {
typeReference = _typeType.element;
}
// TODO(brianwilkerson) Why are we setting the propagated element here?
// It looks wrong.
staticElement =

View file

@ -1122,7 +1122,8 @@ class A<T extends T> {
verify([source]);
}
void test_typePromotion_booleanAnd_useInRight_accessedInClosureRight_mutated() {
void
test_typePromotion_booleanAnd_useInRight_accessedInClosureRight_mutated() {
Source source = addSource(r'''
callMe(f()) { f(); }
main(Object p) {
@ -1151,7 +1152,8 @@ main(Object p) {
assertErrors(source, [StaticTypeWarningCode.UNDEFINED_GETTER]);
}
void test_typePromotion_conditional_useInThen_accessedInClosure_hasAssignment_after() {
void
test_typePromotion_conditional_useInThen_accessedInClosure_hasAssignment_after() {
Source source = addSource(r'''
callMe(f()) { f(); }
main(Object p) {
@ -1162,7 +1164,8 @@ main(Object p) {
assertErrors(source, [StaticTypeWarningCode.UNDEFINED_GETTER]);
}
void test_typePromotion_conditional_useInThen_accessedInClosure_hasAssignment_before() {
void
test_typePromotion_conditional_useInThen_accessedInClosure_hasAssignment_before() {
Source source = addSource(r'''
callMe(f()) { f(); }
main(Object p) {
@ -1442,6 +1445,18 @@ var a = A.B;''');
assertErrors(source, [StaticTypeWarningCode.UNDEFINED_GETTER]);
}
void test_undefinedGetter_typeLiteral_cascadeTarget() {
Source source = addSource(r'''
class T {
static int get foo => 42;
}
main() {
T..foo;
}''');
computeLibrarySourceErrors(source);
assertErrors(source, [StaticTypeWarningCode.UNDEFINED_GETTER]);
}
void test_undefinedGetter_typeLiteral_conditionalAccess() {
// When applied to a type literal, the conditional access operator '?.'
// cannot be used to access instance getters of Type.
@ -1613,6 +1628,19 @@ main() {
assertErrors(source, [StaticTypeWarningCode.UNDEFINED_METHOD]);
}
void test_undefinedMethod_typeLiteral_cascadeTarget() {
Source source = addSource('''
class T {
static void foo() {}
}
main() {
T..foo();
}
''');
computeLibrarySourceErrors(source);
assertErrors(source, [StaticTypeWarningCode.UNDEFINED_METHOD]);
}
void test_undefinedMethod_typeLiteral_conditionalAccess() {
// When applied to a type literal, the conditional access operator '?.'
// cannot be used to access instance methods of Type.
@ -1713,6 +1741,18 @@ f() { A.B = 0;}''');
assertErrors(source, [StaticTypeWarningCode.UNDEFINED_SETTER]);
}
void test_undefinedSetter_typeLiteral_cascadeTarget() {
Source source = addSource(r'''
class T {
static void set foo(_) {}
}
main() {
T..foo = 42;
}''');
computeLibrarySourceErrors(source);
assertErrors(source, [StaticTypeWarningCode.UNDEFINED_SETTER]);
}
void test_undefinedSetter_void() {
Source source = addSource(r'''
class T {