1010 *******************************************************************************/
1111package org .springframework .ide .vscode .boot .java .events ;
1212
13+ import java .util .Arrays ;
1314import java .util .List ;
15+ import java .util .Map ;
1416import java .util .Optional ;
1517import java .util .Set ;
18+ import java .util .stream .Collectors ;
1619
1720import org .eclipse .jdt .core .dom .ASTNode ;
1821import org .eclipse .jdt .core .dom .Annotation ;
2528import org .springframework .ide .vscode .boot .index .SpringMetamodelIndex ;
2629import org .springframework .ide .vscode .boot .java .handlers .ReferenceProvider ;
2730import org .springframework .ide .vscode .commons .java .IJavaProject ;
31+ import org .springframework .ide .vscode .commons .protocol .spring .AnnotationAttributeValue ;
32+ import org .springframework .ide .vscode .commons .protocol .spring .AnnotationMetadata ;
2833import org .springframework .ide .vscode .commons .util .BadLocationException ;
2934import org .springframework .ide .vscode .commons .util .text .TextDocument ;
3035
@@ -55,19 +60,26 @@ public List<? extends Location> provideReferences(CancelChecker cancelToken, IJa
5560 List <EventListenerIndexElement > listeners = index .getNodesOfType (EventListenerIndexElement .class );
5661 List <EventPublisherIndexElement > publishers = index .getNodesOfType (EventPublisherIndexElement .class );
5762
58- // when offset is inside an event listener, find the respective event type
59- Optional <String > listenerEventType = listeners .stream ()
63+ // when offset is inside an event listener, look for references from publishers
64+ Optional <EventListenerIndexElement > listenerElement = listeners .stream ()
6065 .filter (listener -> listener .getLocation ().getUri ().equals (doc .getUri ()))
6166 .filter (eventListener -> isPositionInside (position , eventListener .getLocation ()))
62- .map (eventListener -> eventListener .getEventType ())
6367 .findAny ();
6468
65- if (listenerEventType .isPresent ()) {
66- // use the listener event type to look for publishers for that type
67- String eventType = listenerEventType .get ();
69+ if (listenerElement .isPresent ()) {
70+ Set <String > eventTypes = getListenerEventTypes (listenerElement .get ());
6871
6972 List <Location > foundLocations = publishers .stream ()
70- .filter (publisher -> publisher .getEventType ().equals (eventType ) || publisher .getEventTypesFromHierarchy ().contains (eventType ))
73+ .filter (publisher -> {
74+ if (eventTypes .contains (publisher .getEventType ())) return true ;
75+
76+ for (String listenerEventType : eventTypes ) {
77+ if (publisher .getEventTypesFromHierarchy ().contains (listenerEventType )) {
78+ return true ;
79+ }
80+ }
81+ return false ;
82+ })
7183 .map (publisher -> publisher .getLocation ())
7284 .toList ();
7385
@@ -76,20 +88,30 @@ public List<? extends Location> provideReferences(CancelChecker cancelToken, IJa
7688 }
7789 }
7890
79- // when offset is inside an event publisher, find the respective event type
91+ // when offset is inside an event publisher, look for references from listeners
8092 else {
8193 Optional <EventPublisherIndexElement > publisherElement = publishers .stream ()
8294 .filter (publisher -> publisher .getLocation ().getUri ().equals (doc .getUri ()))
8395 .filter (eventPublisher -> isPositionInside (position , eventPublisher .getLocation ()))
8496 .findAny ();
8597
8698 if (publisherElement .isPresent ()) {
87- // use the publisher event type to look for listeners for that type
8899 String eventType = publisherElement .get ().getEventType ();
89100 Set <String > eventTypesFromHierarchy = publisherElement .get ().getEventTypesFromHierarchy ();
90101
91102 List <Location > foundLocations = listeners .stream ()
92- .filter (listener -> listener .getEventType ().equals (eventType ) || eventTypesFromHierarchy .contains (listener .getEventType ()))
103+ .filter (listener -> {
104+ Set <String > listenerEventTypes = getListenerEventTypes (listener );
105+ for (String listenerEventType : listenerEventTypes ) {
106+ if (listenerEventType .equals (eventType )) {
107+ return true ;
108+ }
109+ if (eventTypesFromHierarchy .contains (listenerEventType )) {
110+ return true ;
111+ }
112+ }
113+ return false ;
114+ })
93115 .map (listener -> listener .getLocation ())
94116 .toList ();
95117
@@ -106,6 +128,29 @@ public List<? extends Location> provideReferences(CancelChecker cancelToken, IJa
106128 return null ;
107129 }
108130
131+ private Set <String > getListenerEventTypes (EventListenerIndexElement eventListenerIndexElement ) {
132+ AnnotationMetadata [] annotations = eventListenerIndexElement .getAnnotations ();
133+ if (annotations != null && annotations .length > 0 ) {
134+ for (AnnotationMetadata annotationMetadata : annotations ) {
135+ Map <String , AnnotationAttributeValue []> attributes = annotationMetadata .getAttributes ();
136+ if (attributes .containsKey ("classes" )) {
137+ AnnotationAttributeValue [] annotationAttributeValues = attributes .get ("classes" );
138+ return Arrays .stream (annotationAttributeValues )
139+ .map (attributeValue -> attributeValue .getName ())
140+ .collect (Collectors .toSet ());
141+ }
142+ else if (attributes .containsKey ("value" )) {
143+ AnnotationAttributeValue [] annotationAttributeValues = attributes .get ("value" );
144+ return Arrays .stream (annotationAttributeValues )
145+ .map (attributeValue -> attributeValue .getName ())
146+ .collect (Collectors .toSet ());
147+ }
148+ }
149+ }
150+
151+ return Set .of (eventListenerIndexElement .getEventType ());
152+ }
153+
109154 private boolean isPositionInside (Position position , Location location ) {
110155 boolean afterStart = position .getLine () > location .getRange ().getStart ().getLine ()
111156 || (position .getLine () == location .getRange ().getStart ().getLine () && position .getCharacter () >= location .getRange ().getStart ().getCharacter ());
0 commit comments