Skip to content

Commit 895ebd1

Browse files
committed
Check for DAO parameters that overlap with for directive definition names
1 parent 538c957 commit 895ebd1

File tree

3 files changed

+58
-20
lines changed

3 files changed

+58
-20
lines changed

src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/inspector/DaoMethodVariableInspector.kt

Lines changed: 54 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -33,18 +33,26 @@ import org.domaframework.doma.intellij.bundle.MessageBundle
3333
import org.domaframework.doma.intellij.common.dao.getDaoClass
3434
import org.domaframework.doma.intellij.common.isJavaOrKotlinFileType
3535
import org.domaframework.doma.intellij.common.psi.PsiDaoMethod
36+
import org.domaframework.doma.intellij.common.util.ForDirectiveUtil
3637
import org.domaframework.doma.intellij.extension.findFile
38+
import org.domaframework.doma.intellij.extension.psi.getForItem
3739
import org.domaframework.doma.intellij.extension.psi.isCollector
3840
import org.domaframework.doma.intellij.extension.psi.isFunctionClazz
3941
import org.domaframework.doma.intellij.extension.psi.isSelectOption
4042
import org.domaframework.doma.intellij.extension.psi.methodParameters
41-
import org.domaframework.doma.intellij.psi.SqlElStaticFieldAccessExpr
43+
import org.domaframework.doma.intellij.psi.SqlElForDirective
44+
import org.domaframework.doma.intellij.psi.SqlElPrimaryExpr
4245
import org.domaframework.doma.intellij.psi.SqlTypes
4346

4447
/**
4548
* Check if Dao method arguments are used in the corresponding SQL file
4649
*/
4750
class DaoMethodVariableInspector : AbstractBaseJavaLocalInspectionTool() {
51+
private data class DaoMethodVariableVisitorResult(
52+
val elements: List<PsiParameter>,
53+
val deplicateForItemElements: List<PsiParameter>,
54+
)
55+
4856
override fun getDisplayName(): String = "Method argument usage check"
4957

5058
override fun getShortName(): String = "org.domaframework.doma.intellij.variablechecker"
@@ -76,38 +84,65 @@ class DaoMethodVariableInspector : AbstractBaseJavaLocalInspectionTool() {
7684
method.project.findFile(it)
7785
} ?: return
7886

79-
findElementsInSqlFile(sqlFileManager, methodParameters.toList()).forEach { arg ->
80-
holder.registerProblem(
81-
(arg.originalElement as PsiParameterImpl).nameIdentifier,
82-
MessageBundle.message("inspection.dao.method.variable.error", arg.name),
83-
ProblemHighlightType.ERROR,
84-
)
87+
val params = methodParameters.toList()
88+
val result = findElementsInSqlFile(sqlFileManager, params)
89+
params.forEach { param ->
90+
if (!result.elements.contains(param)) {
91+
val message =
92+
if (result.deplicateForItemElements.contains(param)) {
93+
MessageBundle.message("inspection.invalid.dao.duplicate")
94+
} else {
95+
MessageBundle.message(
96+
"inspection.dao.method.variable.error",
97+
param.name,
98+
)
99+
}
100+
holder.registerProblem(
101+
(param.originalElement as PsiParameterImpl).nameIdentifier,
102+
message,
103+
ProblemHighlightType.ERROR,
104+
)
105+
}
85106
}
86107
}
87108
}
88109
}
89110

