Skip to content

Commit 114c4af

Browse files
Merge pull request #306 from guymahieu/feature/support-inherited-accessors
[#307] Axon plugin gives false highlights about non existing properties when they are defined in a superclass
2 parents 781f71c + 4f77d7c commit 114c4af

File tree

5 files changed

+144
-11
lines changed

5 files changed

+144
-11
lines changed

src/main/kotlin/org/axonframework/intellij/ide/plugin/inspections/saga/JavaSagaAssociationPropertyInspection.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ class JavaSagaAssociationPropertyInspection : AbstractBaseJavaLocalInspectionToo
4949
return null
5050
val payload = method.resolvePayloadType() ?: return null
5151
val payloadClass = method.project.toClass(payload) ?: return null
52-
if (payloadClass.hasAccessor(attribute)) {
52+
if (payloadClass.hasAccessor(attribute, true)) {
5353
return null
5454
}
5555
val annotation = method.resolveAnnotation(AxonAnnotation.SAGA_EVENT_HANDLER) ?: return null

src/main/kotlin/org/axonframework/intellij/ide/plugin/inspections/saga/KotlinSagaAssociationPropertyInspection.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ class KotlinSagaAssociationPropertyInspection : AbstractKotlinInspection() {
5959
return
6060
val payload = method.resolvePayloadType() ?: return
6161
val payloadClass = method.project.toClass(payload) ?: return
62-
if (payloadClass.hasAccessor(attribute)) {
62+
if (payloadClass.hasAccessor(attribute, true)) {
6363
return
6464
}
6565
val annotation = method.resolveAnnotation(AxonAnnotation.SAGA_EVENT_HANDLER) ?: return

src/main/kotlin/org/axonframework/intellij/ide/plugin/util/PSiProcessingUtils.kt

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,13 +96,32 @@ fun Project.toClass(type: PsiType, scope: GlobalSearchScope = this.axonScope()):
9696
/**
9797
* Checks whether the PsiClass has an accessor with that name. That means either a field, or a function with getter-style naming
9898
*/
99-
fun PsiClass.hasAccessor(name: String): Boolean = this.getAccessor(name) != null
99+
fun PsiClass.hasAccessor(name: String, scanHierarchy: Boolean = false): Boolean = this.getAccessor(name, scanHierarchy) != null
100100

101101
/**
102102
* Gets the PsiElement representing an accessor with that name. That means either a field, or a function with getter-style naming
103+
* Will traverse the class hierarchy if true is passed as value for the scanHierarchy parameter
103104
*/
104-
fun PsiClass.getAccessor(name: String): PsiElement? {
105-
return fields.firstOrNull { it.name == name } ?: methods.firstOrNull { it.name == name.toGetterRepresentation() }
105+
fun PsiClass.getAccessor(name: String, scanHierarchy: Boolean = false): PsiElement? {
106+
return getAccessorImpl(name, scanHierarchy)
107+
}
108+
109+
private fun PsiClass.getAccessorImpl(name: String, scanHierarchy: Boolean = false): PsiElement? {
110+
val foundField = fields.firstOrNull { it.name == name }
111+
if (foundField != null) {
112+
return foundField
113+
}
114+
val foundMethod = methods.firstOrNull { it.name == name.toGetterRepresentation() }
115+
if (foundMethod != null) {
116+
return foundMethod
117+
}
118+
if (scanHierarchy && superClass != null) {
119+
val fromSuperclass = superClass?.getAccessorImpl(name, true)
120+
if (fromSuperclass != null) {
121+
return fromSuperclass
122+
}
123+
}
124+
return null
106125
}
107126

108127
/**

src/test/kotlin/org/axonframework/intellij/ide/plugin/inspections/saga/JavaSagaAssociationPropertyInspectionTest.kt

Lines changed: 71 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ class JavaSagaAssociationPropertyInspectionTest : AbstractAxonFixtureTestCase()
7373
myFixture.openFileInEditor(file)
7474
val highlights = myFixture.doHighlighting(HighlightSeverity.WARNING)
7575
Assertions.assertThat(highlights).noneMatch {
76-
it.text == "handle" && it.description.contains("The message does not declare a property")
76+
it.description.contains("The message does not declare a property")
7777
}
7878
}
7979

@@ -100,7 +100,40 @@ class JavaSagaAssociationPropertyInspectionTest : AbstractAxonFixtureTestCase()
100100
myFixture.openFileInEditor(file)
101101
val highlights = myFixture.doHighlighting(HighlightSeverity.WARNING)
102102
Assertions.assertThat(highlights).noneMatch {
103-
it.text == "handle" && it.description.contains("The message does not declare a property")
103+
it.description.contains("The message does not declare a property")
104+
}
105+
}
106+
107+
fun `test should detect defined property in superclass`() {
108+
addFile(
109+
"MyBaseMessage.java", """
110+
public abstract class MyBaseMessage {
111+
String some;
112+
}
113+
""".trimIndent()
114+
)
115+
addFile(
116+
"MyMessage.java", """
117+
public class MyMessage extends test.MyBaseMessage {
118+
}
119+
""".trimIndent()
120+
)
121+
val file = addFile(
122+
"MyHandler.java", """
123+
import test.MyMessage;
124+
125+
public class MyHandler {
126+
@SagaEventHandler(associationProperty = "some")
127+
public void handle(MyMessage message) {}
128+
}
129+
""".trimIndent()
130+
)
131+
132+
myFixture.enableInspections(JavaSagaAssociationPropertyInspection())
133+
myFixture.openFileInEditor(file)
134+
val highlights = myFixture.doHighlighting(HighlightSeverity.WARNING)
135+
Assertions.assertThat(highlights).noneMatch {
136+
it.description.contains("The message does not declare a property")
104137
}
105138
}
106139

@@ -129,7 +162,42 @@ class JavaSagaAssociationPropertyInspectionTest : AbstractAxonFixtureTestCase()
129162
myFixture.openFileInEditor(file)
130163
val highlights = myFixture.doHighlighting(HighlightSeverity.WARNING)
131164
Assertions.assertThat(highlights).noneMatch {
132-
it.text == "handle" && it.description.contains("The message does not declare a property")
165+
it.description.contains("The message does not declare a property")
166+
}
167+
}
168+
169+
fun `test should detect defined getter in superclass`() {
170+
addFile(
171+
"MyBaseMessage.java", """
172+
public abstract class MyBaseMessage {
173+
String getSome() {
174+
return "";
175+
}
176+
}
177+
""".trimIndent()
178+
)
179+
addFile(
180+
"MyMessage.java", """
181+
public class MyMessage extends test.MyBaseMessage {
182+
}
183+
""".trimIndent()
184+
)
185+
val file = addFile(
186+
"MyHandler.java", """
187+
import test.MyMessage;
188+
189+
public class MyHandler {
190+
@SagaEventHandler(associationProperty = "some")
191+
public void handle(MyMessage message) {}
192+
}
193+
""".trimIndent()
194+
)
195+
196+
myFixture.enableInspections(JavaSagaAssociationPropertyInspection())
197+
myFixture.openFileInEditor(file)
198+
val highlights = myFixture.doHighlighting(HighlightSeverity.WARNING)
199+
Assertions.assertThat(highlights).noneMatch {
200+
it.description.contains("The message does not declare a property")
133201
}
134202
}
135203
}

src/test/kotlin/org/axonframework/intellij/ide/plugin/inspections/saga/KotlinSagaAssociationPropertyInspectionTest.kt

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ class KotlinSagaAssociationPropertyInspectionTest : AbstractAxonFixtureTestCase(
5757
myFixture.openFileInEditor(file)
5858
val highlights = myFixture.doHighlighting(HighlightSeverity.WARNING)
5959
Assertions.assertThat(highlights).noneMatch {
60-
it.text == "handle" && it.description.contains("The message does not declare a property")
60+
it.description.contains("The message does not declare a property")
6161
}
6262
}
6363

@@ -77,7 +77,29 @@ class KotlinSagaAssociationPropertyInspectionTest : AbstractAxonFixtureTestCase(
7777
myFixture.openFileInEditor(file)
7878
val highlights = myFixture.doHighlighting(HighlightSeverity.WARNING)
7979
Assertions.assertThat(highlights).noneMatch {
80-
it.text == "handle" && it.description.contains("The message does not declare a property")
80+
it.description.contains("The message does not declare a property")
81+
}
82+
}
83+
84+
fun `test detect defined property in superclass`() {
85+
val file = addFile(
86+
"file.kt", """
87+
open class MyBaseMessage(open val some: String)
88+
89+
open class MyMessage() : MyBaseMessage("")
90+
91+
class MyHandler {
92+
@SagaEventHandler(associationProperty = "some")
93+
fun handle(message: MyMessage) {}
94+
}
95+
""".trimIndent()
96+
)
97+
98+
myFixture.enableInspections(KotlinSagaAssociationPropertyInspection())
99+
myFixture.openFileInEditor(file)
100+
val highlights = myFixture.doHighlighting(HighlightSeverity.WARNING)
101+
Assertions.assertThat(highlights).noneMatch {
102+
it.description.contains("The message does not declare a property")
81103
}
82104
}
83105

@@ -99,7 +121,31 @@ class KotlinSagaAssociationPropertyInspectionTest : AbstractAxonFixtureTestCase(
99121
myFixture.openFileInEditor(file)
100122
val highlights = myFixture.doHighlighting(HighlightSeverity.WARNING)
101123
Assertions.assertThat(highlights).noneMatch {
102-
it.text == "handle" && it.description.contains("The message does not declare a property")
124+
it.description.contains("The message does not declare a property")
125+
}
126+
}
127+
128+
fun `test detect defined getter in superclass`() {
129+
val file = addFile(
130+
"file.kt", """
131+
open class MyBaseMessage() {
132+
fun getSome() = ""
133+
}
134+
135+
open class MyMessage : MyBaseMessage
136+
137+
class MyHandler {
138+
@SagaEventHandler(associationProperty = "some")
139+
fun handle(message: MyMessage) {}
140+
}
141+
""".trimIndent()
142+
)
143+
144+
myFixture.enableInspections(KotlinSagaAssociationPropertyInspection())
145+
myFixture.openFileInEditor(file)
146+
val highlights = myFixture.doHighlighting(HighlightSeverity.WARNING)
147+
Assertions.assertThat(highlights).noneMatch {
148+
it.description.contains("The message does not declare a property")
103149
}
104150
}
105151
}

0 commit comments

Comments
 (0)