Mark Kernel classes that were Dart mixin declarations

Add a flag to Kernel classes that indicates that they were Dart mixin
declarations.  Also, add an API to Kernel Class that allows a list of
superclass constraints to be gotten from it.

Change-Id: Ie78e7e56b5421dfb9d340e4330135b8d6f4e94f1
Reviewed-on: https://dart-review.googlesource.com/75261
Commit-Queue: Kevin Millikin <kmillikin@google.com>
Reviewed-by: Peter von der Ahé <ahe@google.com>
Reviewed-by: Dmitry Stefantsov <dmitryas@google.com>
This commit is contained in:
Kevin Millikin 2018-09-20 15:10:12 +00:00 committed by commit-bot@chromium.org
parent c688d0c0c3
commit 2e43557274
7 changed files with 61 additions and 9 deletions

View file

@ -88,7 +88,8 @@ class KernelEnumBuilder extends SourceClassBuilder
int startCharOffset,
int charOffset)
: super(metadata, 0, name, null, null, null, scope, constructors, parent,
null, startCharOffset, charOffset, TreeNode.noOffset, cls);
null, startCharOffset, charOffset, TreeNode.noOffset,
cls: cls);
factory KernelEnumBuilder(
MetadataCollector metadataCollector,

View file

@ -62,7 +62,11 @@ import '../import.dart' show Import;
import '../loader.dart' show Loader;
import '../modifier.dart'
show abstractMask, namedMixinApplicationMask, staticMask;
show
abstractMask,
mixinDeclarationMask,
namedMixinApplicationMask,
staticMask;
import '../problems.dart' show unexpected, unhandled;
@ -216,6 +220,11 @@ class KernelLibraryBuilder
// library scope.
Scope constructorScope = new Scope(constructors, null, null, "constructors",
isModifiable: false);
bool isMixinDeclaration = false;
if (modifiers & mixinDeclarationMask != 0) {
isMixinDeclaration = true;
modifiers = (modifiers & ~mixinDeclarationMask) | abstractMask;
}
ClassBuilder cls = new SourceClassBuilder(
metadata,
modifiers,
@ -230,7 +239,8 @@ class KernelLibraryBuilder
new List<ConstructorReferenceBuilder>.from(constructorReferences),
startCharOffset,
charOffset,
charEndOffset);
charEndOffset,
isMixinDeclaration: isMixinDeclaration);
loader.target.metadataCollector
?.setDocumentationComment(cls.target, documentationComment);
@ -470,8 +480,7 @@ class KernelLibraryBuilder
startCharOffset,
charOffset,
TreeNode.noOffset,
null,
mixin);
mixedInType: mixin);
if (isNamedMixinApplication) {
loader.target.metadataCollector?.setDocumentationComment(
application.target, documentationComment);

View file

@ -32,6 +32,10 @@ const int staticMask = finalMask << 1;
const int namedMixinApplicationMask = staticMask << 1;
/// Not a modifier, used for mixins declared explicitly by using the `mixin`
/// keyword.
const int mixinDeclarationMask = namedMixinApplicationMask << 1;
/// Not a real modifier, and by setting it to zero, it is automatically ignored
/// by [Modifier.validate] below.
const int varMask = 0;

View file

@ -59,6 +59,7 @@ import '../modifier.dart'
constMask,
covariantMask,
externalMask,
mixinDeclarationMask,
staticMask;
import '../operator.dart'
@ -535,7 +536,7 @@ class OutlineBuilder extends StackListener {
library.addClass(
documentationComment,
metadata,
abstractMask,
mixinDeclarationMask,
name,
typeVariables,
supertype,

View file

@ -80,6 +80,8 @@ class SourceClassBuilder extends KernelClassBuilder {
KernelTypeBuilder mixedInType;
bool isMixinDeclaration;
SourceClassBuilder(
List<MetadataBuilder> metadata,
int modifiers,
@ -94,8 +96,9 @@ class SourceClassBuilder extends KernelClassBuilder {
int startCharOffset,
int charOffset,
int charEndOffset,
[ShadowClass cls,
this.mixedInType])
{Class cls,
this.mixedInType,
this.isMixinDeclaration = false})
: actualCls = initializeClass(cls, typeVariables, name, parent,
startCharOffset, charOffset, charEndOffset),
super(metadata, modifiers, name, typeVariables, supertype, interfaces,
@ -141,6 +144,7 @@ class SourceClassBuilder extends KernelClassBuilder {
supertype?.buildSupertype(library, charOffset, fileUri);
actualCls.mixedInType =
mixedInType?.buildMixedInType(library, charOffset, fileUri);
actualCls.isMixinDeclaration = isMixinDeclaration;
// TODO(ahe): If `cls.supertype` is null, and this isn't Object, report a
// compile-time error.
cls.isAbstract = isAbstract;

View file

@ -291,7 +291,7 @@ type Class extends Node {
FileOffset fileOffset; // Offset of the name of the class.
FileOffset fileEndOffset;
Byte flags (levelBit0, levelBit1, isAbstract, isEnum, isAnonymousMixin,
isEliminatedMixin); // Where level is index into ClassLevel
isEliminatedMixin, isMixinDeclaration); // Where level is index into ClassLevel
StringReference name;
List<Expression> annotations;
List<TypeParameter> typeParameters;

View file

@ -728,6 +728,7 @@ class Class extends NamedNode implements FileUriNode {
static const int FlagEnum = 1 << 3;
static const int FlagAnonymousMixin = 1 << 4;
static const int FlagEliminatedMixin = 1 << 5;
static const int FlagMixinDeclaration = 1 << 6;
int flags = 0;
@ -774,6 +775,38 @@ class Class extends NamedNode implements FileUriNode {
value ? (flags | FlagEliminatedMixin) : (flags & ~FlagEliminatedMixin);
}
/// True if this class was a mixin declaration in Dart.
///
/// Mixins are declared in Dart with the `mixin` keyword. They are compiled
/// to Kernel classes.
bool get isMixinDeclaration => flags & FlagMixinDeclaration != 0;
void set isMixinDeclaration(bool value) {
flags = value
? (flags | FlagMixinDeclaration)
: (flags & ~FlagMixinDeclaration);
}
List<Supertype> superclassConstraints() {
var constraints = <Supertype>[];
// Not a mixin declaration.
if (!isMixinDeclaration) return constraints;
Class previous = this;
Class current = supertype.classNode;
// Otherwise we have a left-linear binary tree (subtrees are supertype and
// mixedInType) of constraints, where all the interior nodes are anonymous
// mixin applications.
while (current != null && current.isAnonymousMixin) {
constraints.add(current.mixedInType);
previous = current;
current = current.supertype.classNode;
}
return constraints..add(previous.supertype);
}
/// The URI of the source file this class was loaded from.
Uri fileUri;