Skip to content

Commit f51ffd7

Browse files
committed
Add inspection visitor handler
1 parent 482f513 commit f51ffd7

File tree

6 files changed

+311
-186
lines changed

6 files changed

+311
-186
lines changed
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
/*
2+
* Copyright Doma Tools Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.domaframework.doma.intellij.inspection.sql.handler
17+
18+
import com.intellij.codeInspection.ProblemsHolder
19+
import com.intellij.psi.PsiFile
20+
import org.domaframework.doma.intellij.common.dao.findDaoMethod
21+
import org.domaframework.doma.intellij.common.psi.PsiDaoMethod
22+
import org.domaframework.doma.intellij.common.psi.PsiParentClass
23+
import org.domaframework.doma.intellij.common.sql.cleanString
24+
import org.domaframework.doma.intellij.common.sql.validator.result.ValidationForDirectiveItemTypeResult
25+
import org.domaframework.doma.intellij.common.util.ForDirectiveUtil
26+
import org.domaframework.doma.intellij.extension.expr.accessElements
27+
import org.domaframework.doma.intellij.extension.psi.findParameter
28+
import org.domaframework.doma.intellij.psi.SqlElFieldAccessExpr
29+
import org.domaframework.doma.intellij.psi.SqlElIdExpr
30+
import org.domaframework.doma.intellij.psi.SqlElPrimaryExpr
31+
32+
class InspectionFieldAccessVisitorProcessor(
33+
val shortName: String,
34+
private val element: SqlElFieldAccessExpr,
35+
) : InspectionVisitorProcessor(shortName) {
36+
fun check(
37+
holder: ProblemsHolder,
38+
file: PsiFile,
39+
) {
40+
// Get element inside block comment
41+
val blockElement = getFieldAccessBlocks(element)
42+
val topElm = blockElement.firstOrNull() as SqlElPrimaryExpr
43+
44+
// Exclude fixed Literal
45+
if (isLiteralOrStatic(topElm)) return
46+
47+
val topElement = blockElement.firstOrNull() ?: return
48+
val daoMethod = findDaoMethod(file) ?: return
49+
val project = topElement.project
50+
val forDirectiveBlocks = ForDirectiveUtil.getForDirectiveBlocks(topElement)
51+
val forItem = ForDirectiveUtil.findForItem(topElement, forDirectives = forDirectiveBlocks)
52+
var isBatchAnnotation = false
53+
val topElementParentClass =
54+
if (forItem != null) {
55+
val result = ForDirectiveUtil.getForDirectiveItemClassType(project, forDirectiveBlocks, forItem)
56+
if (result == null) {
57+
ValidationForDirectiveItemTypeResult(
58+
topElement,
59+
this.shortName,
60+
).highlightElement(holder)
61+
return
62+
}
63+
val specifiedClassType =
64+
ForDirectiveUtil.resolveForDirectiveItemClassTypeBySuffixElement(topElement.text)
65+
if (specifiedClassType != null) {
66+
PsiParentClass(specifiedClassType)
67+
} else {
68+
result
69+
}
70+
} else {
71+
val paramType = daoMethod.findParameter(cleanString(topElement.text))?.type
72+
if (paramType == null) {
73+
errorHighlight(topElement, daoMethod, holder)
74+
return
75+
}
76+
isBatchAnnotation = PsiDaoMethod(project, daoMethod).daoType.isBatchAnnotation()
77+
PsiParentClass(paramType)
78+
}
79+
80+
val result =
81+
ForDirectiveUtil.getFieldAccessLastPropertyClassType(
82+
blockElement,
83+
project,
84+
topElementParentClass,
85+
shortName = this.shortName,
86+
isBatchAnnotation = isBatchAnnotation,
87+
)
88+
89+
result?.highlightElement(holder)
90+
}
91+
92+
fun getFieldAccessBlocks(element: SqlElFieldAccessExpr): List<SqlElIdExpr> {
93+
val blockElements = element.accessElements
94+
(blockElements.firstOrNull() as? SqlElPrimaryExpr)
95+
?.let { if (isLiteralOrStatic(it)) return emptyList() }
96+
?: return emptyList()
97+
98+
return blockElements.mapNotNull { it as SqlElIdExpr }
99+
}
100+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/*
2+
* Copyright Doma Tools Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.domaframework.doma.intellij.inspection.sql.handler
17+
18+
import com.intellij.codeInspection.ProblemsHolder
19+
import com.intellij.psi.PsiFile
20+
import com.intellij.psi.util.PsiTreeUtil
21+
import org.domaframework.doma.intellij.common.dao.findDaoMethod
22+
import org.domaframework.doma.intellij.common.sql.cleanString
23+
import org.domaframework.doma.intellij.common.sql.validator.result.ValidationDaoParamResult
24+
import org.domaframework.doma.intellij.common.sql.validator.result.ValidationForDirectiveItemTypeResult
25+
import org.domaframework.doma.intellij.common.util.ForDirectiveUtil
26+
import org.domaframework.doma.intellij.extension.psi.findParameter
27+
import org.domaframework.doma.intellij.extension.psi.getForItem
28+
import org.domaframework.doma.intellij.psi.SqlElForDirective
29+
import org.domaframework.doma.intellij.psi.SqlElPrimaryExpr
30+
import org.domaframework.doma.intellij.psi.SqlElStaticFieldAccessExpr
31+
32+
class InspectionPrimaryVisitorProcessor(
33+
val shortName: String,
34+
private val element: SqlElPrimaryExpr,
35+
) : InspectionVisitorProcessor(shortName) {
36+
fun check(
37+
holder: ProblemsHolder,
38+
file: PsiFile,
39+
) {
40+
if (isLiteralOrStatic(element)) return
41+
PsiTreeUtil.getParentOfType(element, SqlElStaticFieldAccessExpr::class.java)?.let { return }
42+
43+
val forDirectiveExp = PsiTreeUtil.getParentOfType(element, SqlElForDirective::class.java)
44+
val isSkip = forDirectiveExp != null && forDirectiveExp.getForItem() != element
45+
46+
var forDirectiveBlocks = ForDirectiveUtil.getForDirectiveBlocks(element, skipSelf = isSkip)
47+
val forItem =
48+
ForDirectiveUtil.findForItem(
49+
element,
50+
skipSelf = isSkip,
51+
forDirectives = forDirectiveBlocks,
52+
)
53+
if (forItem != null) {
54+
val forDeclarationType =
55+
ForDirectiveUtil.getForDirectiveItemClassType(
56+
element.project,
57+
forDirectiveBlocks,
58+
forItem,
59+
)
60+
if (forDeclarationType == null) {
61+
ValidationForDirectiveItemTypeResult(
62+
element,
63+
this.shortName,
64+
).highlightElement(holder)
65+
}
66+
return
67+
}
68+
69+
val daoMethod = findDaoMethod(file) ?: return
70+
val param = daoMethod.findParameter(cleanString(element.text))
71+
if (param != null) return
72+
73+
ValidationDaoParamResult(
74+
element,
75+
daoMethod.name,
76+
this.shortName,
77+
).highlightElement(holder)
78+
}
79+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/*
2+
* Copyright Doma Tools Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.domaframework.doma.intellij.inspection.sql.handler
17+
18+
import com.intellij.codeInspection.ProblemsHolder
19+
import org.domaframework.doma.intellij.common.psi.PsiParentClass
20+
import org.domaframework.doma.intellij.common.psi.PsiStaticElement
21+
import org.domaframework.doma.intellij.common.sql.validator.result.ValidationClassPathResult
22+
import org.domaframework.doma.intellij.common.sql.validator.result.ValidationPropertyResult
23+
import org.domaframework.doma.intellij.common.util.ForDirectiveUtil
24+
import org.domaframework.doma.intellij.extension.expr.accessElements
25+
import org.domaframework.doma.intellij.extension.psi.psiClassType
26+
import org.domaframework.doma.intellij.psi.SqlElStaticFieldAccessExpr
27+
28+
class InspectionStaticFieldAccessVisitorProcessor(
29+
val shortName: String,
30+
) : InspectionVisitorProcessor(shortName) {
31+
/**
32+
* Check for existence of static field
33+
*/
34+
fun check(
35+
staticAccuser: SqlElStaticFieldAccessExpr,
36+
holder: ProblemsHolder,
37+
) {
38+
val blockElements = staticAccuser.accessElements
39+
val psiStaticClass = PsiStaticElement(staticAccuser.elClass.elIdExprList, staticAccuser.containingFile)
40+
val referenceClass = psiStaticClass.getRefClazz()
41+
if (referenceClass == null) {
42+
ValidationClassPathResult(
43+
staticAccuser.elClass,
44+
shortName,
45+
).highlightElement(holder)
46+
return
47+
}
48+
49+
val topParentClass = ForDirectiveUtil.getStaticFieldAccessTopElementClassType(staticAccuser, referenceClass)
50+
if (topParentClass == null) {
51+
blockElements.firstOrNull()?.let {
52+
ValidationPropertyResult(
53+
it,
54+
PsiParentClass(referenceClass.psiClassType),
55+
shortName,
56+
).highlightElement(holder)
57+
}
58+
return
59+
}
60+
val result =
61+
topParentClass.let {
62+
ForDirectiveUtil.getFieldAccessLastPropertyClassType(
63+
blockElements,
64+
staticAccuser.project,
65+
it,
66+
shortName = shortName,
67+
)
68+
}
69+
result?.highlightElement(holder)
70+
}
71+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Copyright Doma Tools Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.domaframework.doma.intellij.inspection.sql.handler
17+
18+
import com.intellij.codeInspection.ProblemsHolder
19+
import com.intellij.psi.PsiElement
20+
import com.intellij.psi.PsiMethod
21+
import com.intellij.psi.util.elementType
22+
import org.domaframework.doma.intellij.common.sql.validator.result.ValidationDaoParamResult
23+
import org.domaframework.doma.intellij.psi.SqlElIdExpr
24+
import org.domaframework.doma.intellij.psi.SqlElNewExpr
25+
import org.domaframework.doma.intellij.psi.SqlTypes
26+
27+
abstract class InspectionVisitorProcessor(
28+
private val shortName: String,
29+
) {
30+
protected fun errorHighlight(
31+
topElement: SqlElIdExpr,
32+
daoMethod: PsiMethod,
33+
holder: ProblemsHolder,
34+
) {
35+
ValidationDaoParamResult(
36+
topElement,
37+
daoMethod.name,
38+
this.shortName,
39+
).highlightElement(holder)
40+
}
41+
42+
protected fun isLiteralOrStatic(targetElement: PsiElement): Boolean =
43+
(
44+
targetElement.firstChild?.elementType == SqlTypes.EL_STRING ||
45+
targetElement.firstChild?.elementType == SqlTypes.EL_CHAR ||
46+
targetElement.firstChild?.elementType == SqlTypes.EL_NUMBER ||
47+
targetElement.firstChild?.elementType == SqlTypes.EL_NULL ||
48+
targetElement.firstChild?.elementType == SqlTypes.BOOLEAN ||
49+
targetElement.firstChild is SqlElNewExpr ||
50+
targetElement.text.startsWith("@")
51+
)
52+
}

0 commit comments

Comments
 (0)