Ensure that Object doesn't have supertypes
Change-Id: Ife632785bdac0d26fb6db1463636fd9a1fec51e1 Reviewed-on: https://dart-review.googlesource.com/c/86201 Commit-Queue: Peter von der Ahé <ahe@google.com> Reviewed-by: Dmitry Stefantsov <dmitryas@google.com>
This commit is contained in:
committed by
commit-bot@chromium.org
parent
1046bf66d4
commit
8cb7ab9567
@@ -6697,6 +6697,28 @@ Message _withArgumentsNotConstantExpression(String string) {
|
||||
arguments: {'string': string});
|
||||
}
|
||||
|
||||
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
|
||||
const Code<Null> codeObjectExtends = messageObjectExtends;
|
||||
|
||||
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
|
||||
const MessageCode messageObjectExtends = const MessageCode("ObjectExtends",
|
||||
message: r"""The class 'Object' can't have a superclass.""");
|
||||
|
||||
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
|
||||
const Code<Null> codeObjectImplements = messageObjectImplements;
|
||||
|
||||
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
|
||||
const MessageCode messageObjectImplements = const MessageCode(
|
||||
"ObjectImplements",
|
||||
message: r"""The class 'Object' can't implement anything.""");
|
||||
|
||||
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
|
||||
const Code<Null> codeObjectMixesIn = messageObjectMixesIn;
|
||||
|
||||
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
|
||||
const MessageCode messageObjectMixesIn = const MessageCode("ObjectMixesIn",
|
||||
message: r"""The class 'Object' can't use mixins.""");
|
||||
|
||||
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
|
||||
const Code<Null> codeOnlyTry = messageOnlyTry;
|
||||
|
||||
|
||||
@@ -646,9 +646,9 @@ abstract class KernelClassBuilder
|
||||
isInterfaceCheck: true);
|
||||
}
|
||||
|
||||
bool hasNoSuchMethod =
|
||||
hierarchy.getDispatchTarget(cls, noSuchMethodName).enclosingClass !=
|
||||
coreTypes.objectClass;
|
||||
Member noSuchMethod = hierarchy.getDispatchTarget(cls, noSuchMethodName);
|
||||
bool hasNoSuchMethod = noSuchMethod != null &&
|
||||
noSuchMethod.enclosingClass != coreTypes.objectClass;
|
||||
|
||||
void findMissingImplementations({bool setters}) {
|
||||
List<Member> dispatchTargets =
|
||||
|
||||
@@ -271,7 +271,7 @@ class KernelTarget extends TargetImplementation {
|
||||
loader.resolveTypes();
|
||||
loader.computeDefaultTypes(dynamicType, bottomType, objectClassBuilder);
|
||||
List<SourceClassBuilder> myClasses = collectMyClasses();
|
||||
loader.checkSemantics(myClasses);
|
||||
loader.checkSemantics(myClasses, objectClassBuilder);
|
||||
loader.finishTypeVariables(objectClassBuilder, dynamicType);
|
||||
loader.buildComponent();
|
||||
installDefaultSupertypes();
|
||||
|
||||
@@ -47,6 +47,9 @@ import '../fasta_codes.dart'
|
||||
Message,
|
||||
SummaryTemplate,
|
||||
Template,
|
||||
messageObjectExtends,
|
||||
messageObjectImplements,
|
||||
messageObjectMixesIn,
|
||||
messagePartOrphan,
|
||||
noLength,
|
||||
templateAmbiguousSupertypes,
|
||||
@@ -552,7 +555,32 @@ class SourceLoader<L> extends Loader<L> {
|
||||
return output;
|
||||
}
|
||||
|
||||
void checkSemantics(List<SourceClassBuilder> classes) {
|
||||
/// Check that [objectClass] has no supertypes. Recover by removing any
|
||||
/// found.
|
||||
void checkObjectClassHierarchy(ClassBuilder objectClass) {
|
||||
if (objectClass is SourceClassBuilder &&
|
||||
objectClass.library.loader == this) {
|
||||
if (objectClass.supertype != null) {
|
||||
objectClass.supertype = null;
|
||||
objectClass.addProblem(
|
||||
messageObjectExtends, objectClass.charOffset, noLength);
|
||||
}
|
||||
if (objectClass.interfaces != null) {
|
||||
objectClass.addProblem(
|
||||
messageObjectImplements, objectClass.charOffset, noLength);
|
||||
objectClass.interfaces = null;
|
||||
}
|
||||
if (objectClass.mixedInType != null) {
|
||||
objectClass.addProblem(
|
||||
messageObjectMixesIn, objectClass.charOffset, noLength);
|
||||
objectClass.mixedInType = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void checkSemantics(
|
||||
List<SourceClassBuilder> classes, ClassBuilder objectClass) {
|
||||
checkObjectClassHierarchy(objectClass);
|
||||
Iterable<ClassBuilder> candidates = cyclicCandidates(classes);
|
||||
if (candidates.isNotEmpty) {
|
||||
Map<ClassBuilder, Set<ClassBuilder>> realCycles =
|
||||
|
||||
@@ -3364,3 +3364,18 @@ TypeOriginWithFileUri:
|
||||
template: "'#name' is from '#uri' ('#uri2')."
|
||||
frontendInternal: true
|
||||
external: test/type_labeler_test.dart
|
||||
|
||||
ObjectExtends:
|
||||
template: "The class 'Object' can't have a superclass."
|
||||
frontendInternal: true
|
||||
external: test/fasta/object_supertype_test.dart
|
||||
|
||||
ObjectImplements:
|
||||
template: "The class 'Object' can't implement anything."
|
||||
frontendInternal: true
|
||||
external: test/fasta/object_supertype_test.dart
|
||||
|
||||
ObjectMixesIn:
|
||||
template: "The class 'Object' can't use mixins."
|
||||
frontendInternal: true
|
||||
external: test/fasta/object_supertype_test.dart
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
// Copyright (c) 2018, 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 "dart:convert" show json;
|
||||
|
||||
import "package:async_helper/async_helper.dart" show asyncTest;
|
||||
|
||||
import "package:expect/expect.dart" show Expect;
|
||||
|
||||
import "package:front_end/src/api_prototype/compiler_options.dart"
|
||||
show CompilerOptions;
|
||||
|
||||
import "package:front_end/src/api_prototype/diagnostic_message.dart"
|
||||
show DiagnosticMessage, getMessageCodeObject;
|
||||
|
||||
import "package:front_end/src/api_prototype/memory_file_system.dart"
|
||||
show MemoryFileSystem;
|
||||
|
||||
import "package:front_end/src/base/processed_options.dart"
|
||||
show ProcessedOptions;
|
||||
|
||||
import "package:front_end/src/fasta/compiler_context.dart" show CompilerContext;
|
||||
|
||||
import "package:front_end/src/fasta/messages.dart"
|
||||
show Code, codeObjectExtends, codeObjectImplements, codeObjectMixesIn;
|
||||
|
||||
import "package:front_end/src/fasta/source/source_loader.dart"
|
||||
show defaultDartCoreSource;
|
||||
|
||||
import "package:front_end/src/fasta/ticker.dart" show Ticker;
|
||||
|
||||
import "../../tool/_fasta/entry_points.dart" show CompileTask;
|
||||
|
||||
Future<List<DiagnosticMessage>> outline(String objectHeader) async {
|
||||
final Ticker ticker = new Ticker(isVerbose: false);
|
||||
final Uri base = Uri.parse("org-dartlang-test:///");
|
||||
|
||||
final MemoryFileSystem fs = new MemoryFileSystem(base);
|
||||
|
||||
final Uri librariesSpecificationUri = base.resolve("sdk/libraries.json");
|
||||
|
||||
fs.entityForUri(librariesSpecificationUri).writeAsStringSync(json.encode({
|
||||
"none": {
|
||||
"libraries": {
|
||||
"core": {
|
||||
"uri": "lib/core/core.dart",
|
||||
},
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
fs.entityForUri(base.resolve("sdk/lib/core/core.dart")).writeAsStringSync(
|
||||
defaultDartCoreSource.replaceAll("class Object {", "$objectHeader"));
|
||||
|
||||
final List<DiagnosticMessage> messages = <DiagnosticMessage>[];
|
||||
|
||||
CompilerContext context = new CompilerContext(new ProcessedOptions(
|
||||
options: new CompilerOptions()
|
||||
..onDiagnostic = messages.add
|
||||
..sdkRoot = base.resolve("sdk/")
|
||||
..fileSystem = fs
|
||||
..compileSdk = true
|
||||
..librariesSpecificationUri = librariesSpecificationUri,
|
||||
inputs: [Uri.parse("dart:core")]));
|
||||
|
||||
await context.runInContext<void>((_) async {
|
||||
CompileTask task = new CompileTask(context, ticker);
|
||||
await task.buildOutline();
|
||||
});
|
||||
return messages;
|
||||
}
|
||||
|
||||
test() async {
|
||||
Set<String> normalErrors = (await outline("class Object {"))
|
||||
.map((DiagnosticMessage message) => getMessageCodeObject(message).name)
|
||||
.toSet();
|
||||
|
||||
check(String objectHeader, List<Code> expectedCodes) async {
|
||||
List<DiagnosticMessage> messages = (await outline(objectHeader))
|
||||
.where((DiagnosticMessage message) =>
|
||||
!normalErrors.contains(getMessageCodeObject(message).name))
|
||||
.toList();
|
||||
Expect.setEquals(
|
||||
expectedCodes,
|
||||
messages.map((DiagnosticMessage m) => getMessageCodeObject(m)),
|
||||
objectHeader);
|
||||
}
|
||||
|
||||
await check("class Object extends String {", <Code>[codeObjectExtends]);
|
||||
|
||||
await check(
|
||||
"class Object implements String, bool {", <Code>[codeObjectImplements]);
|
||||
|
||||
await check("class Object = Object with bool ; class Blah {",
|
||||
<Code>[codeObjectExtends, codeObjectMixesIn]);
|
||||
}
|
||||
|
||||
main() {
|
||||
asyncTest(test);
|
||||
}
|
||||
Reference in New Issue
Block a user