Skip to content

Commit a270349

Browse files
Take class hierarchy into account when resolving
Both when resolving handlers and creators, the hierarchy of classes was not interpreted correctly. This has been resolved. In addition, I discovered that the current interceptor implementation stood in the way of this fix, and that it should be implemented in another way. Interceptors are not handlers, after all, but this mechanism was abused for that. As such, the CommandHandlerInterceptor support has been removed. This may be re-added in the future.
1 parent 1849e17 commit a270349

File tree

15 files changed

+42
-655
lines changed

15 files changed

+42
-655
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
# Axon Framework plugin Changelog
44

5+
## [0.8.8]
6+
- Fix class hierarchy not being taken into account for handler and creator resolving.
7+
- Remove wrong implementation of interceptor support, to possibly be re-implemented in a future release in a better form.
8+
59
## [0.8.7]
610
- Plugin is now compatible with IDEA 2024.2 (IDEA 242.*)
711

src/main/kotlin/org/axonframework/intellij/ide/plugin/api/MessageHandlerType.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ enum class MessageHandlerType(
3232
EVENT_SOURCING(AxonAnnotation.EVENT_SOURCING_HANDLER, MessageType.EVENT),
3333
QUERY(AxonAnnotation.QUERY_HANDLER, MessageType.QUERY),
3434
DEADLINE(AxonAnnotation.DEADLINE_HANDLER, MessageType.DEADLINE),
35-
COMMAND_INTERCEPTOR(AxonAnnotation.COMMAND_HANDLER_INTERCEPTOR, MessageType.COMMAND),
3635
SAGA(AxonAnnotation.SAGA_EVENT_HANDLER, MessageType.EVENT),
3736
;
3837

@@ -43,7 +42,7 @@ enum class MessageHandlerType(
4342
if (annotationName == null) {
4443
return false
4544
}
46-
return values().any { type -> type.annotationName == annotationName }
45+
return entries.any { type -> type.annotationName == annotationName }
4746
}
4847
}
4948
}

src/main/kotlin/org/axonframework/intellij/ide/plugin/markers/handlers/CommandHandlerMethodLineMarkerProvider.kt

Lines changed: 0 additions & 61 deletions
This file was deleted.

src/main/kotlin/org/axonframework/intellij/ide/plugin/markers/handlers/CommandInterceptorLineMarkerProvider.kt

Lines changed: 0 additions & 69 deletions
This file was deleted.

