mirror of
https://github.com/dart-lang/sdk
synced 2024-09-21 20:21:18 +00:00
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:
parent
1a5a9a7247
commit
0f95992770
|
@ -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 =
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in a new issue