1919import org .eclipse .jdt .core .dom .ASTNode ;
2020import org .eclipse .jdt .core .dom .ASTVisitor ;
2121import org .eclipse .jdt .core .dom .Block ;
22+ import org .eclipse .jdt .core .dom .CastExpression ;
23+ import org .eclipse .jdt .core .dom .ClassInstanceCreation ;
2224import org .eclipse .jdt .core .dom .Expression ;
25+ import org .eclipse .jdt .core .dom .IBinding ;
2326import org .eclipse .jdt .core .dom .IMethodBinding ;
2427import org .eclipse .jdt .core .dom .ITypeBinding ;
28+ import org .eclipse .jdt .core .dom .IVariableBinding ;
29+ import org .eclipse .jdt .core .dom .LambdaExpression ;
2530import org .eclipse .jdt .core .dom .MethodDeclaration ;
2631import org .eclipse .jdt .core .dom .MethodInvocation ;
32+ import org .eclipse .jdt .core .dom .Name ;
2733import org .eclipse .jdt .core .dom .TypeDeclaration ;
2834import org .eclipse .lsp4j .Range ;
2935import org .springframework .ide .vscode .boot .java .Annotations ;
@@ -50,13 +56,15 @@ public class WebConfigJavaIndexer {
5056 public static final String USE_PATH_SEGMENT = "usePathSegment" ;
5157 public static final String USE_REQUEST_HEADER = "useRequestHeader" ;
5258 public static final String USE_MEDIA_TYPE_PARAMETER = "useMediaTypeParameter" ;
59+ public static final String USE_VERSION_RESOLVER = "useVersionResolver" ;
5360 public static final String ADD_SUPPORTED_VERSIONS = "addSupportedVersions" ;
5461
5562 public static final Set <String > VERSIONING_CONFIG_METHODS = Set .of (
5663 USE_PATH_SEGMENT ,
5764 USE_QUERY_PARAM ,
5865 USE_REQUEST_HEADER ,
59- USE_MEDIA_TYPE_PARAMETER
66+ USE_MEDIA_TYPE_PARAMETER ,
67+ USE_VERSION_RESOLVER
6068 );
6169
6270
@@ -241,6 +249,37 @@ private static Map<String, MethodInvocationExtractor> initializeMethodExtractors
241249 }
242250 }));
243251
252+ result .put (USE_VERSION_RESOLVER , new MethodInvocationExtractor () {
253+
254+ @ Override
255+ public Set <String > getTargetInvocationType () {
256+ return apiConfigurerInterfaces ;
257+ }
258+
259+ @ Override
260+ public void extractParameters (TextDocument doc , MethodInvocation methodInvocation , Builder webconfigBuilder ) {
261+ @ SuppressWarnings ("unchecked" )
262+ List <Expression > arguments = methodInvocation .arguments ();
263+ if (arguments .isEmpty ()) {
264+ recordVersionResolver (doc , methodInvocation , webconfigBuilder , "unspecified" );
265+ return ;
266+ }
267+ for (Expression expression : arguments ) {
268+ String label = describeApiVersionResolverArgument (expression );
269+ recordVersionResolver (doc , expression , webconfigBuilder , label != null ? label : "custom ApiVersionResolver" );
270+ }
271+ }
272+
273+ private void recordVersionResolver (TextDocument doc , ASTNode rangeNode , Builder webconfigBuilder , String label ) {
274+ try {
275+ Range range = doc .toRange (rangeNode .getStartPosition (), rangeNode .getLength ());
276+ webconfigBuilder .versionStrategy ("Version Resolver: " + label , range );
277+ }
278+ catch (BadLocationException e ) {
279+ }
280+ }
281+ });
282+
244283
245284 Set <String > pathConfigurerInterfaces = Set .of (
246285 Annotations .WEB_MVC_PATH_MATCH_CONFIGURER_INTERFACE ,
@@ -257,6 +296,40 @@ private static Map<String, MethodInvocationExtractor> initializeMethodExtractors
257296
258297 return result ;
259298 }
299+
300+ private static String describeApiVersionResolverArgument (Expression expression ) {
301+ if (expression instanceof CastExpression cast ) {
302+ return describeApiVersionResolverArgument (cast .getExpression ());
303+ }
304+ if (expression instanceof ClassInstanceCreation cic ) {
305+ ITypeBinding typeBinding = cic .getType ().resolveBinding ();
306+ if (typeBinding != null ) {
307+ return typeBinding .getQualifiedName ();
308+ }
309+ }
310+ if (expression instanceof LambdaExpression ) {
311+ return "lambda expression" ;
312+ }
313+ if (expression instanceof MethodInvocation mi ) {
314+ IMethodBinding methodBinding = mi .resolveMethodBinding ();
315+ if (methodBinding != null ) {
316+ ITypeBinding returnType = methodBinding .getReturnType ();
317+ if (returnType != null ) {
318+ return returnType .getQualifiedName ();
319+ }
320+ }
321+ }
322+ if (expression instanceof Name name ) {
323+ IBinding binding = name .resolveBinding ();
324+ if (binding instanceof IVariableBinding variableBinding ) {
325+ ITypeBinding variableType = variableBinding .getType ();
326+ if (variableType != null ) {
327+ return variableType .getQualifiedName ();
328+ }
329+ }
330+ }
331+ return null ;
332+ }
260333
261334 interface MethodInvocationExtractor {
262335 Set <String > getTargetInvocationType ();
0 commit comments