Skip to content

Commit 434a07a

Browse files
authored
Merge pull request #117 from domaframework/feature/analys-for-directive-item-classtype
resolution for elements defined in the %for directive
2 parents 735ea9d + f7e596f commit 434a07a

File tree

51 files changed

+2090
-955
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+2090
-955
lines changed
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.common.sql
17+
18+
import com.intellij.openapi.project.Project
19+
import com.intellij.psi.PsiClassType
20+
import com.intellij.psi.PsiType
21+
import com.intellij.psi.search.GlobalSearchScope
22+
23+
class PsiClassTypeUtil {
24+
companion object {
25+
fun getPsiTypeByList(
26+
classType: PsiClassType,
27+
project: Project,
28+
useListParam: Boolean,
29+
): PsiType? {
30+
val isIterableType = isIterableType(classType, project)
31+
if (isIterableType && useListParam) {
32+
return classType.parameters.firstOrNull()
33+
}
34+
return classType
35+
}
36+
37+
fun isIterableType(
38+
type: PsiClassType,
39+
project: Project,
40+
): Boolean {
41+
val iterableType =
42+
PsiType.getTypeByName(
43+
"java.lang.Iterable",
44+
project,
45+
GlobalSearchScope.allScope(project),
46+
)
47+
return iterableType.isAssignableFrom(type)
48+
}
49+
50+
fun getParameterType(
51+
project: Project,
52+
baseType: PsiType?,
53+
preReturnListType: PsiType,
54+
index: Int,
55+
): PsiClassType? {
56+
val returnType = baseType as? PsiClassType ?: return null
57+
val preReturnType = preReturnListType as? PsiClassType ?: return null
58+
59+
if (returnType.name == "E" && isIterableType(preReturnListType, project)) {
60+
var count = 1
61+
var type: PsiType? = preReturnType.parameters.firstOrNull()
62+
while (index > count && type != null && type is PsiClassType) {
63+
type = type.parameters.firstOrNull()
64+
count++
65+
}
66+
return type as? PsiClassType
67+
}
68+
return null
69+
}
70+
}
71+
}

src/main/kotlin/org/domaframework/doma/intellij/common/sql/directive/EmbeddedDirectiveHandler.kt

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import com.intellij.psi.PsiElement
2121
import com.intellij.psi.PsiFile
2222
import com.intellij.psi.PsiMethod
2323
import org.domaframework.doma.intellij.common.dao.findDaoMethod
24+
import org.domaframework.doma.intellij.extension.psi.searchParameter
2425

