| // Copyright (c) 2017, 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.md file. |
| |
| // @dart = 2.9 |
| |
| library fasta.test.incremental_dynamic_test; |
| |
| import "package:_fe_analyzer_shared/src/messages/diagnostic_message.dart" |
| show |
| DiagnosticMessage, |
| DiagnosticMessageHandler, |
| getMessageCodeObject, |
| getMessageArguments; |
| |
| import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity; |
| |
| import 'package:async_helper/async_helper.dart' show asyncTest; |
| |
| import 'package:expect/expect.dart' show Expect; |
| |
| import 'package:kernel/target/targets.dart' show NoneTarget, TargetFlags; |
| |
| import "package:front_end/src/api_prototype/compiler_options.dart" |
| show CompilerOptions; |
| |
| import 'package:front_end/src/testing/compiler_common.dart' show compileScript; |
| |
| import 'package:front_end/src/fasta/fasta_codes.dart' |
| show codeSuperclassHasNoMethod; |
| |
| /// A subclass of NoneTarget that enables Flutter style super-mixin semantics. |
| /// |
| /// See dartbug.com/31542 for details of the semantics. |
| class NoneTargetWithSuperMixins extends NoneTarget { |
| NoneTargetWithSuperMixins(TargetFlags flags) : super(flags); |
| |
| @override |
| bool get enableSuperMixins => true; |
| } |
| |
| const String testSource = ''' |
| abstract class A { |
| void foo(String value); |
| } |
| |
| abstract class B { |
| void bar(String value); |
| } |
| |
| abstract class Mixin extends A with B { |
| void bar(String value) { |
| // CFE should report an error on the line below under the normal |
| // Dart 2 semantics, because super invocation targets abstract |
| // member. However when enableSuperMixins is set |
| // in the Target the error should be suppressed. |
| super.bar(value); |
| // This line should always trigger an error, irrespective of |
| // whether super-mixins semantics is enabled or disabled. |
| super.baz(); |
| } |
| } |
| |
| class NotMixin extends A with B { |
| void bar(String value) { |
| // Both of these should be reported as error independently |
| // of super-mixins semantics because NotMixin is not an abstract |
| // class. |
| super.foo(value); |
| super.quux(); |
| } |
| |
| void foo(String value) {} |
| } |
| |
| void main() { |
| // Dummy main to avoid warning. |
| } |
| '''; |
| |
| DiagnosticMessageHandler _makeDiagnosticMessageHandler(Set<String> names) { |
| return (DiagnosticMessage message) { |
| Expect.equals(Severity.error, message.severity); |
| Expect.identical(codeSuperclassHasNoMethod, getMessageCodeObject(message)); |
| Expect.isTrue(message.plainTextFormatted.length == 1); |
| names.add(getMessageArguments(message)['name']); |
| }; |
| } |
| |
| /// Check that by default an error is reported for all unresolved super |
| /// invocations: independently of weather they target abstract super members |
| /// or nonexistent targets. |
| testDisabledSuperMixins() async { |
| var missingSuperMethodNames = new Set<String>(); |
| var options = new CompilerOptions() |
| ..onDiagnostic = _makeDiagnosticMessageHandler(missingSuperMethodNames); |
| await compileScript(testSource, options: options); |
| Expect.setEquals( |
| const <String>['bar', 'baz', 'foo', 'quux'], missingSuperMethodNames); |
| } |
| |
| /// Check that in an abstract class an error is reported only for a |
| /// super-invocation that targets an non-existent method, a super-invocation |
| /// that targets an abstract member of the super-class should not be reported. |
| /// In non-abstract class we should report both cases as an error. |
| testEnabledSuperMixins() async { |
| var missingSuperMethodNames = new Set<String>(); |
| var options = new CompilerOptions() |
| ..onDiagnostic = _makeDiagnosticMessageHandler(missingSuperMethodNames) |
| ..target = new NoneTargetWithSuperMixins(new TargetFlags()); |
| await compileScript(testSource, options: options); |
| Expect.setEquals( |
| const <String>['baz', 'foo', 'quux'], missingSuperMethodNames); |
| } |
| |
| void main() { |
| asyncTest(() async { |
| await testDisabledSuperMixins(); |
| await testEnabledSuperMixins(); |
| }); |
| } |