diff --git a/README.md b/README.md index 9d7fd9de..1d75e42f 100644 --- a/README.md +++ b/README.md @@ -35,12 +35,15 @@ The plugin also provides quick fixes for DAO methods where the required SQL file ![quickfix.png](images/quickfix.png) - Checks for unused DAO method arguments. ![inspection.png](images/inspection.png) +- Checks that the return type of DAO method matches the expected type based on its annotation. + ![returnTypeInspection.png](images/returnTypeInspection.png) - Checks for undefined bind variable names. - Checks the class name and package name for static property calls. ![inspectionPackageName.png](images/inspectionPackageName.png) - Optional types are recognized as their element type (e.g., a parameter of type `Optional` is treated as type `String`). - For custom functions, checks for methods that are not defined in the configured ExpressionFunctions implementation class. + ## Completion Code completion is available to assist you in coding within directives. diff --git a/images/returnTypeInspection.png b/images/returnTypeInspection.png new file mode 100644 index 00000000..4bdda0c0 Binary files /dev/null and b/images/returnTypeInspection.png differ 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 41b3a894..e674feac 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 @@ -61,7 +61,7 @@ class PsiDaoMethod( psiMethod.containingFile.virtualFile ?: psiMethod.containingFile.originalFile.virtualFile var daoType: DomaAnnotationType = DomaAnnotationType.Unknown - private var sqlFileOption: Boolean = false + var sqlFileOption: Boolean = false init { setDaoAnnotationType() @@ -77,8 +77,7 @@ class PsiDaoMethod( private fun setSqlFileOption() { val useSqlFileOptionAnnotation = daoType.getPsiAnnotation(psiMethod) ?: return - val isSqlFile = daoType.getSqlFileVal(useSqlFileOptionAnnotation) - sqlFileOption = isSqlFile == true + sqlFileOption = daoType.getSqlFileVal(useSqlFileOptionAnnotation) } @OptIn(ExperimentalStdlibApi::class) diff --git a/src/main/kotlin/org/domaframework/doma/intellij/common/util/ForDirectiveUtil.kt b/src/main/kotlin/org/domaframework/doma/intellij/common/util/ForDirectiveUtil.kt index 6ce82130..49e8117b 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/common/util/ForDirectiveUtil.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/common/util/ForDirectiveUtil.kt @@ -34,10 +34,10 @@ import org.domaframework.doma.intellij.common.psi.PsiStaticElement import org.domaframework.doma.intellij.common.sql.PsiClassTypeUtil import org.domaframework.doma.intellij.common.sql.cleanString import org.domaframework.doma.intellij.common.sql.foritem.ForItem -import org.domaframework.doma.intellij.common.sql.validator.result.ValidationCompleteResult -import org.domaframework.doma.intellij.common.sql.validator.result.ValidationNotFoundTopTypeResult -import org.domaframework.doma.intellij.common.sql.validator.result.ValidationPropertyResult -import org.domaframework.doma.intellij.common.sql.validator.result.ValidationResult +import org.domaframework.doma.intellij.common.validation.result.ValidationCompleteResult +import org.domaframework.doma.intellij.common.validation.result.ValidationNotFoundTopTypeResult +import org.domaframework.doma.intellij.common.validation.result.ValidationPropertyResult +import org.domaframework.doma.intellij.common.validation.result.ValidationResult import org.domaframework.doma.intellij.extension.expr.accessElements import org.domaframework.doma.intellij.extension.psi.findParameter import org.domaframework.doma.intellij.extension.psi.findStaticField diff --git a/src/main/kotlin/org/domaframework/doma/intellij/common/sql/validator/result/ValidationClassPathResult.kt b/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationClassPathResult.kt similarity index 95% rename from src/main/kotlin/org/domaframework/doma/intellij/common/sql/validator/result/ValidationClassPathResult.kt rename to src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationClassPathResult.kt index 3f892439..374a58e9 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/common/sql/validator/result/ValidationClassPathResult.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationClassPathResult.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.domaframework.doma.intellij.common.sql.validator.result +package org.domaframework.doma.intellij.common.validation.result import com.intellij.codeInspection.ProblemsHolder import com.intellij.openapi.util.TextRange diff --git a/src/main/kotlin/org/domaframework/doma/intellij/common/sql/validator/result/ValidationCompleteResult.kt b/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationCompleteResult.kt similarity index 94% rename from src/main/kotlin/org/domaframework/doma/intellij/common/sql/validator/result/ValidationCompleteResult.kt rename to src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationCompleteResult.kt index bb5c2547..1abbf7ff 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/common/sql/validator/result/ValidationCompleteResult.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationCompleteResult.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.domaframework.doma.intellij.common.sql.validator.result +package org.domaframework.doma.intellij.common.validation.result import com.intellij.codeInspection.ProblemsHolder import com.intellij.openapi.util.TextRange diff --git a/src/main/kotlin/org/domaframework/doma/intellij/common/sql/validator/result/ValidationDaoParamResult.kt b/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationDaoParamResult.kt similarity index 96% rename from src/main/kotlin/org/domaframework/doma/intellij/common/sql/validator/result/ValidationDaoParamResult.kt rename to src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationDaoParamResult.kt index fb39f83b..ffa6987e 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/common/sql/validator/result/ValidationDaoParamResult.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationDaoParamResult.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.domaframework.doma.intellij.common.sql.validator.result +package org.domaframework.doma.intellij.common.validation.result import com.intellij.codeInspection.ProblemsHolder import com.intellij.openapi.util.TextRange diff --git a/src/main/kotlin/org/domaframework/doma/intellij/common/sql/validator/result/ValidationForDirectiveItemTypeResult.kt b/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationForDirectiveItemTypeResult.kt similarity index 95% rename from src/main/kotlin/org/domaframework/doma/intellij/common/sql/validator/result/ValidationForDirectiveItemTypeResult.kt rename to src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationForDirectiveItemTypeResult.kt index b980a31e..97b47085 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/common/sql/validator/result/ValidationForDirectiveItemTypeResult.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationForDirectiveItemTypeResult.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.domaframework.doma.intellij.common.sql.validator.result +package org.domaframework.doma.intellij.common.validation.result import com.intellij.codeInspection.ProblemsHolder import com.intellij.openapi.util.TextRange diff --git a/src/main/kotlin/org/domaframework/doma/intellij/common/sql/validator/result/ValidationInvalidExpressionFunctionsResult.kt b/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationInvalidExpressionFunctionsResult.kt similarity index 96% rename from src/main/kotlin/org/domaframework/doma/intellij/common/sql/validator/result/ValidationInvalidExpressionFunctionsResult.kt rename to src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationInvalidExpressionFunctionsResult.kt index a7603d18..fb2e78d4 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/common/sql/validator/result/ValidationInvalidExpressionFunctionsResult.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationInvalidExpressionFunctionsResult.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.domaframework.doma.intellij.common.sql.validator.result +package org.domaframework.doma.intellij.common.validation.result import com.intellij.codeInspection.ProblemsHolder import com.intellij.openapi.util.TextRange diff --git a/src/main/kotlin/org/domaframework/doma/intellij/common/sql/validator/result/ValidationInvalidFunctionCallResult.kt b/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationInvalidFunctionCallResult.kt similarity index 96% rename from src/main/kotlin/org/domaframework/doma/intellij/common/sql/validator/result/ValidationInvalidFunctionCallResult.kt rename to src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationInvalidFunctionCallResult.kt index 3b439520..f9321db9 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/common/sql/validator/result/ValidationInvalidFunctionCallResult.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationInvalidFunctionCallResult.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.domaframework.doma.intellij.common.sql.validator.result +package org.domaframework.doma.intellij.common.validation.result import com.intellij.codeInspection.ProblemsHolder import com.intellij.openapi.util.TextRange diff --git a/src/main/kotlin/org/domaframework/doma/intellij/common/sql/validator/result/ValidationNotFoundStaticPropertyResult.kt b/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationNotFoundStaticPropertyResult.kt similarity index 96% rename from src/main/kotlin/org/domaframework/doma/intellij/common/sql/validator/result/ValidationNotFoundStaticPropertyResult.kt rename to src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationNotFoundStaticPropertyResult.kt index 50735156..890cffd6 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/common/sql/validator/result/ValidationNotFoundStaticPropertyResult.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationNotFoundStaticPropertyResult.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.domaframework.doma.intellij.common.sql.validator.result +package org.domaframework.doma.intellij.common.validation.result import com.intellij.codeInspection.ProblemsHolder import com.intellij.openapi.util.TextRange diff --git a/src/main/kotlin/org/domaframework/doma/intellij/common/sql/validator/result/ValidationNotFoundTopTypeResult.kt b/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationNotFoundTopTypeResult.kt similarity index 95% rename from src/main/kotlin/org/domaframework/doma/intellij/common/sql/validator/result/ValidationNotFoundTopTypeResult.kt rename to src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationNotFoundTopTypeResult.kt index 02bf657a..da89a025 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/common/sql/validator/result/ValidationNotFoundTopTypeResult.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationNotFoundTopTypeResult.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.domaframework.doma.intellij.common.sql.validator.result +package org.domaframework.doma.intellij.common.validation.result import com.intellij.codeInspection.ProblemsHolder import com.intellij.openapi.util.TextRange diff --git a/src/main/kotlin/org/domaframework/doma/intellij/common/sql/validator/result/ValidationPropertyResult.kt b/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationPropertyResult.kt similarity index 96% rename from src/main/kotlin/org/domaframework/doma/intellij/common/sql/validator/result/ValidationPropertyResult.kt rename to src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationPropertyResult.kt index 4c3fe267..aee4be6c 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/common/sql/validator/result/ValidationPropertyResult.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationPropertyResult.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.domaframework.doma.intellij.common.sql.validator.result +package org.domaframework.doma.intellij.common.validation.result import com.intellij.codeInspection.ProblemsHolder import com.intellij.openapi.util.TextRange diff --git a/src/main/kotlin/org/domaframework/doma/intellij/common/sql/validator/result/ValidationResult.kt b/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationResult.kt similarity index 97% rename from src/main/kotlin/org/domaframework/doma/intellij/common/sql/validator/result/ValidationResult.kt rename to src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationResult.kt index 0976410e..2936dc0f 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/common/sql/validator/result/ValidationResult.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationResult.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.domaframework.doma.intellij.common.sql.validator.result +package org.domaframework.doma.intellij.common.validation.result import com.intellij.codeHighlighting.HighlightDisplayLevel import com.intellij.codeInspection.ProblemHighlightType diff --git a/src/main/kotlin/org/domaframework/doma/intellij/common/sql/validator/result/ValidationUsedDaoMethodArgsResult.kt b/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationReturnTypeForMultiInsertReturningResult.kt similarity index 58% rename from src/main/kotlin/org/domaframework/doma/intellij/common/sql/validator/result/ValidationUsedDaoMethodArgsResult.kt rename to src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationReturnTypeForMultiInsertReturningResult.kt index 6869fa5e..41a395d2 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/common/sql/validator/result/ValidationUsedDaoMethodArgsResult.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationReturnTypeForMultiInsertReturningResult.kt @@ -13,19 +13,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.domaframework.doma.intellij.common.sql.validator.result +package org.domaframework.doma.intellij.common.validation.result import com.intellij.codeInspection.ProblemsHolder import com.intellij.openapi.util.TextRange import com.intellij.psi.PsiElement -import com.intellij.psi.PsiParameter -import com.intellij.psi.impl.source.PsiParameterImpl import org.domaframework.doma.intellij.bundle.MessageBundle import org.domaframework.doma.intellij.common.psi.PsiParentClass -import org.domaframework.doma.intellij.inspection.dao.visitor.DaoMethodVariableInspectionVisitor.DaoMethodVariableVisitorResult -class ValidationUsedDaoMethodArgsResult( - private val daoMethodVariableResult: DaoMethodVariableVisitorResult, +class ValidationReturnTypeForMultiInsertReturningResult( + private val paramClassName: String, override val identify: PsiElement?, override val shortName: String = "", ) : ValidationResult(identify, null, shortName) { @@ -35,21 +32,15 @@ class ValidationUsedDaoMethodArgsResult( holder: ProblemsHolder, parent: PsiParentClass?, ) { - val param = identify as? PsiParameter ?: return val project = identify.project - val message = - if (daoMethodVariableResult.deplicateForItemElements.contains(identify)) { - MessageBundle.message("inspection.invalid.dao.duplicate") - } else { - MessageBundle.message( - "inspection.invalid.dao.paramUse", - param.name, - ) - } holder.registerProblem( - (param.originalElement as PsiParameterImpl).nameIdentifier, - message, + identify, + MessageBundle.message( + "inspection.invalid.dao.multiInsert.returnType.returning", + paramClassName, + ), problemHighlightType(project, shortName), + highlightRange, ) } } diff --git a/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationReturnTypeForReturningResult.kt b/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationReturnTypeForReturningResult.kt new file mode 100644 index 00000000..83500698 --- /dev/null +++ b/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationReturnTypeForReturningResult.kt @@ -0,0 +1,46 @@ +/* + * Copyright Doma Tools Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.domaframework.doma.intellij.common.validation.result + +import com.intellij.codeInspection.ProblemsHolder +import com.intellij.openapi.util.TextRange +import com.intellij.psi.PsiElement +import org.domaframework.doma.intellij.bundle.MessageBundle +import org.domaframework.doma.intellij.common.psi.PsiParentClass + +class ValidationReturnTypeForReturningResult( + private val paramClassName: String, + override val identify: PsiElement?, + override val shortName: String = "", +) : ValidationResult(identify, null, shortName) { + override fun setHighlight( + highlightRange: TextRange, + identify: PsiElement, + holder: ProblemsHolder, + parent: PsiParentClass?, + ) { + val project = identify.project + holder.registerProblem( + identify, + MessageBundle.message( + "inspection.invalid.dao.update.returnType.returning", + paramClassName, + ), + problemHighlightType(project, shortName), + highlightRange, + ) + } +} diff --git a/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationReturnTypeImmutableResult.kt b/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationReturnTypeImmutableResult.kt new file mode 100644 index 00000000..8b2cc366 --- /dev/null +++ b/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationReturnTypeImmutableResult.kt @@ -0,0 +1,45 @@ +/* + * Copyright Doma Tools Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.domaframework.doma.intellij.common.validation.result + +import com.intellij.codeInspection.ProblemsHolder +import com.intellij.openapi.util.TextRange +import com.intellij.psi.PsiElement +import org.domaframework.doma.intellij.bundle.MessageBundle +import org.domaframework.doma.intellij.common.psi.PsiParentClass + +class ValidationReturnTypeImmutableResult( + override val identify: PsiElement?, + override val shortName: String = "", + private val annotationName: String, + private val resultTypeName: String, + private val returnTypeName: String, +) : ValidationResult(identify, null, shortName) { + override fun setHighlight( + highlightRange: TextRange, + identify: PsiElement, + holder: ProblemsHolder, + parent: PsiParentClass?, + ) { + val project = identify.project + holder.registerProblem( + identify, + MessageBundle.message("inspection.invalid.dao.returnType.immutable", annotationName, resultTypeName, returnTypeName), + problemHighlightType(project, shortName), + highlightRange, + ) + } +} diff --git a/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationReturnTypeResult.kt b/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationReturnTypeResult.kt new file mode 100644 index 00000000..51f1b09f --- /dev/null +++ b/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationReturnTypeResult.kt @@ -0,0 +1,43 @@ +/* + * Copyright Doma Tools Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.domaframework.doma.intellij.common.validation.result + +import com.intellij.codeInspection.ProblemsHolder +import com.intellij.openapi.util.TextRange +import com.intellij.psi.PsiElement +import org.domaframework.doma.intellij.bundle.MessageBundle +import org.domaframework.doma.intellij.common.psi.PsiParentClass + +class ValidationReturnTypeResult( + override val identify: PsiElement?, + override val shortName: String = "", + private val returnTypeName: String, +) : ValidationResult(identify, null, shortName) { + override fun setHighlight( + highlightRange: TextRange, + identify: PsiElement, + holder: ProblemsHolder, + parent: PsiParentClass?, + ) { + val project = identify.project + holder.registerProblem( + identify, + MessageBundle.message("inspection.invalid.dao.returnType.psiTypes", returnTypeName), + problemHighlightType(project, shortName), + highlightRange, + ) + } +} diff --git a/src/main/kotlin/org/domaframework/doma/intellij/common/sql/validator/result/ValidationSqlFileExistResult.kt b/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationSqlFileExistResult.kt similarity index 96% rename from src/main/kotlin/org/domaframework/doma/intellij/common/sql/validator/result/ValidationSqlFileExistResult.kt rename to src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationSqlFileExistResult.kt index 809caeef..a9e4352d 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/common/sql/validator/result/ValidationSqlFileExistResult.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationSqlFileExistResult.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.domaframework.doma.intellij.common.sql.validator.result +package org.domaframework.doma.intellij.common.validation.result import com.intellij.codeInspection.ProblemsHolder import com.intellij.openapi.util.TextRange diff --git a/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationSqlProcessorReturnResult.kt b/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationSqlProcessorReturnResult.kt new file mode 100644 index 00000000..74ab106d --- /dev/null +++ b/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationSqlProcessorReturnResult.kt @@ -0,0 +1,48 @@ +/* + * Copyright Doma Tools Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.domaframework.doma.intellij.common.validation.result + +import com.intellij.codeInspection.ProblemsHolder +import com.intellij.openapi.util.TextRange +import com.intellij.psi.PsiElement +import org.domaframework.doma.intellij.bundle.MessageBundle +import org.domaframework.doma.intellij.common.psi.PsiParentClass + +class ValidationSqlProcessorReturnResult( + private val returnTypeName: String, + private val paramClassName: String, + override val identify: PsiElement?, + override val shortName: String = "", +) : ValidationResult(identify, null, shortName) { + override fun setHighlight( + highlightRange: TextRange, + identify: PsiElement, + holder: ProblemsHolder, + parent: PsiParentClass?, + ) { + val project = identify.project + holder.registerProblem( + identify, + MessageBundle.message( + "inspection.invalid.dao.sqlProcessor.returnType.returning", + returnTypeName, + paramClassName, + ), + problemHighlightType(project, shortName), + highlightRange, + ) + } +} diff --git a/src/main/kotlin/org/domaframework/doma/intellij/common/sql/validator/result/ValidationTestDataResult.kt b/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationTestDataResult.kt similarity index 95% rename from src/main/kotlin/org/domaframework/doma/intellij/common/sql/validator/result/ValidationTestDataResult.kt rename to src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationTestDataResult.kt index 0cc43a4c..ce4ef937 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/common/sql/validator/result/ValidationTestDataResult.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationTestDataResult.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.domaframework.doma.intellij.common.sql.validator.result +package org.domaframework.doma.intellij.common.validation.result import com.intellij.codeInspection.ProblemsHolder import com.intellij.openapi.util.TextRange diff --git a/src/main/kotlin/org/domaframework/doma/intellij/contributor/sql/provider/SqlParameterCompletionProvider.kt b/src/main/kotlin/org/domaframework/doma/intellij/contributor/sql/provider/SqlParameterCompletionProvider.kt index 31f88e7a..c8b9a1e4 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/contributor/sql/provider/SqlParameterCompletionProvider.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/contributor/sql/provider/SqlParameterCompletionProvider.kt @@ -39,11 +39,11 @@ import org.domaframework.doma.intellij.common.psi.PsiPatternUtil import org.domaframework.doma.intellij.common.sql.PsiClassTypeUtil import org.domaframework.doma.intellij.common.sql.cleanString import org.domaframework.doma.intellij.common.sql.directive.DirectiveCompletion -import org.domaframework.doma.intellij.common.sql.validator.result.ValidationCompleteResult import org.domaframework.doma.intellij.common.util.ForDirectiveUtil import org.domaframework.doma.intellij.common.util.PluginLoggerUtil import org.domaframework.doma.intellij.common.util.SqlCompletionUtil.createMethodLookupElement import org.domaframework.doma.intellij.common.util.StringUtil +import org.domaframework.doma.intellij.common.validation.result.ValidationCompleteResult import org.domaframework.doma.intellij.contributor.sql.processor.SqlCompletionDirectiveBlockProcessor import org.domaframework.doma.intellij.contributor.sql.processor.SqlCompletionOtherBlockProcessor import org.domaframework.doma.intellij.contributor.sql.processor.SqlCompletionParameterArgsBlockProcessor 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 8df5cf4b..9c6a0d02 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 @@ -21,7 +21,6 @@ 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, @@ -32,6 +31,8 @@ enum class DomaAnnotationType( BatchInsert("org.seasar.doma.BatchInsert"), BatchUpdate("org.seasar.doma.BatchUpdate"), BatchDelete("org.seasar.doma.BatchDelete"), + MultiInsert("org.seasar.doma.MultiInsert"), + Procedure("org.seasar.doma.Procedure"), Select("org.seasar.doma.Select"), Insert("org.seasar.doma.Insert"), Update("org.seasar.doma.Update"), @@ -44,7 +45,7 @@ enum class DomaAnnotationType( fun isRequireSqlTemplate(): Boolean = this == Select || this == Script || this == SqlProcessor - private fun useSqlFileOption(): Boolean = + private fun mayUseSqlFileOption(): Boolean = this == Insert || this == Update || this == Delete || @@ -59,9 +60,13 @@ enum class DomaAnnotationType( ) fun getSqlFileVal(element: PsiAnnotation): Boolean = - when (this.useSqlFileOption()) { - true -> AnnotationUtil.getBooleanAttributeValue(element, "sqlFile") == true - false -> false + if (this.mayUseSqlFileOption()) { + AnnotationUtil.getBooleanAttributeValue( + element, + "sqlFile", + ) == true + } else { + false } fun isSelectTypeCollect(element: PsiAnnotation): Boolean { diff --git a/src/main/kotlin/org/domaframework/doma/intellij/extension/psi/PsiClassExtension.kt b/src/main/kotlin/org/domaframework/doma/intellij/extension/psi/PsiClassExtension.kt index 9906402d..a2019983 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/extension/psi/PsiClassExtension.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/extension/psi/PsiClassExtension.kt @@ -15,6 +15,7 @@ */ package org.domaframework.doma.intellij.extension.psi +import com.intellij.psi.PsiAnnotation import com.intellij.psi.PsiClass import com.intellij.psi.PsiClassType import com.intellij.psi.PsiField @@ -26,14 +27,6 @@ import org.domaframework.doma.intellij.common.psi.PropertyModifyUtil val PsiClass.psiClassType: PsiClassType get() = PsiTypesUtil.getClassType(this) -fun PsiClass.searchStaticField(searchName: String): Array = - this.allFields - .filter { - it.name.startsWith(searchName) && - it.hasModifierProperty(PsiModifier.STATIC) && - PropertyModifyUtil.filterPrivateField(it, this.psiClassType) - }.toTypedArray() - fun PsiClass.findStaticField(searchName: String): PsiField? = this.allFields.firstOrNull { it.name == searchName && @@ -41,17 +34,15 @@ fun PsiClass.findStaticField(searchName: String): PsiField? = PropertyModifyUtil.filterPrivateField(it, this.psiClassType) } -fun PsiClass.searchStaticMethod(searchName: String): Array = - this.allMethods - .filter { - it.name.startsWith(searchName) && - it.hasModifierProperty(PsiModifier.STATIC) && - it.hasModifierProperty(PsiModifier.PUBLIC) - }.toTypedArray() - fun PsiClass.findStaticMethod(searchName: String): PsiMethod? = this.allMethods.firstOrNull { it.name == searchName && it.hasModifierProperty(PsiModifier.STATIC) && it.hasModifierProperty(PsiModifier.PUBLIC) } + +fun PsiClass.getEntityAnnotation(): PsiAnnotation? = + this.annotations + .firstOrNull { it.qualifiedName == "org.seasar.doma.Entity" } + +fun PsiClass.isEntity(): Boolean = this.getEntityAnnotation() != null diff --git a/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/inspector/DaoMethodReturnTypeVariableInspection.kt b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/inspector/DaoMethodReturnTypeVariableInspection.kt new file mode 100644 index 00000000..f0693b21 --- /dev/null +++ b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/inspector/DaoMethodReturnTypeVariableInspection.kt @@ -0,0 +1,39 @@ +/* + * Copyright Doma Tools Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.domaframework.doma.intellij.inspection.dao.inspector + +import com.intellij.codeHighlighting.HighlightDisplayLevel +import com.intellij.codeInspection.AbstractBaseJavaLocalInspectionTool +import com.intellij.codeInspection.ProblemsHolder +import com.intellij.psi.PsiElementVisitor +import org.domaframework.doma.intellij.inspection.dao.visitor.DaoMethodReturnTypeVariableInspectionVisitor + +class DaoMethodReturnTypeVariableInspection : AbstractBaseJavaLocalInspectionTool() { + override fun getDisplayName(): String = "Check return type variable of DAO method" + + override fun getShortName(): String = "org.domaframework.doma.intellij.returnType" + + override fun getGroupDisplayName(): String = "DomaTools" + + override fun isEnabledByDefault(): Boolean = true + + override fun getDefaultLevel(): HighlightDisplayLevel = HighlightDisplayLevel.ERROR + + override fun buildVisitor( + holder: ProblemsHolder, + isOnTheFly: Boolean, + ): PsiElementVisitor = DaoMethodReturnTypeVariableInspectionVisitor(holder, this.shortName) +} diff --git a/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/inspector/SqlFileExistInspection.kt b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/inspector/SqlFileExistInspection.kt index 00bebed3..be791b0c 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/inspector/SqlFileExistInspection.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/inspector/SqlFileExistInspection.kt @@ -25,7 +25,7 @@ import org.domaframework.doma.intellij.inspection.dao.visitor.SqlFileExistInspec * Check for existence of SQL file */ class SqlFileExistInspection : AbstractBaseJavaLocalInspectionTool() { - override fun getDisplayName(): String = "Ensure the existence of SQL files for DAO methods." + override fun getDisplayName(): String = "Check existence of SQL file" override fun getShortName(): String = "org.domaframework.doma.intellij.existsqlchecker" diff --git a/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/inspector/DaoMethodVariableInspection.kt b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/inspector/UsedDaoMethodArgsVariableInspection.kt similarity index 82% rename from src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/inspector/DaoMethodVariableInspection.kt rename to src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/inspector/UsedDaoMethodArgsVariableInspection.kt index e7a9e918..262808b8 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/inspector/DaoMethodVariableInspection.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/inspector/UsedDaoMethodArgsVariableInspection.kt @@ -19,13 +19,13 @@ import com.intellij.codeHighlighting.HighlightDisplayLevel import com.intellij.codeInspection.AbstractBaseJavaLocalInspectionTool import com.intellij.codeInspection.ProblemsHolder import com.intellij.psi.PsiElementVisitor -import org.domaframework.doma.intellij.inspection.dao.visitor.DaoMethodVariableInspectionVisitor +import org.domaframework.doma.intellij.inspection.dao.visitor.UsedDaoMethodArgsVariableInspectionVisitor /** * Check if DAO method arguments are used in the corresponding SQL file */ -class DaoMethodVariableInspection : AbstractBaseJavaLocalInspectionTool() { - override fun getDisplayName(): String = "Check usage of DAO method arguments in corresponding SQL file." +class UsedDaoMethodArgsVariableInspection : AbstractBaseJavaLocalInspectionTool() { + override fun getDisplayName(): String = "Check usage of DAO method arguments" override fun getShortName(): String = "org.domaframework.doma.intellij.variablechecker" @@ -38,5 +38,5 @@ class DaoMethodVariableInspection : AbstractBaseJavaLocalInspectionTool() { override fun buildVisitor( holder: ProblemsHolder, isOnTheFly: Boolean, - ): PsiElementVisitor = DaoMethodVariableInspectionVisitor(holder, this.shortName) + ): PsiElementVisitor = UsedDaoMethodArgsVariableInspectionVisitor(holder) } diff --git a/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/BatchAnnotationReturnTypeCheckProcessor.kt b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/BatchAnnotationReturnTypeCheckProcessor.kt new file mode 100644 index 00000000..f97f1677 --- /dev/null +++ b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/BatchAnnotationReturnTypeCheckProcessor.kt @@ -0,0 +1,79 @@ +/* + * Copyright Doma Tools Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.domaframework.doma.intellij.inspection.dao.processor + +import com.intellij.psi.PsiType +import com.intellij.psi.PsiTypes +import com.intellij.psi.impl.source.PsiClassReferenceType +import org.domaframework.doma.intellij.common.psi.PsiDaoMethod +import org.domaframework.doma.intellij.common.sql.PsiClassTypeUtil +import org.domaframework.doma.intellij.common.validation.result.ValidationResult + +/** + * Processor for checking the return type of batch annotations. + * + * @property psiDaoMethod The target DAO method info to be checked. + * @property shortName The short name of inspection to check. + */ +class BatchAnnotationReturnTypeCheckProcessor( + private val psiDaoMethod: PsiDaoMethod, + shortName: String, +) : ReturnTypeCheckerProcessor(psiDaoMethod, shortName) { + /** + * Checks the return type of the DAO method. + * + * @return [ValidationResult] if the return type is invalid, otherwise null. + */ + override fun checkReturnType(): ValidationResult? { + val methodOtherReturnType = PsiTypes.intType().createArrayType() + if (psiDaoMethod.useSqlAnnotation() || psiDaoMethod.sqlFileOption) { + return generatePsiTypeReturnTypeResult(methodOtherReturnType) + } + + // Check if it has an immutable entity parameter + val parameters = method.parameterList.parameters + val immutableEntityParam = parameters.firstOrNull() ?: return null + + val convertOptional = PsiClassTypeUtil.convertOptionalType(immutableEntityParam.type, project) + val parameterType = convertOptional as PsiClassReferenceType + val nestPsiType = parameterType.reference.typeParameters.firstOrNull() ?: return null + val nestClass: PsiType = PsiClassTypeUtil.convertOptionalType(nestPsiType, project) + + if (isImmutableEntity(nestClass.canonicalText)) { + return checkReturnTypeImmutableEntity(nestClass) + } + + // If the return type is not an int[], return a validation result + return generatePsiTypeReturnTypeResult(methodOtherReturnType) + } + + /** + * Checks the return type when an immutable entity parameter is present. + * + * @param nestClass The immutable entity parameter type. + * @return [ValidationResult] if the return type is invalid, otherwise null. + */ + private fun checkReturnTypeImmutableEntity(nestClass: PsiType): ValidationResult? { + val methodResultClassName = "org.seasar.doma.jdbc.BatchResult" + val resultTypeName = "BatchResult" + return generateResultReturnTypeImmutable( + psiDaoMethod.daoType, + nestClass, + methodResultClassName, + resultTypeName, + ) + } +} diff --git a/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/MultiInsertAnnotationReturnTypeCheckProcessor.kt b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/MultiInsertAnnotationReturnTypeCheckProcessor.kt new file mode 100644 index 00000000..7b9a2a33 --- /dev/null +++ b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/MultiInsertAnnotationReturnTypeCheckProcessor.kt @@ -0,0 +1,109 @@ +/* + * Copyright Doma Tools Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.domaframework.doma.intellij.inspection.dao.processor + +import com.intellij.psi.PsiType +import com.intellij.psi.PsiTypes +import com.intellij.psi.impl.source.PsiClassReferenceType +import org.domaframework.doma.intellij.common.psi.PsiDaoMethod +import org.domaframework.doma.intellij.common.sql.PsiClassTypeUtil +import org.domaframework.doma.intellij.common.validation.result.ValidationResult +import org.domaframework.doma.intellij.common.validation.result.ValidationReturnTypeForMultiInsertReturningResult +import org.domaframework.doma.intellij.extension.psi.DomaAnnotationType + +/** + * Processor for checking the return type of MultiInsert annotation. + * + * @property psiDaoMethod The target DAO method info to be checked. + * @property shortName The short name of the inspection to check. + */ +class MultiInsertAnnotationReturnTypeCheckProcessor( + private val psiDaoMethod: PsiDaoMethod, + private val shortName: String, +) : ReturnTypeCheckerProcessor(psiDaoMethod, shortName) { + /** + * Checks the return type of the DAO method. + * + * @return ValidationResult if the return type is invalid, otherwise null. + */ + override fun checkReturnType(): ValidationResult? { + if (psiDaoMethod.isUseSqlFileMethod()) return null + + val parameters = method.parameterList.parameters + val immutableEntityParam = parameters.firstOrNull() ?: return null + + val convertOptional = + PsiClassTypeUtil.convertOptionalType(immutableEntityParam.type, project) + val parameterType = convertOptional as? PsiClassReferenceType ?: return null + val nestPsiType = parameterType.reference.typeParameters.firstOrNull() ?: return null + var nestClass: PsiType? = PsiClassTypeUtil.convertOptionalType(nestPsiType, project) + + // Check if the method is annotated with @Returning + if (hasReturingOption()) { + return checkReturnTypeWithReturning(nestClass) + } + + // Check if it has an immutable entity parameter + if (nestClass != null && isImmutableEntity(nestClass.canonicalText)) { + return checkReturnTypeImmutableEntity(nestClass) + } + + // If the return type is not an int, return a validation result + val methodOtherReturnType = PsiTypes.intType() + return generatePsiTypeReturnTypeResult(methodOtherReturnType) + } + + /** + * Checks the return type when the @Returning annotation is present. + * + * @param paramPsiType The parameter type to check. + * @return ValidationResult if the return type is invalid, otherwise null. + */ + private fun checkReturnTypeWithReturning(paramPsiType: PsiType?): ValidationResult? { + if (paramPsiType == null) return null + + val returnTypeName = returnType?.canonicalText ?: "" + val methodResultClassName = "java.util.List" + val actualResultTypeText = "$methodResultClassName<${paramPsiType.canonicalText}>" + + return if (actualResultTypeText != returnTypeName) { + ValidationReturnTypeForMultiInsertReturningResult( + paramPsiType.presentableText, + method.nameIdentifier, + shortName, + ) + } else { + null + } + } + + /** + * Checks the return type when an immutable entity parameter is present. + * + * @param immutableEntityParam The immutable entity parameter type. + * @return ValidationResult if the return type is invalid, otherwise null. + */ + private fun checkReturnTypeImmutableEntity(immutableEntityParam: PsiType): ValidationResult? { + val methodResultClassName = "org.seasar.doma.jdbc.MultiResult" + val resultTypeName = "MultiResult" + return generateResultReturnTypeImmutable( + DomaAnnotationType.MultiInsert, + immutableEntityParam, + methodResultClassName, + resultTypeName, + ) + } +} diff --git a/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/ProcedureAnnotationReturnTypeCheckProcessor.kt b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/ProcedureAnnotationReturnTypeCheckProcessor.kt new file mode 100644 index 00000000..09b2360d --- /dev/null +++ b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/ProcedureAnnotationReturnTypeCheckProcessor.kt @@ -0,0 +1,34 @@ +/* + * Copyright Doma Tools Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.domaframework.doma.intellij.inspection.dao.processor + +import com.intellij.psi.PsiTypes +import org.domaframework.doma.intellij.common.psi.PsiDaoMethod +import org.domaframework.doma.intellij.common.validation.result.ValidationResult + +class ProcedureAnnotationReturnTypeCheckProcessor( + psiDaoMethod: PsiDaoMethod, + shortName: String, +) : ReturnTypeCheckerProcessor(psiDaoMethod, shortName) { + /** + * Checks the return type of method annotated with `@Procedure`. + * The expected return type is `void`. + */ + override fun checkReturnType(): ValidationResult? { + val methodOtherReturnType = PsiTypes.voidType() + return generatePsiTypeReturnTypeResult(methodOtherReturnType) + } +} diff --git a/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/ReturnTypeCheckerProcessor.kt b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/ReturnTypeCheckerProcessor.kt new file mode 100644 index 00000000..c139e5b8 --- /dev/null +++ b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/ReturnTypeCheckerProcessor.kt @@ -0,0 +1,101 @@ +/* + * Copyright Doma Tools Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.domaframework.doma.intellij.inspection.dao.processor + +import com.intellij.codeInsight.AnnotationUtil +import com.intellij.psi.PsiAnnotation +import com.intellij.psi.PsiType +import org.domaframework.doma.intellij.common.psi.PsiDaoMethod +import org.domaframework.doma.intellij.common.validation.result.ValidationResult +import org.domaframework.doma.intellij.common.validation.result.ValidationReturnTypeImmutableResult +import org.domaframework.doma.intellij.common.validation.result.ValidationReturnTypeResult +import org.domaframework.doma.intellij.extension.getJavaClazz +import org.domaframework.doma.intellij.extension.psi.DomaAnnotationType +import org.domaframework.doma.intellij.extension.psi.getEntityAnnotation + +abstract class ReturnTypeCheckerProcessor( + private val psiDaoMethod: PsiDaoMethod, + private val shortName: String, +) { + protected val returningFqn = "org.seasar.doma.Returning" + protected val method = psiDaoMethod.psiMethod + protected val project = method.project + protected val returnType = psiDaoMethod.psiMethod.returnType + + abstract fun checkReturnType(): ValidationResult? + + protected fun getAnnotation(fqName: String): PsiAnnotation = method.annotations.first { it.qualifiedName == fqName } + + protected fun isImmutableEntity(canonicalText: String): Boolean { + val returnTypeClass = method.project.getJavaClazz(canonicalText) + val entity = returnTypeClass?.getEntityAnnotation() ?: return false + return entity.let { entity -> + AnnotationUtil.getBooleanAttributeValue(entity, "immutable") == true + } == true + } + + protected fun hasReturingOption(): Boolean { + val methodAnnotation: PsiAnnotation = getAnnotation(psiDaoMethod.daoType.fqdn) + val returningOption: PsiAnnotation? = getDaoAnnotationOption(methodAnnotation, "returning") + return returningOption?.nameReferenceElement?.qualifiedName == returningFqn + } + + private fun getDaoAnnotationOption( + psiAnnotation: PsiAnnotation, + findOptionName: String, + ): PsiAnnotation? { + val returningOption = + psiAnnotation.parameterList.attributes + .firstOrNull { param -> + param.name == findOptionName + }?.value as? PsiAnnotation + + return returningOption + } + + protected fun generatePsiTypeReturnTypeResult(methodOtherReturnType: PsiType): ValidationResult? { + return if (returnType != methodOtherReturnType) { + return ValidationReturnTypeResult( + method.nameIdentifier, + shortName, + methodOtherReturnType.presentableText, + ) + } else { + null + } + } + + protected fun generateResultReturnTypeImmutable( + annotation: DomaAnnotationType, + immutableParamClassType: PsiType, + methodResultClassName: String, + typeName: String, + ): ValidationResult? { + val actualResultTypeName = + "$methodResultClassName<${immutableParamClassType.canonicalText}>" + return if (returnType?.canonicalText != actualResultTypeName) { + ValidationReturnTypeImmutableResult( + method.nameIdentifier, + shortName, + annotation.name, + typeName, + immutableParamClassType.presentableText, + ) + } else { + null + } + } +} diff --git a/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/SqlProcessorAnnotationReturnTypeCheckProcessor.kt b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/SqlProcessorAnnotationReturnTypeCheckProcessor.kt new file mode 100644 index 00000000..b7fb5e61 --- /dev/null +++ b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/SqlProcessorAnnotationReturnTypeCheckProcessor.kt @@ -0,0 +1,87 @@ +/* + * Copyright Doma Tools Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.domaframework.doma.intellij.inspection.dao.processor + +import com.intellij.psi.PsiType +import com.intellij.psi.PsiTypes +import com.intellij.psi.impl.source.PsiClassReferenceType +import org.domaframework.doma.intellij.common.psi.PsiDaoMethod +import org.domaframework.doma.intellij.common.sql.PsiClassTypeUtil +import org.domaframework.doma.intellij.common.validation.result.ValidationResult +import org.domaframework.doma.intellij.common.validation.result.ValidationSqlProcessorReturnResult + +/** + * Processor for checking the return type of SqlProcessor annotation. + * + * @param psiDaoMethod The target DAO method info to be checked. + * @param shortName The short name of the inspection to check. + */ +class SqlProcessorAnnotationReturnTypeCheckProcessor( + psiDaoMethod: PsiDaoMethod, + private val shortName: String, +) : ReturnTypeCheckerProcessor(psiDaoMethod, shortName) { + /** + * Checks the return type of the DAO method. + * + * @return [ValidationResult] if the return type is invalid, otherwise null. + */ + override fun checkReturnType(): ValidationResult? { + val parameters = method.parameterList.parameters + val biFunctionParam = parameters.firstOrNull() ?: return null + val convertOptional = PsiClassTypeUtil.convertOptionalType(biFunctionParam.type, project) + val parameterType = convertOptional as PsiClassReferenceType + return checkReturnTypeBiFunctionParam(parameterType) + } + + /** + * Checks the return type when a BiFunction parameter is present. + * + * @param parameterType The BiFunction parameter type to check. + * @return [ValidationResult] if the return type is invalid, otherwise null. + */ + private fun checkReturnTypeBiFunctionParam(parameterType: PsiClassReferenceType): ValidationResult? { + if (!parameterType.canonicalText.startsWith("java.util.function.BiFunction")) return null + + val parameterTypeParams = parameterType.reference.typeParameters + if (parameterTypeParams.size < 3) return null + + val nestPsiType = parameterType.reference.typeParameters[2] + if (nestPsiType == null) return null + + val nestClass: PsiType = PsiClassTypeUtil.convertOptionalType(nestPsiType, project) + + if (nestClass.canonicalText != "java.lang.Void") { + val methodReturnType = method.returnType + val returnTypeCheckResult = + (nestClass.canonicalText == "?" && methodReturnType?.canonicalText == "R") || + methodReturnType?.canonicalText == nestClass.canonicalText + + return if (!returnTypeCheckResult) { + ValidationSqlProcessorReturnResult( + returnType?.canonicalText ?: "void", + nestClass.canonicalText, + method.nameIdentifier, + shortName, + ) + } else { + null + } + } + // If the return type is not void, return a validation result + val methodOtherReturnType = PsiTypes.voidType() + return generatePsiTypeReturnTypeResult(methodOtherReturnType) + } +} diff --git a/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/UpdateAnnotationReturnTypeCheckProcessor.kt b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/UpdateAnnotationReturnTypeCheckProcessor.kt new file mode 100644 index 00000000..a8270a75 --- /dev/null +++ b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/UpdateAnnotationReturnTypeCheckProcessor.kt @@ -0,0 +1,112 @@ +/* + * Copyright Doma Tools Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.domaframework.doma.intellij.inspection.dao.processor + +import com.intellij.psi.PsiParameter +import com.intellij.psi.PsiTypes +import org.domaframework.doma.intellij.common.psi.PsiDaoMethod +import org.domaframework.doma.intellij.common.sql.PsiClassTypeUtil +import org.domaframework.doma.intellij.common.validation.result.ValidationResult +import org.domaframework.doma.intellij.common.validation.result.ValidationReturnTypeForReturningResult +import org.domaframework.doma.intellij.extension.getJavaClazz +import org.domaframework.doma.intellij.extension.psi.isEntity + +/** + * Processor for checking the return type of update-related annotations in DAO methods. + * + * @property psiDaoMethod The target DAO method info to be checked. + * @property shortName The short name of inspection. + */ +class UpdateAnnotationReturnTypeCheckProcessor( + private val psiDaoMethod: PsiDaoMethod, + private val shortName: String, +) : ReturnTypeCheckerProcessor(psiDaoMethod, shortName) { + /** + * Checks the return type of the DAO method. + * + * @return [ValidationResult] if the return type is invalid, otherwise null. + */ + override fun checkReturnType(): ValidationResult? { + val methodOtherReturnType = PsiTypes.intType() + if (psiDaoMethod.useSqlAnnotation() || psiDaoMethod.sqlFileOption) { + return generatePsiTypeReturnTypeResult(methodOtherReturnType) + } + + val parameters = method.parameterList.parameters + val immutableEntityParam = + parameters.firstOrNull() ?: return null + + // Check if the method is annotated with @Returning + if (hasReturingOption()) { + return checkReturnTypeWithReturning(immutableEntityParam) + } + + // Check if it has an immutable entity parameter + if (isImmutableEntity(immutableEntityParam.type.canonicalText)) { + return checkReturnTypeImmutableEntity(immutableEntityParam) + } + + // If the return type is not an int, return a validation result + return generatePsiTypeReturnTypeResult(methodOtherReturnType) + } + + /** + * Checks the return type when the @Returning annotation is present. + * + * @param paramClass The method parameter to compare against. + * @return [ValidationResult] if the return type is invalid, otherwise null. + */ + private fun checkReturnTypeWithReturning(paramClass: PsiParameter): ValidationResult? { + if (returnType == null) { + return ValidationReturnTypeForReturningResult( + paramClass.type.presentableText, + method.nameIdentifier, + shortName, + ) + } + + val checkReturnType = + PsiClassTypeUtil.convertOptionalType(returnType, project) + val returnTypeClass = project.getJavaClazz(checkReturnType.canonicalText) + + return if (returnTypeClass?.isEntity() != true || returnType.canonicalText != paramClass.type.canonicalText) { + ValidationReturnTypeForReturningResult( + paramClass.type.presentableText, + method.nameIdentifier, + shortName, + ) + } else { + null + } + } + + /** + * Checks the return type when an immutable entity parameter is present. + * + * @param immutableEntityParam The immutable entity parameter. + * @return [ValidationResult] if the return type is invalid, otherwise null. + */ + private fun checkReturnTypeImmutableEntity(immutableEntityParam: PsiParameter): ValidationResult? { + val methodResultClassName = "org.seasar.doma.jdbc.Result" + val resultTypeName = "Result" + return generateResultReturnTypeImmutable( + psiDaoMethod.daoType, + immutableEntityParam.type, + methodResultClassName, + resultTypeName, + ) + } +} diff --git a/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/provider/DaoMethodReturnTypeVariableProvider.kt b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/provider/DaoMethodReturnTypeVariableProvider.kt new file mode 100644 index 00000000..baa643cd --- /dev/null +++ b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/provider/DaoMethodReturnTypeVariableProvider.kt @@ -0,0 +1,27 @@ +/* + * Copyright Doma Tools Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.domaframework.doma.intellij.inspection.dao.provider + +import com.intellij.codeInspection.InspectionToolProvider +import com.intellij.codeInspection.LocalInspectionTool +import org.domaframework.doma.intellij.inspection.dao.inspector.DaoMethodReturnTypeVariableInspection + +class DaoMethodReturnTypeVariableProvider : InspectionToolProvider { + override fun getInspectionClasses(): Array> = + arrayOf( + DaoMethodReturnTypeVariableInspection::class.java, + ) +} diff --git a/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/provider/DaoMethodVariableProvider.kt b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/provider/UsedDaoMethodArgsVariableProvider.kt similarity index 85% rename from src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/provider/DaoMethodVariableProvider.kt rename to src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/provider/UsedDaoMethodArgsVariableProvider.kt index 8c30630f..ede3c6d9 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/provider/DaoMethodVariableProvider.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/provider/UsedDaoMethodArgsVariableProvider.kt @@ -17,11 +17,11 @@ package org.domaframework.doma.intellij.inspection.dao.provider import com.intellij.codeInspection.InspectionToolProvider import com.intellij.codeInspection.LocalInspectionTool -import org.domaframework.doma.intellij.inspection.dao.inspector.DaoMethodVariableInspection +import org.domaframework.doma.intellij.inspection.dao.inspector.UsedDaoMethodArgsVariableInspection -class DaoMethodVariableProvider : InspectionToolProvider { +class UsedDaoMethodArgsVariableProvider : InspectionToolProvider { override fun getInspectionClasses(): Array> = arrayOf( - DaoMethodVariableInspection::class.java, + UsedDaoMethodArgsVariableInspection::class.java, ) } diff --git a/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/visitor/DaoMethodReturnTypeVariableInspectionVisitor.kt b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/visitor/DaoMethodReturnTypeVariableInspectionVisitor.kt new file mode 100644 index 00000000..72e215ca --- /dev/null +++ b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/visitor/DaoMethodReturnTypeVariableInspectionVisitor.kt @@ -0,0 +1,74 @@ +/* + * Copyright Doma Tools Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.domaframework.doma.intellij.inspection.dao.visitor + +import com.intellij.codeInspection.ProblemsHolder +import com.intellij.psi.JavaElementVisitor +import com.intellij.psi.PsiMethod +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.psi.DomaAnnotationType +import org.domaframework.doma.intellij.inspection.dao.processor.BatchAnnotationReturnTypeCheckProcessor +import org.domaframework.doma.intellij.inspection.dao.processor.MultiInsertAnnotationReturnTypeCheckProcessor +import org.domaframework.doma.intellij.inspection.dao.processor.ProcedureAnnotationReturnTypeCheckProcessor +import org.domaframework.doma.intellij.inspection.dao.processor.ReturnTypeCheckerProcessor +import org.domaframework.doma.intellij.inspection.dao.processor.SqlProcessorAnnotationReturnTypeCheckProcessor +import org.domaframework.doma.intellij.inspection.dao.processor.UpdateAnnotationReturnTypeCheckProcessor + +class DaoMethodReturnTypeVariableInspectionVisitor( + private val holder: ProblemsHolder, + private val shortName: String, +) : JavaElementVisitor() { + override fun visitMethod(method: PsiMethod) { + super.visitMethod(method) + val file = method.containingFile + if (!isJavaOrKotlinFileType(file) || getDaoClass(file) == null) return + + val psiDaoMethod = PsiDaoMethod(method.project, method) + var processor: ReturnTypeCheckerProcessor? = getReturnTypeCheckProcessor(psiDaoMethod) + val result = processor?.checkReturnType() + result?.highlightElement(holder) + } + + private fun getReturnTypeCheckProcessor(psiDaoMethod: PsiDaoMethod): ReturnTypeCheckerProcessor? = + when (psiDaoMethod.daoType) { + DomaAnnotationType.Insert, DomaAnnotationType.Update, DomaAnnotationType.Delete -> { + UpdateAnnotationReturnTypeCheckProcessor(psiDaoMethod, this.shortName) + } + + DomaAnnotationType.BatchInsert, DomaAnnotationType.BatchUpdate, DomaAnnotationType.BatchDelete -> { + BatchAnnotationReturnTypeCheckProcessor(psiDaoMethod, this.shortName) + } + + DomaAnnotationType.Procedure -> { + ProcedureAnnotationReturnTypeCheckProcessor(psiDaoMethod, this.shortName) + } + DomaAnnotationType.SqlProcessor -> { + SqlProcessorAnnotationReturnTypeCheckProcessor( + psiDaoMethod, + this.shortName, + ) + } + DomaAnnotationType.MultiInsert -> + MultiInsertAnnotationReturnTypeCheckProcessor( + psiDaoMethod, + this.shortName, + ) + + DomaAnnotationType.Select, DomaAnnotationType.Sql, DomaAnnotationType.Script, DomaAnnotationType.Unknown -> null + } +} diff --git a/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/visitor/DaoMethodVariableSqlVisitor.kt b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/visitor/DaoMethodVariableSqlVisitor.kt index fb91231a..d8b188ff 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/visitor/DaoMethodVariableSqlVisitor.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/visitor/DaoMethodVariableSqlVisitor.kt @@ -39,13 +39,11 @@ class DaoMethodVariableSqlVisitor( // Recursively explore child elements in a file with PsiRecursiveElementVisitor. override fun visitElement(element: PsiElement) { - val prevElementType = PsiTreeUtil.prevLeaf(element)?.elementType if (( element.elementType == SqlTypes.EL_IDENTIFIER || element is SqlElPrimaryExpr ) && - prevElementType != SqlTypes.DOT && - prevElementType != SqlTypes.AT_SIGN + element.prevSibling?.elementType != SqlTypes.DOT ) { iterator = args.minus(elements.toSet()).iterator() while (iterator.hasNext()) { diff --git a/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/visitor/SqlFileExistInspectionVisitor.kt b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/visitor/SqlFileExistInspectionVisitor.kt index c7528cdc..ea65bca6 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/visitor/SqlFileExistInspectionVisitor.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/visitor/SqlFileExistInspectionVisitor.kt @@ -21,7 +21,7 @@ import com.intellij.psi.PsiMethod 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.common.sql.validator.result.ValidationSqlFileExistResult +import org.domaframework.doma.intellij.common.validation.result.ValidationSqlFileExistResult class SqlFileExistInspectionVisitor( private val holder: ProblemsHolder, @@ -35,25 +35,19 @@ class SqlFileExistInspectionVisitor( val psiDaoMethod = PsiDaoMethod(method.project, method) if (psiDaoMethod.isUseSqlFileMethod()) { - checkDaoMethod(psiDaoMethod, holder) + checkDaoMethod(psiDaoMethod) } } - private fun checkDaoMethod( - psiDaoMethod: PsiDaoMethod, - problemHolder: ProblemsHolder, - ) { + private fun checkDaoMethod(psiDaoMethod: PsiDaoMethod) { val identifier = psiDaoMethod.psiMethod.nameIdentifier ?: return if (psiDaoMethod.sqlFile == null) { ValidationSqlFileExistResult( psiDaoMethod, identifier, shortName, - ).setHighlight( - identifier.textRange, - identifier, - problemHolder, - null, + ).highlightElement( + holder, ) } } diff --git a/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/visitor/DaoMethodVariableInspectionVisitor.kt b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/visitor/UsedDaoMethodArgsVariableInspectionVisitor.kt similarity index 76% rename from src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/visitor/DaoMethodVariableInspectionVisitor.kt rename to src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/visitor/UsedDaoMethodArgsVariableInspectionVisitor.kt index 3326dd54..9636409d 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/visitor/DaoMethodVariableInspectionVisitor.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/visitor/UsedDaoMethodArgsVariableInspectionVisitor.kt @@ -15,24 +15,25 @@ */ package org.domaframework.doma.intellij.inspection.dao.visitor +import com.intellij.codeInspection.ProblemHighlightType import com.intellij.codeInspection.ProblemsHolder import com.intellij.psi.JavaElementVisitor import com.intellij.psi.PsiFile import com.intellij.psi.PsiMethod import com.intellij.psi.PsiParameter +import com.intellij.psi.impl.source.PsiParameterImpl +import org.domaframework.doma.intellij.bundle.MessageBundle 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.common.sql.validator.result.ValidationUsedDaoMethodArgsResult 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 -class DaoMethodVariableInspectionVisitor( +class UsedDaoMethodArgsVariableInspectionVisitor( private val holder: ProblemsHolder, - private val shotName: String, ) : JavaElementVisitor() { override fun visitMethod(method: PsiMethod) { super.visitMethod(method) @@ -54,12 +55,25 @@ class DaoMethodVariableInspectionVisitor( val result = findElementsInSqlFile(sqlFileManager, params) params.forEach { param -> if (!result.elements.contains(param)) { - ValidationUsedDaoMethodArgsResult(result, param, shotName).highlightElement(holder) + val message = + if (result.deplicateForItemElements.contains(param)) { + MessageBundle.message("inspection.invalid.dao.duplicate") + } else { + MessageBundle.message( + "inspection.invalid.dao.paramUse", + param.name, + ) + } + holder.registerProblem( + (param.originalElement as PsiParameterImpl).nameIdentifier, + message, + ProblemHighlightType.ERROR, + ) } } } - data class DaoMethodVariableVisitorResult( + private data class DaoMethodVariableVisitorResult( val elements: List, val deplicateForItemElements: List, ) diff --git a/src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/inspector/SqlBindVariableInspection.kt b/src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/inspector/SqlBindVariableInspection.kt index 2e0ecfff..d85d680c 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/inspector/SqlBindVariableInspection.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/inspector/SqlBindVariableInspection.kt @@ -25,7 +25,7 @@ import org.domaframework.doma.intellij.psi.SqlVisitor * Code inspection for SQL bind variables */ class SqlBindVariableInspection : LocalInspectionTool() { - override fun getDisplayName(): String = "Check where SQL bind variables are defined." + override fun getDisplayName(): String = "Check bind variables" override fun getShortName(): String = "org.domaframework.doma.intellij.validBindVariable" diff --git a/src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/inspector/SqlFunctionCallInspection.kt b/src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/inspector/SqlFunctionCallInspection.kt index 0f8451b9..a97217c1 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/inspector/SqlFunctionCallInspection.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/inspector/SqlFunctionCallInspection.kt @@ -22,11 +22,7 @@ import org.domaframework.doma.intellij.inspection.sql.visitor.SqlFunctionCallIns import org.domaframework.doma.intellij.psi.SqlVisitor class SqlFunctionCallInspection : LocalInspectionTool() { - override fun getDisplayName(): String = - "This inspection checks whether the function name called " + - "in a function call is defined in the implementation class specified " + - "by the `doma.expr.functions` property of doma.compile.config," + - " or in org.seasar.doma.expr.ExpressionFunctions." + override fun getDisplayName(): String = "Check function call" override fun getShortName(): String = "org.domaframework.doma.intellij.functionCall" diff --git a/src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/inspector/SqlLoopDirectiveTypeInspection.kt b/src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/inspector/SqlLoopDirectiveTypeInspection.kt index fbf021df..5cf75c68 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/inspector/SqlLoopDirectiveTypeInspection.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/inspector/SqlLoopDirectiveTypeInspection.kt @@ -22,8 +22,7 @@ import org.domaframework.doma.intellij.inspection.sql.visitor.SqlLoopDirectiveTy import org.domaframework.doma.intellij.psi.SqlVisitor class SqlLoopDirectiveTypeInspection : LocalInspectionTool() { - override fun getDisplayName(): String = - "This inspection checks whether the base type of the element defined in a loop directive is of an Iterable type." + override fun getDisplayName(): String = "Check loop directive type" override fun getShortName(): String = "org.domaframework.doma.intellij.loopDirectiveType" diff --git a/src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/inspector/SqlTestDataInspection.kt b/src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/inspector/SqlTestDataInspection.kt index 3c52bb24..c20c5f52 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/inspector/SqlTestDataInspection.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/inspector/SqlTestDataInspection.kt @@ -25,7 +25,7 @@ import org.domaframework.doma.intellij.psi.SqlVisitor * Code inspection for SQL bind variables */ class SqlTestDataInspection : LocalInspectionTool() { - override fun getDisplayName(): String = "Verify the presence of test data after SQL bind variables" + override fun getDisplayName(): String = "Check test data presence" override fun getShortName(): String = "org.domaframework.doma.intellij.existaftertestdata" diff --git a/src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/processor/InspectionForDirectiveVisitorProcessor.kt b/src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/processor/InspectionForDirectiveVisitorProcessor.kt index 791ea0b1..3c85633e 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/processor/InspectionForDirectiveVisitorProcessor.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/processor/InspectionForDirectiveVisitorProcessor.kt @@ -16,8 +16,8 @@ package org.domaframework.doma.intellij.inspection.sql.processor import com.intellij.codeInspection.ProblemsHolder -import org.domaframework.doma.intellij.common.sql.validator.result.ValidationForDirectiveItemTypeResult import org.domaframework.doma.intellij.common.util.ForDirectiveUtil +import org.domaframework.doma.intellij.common.validation.result.ValidationForDirectiveItemTypeResult import org.domaframework.doma.intellij.extension.psi.getForItem import org.domaframework.doma.intellij.psi.SqlElForDirective diff --git a/src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/processor/InspectionFunctionCallVisitorProcessor.kt b/src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/processor/InspectionFunctionCallVisitorProcessor.kt index 173f1f97..a3e5d9f3 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/processor/InspectionFunctionCallVisitorProcessor.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/processor/InspectionFunctionCallVisitorProcessor.kt @@ -21,9 +21,9 @@ import org.domaframework.doma.intellij.common.CommonPathParameterUtil import org.domaframework.doma.intellij.common.config.DomaCompileConfigUtil import org.domaframework.doma.intellij.common.config.DomaCompileConfigUtil.EXPRESSION_FUNCTIONS_NAME import org.domaframework.doma.intellij.common.helper.ExpressionFunctionsHelper -import org.domaframework.doma.intellij.common.sql.validator.result.ValidationInvalidExpressionFunctionsResult -import org.domaframework.doma.intellij.common.sql.validator.result.ValidationInvalidFunctionCallResult -import org.domaframework.doma.intellij.common.sql.validator.result.ValidationResult +import org.domaframework.doma.intellij.common.validation.result.ValidationInvalidExpressionFunctionsResult +import org.domaframework.doma.intellij.common.validation.result.ValidationInvalidFunctionCallResult +import org.domaframework.doma.intellij.common.validation.result.ValidationResult import org.domaframework.doma.intellij.extension.getJavaClazz import org.domaframework.doma.intellij.psi.SqlElFunctionCallExpr import org.jetbrains.kotlin.idea.util.projectStructure.module diff --git a/src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/processor/InspectionPrimaryVisitorProcessor.kt b/src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/processor/InspectionPrimaryVisitorProcessor.kt index 37d7130c..501ed2a4 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/processor/InspectionPrimaryVisitorProcessor.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/processor/InspectionPrimaryVisitorProcessor.kt @@ -20,9 +20,9 @@ import com.intellij.psi.PsiFile import com.intellij.psi.util.PsiTreeUtil import org.domaframework.doma.intellij.common.dao.findDaoMethod import org.domaframework.doma.intellij.common.sql.cleanString -import org.domaframework.doma.intellij.common.sql.validator.result.ValidationDaoParamResult -import org.domaframework.doma.intellij.common.sql.validator.result.ValidationForDirectiveItemTypeResult import org.domaframework.doma.intellij.common.util.ForDirectiveUtil +import org.domaframework.doma.intellij.common.validation.result.ValidationDaoParamResult +import org.domaframework.doma.intellij.common.validation.result.ValidationForDirectiveItemTypeResult import org.domaframework.doma.intellij.extension.psi.findParameter import org.domaframework.doma.intellij.extension.psi.getForItem import org.domaframework.doma.intellij.psi.SqlElForDirective diff --git a/src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/processor/InspectionStaticFieldAccessVisitorProcessor.kt b/src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/processor/InspectionStaticFieldAccessVisitorProcessor.kt index 79b82c2a..7c9d3204 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/processor/InspectionStaticFieldAccessVisitorProcessor.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/processor/InspectionStaticFieldAccessVisitorProcessor.kt @@ -17,9 +17,9 @@ package org.domaframework.doma.intellij.inspection.sql.processor import com.intellij.codeInspection.ProblemsHolder import org.domaframework.doma.intellij.common.psi.PsiStaticElement -import org.domaframework.doma.intellij.common.sql.validator.result.ValidationClassPathResult -import org.domaframework.doma.intellij.common.sql.validator.result.ValidationNotFoundStaticPropertyResult import org.domaframework.doma.intellij.common.util.ForDirectiveUtil +import org.domaframework.doma.intellij.common.validation.result.ValidationClassPathResult +import org.domaframework.doma.intellij.common.validation.result.ValidationNotFoundStaticPropertyResult import org.domaframework.doma.intellij.extension.expr.accessElements import org.domaframework.doma.intellij.psi.SqlElStaticFieldAccessExpr diff --git a/src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/processor/InspectionVisitorProcessor.kt b/src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/processor/InspectionVisitorProcessor.kt index 8be0d357..cfc55641 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/processor/InspectionVisitorProcessor.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/processor/InspectionVisitorProcessor.kt @@ -19,7 +19,7 @@ import com.intellij.codeInspection.ProblemsHolder import com.intellij.psi.PsiElement import com.intellij.psi.PsiMethod import com.intellij.psi.util.elementType -import org.domaframework.doma.intellij.common.sql.validator.result.ValidationDaoParamResult +import org.domaframework.doma.intellij.common.validation.result.ValidationDaoParamResult import org.domaframework.doma.intellij.psi.SqlElIdExpr import org.domaframework.doma.intellij.psi.SqlElNewExpr import org.domaframework.doma.intellij.psi.SqlTypes diff --git a/src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/visitor/SqlTestDataInspectionVisitor.kt b/src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/visitor/SqlTestDataInspectionVisitor.kt index be8a1c17..37e3db09 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/visitor/SqlTestDataInspectionVisitor.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/visitor/SqlTestDataInspectionVisitor.kt @@ -23,7 +23,7 @@ import com.intellij.psi.util.PsiTreeUtil import com.intellij.psi.util.nextLeafs import org.domaframework.doma.intellij.common.isInjectionSqlFile import org.domaframework.doma.intellij.common.isJavaOrKotlinFileType -import org.domaframework.doma.intellij.common.sql.validator.result.ValidationTestDataResult +import org.domaframework.doma.intellij.common.validation.result.ValidationTestDataResult import org.domaframework.doma.intellij.psi.SqlBlockComment import org.domaframework.doma.intellij.psi.SqlElElseifDirective import org.domaframework.doma.intellij.psi.SqlElForDirective diff --git a/src/main/kotlin/org/domaframework/doma/intellij/reference/SqlElIdExprReference.kt b/src/main/kotlin/org/domaframework/doma/intellij/reference/SqlElIdExprReference.kt index d8fe4261..6af92612 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/reference/SqlElIdExprReference.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/reference/SqlElIdExprReference.kt @@ -25,9 +25,9 @@ import org.domaframework.doma.intellij.common.psi.PsiDaoMethod import org.domaframework.doma.intellij.common.psi.PsiParentClass import org.domaframework.doma.intellij.common.sql.cleanString import org.domaframework.doma.intellij.common.sql.foritem.ForItem -import org.domaframework.doma.intellij.common.sql.validator.result.ValidationCompleteResult import org.domaframework.doma.intellij.common.util.ForDirectiveUtil import org.domaframework.doma.intellij.common.util.PluginLoggerUtil +import org.domaframework.doma.intellij.common.validation.result.ValidationCompleteResult import org.domaframework.doma.intellij.extension.psi.findParameter import org.domaframework.doma.intellij.extension.psi.getForItem import org.domaframework.doma.intellij.psi.SqlElFieldAccessExpr diff --git a/src/main/kotlin/org/domaframework/doma/intellij/reference/SqlElStaticFieldReference.kt b/src/main/kotlin/org/domaframework/doma/intellij/reference/SqlElStaticFieldReference.kt index 816151d6..19a8fc6d 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/reference/SqlElStaticFieldReference.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/reference/SqlElStaticFieldReference.kt @@ -20,9 +20,9 @@ import com.intellij.psi.PsiFile import com.intellij.psi.util.PsiTreeUtil import org.domaframework.doma.intellij.common.psi.PsiParentClass import org.domaframework.doma.intellij.common.psi.PsiStaticElement -import org.domaframework.doma.intellij.common.sql.validator.result.ValidationCompleteResult import org.domaframework.doma.intellij.common.util.ForDirectiveUtil import org.domaframework.doma.intellij.common.util.PluginLoggerUtil +import org.domaframework.doma.intellij.common.validation.result.ValidationCompleteResult import org.domaframework.doma.intellij.extension.psi.psiClassType import org.domaframework.doma.intellij.psi.SqlElStaticFieldAccessExpr diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index 537a7a61..67871af6 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -49,7 +49,8 @@ - + + diff --git a/src/main/resources/inspectionDescriptions/org.domaframework.doma.intellij.existaftertestdata.html b/src/main/resources/inspectionDescriptions/org.domaframework.doma.intellij.existaftertestdata.html index 6446a297..be3aeedb 100644 --- a/src/main/resources/inspectionDescriptions/org.domaframework.doma.intellij.existaftertestdata.html +++ b/src/main/resources/inspectionDescriptions/org.domaframework.doma.intellij.existaftertestdata.html @@ -1,7 +1,8 @@