90-
fun findElementsInSqlFile(
111+
private fun findElementsInSqlFile(
91112
sqlFile: PsiFile,
92113
args: List<PsiParameter>,
93-
): List<PsiParameter> {
114+
): DaoMethodVariableVisitorResult {
94115
val elements = mutableListOf<PsiParameter>()
116+
val deplicateForItemElements = mutableListOf<PsiParameter>()
95117
var iterator: Iterator<PsiParameter>
96118
sqlFile.accept(
97119
object : PsiRecursiveElementVisitor() {
98120
// Recursively explore child elements in a file with PsiRecursiveElementVisitor.
99121
override fun visitElement(element: PsiElement) {
100-
if (element.elementType == SqlTypes.EL_IDENTIFIER && element.prevSibling?.elementType != SqlTypes.DOT) {
122+
if ((
123+
element.elementType == SqlTypes.EL_IDENTIFIER ||
124+
element is SqlElPrimaryExpr
125+
) &&
126+
element.prevSibling?.elementType != SqlTypes.DOT
127+
) {
101128
iterator = args.minus(elements.toSet()).iterator()
102129
while (iterator.hasNext()) {
103130
val arg = iterator.next()
104-
val fieldAccessExpr =
105-
PsiTreeUtil.getParentOfType(
106-
element,
107-
SqlElStaticFieldAccessExpr::class.java,
108-
)
109-
if (fieldAccessExpr == null && element.text == arg.name) {
110-
elements.add(arg)
131+
if (element.text == arg.name) {
132+
// Check if you are in a For directive
133+
val elementParent = PsiTreeUtil.getParentOfType(element, SqlElForDirective::class.java)
134+
val isForItemSide = elementParent?.getForItem()?.textOffset == element.textOffset
135+
136+
// Check if the element name definition source is in the for directive
137+
val forDirectiveBlocks =
138+
ForDirectiveUtil.getForDirectiveBlocks(element)
139+
val forItem = ForDirectiveUtil.findForItem(element, forDirectives = forDirectiveBlocks)
140+
141+
if (forItem != null || isForItemSide) {
142+
deplicateForItemElements.add(arg)
143+
} else {
144+
elements.add(arg)
145+
}
111146
break
112147
}
113148
}
@@ -116,6 +151,7 @@ class DaoMethodVariableInspector : AbstractBaseJavaLocalInspectionTool() {
116151
}
117152
},
118153
)
119-
return args.minus(elements.toSet())
154+
val result = DaoMethodVariableVisitorResult(elements, deplicateForItemElements)
155+
return result
120156
}
121157
}

src/main/resources/messages/DomaToolsBundle.properties

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,5 @@ inspection.invalid.sql.topType=Can't get type of first element
1010
inspection.invalid.sql.staticProperty=[{0}] is not a public or static property in the class [{1}]
1111
inspection.invalid.sql.testdata=Bind variables must be followed by test data
1212
inspection.invalid.sql.classpath=A non-existent package or class name was specified [{0}]
13-
inspection.invalid.sql.iterable=The type that can be used in the for directive is an Iterable type
13+
inspection.invalid.sql.iterable=The type that can be used in the for directive is an Iterable type
14+
inspection.invalid.dao.duplicate=An element name that is a duplicate of an element name defined in SQL is used

src/main/resources/messages/DomaToolsBundle_ja.properties

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,5 @@ inspection.invalid.sql.topType=\u6700\u521D\u306E\u8981\u7D20\u306E\u578B\u304C\
1010
inspection.invalid.sql.staticProperty=[{0}]\u0020\u306F\u30AF\u30E9\u30B9\u0020[{1}]\u0020\u306E\u0020\u0070\u0075\u0062\u006C\u0069\u0063\u0020\u307E\u305F\u0020\u0073\u0074\u0061\u0074\u0069\u0063\u0020\u30D7\u30ED\u30D1\u30C6\u30A3\u3067\u306F\u3042\u308A\u307E\u305B\u3093
1111
inspection.invalid.sql.testdata=\u30D0\u30A4\u30F3\u30C9\u5909\u6570\u306E\u5F8C\u308D\u306B\u306F\u30C6\u30B9\u30C8\u30C7\u30FC\u30BF\u304C\u5FC5\u8981\u3067\u3059
1212
inspection.invalid.sql.classpath=\u5B58\u5728\u3057\u306A\u3044\u30D1\u30C3\u30B1\u30FC\u30B8\u307E\u305F\u306F\u30AF\u30E9\u30B9\u540D\u304C\u6307\u5B9A\u3055\u308C\u307E\u3057\u305F\u3002:[{0}]
13-
inspection.invalid.sql.iterable=\u0066\u006F\u0072\u30C7\u30A3\u30EC\u30AF\u30C6\u30A3\u30D6\u306B\u4F7F\u7528\u3067\u304D\u308B\u578B\u306F\u0049\u0074\u0065\u0072\u0061\u0062\u006C\u0065\u578B\u3067\u3059
13+
inspection.invalid.sql.iterable=\u0066\u006F\u0072\u30C7\u30A3\u30EC\u30AF\u30C6\u30A3\u30D6\u306B\u4F7F\u7528\u3067\u304D\u308B\u578B\u306F\u0049\u0074\u0065\u0072\u0061\u0062\u006C\u0065\u578B\u3067\u3059
14+
inspection.invalid.dao.duplicate=\u0053\u0051\u004C\u5185\u3067\u5B9A\u7FA9\u3055\u308C\u305F\u8981\u7D20\u540D\u3068\u91CD\u8907\u3057\u305F\u8981\u7D20\u540D\u304C\u4F7F\u7528\u3055\u308C\u3066\u3044\u307E\u3059

0 commit comments

Comments
 (0)