Skip to content

Commit 42ff43d

Browse files
authored
Merge pull request #115 from domaframework/fix/reference-static-class
Support reference resolution for bind variables that reference classpath resources within JAR files.
2 parents b9c3180 + 0f3a757 commit 42ff43d

File tree

5 files changed

+89
-39
lines changed

5 files changed

+89
-39
lines changed

src/main/kotlin/org/domaframework/doma/intellij/common/psi/PsiStaticElement.kt

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,10 @@
1515
*/
1616
package org.domaframework.doma.intellij.common.psi
1717

18+
import com.intellij.psi.JavaPsiFacade
1819
import com.intellij.psi.PsiClass
1920
import com.intellij.psi.PsiFile
21+
import com.intellij.psi.search.GlobalSearchScope
2022
import org.domaframework.doma.intellij.extension.getJavaClazz
2123
import org.domaframework.doma.intellij.psi.SqlElExpr
2224
import org.jetbrains.kotlin.idea.base.util.module
@@ -26,7 +28,7 @@ import org.jetbrains.kotlin.idea.base.util.module
2628
*/
2729
class PsiStaticElement(
2830
elExprList: List<SqlElExpr>? = null,
29-
originalFile: PsiFile,
31+
private val originalFile: PsiFile,
3032
) {
3133
private var fqdn = elExprList?.joinToString(".") { e -> e.text } ?: ""
3234
private val module = originalFile.module
@@ -38,5 +40,10 @@ class PsiStaticElement(
3840
.substringBefore("@")
3941
}
4042

41-
fun getRefClazz(): PsiClass? = module?.getJavaClazz(true, fqdn)
43+
fun getRefClazz(): PsiClass? =
44+
module?.getJavaClazz(true, fqdn)
45+
?: JavaPsiFacade.getInstance(originalFile.project).findClass(
46+
fqdn,
47+
GlobalSearchScope.allScope(originalFile.project),
48+
)
4249
}