src/main/kotlin/org/axonframework/intellij/ide/plugin/markers/handlers/CommonHandlerMethodLineMarkerProvider.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import org.axonframework.intellij.ide.plugin.util.creatorResolver
2929
* Provides a gutter icon on all generic handler methods
3030
*/
3131
class CommonHandlerMethodLineMarkerProvider : AbstractHandlerLineMarkerProvider() {
32-
private val blacklistedTypes = listOf(MessageHandlerType.DEADLINE, MessageHandlerType.COMMAND, MessageHandlerType.COMMAND_INTERCEPTOR)
32+
private val blacklistedTypes = listOf(MessageHandlerType.DEADLINE)
3333
override fun createLineMarker(
3434
element: PsiElement,
3535
handlerType: MessageHandlerType,

src/main/kotlin/org/axonframework/intellij/ide/plugin/markers/publishers/PublishMethodLineMarkerProvider.kt

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@ package org.axonframework.intellij.ide.plugin.markers.publishers
1818

1919
import com.intellij.codeInsight.daemon.LineMarkerInfo
2020
import com.intellij.codeInsight.daemon.LineMarkerProvider
21-
import com.intellij.codeInsight.daemon.RelatedItemLineMarkerInfo
22-
import com.intellij.codeInsight.daemon.RelatedItemLineMarkerProvider
2321
import com.intellij.codeInsight.navigation.NavigationGutterIconBuilder
2422
import com.intellij.ide.highlighter.JavaFileType
2523
import com.intellij.psi.PsiElement
@@ -29,7 +27,6 @@ import org.axonframework.intellij.ide.plugin.AxonIcons
2927
import org.axonframework.intellij.ide.plugin.api.MessageHandlerType
3028
import org.axonframework.intellij.ide.plugin.markers.AxonNavigationTargetRenderer
3129
import org.axonframework.intellij.ide.plugin.resolving.MessageHandlerResolver
32-
import org.axonframework.intellij.ide.plugin.resolving.handlers.types.CommandHandlerInterceptor
3330
import org.axonframework.intellij.ide.plugin.resolving.handlers.types.DeadlineHandler
3431
import org.axonframework.intellij.ide.plugin.util.containingClassFqn
3532
import org.axonframework.intellij.ide.plugin.util.handlerResolver
@@ -66,11 +63,9 @@ class PublishMethodLineMarkerProvider : LineMarkerProvider {
6663
else -> null
6764
} ?: return null
6865

69-
val allHandlers = element.handlerResolver().findHandlersForType(payload)
66+
val handlers = element.handlerResolver().findHandlersForType(payload)
7067
// Hide DeadlineHandlers here. These are handled by a more specific LineMarkerProvider
7168
.filter { it !is DeadlineHandler }
72-
val isCommand = allHandlers.all { it.handlerType == MessageHandlerType.COMMAND }
73-
val handlers = allHandlers.filter { it !is CommandHandlerInterceptor || isCommand } // Only show interceptors when is a command
7469
if (handlers.isEmpty()) {
7570
return null
7671
}

src/main/kotlin/org/axonframework/intellij/ide/plugin/resolving/MessageCreationResolver.kt

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@ package org.axonframework.intellij.ide.plugin.resolving
1818

1919
import com.intellij.openapi.project.Project
2020
import com.intellij.psi.PsiElement
21+
import com.intellij.psi.search.searches.ClassInheritorsSearch
2122
import com.intellij.psi.search.searches.MethodReferencesSearch
2223
import com.intellij.psi.util.CachedValue
2324
import org.axonframework.intellij.ide.plugin.api.MessageCreator
2425
import org.axonframework.intellij.ide.plugin.resolving.creators.DefaultMessageCreator
25-
import org.axonframework.intellij.ide.plugin.util.areAssignable
2626
import org.axonframework.intellij.ide.plugin.util.axonScope
2727
import org.axonframework.intellij.ide.plugin.util.createCachedValue
2828
import org.axonframework.intellij.ide.plugin.util.findParentHandlers
@@ -38,7 +38,6 @@ import java.util.concurrent.ConcurrentHashMap
3838
* the PSI is modified (code is edited) or is collected by the garbage collector.
3939
*/
4040
class MessageCreationResolver(private val project: Project) {
41-
private val handlerResolver = project.handlerResolver()
4241
private val psiFacade = project.javaFacade()
4342
private val constructorsByPayloadCache = ConcurrentHashMap<String, CachedValue<List<MessageCreator>>>()
4443

@@ -59,25 +58,19 @@ class MessageCreationResolver(private val project: Project) {
5958
}
6059

6160
private fun findByPayload(payload: String): List<MessageCreator> {
62-
val matchingHandlers = handlerResolver.findAllHandlers()
63-
.map { it.payload }
64-
.filter { areAssignable(project, payload, it) }
65-
val classesForQualifiedName = listOf(payload).plus(matchingHandlers)
66-
.distinct()
67-
return resolveCreatorsForFqns(classesForQualifiedName)
68-
}
61+
val classes = psiFacade.findClass(payload, project.axonScope())?.let { clazz ->
62+
listOf(clazz) + ClassInheritorsSearch.search(clazz, project.axonScope(), true)
63+
} ?: return emptyList()
6964

70-
private fun resolveCreatorsForFqns(fqns: List<String>): List<MessageCreator> {
71-
return fqns.flatMap { typeFqn ->
72-
psiFacade.findClasses(typeFqn, project.axonScope()).flatMap { clazz ->
65+
return classes
66+
.flatMap { clazz ->
7367
// Account for constructors and builder methods (builder(), toBuilder(), etc)
7468
val methods = clazz.constructors + clazz.methods.filter { it.name.contains("build", ignoreCase = true) }
7569
methods
7670
.flatMap { MethodReferencesSearch.search(it, project.axonScope(), true) }
77-
.flatMap { ref -> createCreators(typeFqn, ref.element) }
71+
.flatMap { ref -> createCreators(clazz.qualifiedName!!, ref.element) }
7872
.distinct()
7973
}
80-
}
8174
}
8275

8376
private fun createCreators(payload: String, element: PsiElement): List<MessageCreator> {

src/main/kotlin/org/axonframework/intellij/ide/plugin/resolving/MessageHandlerResolver.kt

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,22 @@
1717
package org.axonframework.intellij.ide.plugin.resolving
1818

1919
import com.intellij.openapi.project.Project
20+
import com.intellij.psi.JavaPsiFacade
21+
import com.intellij.psi.PsiClass
2022
import com.intellij.psi.PsiElement
23+
import com.intellij.psi.search.searches.ClassInheritorsSearch
2124
import org.axonframework.intellij.ide.plugin.api.Handler
2225
import org.axonframework.intellij.ide.plugin.api.MessageType
2326
import org.axonframework.intellij.ide.plugin.resolving.handlers.searchers.AggregateConstructorSearcher
24-
import org.axonframework.intellij.ide.plugin.resolving.handlers.searchers.CommandHandlerInterceptorSearcher
2527
import org.axonframework.intellij.ide.plugin.resolving.handlers.searchers.CommandHandlerSearcher
2628
import org.axonframework.intellij.ide.plugin.resolving.handlers.searchers.DeadlineHandlerSearcher
2729
import org.axonframework.intellij.ide.plugin.resolving.handlers.searchers.EventHandlerSearcher
2830
import org.axonframework.intellij.ide.plugin.resolving.handlers.searchers.EventSourcingHandlerSearcher
2931
import org.axonframework.intellij.ide.plugin.resolving.handlers.searchers.QueryHandlerSearcher
3032
import org.axonframework.intellij.ide.plugin.resolving.handlers.searchers.SagaEventHandlerSearcher
31-
import org.axonframework.intellij.ide.plugin.util.areAssignable
33+
import org.axonframework.intellij.ide.plugin.util.axonScope
3234
import org.axonframework.intellij.ide.plugin.util.createCachedValue
35+
import org.axonframework.intellij.ide.plugin.util.findCompleteSupers
3336

3437
/**
3538
* Searches the codebase for Message handlers based on the annotations defined in MessageHandlerType.
@@ -41,7 +44,6 @@ import org.axonframework.intellij.ide.plugin.util.createCachedValue
4144
*/
4245
class MessageHandlerResolver(private val project: Project) {
4346
private val searchers = listOf(
44-
CommandHandlerInterceptorSearcher(),
4547
CommandHandlerSearcher(),
4648
EventHandlerSearcher(),
4749
EventSourcingHandlerSearcher(),
@@ -61,20 +63,29 @@ class MessageHandlerResolver(private val project: Project) {
6163
fun findHandlersForType(
6264
qualifiedName: String,
6365
messageType: MessageType? = null,
64-
reverseAssign: Boolean = false
6566
): List<Handler> {
67+
val baseClass = JavaPsiFacade.getInstance(project).findClasses(qualifiedName, project.axonScope()).firstOrNull()
68+
?: return emptyList()
69+
70+
val additionalSupersOrImplementors = searchRelatedClasses(baseClass)
71+
val completeList = listOf(qualifiedName) + additionalSupersOrImplementors
6672
return handlerCache.value
6773
.filter { messageType == null || it.handlerType.messageType == messageType }
68-
.filter {
69-
if (reverseAssign) areAssignable(project, qualifiedName, it.payload) else areAssignable(
70-
project,
71-
it.payload,
72-
qualifiedName
73-
)
74-
}
74+
.filter { completeList.contains(it.payload) }
7575
.filter { it.element.isValid }
7676
}
7777

78+
private fun searchRelatedClasses(baseClass: PsiClass): List<String> {
79+
val implementors = ClassInheritorsSearch.search(baseClass, project.axonScope(), true)
80+
.mapNotNull { it.qualifiedName }
81+
.distinct()
82+
83+
// The supers call only returns one level at a time. We need to do this recursively
84+
return implementors + baseClass.findCompleteSupers()
85+
.mapNotNull { it.qualifiedName }
86+
.distinct()
87+
}
88+
7889
fun findAllHandlers(): List<Handler> = handlerCache.value
7990

8091
fun findHandlerByElement(psiElement: PsiElement): Handler? {

src/main/kotlin/org/axonframework/intellij/ide/plugin/resolving/handlers/searchers/CommandHandlerInterceptorSearcher.kt

Lines changed: 0 additions & 42 deletions
This file was deleted.

0 commit comments

Comments
 (0)