@@ -8,13 +8,16 @@ import 'package:kernel/core_types.dart' show CoreTypes;
8
8
import 'package:kernel/library_index.dart' show LibraryIndex;
9
9
import 'package:yaml/yaml.dart' ;
10
10
import '../source/source_loader.dart' show SourceLoader;
11
+ import '../api_prototype/lowering_predicates.dart'
12
+ show extractQualifiedNameFromExtensionMethodName;
11
13
12
14
import '../codes/cfe_codes.dart'
13
15
show
14
16
messageDynamicCallsAreNotAllowedInDynamicModule,
15
17
noLength,
16
18
templateConstructorShouldBeListedAsCallableInDynamicInterface,
17
19
templateMemberShouldBeListedAsCallableInDynamicInterface,
20
+ templateExtensionTypeShouldBeListedAsCallableInDynamicInterface,
18
21
templateClassShouldBeListedAsCallableInDynamicInterface,
19
22
templateClassShouldBeListedAsExtendableInDynamicInterface,
20
23
templateMemberShouldBeListedAsCanBeOverriddenInDynamicInterface;
@@ -214,13 +217,19 @@ class DynamicInterfaceLanguageImplPragmas {
214
217
215
218
bool isCallable (TreeNode node) => switch (node) {
216
219
Member () => isPlatformLibrary (node.enclosingLibrary) &&
217
- // Coverage-ignore(suite): Not run.
218
220
(isAnnotatedWith (node, callablePragmaName) ||
219
221
(! node.name.isPrivate &&
220
222
node.enclosingClass != null &&
221
223
isAnnotatedWith (node.enclosingClass! , callablePragmaName))),
222
224
Class () => isPlatformLibrary (node.enclosingLibrary) &&
223
225
isAnnotatedWith (node, callablePragmaName),
226
+ ExtensionTypeDeclaration () =>
227
+ isPlatformLibrary (node.enclosingLibrary) &&
228
+ // Coverage-ignore(suite): Not run.
229
+ isAnnotatedWith (node, callablePragmaName),
230
+ // Coverage-ignore(suite): Not run.
231
+ Extension () => isPlatformLibrary (node.enclosingLibrary) &&
232
+ isAnnotatedWith (node, callablePragmaName),
224
233
_ => // Coverage-ignore(suite): Not run.
225
234
throw 'Unexpected node ${node .runtimeType } $node '
226
235
};
@@ -230,7 +239,6 @@ class DynamicInterfaceLanguageImplPragmas {
230
239
if (annotation case ConstantExpression (: var constant)) {
231
240
if (constant case InstanceConstant (: var classNode, : var fieldValues)
232
241
when classNode == coreTypes.pragmaClass) {
233
- // Coverage-ignore-block(suite): Not run.
234
242
if (fieldValues[coreTypes.pragmaName.fieldReference]
235
243
case StringConstant (: var value) when value == pragmaName) {
236
244
return true ;
@@ -254,19 +262,69 @@ class _DynamicModuleValidator extends RecursiveVisitor {
254
262
255
263
_DynamicModuleValidator (this .spec, this .languageImplPragmas,
256
264
this .moduleLibraries, this .hierarchy, this .loader) {
257
- _addLibraryExports (spec.callable);
258
- _addLibraryExports (spec.extendable);
259
- _addLibraryExports (spec.canBeOverridden);
265
+ _expandNodes (spec.callable);
266
+ _expandNodes (spec.extendable);
267
+ _expandNodes (spec.canBeOverridden);
260
268
}
261
269
262
- void _addLibraryExports (Set <TreeNode > nodes) {
263
- Set <TreeNode > exports = {};
270
+ // Add nodes which do not have direct relation to its logical "parent" node.
271
+ void _expandNodes (Set <TreeNode > nodes) {
272
+ Set <TreeNode > extraNodes = {};
264
273
for (TreeNode node in nodes) {
265
- if (node is Library ) {
266
- exports.addAll (node.additionalExports.map ((ref) => ref.node! ));
267
- }
274
+ _expandNode (node, extraNodes);
275
+ }
276
+ nodes.addAll (extraNodes);
277
+ }
278
+
279
+ // Add re-exports of Library and members of ExtensionTypeDeclaration and
280
+ // Extension. These nodes do not have direct relations to their "parents".
281
+ void _expandNode (TreeNode node, Set <TreeNode > extraNodes) {
282
+ switch (node) {
283
+ case Library ():
284
+ for (Reference ref in node.additionalExports) {
285
+ TreeNode node = ref.node! ;
286
+ extraNodes.add (node);
287
+ _expandNode (node, extraNodes);
288
+ }
289
+ for (ExtensionTypeDeclaration e in node.extensionTypeDeclarations) {
290
+ // Coverage-ignore-block(suite): Not run.
291
+ if (e.name[0 ] != '_' ) {
292
+ _expandNode (e, extraNodes);
293
+ }
294
+ }
295
+ for (Extension e in node.extensions) {
296
+ // Coverage-ignore-block(suite): Not run.
297
+ if (e.name[0 ] != '_' ) {
298
+ _expandNode (e, extraNodes);
299
+ }
300
+ }
301
+ case ExtensionTypeDeclaration ():
302
+ for (ExtensionTypeMemberDescriptor md in node.memberDescriptors) {
303
+ TreeNode ? member = md.memberReference? .node;
304
+ if (member != null ) {
305
+ extraNodes.add (member);
306
+ }
307
+ TreeNode ? tearOff = md.tearOffReference? .node;
308
+ if (tearOff != null ) {
309
+ extraNodes.add (tearOff);
310
+ }
311
+ }
312
+ case Extension ():
313
+ for (ExtensionMemberDescriptor md in node.memberDescriptors) {
314
+ TreeNode ? member = md.memberReference? .node;
315
+ if (member != null ) {
316
+ extraNodes.add (member);
317
+ }
318
+ TreeNode ? tearOff = md
319
+ .tearOffReference
320
+ // Coverage-ignore(suite): Not run.
321
+ ? .node;
322
+ if (tearOff != null ) {
323
+ // Coverage-ignore-block(suite): Not run.
324
+ extraNodes.add (tearOff);
325
+ }
326
+ }
268
327
}
269
- nodes.addAll (exports);
270
328
}
271
329
272
330
@override
@@ -479,9 +537,9 @@ class _DynamicModuleValidator extends RecursiveVisitor {
479
537
}
480
538
481
539
@override
482
- // Coverage-ignore(suite): Not run.
483
540
void visitExtensionType (ExtensionType node) {
484
- node.extensionTypeErasure.accept (this );
541
+ _verifyCallable (node.extensionTypeDeclaration, _enclosingTreeNode! );
542
+ super .visitExtensionType (node);
485
543
}
486
544
487
545
@override
@@ -570,9 +628,15 @@ class _DynamicModuleValidator extends RecursiveVisitor {
570
628
node.location! .file);
571
629
case Member ():
572
630
final Class ? cls = target.enclosingClass;
573
- final String name = (cls != null )
574
- ? '${cls .name }.${target .name .text }'
575
- : target.name.text;
631
+ String name;
632
+ if (cls != null ) {
633
+ name = '${cls .name }.${target .name .text }' ;
634
+ } else {
635
+ name = target.name.text;
636
+ if (target.isExtensionMember || target.isExtensionTypeMember) {
637
+ name = extractQualifiedNameFromExtensionMethodName (name)! ;
638
+ }
639
+ }
576
640
loader.addProblem (
577
641
templateMemberShouldBeListedAsCallableInDynamicInterface
578
642
.withArguments (name),
@@ -586,6 +650,13 @@ class _DynamicModuleValidator extends RecursiveVisitor {
586
650
node.fileOffset,
587
651
noLength,
588
652
node.location! .file);
653
+ case ExtensionTypeDeclaration ():
654
+ loader.addProblem (
655
+ templateExtensionTypeShouldBeListedAsCallableInDynamicInterface
656
+ .withArguments (target.name),
657
+ node.fileOffset,
658
+ noLength,
659
+ node.location! .file);
589
660
// Coverage-ignore(suite): Not run.
590
661
case _:
591
662
throw 'Unexpected node ${node .runtimeType } $node ' ;
@@ -659,6 +730,7 @@ class _DynamicModuleValidator extends RecursiveVisitor {
659
730
Library _enclosingLibrary (TreeNode node) => switch (node) {
660
731
Member () => node.enclosingLibrary,
661
732
Class () => node.enclosingLibrary,
733
+ ExtensionTypeDeclaration () => node.enclosingLibrary,
662
734
// Coverage-ignore(suite): Not run.
663
735
Library () => node,
664
736
_ => // Coverage-ignore(suite): Not run.
@@ -672,6 +744,8 @@ class _DynamicModuleValidator extends RecursiveVisitor {
672
744
! node.name.isPrivate && _isSpecified (node.parent! , specified),
673
745
Class () =>
674
746
node.name[0 ] != '_' && _isSpecified (node.enclosingLibrary, specified),
747
+ ExtensionTypeDeclaration () =>
748
+ node.name[0 ] != '_' && _isSpecified (node.enclosingLibrary, specified),
675
749
Library () => false ,
676
750
_ => // Coverage-ignore(suite): Not run.
677
751
throw 'Unexpected node ${node .runtimeType } $node '
0 commit comments