[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:
Kallen Tu 2022-12-15 19:20:06 +00:00 committed by Commit Queue
parent 6d41f47d45
commit 8e1162cb72
8 changed files with 96 additions and 10 deletions

View file

@ -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.

View file

@ -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);

View file

@ -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,

View file

@ -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);

View file

@ -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);

View file

@ -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('''

View file

@ -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;

View file

@ -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;