| // 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/diagnostic/diagnostic.dart' as diag; |
| import 'package:test_reflective_loader/test_reflective_loader.dart'; |
| |
| import '../dart/resolution/context_collection_resolution.dart'; |
| |
| main() { |
| defineReflectiveSuite(() { |
| defineReflectiveTests(InvalidOverrideTest); |
| }); |
| } |
| |
| @reflectiveTest |
| class InvalidOverrideTest extends PubPackageResolutionTest { |
| test_abstract_field_covariant_inheritance() async { |
| await assertNoErrorsInCode(''' |
| abstract class A { |
| abstract covariant num x; |
| } |
| abstract class B implements A { |
| void set x(Object value); // Implicitly covariant |
| } |
| abstract class C implements B { |
| int get x; |
| void set x(int value); // Ok because covariant |
| } |
| '''); |
| } |
| |
| test_class_augment_method_covariant_multiFile_invalid() async { |
| var a = newFile('$testPackageLibPath/a.dart', r''' |
| part 'b.dart'; |
| |
| class A { |
| void foo(num a) {} |
| } |
| |
| class B extends A {} |
| '''); |
| |
| var b = newFile('$testPackageLibPath/b.dart', r''' |
| part of 'a.dart'; |
| |
| augment class B { |
| void foo(covariant String a) {} |
| } |
| '''); |
| |
| await assertErrorsInFile2(a, []); |
| await assertErrorsInFile2(b, [error(diag.invalidOverride, 44, 3)]); |
| } |
| |
| test_class_augment_method_covariant_multiFile_valid() async { |
| var a = newFile('$testPackageLibPath/a.dart', r''' |
| part 'b.dart'; |
| |
| class A { |
| void foo(num a) {} |
| } |
| |
| class B extends A {} |
| '''); |
| |
| var b = newFile('$testPackageLibPath/b.dart', r''' |
| part of 'a.dart'; |
| |
| augment class B { |
| void foo(covariant int a) {} |
| } |
| '''); |
| |
| await assertErrorsInFile2(a, []); |
| await assertErrorsInFile2(b, []); |
| } |
| |
| test_class_augment_method_covariant_singleFile_invalid() async { |
| await assertErrorsInCode( |
| r''' |
| class A { |
| void foo(num a) {} |
| } |
| |
| class B extends A {} |
| |
| augment class B { |
| void foo(covariant String a) {} |
| } |
| ''', |
| [error(diag.invalidOverride, 81, 3)], |
| ); |
| } |
| |
| test_class_augment_method_covariant_singleFile_valid() async { |
| await assertNoErrorsInCode(r''' |
| class A { |
| void foo(num a) {} |
| } |
| |
| class B extends A {} |
| |
| augment class B { |
| void foo(covariant int a) {} |
| } |
| '''); |
| } |
| |
| test_class_augment_method_multiFile() async { |
| var a = newFile('$testPackageLibPath/a.dart', r''' |
| part 'b.dart'; |
| |
| class A { |
| int foo() => 0; |
| } |
| |
| class B extends A {} |
| '''); |
| |
| var b = newFile('$testPackageLibPath/b.dart', r''' |
| part of 'a.dart'; |
| |
| augment class B { |
| String foo() => ''; |
| } |
| '''); |
| |
| await assertErrorsInFile2(a, []); |
| await assertErrorsInFile2(b, [ |
| error(diag.invalidOverride, 46, 3, contextMessages: [message(a, 32, 3)]), |
| ]); |
| } |
| |
| test_class_augment_method_singleFile() async { |
| await assertErrorsInCode( |
| r''' |
| class A { |
| int foo() => 0; |
| } |
| |
| class B extends A {} |
| |
| augment class B { |
| String foo() => ''; |
| } |
| ''', |
| [ |
| error( |
| diag.invalidOverride, |
| 80, |
| 3, |
| contextMessages: [message(testFile, 16, 3)], |
| ), |
| ], |
| ); |
| } |
| |
| test_class_augment_setter_multiFile() async { |
| var a = newFile('$testPackageLibPath/a.dart', r''' |
| part 'b.dart'; |
| |
| class A { |
| void set foo(int value) {} |
| } |
| |
| class B extends A {} |
| '''); |
| |
| var b = newFile('$testPackageLibPath/b.dart', r''' |
| part of 'a.dart'; |
| |
| augment class B { |
| void set foo(String value) {} |
| } |
| '''); |
| |
| await assertErrorsInFile2(a, []); |
| await assertErrorsInFile2(b, [ |
| error( |
| diag.invalidOverrideSetter, |
| 48, |
| 3, |
| contextMessages: [message(a, 37, 3)], |
| ), |
| ]); |
| } |
| |
| test_class_augment_setter_singleFile() async { |
| await assertErrorsInCode( |
| r''' |
| class A { |
| void set foo(int value) {} |
| } |
| |
| class B extends A {} |
| |
| augment class B { |
| void set foo(String value) {} |
| } |
| ''', |
| [ |
| error( |
| diag.invalidOverrideSetter, |
| 93, |
| 3, |
| contextMessages: [message(testFile, 21, 3)], |
| ), |
| ], |
| ); |
| } |
| |
| test_class_augment_withClause_multiFile__declaration0_augment1_augment1() async { |
| var a = newFile('$testPackageLibPath/a.dart', r''' |
| part 'b.dart'; |
| part 'c.dart'; |
| |
| mixin M1 {} |
| mixin M2 {} |
| |
| class A {} |
| '''); |
| |
| var b = newFile('$testPackageLibPath/b.dart', r''' |
| part of 'a.dart'; |
| |
| augment class A with M1 {} |
| '''); |
| |
| var c = newFile('$testPackageLibPath/c.dart', r''' |
| part of 'a.dart'; |
| |
| augment class A with M2 {} |
| '''); |
| |
| await assertErrorsInFile2(a, []); |
| await assertErrorsInFile2(b, []); |
| await assertErrorsInFile2(c, []); |
| } |
| |
| test_class_augment_withClause_multiFile_declaration0_augment2() async { |
| var a = newFile('$testPackageLibPath/a.dart', r''' |
| part 'b.dart'; |
| |
| mixin M1 {} |
| mixin M2 {} |
| |
| class A {} |
| '''); |
| |
| var b = newFile('$testPackageLibPath/b.dart', r''' |
| part of 'a.dart'; |
| |
| augment class A with M1, M2 {} |
| '''); |
| |
| await assertErrorsInFile2(a, []); |
| await assertErrorsInFile2(b, []); |
| } |
| |
| test_class_augment_withClause_multiFile_declaration1_augment1() async { |
| var a = newFile('$testPackageLibPath/a.dart', r''' |
| part 'b.dart'; |
| |
| mixin M1 {} |
| mixin M2 {} |
| |
| class A with M1 {} |
| '''); |
| |
| var b = newFile('$testPackageLibPath/b.dart', r''' |
| part of 'a.dart'; |
| |
| augment class A with M2 {} |
| '''); |
| |
| await assertErrorsInFile2(a, []); |
| await assertErrorsInFile2(b, []); |
| } |
| |
| test_class_augment_withClause_singleFile_declaration0_augment1() async { |
| await assertNoErrorsInCode(r''' |
| mixin M {} |
| |
| class A {} |
| |
| augment class A with M {} |
| '''); |
| } |
| |
| test_class_augment_withClause_singleFile_declaration0_augment1_augment1() async { |
| await assertNoErrorsInCode(r''' |
| mixin M1 {} |
| mixin M2 {} |
| |
| class A {} |
| |
| augment class A with M1 {} |
| |
| augment class A with M2 {} |
| '''); |
| } |
| |
| test_class_augment_withClause_singleFile_declaration0_augment2() async { |
| await assertNoErrorsInCode(r''' |
| mixin M1 {} |
| mixin M2 {} |
| |
| class A {} |
| |
| augment class A with M1, M2 {} |
| '''); |
| } |
| |
| test_class_augment_withClause_singleFile_declaration1_augment1() async { |
| await assertNoErrorsInCode(r''' |
| mixin M1 {} |
| mixin M2 {} |
| |
| class A with M1 {} |
| |
| augment class A with M2 {} |
| '''); |
| } |
| |
| test_class_augment_withClause_twoFiles_declaration0_augment1() async { |
| var a = newFile('$testPackageLibPath/a.dart', r''' |
| part 'b.dart'; |
| |
| mixin M {} |
| |
| class A {} |
| '''); |
| |
| var b = newFile('$testPackageLibPath/b.dart', r''' |
| part of 'a.dart'; |
| |
| augment class A with M {} |
| '''); |
| |
| await assertErrorsInFile2(a, []); |
| await assertErrorsInFile2(b, []); |
| } |
| |
| test_external_field_covariant_inheritance() async { |
| await assertNoErrorsInCode(''' |
| abstract class A { |
| external covariant num x; |
| } |
| abstract class B implements A { |
| void set x(Object value); // Implicitly covariant |
| } |
| abstract class C implements B { |
| int get x; |
| void set x(int value); // Ok because covariant |
| } |
| '''); |
| } |
| |
| test_getter_overrides_abstract_field_covariant_invalid() async { |
| await assertErrorsInCode( |
| ''' |
| abstract class A { |
| abstract covariant int x; |
| } |
| abstract class B implements A { |
| num get x; |
| void set x(num value); |
| } |
| ''', |
| [ |
| error( |
| diag.invalidOverride, |
| 91, |
| 1, |
| contextMessages: [message(testFile, 44, 1)], |
| ), |
| ], |
| ); |
| } |
| |
| test_getter_overrides_abstract_field_covariant_valid() async { |
| await assertNoErrorsInCode(''' |
| abstract class A { |
| abstract covariant num x; |
| } |
| abstract class B implements A { |
| int get x; |
| } |
| '''); |
| } |
| |
| test_getter_overrides_abstract_field_final_invalid() async { |
| await assertErrorsInCode( |
| ''' |
| abstract class A { |
| abstract final int x; |
| } |
| abstract class B implements A { |
| num get x; |
| void set x(num value); |
| } |
| ''', |
| [ |
| error( |
| diag.invalidOverride, |
| 87, |
| 1, |
| contextMessages: [message(testFile, 40, 1)], |
| ), |
| ], |
| ); |
| } |
| |
| test_getter_overrides_abstract_field_final_valid() async { |
| await assertNoErrorsInCode(''' |
| abstract class A { |
| abstract final num x; |
| } |
| abstract class B implements A { |
| int get x; |
| } |
| '''); |
| } |
| |
| test_getter_overrides_abstract_field_invalid() async { |
| await assertErrorsInCode( |
| ''' |
| abstract class A { |
| abstract int x; |
| } |
| abstract class B implements A { |
| num get x; |
| void set x(num value); |
| } |
| ''', |
| [ |
| error( |
| diag.invalidOverride, |
| 81, |
| 1, |
| contextMessages: [message(testFile, 34, 1)], |
| ), |
| ], |
| ); |
| } |
| |
| test_getter_overrides_abstract_field_valid() async { |
| await assertNoErrorsInCode(''' |
| abstract class A { |
| abstract num x; |
| } |
| abstract class B implements A { |
| int get x; |
| } |
| '''); |
| } |
| |
| test_getter_overrides_external_field_covariant_invalid() async { |
| await assertErrorsInCode( |
| ''' |
| class A { |
| external covariant int x; |
| } |
| abstract class B implements A { |
| num get x; |
| void set x(num value); |
| } |
| ''', |
| [ |
| error( |
| diag.invalidOverride, |
| 82, |
| 1, |
| contextMessages: [message(testFile, 35, 1)], |
| ), |
| ], |
| ); |
| } |
| |
| test_getter_overrides_external_field_covariant_valid() async { |
| await assertNoErrorsInCode(''' |
| class A { |
| external covariant num x; |
| } |
| abstract class B implements A { |
| int get x; |
| } |
| '''); |
| } |
| |
| test_getter_overrides_external_field_final_invalid() async { |
| await assertErrorsInCode( |
| ''' |
| class A { |
| external final int x; |
| } |
| abstract class B implements A { |
| num get x; |
| void set x(num value); |
| } |
| ''', |
| [ |
| error( |
| diag.invalidOverride, |
| 78, |
| 1, |
| contextMessages: [message(testFile, 31, 1)], |
| ), |
| ], |
| ); |
| } |
| |
| test_getter_overrides_external_field_final_valid() async { |
| await assertNoErrorsInCode(''' |
| class A { |
| external final num x; |
| } |
| abstract class B implements A { |
| int get x; |
| } |
| '''); |
| } |
| |
| test_getter_overrides_external_field_invalid() async { |
| await assertErrorsInCode( |
| ''' |
| class A { |
| external int x; |
| } |
| abstract class B implements A { |
| num get x; |
| void set x(num value); |
| } |
| ''', |
| [ |
| error( |
| diag.invalidOverride, |
| 72, |
| 1, |
| contextMessages: [message(testFile, 25, 1)], |
| ), |
| ], |
| ); |
| } |
| |
| test_getter_overrides_external_field_valid() async { |
| await assertNoErrorsInCode(''' |
| class A { |
| external num x; |
| } |
| abstract class B implements A { |
| int get x; |
| } |
| '''); |
| } |
| |
| test_getter_returnType() async { |
| await assertErrorsInCode( |
| ''' |
| class A { |
| int get g { return 0; } |
| } |
| class B extends A { |
| String get g { return 'a'; } |
| } |
| ''', |
| [ |
| error( |
| diag.invalidOverride, |
| 71, |
| 1, |
| contextMessages: [message(testFile, 20, 1)], |
| ), |
| ], |
| ); |
| } |
| |
| test_getter_returnType_implicit() async { |
| await assertErrorsInCode( |
| ''' |
| class A { |
| String? f; |
| } |
| class B extends A { |
| int? f; |
| } |
| ''', |
| [ |
| error( |
| diag.invalidOverride, |
| 52, |
| 1, |
| contextMessages: [message(testFile, 20, 1)], |
| ), |
| error( |
| diag.invalidOverrideSetter, |
| 52, |
| 1, |
| contextMessages: [message(testFile, 20, 1)], |
| ), |
| ], |
| ); |
| } |
| |
| test_getter_returnType_twoInterfaces() async { |
| // test from language/override_inheritance_field_test_11.dart |
| await assertErrorsInCode( |
| ''' |
| abstract class I { |
| int get getter => 0; |
| } |
| abstract class J { |
| num get getter => 0; |
| } |
| abstract class A implements I, J {} |
| class B extends A { |
| String get getter => ''; |
| } |
| ''', |
| [ |
| error( |
| diag.invalidOverride, |
| 157, |
| 6, |
| contextMessages: [message(testFile, 29, 6)], |
| ), |
| ], |
| ); |
| } |
| |
| test_getter_returnType_twoInterfaces_conflicting() async { |
| await assertErrorsInCode( |
| ''' |
| abstract class I<U> { |
| U get g => throw 0; |
| } |
| abstract class J<V> { |
| V get g => throw 0; |
| } |
| class B implements I<int>, J<String> { |
| double get g => throw 0; |
| } |
| ''', |
| [ |
| error( |
| diag.invalidOverride, |
| 144, |
| 1, |
| contextMessages: [message(testFile, 30, 1)], |
| ), |
| error( |
| diag.invalidOverride, |
| 144, |
| 1, |
| contextMessages: [message(testFile, 76, 1)], |
| ), |
| ], |
| ); |
| } |
| |
| test_issue48468() async { |
| await assertNoErrorsInCode(r''' |
| abstract class A { |
| void foo<T extends R, R>(); |
| } |
| |
| class B implements A { |
| void foo<T extends R, R>() {} |
| } |
| '''); |
| } |
| |
| test_method_abstractOverridesConcrete() async { |
| await assertErrorsInCode( |
| ''' |
| class A { |
| int add(int a, int b) => a + b; |
| } |
| class B extends A { |
| int add(); |
| } |
| ''', |
| [ |
| error(diag.invalidImplementationOverride, 52, 1), |
| error( |
| diag.invalidOverride, |
| 72, |
| 3, |
| contextMessages: [message(testFile, 16, 3)], |
| ), |
| ], |
| ); |
| } |
| |
| test_method_abstractOverridesConcreteInMixin() async { |
| await assertErrorsInCode( |
| ''' |
| mixin M { |
| int add(int a, int b) => a + b; |
| } |
| class A with M { |
| int add(); |
| } |
| ''', |
| [ |
| error(diag.invalidImplementationOverride, 52, 1), |
| error( |
| diag.invalidOverride, |
| 69, |
| 3, |
| contextMessages: [message(testFile, 16, 3)], |
| ), |
| ], |
| ); |
| } |
| |
| test_method_abstractOverridesConcreteViaMixin() async { |
| await assertErrorsInCode( |
| ''' |
| class A { |
| int add(int a, int b) => a + b; |
| } |
| mixin M { |
| int add(); |
| } |
| class B extends A with M {} |
| ''', |
| [ |
| error(diag.invalidImplementationOverride, 77, 1), |
| error( |
| diag.invalidOverride, |
| 94, |
| 1, |
| contextMessages: [message(testFile, 16, 3)], |
| ), |
| ], |
| ); |
| } |
| |
| test_method_covariant_1() async { |
| await assertNoErrorsInCode(r''' |
| abstract class A<T> { |
| A<U> foo<U>(covariant A<Map<T, U>> a); |
| } |
| |
| abstract class B<U, T> extends A<T> { |
| B<U, V> foo<V>(B<U, Map<T, V>> a); |
| } |
| '''); |
| } |
| |
| test_method_covariant_2() async { |
| await assertNoErrorsInCode(r''' |
| abstract class A { |
| R foo<R>(VA<R> v); |
| } |
| |
| abstract class B implements A { |
| R foo<R>(covariant VB<R> v); |
| } |
| |
| abstract class VA<T> {} |
| |
| abstract class VB<T> implements VA<T> {} |
| '''); |
| } |
| |
| test_method_covariant_3() async { |
| await assertErrorsInCode( |
| r''' |
| class A { |
| void foo(num a) {} |
| } |
| |
| class B extends A { |
| void foo(dynamic a) {} |
| } |
| |
| class C extends B { |
| void foo(covariant String a) {} |
| } |
| ''', |
| [error(diag.invalidOverride, 109, 3)], |
| ); |
| } |
| |
| test_method_named_fewerNamedParameters() async { |
| await assertErrorsInCode( |
| ''' |
| class A { |
| m({a, b}) {} |
| } |
| class B extends A { |
| m({a}) {} |
| } |
| ''', |
| [ |
| error( |
| diag.invalidOverride, |
| 49, |
| 1, |
| contextMessages: [message(testFile, 12, 1)], |
| ), |
| ], |
| ); |
| } |
| |
| test_method_named_missingNamedParameter() async { |
| await assertErrorsInCode( |
| ''' |
| class A { |
| m({a, b}) {} |
| } |
| class B extends A { |
| m({a, c}) {} |
| } |
| ''', |
| [ |
| error( |
| diag.invalidOverride, |
| 49, |
| 1, |
| contextMessages: [message(testFile, 12, 1)], |
| ), |
| ], |
| ); |
| } |
| |
| test_method_namedParamType() async { |
| await assertErrorsInCode( |
| ''' |
| class A { |
| m({int? a}) {} |
| } |
| class B implements A { |
| m({String? a}) {} |
| } |
| ''', |
| [ |
| error( |
| diag.invalidOverride, |
| 54, |
| 1, |
| contextMessages: [message(testFile, 12, 1)], |
| ), |
| ], |
| ); |
| } |
| |
| test_method_normalParamType_interface() async { |
| await assertErrorsInCode( |
| ''' |
| class A { |
| m(int a) {} |
| } |
| class B implements A { |
| m(String a) {} |
| } |
| ''', |
| [ |
| error( |
| diag.invalidOverride, |
| 51, |
| 1, |
| contextMessages: [message(testFile, 12, 1)], |
| ), |
| ], |
| ); |
| } |
| |
| test_method_normalParamType_superclass() async { |
| await assertErrorsInCode( |
| ''' |
| class A { |
| m(int a) {} |
| } |
| class B extends A { |
| m(String a) {} |
| } |
| ''', |
| [ |
| error( |
| diag.invalidOverride, |
| 48, |
| 1, |
| contextMessages: [message(testFile, 12, 1)], |
| ), |
| ], |
| ); |
| } |
| |
| test_method_normalParamType_superclass_interface() async { |
| await assertErrorsInCode( |
| ''' |
| abstract class I<U> { |
| void m(U u) => null; |
| } |
| abstract class J<V> { |
| void m(V v) => null; |
| } |
| class B extends I<int> implements J<String> { |
| void m(double d) {} |
| } |
| ''', |
| [ |
| error( |
| diag.invalidOverride, |
| 147, |
| 1, |
| contextMessages: [message(testFile, 76, 1)], |
| ), |
| error( |
| diag.invalidOverride, |
| 147, |
| 1, |
| contextMessages: [message(testFile, 29, 1)], |
| ), |
| ], |
| ); |
| } |
| |
| test_method_normalParamType_twoInterfaces() async { |
| await assertErrorsInCode( |
| ''' |
| abstract class I { |
| m(int n); |
| } |
| abstract class J { |
| m(num n); |
| } |
| abstract class A implements I, J {} |
| class B extends A { |
| m(String n) {} |
| } |
| ''', |
| [ |
| error( |
| diag.invalidOverride, |
| 124, |
| 1, |
| contextMessages: [message(testFile, 54, 1)], |
| ), |
| ], |
| ); |
| } |
| |
| test_method_normalParamType_twoInterfaces_conflicting() async { |
| // language/override_inheritance_generic_test/08 |
| await assertErrorsInCode( |
| ''' |
| abstract class I<U> { |
| void m(U u) => null; |
| } |
| abstract class J<V> { |
| void m(V v) => null; |
| } |
| class B implements I<int>, J<String> { |
| void m(double d) {} |
| } |
| ''', |
| [ |
| error( |
| diag.invalidOverride, |
| 140, |
| 1, |
| contextMessages: [message(testFile, 29, 1)], |
| ), |
| error( |
| diag.invalidOverride, |
| 140, |
| 1, |
| contextMessages: [message(testFile, 76, 1)], |
| ), |
| ], |
| ); |
| } |
| |
| test_method_optionalParamType() async { |
| await assertErrorsInCode( |
| ''' |
| class A { |
| m([int? a]) {} |
| } |
| class B implements A { |
| m([String? a]) {} |
| } |
| ''', |
| [ |
| error( |
| diag.invalidOverride, |
| 54, |
| 1, |
| contextMessages: [message(testFile, 12, 1)], |
| ), |
| ], |
| ); |
| } |
| |
| test_method_optionalParamType_twoInterfaces() async { |
| await assertErrorsInCode( |
| ''' |
| abstract class I { |
| m([int? n]); |
| } |
| abstract class J { |
| m([num? n]); |
| } |
| abstract class A implements I, J {} |
| class B extends A { |
| m([String? n]) {} |
| } |
| ''', |
| [ |
| error( |
| diag.invalidOverride, |
| 130, |
| 1, |
| contextMessages: [message(testFile, 57, 1)], |
| ), |
| ], |
| ); |
| } |
| |
| test_method_positional_optional() async { |
| await assertErrorsInCode( |
| ''' |
| class A { |
| m([a, b]) {} |
| } |
| class B extends A { |
| m([a]) {} |
| } |
| ''', |
| [ |
| error( |
| diag.invalidOverride, |
| 49, |
| 1, |
| contextMessages: [message(testFile, 12, 1)], |
| ), |
| ], |
| ); |
| } |
| |
| test_method_positional_optionalAndRequired() async { |
| await assertErrorsInCode( |
| ''' |
| class A { |
| m(a, b, [c, d]) {} |
| } |
| class B extends A { |
| m(a, b, [c]) {} |
| } |
| ''', |
| [ |
| error( |
| diag.invalidOverride, |
| 55, |
| 1, |
| contextMessages: [message(testFile, 12, 1)], |
| ), |
| ], |
| ); |
| } |
| |
| test_method_positional_optionalAndRequired2() async { |
| await assertErrorsInCode( |
| ''' |
| class A { |
| m(a, b, [c, d]) {} |
| } |
| class B extends A { |
| m(a, [c, d]) {} |
| } |
| ''', |
| [ |
| error( |
| diag.invalidOverride, |
| 55, |
| 1, |
| contextMessages: [message(testFile, 12, 1)], |
| ), |
| ], |
| ); |
| } |
| |
| test_method_required() async { |
| await assertErrorsInCode( |
| ''' |
| class A { |
| m(a) {} |
| } |
| class B extends A { |
| m(a, b) {} |
| } |
| ''', |
| [ |
| error( |
| diag.invalidOverride, |
| 44, |
| 1, |
| contextMessages: [message(testFile, 12, 1)], |
| ), |
| ], |
| ); |
| } |
| |
| test_method_returnType_interface() async { |
| await assertErrorsInCode( |
| ''' |
| class A { |
| int m() { return 0; } |
| } |
| class B implements A { |
| String m() { return 'a'; } |
| } |
| ''', |
| [ |
| error( |
| diag.invalidOverride, |
| 68, |
| 1, |
| contextMessages: [message(testFile, 16, 1)], |
| ), |
| ], |
| ); |
| } |
| |
| @SkippedTest() // TODO(scheglov): implement augmentation |
| test_method_returnType_interface_fromAugmentation() async { |
| await assertErrorsInCode( |
| ''' |
| class A { |
| int foo() => 0; |
| } |
| |
| class B { |
| String foo() => ''; |
| } |
| |
| augment class B implements A {} |
| ''', |
| [ |
| error( |
| diag.invalidOverride, |
| 50, |
| 3, |
| contextMessages: [message(testFile, 16, 3)], |
| ), |
| ], |
| ); |
| } |
| |
| test_method_returnType_interface_grandparent() async { |
| await assertErrorsInCode( |
| ''' |
| abstract class A { |
| int m(); |
| } |
| abstract class B implements A { |
| } |
| class C implements B { |
| String m() { return 'a'; } |
| } |
| ''', |
| [ |
| error( |
| diag.invalidOverride, |
| 98, |
| 1, |
| contextMessages: [message(testFile, 25, 1)], |
| ), |
| ], |
| ); |
| } |
| |
| test_method_returnType_mixin() async { |
| await assertErrorsInCode( |
| ''' |
| mixin class A { |
| int m() { return 0; } |
| } |
| class B extends Object with A { |
| String m() { return 'a'; } |
| } |
| ''', |
| [ |
| error( |
| diag.invalidOverride, |
| 83, |
| 1, |
| contextMessages: [message(testFile, 22, 1)], |
| ), |
| ], |
| ); |
| } |
| |
| test_method_returnType_superclass() async { |
| await assertErrorsInCode( |
| ''' |
| class A { |
| int m() { return 0; } |
| } |
| class B extends A { |
| String m() { return 'a'; } |
| } |
| ''', |
| [ |
| error( |
| diag.invalidOverride, |
| 65, |
| 1, |
| contextMessages: [message(testFile, 16, 1)], |
| ), |
| ], |
| ); |
| } |
| |
| @SkippedTest() // TODO(scheglov): implement augmentation |
| test_method_returnType_superclass_fromAugmentation() async { |
| await assertErrorsInCode( |
| ''' |
| class A { |
| int foo() => 0; |
| } |
| |
| class B { |
| String foo() => ''; |
| } |
| |
| augment class B extends A {} |
| ''', |
| [ |
| error( |
| diag.invalidOverride, |
| 50, |
| 3, |
| contextMessages: [message(testFile, 16, 3)], |
| ), |
| ], |
| ); |
| } |
| |
| test_method_returnType_superclass_grandparent() async { |
| await assertErrorsInCode( |
| ''' |
| class A { |
| int m() { return 0; } |
| } |
| class B extends A { |
| } |
| class C extends B { |
| String m() { return 'a'; } |
| } |
| ''', |
| [ |
| error( |
| diag.invalidOverride, |
| 87, |
| 1, |
| contextMessages: [message(testFile, 16, 1)], |
| ), |
| ], |
| ); |
| } |
| |
| test_method_returnType_twoInterfaces() async { |
| await assertErrorsInCode( |
| ''' |
| abstract class I { |
| int m(); |
| } |
| abstract class J { |
| num m(); |
| } |
| abstract class A implements I, J {} |
| class B extends A { |
| String m() => ''; |
| } |
| ''', |
| [ |
| error( |
| diag.invalidOverride, |
| 129, |
| 1, |
| contextMessages: [message(testFile, 25, 1)], |
| ), |
| ], |
| ); |
| } |
| |
| test_method_returnType_void() async { |
| await assertErrorsInCode( |
| ''' |
| class A { |
| int m() { return 0; } |
| } |
| class B extends A { |
| void m() {} |
| } |
| ''', |
| [ |
| error( |
| diag.invalidOverride, |
| 63, |
| 1, |
| contextMessages: [message(testFile, 16, 1)], |
| ), |
| ], |
| ); |
| } |
| |
| test_mixin_field_type_on() async { |
| await assertErrorsInCode( |
| r''' |
| class A { |
| String foo = ''; |
| } |
| |
| mixin M on A { |
| int foo = 0; |
| } |
| ''', |
| [ |
| error( |
| diag.invalidOverride, |
| 53, |
| 3, |
| contextMessages: [message(testFile, 19, 3)], |
| ), |
| error( |
| diag.invalidOverrideSetter, |
| 53, |
| 3, |
| contextMessages: [message(testFile, 19, 3)], |
| ), |
| ], |
| ); |
| } |
| |
| test_mixin_getter_type_on() async { |
| await assertErrorsInCode( |
| r''' |
| class A { |
| String get foo => ''; |
| } |
| |
| mixin M on A { |
| int get foo => 0; |
| } |
| ''', |
| [ |
| error( |
| diag.invalidOverride, |
| 62, |
| 3, |
| contextMessages: [message(testFile, 23, 3)], |
| ), |
| ], |
| ); |
| } |
| |
| test_mixin_method_returnType_on() async { |
| await assertErrorsInCode( |
| r''' |
| class A { |
| String foo() => ''; |
| } |
| |
| mixin M on A { |
| int foo() => 0; |
| } |
| ''', |
| [ |
| error( |
| diag.invalidOverride, |
| 56, |
| 3, |
| contextMessages: [message(testFile, 19, 3)], |
| ), |
| ], |
| ); |
| } |
| |
| @SkippedTest() // TODO(scheglov): implement augmentation |
| test_mixin_method_returnType_on_fromAugmentation() async { |
| await assertErrorsInCode( |
| r''' |
| class A { |
| int foo() => 0; |
| } |
| |
| mixin M { |
| String foo() => ''; |
| } |
| |
| augment mixin M on A {} |
| ''', |
| [ |
| error( |
| diag.invalidOverride, |
| 50, |
| 3, |
| contextMessages: [message(testFile, 16, 3)], |
| ), |
| ], |
| ); |
| } |
| |
| test_mixin_setter_type_on() async { |
| await assertErrorsInCode( |
| r''' |
| class A { |
| set foo(String _) {} |
| } |
| |
| mixin M on A { |
| set foo(int _) {} |
| } |
| ''', |
| [ |
| error( |
| diag.invalidOverrideSetter, |
| 57, |
| 3, |
| contextMessages: [message(testFile, 16, 3)], |
| ), |
| ], |
| ); |
| } |
| |
| test_setter_normalParamType() async { |
| await assertErrorsInCode( |
| ''' |
| class A { |
| void set s(int v) {} |
| } |
| class B extends A { |
| void set s(String v) {} |
| } |
| ''', |
| [ |
| error( |
| diag.invalidOverrideSetter, |
| 66, |
| 1, |
| contextMessages: [message(testFile, 21, 1)], |
| ), |
| ], |
| ); |
| } |
| |
| test_setter_normalParamType_superclass_interface() async { |
| await assertErrorsInCode( |
| ''' |
| abstract class I { |
| set setter14(int _) => null; |
| } |
| abstract class J { |
| set setter14(num _) => null; |
| } |
| abstract class A extends I implements J {} |
| class B extends A { |
| set setter14(String _) => null; |
| } |
| ''', |
| [ |
| error( |
| diag.invalidOverrideSetter, |
| 173, |
| 8, |
| contextMessages: [message(testFile, 77, 8)], |
| ), |
| ], |
| ); |
| } |
| |
| test_setter_normalParamType_twoInterfaces() async { |
| // test from language/override_inheritance_field_test_34.dart |
| await assertErrorsInCode( |
| ''' |
| abstract class I { |
| set setter14(int _) => null; |
| } |
| abstract class J { |
| set setter14(num _) => null; |
| } |
| abstract class A implements I, J {} |
| class B extends A { |
| set setter14(String _) => null; |
| } |
| ''', |
| [ |
| error( |
| diag.invalidOverrideSetter, |
| 166, |
| 8, |
| contextMessages: [message(testFile, 77, 8)], |
| ), |
| ], |
| ); |
| } |
| |
| test_setter_normalParamType_twoInterfaces_conflicting() async { |
| await assertErrorsInCode( |
| ''' |
| abstract class I<U> { |
| set s(U u) {} |
| } |
| abstract class J<V> { |
| set s(V v) {} |
| } |
| class B implements I<int>, J<String> { |
| set s(double d) {} |
| } |
| ''', |
| [ |
| error( |
| diag.invalidOverrideSetter, |
| 125, |
| 1, |
| contextMessages: [message(testFile, 28, 1)], |
| ), |
| error( |
| diag.invalidOverrideSetter, |
| 125, |
| 1, |
| contextMessages: [message(testFile, 68, 1)], |
| ), |
| ], |
| ); |
| } |
| |
| test_setter_overrides_abstract_field_covariant_valid() async { |
| await assertNoErrorsInCode(''' |
| abstract class A { |
| abstract covariant num x; |
| } |
| abstract class B implements A { |
| int get x; |
| void set x(int value); |
| } |
| '''); |
| } |
| |
| test_setter_overrides_abstract_field_final_valid() async { |
| await assertNoErrorsInCode(''' |
| abstract class A { |
| abstract final num x; |
| } |
| abstract class B implements A { |
| int get x; |
| void set x(int value); |
| } |
| '''); |
| } |
| |
| test_setter_overrides_abstract_field_invalid() async { |
| await assertErrorsInCode( |
| ''' |
| abstract class A { |
| abstract num x; |
| } |
| abstract class B implements A { |
| int get x; |
| void set x(int value); |
| } |
| ''', |
| [ |
| error( |
| diag.invalidOverrideSetter, |
| 95, |
| 1, |
| contextMessages: [message(testFile, 34, 1)], |
| messageContains: ["'B.x'"], |
| ), |
| ], |
| ); |
| } |
| |
| test_setter_overrides_abstract_field_valid() async { |
| await assertNoErrorsInCode(''' |
| abstract class A { |
| abstract int x; |
| } |
| abstract class B implements A { |
| void set x(num value); |
| } |
| '''); |
| } |
| |
| test_setter_overrides_external_field_covariant_valid() async { |
| await assertNoErrorsInCode(''' |
| class A { |
| external covariant num x; |
| } |
| abstract class B implements A { |
| int get x; |
| void set x(int value); |
| } |
| '''); |
| } |
| |
| test_setter_overrides_external_field_final_valid() async { |
| await assertNoErrorsInCode(''' |
| class A { |
| external final num x; |
| } |
| abstract class B implements A { |
| int get x; |
| void set x(int value); |
| } |
| '''); |
| } |
| |
| test_setter_overrides_external_field_invalid() async { |
| await assertErrorsInCode( |
| ''' |
| class A { |
| external num x; |
| } |
| abstract class B implements A { |
| int get x; |
| void set x(int value); |
| } |
| ''', |
| [ |
| error( |
| diag.invalidOverrideSetter, |
| 86, |
| 1, |
| contextMessages: [message(testFile, 25, 1)], |
| ), |
| ], |
| ); |
| } |
| |
| test_setter_overrides_external_field_valid() async { |
| await assertNoErrorsInCode(''' |
| class A { |
| external int x; |
| } |
| abstract class B implements A { |
| void set x(num value); |
| } |
| '''); |
| } |
| } |