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:
Peter von der Ahé
2018-12-12 10:55:29 +00:00
committed by commit-bot@chromium.org
parent 1046bf66d4
commit 8cb7ab9567
6 changed files with 171 additions and 5 deletions
@@ -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 =
+15
View File
@@ -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);
}