Skip to content

Commit 5f637bb

Browse files
Merge pull request #271 from AxonFramework/feature/fix-agg-model-recursion
Implement recursion guard for aggregate inspection
2 parents 4e8f837 + 8f7edff commit 5f637bb

File tree

2 files changed

+30
-3
lines changed

2 files changed

+30
-3
lines changed

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

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97,13 +97,18 @@ class AggregateStructureResolver(private val project: Project) {
9797
.flatMap {
9898
AnnotatedElementsSearch.searchPsiClasses(it.psiClass, project.axonScope()).findAll()
9999
}
100-
.mapNotNull { inspect(it, null) }
100+
.mapNotNull { inspect(it, emptyList()) }
101101
.flatMap { it.flatten() }
102102

103-
private fun inspect(clazz: PsiClass, parent: PsiClass?): Entity? {
103+
private fun inspect(clazz: PsiClass, parents: List<PsiClass>, depth: Int = 0): Entity? {
104104
if (clazz.isEnum) {
105105
return null
106106
}
107+
if(parents.contains(clazz) || depth > 20) {
108+
// Guard for infinite recursion; we already have this class indexed, or we exceed an exorbitant depth
109+
return null
110+
}
111+
val parent = parents.lastOrNull()
107112
val children = clazz.fields.toList()
108113
.filter { it.isAnnotated(AxonAnnotation.AGGREGATE_MEMBER) }
109114
.mapNotNull { field ->
@@ -112,7 +117,7 @@ class AggregateStructureResolver(private val project: Project) {
112117
val qualifiedName = psiType.toQualifiedName() ?: return@mapNotNull null
113118
val targetClass = clazz.javaFacade().findClass(qualifiedName, clazz.project.axonScope())
114119
?: return@mapNotNull null
115-
val modelMember = inspect(targetClass, clazz) ?: return@mapNotNull null
120+
val modelMember = inspect(targetClass, parents + clazz, depth + 1) ?: return@mapNotNull null
116121
val routingKey = field.resolveAnnotationStringValue(AxonAnnotation.AGGREGATE_MEMBER, "routingKey")
117122
val eventForwardingMode = field.resolveAnnotationClassValue(AxonAnnotation.AGGREGATE_MEMBER, "eventForwardingMode")
118123
EntityMember(field, field.name, modelMember, isCollection, routingKey, eventForwardingMode)

src/test/kotlin/org/axonframework/intellij/ide/plugin/markers/ClassLineMarkerProviderTest.kt

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,28 @@ class ClassLineMarkerProviderTest : AbstractAxonFixtureTestCase() {
102102
)
103103
}
104104

105+
fun `test shows line marker on aggregate of hierarchy when recursive`() {
106+
addFile(
107+
"MyAggregate.kt", """
108+
class RecursiveAggregateMember {
109+
@AggregateMember
110+
private var subItems: List<RecursiveAggregateMember>
111+
}
112+
113+
@AggregateRoot
114+
class MyAggregate {<caret>
115+
@AggregateMember
116+
private lateinit var singleMember: RecursiveAggregateMember
117+
}
118+
""".trimIndent(), open = true
119+
)
120+
Assertions.assertThat(hasLineMarker(ClassLineMarkerProvider::class.java)).isTrue
121+
Assertions.assertThat(getLineMarkerOptions(ClassLineMarkerProvider::class.java)).containsExactly(
122+
OptionSummary("MyAggregate", null, AxonIcons.Axon),
123+
OptionSummary("- RecursiveAggregateMember", null, AxonIcons.Axon),
124+
)
125+
}
126+
105127
fun `test shows line marker on child of hierarchy`() {
106128
addFile(
107129
"MyAggregate.kt", """

0 commit comments

Comments
 (0)