mirror of
https://github.com/dart-lang/sdk
synced 2024-09-16 03:07:49 +00:00
[analyzer] Add mixin classes to ClassElementImpl
Change-Id: I41cbbf218a9c8d7c26fa8f32e3b8022c51b42789 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/275521 Reviewed-by: Konstantin Shcheglov <scheglov@google.com> Commit-Queue: Kallen Tu <kallentu@google.com>
This commit is contained in:
parent
6d41f47d45
commit
8e1162cb72
|
@ -85,7 +85,7 @@ import 'package:analyzer/src/util/performance/operation_performance.dart';
|
|||
/// TODO(scheglov) Clean up the list of implicitly analyzed files.
|
||||
class AnalysisDriver implements AnalysisDriverGeneric {
|
||||
/// The version of data format, should be incremented on every format change.
|
||||
static const int DATA_VERSION = 253;
|
||||
static const int DATA_VERSION = 254;
|
||||
|
||||
/// The number of exception contexts allowed to write. Once this field is
|
||||
/// zero, we stop writing any new exception contexts in this process.
|
||||
|
|
|
@ -194,6 +194,7 @@ class ToSourceVisitor implements AstVisitor<void> {
|
|||
_visitToken(node.abstractKeyword, suffix: ' ');
|
||||
_visitToken(node.macroKeyword, suffix: ' ');
|
||||
_visitToken(node.sealedKeyword, suffix: ' ');
|
||||
_visitToken(node.mixinKeyword, suffix: ' ');
|
||||
sink.write('class ');
|
||||
_visitToken(node.name);
|
||||
_visitNode(node.typeParameters);
|
||||
|
@ -212,6 +213,7 @@ class ToSourceVisitor implements AstVisitor<void> {
|
|||
_visitToken(node.abstractKeyword, suffix: ' ');
|
||||
_visitToken(node.macroKeyword, suffix: ' ');
|
||||
_visitToken(node.sealedKeyword, suffix: ' ');
|
||||
_visitToken(node.mixinKeyword, suffix: ' ');
|
||||
sink.write('class ');
|
||||
_visitToken(node.name);
|
||||
_visitNode(node.typeParameters);
|
||||
|
|
|
@ -748,6 +748,14 @@ class ClassElementImpl extends ClassOrMixinElementImpl implements ClassElement {
|
|||
setModifier(Modifier.MIXIN_APPLICATION, isMixinApplication);
|
||||
}
|
||||
|
||||
bool get isMixinClass {
|
||||
return hasModifier(Modifier.MIXIN_CLASS);
|
||||
}
|
||||
|
||||
set isMixinClass(bool isMixinClass) {
|
||||
setModifier(Modifier.MIXIN_CLASS, isMixinClass);
|
||||
}
|
||||
|
||||
@override
|
||||
bool get isValidMixin {
|
||||
final supertype = this.supertype;
|
||||
|
@ -4841,29 +4849,32 @@ class Modifier implements Comparable<Modifier> {
|
|||
/// Indicates that a class is a mixin application.
|
||||
static const Modifier MIXIN_APPLICATION = Modifier('MIXIN_APPLICATION', 19);
|
||||
|
||||
static const Modifier PROMOTABLE = Modifier('IS_PROMOTABLE', 20);
|
||||
/// Indicates that a class is a mixin class.
|
||||
static const Modifier MIXIN_CLASS = Modifier('MIXIN_CLASS', 20);
|
||||
|
||||
static const Modifier PROMOTABLE = Modifier('IS_PROMOTABLE', 21);
|
||||
|
||||
/// Indicates that the modifier 'sealed' was applied to the element.
|
||||
static const Modifier SEALED = Modifier('SEALED', 21);
|
||||
static const Modifier SEALED = Modifier('SEALED', 22);
|
||||
|
||||
/// Indicates that the pseudo-modifier 'set' was applied to the element.
|
||||
static const Modifier SETTER = Modifier('SETTER', 22);
|
||||
static const Modifier SETTER = Modifier('SETTER', 23);
|
||||
|
||||
/// See [TypeParameterizedElement.isSimplyBounded].
|
||||
static const Modifier SIMPLY_BOUNDED = Modifier('SIMPLY_BOUNDED', 23);
|
||||
static const Modifier SIMPLY_BOUNDED = Modifier('SIMPLY_BOUNDED', 24);
|
||||
|
||||
/// Indicates that the modifier 'static' was applied to the element.
|
||||
static const Modifier STATIC = Modifier('STATIC', 24);
|
||||
static const Modifier STATIC = Modifier('STATIC', 25);
|
||||
|
||||
/// Indicates that the element does not appear in the source code but was
|
||||
/// implicitly created. For example, if a class does not define any
|
||||
/// constructors, an implicit zero-argument constructor will be created and it
|
||||
/// will be marked as being synthetic.
|
||||
static const Modifier SYNTHETIC = Modifier('SYNTHETIC', 25);
|
||||
static const Modifier SYNTHETIC = Modifier('SYNTHETIC', 26);
|
||||
|
||||
/// Indicates that the element was appended to this enclosing element to
|
||||
/// simulate temporary the effect of applying augmentation.
|
||||
static const Modifier TEMP_AUGMENTATION = Modifier('TEMP_AUGMENTATION', 26);
|
||||
static const Modifier TEMP_AUGMENTATION = Modifier('TEMP_AUGMENTATION', 27);
|
||||
|
||||
static const List<Modifier> values = [
|
||||
ABSTRACT,
|
||||
|
@ -4885,6 +4896,7 @@ class Modifier implements Comparable<Modifier> {
|
|||
LATE,
|
||||
MACRO,
|
||||
MIXIN_APPLICATION,
|
||||
MIXIN_CLASS,
|
||||
PROMOTABLE,
|
||||
SEALED,
|
||||
SETTER,
|
||||
|
|
|
@ -95,6 +95,7 @@ class ElementBuilder extends ThrowingAstVisitor<void> {
|
|||
element.isSealed = true;
|
||||
element.isAbstract = true;
|
||||
}
|
||||
element.isMixinClass = node.mixinKeyword != null;
|
||||
element.metadata = _buildAnnotations(node.metadata);
|
||||
_setCodeRange(element, node);
|
||||
_setDocumentation(element, node);
|
||||
|
@ -133,6 +134,7 @@ class ElementBuilder extends ThrowingAstVisitor<void> {
|
|||
element.isAbstract = true;
|
||||
}
|
||||
element.isMixinApplication = true;
|
||||
element.isMixinClass = node.mixinKeyword != null;
|
||||
element.metadata = _buildAnnotations(node.metadata);
|
||||
_setCodeRange(element, node);
|
||||
_setDocumentation(element, node);
|
||||
|
|
|
@ -10,14 +10,16 @@ class ClassElementFlags {
|
|||
static const int _isAbstract = 1 << 0;
|
||||
static const int _isMacro = 1 << 1;
|
||||
static const int _isMixinApplication = 1 << 2;
|
||||
static const int _isSealed = 1 << 3;
|
||||
static const int _isSimplyBounded = 1 << 4;
|
||||
static const int _isMixinClass = 1 << 3;
|
||||
static const int _isSealed = 1 << 4;
|
||||
static const int _isSimplyBounded = 1 << 5;
|
||||
|
||||
static void read(SummaryDataReader reader, ClassElementImpl element) {
|
||||
var byte = reader.readByte();
|
||||
element.isAbstract = (byte & _isAbstract) != 0;
|
||||
element.isMacro = (byte & _isMacro) != 0;
|
||||
element.isMixinApplication = (byte & _isMixinApplication) != 0;
|
||||
element.isMixinClass = (byte & _isMixinClass) != 0;
|
||||
element.isSealed = (byte & _isSealed) != 0;
|
||||
element.isSimplyBounded = (byte & _isSimplyBounded) != 0;
|
||||
}
|
||||
|
@ -27,6 +29,7 @@ class ClassElementFlags {
|
|||
result |= element.isAbstract ? _isAbstract : 0;
|
||||
result |= element.isMacro ? _isMacro : 0;
|
||||
result |= element.isMixinApplication ? _isMixinApplication : 0;
|
||||
result |= element.isMixinClass ? _isMixinClass : 0;
|
||||
result |= element.isSealed ? _isSealed : 0;
|
||||
result |= element.isSimplyBounded ? _isSimplyBounded : 0;
|
||||
sink.writeByte(result);
|
||||
|
|
|
@ -437,6 +437,16 @@ macro class A {}
|
|||
);
|
||||
}
|
||||
|
||||
void test_visitClassDeclaration_mixin() {
|
||||
var findNode = _parseStringToFindNode(r'''
|
||||
mixin class A {}
|
||||
''');
|
||||
_assertSource(
|
||||
'mixin class A {}',
|
||||
findNode.classDeclaration('class A'),
|
||||
);
|
||||
}
|
||||
|
||||
void test_visitClassDeclaration_multipleMember() {
|
||||
final code = 'class C {var a; var b;}';
|
||||
final findNode = _parseStringToFindNode('''
|
||||
|
@ -590,6 +600,16 @@ $code
|
|||
_assertSource(code, findNode.classTypeAlias(code));
|
||||
}
|
||||
|
||||
void test_visitClassTypeAlias_mixin() {
|
||||
var findNode = _parseStringToFindNode(r'''
|
||||
mixin class A = S with M;
|
||||
''');
|
||||
_assertSource(
|
||||
'mixin class A = S with M;',
|
||||
findNode.classTypeAlias('class A'),
|
||||
);
|
||||
}
|
||||
|
||||
void test_visitClassTypeAlias_parameters_abstract() {
|
||||
final code = 'abstract class C<E> = S with M;';
|
||||
final findNode = _parseStringToFindNode('''
|
||||
|
|
|
@ -291,6 +291,7 @@ class _ElementWriter {
|
|||
_writeIf(e.isAbstract, 'abstract ');
|
||||
_writeIf(e.isMacro, 'macro ');
|
||||
_writeIf(e.isSealed, 'sealed ');
|
||||
_writeIf(e.isMixinClass, 'mixin ');
|
||||
}
|
||||
_writeIf(!e.isSimplyBounded, 'notSimplyBounded ');
|
||||
|
||||
|
@ -1088,6 +1089,11 @@ extension on ClassElement {
|
|||
return self is ClassElementImpl && self.isMacro;
|
||||
}
|
||||
|
||||
bool get isMixinClass {
|
||||
final self = this;
|
||||
return self is ClassElementImpl && self.isMixinClass;
|
||||
}
|
||||
|
||||
bool get isSealed {
|
||||
final self = this;
|
||||
return self is ClassElementImpl && self.isSealed;
|
||||
|
|
|
@ -6828,6 +6828,18 @@ library
|
|||
''');
|
||||
}
|
||||
|
||||
test_class_mixin_class() async {
|
||||
var library = await buildLibrary('mixin class C {}');
|
||||
checkElementText(library, r'''
|
||||
library
|
||||
definingUnit
|
||||
classes
|
||||
mixin class C @12
|
||||
constructors
|
||||
synthetic @-1
|
||||
''');
|
||||
}
|
||||
|
||||
test_class_mixins() async {
|
||||
var library = await buildLibrary('''
|
||||
class C extends D with E, F, G {}
|
||||
|
@ -8931,6 +8943,35 @@ library
|
|||
''');
|
||||
}
|
||||
|
||||
test_classAlias_mixin_class() async {
|
||||
var library = await buildLibrary('''
|
||||
mixin class C = Object with M;
|
||||
mixin M {}
|
||||
''');
|
||||
checkElementText(library, r'''
|
||||
library
|
||||
definingUnit
|
||||
classes
|
||||
mixin class alias C @12
|
||||
supertype: Object
|
||||
mixins
|
||||
M
|
||||
constructors
|
||||
synthetic const @-1
|
||||
constantInitializers
|
||||
SuperConstructorInvocation
|
||||
superKeyword: super @0
|
||||
argumentList: ArgumentList
|
||||
leftParenthesis: ( @0
|
||||
rightParenthesis: ) @0
|
||||
staticElement: dart:core::@class::Object::@constructor::new
|
||||
mixins
|
||||
mixin M @37
|
||||
superclassConstraints
|
||||
Object
|
||||
''');
|
||||
}
|
||||
|
||||
test_classAlias_notSimplyBounded_self() async {
|
||||
var library = await buildLibrary('''
|
||||
class C<T extends C> = D with E;
|
||||
|
|
Loading…
Reference in a new issue