| // Copyright (c) 2019, 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. |
| |
| import 'package:analyzer/src/dart/error/syntactic_errors.dart'; |
| import 'package:analyzer/src/error/codes.dart'; |
| import 'package:test_reflective_loader/test_reflective_loader.dart'; |
| |
| import '../dart/resolution/context_collection_resolution.dart'; |
| |
| main() { |
| defineReflectiveSuite(() { |
| defineReflectiveTests(UndefinedGetterTest); |
| }); |
| } |
| |
| @reflectiveTest |
| class UndefinedGetterTest extends PubPackageResolutionTest { |
| test_compoundAssignment_hasSetter_instance() async { |
| await assertErrorsInCode(''' |
| class C { |
| set foo(int _) {} |
| } |
| |
| f(C c) { |
| c.foo += 1; |
| } |
| ''', [ |
| error(CompileTimeErrorCode.UNDEFINED_GETTER, 46, 3), |
| ]); |
| } |
| |
| test_compoundAssignment_hasSetter_static() async { |
| await assertErrorsInCode(''' |
| class C { |
| static set foo(int _) {} |
| } |
| |
| f() { |
| C.foo += 1; |
| } |
| ''', [ |
| error(CompileTimeErrorCode.UNDEFINED_GETTER, 50, 3), |
| ]); |
| } |
| |
| test_emptyName() async { |
| await assertErrorsInCode(''' |
| class A { |
| } |
| main() { |
| print(A().); |
| } |
| ''', [ |
| error(ParserErrorCode.MISSING_IDENTIFIER, 33, 1), |
| ]); |
| } |
| |
| test_extension_instance_extendedHasSetter_extensionHasGetter() async { |
| await assertErrorsInCode(''' |
| class C { |
| void set foo(int _) {} |
| } |
| |
| extension E on C { |
| int get foo => 0; |
| |
| f() { |
| this.foo; |
| } |
| } |
| ''', [ |
| error(CompileTimeErrorCode.UNDEFINED_GETTER, 95, 3), |
| ]); |
| } |
| |
| test_extension_instance_undefined_hasSetter() async { |
| await assertErrorsInCode(''' |
| extension E on int { |
| void set foo(int _) {} |
| } |
| f() { |
| 0.foo; |
| } |
| ''', [ |
| error(CompileTimeErrorCode.UNDEFINED_GETTER, 58, 3), |
| ]); |
| } |
| |
| test_extension_instance_withInference() async { |
| await assertErrorsInCode(r''' |
| extension E on int {} |
| var a = 3.v; |
| ''', [ |
| error(CompileTimeErrorCode.UNDEFINED_GETTER, 32, 1), |
| ]); |
| } |
| |
| test_extension_instance_withoutInference() async { |
| await assertErrorsInCode(r''' |
| class C {} |
| |
| extension E on C {} |
| |
| f(C c) { |
| c.a; |
| } |
| ''', [ |
| error(CompileTimeErrorCode.UNDEFINED_GETTER, 46, 1), |
| ]); |
| } |
| |
| test_extension_this_extendedHasSetter_extensionHasGetter() async { |
| await assertErrorsInCode(''' |
| class C { |
| void set foo(int _) {} |
| } |
| |
| extension E on C { |
| int get foo => 0; |
| } |
| |
| f(C c) { |
| c.foo; |
| } |
| ''', [ |
| error(CompileTimeErrorCode.UNDEFINED_GETTER, 93, 3), |
| ]); |
| } |
| |
| test_functionAlias_typeInstantiated_getter() async { |
| await assertErrorsInCode(''' |
| typedef Fn<T> = void Function(T); |
| |
| void bar() { |
| Fn<int>.foo; |
| } |
| |
| extension E on Type { |
| int get foo => 1; |
| } |
| ''', [ |
| error(CompileTimeErrorCode.UNDEFINED_GETTER_ON_FUNCTION_TYPE, 58, 3), |
| ]); |
| } |
| |
| test_functionAlias_typeInstantiated_getter_parenthesized() async { |
| await assertNoErrorsInCode(''' |
| typedef Fn<T> = void Function(T); |
| |
| void bar() { |
| (Fn<int>).foo; |
| } |
| |
| extension E on Type { |
| int get foo => 1; |
| } |
| '''); |
| } |
| |
| test_generic_function_call() async { |
| // Referencing `.call` on a `Function` type works similarly to referencing |
| // it on `dynamic`--the reference is accepted at compile time, and all type |
| // checking is deferred until runtime. |
| await assertNoErrorsInCode(''' |
| f(Function f) { |
| return f.call; |
| } |
| '''); |
| } |
| |
| test_get_from_abstract_field_final_valid() async { |
| await assertNoErrorsInCode(''' |
| abstract class A { |
| abstract final int x; |
| } |
| int f(A a) => a.x; |
| '''); |
| } |
| |
| test_get_from_abstract_field_valid() async { |
| await assertNoErrorsInCode(''' |
| abstract class A { |
| abstract int x; |
| } |
| int f(A a) => a.x; |
| '''); |
| } |
| |
| test_get_from_external_field_final_valid() async { |
| await assertNoErrorsInCode(''' |
| class A { |
| external final int x; |
| } |
| int f(A a) => a.x; |
| '''); |
| } |
| |
| test_get_from_external_field_valid() async { |
| await assertNoErrorsInCode(''' |
| class A { |
| external int x; |
| } |
| int f(A a) => a.x; |
| '''); |
| } |
| |
| test_get_from_external_static_field_final_valid() async { |
| await assertNoErrorsInCode(''' |
| class A { |
| external static final int x; |
| } |
| int f() => A.x; |
| '''); |
| } |
| |
| test_get_from_external_static_field_valid() async { |
| await assertNoErrorsInCode(''' |
| class A { |
| external static int x; |
| } |
| int f() => A.x; |
| '''); |
| } |
| |
| test_ifElement_inList_notPromoted() async { |
| await assertErrorsInCode(''' |
| f(int x) { |
| return [if (x is String) x.length]; |
| } |
| ''', [ |
| error(CompileTimeErrorCode.UNDEFINED_GETTER, 40, 6), |
| ]); |
| } |
| |
| test_ifElement_inList_promoted() async { |
| await assertNoErrorsInCode(''' |
| f(Object x) { |
| return [if (x is String) x.length]; |
| } |
| '''); |
| } |
| |
| test_ifElement_inMap_notPromoted() async { |
| await assertErrorsInCode(''' |
| f(int x) { |
| return {if (x is String) x : x.length}; |
| } |
| ''', [ |
| error(CompileTimeErrorCode.UNDEFINED_GETTER, 44, 6), |
| ]); |
| } |
| |
| test_ifElement_inMap_promoted() async { |
| await assertNoErrorsInCode(''' |
| f(Object x) { |
| return {if (x is String) x : x.length}; |
| } |
| '''); |
| } |
| |
| test_ifElement_inSet_notPromoted() async { |
| await assertErrorsInCode(''' |
| f(int x) { |
| return {if (x is String) x.length}; |
| } |
| ''', [ |
| error(CompileTimeErrorCode.UNDEFINED_GETTER, 40, 6), |
| ]); |
| } |
| |
| test_ifElement_inSet_promoted() async { |
| await assertNoErrorsInCode(''' |
| f(Object x) { |
| return {if (x is String) x.length}; |
| } |
| '''); |
| } |
| |
| test_ifStatement_notPromoted() async { |
| await assertErrorsInCode(''' |
| f(int x) { |
| if (x is String) { |
| x.length; |
| } |
| } |
| ''', [ |
| error(CompileTimeErrorCode.UNDEFINED_GETTER, 38, 6), |
| ]); |
| } |
| |
| test_ifStatement_promoted() async { |
| await assertNoErrorsInCode(''' |
| f(Object x) { |
| if (x is String) { |
| x.length; |
| } |
| } |
| '''); |
| } |
| |
| test_instance_undefined() async { |
| await assertErrorsInCode(r''' |
| class T {} |
| f(T e) { return e.m; } |
| ''', [ |
| error(CompileTimeErrorCode.UNDEFINED_GETTER, 29, 1), |
| ]); |
| } |
| |
| test_instance_undefined_mixin() async { |
| await assertErrorsInCode(r''' |
| mixin M { |
| f() { return this.m; } |
| } |
| ''', [ |
| error(CompileTimeErrorCode.UNDEFINED_GETTER, 30, 1), |
| ]); |
| } |
| |
| test_new_cascade() async { |
| await assertErrorsInCode(''' |
| class C {} |
| |
| f(C? c) { |
| c..new; |
| } |
| ''', [ |
| error(CompileTimeErrorCode.UNDEFINED_GETTER, 27, 3), |
| ]); |
| } |
| |
| test_new_dynamic() async { |
| await assertErrorsInCode(''' |
| f(dynamic d) { |
| d.new; |
| } |
| ''', [ |
| error(CompileTimeErrorCode.UNDEFINED_GETTER, 19, 3), |
| ]); |
| } |
| |
| test_new_expression() async { |
| await assertErrorsInCode(''' |
| class C {} |
| |
| f(C? c1, C c2) { |
| (c1 ?? c2).new; |
| } |
| ''', [ |
| error(CompileTimeErrorCode.UNDEFINED_GETTER, 42, 3), |
| ]); |
| } |
| |
| test_new_nullAware() async { |
| await assertErrorsInCode(''' |
| class C {} |
| |
| f(C? c) { |
| c?.new; |
| } |
| ''', [ |
| error(CompileTimeErrorCode.UNDEFINED_GETTER, 27, 3), |
| ]); |
| } |
| |
| test_new_prefixedIdentifier() async { |
| await assertErrorsInCode(''' |
| class C {} |
| |
| abstract class D { |
| C get c; |
| } |
| |
| f(D d) { |
| d.c.new; |
| } |
| ''', [ |
| error(CompileTimeErrorCode.UNDEFINED_GETTER, 60, 3), |
| ]); |
| } |
| |
| test_new_simpleIdentifier() async { |
| await assertErrorsInCode(''' |
| class C {} |
| |
| f(C c) { |
| c.new; |
| } |
| ''', [ |
| error(CompileTimeErrorCode.UNDEFINED_GETTER, 25, 3), |
| ]); |
| } |
| |
| test_new_typeVariable() async { |
| await assertErrorsInCode(''' |
| f<T>(T t) { |
| t.new; |
| } |
| ''', [ |
| error(CompileTimeErrorCode.UNDEFINED_GETTER, 16, 3), |
| ]); |
| } |
| |
| test_nullMember_undefined() async { |
| await assertErrorsInCode(r''' |
| m() { |
| Null _null; |
| _null.foo; |
| } |
| ''', [ |
| error(CompileTimeErrorCode.INVALID_USE_OF_NULL_VALUE, 28, 3), |
| ]); |
| } |
| |
| test_object_call() async { |
| await assertErrorsInCode(''' |
| f(Object o) { |
| return o.call; |
| } |
| ''', [ |
| error(CompileTimeErrorCode.UNDEFINED_GETTER, 25, 4), |
| ]); |
| } |
| |
| test_promotedTypeParameter_regress35305() async { |
| await assertErrorsInCode(r''' |
| void f<X extends num, Y extends X>(Y y) { |
| if (y is int) { |
| y.isEven; |
| } |
| } |
| ''', [ |
| error(CompileTimeErrorCode.UNDEFINED_GETTER, 66, 6), |
| ]); |
| } |
| |
| test_propertyAccess_functionClass_call() async { |
| await assertErrorsInCode(''' |
| void f(Function a) { |
| return (a).call; |
| } |
| ''', [ |
| error(CompileTimeErrorCode.RETURN_OF_INVALID_TYPE_FROM_FUNCTION, 30, 8), |
| ]); |
| } |
| |
| test_propertyAccess_functionType_call() async { |
| await assertNoErrorsInCode(''' |
| class A { |
| void staticMethod() {} |
| } |
| |
| void f(A a) { |
| a.staticMethod.call; |
| } |
| '''); |
| } |
| |
| test_static_conditionalAccess_defined() async { |
| await assertErrorsInCode(''' |
| class A { |
| static var x; |
| } |
| var a = A?.x; |
| ''', [ |
| error(StaticWarningCode.INVALID_NULL_AWARE_OPERATOR, 37, 2), |
| ]); |
| } |
| |
| test_static_definedInSuperclass() async { |
| await assertErrorsInCode(''' |
| class S { |
| static int get g => 0; |
| } |
| class C extends S {} |
| f(var p) { |
| f(C.g); |
| }''', [ |
| error(CompileTimeErrorCode.UNDEFINED_GETTER, 75, 1), |
| ]); |
| } |
| |
| test_static_extension_InstanceAccess() async { |
| await assertErrorsInCode(''' |
| class C {} |
| |
| extension E on C { |
| static int get a => 0; |
| } |
| |
| C g(C c) => C(); |
| f(C c) { |
| g(c).a; |
| } |
| ''', [ |
| error(CompileTimeErrorCode.UNDEFINED_GETTER, 92, 1), |
| ]); |
| } |
| |
| test_static_undefined() async { |
| await assertErrorsInCode(''' |
| class C {} |
| f(var p) { |
| f(C.m); |
| }''', [ |
| error(CompileTimeErrorCode.UNDEFINED_GETTER, 28, 1), |
| ]); |
| } |
| |
| test_typeLiteral_cascadeTarget() async { |
| await assertErrorsInCode(r''' |
| class T { |
| static int get foo => 42; |
| } |
| main() { |
| T..foo; |
| } |
| ''', [ |
| error(CompileTimeErrorCode.UNDEFINED_GETTER, 54, 3), |
| ]); |
| } |
| |
| test_typeLiteral_conditionalAccess() async { |
| await assertErrorsInCode(''' |
| class A {} |
| f() => A?.hashCode; |
| ''', [ |
| error(StaticWarningCode.INVALID_NULL_AWARE_OPERATOR, 19, 2), |
| error(CompileTimeErrorCode.UNDEFINED_GETTER, 21, 8), |
| ]); |
| } |
| |
| test_typeSubstitution_defined() async { |
| await assertNoErrorsInCode(r''' |
| class A<E> { |
| E element; |
| A(this.element); |
| } |
| class B extends A<List> { |
| B(List element) : super(element); |
| m() { |
| element.last; |
| } |
| } |
| '''); |
| } |
| } |