// 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:expect/expect.dart"; // Tests the resolution of multiple applicable extensions. String? lastSetterValue; class SuperTarget {} class Target extends SuperTarget { String targetMethod() => "targetMethod"; String get targetGetter => "targetGetter"; void set targetSetter(String argument) { lastSetterValue = "targetSetter: $argument"; } } class SubTarget extends Target { String subTargetMethod() => "subTargetMethod"; String get subTargetGetter => "subTargetGetter"; void set subTargetSetter(String argument) { lastSetterValue = "subTargetSetter: $argument"; } } extension E1 on SubTarget { static String name = "SubTarget"; String e1() => "$name.e1"; String targetMethod() => "$name.targetMethod"; String get targetGetter => "$name.targetGetter"; void set targetSetter(String value) { lastSetterValue = "$name.targetSetter: $value"; } String subTargetMethod() => "$name.subTargetMethod"; String get subTargetGetter => "$name.subTargetGetter"; void set subTargetSetter(String value) { lastSetterValue = "$name.subTargetSetter: $value"; } List get typedList => []; } extension E2 on SubTarget { static String name = "SubTarget"; String e1() => "$name.e1"; String e2() => "$name.e2"; String targetMethod() => "$name.targetMethod"; String get targetGetter => "$name.targetGetter"; void set targetSetter(String value) { lastSetterValue = "$name.targetSetter: $value"; } String subTargetMethod() => "$name.subTargetMethod"; String get subTargetGetter => "$name.subTargetGetter"; void set subTargetSetter(String value) { lastSetterValue = "$name.subTargetSetter: $value"; } } extension E3 on Target { static String name = "Target"; String e1() => "$name.e1"; String e2() => "$name.e2"; String e3() => "$name.e3"; String targetMethod() => "$name.targetMethod"; String get targetGetter => "$name.targetGetter"; void set targetSetter(String value) { lastSetterValue = "$name.targetSetter: $value"; } String subTargetMethod() => "$name.subTargetMethod"; String get subTargetGetter => "$name.subTargetGetter"; void set subTargetSetter(String value) { lastSetterValue = "$name.subTargetSetter: $value"; } List get typedList => []; } extension E4 on Target { static String name = "Target"; String e1() => "$name.e1"; String e2() => "$name.e2"; String e3() => "$name.e3"; String e4() => "$name.e4"; String targetMethod() => "$name.targetMethod"; String get targetGetter => "$name.targetGetter"; void set targetSetter(String value) { lastSetterValue = "$name.targetSetter: $value"; } String subTargetMethod() => "$name.subTargetMethod"; String get subTargetGetter => "$name.subTargetGetter"; void set subTargetSetter(String value) { lastSetterValue = "$name.subTargetSetter: $value"; } } extension E5 on T { static String name = "T"; String e1() => "$name.e1"; String e2() => "$name.e2"; String e3() => "$name.e3"; String e4() => "$name.e4"; String e5() => "$name.e5"; String targetMethod() => "$name.targetMethod"; String get targetGetter => "$name.targetGetter"; void set targetSetter(String value) { lastSetterValue = "$name.targetSetter: $value"; } String subTargetMethod() => "$name.subTargetMethod"; String get subTargetGetter => "$name.subTargetGetter"; void set subTargetSetter(String value) { lastSetterValue = "$name.subTargetSetter: $value"; } List get typedList => []; } extension E6 on Object { static String name = "Object"; String e1() => "$name.e1"; String e2() => "$name.e2"; String e3() => "$name.e3"; String e4() => "$name.e4"; String e5() => "$name.e5"; String e6() => "$name.e6"; String targetMethod() => "$name.targetMethod"; String get targetGetter => "$name.targetGetter"; void set targetSetter(String value) { lastSetterValue = "$name.targetSetter: $value"; } String subTargetMethod() => "$name.subTargetMethod"; String get subTargetGetter => "$name.subTargetGetter"; void set subTargetSetter(String value) { lastSetterValue = "$name.subTargetSetter: $value"; } } main() { SubTarget s1 = SubTarget(); Target t1 = SubTarget(); SuperTarget o1 = SubTarget(); Target ti1 = SubTarget(); ; SubTarget si1 = SubTarget(); ; // Interface methods take precedence. Expect.equals("targetGetter", s1.targetGetter); Expect.equals("targetMethod", s1.targetMethod()); s1.targetSetter = "1"; Expect.equals("targetSetter: 1", lastSetterValue); Expect.equals("subTargetGetter", s1.subTargetGetter); Expect.equals("subTargetMethod", s1.subTargetMethod()); s1.subTargetSetter = "2"; Expect.equals("subTargetSetter: 2", lastSetterValue); Expect.equals("targetGetter", t1.targetGetter); Expect.equals("targetMethod", t1.targetMethod()); t1.targetSetter = "3"; Expect.equals("targetSetter: 3", lastSetterValue); // Methods not on the instance resolve to extension methods. Expect.equals("Target.subTargetGetter", t1.subTargetGetter); Expect.equals("Target.subTargetMethod", t1.subTargetMethod()); t1.subTargetSetter = "4"; Expect.equals("Target.subTargetSetter: 4", lastSetterValue); Expect.type>(ti1.typedList); Expect.type>(si1.typedList); Expect.type>(o1.typedList); // Extension methods can be called directly using override syntax. Expect.equals("SubTarget.targetGetter", E1(si1).targetGetter); Expect.equals("SubTarget.targetMethod", E1(si1).targetMethod()); E1(si1).targetSetter = "5"; Expect.equals("SubTarget.targetSetter: 5", lastSetterValue); Expect.equals("SubTarget.subTargetGetter", E1(si1).subTargetGetter); Expect.equals("SubTarget.subTargetMethod", E1(si1).subTargetMethod()); E1(si1).subTargetSetter = "6"; Expect.equals("SubTarget.subTargetSetter: 6", lastSetterValue); Expect.type>(E1(si1).typedList); // Applicable methods. Expect.equals("SubTarget.e1", s1.e1()); Expect.equals("T.e2", s1.e2()); Expect.equals("T.e3", s1.e3()); Expect.equals("T.e4", s1.e4()); Expect.equals("T.e5", s1.e5()); Expect.equals("Object.e6", s1.e6()); Expect.equals("Target.e1", t1.e1()); Expect.equals("Target.e2", t1.e2()); Expect.equals("Target.e3", t1.e3()); Expect.equals("T.e4", t1.e4()); Expect.equals("T.e5", t1.e5()); Expect.equals("Object.e6", t1.e6()); Expect.equals("T.e1", o1.e1()); Expect.equals("T.e2", o1.e2()); Expect.equals("T.e3", o1.e3()); Expect.equals("T.e4", o1.e4()); Expect.equals("T.e5", o1.e5()); Expect.equals("Object.e6", o1.e6()); }