Skip to content

Commit d96cecb

Browse files
johnniwintherCommit Queue
authored andcommitted
[_fe_analyzer_shared] Support mixins in macro metadata
Change-Id: I1eec1feb0230fa938b727c8eff88a048a53794be Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/391660 Reviewed-by: Konstantin Shcheglov <[email protected]> Reviewed-by: Jens Johansen <[email protected]>
1 parent 0d93251 commit d96cecb

File tree

7 files changed

+398
-1
lines changed

7 files changed

+398
-1
lines changed

pkg/_fe_analyzer_shared/lib/src/metadata/proto.dart

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -622,6 +622,112 @@ class GenericEnumProto extends Proto {
622622
}
623623
}
624624

625+
/// A [reference] to a mixin
626+
///
627+
/// The [Proto] includes the [scope] of the mixin, which is used to resolve
628+
/// access to static members on the mixin.
629+
class MixinProto extends Proto {
630+
final MixinReference reference;
631+
final TypeDeclarationScope scope;
632+
633+
MixinProto(this.reference, this.scope);
634+
635+
@override
636+
String toString() => 'MixinProto($reference)';
637+
638+
@override
639+
Proto access(String? name) {
640+
if (name == null) {
641+
return this;
642+
}
643+
if (name == 'new') {
644+
name = '';
645+
}
646+
return scope.lookup(name);
647+
}
648+
649+
@override
650+
Proto instantiate(List<TypeAnnotation>? typeArguments) {
651+
return typeArguments != null
652+
? new GenericMixinProto(reference, scope, typeArguments)
653+
: this;
654+
}
655+
656+
@override
657+
Proto invoke(List<Argument>? arguments) {
658+
return arguments != null
659+
? new InvalidInvocationProto(this, const [], arguments)
660+
: this;
661+
}
662+
663+
@override
664+
Expression toExpression() {
665+
return new TypeLiteral(toTypeAnnotation());
666+
}
667+
668+
@override
669+
TypeAnnotation toTypeAnnotation() => new NamedTypeAnnotation(reference);
670+
671+
@override
672+
Proto? resolve() => null;
673+
}
674+
675+
/// A [reference] to an enum instantiated with [typeArguments].
676+
///
677+
/// The [Proto] includes the [scope] of the enum, which is used to resolve
678+
/// access to constructors on the enum.
679+
class GenericMixinProto extends Proto {
680+
final MixinReference reference;
681+
final TypeDeclarationScope scope;
682+
final List<TypeAnnotation> typeArguments;
683+
684+
GenericMixinProto(this.reference, this.scope, this.typeArguments);
685+
686+
@override
687+
String toString() => 'GenericMixinProto($reference,$typeArguments)';
688+
689+
@override
690+
Proto access(String? name) {
691+
if (name == null) {
692+
return this;
693+
}
694+
if (name == 'new') {
695+
name = '';
696+
}
697+
return scope.lookup(name, typeArguments);
698+
}
699+
700+
@override
701+
Proto instantiate(List<TypeAnnotation>? typeArguments) {
702+
return typeArguments != null
703+
? throw new UnimplementedError('$this.instantiate')
704+
: this;
705+
}
706+
707+
@override
708+
Proto invoke(List<Argument>? arguments) {
709+
return arguments != null ? access('new').invoke(arguments) : this;
710+
}
711+
712+
@override
713+
Expression toExpression() {
714+
return new TypeLiteral(toTypeAnnotation());
715+
}
716+
717+
@override
718+
TypeAnnotation toTypeAnnotation() =>
719+
new NamedTypeAnnotation(reference, typeArguments);
720+
721+
@override
722+
Proto? resolve() {
723+
List<TypeAnnotation>? newTypeArguments =
724+
typeArguments.resolve((a) => a.resolve());
725+
return newTypeArguments == null
726+
? null
727+
: new GenericMixinProto(reference, scope, newTypeArguments);
728+
}
729+
}
730+
625731
/// A [reference] to an extension type.
626732
///
627733
/// The [Proto] includes the [scope] of the extension type, which is used to

