@@ -19,6 +19,7 @@ import 'package:_fe_analyzer_shared/src/messages/codes.dart'
1919 messageJsInteropNonExternalConstructor,
2020 messageJsInteropNonExternalMember,
2121 messageJsInteropOperatorsNotSupported,
22+ messageJsInteropStaticInteropExternalExtensionMembersWithTypeParameters,
2223 messageJsInteropStaticInteropGenerativeConstructor,
2324 templateJsInteropDartClassExtendsJSClass,
2425 templateJsInteropStaticInteropWithInstanceMembers,
@@ -34,6 +35,7 @@ class JsInteropChecks extends RecursiveVisitor {
3435 final CoreTypes _coreTypes;
3536 final DiagnosticReporter <Message , LocatedMessage > _diagnosticsReporter;
3637 final Map <String , Class > _nativeClasses;
38+ final _TypeParameterVisitor _typeParameterVisitor = _TypeParameterVisitor ();
3739 bool _classHasJSAnnotation = false ;
3840 bool _classHasAnonymousAnnotation = false ;
3941 bool _classHasStaticInteropAnnotation = false ;
@@ -301,6 +303,26 @@ class JsInteropChecks extends RecursiveVisitor {
301303 procedure.name.text.length,
302304 procedure.fileUri);
303305 }
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+ }
304326 }
305327
306328 @override
@@ -450,6 +472,12 @@ class JsInteropChecks extends RecursiveVisitor {
450472 return _checkExtensionMember (member, hasJSInteropAnnotation);
451473 }
452474
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+
453481 /// Returns whether given extension [member] is in an extension on a Native
454482 /// class.
455483 bool _isNativeExtensionMember (Member member) {
@@ -471,3 +499,18 @@ class JsInteropChecks extends RecursiveVisitor {
471499 return onType is InterfaceType && validateExtensionClass (onType.classNode);
472500 }
473501}
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