2526
class EmbeddedDirectiveHandler(
2627
private val originalFile: PsiFile,
@@ -36,11 +37,8 @@ class EmbeddedDirectiveHandler(
3637
result,
3738
) { daoMethod, bind ->
3839
daoMethod
39-
?.parameterList
40-
?.parameters
41-
?.filter {
42-
it.name.startsWith(bind)
43-
}?.map { param -> VariableLookupItem(param) }
40+
?.searchParameter(bind)
41+
?.map { param -> VariableLookupItem(param) }
4442
?.toList()
4543
?: emptyList()
4644
}

src/main/kotlin/org/domaframework/doma/intellij/common/sql/directive/LiteralDirectiveHandler.kt

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import com.intellij.psi.PsiFile
2222
import com.intellij.psi.PsiMethod
2323
import org.domaframework.doma.intellij.common.dao.findDaoMethod
2424
import org.domaframework.doma.intellij.common.psi.PsiTypeChecker
25+
import org.domaframework.doma.intellij.extension.psi.searchParameter
2526

2627
class LiteralDirectiveHandler(
2728
private val originalFile: PsiFile,
@@ -37,11 +38,9 @@ class LiteralDirectiveHandler(
3738
result,
3839
) { daoMethod, bind ->
3940
daoMethod
40-
?.parameterList
41-
?.parameters
41+
?.searchParameter(bind)
4242
?.filter {
43-
it.name.startsWith(bind) &&
44-
PsiTypeChecker.isTargetType(it.type)
43+
PsiTypeChecker.isTargetType(it.type)
4544
}?.map { param -> VariableLookupItem(param) }
4645
?.toList()
4746
?: emptyList()
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
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.common.sql.foritem
17+
18+
import com.intellij.psi.PsiParameter
19+
import org.domaframework.doma.intellij.common.psi.PsiParentClass
20+
import org.domaframework.doma.intellij.common.sql.validator.SqlElFieldAccessorChildElementValidator
21+
import org.domaframework.doma.intellij.psi.SqlElIdExpr
22+
23+
/**
24+
* In the For directive, define the element based on the Dao parameter.
25+
* %for [ForItem] : [ForDeclarationDaoBaseItem]
26+
* %for [ForItem] : [ForDeclarationItem]
27+
* ...
28+
*/
29+
open class ForDeclarationDaoBaseItem(
30+
private val blocks: List<SqlElIdExpr>,
31+
val daoParameter: PsiParameter? = null,
32+
open val index: Int = 0,
33+
) : ForDeclarationItem(blocks.first()) {
34+
/***
35+
* Obtain the type information of the For item defined from the Dao parameters.
36+
*/
37+
open fun getPsiParentClass(): PsiParentClass? {
38+
val daoParamFieldValidator =
39+
SqlElFieldAccessorChildElementValidator(
40+
blocks,
41+
element.containingFile,
42+
topDaoParameter = daoParameter,
43+
)
44+
45+
var lastType: PsiParentClass? = null
46+
daoParamFieldValidator.validateChildren(
47+
complete = { parent ->
48+
lastType = parent
49+
},
50+
)
51+
if (lastType == null) return null
52+
return lastType
53+
}
54+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
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.common.sql.foritem
17+
18+
import com.intellij.psi.PsiElement
19+
import org.domaframework.doma.intellij.extension.expr.accessElements
20+
import org.domaframework.doma.intellij.psi.SqlElFieldAccessExpr
21+
import org.domaframework.doma.intellij.psi.SqlElIdExpr
22+
23+
/**
24+
* definition source in the For directive
25+
* %for [ForItem] : [ForDeclarationItem]
26+
*/
27+
open class ForDeclarationItem(
28+
override val element: PsiElement,
29+
) : ForDirectiveItemBase(element) {
30+
open fun getDeclarationChildren(): List<SqlElIdExpr> =
31+
(element as? SqlElFieldAccessExpr)?.accessElements?.mapNotNull { it as SqlElIdExpr }
32+
?: listOf(element as SqlElIdExpr)
33+
}
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.common.sql.foritem
17+
18+
import org.domaframework.doma.intellij.common.psi.PsiParentClass
19+
import org.domaframework.doma.intellij.common.sql.cleanString
20+
import org.domaframework.doma.intellij.common.sql.validator.SqlElStaticFieldAccessorChildElementValidator
21+
import org.domaframework.doma.intellij.psi.SqlElIdExpr
22+
import org.domaframework.doma.intellij.psi.SqlElStaticFieldAccessExpr
23+
24+
/**
25+
* In the For directive, define the element based on the Dao parameter.
26+
* %for [ForItem] : [ForDeclarationStaticFieldAccessorItem]
27+
* %for [ForItem] : [ForDeclarationItem]
28+
* ...
29+
*/
30+
class ForDeclarationStaticFieldAccessorItem(
31+
private val blocks: List<SqlElIdExpr>,
32+
private val staticFieldAccessExpr: SqlElStaticFieldAccessExpr,
33+
override val index: Int = 0,
34+
private val shortName: String = "",
35+
) : ForDeclarationDaoBaseItem(blocks, null, index) {
36+
/***
37+
* Obtain the type information of the For item defined from the Dao parameters.
38+
*/
39+
override fun getPsiParentClass(): PsiParentClass? {
40+
val staticFieldValidator =
41+
SqlElStaticFieldAccessorChildElementValidator(
42+
blocks,
43+
staticFieldAccessExpr,
44+
shortName = shortName,
45+
)
46+
47+
var lastPsiParentClass: PsiParentClass? = null
48+
staticFieldValidator.validateChildren(
49+
complete = { parent ->
50+
lastPsiParentClass = parent
51+
},
52+
)
53+
if (lastPsiParentClass == null) return null
54+
55+
if (blocks.size == 1) {
56+
val searchElementText = cleanString(blocks.first().text)
57+
val field = lastPsiParentClass.findField(searchElementText)
58+
if (field != null) {
59+
val fieldType = field.type
60+
return PsiParentClass(fieldType)
61+
}
62+
63+
val method = lastPsiParentClass.findMethod(searchElementText)
64+
if (method != null) {
65+
val methodReturnType = method.returnType ?: return null
66+
return PsiParentClass(methodReturnType)
67+
}
68+
}
69+
return lastPsiParentClass
70+
}
71+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
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.common.sql.foritem
17+
18+
import com.intellij.psi.PsiElement
19+
20+
abstract class ForDirectiveItemBase(
21+
open val element: PsiElement,
22+
)
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
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.common.sql.foritem
17+
18+
import com.intellij.psi.PsiElement
19+
import com.intellij.psi.util.PsiTreeUtil
20+
import org.domaframework.doma.intellij.psi.SqlElForDirective
21+
22+
/**
23+
* Elements defined within the For directive
24+
* %for [ForItem] : [ForDeclarationItem]
25+
*/
26+
class ForItem(
27+
override val element: PsiElement,
28+
) : ForDirectiveItemBase(element) {
29+
fun getParentForDirectiveExpr() = PsiTreeUtil.getParentOfType(element, SqlElForDirective::class.java)
30+
}

0 commit comments

Comments
 (0)