1919import org .eclipse .jdt .core .dom .ASTNode ;
2020import org .eclipse .jdt .core .dom .Annotation ;
2121import org .eclipse .jdt .core .dom .CompilationUnit ;
22- import org .eclipse .jdt .core .dom .FieldDeclaration ;
22+ import org .eclipse .jdt .core .dom .Expression ;
2323import org .eclipse .jdt .core .dom .IAnnotationBinding ;
2424import org .eclipse .jdt .core .dom .MemberValuePair ;
25+ import org .eclipse .jdt .core .dom .NormalAnnotation ;
26+ import org .eclipse .jdt .core .dom .SingleMemberAnnotation ;
2527import org .eclipse .jdt .core .dom .StringLiteral ;
2628import org .eclipse .lsp4j .Location ;
2729import org .eclipse .lsp4j .LocationLink ;
4345public class PropertyValueAnnotationDefProvider implements IJavaDefinitionProvider {
4446
4547 private static final Logger log = LoggerFactory .getLogger (PropertyValueAnnotationDefProvider .class );
48+
49+ private static final String PARAM_VALUE = "value" ;
50+ private static final String PARAM_NAME = "name" ;
51+ private static final String PARAM_PREFIX = "prefix" ;
52+
53+ private Map <String , PropertyKeyExtractor > annotationToPropertyKeyExtractor = Map .of (
54+ Annotations .VALUE , (a , p , v ) -> {
55+ if (a .isSingleMemberAnnotation ()) {
56+ return extractPropertyKey (v .getLiteralValue ());
57+ } else if (a .isNormalAnnotation () && PARAM_VALUE .equals (p .getName ().getIdentifier ())) {
58+ return extractPropertyKey (v .getLiteralValue ());
59+ }
60+ return null ;
61+ },
62+ Annotations .CONDITIONAL_ON_PROPERTY , (a , p , v ) -> {
63+ if (a .isSingleMemberAnnotation ()) {
64+ return v .getLiteralValue ();
65+ } else if (a .isNormalAnnotation ()) {
66+ switch (p .getName ().getIdentifier ()) {
67+ case PARAM_VALUE :
68+ return v .getLiteralValue ();
69+ case PARAM_NAME :
70+ String prefix = extractAnnotationParameter (a , PARAM_PREFIX );
71+ String name = v .getLiteralValue ();
72+ return prefix != null && !prefix .isBlank () ? prefix + "." + name : name ;
73+ }
74+ }
75+ return null ;
76+ }
77+ );
4678
4779 @ Override
4880 public List <LocationLink > getDefinitions (CancelChecker cancelToken , IJavaProject project , CompilationUnit cu ,
@@ -52,13 +84,26 @@ public List<LocationLink> getDefinitions(CancelChecker cancelToken, IJavaProject
5284 String propertyKey = null ;
5385
5486 ASTNode parent = valueNode .getParent ();
55- if (parent instanceof Annotation && isApplicableValueAnnotation ((Annotation ) parent )) {
56- propertyKey = extractPropertyKey (valueNode .getLiteralValue ());
87+ if (parent instanceof Annotation ) {
88+ Annotation a = (Annotation ) parent ;
89+ IAnnotationBinding binding = a .resolveAnnotationBinding ();
90+ if (binding != null && binding .getAnnotationType () != null ) {
91+ PropertyKeyExtractor propertyExtractor = annotationToPropertyKeyExtractor .get (binding .getAnnotationType ().getQualifiedName ());
92+ if (propertyExtractor != null ) {
93+ propertyKey = propertyExtractor .extract (a , null , valueNode );
94+ }
95+ }
5796 } else if (parent instanceof MemberValuePair
58- && "value" .equals (((MemberValuePair ) parent ).getName ().getIdentifier ())
59- && parent .getParent () instanceof Annotation
60- && isApplicableValueAnnotation ((Annotation ) parent .getParent ())) {
61- propertyKey = extractPropertyKey (valueNode .getLiteralValue ());
97+ && parent .getParent () instanceof Annotation ) {
98+ MemberValuePair pair = (MemberValuePair ) parent ;
99+ Annotation a = (Annotation ) parent .getParent ();
100+ IAnnotationBinding binding = a .resolveAnnotationBinding ();
101+ if (binding != null && binding .getAnnotationType () != null ) {
102+ PropertyKeyExtractor propertyExtractor = annotationToPropertyKeyExtractor .get (binding .getAnnotationType ().getQualifiedName ());
103+ if (propertyExtractor != null ) {
104+ propertyKey = propertyExtractor .extract (a , pair , valueNode );
105+ }
106+ }
62107 }
63108
64109 if (propertyKey != null ) {
@@ -87,12 +132,6 @@ && isApplicableValueAnnotation((Annotation) parent.getParent())) {
87132 return Collections .emptyList ();
88133 }
89134
90- private static boolean isApplicableValueAnnotation (Annotation a ) {
91- IAnnotationBinding binding = a .resolveAnnotationBinding ();
92- return binding != null && Annotations .VALUE .equals (binding .getAnnotationType ().getQualifiedName ())
93- && a .getParent () instanceof FieldDeclaration ;
94- }
95-
96135 private List <Location > findValueReferences (IJavaProject project , String propertyKey , Map <Location , Range > targetRanges ) {
97136 Builder <Location > links = ImmutableList .builder ();
98137 IClasspathUtil .getClasspathResourcesFullPaths (project .getClasspath ()).forEach (path -> {
@@ -159,12 +198,35 @@ private List<Location> findValueReferences(IJavaProject project, String property
159198 });
160199 return links .build ();
161200 }
201+
202+ @ SuppressWarnings ("unchecked" )
203+ private static String extractAnnotationParameter (Annotation a , String param ) {
204+ Expression value = null ;
205+ if (a .isSingleMemberAnnotation () && PARAM_VALUE .equals (param )) {
206+ value = ((SingleMemberAnnotation ) a ).getValue ();
207+ } else if (a .isNormalAnnotation ()) {
208+ for (MemberValuePair pair : (List <MemberValuePair >) ((NormalAnnotation ) a ).values ()) {
209+ if (param .equals (pair .getName ().getIdentifier ())) {
210+ value = pair .getValue ();
211+ break ;
212+ }
213+ }
214+ }
215+ if (value instanceof StringLiteral ) {
216+ return ((StringLiteral ) value ).getLiteralValue ();
217+ }
218+ return null ;
219+ }
162220
163221 private static String extractPropertyKey (String s ) {
164222 if (s .length () > 3 && (s .startsWith ("${" ) || s .startsWith ("#{" )) && s .endsWith ("}" )) {
165223 return s .substring (2 , s .length () - 1 );
166224 }
167225 return null ;
168226 }
227+
228+ private interface PropertyKeyExtractor {
229+ String extract (Annotation a , MemberValuePair pair , StringLiteral v );
230+ }
169231
170232}
0 commit comments