pkg/_fe_analyzer_shared/lib/src/metadata/references.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,13 @@ abstract class EnumReference extends Reference {
7373
String toString() => 'EnumReference(${name})';
7474
}
7575

76+
abstract class MixinReference extends Reference {
77+
String get name;
78+
79+
@override
80+
String toString() => 'MixinReference(${name})';
81+
}
82+
7683
abstract class FunctionTypeParameterReference extends Reference {
7784
String get name;
7885

pkg/_fe_analyzer_shared/lib/src/metadata/scope.dart

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,30 @@ abstract base class BaseEnumScope implements TypeDeclarationScope {
137137
}
138138
}
139139

140+
/// Base implementation for creating a [TypeDeclarationScope] for a mixin.
141+
abstract base class BaseMixinScope implements TypeDeclarationScope {
142+
MixinReference get mixinReference;
143+
144+
Proto createMemberProto<T>(List<TypeAnnotation>? typeArguments, String name,
145+
T? member, Proto Function(T, String) memberToProto) {
146+
if (member == null) {
147+
if (typeArguments != null) {
148+
return new UnresolvedAccess(
149+
new GenericMixinProto(mixinReference, this, typeArguments), name);
150+
} else {
151+
return new UnresolvedAccess(new MixinProto(mixinReference, this), name);
152+
}
153+
} else {
154+
if (typeArguments != null) {
155+
return new InvalidAccessProto(
156+
new GenericMixinProto(mixinReference, this, typeArguments), name);
157+
} else {
158+
return memberToProto(member, name);
159+
}
160+
}
161+
}
162+
}
163+
140164
/// Base implementation for creating a [TypeDeclarationScope] for a typedef.
141165
abstract base class BaseTypedefScope implements TypeDeclarationScope {
142166
TypedefReference get typedefReference;

pkg/_fe_analyzer_shared/lib/src/testing/metadata_helper.dart

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,8 @@ class Writer {
316316
_write(reference.name);
317317
case EnumReference():
318318
_write(reference.name);
319+
case MixinReference():
320+
_write(reference.name);
319321
case FunctionTypeParameterReference():
320322
_write(reference.name);
321323
}
@@ -658,6 +660,15 @@ class Writer {
658660
_referenceToText(proto.reference);
659661
_typeArgumentsToText(proto.typeArguments);
660662
_write(')');
663+
case MixinProto():
664+
_write('MixinProto(');
665+
_referenceToText(proto.reference);
666+
_write(')');
667+
case GenericMixinProto():
668+
_write('GenericMixinProto(');
669+
_referenceToText(proto.reference);
670+
_typeArgumentsToText(proto.typeArguments);
671+
_write(')');
661672
case ExtensionProto():
662673
_write('ExtensionProto(');
663674
_referenceToText(proto.reference);
Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'dart:async';
6+
import 'main.dart' as self;
7+
8+
class Helper {
9+
const Helper(a);
10+
}
11+
12+
mixin Mixin {
13+
static const int variable = 42;
14+
static void method() {}
15+
static void genericMethod<T>() {}
16+
}
17+
18+
mixin GenericMixin<T> {}
19+
20+
@Mixin.variable
21+
/*member: mixinConstant1:
22+
unresolved=UnresolvedExpression(UnresolvedAccess(
23+
UnresolvedIdentifier(Mixin).variable))
24+
resolved=StaticGet(variable)*/
25+
void mixinConstant1() {}
26+
27+
@self.Mixin.variable
28+
/*member: mixinConstant2:
29+
unresolved=UnresolvedExpression(UnresolvedAccess(
30+
UnresolvedAccess(
31+
UnresolvedIdentifier(self).Mixin).variable))
32+
resolved=StaticGet(variable)*/
33+
void mixinConstant2() {}
34+
35+
@Helper(Mixin)
36+
/*member: mixinConstant3:
37+
unresolved=UnresolvedExpression(UnresolvedInvoke(
38+
UnresolvedIdentifier(Helper)
39+
(UnresolvedExpression(UnresolvedIdentifier(Mixin)))))
40+
resolved=TypeLiteral(Mixin)*/
41+
void mixinConstant3() {}
42+
43+
@Helper(self.Mixin)
44+
/*member: mixinConstant4:
45+
unresolved=UnresolvedExpression(UnresolvedInvoke(
46+
UnresolvedIdentifier(Helper)
47+
(UnresolvedExpression(UnresolvedAccess(
48+
UnresolvedIdentifier(self).Mixin)))))
49+
resolved=TypeLiteral(Mixin)*/
50+
void mixinConstant4() {}
51+
52+
@Helper(Mixin.method)
53+
/*member: mixinConstant5:
54+
unresolved=UnresolvedExpression(UnresolvedInvoke(
55+
UnresolvedIdentifier(Helper)
56+
(UnresolvedExpression(UnresolvedAccess(
57+
UnresolvedIdentifier(Mixin).method)))))
58+
resolved=FunctionTearOff(method)*/
59+
void mixinConstant5() {}
60+
61+
@Helper(self.Mixin.method)
62+
/*member: mixinConstant6:
63+
unresolved=UnresolvedExpression(UnresolvedInvoke(
64+
UnresolvedIdentifier(Helper)
65+
(UnresolvedExpression(UnresolvedAccess(
66+
UnresolvedAccess(
67+
UnresolvedIdentifier(self).Mixin).method)))))
68+
resolved=FunctionTearOff(method)*/
69+
void mixinConstant6() {}
70+
71+
@Helper(Mixin.genericMethod)
72+
/*member: mixinConstant7:
73+
unresolved=UnresolvedExpression(UnresolvedInvoke(
74+
UnresolvedIdentifier(Helper)
75+
(UnresolvedExpression(UnresolvedAccess(
76+
UnresolvedIdentifier(Mixin).genericMethod)))))
77+
resolved=FunctionTearOff(genericMethod)*/
78+
void mixinConstant7() {}
79+
80+
@Helper(self.Mixin.genericMethod)
81+
/*member: mixinConstant8:
82+
unresolved=UnresolvedExpression(UnresolvedInvoke(
83+
UnresolvedIdentifier(Helper)
84+
(UnresolvedExpression(UnresolvedAccess(
85+
UnresolvedAccess(
86+
UnresolvedIdentifier(self).Mixin).genericMethod)))))
87+
resolved=FunctionTearOff(genericMethod)*/
88+
void mixinConstant8() {}
89+
90+
@Helper(Mixin.genericMethod<int>)
91+
/*member: mixinConstant9:
92+
unresolved=UnresolvedExpression(UnresolvedInvoke(
93+
UnresolvedIdentifier(Helper)
94+
(UnresolvedExpression(UnresolvedInstantiate(
95+
UnresolvedAccess(
96+
UnresolvedIdentifier(Mixin).genericMethod)<{unresolved-type-annotation:UnresolvedIdentifier(int)}>)))))
97+
resolved=Instantiation(FunctionTearOff(genericMethod)<int>)*/
98+
void mixinConstant9() {}
99+
100+
@Helper(self.Mixin.genericMethod<int>)
101+
/*member: mixinConstant10:
102+
unresolved=UnresolvedExpression(UnresolvedInvoke(
103+
UnresolvedIdentifier(Helper)
104+
(UnresolvedExpression(UnresolvedInstantiate(
105+
UnresolvedAccess(
106+
UnresolvedAccess(
107+
UnresolvedIdentifier(self).Mixin).genericMethod)<{unresolved-type-annotation:UnresolvedIdentifier(int)}>)))))
108+
resolved=Instantiation(FunctionTearOff(genericMethod)<int>)*/
109+
void mixinConstant10() {}
110+
111+
@Helper(GenericMixin)
112+
/*member: mixinConstant11:
113+
unresolved=UnresolvedExpression(UnresolvedInvoke(
114+
UnresolvedIdentifier(Helper)
115+
(UnresolvedExpression(UnresolvedIdentifier(GenericMixin)))))
116+
resolved=TypeLiteral(GenericMixin)*/
117+
void mixinConstant11() {}
118+
119+
@Helper(self.GenericMixin)
120+
/*member: mixinConstant12:
121+
unresolved=UnresolvedExpression(UnresolvedInvoke(
122+
UnresolvedIdentifier(Helper)
123+
(UnresolvedExpression(UnresolvedAccess(
124+
UnresolvedIdentifier(self).GenericMixin)))))
125+
resolved=TypeLiteral(GenericMixin)*/
126+
void mixinConstant12() {}
127+
128+
@Helper(GenericMixin<bool>)
129+
/*member: mixinConstant13:
130+
unresolved=UnresolvedExpression(UnresolvedInvoke(
131+
UnresolvedIdentifier(Helper)
132+
(UnresolvedExpression(UnresolvedInstantiate(
133+
UnresolvedIdentifier(GenericMixin)<{unresolved-type-annotation:UnresolvedIdentifier(bool)}>)))))
134+
resolved=TypeLiteral(GenericMixin<bool>)*/
135+
void mixinConstant13() {}
136+
137+
@Helper(self.GenericMixin<double>)
138+
/*member: mixinConstant14:
139+
unresolved=UnresolvedExpression(UnresolvedInvoke(
140+
UnresolvedIdentifier(Helper)
141+
(UnresolvedExpression(UnresolvedInstantiate(
142+
UnresolvedAccess(
143+
UnresolvedIdentifier(self).GenericMixin)<{unresolved-type-annotation:UnresolvedIdentifier(double)}>)))))
144+
resolved=TypeLiteral(GenericMixin<double>)*/
145+
void mixinConstant14() {}
146+
147+
@Helper(Mixin.unresolved)
148+
/*member: mixinConstant15:
149+
unresolved=UnresolvedExpression(UnresolvedInvoke(
150+
UnresolvedIdentifier(Helper)
151+
(UnresolvedExpression(UnresolvedAccess(
152+
UnresolvedIdentifier(Mixin).unresolved)))))
153+
resolved=UnresolvedExpression(UnresolvedAccess(
154+
MixinProto(Mixin).unresolved))*/
155+
void mixinConstant15() {}
156+
157+
@Helper(self.Mixin.unresolved)
158+
/*member: mixinConstant16:
159+
unresolved=UnresolvedExpression(UnresolvedInvoke(
160+
UnresolvedIdentifier(Helper)
161+
(UnresolvedExpression(UnresolvedAccess(
162+
UnresolvedAccess(
163+
UnresolvedIdentifier(self).Mixin).unresolved)))))
164+
resolved=UnresolvedExpression(UnresolvedAccess(
165+
MixinProto(Mixin).unresolved))*/
166+
void mixinConstant16() {}
167+
168+
@Helper(Mixin.unresolved<int>)
169+
/*member: mixinConstant17:
170+
unresolved=UnresolvedExpression(UnresolvedInvoke(
171+
UnresolvedIdentifier(Helper)
172+
(UnresolvedExpression(UnresolvedInstantiate(
173+
UnresolvedAccess(
174+
UnresolvedIdentifier(Mixin).unresolved)<{unresolved-type-annotation:UnresolvedIdentifier(int)}>)))))
175+
resolved=UnresolvedExpression(UnresolvedInstantiate(
176+
UnresolvedAccess(
177+
MixinProto(Mixin).unresolved)<int>))*/
178+
void mixinConstant17() {}
179+
180+
@Helper(self.Mixin.unresolved<int>)
181+
/*member: mixinConstant18:
182+
unresolved=UnresolvedExpression(UnresolvedInvoke(
183+
UnresolvedIdentifier(Helper)
184+
(UnresolvedExpression(UnresolvedInstantiate(
185+
UnresolvedAccess(
186+
UnresolvedAccess(
187+
UnresolvedIdentifier(self).Mixin).unresolved)<{unresolved-type-annotation:UnresolvedIdentifier(int)}>)))))
188+
resolved=UnresolvedExpression(UnresolvedInstantiate(
189+
UnresolvedAccess(
190+
MixinProto(Mixin).unresolved)<int>))*/
191+
void mixinConstant18() {}

0 commit comments

Comments
 (0)