- Displays an error or warning if there is no test data after a variable directive. + This inspection checks whether test data elements exist immediately after block comments in SQL files. + Ensure that test data is properly defined to maintain SQL integrity and avoid unexpected behavior.

\ No newline at end of file diff --git a/src/main/resources/inspectionDescriptions/org.domaframework.doma.intellij.existsqlchecker.html b/src/main/resources/inspectionDescriptions/org.domaframework.doma.intellij.existsqlchecker.html index 2f491307..ad8dfb9b 100644 --- a/src/main/resources/inspectionDescriptions/org.domaframework.doma.intellij.existsqlchecker.html +++ b/src/main/resources/inspectionDescriptions/org.domaframework.doma.intellij.existsqlchecker.html @@ -1,9 +1,8 @@

- DAO Method Inspection with Doma Tools. - If a DAO method does not have a corresponding SQL file, a warning or error is displayed. - A quick-fix to generate the missing SQL file is then offered. + This inspection ensures that a DAO method has a corresponding SQL file. + If the SQL file is missing, a warning or error is displayed, and a quick-fix is provided to generate the missing file.

\ No newline at end of file diff --git a/src/main/resources/inspectionDescriptions/org.domaframework.doma.intellij.returnType.html b/src/main/resources/inspectionDescriptions/org.domaframework.doma.intellij.returnType.html new file mode 100644 index 00000000..970ed9db --- /dev/null +++ b/src/main/resources/inspectionDescriptions/org.domaframework.doma.intellij.returnType.html @@ -0,0 +1,8 @@ + + +