src/main/kotlin/org/domaframework/doma/intellij/reference/SqlElIdExprReference.kt

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -71,10 +71,10 @@ class SqlElIdExprReference(
7171
startTime: Long,
7272
file: PsiFile,
7373
): PsiElement? {
74-
val targetElement = getBlockCommentElements(element)
75-
if (targetElement.isEmpty()) return null
74+
val targetElements = getBlockCommentElements(element)
75+
if (targetElements.isEmpty()) return null
7676

77-
val topElm = targetElement.firstOrNull() as? PsiElement ?: return null
77+
val topElm = targetElements.firstOrNull() as? PsiElement ?: return null
7878

7979
if (topElm.prevSibling.elementType == SqlTypes.AT_SIGN) return null
8080

@@ -92,14 +92,14 @@ class SqlElIdExprReference(
9292
val daoMethod = findDaoMethod(file) ?: return null
9393

9494
return when (element.textOffset) {
95-
targetElement.first().textOffset ->
95+
targetElements.first().textOffset ->
9696
getReferenceDaoMethodParameter(
9797
daoMethod,
9898
element,
9999
startTime,
100100
)
101101

102-
else -> getReferenceEntity(daoMethod, targetElement, startTime)
102+
else -> getReferenceEntity(daoMethod, targetElements, startTime)
103103
}
104104
}
105105

@@ -124,13 +124,13 @@ class SqlElIdExprReference(
124124

125125
private fun getReferenceDaoMethodParameter(
126126
daoMethod: PsiMethod,
127-
it: PsiElement,
127+
bindElement: PsiElement,
128128
startTime: Long,
129129
): PsiElement? {
130130
daoMethod
131131
.let { method ->
132132
method.methodParameters.firstOrNull { param ->
133-
param.name == it.text
133+
param.name == bindElement.text
134134
}
135135
}?.originalElement
136136
?.let { originalElm ->

src/main/kotlin/org/domaframework/doma/intellij/reference/SqlElStaticFieldReference.kt

Lines changed: 69 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,14 @@ import com.intellij.psi.util.CachedValuesManager
2424
import com.intellij.psi.util.PsiModificationTracker
2525
import com.intellij.psi.util.PsiTreeUtil
2626
import com.intellij.psi.util.PsiTypesUtil
27+
import com.intellij.psi.util.elementType
2728
import org.domaframework.doma.intellij.common.PluginLoggerUtil
2829
import org.domaframework.doma.intellij.common.isSupportFileType
2930
import org.domaframework.doma.intellij.common.psi.PsiParentClass
3031
import org.domaframework.doma.intellij.common.psi.PsiStaticElement
32+
import org.domaframework.doma.intellij.psi.SqlElIdExpr
3133
import org.domaframework.doma.intellij.psi.SqlElStaticFieldAccessExpr
34+
import org.domaframework.doma.intellij.psi.SqlTypes
3235

3336
class SqlElStaticFieldReference(
3437
element: PsiElement,
@@ -73,37 +76,74 @@ class SqlElStaticFieldReference(
7376
// Jump from field or method to definition (assuming the top element is static)
7477
val staticAccessParent =
7578
PsiTreeUtil.getParentOfType(staticDirection, SqlElStaticFieldAccessExpr::class.java)
76-
if (staticAccessParent != null) {
77-
val firstChildText =
78-
staticAccessParent.children
79-
.firstOrNull()
80-
?.text ?: ""
81-
val psiStaticElement =
82-
PsiStaticElement(
83-
firstChildText,
84-
file,
85-
)
86-
val javaClazz = psiStaticElement.getRefClazz() ?: return null
87-
val psiParentClass = PsiParentClass(PsiTypesUtil.getClassType(javaClazz))
88-
psiParentClass.findField(elementName)?.let {
89-
PluginLoggerUtil.countLogging(
90-
this::class.java.simpleName,
91-
"ReferenceStaticField",
92-
"Reference",
93-
startTime,
94-
)
95-
return it
96-
}
97-
psiParentClass.findMethod(elementName)?.let {
98-
PluginLoggerUtil.countLogging(
99-
this::class.java.simpleName,
100-
"ReferenceStaticMethod",
101-
"Reference",
102-
startTime,
103-
)
104-
return it
79+
if (staticAccessParent == null) return null
80+
81+
val firstChildText =
82+
staticAccessParent.children
83+
.firstOrNull()
84+
?.text ?: ""
85+
val psiStaticElement =
86+
PsiStaticElement(
87+
firstChildText,
88+
file,
89+
)
90+
val javaClazz = psiStaticElement.getRefClazz() ?: return null
91+
var parentClass = PsiParentClass(PsiTypesUtil.getClassType(javaClazz))
92+
93+
val targetElements = getBlockCommentElements(element)
94+
if (targetElements.isEmpty()) return null
95+
96+
val topElm = targetElements.firstOrNull() as? PsiElement ?: return null
97+
val prevSibling = topElm.prevSibling ?: return null
98+
if (prevSibling.elementType != SqlTypes.AT_SIGN) return null
99+
var index = 1
100+
for (staticFieldAccess in targetElements) {
101+
if (index >= targetElements.size) {
102+
parentClass.findField(elementName)?.let {
103+
PluginLoggerUtil.countLogging(
104+
this::class.java.simpleName,
105+
"ReferenceStaticField",
106+
"Reference",
107+
startTime,
108+
)
109+
return it
110+
}
111+
parentClass.findMethod(elementName)?.let {
112+
PluginLoggerUtil.countLogging(
113+
this::class.java.simpleName,
114+
"ReferenceStaticMethod",
115+
"Reference",
116+
startTime,
117+
)
118+
return it
119+
}
105120
}
121+
122+
val newParentType =
123+
parentClass.findField(staticFieldAccess.text)?.type
124+
?: parentClass.findMethod(staticFieldAccess.text)?.returnType
125+
if (newParentType == null) return null
126+
127+
parentClass = PsiParentClass(newParentType)
128+
index++
106129
}
107130
return null
108131
}
132+
133+
private fun getBlockCommentElements(element: PsiElement): List<PsiElement> {
134+
val fieldAccessExpr = PsiTreeUtil.getParentOfType(element, SqlElStaticFieldAccessExpr::class.java)
135+
val nodeElm =
136+
if (fieldAccessExpr != null) {
137+
PsiTreeUtil
138+
.getChildrenOfType(
139+
fieldAccessExpr,
140+
SqlElIdExpr::class.java,
141+
)?.filter { it.textOffset <= element.textOffset }
142+
} else {
143+
listOf(element)
144+
}
145+
return nodeElm
146+
?.toList()
147+
?.sortedBy { it.textOffset } ?: emptyList()
148+
}
109149
}

src/test/kotlin/org/domaframework/doma/intellij/reference/SqlReferenceTestCase.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,11 @@ class SqlReferenceTestCase : DomaSqlTest() {
7272
"referenceStaticField",
7373
mapOf(
7474
"doma.example.entity.ProjectDetail" to "$classResolve:ProjectDetail",
75+
"doma.example.entity.Project" to "$classResolve:Project",
7576
"projectCategory" to "$fieldResolve:projectCategory",
7677
"getTermNumber" to "$methodResolve:getTermNumber",
78+
"getFirstEmployee" to "$methodResolve:getFirstEmployee",
79+
"employeeId" to "$fieldResolve:employeeId",
7780
),
7881
)
7982
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
SELECT *
22
FROM project_detail
33
WHERE category = /* @doma.example.entity.ProjectDetail@projectCategory */'category'
4-
AND number = /* @doma.example.entity.ProjectDetail@getTermNumber() */'9999'
4+
AND number = /* @doma.example.entity.Project@getFirstEmployee().employeeId */'9999'

0 commit comments

Comments
 (0)