diff --git a/src/main/kotlin/org/domaframework/doma/intellij/common/psi/PsiDaoMethod.kt b/src/main/kotlin/org/domaframework/doma/intellij/common/psi/PsiDaoMethod.kt index 992c5c49..a34a1ab8 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/common/psi/PsiDaoMethod.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/common/psi/PsiDaoMethod.kt @@ -92,6 +92,11 @@ class PsiDaoMethod( private fun getSqlAnnotation(): PsiAnnotation? = DomaAnnotationType.Sql.getPsiAnnotation(psiMethod) + fun isSelectTypeCollect(): Boolean { + val selectAnnotation = DomaAnnotationType.Select.getPsiAnnotation(psiMethod) ?: return false + return daoType.isSelectTypeCollect(selectAnnotation) + } + fun useSqlAnnotation(): Boolean = getSqlAnnotation() != null private fun setSqlFilePath() { diff --git a/src/main/kotlin/org/domaframework/doma/intellij/extension/psi/DomaAnnotationType.kt b/src/main/kotlin/org/domaframework/doma/intellij/extension/psi/DomaAnnotationType.kt index 792ea27d..8df5cf4b 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/extension/psi/DomaAnnotationType.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/extension/psi/DomaAnnotationType.kt @@ -18,6 +18,10 @@ package org.domaframework.doma.intellij.extension.psi import com.intellij.codeInsight.AnnotationUtil import com.intellij.psi.PsiAnnotation import com.intellij.psi.PsiModifierListOwner +import com.intellij.psi.PsiNameValuePair +import com.intellij.psi.PsiReferenceExpression +import com.intellij.psi.util.PsiTreeUtil +import kotlin.jvm.java enum class DomaAnnotationType( val fqdn: String, @@ -59,4 +63,19 @@ enum class DomaAnnotationType( true -> AnnotationUtil.getBooleanAttributeValue(element, "sqlFile") == true false -> false } + + fun isSelectTypeCollect(element: PsiAnnotation): Boolean { + val strategyPair = + PsiTreeUtil + .getChildrenOfTypeAsList(element.parameterList, PsiNameValuePair::class.java) + .firstOrNull { + it.text.startsWith("strategy") + } ?: return false + + return PsiTreeUtil + .getChildOfType( + strategyPair, + PsiReferenceExpression::class.java, + )?.text == "SelectType.COLLECT" + } } diff --git a/src/main/kotlin/org/domaframework/doma/intellij/extension/psi/PsiParameterExtension.kt b/src/main/kotlin/org/domaframework/doma/intellij/extension/psi/PsiParameterExtension.kt index e6daea2d..d83a7e2c 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/extension/psi/PsiParameterExtension.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/extension/psi/PsiParameterExtension.kt @@ -48,3 +48,9 @@ val PsiParameter.isSelectOption: Boolean (this.typeElement?.type as? PsiClassReferenceType) ?.resolve() ?.qualifiedName == "org.seasar.doma.jdbc.SelectOptions" + +val PsiParameter.isCollector: Boolean + get() = + (this.typeElement?.type as? PsiClassReferenceType) + ?.resolve() + ?.qualifiedName == "java.util.stream.Collector" diff --git a/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/inspector/DaoMethodVariableInspector.kt b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/inspector/DaoMethodVariableInspector.kt index c29200b5..2759b8f2 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/inspector/DaoMethodVariableInspector.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/inspector/DaoMethodVariableInspector.kt @@ -32,6 +32,7 @@ import org.domaframework.doma.intellij.common.dao.getDaoClass import org.domaframework.doma.intellij.common.isJavaOrKotlinFileType import org.domaframework.doma.intellij.common.psi.PsiDaoMethod import org.domaframework.doma.intellij.extension.findFile +import org.domaframework.doma.intellij.extension.psi.isCollector import org.domaframework.doma.intellij.extension.psi.isFunctionClazz import org.domaframework.doma.intellij.extension.psi.isSelectOption import org.domaframework.doma.intellij.extension.psi.methodParameters @@ -66,7 +67,7 @@ class DaoMethodVariableInspector : AbstractBaseJavaLocalInspectionTool() { val methodParameters = method.methodParameters - .filter { !it.isFunctionClazz && !it.isSelectOption } + .filter { !it.isFunctionClazz && !it.isSelectOption && !(it.isCollector && psiDaoMethod.isSelectTypeCollect()) } val sqlFileManager = psiDaoMethod.sqlFile?.let { method.project.findFile(it) diff --git a/src/test/kotlin/org/domaframework/doma/intellij/inspection/dao/DomaUseVariableTest.kt b/src/test/kotlin/org/domaframework/doma/intellij/inspection/dao/DomaUseVariableTest.kt index 2fd84d21..5eb8b6b8 100644 --- a/src/test/kotlin/org/domaframework/doma/intellij/inspection/dao/DomaUseVariableTest.kt +++ b/src/test/kotlin/org/domaframework/doma/intellij/inspection/dao/DomaUseVariableTest.kt @@ -32,6 +32,8 @@ class DomaUseVariableTest : DomaSqlTest() { addSqlFile( "$testDaoName/biFunctionDoesNotCauseError.sql", "$testDaoName/selectOptionDoesNotCauseError.sql", + "$testDaoName/collectDoesNotCauseError.sql", + "$testDaoName/collectDoesCauseError.sql", ) myFixture.enableInspections(DaoMethodVariableInspector()) } diff --git a/src/test/testData/src/main/java/doma/example/dao/DaoMethodVariableInspectionTestDao.java b/src/test/testData/src/main/java/doma/example/dao/DaoMethodVariableInspectionTestDao.java index 5e43e509..83c1e6d6 100644 --- a/src/test/testData/src/main/java/doma/example/dao/DaoMethodVariableInspectionTestDao.java +++ b/src/test/testData/src/main/java/doma/example/dao/DaoMethodVariableInspectionTestDao.java @@ -16,6 +16,8 @@ import org.seasar.doma.jdbc.Config; import org.seasar.doma.jdbc.PreparedSql; import org.seasar.doma.jdbc.SelectOptions; +import org.seasar.doma.SelectType; +import java.util.stream.Collector; import java.util.List; import java.util.function.BiFunction; @@ -39,4 +41,11 @@ interface DaoMethodVariableInspectionTestDao { @Select Project selectOptionDoesNotCauseError(Employee employee,String searchName,SelectOptions options); + @Select(strategy = SelectType.COLLECT) + Project collectDoesNotCauseError(Employee employee,Integer id,Collector collector); + + @Select + Project collectDoesCauseError(Employee employee,String searchName,Collector collector); + + } \ No newline at end of file diff --git a/src/test/testData/src/main/resources/META-INF/doma/example/dao/DaoMethodVariableInspectionTestDao/collectDoesCauseError.sql b/src/test/testData/src/main/resources/META-INF/doma/example/dao/DaoMethodVariableInspectionTestDao/collectDoesCauseError.sql new file mode 100644 index 00000000..2fa8e8ac --- /dev/null +++ b/src/test/testData/src/main/resources/META-INF/doma/example/dao/DaoMethodVariableInspectionTestDao/collectDoesCauseError.sql @@ -0,0 +1,8 @@ +-- Using Dao arguments other than SelectOption as bind variables +select + p.project_id + , p.project_name + , p.project_number +from project p +where p.project_id = /* id */0 + and p. project_name = /* searchName */'search' \ No newline at end of file diff --git a/src/test/testData/src/main/resources/META-INF/doma/example/dao/DaoMethodVariableInspectionTestDao/collectDoesNotCauseError.sql b/src/test/testData/src/main/resources/META-INF/doma/example/dao/DaoMethodVariableInspectionTestDao/collectDoesNotCauseError.sql new file mode 100644 index 00000000..2f7a6a93 --- /dev/null +++ b/src/test/testData/src/main/resources/META-INF/doma/example/dao/DaoMethodVariableInspectionTestDao/collectDoesNotCauseError.sql @@ -0,0 +1,7 @@ +-- Using Dao arguments other than SelectOption as bind variables +select + p.project_id + , p.project_name + , p.project_number +from project p +where p.project_id = /* id */0 \ No newline at end of file