+ This inspection verifies that the return type of DAO method matches the expected type based on its annotation. + Ensure that the method's return type aligns with the annotation's requirements to avoid runtime errors. +

+ + \ No newline at end of file diff --git a/src/main/resources/inspectionDescriptions/org.domaframework.doma.intellij.variablechecker.html b/src/main/resources/inspectionDescriptions/org.domaframework.doma.intellij.variablechecker.html index b27a45b2..95ae700b 100644 --- a/src/main/resources/inspectionDescriptions/org.domaframework.doma.intellij.variablechecker.html +++ b/src/main/resources/inspectionDescriptions/org.domaframework.doma.intellij.variablechecker.html @@ -1,7 +1,8 @@

- Doma Tools displays warnings or errors for unused method arguments. + This inspection checks whether DAO method arguments are used as bind variables in the corresponding SQL file. + Ensure that all method arguments are properly referenced in the SQL to avoid unused parameters and maintain consistency.

\ No newline at end of file diff --git a/src/main/resources/messages/DomaToolsBundle.properties b/src/main/resources/messages/DomaToolsBundle.properties index fbaf4522..2d5cd80b 100644 --- a/src/main/resources/messages/DomaToolsBundle.properties +++ b/src/main/resources/messages/DomaToolsBundle.properties @@ -14,3 +14,8 @@ inspection.invalid.sql.iterable=The type that can be used in the loop directive inspection.invalid.dao.duplicate=An element name that is a duplicate of an element name defined in SQL is used inspection.invalid.sql.notFound.customFunction=Custom function [{0}] not found in class [{1}] inspection.invalid.sql.notFound.expressionClass=An invalid ExpressionFunctions implementation class is configured in doma.compile.config +inspection.invalid.dao.returnType.psiTypes=The return type must be "{0}". +inspection.invalid.dao.update.returnType.returning=When "returning = @Returning" is specified, the return type must be "{0}" or Optional<{0}> +inspection.invalid.dao.sqlProcessor.returnType.returning=The return type "{0}" is not the same as the third type argument "{1}" of BiFunction. +inspection.invalid.dao.multiInsert.returnType.returning=When "returning = @Returning" is specified, the return type must be List<{0}> +inspection.invalid.dao.returnType.immutable=If a method annotated with @{0} targets immutable entities for insertion, the return type must be {1}<{2}>. \ No newline at end of file diff --git a/src/main/resources/messages/DomaToolsBundle_ja.properties b/src/main/resources/messages/DomaToolsBundle_ja.properties index 97a9501d..4c27b0eb 100644 --- a/src/main/resources/messages/DomaToolsBundle_ja.properties +++ b/src/main/resources/messages/DomaToolsBundle_ja.properties @@ -14,3 +14,8 @@ inspection.invalid.sql.iterable=\u30EB\u30FC\u30D7\u30C7\u30A3\u30EC\u30AF\u30C6 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 inspection.invalid.sql.notFound.customFunction=\u30AB\u30B9\u30BF\u30E0\u95A2\u6570[{0}]\u304C\u30AF\u30E9\u30B9[{1}]\u5185\u306B\u898B\u3064\u304B\u308A\u307E\u305B\u3093 inspection.invalid.sql.notFound.expressionClass=\u0064\u006F\u006D\u0061\u002E\u0063\u006F\u006D\u0070\u0069\u006C\u0065\u002E\u0063\u006F\u006E\u0066\u0069\u0067\u0020\u306B\u7121\u52B9\u306A\u0020\u0045\u0078\u0070\u0072\u0065\u0073\u0073\u0069\u006F\u006E\u0046\u0075\u006E\u0063\u0074\u0069\u006F\u006E\u0073\u0020\u5B9F\u88C5\u30AF\u30E9\u30B9\u304C\u8A2D\u5B9A\u3055\u308C\u3066\u3044\u307E\u3059 +inspection.invalid.dao.returnType.psiTypes=\u623B\u308A\u5024\u306F"{0}"\u3067\u306A\u3051\u308C\u3070\u306A\u308A\u307E\u305B\u3093 +inspection.invalid.dao.update.returnType.returning=\u300Creturning = @Returning\u300D\u304C\u6307\u5B9A\u3055\u308C\u305F\u5834\u5408\u3001\u623B\u308A\u5024\u306F"{0}"\u307E\u305F\u306F Optional<{0}>\u3067\u306A\u3051\u308C\u3070\u306A\u308A\u307E\u305B\u3093 +inspection.invalid.dao.sqlProcessor.returnType.returning=\u623B\u308A\u5024"{0}"\u306F BiFunction \u306E 3 \u756A\u76EE\u306E\u578B\u5F15\u6570"{1}"\u3068\u540C\u3058\u3067\u306A\u3051\u308C\u3070\u306A\u308A\u307E\u305B\u3093 +inspection.invalid.dao.multiInsert.returnType.returning=\u300Creturning = @Returning\u300D\u304C\u6307\u5B9A\u3055\u308C\u305F\u5834\u5408\u3001\u623B\u308A\u5024\u306F List<{0}>\u3067\u306A\u3051\u308C\u3070\u306A\u308A\u307E\u305B\u3093 +inspection.invalid.dao.returnType.immutable=@{0}\u304C\u4ED8\u4E0E\u3055\u308C\u305F\u30E1\u30BD\u30C3\u30C9\u304C\u4E0D\u5909\u306A\u30A8\u30F3\u30C6\u30A3\u30C6\u30A3\u30AF\u30E9\u30B9\u3092\u5F15\u6570\u306B\u6301\u3064\u5834\u5408\u3001\u623B\u308A\u5024\u306F {1}<{2}>\u3067\u306A\u3051\u308C\u3070\u306A\u308A\u307E\u305B\u3093 diff --git a/src/test/kotlin/org/domaframework/doma/intellij/DomaSqlTest.kt b/src/test/kotlin/org/domaframework/doma/intellij/DomaSqlTest.kt index b549c90a..a4316805 100644 --- a/src/test/kotlin/org/domaframework/doma/intellij/DomaSqlTest.kt +++ b/src/test/kotlin/org/domaframework/doma/intellij/DomaSqlTest.kt @@ -49,7 +49,7 @@ open class DomaSqlTest : LightJavaCodeInsightFixtureTestCase() { super.setUp() settingJdk() setDirectoryRoot() - addLibrary("doma-core-3.2.0.jar", "doma-core") + addLibrary("doma-core-3.8.0.jar", "doma-core") addEntityJavaFile("User.java") addEntityJavaFile("UserSummary.java") @@ -161,7 +161,7 @@ open class DomaSqlTest : LightJavaCodeInsightFixtureTestCase() { } } - private fun addEntityJavaFile(fileName: String) { + protected fun addEntityJavaFile(fileName: String) { val file = File("$testDataPath/$sourceRoot/$packagePath/entity/$fileName") myFixture.addFileToProject( "main/$sourceRoot/$packagePath/entity/$fileName", diff --git a/src/test/kotlin/org/domaframework/doma/intellij/gutteraction/dao/DaoGenerateSqlActionTest.kt b/src/test/kotlin/org/domaframework/doma/intellij/gutteraction/dao/DaoGenerateSqlActionTest.kt index 83699324..f148b58a 100644 --- a/src/test/kotlin/org/domaframework/doma/intellij/gutteraction/dao/DaoGenerateSqlActionTest.kt +++ b/src/test/kotlin/org/domaframework/doma/intellij/gutteraction/dao/DaoGenerateSqlActionTest.kt @@ -37,50 +37,51 @@ class DaoGenerateSqlActionTest : DomaSqlTest() { override fun setUp() { super.setUp() + val gutterActionPackageName = "gutteraction" addDaoJavaFile( - "quickfix/SelectQuickFixTestDao.java", - "quickfix/InsertQuickFixTestDao.java", - "quickfix/UpdateQuickFixTestDao.java", - "quickfix/DeleteQuickFixTestDao.java", - "quickfix/BatchInsertQuickFixTestDao.java", - "quickfix/BatchUpdateQuickFixTestDao.java", - "quickfix/BatchDeleteQuickFixTestDao.java", - "quickfix/ScriptQuickFixTestDao.java", - "quickfix/SqlProcessorQuickFixTestDao.java", + "$packageName/SelectQuickFixTestDao.java", + "$packageName/InsertQuickFixTestDao.java", + "$packageName/UpdateQuickFixTestDao.java", + "$packageName/DeleteQuickFixTestDao.java", + "$packageName/BatchInsertQuickFixTestDao.java", + "$packageName/BatchUpdateQuickFixTestDao.java", + "$packageName/BatchDeleteQuickFixTestDao.java", + "$packageName/ScriptQuickFixTestDao.java", + "$packageName/SqlProcessorQuickFixTestDao.java", ) addDaoJavaFile( - "gutteraction/SelectGutterTestDao.java", - "gutteraction/InsertGutterTestDao.java", - "gutteraction/notdisplayed/UpdateInvalidCaretTestDao.java", - "gutteraction/notdisplayed/DeleteInvalidCaretTestDao.java", - "gutteraction/BatchInsertGutterTestDao.java", - "gutteraction/BatchUpdateGutterTestDao.java", - "gutteraction/notdisplayed/BatchDeleteInvalidCaretTestDao.java", - "gutteraction/ScriptGutterTestDao.java", - "gutteraction/SqlProcessorGutterTestDao.java", + "$gutterActionPackageName/SelectGutterTestDao.java", + "$gutterActionPackageName/InsertGutterTestDao.java", + "$gutterActionPackageName/notdisplayed/UpdateInvalidCaretTestDao.java", + "$gutterActionPackageName/notdisplayed/DeleteInvalidCaretTestDao.java", + "$gutterActionPackageName/BatchInsertGutterTestDao.java", + "$gutterActionPackageName/BatchUpdateGutterTestDao.java", + "$gutterActionPackageName/notdisplayed/BatchDeleteInvalidCaretTestDao.java", + "$gutterActionPackageName/ScriptGutterTestDao.java", + "$gutterActionPackageName/SqlProcessorGutterTestDao.java", ) addResourceEmptySqlFile( - "quickfix/SelectQuickFixTestDao/existsSQLFile.sql", - "quickfix/InsertQuickFixTestDao/existsSQLFile.sql", - "quickfix/UpdateQuickFixTestDao/existsSQLFile.sql", - "quickfix/DeleteQuickFixTestDao/existsSQLFile.sql", - "quickfix/BatchInsertQuickFixTestDao/existsSQLFile.sql", - "quickfix/BatchUpdateQuickFixTestDao/existsSQLFile.sql", - "quickfix/BatchDeleteQuickFixTestDao/existsSQLFile.sql", - "quickfix/ScriptQuickFixTestDao/existsSQLFile.script", - "quickfix/SqlProcessorQuickFixTestDao/existsSQLFile.sql", + "$packageName/SelectQuickFixTestDao/existsSQLFile.sql", + "$packageName/InsertQuickFixTestDao/existsSQLFile.sql", + "$packageName/UpdateQuickFixTestDao/existsSQLFile.sql", + "$packageName/DeleteQuickFixTestDao/existsSQLFile.sql", + "$packageName/BatchInsertQuickFixTestDao/existsSQLFile.sql", + "$packageName/BatchUpdateQuickFixTestDao/existsSQLFile.sql", + "$packageName/BatchDeleteQuickFixTestDao/existsSQLFile.sql", + "$packageName/ScriptQuickFixTestDao/existsSQLFile.script", + "$packageName/SqlProcessorQuickFixTestDao/existsSQLFile.sql", ) addResourceEmptySqlFile( - "gutteraction/SelectGutterTestDao/existsSQLFile1.sql", - "gutteraction/InsertGutterTestDao/existsSQLFile2.sql", - "gutteraction/UpdateGutterTestDao/existsSQLFile1.sql", - "gutteraction/DeleteGutterTestDao/existsSQLFile1.sql", - "gutteraction/BatchInsertGutterTestDao/existsSQLFile2.sql", - "gutteraction/BatchUpdateGutterTestDao/existsSQLFile2.sql", - "gutteraction/BatchDeleteGutterTestDao/existsSQLFile1.sql", - "gutteraction/ScriptGutterTestDao/existsSQLFile2.script", - "gutteraction/SqlProcessorGutterTestDao/existsSQLFile1.sql", + "$gutterActionPackageName/SelectGutterTestDao/existsSQLFile1.sql", + "$gutterActionPackageName/InsertGutterTestDao/existsSQLFile2.sql", + "$gutterActionPackageName/UpdateGutterTestDao/existsSQLFile1.sql", + "$gutterActionPackageName/DeleteGutterTestDao/existsSQLFile1.sql", + "$gutterActionPackageName/BatchInsertGutterTestDao/existsSQLFile2.sql", + "$gutterActionPackageName/BatchUpdateGutterTestDao/existsSQLFile2.sql", + "$gutterActionPackageName/BatchDeleteGutterTestDao/existsSQLFile1.sql", + "$gutterActionPackageName/ScriptGutterTestDao/existsSQLFile2.script", + "$gutterActionPackageName/SqlProcessorGutterTestDao/existsSQLFile1.sql", ) } diff --git a/src/test/kotlin/org/domaframework/doma/intellij/inspection/dao/AnnotationReturnTypeCheckInspectionTest.kt b/src/test/kotlin/org/domaframework/doma/intellij/inspection/dao/AnnotationReturnTypeCheckInspectionTest.kt new file mode 100644 index 00000000..9e4784e0 --- /dev/null +++ b/src/test/kotlin/org/domaframework/doma/intellij/inspection/dao/AnnotationReturnTypeCheckInspectionTest.kt @@ -0,0 +1,70 @@ +/* + * Copyright Doma Tools Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.domaframework.doma.intellij.inspection.dao + +import org.domaframework.doma.intellij.DomaSqlTest +import org.domaframework.doma.intellij.inspection.dao.inspector.DaoMethodReturnTypeVariableInspection + +/** + * Test class for annotation return type check inspection. + */ +class AnnotationReturnTypeCheckInspectionTest : DomaSqlTest() { + private val testDaoNames = + listOf( + "UpdateReturnTypeDao", + "BatchReturnTypeDao", + "MultiInsertReturnTypeDao", + "SqlProcessorReturnTypeDao", + "ProcedureReturnTypeDao", + ) + private val daoPackage = "inspection" + + override fun setUp() { + super.setUp() + testDaoNames.forEach { daoName -> + addDaoJavaFile("inspection/$daoName.java") + } + // Entity classes + addEntityJavaFile("Packet.java") + addEntityJavaFile("Pckt.java") + myFixture.enableInspections(DaoMethodReturnTypeVariableInspection()) + } + + fun testUpdateAnnotationReturnTypeCheckProcessor() { + val dao = findDaoClass("$daoPackage.UpdateReturnTypeDao") + myFixture.testHighlighting(false, false, false, dao.containingFile.virtualFile) + } + + fun testBatchAnnotationReturnTypeCheckProcessor() { + val dao = findDaoClass("$daoPackage.BatchReturnTypeDao") + myFixture.testHighlighting(false, false, false, dao.containingFile.virtualFile) + } + + fun testMultiInsertAnnotationReturnTypeCheckProcessor() { + val dao = findDaoClass("$daoPackage.MultiInsertReturnTypeDao") + myFixture.testHighlighting(false, false, false, dao.containingFile.virtualFile) + } + + fun testSqlProcessorAnnotationReturnTypeCheckProcessor() { + val dao = findDaoClass("$daoPackage.SqlProcessorReturnTypeDao") + myFixture.testHighlighting(false, false, false, dao.containingFile.virtualFile) + } + + fun testProcedureAnnotationReturnTypeCheckProcessor() { + val dao = findDaoClass("$daoPackage.ProcedureReturnTypeDao") + myFixture.testHighlighting(false, false, false, dao.containingFile.virtualFile) + } +} diff --git a/src/test/kotlin/org/domaframework/doma/intellij/inspection/dao/DomaSqlQuickFixTest.kt b/src/test/kotlin/org/domaframework/doma/intellij/inspection/dao/DomaSqlQuickFixTest.kt index 8de01631..97178eb7 100644 --- a/src/test/kotlin/org/domaframework/doma/intellij/inspection/dao/DomaSqlQuickFixTest.kt +++ b/src/test/kotlin/org/domaframework/doma/intellij/inspection/dao/DomaSqlQuickFixTest.kt @@ -23,30 +23,32 @@ import org.domaframework.doma.intellij.inspection.dao.inspector.SqlFileExistInsp * Quick fix execution test */ class DomaSqlQuickFixTest : DomaSqlTest() { + private val packagename = "quickfix" + override fun setUp() { super.setUp() addDaoJavaFile( - "quickfix/SelectQuickFixTestDao.java", - "quickfix/InsertQuickFixTestDao.java", - "quickfix/UpdateQuickFixTestDao.java", - "quickfix/DeleteQuickFixTestDao.java", - "quickfix/BatchInsertQuickFixTestDao.java", - "quickfix/BatchUpdateQuickFixTestDao.java", - "quickfix/BatchDeleteQuickFixTestDao.java", - "quickfix/ScriptQuickFixTestDao.java", - "quickfix/SqlProcessorQuickFixTestDao.java", + "$packagename/SelectQuickFixTestDao.java", + "$packagename/InsertQuickFixTestDao.java", + "$packagename/UpdateQuickFixTestDao.java", + "$packagename/DeleteQuickFixTestDao.java", + "$packagename/BatchInsertQuickFixTestDao.java", + "$packagename/BatchUpdateQuickFixTestDao.java", + "$packagename/BatchDeleteQuickFixTestDao.java", + "$packagename/ScriptQuickFixTestDao.java", + "$packagename/SqlProcessorQuickFixTestDao.java", ) addResourceEmptySqlFile( - "quickfix/SelectQuickFixTestDao/existsSQLFile.sql", - "quickfix/InsertQuickFixTestDao/existsSQLFile.sql", - "quickfix/UpdateQuickFixTestDao/existsSQLFile.sql", - "quickfix/DeleteQuickFixTestDao/existsSQLFile.sql", - "quickfix/BatchInsertQuickFixTestDao/existsSQLFile.sql", - "quickfix/BatchUpdateQuickFixTestDao/existsSQLFile.sql", - "quickfix/BatchDeleteQuickFixTestDao/existsSQLFile.sql", - "quickfix/ScriptQuickFixTestDao/existsSQLFile.script", - "quickfix/SqlProcessorQuickFixTestDao/existsSQLFile.sql", + "$packagename/SelectQuickFixTestDao/existsSQLFile.sql", + "$packagename/InsertQuickFixTestDao/existsSQLFile.sql", + "$packagename/UpdateQuickFixTestDao/existsSQLFile.sql", + "$packagename/DeleteQuickFixTestDao/existsSQLFile.sql", + "$packagename/BatchInsertQuickFixTestDao/existsSQLFile.sql", + "$packagename/BatchUpdateQuickFixTestDao/existsSQLFile.sql", + "$packagename/BatchDeleteQuickFixTestDao/existsSQLFile.sql", + "$packagename/ScriptQuickFixTestDao/existsSQLFile.script", + "$packagename/SqlProcessorQuickFixTestDao/existsSQLFile.sql", ) myFixture.enableInspections(SqlFileExistInspection()) } @@ -127,5 +129,5 @@ class DomaSqlQuickFixTest : DomaSqlTest() { afterCheck() } - private fun getQuickFixTestDaoName(daoName: String): String = "quickfix/$daoName" + private fun getQuickFixTestDaoName(daoName: String): String = "$packagename/$daoName" } 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 48d44874..cda2ae31 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 @@ -16,7 +16,7 @@ package org.domaframework.doma.intellij.inspection.dao import org.domaframework.doma.intellij.DomaSqlTest -import org.domaframework.doma.intellij.inspection.dao.inspector.DaoMethodVariableInspection +import org.domaframework.doma.intellij.inspection.dao.inspector.UsedDaoMethodArgsVariableInspection /** * Test class to verify whether DAO method arguments are used @@ -37,7 +37,7 @@ class DomaUseVariableTest : DomaSqlTest() { "$testDaoName/noErrorWhenUsedInFunctionParameters.sql", "$testDaoName/duplicateForDirectiveDefinitionNames.sql", ) - myFixture.enableInspections(DaoMethodVariableInspection()) + myFixture.enableInspections(UsedDaoMethodArgsVariableInspection()) } /** diff --git a/src/test/lib/doma-core-3.8.0.jar b/src/test/lib/doma-core-3.8.0.jar new file mode 100644 index 00000000..c6033fa7 Binary files /dev/null and b/src/test/lib/doma-core-3.8.0.jar differ diff --git a/src/test/lib/doma-processor-3.8.0.jar b/src/test/lib/doma-processor-3.8.0.jar new file mode 100644 index 00000000..8976fe04 Binary files /dev/null and b/src/test/lib/doma-processor-3.8.0.jar differ 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 98eb8952..aec91b45 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 @@ -32,11 +32,8 @@ interface DaoMethodVariableInspectionTestDao { List nonExistSQLFile(String name); @Select - @Sql("select * from employee where name = /* employee.employeeName */'test' and status = /* @doma.example.entity.Project@status */'status'") - Employee noArgumentsUsedInSQLAnnotations(Employee employee, - String employeeName, - String status, - String doma); + @Sql("select * from employee where name = /* name */'test'") + Employee noArgumentsUsedInSQLAnnotations(String name,Integer id); @SqlProcessor R biFunctionDoesNotCauseError(Integer id, BiFunction handler); @@ -45,12 +42,10 @@ Employee noArgumentsUsedInSQLAnnotations(Employee employee, Project selectOptionDoesNotCauseError(Employee employee,String searchName,SelectOptions options); @Select(strategy = SelectType.COLLECT) - Project collectDoesNotCauseError(Employee employee,Integer id, - Collector collector); + Project collectDoesNotCauseError(Employee employee,Integer id,Collector collector); @Select - Project collectDoesCauseError(Employee employee,String searchName, - Collector collector); + Project collectDoesCauseError(Employee employee,String searchName,Collector collector); @Select Project noErrorWhenUsedInFunctionParameters(Employee employee, Integer count); diff --git a/src/test/testData/src/main/java/doma/example/dao/inspection/BatchReturnTypeDao.java b/src/test/testData/src/main/java/doma/example/dao/inspection/BatchReturnTypeDao.java new file mode 100644 index 00000000..4358e1c7 --- /dev/null +++ b/src/test/testData/src/main/java/doma/example/dao/inspection/BatchReturnTypeDao.java @@ -0,0 +1,21 @@ +package doma.example.dao.inspection; + +import org.seasar.doma.*; +import org.seasar.doma.jdbc.BatchResult; +import doma.example.entity.*; +import java.util.List; + +@Dao +public interface BatchReturnTypeDao { + @BatchInsert + int[] batchInsertReturnsIntArray(List e); + + @BatchUpdate + String batchUpdateReturnsString(List e); + + @BatchDelete + int[] batchDeleteReturnsIntWithImmutable(List e); + + @BatchDelete + BatchResult batchDeleteReturnsBatchResultWithImmutable(List e); +} diff --git a/src/test/testData/src/main/java/doma/example/dao/inspection/MultiInsertReturnTypeDao.java b/src/test/testData/src/main/java/doma/example/dao/inspection/MultiInsertReturnTypeDao.java new file mode 100644 index 00000000..a5ceb3c9 --- /dev/null +++ b/src/test/testData/src/main/java/doma/example/dao/inspection/MultiInsertReturnTypeDao.java @@ -0,0 +1,27 @@ +package doma.example.dao.inspection; + +import org.seasar.doma.*; +import org.seasar.doma.jdbc.MultiResult; +import doma.example.entity.*; +import java.util.List; + +@Dao +public interface MultiInsertReturnTypeDao { + @MultiInsert + int multiInsertReturnsInt(List e); + + @MultiInsert + String multiInsertReturnsString(List e); + + @MultiInsert(returning = @Returning) + List multiInsertReturningList(List e); + + @MultiInsert(returning = @Returning) + String ">multiInsertReturningString(List e); + + @MultiInsert + int multiInsertReturnsIntWithImmutable(List e); + + @MultiInsert + MultiResult multiInsertReturnsMultiResultWithImmutable(List e); +} diff --git a/src/test/testData/src/main/java/doma/example/dao/inspection/ProcedureReturnTypeDao.java b/src/test/testData/src/main/java/doma/example/dao/inspection/ProcedureReturnTypeDao.java new file mode 100644 index 00000000..5da218eb --- /dev/null +++ b/src/test/testData/src/main/java/doma/example/dao/inspection/ProcedureReturnTypeDao.java @@ -0,0 +1,11 @@ +package doma.example.dao.inspection; + +import org.seasar.doma.*; + +@Dao +public interface ProcedureReturnTypeDao { + @Procedure + void callProcedureReturnsVoid(); + @Procedure + int callProcedureReturnsInt(); +} \ No newline at end of file diff --git a/src/test/testData/src/main/java/doma/example/dao/inspection/SqlProcessorReturnTypeDao.java b/src/test/testData/src/main/java/doma/example/dao/inspection/SqlProcessorReturnTypeDao.java new file mode 100644 index 00000000..6194a8d2 --- /dev/null +++ b/src/test/testData/src/main/java/doma/example/dao/inspection/SqlProcessorReturnTypeDao.java @@ -0,0 +1,24 @@ +package doma.example.dao.inspection; + +import org.seasar.doma.Dao; +import org.seasar.doma.SqlProcessor; +import org.seasar.doma.jdbc.Config; +import org.seasar.doma.jdbc.PreparedSql; + +import java.util.function.BiFunction; +import doma.example.entity.*; + +@Dao +public interface SqlProcessorReturnTypeDao { + @SqlProcessor + R processSqlReturnsR(BiFunction handler); + + @SqlProcessor + String processSqlReturnsString(BiFunction handler); + + @SqlProcessor + void processSqlReturnsVoid(BiFunction handler); + + @SqlProcessor + String processSqlReturnsStringWithVoidHandler(BiFunction handler); +} diff --git a/src/test/testData/src/main/java/doma/example/dao/inspection/TestDataCheckDao.java b/src/test/testData/src/main/java/doma/example/dao/inspection/TestDataCheckDao.java index a8dfc0ae..5068665d 100644 --- a/src/test/testData/src/main/java/doma/example/dao/inspection/TestDataCheckDao.java +++ b/src/test/testData/src/main/java/doma/example/dao/inspection/TestDataCheckDao.java @@ -30,4 +30,5 @@ interface TestDataCheckDao { @Insert(sqlFile=true) int invalidTestData(Employee employee); -} \ No newline at end of file +} + diff --git a/src/test/testData/src/main/java/doma/example/dao/inspection/UpdateReturnTypeDao.java b/src/test/testData/src/main/java/doma/example/dao/inspection/UpdateReturnTypeDao.java new file mode 100644 index 00000000..b0e87e79 --- /dev/null +++ b/src/test/testData/src/main/java/doma/example/dao/inspection/UpdateReturnTypeDao.java @@ -0,0 +1,28 @@ +package doma.example.dao.inspection; + +import org.seasar.doma.*; +import org.seasar.doma.jdbc.Result; +import doma.example.entity.*; +import java.util.List; + +@Dao +public interface UpdateReturnTypeDao { + @Insert + int insertReturnsInt(Packet e); + + @Update + String updateReturnsString(Packet e); + + @Delete(returning = @Returning) + Packet deleteReturningEntity(Packet e); + + @Delete(returning = @Returning) + int ">deleteReturningInt(Packet e); + + @Update + Result updateReturnsResultWithImmutable(Pckt e); + + @Update + int updateReturnsIntWithImmutable(Pckt e); +} + diff --git a/src/test/testData/src/main/java/doma/example/entity/Packet.java b/src/test/testData/src/main/java/doma/example/entity/Packet.java new file mode 100644 index 00000000..98675374 --- /dev/null +++ b/src/test/testData/src/main/java/doma/example/entity/Packet.java @@ -0,0 +1,15 @@ +package doma.example.entity; + +import org.seasar.doma.Entity; + +@Entity +public class Packet { + private int id; + private String name; + + public int getId() { return id; } + public void setId(int id) { this.id = id; } + public String getName() { return name; } + public void setName(String name) { this.name = name; } +} + diff --git a/src/test/testData/src/main/java/doma/example/entity/Pckt.java b/src/test/testData/src/main/java/doma/example/entity/Pckt.java new file mode 100644 index 00000000..03252780 --- /dev/null +++ b/src/test/testData/src/main/java/doma/example/entity/Pckt.java @@ -0,0 +1,18 @@ +package doma.example.entity; + +import org.seasar.doma.Entity; + +@Entity(immutable = true) +public class Pckt { + private final int id; + private final String name; + + public Pckt(int id, String name) { + this.id = id; + this.name = name; + } + + public int getId() { return id; } + public String getName() { return name; } +} +