@@ -19,6 +19,7 @@ import 'package:_fe_analyzer_shared/src/messages/codes.dart'
19
19
messageJsInteropNonExternalConstructor,
20
20
messageJsInteropNonExternalMember,
21
21
messageJsInteropOperatorsNotSupported,
22
+ messageJsInteropStaticInteropExternalExtensionMembersWithTypeParameters,
22
23
messageJsInteropStaticInteropGenerativeConstructor,
23
24
templateJsInteropDartClassExtendsJSClass,
24
25
templateJsInteropStaticInteropWithInstanceMembers,
@@ -34,6 +35,7 @@ class JsInteropChecks extends RecursiveVisitor {
34
35
final CoreTypes _coreTypes;
35
36
final DiagnosticReporter <Message , LocatedMessage > _diagnosticsReporter;
36
37
final Map <String , Class > _nativeClasses;
38
+ final _TypeParameterVisitor _typeParameterVisitor = _TypeParameterVisitor ();
37
39
bool _classHasJSAnnotation = false ;
38
40
bool _classHasAnonymousAnnotation = false ;
39
41
bool _classHasStaticInteropAnnotation = false ;
@@ -301,6 +303,26 @@ class JsInteropChecks extends RecursiveVisitor {
301
303
procedure.name.text.length,
302
304
procedure.fileUri);
303
305
}
306
+
307
+ if (procedure.isExternal &&
308
+ procedure.isExtensionMember &&
309
+ _isStaticInteropExtensionMember (procedure)) {
310
+ // If the extension has type parameters of its own, it copies those type
311
+ // parameters to the procedure's type parameters (in the front) as well.
312
+ // Ignore these for the analysis.
313
+ var extensionTypeParams =
314
+ _libraryExtensionsIndex! [procedure.reference]! .typeParameters;
315
+ var procedureTypeParams = List .from (procedure.function.typeParameters);
316
+ procedureTypeParams.removeRange (0 , extensionTypeParams.length);
317
+ if (procedureTypeParams.isNotEmpty ||
318
+ _typeParameterVisitor.usesTypeParameters (procedure)) {
319
+ _diagnosticsReporter.report (
320
+ messageJsInteropStaticInteropExternalExtensionMembersWithTypeParameters,
321
+ procedure.fileOffset,
322
+ procedure.name.text.length,
323
+ procedure.fileUri);
324
+ }
325
+ }
304
326
}
305
327
306
328
@override
@@ -450,6 +472,12 @@ class JsInteropChecks extends RecursiveVisitor {
450
472
return _checkExtensionMember (member, hasJSInteropAnnotation);
451
473
}
452
474
475
+ /// Returns whether given extension [member] is in an extension that is on a
476
+ /// `@staticInterop` class.
477
+ bool _isStaticInteropExtensionMember (Member member) {
478
+ return _checkExtensionMember (member, hasStaticInteropAnnotation);
479
+ }
480
+
453
481
/// Returns whether given extension [member] is in an extension on a Native
454
482
/// class.
455
483
bool _isNativeExtensionMember (Member member) {
@@ -471,3 +499,18 @@ class JsInteropChecks extends RecursiveVisitor {
471
499
return onType is InterfaceType && validateExtensionClass (onType.classNode);
472
500
}
473
501
}
502
+
503
+ class _TypeParameterVisitor extends RecursiveVisitor {
504
+ bool _visitedTypeParameterType = false ;
505
+
506
+ bool usesTypeParameters (Node node) {
507
+ _visitedTypeParameterType = false ;
508
+ node.accept (this );
509
+ return _visitedTypeParameterType;
510
+ }
511
+
512
+ @override
513
+ void visitTypeParameterType (TypeParameterType node) {
514
+ _visitedTypeParameterType = true ;
515
+ }
516
+ }
0 commit comments