3434import org .eclipse .jdt .core .dom .ITypeBinding ;
3535import org .eclipse .jdt .core .dom .ImportDeclaration ;
3636import org .eclipse .jdt .core .dom .InstanceofExpression ;
37+ import org .eclipse .jdt .core .dom .JdtCoreDomPackagePrivateUtility ;
3738import org .eclipse .jdt .core .dom .LabeledStatement ;
3839import org .eclipse .jdt .core .dom .Name ;
3940import org .eclipse .jdt .core .dom .PackageDeclaration ;
@@ -58,6 +59,7 @@ public class DOMTypeReferenceLocator extends DOMPatternLocator {
5859 private TypeReferenceLocator locator ;
5960 private List <IJavaElement > foundElements = new ArrayList <>();
6061 private Set <org .eclipse .jdt .core .dom .Name > imports = new HashSet <>();
62+ private MatchLocator matchLocator = null ;
6163
6264 public DOMTypeReferenceLocator (TypeReferenceLocator locator ) {
6365 super (locator .pattern );
@@ -76,6 +78,7 @@ public LocatorResponse match(org.eclipse.jdt.core.dom.Annotation node, NodeSetWr
7678 }
7779 @ Override
7880 public LocatorResponse match (Name name , NodeSetWrapper nodeSet , MatchLocator locator ) {
81+ this .matchLocator = locator ;
7982 if (name .getParent () instanceof AbstractTypeDeclaration ) {
8083 return toResponse (IMPOSSIBLE_MATCH );
8184 }
@@ -124,6 +127,7 @@ public LocatorResponse match(Name name, NodeSetWrapper nodeSet, MatchLocator loc
124127 }
125128 @ Override
126129 public LocatorResponse match (org .eclipse .jdt .core .dom .ASTNode node , NodeSetWrapper nodeSet , MatchLocator locator ) {
130+ this .matchLocator = locator ;
127131 if (failsFineGrain (node , this .locator .fineGrain ())) {
128132 return toResponse (IMPOSSIBLE_MATCH );
129133 }
@@ -169,6 +173,7 @@ private LocatorResponse matchTypeNodeReturnComponent(Type node, String qualified
169173
170174 @ Override
171175 public LocatorResponse match (Type node , NodeSetWrapper nodeSet , MatchLocator locator ) {
176+ this .matchLocator = locator ;
172177 if (failsFineGrain (node , this .locator .fineGrain ())) {
173178 return toResponse (IMPOSSIBLE_MATCH );
174179 }
@@ -204,6 +209,15 @@ public LocatorResponse match(Type node, NodeSetWrapper nodeSet, MatchLocator loc
204209 r1 = matchTypeNodeReturnComponent (node , patternQualifiedString , fqqn , defaultLevel );
205210 if ( r1 != null ) return r1 ;
206211 }
212+ // } else {
213+ // String[] qualifiedNameFromNodeSegments = qualifiedNameFromNode.split("\\.");
214+ // String first = qualifiedNameFromNodeSegments == null ? null : qualifiedNameFromNodeSegments.length == 0 ? null : qualifiedNameFromNodeSegments[0];
215+ // String fqqnImport = fqqnFromImport(first);
216+ // if( fqqnImport != null ) {
217+ // String fqqn = fqqnImport + qualifiedNameFromNode.substring(first.length());
218+ // r1 = matchTypeNodeReturnComponent(node, qualifiedNameFromNode, fqqn, defaultLevel);
219+ // if( r1 != null ) return r1;
220+ // }
207221 }
208222 } else if (simpleNameFromNode != null ) {
209223 if ( this .locator .matchesName (this .locator .pattern .simpleName , simpleNameFromNode .toCharArray ()) ) {
@@ -284,22 +298,18 @@ private int validateTypeParameters(Type node) {
284298 }
285299 for ( int j = 0 ; j < thisLevelTypeParams .length ; j ++ ) {
286300 String typeFromPattern = new String (thisLevelTypeParams [j ]);
301+ IBinding patternTypeBinding = JdtCoreDomPackagePrivateUtility .findBindingForType (node , typeFromPattern );
287302 IBinding b = DOMASTNodeUtils .getBinding ((ASTNode )typeArgs .get (j ));
288303 String sig = b == null ? null : b instanceof JavacTypeBinding jctb ? jctb .getGenericTypeSignature (false ) : b .getKey ();
289304 if ( sig .startsWith ("+" ) && b instanceof ITypeBinding tb ) {
290- boolean isQuestionMark = "+Ljava/lang/Object;" .equals (sig );
291- if ( isQuestionMark ) {
292- // TODO - if pattern is <Unresolved1,Unresolved2> we must return no_match
293- continue ;
305+ boolean canContinue = validateOneTypeParameterExtends (typeFromPattern , sig , tb , patternTypeBinding );
306+ if ( !canContinue ) {
307+ return TYPE_PARAMS_COUNT_MATCH ;
294308 }
295- String remaining = sig .substring (1 );
296- ITypeBinding [] bounds = tb .getTypeBounds ();
297- if ( bounds != null && bounds .length == 1 && bounds [0 ] != null ) {
298- ITypeBinding b1 = bounds [0 ];
299- String boundSig = b1 == null ? null : b1 instanceof JavacTypeBinding jctb ? jctb .getGenericTypeSignature (false ) : b1 .getKey ();
300- if ( !typeFromPattern .equals (boundSig )) {
301- return TYPE_PARAMS_COUNT_MATCH ;
302- }
309+ } else if ( sig .startsWith ("-" ) && b instanceof ITypeBinding tb ) {
310+ boolean canContinue = validateOneTypeParameterSuper (typeFromPattern , sig , tb , patternTypeBinding );
311+ if ( !canContinue ) {
312+ return TYPE_PARAMS_COUNT_MATCH ;
303313 }
304314 } else if ( !typeFromPattern .equals (sig )) {
305315 return TYPE_PARAMS_COUNT_MATCH ;
@@ -322,6 +332,69 @@ private int validateTypeParameters(Type node) {
322332 }
323333 return TYPE_PARAMS_MATCH ;
324334 }
335+
336+ private boolean validateOneTypeParameterExtends (String typeFromPattern , String sig , ITypeBinding tb , IBinding patternTypeBinding ) {
337+ boolean isQuestionMark = "+Ljava/lang/Object;" .equals (sig );
338+ if ( isQuestionMark ) {
339+ // TODO - if pattern is <Unresolved1,Unresolved2> we must return no_match
340+ return true ;
341+ }
342+ String remaining = sig .substring (1 );
343+ ITypeBinding [] bounds = tb .getTypeBounds ();
344+ if ( bounds != null && bounds .length == 1 && bounds [0 ] != null ) {
345+ ITypeBinding b1 = bounds [0 ];
346+ String boundSig = b1 == null ? null : b1 instanceof JavacTypeBinding jctb ? jctb .getGenericTypeSignature (false ) : b1 .getKey ();
347+ if ( typeFromPattern .equals (boundSig )) {
348+ return true ;
349+ }
350+ if ( patternTypeBinding instanceof ITypeBinding itb ) {
351+ ITypeBinding working = itb ;
352+ while (working != null ) {
353+ ITypeBinding superClaz = working .getSuperclass ();
354+ if ( superClaz != null ) {
355+ String superClazKey = b1 == null ? null : superClaz instanceof JavacTypeBinding jctb ? jctb .getGenericTypeSignature (false ) : superClaz .getKey ();
356+ if ( superClazKey .equals (boundSig )) {
357+ return true ;
358+ }
359+ }
360+ working = superClaz ;
361+ }
362+ return false ;
363+ } else {
364+ return false ;
365+ }
366+ }
367+ return true ;
368+ }
369+
370+ private boolean validateOneTypeParameterSuper (String typeFromPattern , String sig , ITypeBinding tb , IBinding patternTypeBinding ) {
371+ String remaining = sig .substring (1 );
372+ ITypeBinding b1 = tb .getBound ();
373+ if ( b1 != null ) {
374+ String boundSig = b1 == null ? null : b1 instanceof JavacTypeBinding jctb ? jctb .getGenericTypeSignature (false ) : b1 .getKey ();
375+ if ( typeFromPattern .equals (boundSig )) {
376+ return true ;
377+ }
378+ if ( patternTypeBinding instanceof ITypeBinding itb ) {
379+ ITypeBinding working = b1 ;
380+ while (working != null ) {
381+ ITypeBinding superClaz = working .getSuperclass ();
382+ if ( superClaz != null ) {
383+ String superClazKey = b1 == null ? null : superClaz instanceof JavacTypeBinding jctb ? jctb .getGenericTypeSignature (false ) : superClaz .getKey ();
384+ if ( superClazKey .equals (typeFromPattern )) {
385+ return true ;
386+ }
387+ }
388+ working = superClaz ;
389+ }
390+ return false ;
391+ } else {
392+ return false ;
393+ }
394+ }
395+ return true ;
396+ }
397+
325398 private String getQualifiedNameFromType (Type query ) {
326399 if ( query instanceof QualifiedType qtt ) {
327400 String qualString = getQualifiedNameFromType (qtt .getQualifier ());
@@ -426,16 +499,21 @@ public LocatorResponse resolveLevel(org.eclipse.jdt.core.dom.ASTNode node, IBind
426499 int v = resolveLevelForTypeBinding (node , typeBinding , locator );
427500 boolean patternHasTypeArgs = this .locator .pattern .hasTypeArguments ();
428501 boolean patternHasTypeParameters = this .locator .pattern .hasTypeParameters ();
502+ boolean patternHasSignatures = this .locator .pattern .hasSignatures ();
429503 boolean erasureMatch = isPatternErasureMatch ();
430504 boolean equivMatch = isPatternEquivalentMatch ();
431- if ( patternHasTypeArgs && !(erasureMatch || equivMatch )) {
505+ if ( ( patternHasTypeArgs && !(erasureMatch || equivMatch ) )) {
432506 return toResponse (IMPOSSIBLE_MATCH );
433507 }
434-
435508 if ( node instanceof ParameterizedType pt ) {
436509 ASTNode n = preferParamaterizedNode () ? pt : pt .getType ();
437510 return new LocatorResponse (v , n != pt , n , false , false );
438511 }
512+ if ( patternHasTypeArgs && !patternHasSignatures && !erasureMatch ) {
513+ // the search doesn't have type args in it, but the type does
514+ return toResponse (IMPOSSIBLE_MATCH );
515+ }
516+
439517 return toResponse (v );
440518 }
441519 if ( binding instanceof IPackageBinding && node instanceof SimpleName sn ) {
@@ -544,14 +622,17 @@ public String findImportForString(String s) {
544622 }
545623 }
546624 if ( newLevel == ACCURATE_MATCH && this .locator .pattern .hasTypeArguments () ) {
547- return resolveLevelForTypeBindingWithTypeArguments (typeBinding , node , newLevel , locator );
625+ return resolveLevelForTypeBindingWithTypeArguments (typeBinding , node , locator );
548626 }
549627 return newLevel ;
550628 }
551629
552- private int resolveLevelForTypeBindingWithTypeArguments (ITypeBinding typeBinding , ASTNode node , int newLevel ,
630+ private int resolveLevelForTypeBindingWithTypeArguments (ITypeBinding typeBinding , ASTNode node ,
553631 MatchLocator locator2 ) {
554632 boolean patternHasTypeArgs = this .locator .pattern .hasTypeArguments ();
633+ boolean patternHasTypeParams = this .locator .pattern .hasTypeParameters ();
634+ boolean patternHasTypeSignatures = !(patternHasTypeArgs && patternHasTypeParams );
635+
555636 char [][][] patternTypeArgArray = this .locator .pattern .getTypeArguments ();
556637 int patternTypeArgsLength = patternTypeArgArray == null ? -1 :
557638 patternTypeArgArray [0 ] == null ? -1 :
@@ -568,14 +649,30 @@ private int resolveLevelForTypeBindingWithTypeArguments(ITypeBinding typeBinding
568649 int bindingTypeArgsLength = bindingArgs == null ? -1 : bindingArgs .length ;
569650 // Compare arguments lengths
570651 if (patternTypeArgsLength == bindingTypeArgsLength ) {
652+ Type t = node instanceof Type ? (Type )node : null ;
653+ if ( t != null ) {
654+ int typeArgsValidation = validateTypeParameters (t );
655+ if ( typeArgsValidation == TYPE_PARAMS_MATCH ) {
656+ if ( !patternHasTypeSignatures ) {
657+ return ERASURE_MATCH ;
658+ }
659+ return ACCURATE_MATCH ;
660+ }
661+ if ( typeArgsValidation == TYPE_PARAMS_COUNT_MATCH ) {
662+ return ERASURE_MATCH ;
663+ }
664+ if ( typeArgsValidation == TYPE_PARAMS_NO_MATCH ) {
665+ return ERASURE_MATCH ;
666+ }
667+ }
571668 if (!bindingIsRaw && patternHasTypeArgs ) {
572669 // generic patterns are always not compatible match
573670 return ERASURE_MATCH ;
574671 }
575- return newLevel ;
672+ return ACCURATE_MATCH ;
576673 } else {
577674 if (patternTypeArgsLength ==0 ) {
578- return newLevel ;
675+ return ACCURATE_MATCH ;
579676 } else if (bindingTypeArgsLength ==0 ) {
580677 // If this is an import, we have to treat it differently
581678
@@ -585,13 +682,13 @@ private int resolveLevelForTypeBindingWithTypeArguments(ITypeBinding typeBinding
585682// ITypeBinding[] declParams = decl.getTypeParameters();
586683 // raw binding is always compatible
587684 if ( patternIsEquivMatch && bindingIsRaw ) {
588- return IMPOSSIBLE_MATCH ;
685+ return ACCURATE_MATCH ;
589686 }
590687 if ( !bindingIsRaw && !(patternIsEquivMatch || patternIsErasureMatch )) {
591688 return IMPOSSIBLE_MATCH ;
592689 }
593690 if ( !patternIsEquivMatch || bindingIsRaw )
594- return newLevel ;
691+ return ACCURATE_MATCH ;
595692 }
596693 }
597694 return IMPOSSIBLE_MATCH ;
@@ -712,6 +809,12 @@ public void reportSearchMatch(MatchLocator locator, ASTNode node, SearchMatch ma
712809 match .setLength (newLength );
713810 }
714811
812+ // boolean matchIsEr = match.isErasure();
813+ // boolean matchIsEq = match.isEquivalent();
814+ // boolean matchIsEx = match.isExact();
815+ // boolean report = (this.isErasureMatch && match.isErasure())
816+ // || ((this.isErasureMatch || this.isEquivalentMatch) && match.isEquivalent())
817+ // || match.isExact();
715818 boolean report = (this .isErasureMatch && match .isErasure ()) || (this .isEquivalentMatch && match .isEquivalent ()) || match .isExact ();
716819 if (!report ) return ;
717820
0 commit comments