diff --git a/src/main/kotlin/org/domaframework/doma/intellij/common/psi/PsiTypeChecker.kt b/src/main/kotlin/org/domaframework/doma/intellij/common/psi/PsiTypeChecker.kt index 6610d908..d90b1f28 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/common/psi/PsiTypeChecker.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/common/psi/PsiTypeChecker.kt @@ -20,35 +20,36 @@ import com.intellij.psi.PsiClassType import com.intellij.psi.PsiPrimitiveType import com.intellij.psi.PsiType import com.intellij.psi.util.PsiUtil +import org.domaframework.doma.intellij.common.util.DomaClassName object PsiTypeChecker { private val TARGET_CLASSES: MutableSet = HashSet() private val WRAPPER_CLASSES: MutableSet = HashSet() init { - TARGET_CLASSES.add("java.lang.String") - TARGET_CLASSES.add("java.lang.Object") - TARGET_CLASSES.add("java.math.BigDecimal") - TARGET_CLASSES.add("java.math.BigInteger") - TARGET_CLASSES.add("java.time.LocalDate") - TARGET_CLASSES.add("java.time.LocalTime") - TARGET_CLASSES.add("java.time.LocalDateTime") - TARGET_CLASSES.add("java.sql.Date") - TARGET_CLASSES.add("java.sql.Time") - TARGET_CLASSES.add("java.sql.Timestamp") - TARGET_CLASSES.add("java.sql.Array") - TARGET_CLASSES.add("java.sql.Blob") - TARGET_CLASSES.add("java.sql.Clob") - TARGET_CLASSES.add("java.sql.SQLXML") - TARGET_CLASSES.add("java.util.Date") + TARGET_CLASSES.add(DomaClassName.STRING.className) + TARGET_CLASSES.add(DomaClassName.OBJECT.className) + TARGET_CLASSES.add(DomaClassName.BIG_DECIMAL.className) + TARGET_CLASSES.add(DomaClassName.BIG_INTEGER.className) + TARGET_CLASSES.add(DomaClassName.LOCAL_DATE.className) + TARGET_CLASSES.add(DomaClassName.LOCAL_TIME.className) + TARGET_CLASSES.add(DomaClassName.LOCAL_DATE_TIME.className) + TARGET_CLASSES.add(DomaClassName.SQL_DATE.className) + TARGET_CLASSES.add(DomaClassName.SQL_TIME.className) + TARGET_CLASSES.add(DomaClassName.SQL_TIMESTAMP.className) + TARGET_CLASSES.add(DomaClassName.SQL_ARRAY.className) + TARGET_CLASSES.add(DomaClassName.SQL_BLOB.className) + TARGET_CLASSES.add(DomaClassName.SQL_CLOB.className) + TARGET_CLASSES.add(DomaClassName.SQL_XML.className) + TARGET_CLASSES.add(DomaClassName.UTIL_DATE.className) - WRAPPER_CLASSES.add("java.lang.Byte") - WRAPPER_CLASSES.add("java.lang.Short") - WRAPPER_CLASSES.add("java.lang.Integer") - WRAPPER_CLASSES.add("java.lang.Long") - WRAPPER_CLASSES.add("java.lang.Float") - WRAPPER_CLASSES.add("java.lang.Double") - WRAPPER_CLASSES.add("java.lang.Boolean") + WRAPPER_CLASSES.add(DomaClassName.BYTE.className) + WRAPPER_CLASSES.add(DomaClassName.SHORT.className) + WRAPPER_CLASSES.add(DomaClassName.INTEGER.className) + WRAPPER_CLASSES.add(DomaClassName.LONG.className) + WRAPPER_CLASSES.add(DomaClassName.FLOAT.className) + WRAPPER_CLASSES.add(DomaClassName.DOUBLE.className) + WRAPPER_CLASSES.add(DomaClassName.BOOLEAN.className) } /** @@ -56,11 +57,14 @@ object PsiTypeChecker { * @param psiType Check target PsiType * @return true if the condition is met */ - fun isTargetType(psiType: PsiType?): Boolean { + fun isBaseClassType(psiType: PsiType?): Boolean { if (psiType == null) return false + // Check if the type is a primitive type if (psiType is PsiPrimitiveType && psiType.canonicalText == "char") { return false } + + // Check if the type is a wrapper class if (psiType is PsiClassType) { val psiClass = PsiUtil.resolveClassInType(psiType) if (psiClass != null) { @@ -79,10 +83,9 @@ object PsiTypeChecker { } if (psiType is PsiArrayType) { val componentType = psiType.componentType.canonicalText - if ("java.lang.Byte" == componentType) { - return true - } + return DomaClassName.BYTE.className == componentType } - return true + // TODO If the condition does not match, return false to strengthen type checking. + return false } } diff --git a/src/main/kotlin/org/domaframework/doma/intellij/common/sql/PsiClassTypeUtil.kt b/src/main/kotlin/org/domaframework/doma/intellij/common/sql/PsiClassTypeUtil.kt index 5901549d..031d9c95 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/common/sql/PsiClassTypeUtil.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/common/sql/PsiClassTypeUtil.kt @@ -19,6 +19,7 @@ import com.intellij.openapi.project.Project import com.intellij.psi.PsiClassType import com.intellij.psi.PsiType import com.intellij.psi.search.GlobalSearchScope +import org.domaframework.doma.intellij.common.util.DomaClassName class PsiClassTypeUtil { companion object { @@ -28,7 +29,7 @@ class PsiClassTypeUtil { ): Boolean { val iterableType = PsiType.getTypeByName( - "java.lang.Iterable", + DomaClassName.ITERABLE.className, project, GlobalSearchScope.allScope(project), ) @@ -68,15 +69,15 @@ class PsiClassTypeUtil { val resolved = daoParamType.resolve() val optionalTypeMap = mapOf( - "java.util.OptionalInt" to "java.lang.Integer", - "java.util.OptionalDouble" to "java.lang.Double", - "java.util.OptionalLong" to "java.lang.Long", + DomaClassName.OPTIONAL_INT.className to DomaClassName.INTEGER.className, + DomaClassName.OPTIONAL_DOUBLE.className to DomaClassName.DOUBLE.className, + DomaClassName.OPTIONAL_LONG.className to DomaClassName.LONG.className, ) if (resolved != null) { when (resolved.qualifiedName) { // If the type is java.util.Optional, return its parameter type if available; // otherwise, return the original daoParamType. - "java.util.Optional" -> return daoParamType.parameters.firstOrNull() + DomaClassName.OPTIONAL.className -> return daoParamType.parameters.firstOrNull() ?: daoParamType // For primitive Optional types (e.g., OptionalInt, OptionalDouble), diff --git a/src/main/kotlin/org/domaframework/doma/intellij/common/sql/directive/LiteralDirectiveHandler.kt b/src/main/kotlin/org/domaframework/doma/intellij/common/sql/directive/LiteralDirectiveHandler.kt index 76c28735..44e71803 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/common/sql/directive/LiteralDirectiveHandler.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/common/sql/directive/LiteralDirectiveHandler.kt @@ -21,7 +21,6 @@ import com.intellij.psi.PsiElement import com.intellij.psi.PsiFile import com.intellij.psi.PsiMethod import org.domaframework.doma.intellij.common.dao.findDaoMethod -import org.domaframework.doma.intellij.common.psi.PsiTypeChecker import org.domaframework.doma.intellij.extension.psi.searchParameter class LiteralDirectiveHandler( @@ -39,9 +38,7 @@ class LiteralDirectiveHandler( ) { daoMethod, bind -> daoMethod ?.searchParameter(bind) - ?.filter { - PsiTypeChecker.isTargetType(it.type) - }?.map { param -> VariableLookupItem(param) } + ?.map { param -> VariableLookupItem(param) } ?.toList() ?: emptyList() } diff --git a/src/main/kotlin/org/domaframework/doma/intellij/common/util/DomaClassName.kt b/src/main/kotlin/org/domaframework/doma/intellij/common/util/DomaClassName.kt new file mode 100644 index 00000000..4ed14489 --- /dev/null +++ b/src/main/kotlin/org/domaframework/doma/intellij/common/util/DomaClassName.kt @@ -0,0 +1,84 @@ +/* + * 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.util + +enum class DomaClassName( + val className: String, +) { + OPTIONAL("java.util.Optional"), + OPTIONAL_INT("java.util.OptionalInt"), + OPTIONAL_DOUBLE("java.util.OptionalDouble"), + OPTIONAL_LONG("java.util.OptionalLong"), + + INTEGER("java.lang.Integer"), + DOUBLE("java.lang.Double"), + LONG("java.lang.Long"), + + MAP("java.util.Map"), + LIST("java.util.List"), + ITERABLE("java.lang.Iterable"), + + DOMAIN("org.seasar.doma.Domain"), + BI_FUNCTION("java.util.function.BiFunction"), + CONFIG("org.seasar.doma.jdbc.Config"), + PREPARED_SQL("org.seasar.doma.jdbc.PreparedSql"), + VOID("java.lang.Void"), + RETURNING("org.seasar.doma.Returning"), + REFERENCE("org.seasar.doma.jdbc.Reference"), + + STRING("java.lang.String"), + OBJECT("java.lang.Object"), + BIG_DECIMAL("java.math.BigDecimal"), + BIG_INTEGER("java.math.BigInteger"), + LOCAL_DATE("java.time.LocalDate"), + LOCAL_TIME("java.time.LocalTime"), + LOCAL_DATE_TIME("java.time.LocalDateTime"), + SQL_DATE("java.sql.Date"), + SQL_TIME("java.sql.Time"), + SQL_TIMESTAMP("java.sql.Timestamp"), + SQL_ARRAY("java.sql.Array"), + SQL_BLOB("java.sql.Blob"), + SQL_CLOB("java.sql.Clob"), + SQL_XML("java.sql.SQLXML"), + UTIL_DATE("java.util.Date"), + + BYTE("java.lang.Byte"), + SHORT("java.lang.Short"), + FLOAT("java.lang.Float"), + BOOLEAN("java.lang.Boolean"), + + JAVA_FUNCTION("java.util.function.Function"), + JAVA_COLLECTOR("java.util.stream.Collector"), + JAVA_STREAM("java.util.stream.Stream"), + SELECT_TYPE("org.seasar.doma.SelectType"), + + ENTITY("org.seasar.doma.Entity"), + ; + + fun isTargetClassNameStartsWith(paramTypeCanonicalNames: String): Boolean = paramTypeCanonicalNames.startsWith(this.className) + + fun getGenericParamCanonicalText(vararg genericParas: String): String = "${this.className}<${genericParas.joinToString(", ")}>" + + companion object { + fun isOptionalWrapperType(paramTypeCanonicalName: String): Boolean = + paramTypeCanonicalName in + listOf( + OPTIONAL_INT.className, + OPTIONAL_DOUBLE.className, + OPTIONAL_LONG.className, + ) + } +} diff --git a/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationMethodBiFunctionParamResult.kt b/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationMethodBiFunctionParamResult.kt new file mode 100644 index 00000000..762a85ef --- /dev/null +++ b/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationMethodBiFunctionParamResult.kt @@ -0,0 +1,51 @@ +/* + * 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.common.psi.PsiParentClass +import org.domaframework.doma.intellij.common.util.DomaClassName + +class ValidationMethodBiFunctionParamResult( + override val identify: PsiElement?, + override val shortName: String = "", + private val index: Int, +) : ValidationResult(identify, null, shortName) { + override fun setHighlight( + highlightRange: TextRange, + identify: PsiElement, + holder: ProblemsHolder, + parent: PsiParentClass?, + ) { + val project = identify.project + holder.registerProblem( + identify, + getCheckParamIndexMessage(index), + problemHighlightType(project, shortName), + highlightRange, + ) + } + + private fun getCheckParamIndexMessage(index: Int): String = + when (index) { + 0 -> "The first type argument of BiFunction must be ${DomaClassName.CONFIG.className}" + 1 -> "The second type argument of BiFunction must be ${DomaClassName.PREPARED_SQL.className}" + + else -> "The type argument at index $index is not supported" + } +} diff --git a/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationMethodHasRequireClassParamResult.kt b/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationMethodHasRequireClassParamResult.kt new file mode 100644 index 00000000..b4d96309 --- /dev/null +++ b/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationMethodHasRequireClassParamResult.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 +import org.domaframework.doma.intellij.extension.psi.DomaAnnotationType + +class ValidationMethodHasRequireClassParamResult( + override val identify: PsiElement?, + override val shortName: String = "", + private val annotationType: DomaAnnotationType, + private val requiredClass: 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.params.require.type", annotationType.name, requiredClass), + problemHighlightType(project, shortName), + highlightRange, + ) + } +} diff --git a/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationMethodNotSelectStreamParamResult.kt b/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationMethodNotSelectStreamParamResult.kt new file mode 100644 index 00000000..8d20fcc6 --- /dev/null +++ b/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationMethodNotSelectStreamParamResult.kt @@ -0,0 +1,42 @@ +/* + * 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 ValidationMethodNotSelectStreamParamResult( + 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.select.param.notFound.strategy.stream"), + problemHighlightType(project, shortName), + highlightRange, + ) + } +} diff --git a/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationMethodParamEntityResult.kt b/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationMethodParamEntityResult.kt new file mode 100644 index 00000000..d1db7aec --- /dev/null +++ b/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationMethodParamEntityResult.kt @@ -0,0 +1,42 @@ +/* + * 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 ValidationMethodParamEntityResult( + 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.params.entity"), + problemHighlightType(project, shortName), + highlightRange, + ) + } +} diff --git a/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationMethodParamsCountResult.kt b/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationMethodParamsCountResult.kt new file mode 100644 index 00000000..76747699 --- /dev/null +++ b/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationMethodParamsCountResult.kt @@ -0,0 +1,42 @@ +/* + * 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 ValidationMethodParamsCountResult( + 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.params.count"), + problemHighlightType(project, shortName), + highlightRange, + ) + } +} diff --git a/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationMethodParamsEmptyResult.kt b/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationMethodParamsEmptyResult.kt new file mode 100644 index 00000000..4ab34ca5 --- /dev/null +++ b/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationMethodParamsEmptyResult.kt @@ -0,0 +1,42 @@ +/* + * 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 ValidationMethodParamsEmptyResult( + 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.params.empty"), + problemHighlightType(project, shortName), + highlightRange, + ) + } +} diff --git a/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationMethodParamsIterableEntityResult.kt b/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationMethodParamsIterableEntityResult.kt new file mode 100644 index 00000000..3a36ad82 --- /dev/null +++ b/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationMethodParamsIterableEntityResult.kt @@ -0,0 +1,42 @@ +/* + * 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 ValidationMethodParamsIterableEntityResult( + 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.params.require.iterable.entity"), + problemHighlightType(project, shortName), + highlightRange, + ) + } +} diff --git a/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationMethodParamsProcedureAnnotationResult.kt b/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationMethodParamsProcedureAnnotationResult.kt new file mode 100644 index 00000000..ab6632bb --- /dev/null +++ b/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationMethodParamsProcedureAnnotationResult.kt @@ -0,0 +1,42 @@ +/* + * 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 ValidationMethodParamsProcedureAnnotationResult( + 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.procedure.params.require.annotation"), + problemHighlightType(project, shortName), + highlightRange, + ) + } +} diff --git a/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationMethodParamsProcedureInTypeResult.kt b/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationMethodParamsProcedureInTypeResult.kt new file mode 100644 index 00000000..48c16dd5 --- /dev/null +++ b/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationMethodParamsProcedureInTypeResult.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 ValidationMethodParamsProcedureInTypeResult( + override val identify: PsiElement?, + override val shortName: String = "", + private val validaType: 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.procedure.params.in.type", validaType), + problemHighlightType(project, shortName), + highlightRange, + ) + } +} diff --git a/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationMethodProcedureParamTypeResult.kt b/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationMethodProcedureParamTypeResult.kt new file mode 100644 index 00000000..fec04828 --- /dev/null +++ b/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationMethodProcedureParamTypeResult.kt @@ -0,0 +1,44 @@ +/* + * 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 +import org.domaframework.doma.intellij.inspection.dao.processor.cheker.ProcedureFunctionParamAnnotationType + +class ValidationMethodProcedureParamTypeResult( + override val identify: PsiElement?, + override val shortName: String = "", + private val annotationType: ProcedureFunctionParamAnnotationType, +) : 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.procedure.params.type", annotationType.name, annotationType.requireType), + problemHighlightType(project, shortName), + highlightRange, + ) + } +} diff --git a/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationMethodProcedureParamsSupportGenericParamResult.kt b/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationMethodProcedureParamsSupportGenericParamResult.kt new file mode 100644 index 00000000..88c97348 --- /dev/null +++ b/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationMethodProcedureParamsSupportGenericParamResult.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 ValidationMethodProcedureParamsSupportGenericParamResult( + override val identify: PsiElement?, + override val shortName: String = "", + private val paramTypeName: String, + private val requireTypeName: 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.procedure.params.support.generic.param", + paramTypeName, + requireTypeName, + ), + problemHighlightType(project, shortName), + highlightRange, + ) + } +} diff --git a/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationMethodSelectStrategyParamResult.kt b/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationMethodSelectStrategyParamResult.kt new file mode 100644 index 00000000..67f83017 --- /dev/null +++ b/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationMethodSelectStrategyParamResult.kt @@ -0,0 +1,44 @@ +/* + * 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 ValidationMethodSelectStrategyParamResult( + override val identify: PsiElement?, + override val shortName: String = "", + private val selectTypeName: String, + private val requireClassName: 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.select.param.strategy.require.type", selectTypeName, requireClassName), + 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/ValidationReturnTypeUpdateReturningResult.kt similarity index 97% rename from src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationReturnTypeForReturningResult.kt rename to src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationReturnTypeUpdateReturningResult.kt index 83500698..305bd39e 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationReturnTypeForReturningResult.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/common/validation/result/ValidationReturnTypeUpdateReturningResult.kt @@ -21,7 +21,7 @@ import com.intellij.psi.PsiElement import org.domaframework.doma.intellij.bundle.MessageBundle import org.domaframework.doma.intellij.common.psi.PsiParentClass -class ValidationReturnTypeForReturningResult( +class ValidationReturnTypeUpdateReturningResult( private val paramClassName: String, override val identify: PsiElement?, override val shortName: String = "", diff --git a/src/main/kotlin/org/domaframework/doma/intellij/extension/ProjectExtensions.kt b/src/main/kotlin/org/domaframework/doma/intellij/extension/ProjectExtensions.kt index e900a9ef..cd78c5e1 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/extension/ProjectExtensions.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/extension/ProjectExtensions.kt @@ -41,12 +41,13 @@ fun Project.findFile(file: VirtualFile): PsiFile? = PsiManager.getInstance(this) fun Project.getJavaClazz(fqdn: String): PsiClass? { val scope = GlobalSearchScope.allScope(this) + val topClassName = fqdn.substringBefore("<") return JavaPsiFacade .getInstance(this) - .findClasses(fqdn, scope) + .findClasses(topClassName, scope) .firstOrNull() ?: JavaPsiFacade.getInstance(this).findClass( - fqdn, + topClassName, GlobalSearchScope.allScope(this), ) } 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 9c6a0d02..db3e42af 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 @@ -33,6 +33,7 @@ enum class DomaAnnotationType( BatchDelete("org.seasar.doma.BatchDelete"), MultiInsert("org.seasar.doma.MultiInsert"), Procedure("org.seasar.doma.Procedure"), + Function("org.seasar.doma.Function"), Select("org.seasar.doma.Select"), Insert("org.seasar.doma.Insert"), Update("org.seasar.doma.Update"), 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 a2019983..96582cb9 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 @@ -23,6 +23,7 @@ import com.intellij.psi.PsiMethod import com.intellij.psi.PsiModifier import com.intellij.psi.util.PsiTypesUtil import org.domaframework.doma.intellij.common.psi.PropertyModifyUtil +import org.domaframework.doma.intellij.common.util.DomaClassName val PsiClass.psiClassType: PsiClassType get() = PsiTypesUtil.getClassType(this) @@ -41,8 +42,21 @@ fun PsiClass.findStaticMethod(searchName: String): PsiMethod? = it.hasModifierProperty(PsiModifier.PUBLIC) } -fun PsiClass.getEntityAnnotation(): PsiAnnotation? = +fun PsiClass.getClassAnnotation(annotationClassName: String): PsiAnnotation? = this.annotations - .firstOrNull { it.qualifiedName == "org.seasar.doma.Entity" } + .firstOrNull { it.qualifiedName == annotationClassName } -fun PsiClass.isEntity(): Boolean = this.getEntityAnnotation() != null +fun PsiClass.isEntity(): Boolean = this.getClassAnnotation(DomaClassName.ENTITY.className) != null + +fun PsiClass.isDomain(): Boolean = this.getClassAnnotation(DomaClassName.DOMAIN.className) != null + +fun PsiClassType.getSuperType(superClassName: String): PsiClassType? { + var parent: PsiClassType? = this + while (parent != null && !parent.canonicalText.startsWith(superClassName)) { + parent = + parent.superTypes.find { superType -> + superType.canonicalText.startsWith(superClassName) + } as? PsiClassType + } + return parent +} diff --git a/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/inspector/DaoMethodParamTypeInspection.kt b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/inspector/DaoMethodParamTypeInspection.kt new file mode 100644 index 00000000..500f1739 --- /dev/null +++ b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/inspector/DaoMethodParamTypeInspection.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.DaoMethodParamTypeInspectionVisitor + +class DaoMethodParamTypeInspection : AbstractBaseJavaLocalInspectionTool() { + override fun getDisplayName(): String = "Check parameter type variable of DAO method" + + override fun getShortName(): String = "org.domaframework.doma.intellij.param" + + override fun getGroupDisplayName(): String = "DomaTools" + + override fun isEnabledByDefault(): Boolean = true + + override fun getDefaultLevel(): HighlightDisplayLevel = HighlightDisplayLevel.ERROR + + override fun buildVisitor( + holder: ProblemsHolder, + isOnTheFly: Boolean, + ): PsiElementVisitor = DaoMethodParamTypeInspectionVisitor(holder, this.shortName) +} 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/DaoMethodReturnTypeInspection.kt similarity index 86% rename from src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/inspector/DaoMethodReturnTypeVariableInspection.kt rename to src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/inspector/DaoMethodReturnTypeInspection.kt index f0693b21..1346d673 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/inspector/DaoMethodReturnTypeVariableInspection.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/inspector/DaoMethodReturnTypeInspection.kt @@ -19,9 +19,9 @@ 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 +import org.domaframework.doma.intellij.inspection.dao.visitor.DaoMethodReturnTypeInspectionVisitor -class DaoMethodReturnTypeVariableInspection : AbstractBaseJavaLocalInspectionTool() { +class DaoMethodReturnTypeInspection : AbstractBaseJavaLocalInspectionTool() { override fun getDisplayName(): String = "Check return type variable of DAO method" override fun getShortName(): String = "org.domaframework.doma.intellij.returnType" @@ -35,5 +35,5 @@ class DaoMethodReturnTypeVariableInspection : AbstractBaseJavaLocalInspectionToo override fun buildVisitor( holder: ProblemsHolder, isOnTheFly: Boolean, - ): PsiElementVisitor = DaoMethodReturnTypeVariableInspectionVisitor(holder, this.shortName) + ): PsiElementVisitor = DaoMethodReturnTypeInspectionVisitor(holder, this.shortName) } diff --git a/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/inspector/UsedDaoMethodArgsVariableInspection.kt b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/inspector/UsedDaoMethodParamInspection.kt similarity index 88% rename from src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/inspector/UsedDaoMethodArgsVariableInspection.kt rename to src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/inspector/UsedDaoMethodParamInspection.kt index 262808b8..53b34ef3 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/inspector/UsedDaoMethodArgsVariableInspection.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/inspector/UsedDaoMethodParamInspection.kt @@ -19,12 +19,12 @@ 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.UsedDaoMethodArgsVariableInspectionVisitor +import org.domaframework.doma.intellij.inspection.dao.visitor.UsedDaoMethodParamInspectionVisitor /** * Check if DAO method arguments are used in the corresponding SQL file */ -class UsedDaoMethodArgsVariableInspection : AbstractBaseJavaLocalInspectionTool() { +class UsedDaoMethodParamInspection : 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 UsedDaoMethodArgsVariableInspection : AbstractBaseJavaLocalInspectionTool( override fun buildVisitor( holder: ProblemsHolder, isOnTheFly: Boolean, - ): PsiElementVisitor = UsedDaoMethodArgsVariableInspectionVisitor(holder) + ): PsiElementVisitor = UsedDaoMethodParamInspectionVisitor(holder) } diff --git a/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/TypeCheckerProcessor.kt b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/TypeCheckerProcessor.kt new file mode 100644 index 00000000..af81889e --- /dev/null +++ b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/TypeCheckerProcessor.kt @@ -0,0 +1,95 @@ +/* + * 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.PsiAnnotation +import com.intellij.psi.PsiClassType +import com.intellij.psi.PsiField +import com.intellij.psi.PsiReferenceExpression +import com.intellij.psi.PsiType +import org.domaframework.doma.intellij.common.psi.PsiDaoMethod +import org.domaframework.doma.intellij.common.psi.PsiTypeChecker +import org.domaframework.doma.intellij.common.util.DomaClassName +import org.domaframework.doma.intellij.extension.getJavaClazz +import org.domaframework.doma.intellij.extension.psi.isDomain + +abstract class TypeCheckerProcessor( + psiDaoMethod: PsiDaoMethod, +) { + protected val method = psiDaoMethod.psiMethod + protected val project = method.project + + protected fun getAnnotation(fqName: String): PsiAnnotation? = method.annotations.find { it.qualifiedName == fqName } + + protected fun getDaoAnnotationOption( + psiAnnotation: PsiAnnotation, + findOptionName: String, + ): PsiAnnotation? { + val returningOption = + psiAnnotation.parameterList.attributes + .firstOrNull { param -> + param.name == findOptionName + }?.value as? PsiAnnotation + + return returningOption + } + + protected fun getDaoPsiReferenceOption( + psiAnnotation: PsiAnnotation, + findOptionName: String, + ): PsiField? { + val strategy = + psiAnnotation.parameterList.attributes + .firstOrNull { param -> + param.name == findOptionName + }?.value as? PsiReferenceExpression + + val field = strategy?.reference?.resolve() as? PsiField + + return field + } + + open fun checkParamType(paramType: PsiType): Boolean { + if (PsiTypeChecker.isBaseClassType(paramType)) return true + + if (DomaClassName.isOptionalWrapperType(paramType.canonicalText)) { + return true + } + + if (DomaClassName.OPTIONAL.isTargetClassNameStartsWith(paramType.canonicalText)) { + val paramClassType = paramType as? PsiClassType ?: return false + val optionalParam = paramClassType.parameters.firstOrNull() + return optionalParam?.let { + val optionalParamClass = project.getJavaClazz(it.canonicalText) + optionalParamClass?.isDomain() == true || PsiTypeChecker.isBaseClassType(it) + } == true + } + + val paramClass = project.getJavaClazz(paramType.canonicalText) + return paramClass?.isDomain() == true + } + + protected fun checkMapType(paramTypeCanonicalText: String): Boolean { + val mapClassName = paramTypeCanonicalText.replace(" ", "") + val mapExpectedType = + DomaClassName.MAP + .getGenericParamCanonicalText( + DomaClassName.STRING.className, + DomaClassName.OBJECT.className, + ).replace(" ", "") + return mapClassName != mapExpectedType + } +} diff --git a/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/cheker/ProcedureFunctionInOutParamAnnotationTypeChecker.kt b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/cheker/ProcedureFunctionInOutParamAnnotationTypeChecker.kt new file mode 100644 index 00000000..a332dea5 --- /dev/null +++ b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/cheker/ProcedureFunctionInOutParamAnnotationTypeChecker.kt @@ -0,0 +1,69 @@ +/* + * 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.cheker + +import com.intellij.codeInspection.ProblemsHolder +import com.intellij.openapi.project.Project +import com.intellij.psi.PsiClassType +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiType +import org.domaframework.doma.intellij.common.psi.PsiDaoMethod +import org.domaframework.doma.intellij.common.util.DomaClassName +import org.domaframework.doma.intellij.common.validation.result.ValidationMethodProcedureParamTypeResult +import org.domaframework.doma.intellij.common.validation.result.ValidationMethodProcedureParamsSupportGenericParamResult + +class ProcedureFunctionInOutParamAnnotationTypeChecker( + private val annotationType: ProcedureFunctionParamAnnotationType, + psiDaoMethod: PsiDaoMethod, +) : ProcedureFunctionParamAnnotationTypeChecker(psiDaoMethod) { + override fun checkParam( + identifier: PsiElement, + paramType: PsiType, + project: Project, + shortName: String, + holder: ProblemsHolder, + ) { + // Check if the parameter type is a valid reference type + if (!DomaClassName.REFERENCE.isTargetClassNameStartsWith(paramType.canonicalText)) { + ValidationMethodProcedureParamTypeResult( + identifier, + shortName, + annotationType, + ).highlightElement(holder) + return + } + + // Check if the parameter type is a valid reference type with generic parameters + val referenceParamType = (paramType as? PsiClassType)?.parameters?.firstOrNull() + if (referenceParamType == null) { + ValidationMethodProcedureParamsSupportGenericParamResult( + identifier, + shortName, + "Unknown", + annotationType.requireType, + ).highlightElement(holder) + return + } + + if (checkParamType(referenceParamType)) return + ValidationMethodProcedureParamsSupportGenericParamResult( + identifier, + shortName, + referenceParamType.canonicalText, + annotationType.requireType, + ).highlightElement(holder) + } +} diff --git a/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/cheker/ProcedureFunctionInParamAnnotationTypeChecker.kt b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/cheker/ProcedureFunctionInParamAnnotationTypeChecker.kt new file mode 100644 index 00000000..c9e8aff4 --- /dev/null +++ b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/cheker/ProcedureFunctionInParamAnnotationTypeChecker.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.inspection.dao.processor.cheker + +import com.intellij.codeInspection.ProblemsHolder +import com.intellij.openapi.project.Project +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiType +import org.domaframework.doma.intellij.common.psi.PsiDaoMethod +import org.domaframework.doma.intellij.common.validation.result.ValidationMethodParamsProcedureInTypeResult + +class ProcedureFunctionInParamAnnotationTypeChecker( + psiDaoMethod: PsiDaoMethod, +) : ProcedureFunctionParamAnnotationTypeChecker(psiDaoMethod) { + override fun checkParam( + identifier: PsiElement, + paramType: PsiType, + project: Project, + shortName: String, + holder: ProblemsHolder, + ) { + if (checkParamType(paramType)) return + + ValidationMethodParamsProcedureInTypeResult( + identifier, + shortName, + paramType.presentableText, + ).highlightElement(holder) + } +} diff --git a/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/cheker/ProcedureFunctionParamAnnotationType.kt b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/cheker/ProcedureFunctionParamAnnotationType.kt new file mode 100644 index 00000000..9a69b324 --- /dev/null +++ b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/cheker/ProcedureFunctionParamAnnotationType.kt @@ -0,0 +1,67 @@ +/* + * 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.cheker + +import com.intellij.codeInspection.ProblemsHolder +import com.intellij.openapi.project.Project +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiType +import org.domaframework.doma.intellij.common.psi.PsiDaoMethod +import org.domaframework.doma.intellij.common.util.DomaClassName + +enum class ProcedureFunctionParamAnnotationType( + val fqdn: String, + val requireType: String, + val checkParamType: ( + psiDaoMethod: PsiDaoMethod, + identifier: PsiElement, + paramType: PsiType, + project: Project, + shortName: String, + holder: ProblemsHolder, + ) -> Unit, +) { + In("org.seasar.doma.In", "", { psiDaoMethod, identifier, paramType, project, shortName, holder -> + ProcedureFunctionInParamAnnotationTypeChecker(psiDaoMethod).checkParam(identifier, paramType, project, shortName, holder) + }), + InOut( + "org.seasar.doma.InOut", + DomaClassName.REFERENCE.className, + { psiDaoMethod, identifier, paramType, project, shortName, holder -> + ProcedureFunctionInOutParamAnnotationTypeChecker( + InOut, + psiDaoMethod, + ).checkParam(identifier, paramType, project, shortName, holder) + }, + ), + Out( + "org.seasar.doma.Out", + DomaClassName.REFERENCE.className, + { psiDaoMethod, identifier, paramType, project, shortName, holder -> + ProcedureFunctionInOutParamAnnotationTypeChecker( + Out, + psiDaoMethod, + ).checkParam(identifier, paramType, project, shortName, holder) + }, + ), + ResultSet( + "org.seasar.doma.ResultSet", + DomaClassName.LIST.className, + { psiDaoMethod, identifier, paramType, project, shortName, holder -> + ProcedureFunctionResultSetParamAnnotationTypeChecker(psiDaoMethod).checkParam(identifier, paramType, project, shortName, holder) + }, + ), +} diff --git a/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/cheker/ProcedureFunctionParamAnnotationTypeChecker.kt b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/cheker/ProcedureFunctionParamAnnotationTypeChecker.kt new file mode 100644 index 00000000..480903e7 --- /dev/null +++ b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/cheker/ProcedureFunctionParamAnnotationTypeChecker.kt @@ -0,0 +1,35 @@ +/* + * 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.cheker + +import com.intellij.codeInspection.ProblemsHolder +import com.intellij.openapi.project.Project +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiType +import org.domaframework.doma.intellij.common.psi.PsiDaoMethod +import org.domaframework.doma.intellij.inspection.dao.processor.TypeCheckerProcessor + +abstract class ProcedureFunctionParamAnnotationTypeChecker( + psiDaoMethod: PsiDaoMethod, +) : TypeCheckerProcessor(psiDaoMethod) { + abstract fun checkParam( + identifier: PsiElement, + paramType: PsiType, + project: Project, + shortName: String, + holder: ProblemsHolder, + ) +} diff --git a/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/cheker/ProcedureFunctionResultSetParamAnnotationTypeChecker.kt b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/cheker/ProcedureFunctionResultSetParamAnnotationTypeChecker.kt new file mode 100644 index 00000000..4f706528 --- /dev/null +++ b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/cheker/ProcedureFunctionResultSetParamAnnotationTypeChecker.kt @@ -0,0 +1,107 @@ +/* + * 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.cheker + +import com.intellij.codeInspection.ProblemsHolder +import com.intellij.openapi.project.Project +import com.intellij.psi.PsiClassType +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiType +import org.domaframework.doma.intellij.common.psi.PsiDaoMethod +import org.domaframework.doma.intellij.common.psi.PsiTypeChecker +import org.domaframework.doma.intellij.common.util.DomaClassName +import org.domaframework.doma.intellij.common.validation.result.ValidationMethodProcedureParamTypeResult +import org.domaframework.doma.intellij.common.validation.result.ValidationMethodProcedureParamsSupportGenericParamResult +import org.domaframework.doma.intellij.extension.getJavaClazz +import org.domaframework.doma.intellij.extension.psi.isDomain +import org.domaframework.doma.intellij.extension.psi.isEntity + +class ProcedureFunctionResultSetParamAnnotationTypeChecker( + psiDaoMethod: PsiDaoMethod, +) : ProcedureFunctionParamAnnotationTypeChecker(psiDaoMethod) { + override fun checkParamType(paramType: PsiType): Boolean { + if (PsiTypeChecker.isBaseClassType(paramType)) return true + + if (DomaClassName.isOptionalWrapperType(paramType.canonicalText)) { + return true + } + + if (DomaClassName.OPTIONAL.isTargetClassNameStartsWith(paramType.canonicalText)) { + val paramClassType = paramType as? PsiClassType ?: return false + val optionalParam = paramClassType.parameters.firstOrNull() + return optionalParam?.let { + val optionalParamClass = project.getJavaClazz(it.canonicalText) + optionalParamClass?.isDomain() == true || + optionalParamClass?.isEntity() == true || + PsiTypeChecker.isBaseClassType( + it, + ) + } == true + } + + val paramClass = project.getJavaClazz(paramType.canonicalText) + return paramClass?.isDomain() == true + } + + override fun checkParam( + identifier: PsiElement, + paramType: PsiType, + project: Project, + shortName: String, + holder: ProblemsHolder, + ) { + val annotationType = ProcedureFunctionParamAnnotationType.ResultSet + // Check if the parameter type is a valid List type + if (!DomaClassName.LIST.isTargetClassNameStartsWith(paramType.canonicalText)) { + ValidationMethodProcedureParamTypeResult( + identifier, + shortName, + annotationType, + ).highlightElement(holder) + return + } + + // Check if the parameter type is a valid List type with generic parameters + val listParamType = (paramType as? PsiClassType)?.parameters?.firstOrNull() + if (listParamType == null) { + ValidationMethodProcedureParamsSupportGenericParamResult( + identifier, + shortName, + "Unknown", + annotationType.requireType, + ).highlightElement(holder) + return + } + + val listCanonicalText = listParamType.canonicalText + val result = + ValidationMethodProcedureParamsSupportGenericParamResult( + identifier, + shortName, + listCanonicalText, + annotationType.requireType, + ) + if (DomaClassName.MAP.isTargetClassNameStartsWith(listCanonicalText)) { + if (checkMapType(listCanonicalText)) result.highlightElement(holder) + return + } + + val paramClass = project.getJavaClazz(listParamType.canonicalText) + + if (checkParamType(listParamType) || paramClass?.isEntity() == true) return + result.highlightElement(holder) + } +} diff --git a/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/paramtype/BatchParamTypeCheckProcessor.kt b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/paramtype/BatchParamTypeCheckProcessor.kt new file mode 100644 index 00000000..60e2cfd8 --- /dev/null +++ b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/paramtype/BatchParamTypeCheckProcessor.kt @@ -0,0 +1,100 @@ +/* + * 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.paramtype + +import com.intellij.codeInspection.ProblemsHolder +import com.intellij.psi.PsiClassType +import org.domaframework.doma.intellij.common.psi.PsiDaoMethod +import org.domaframework.doma.intellij.common.sql.PsiClassTypeUtil +import org.domaframework.doma.intellij.common.validation.result.ValidationMethodParamsCountResult +import org.domaframework.doma.intellij.common.validation.result.ValidationMethodParamsIterableEntityResult +import org.domaframework.doma.intellij.extension.getJavaClazz +import org.domaframework.doma.intellij.extension.psi.isEntity +import org.domaframework.doma.intellij.extension.psi.psiClassType + +/** + * Processor for checking the parameter types of DAO methods annotated with batch annotations. + * + * This class validates the parameters of DAO methods to ensure they meet the requirements + * for methods annotated with batch annotations. It performs checks such as: + * - Ensuring the method has exactly one parameter. + * - Verifying that the parameter is an iterable of entity types. + * + * @property psiDaoMethod The DAO method to be checked. + * @property shortName The short name of the annotation being processed. + */ +class BatchParamTypeCheckProcessor( + private val psiDaoMethod: PsiDaoMethod, + private val shortName: String, +) : ParamTypeCheckProcessor(psiDaoMethod, shortName) { + /** + * Checks the parameters of the DAO method. + * + * This method validates the parameters of the DAO method to ensure compliance + * with the requirements for methods annotated with batch annotations. + * + * @param holder The ProblemsHolder instance used to report validation issues. + */ + override fun checkParams(holder: ProblemsHolder) { + // Check if the method has exactly one parameter + checkMethodCount()?.let { result -> + result.highlightElement(holder) + return + } + + // Check if the parameter is an entity + val param = method.parameterList.parameters.firstOrNull() + if (param == null) { + ValidationMethodParamsCountResult( + method.nameIdentifier ?: return, + shortName, + ).highlightElement(holder) + return + } + + val identifier = param.nameIdentifier ?: return + val resultParamType = + ValidationMethodParamsIterableEntityResult( + identifier, + shortName, + ) + + project.getJavaClazz(param.type.canonicalText)?.let { paramClass -> + val paramClassType = paramClass.psiClassType + if (!PsiClassTypeUtil.isIterableType( + paramClassType, + project, + ) + ) { + resultParamType.highlightElement(holder) + return + } + } + + val iterableClassType = param.type as? PsiClassType + iterableClassType?.parameters?.firstOrNull()?.let { iterableParam -> + project + .getJavaClazz(iterableParam.canonicalText) + ?.let { + if (!it.isEntity()) { + resultParamType.highlightElement(holder) + } + } + return + } + resultParamType.highlightElement(holder) + } +} diff --git a/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/paramtype/MultiInsertParamTypeCheckProcessor.kt b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/paramtype/MultiInsertParamTypeCheckProcessor.kt new file mode 100644 index 00000000..8cd5d387 --- /dev/null +++ b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/paramtype/MultiInsertParamTypeCheckProcessor.kt @@ -0,0 +1,100 @@ +/* + * 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.paramtype + +import com.intellij.codeInspection.ProblemsHolder +import com.intellij.psi.PsiClassType +import org.domaframework.doma.intellij.common.psi.PsiDaoMethod +import org.domaframework.doma.intellij.common.sql.PsiClassTypeUtil +import org.domaframework.doma.intellij.common.validation.result.ValidationMethodParamsCountResult +import org.domaframework.doma.intellij.common.validation.result.ValidationMethodParamsIterableEntityResult +import org.domaframework.doma.intellij.extension.getJavaClazz +import org.domaframework.doma.intellij.extension.psi.isEntity +import org.domaframework.doma.intellij.extension.psi.psiClassType + +/** + * Processor for checking the parameter types of DAO methods annotated with @MultiInsert. + * + * This class validates the parameters of DAO methods to ensure they meet the requirements + * for methods annotated with @MultiInsert. It performs checks such as: + * - Ensuring the method has exactly one parameter. + * - Verifying that the parameter is an iterable of entity types. + * + * @property psiDaoMethod The DAO method to be checked. + * @property shortName The short name of the annotation being processed. + */ +class MultiInsertParamTypeCheckProcessor( + psiDaoMethod: PsiDaoMethod, + private val shortName: String, +) : ParamTypeCheckProcessor(psiDaoMethod, shortName) { + /** + * Checks the parameters of the DAO method. + * + * This method validates the parameters of the DAO method to ensure compliance + * with the requirements for methods annotated with @MultiInsert. + * + * @param holder The ProblemsHolder instance used to report validation issues. + */ + override fun checkParams(holder: ProblemsHolder) { + // Check if the method has exactly one parameter + checkMethodCount()?.let { result -> + result.highlightElement(holder) + return + } + + // Check if the parameter is an entity + val param = method.parameterList.parameters.firstOrNull() + if (param == null) { + ValidationMethodParamsCountResult( + method.nameIdentifier ?: return, + shortName, + ).highlightElement(holder) + return + } + + val paramIdentity = param.nameIdentifier ?: return + val resultParamType = + ValidationMethodParamsIterableEntityResult( + paramIdentity, + shortName, + ) + + project.getJavaClazz(param.type.canonicalText)?.let { paramClass -> + val paramClassType = paramClass.psiClassType + if (!PsiClassTypeUtil.isIterableType( + paramClassType, + project, + ) + ) { + resultParamType.highlightElement(holder) + return + } + } + + val iterableClassType = param.type as? PsiClassType + iterableClassType?.parameters?.firstOrNull()?.let { iterableParam -> + project + .getJavaClazz(iterableParam.canonicalText) + ?.let { + if (!it.isEntity()) { + resultParamType.highlightElement(holder) + } + } + return + } + resultParamType.highlightElement(holder) + } +} diff --git a/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/paramtype/ParamTypeCheckProcessor.kt b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/paramtype/ParamTypeCheckProcessor.kt new file mode 100644 index 00000000..a6c2a944 --- /dev/null +++ b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/paramtype/ParamTypeCheckProcessor.kt @@ -0,0 +1,64 @@ +/* + * 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.paramtype + +import com.intellij.codeInspection.ProblemsHolder +import org.domaframework.doma.intellij.common.psi.PsiDaoMethod +import org.domaframework.doma.intellij.common.validation.result.ValidationMethodParamsCountResult +import org.domaframework.doma.intellij.common.validation.result.ValidationResult +import org.domaframework.doma.intellij.inspection.dao.processor.TypeCheckerProcessor + +/** + * Abstract base class for checking the parameter types of DAO methods. + * + * This class provides common functionality for validating the parameters of DAO methods + * in various annotation processors. Subclasses should implement the `checkParams` method + * to perform specific validation logic. + * + * @property psiDaoMethod The DAO method to be checked. + * @property shortName The short name of the annotation being processed. + */ +abstract class ParamTypeCheckProcessor( + psiDaoMethod: PsiDaoMethod, + private val shortName: String, +) : TypeCheckerProcessor(psiDaoMethod) { + /** + * Abstract method for checking the parameters of the DAO method. + * + * Subclasses should implement this method to perform specific validation logic. + * + * @param holder The ProblemsHolder instance used to report validation issues. + */ + abstract fun checkParams(holder: ProblemsHolder) + + /** + * Checks if the method has the correct number of parameters. + * + * By default, this method checks if the method has exactly one parameter. + * Subclasses can override this method to provide custom logic. + * + * @return A ValidationResult if the parameter count is invalid, or null if valid. + */ + protected open fun checkMethodCount(): ValidationResult? = + if (method.parameterList.parameters.size != 1) { + ValidationMethodParamsCountResult( + method.nameIdentifier, + shortName, + ) + } else { + null + } +} diff --git a/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/paramtype/ProcedureParamTypeCheckProcessor.kt b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/paramtype/ProcedureParamTypeCheckProcessor.kt new file mode 100644 index 00000000..f4a4f635 --- /dev/null +++ b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/paramtype/ProcedureParamTypeCheckProcessor.kt @@ -0,0 +1,85 @@ +/* + * 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.paramtype + +import com.intellij.codeInspection.ProblemsHolder +import com.intellij.psi.PsiParameter +import org.domaframework.doma.intellij.common.psi.PsiDaoMethod +import org.domaframework.doma.intellij.common.validation.result.ValidationMethodParamsProcedureAnnotationResult +import org.domaframework.doma.intellij.inspection.dao.processor.cheker.ProcedureFunctionParamAnnotationType + +/** + * Processor for checking the parameter types of DAO methods annotated with @Procedure. + * + * This class validates the parameters of DAO methods to ensure they meet the requirements + * for methods annotated with @Procedure. It performs checks such as: + * - Ensuring each parameter has a valid annotation. + * - Validating the parameter types based on the annotation. + * + * @property psiDaoMethod The DAO method to be checked. + * @property shortName The short name of the annotation being processed. + */ +class ProcedureParamTypeCheckProcessor( + psiDaoMethod: PsiDaoMethod, + private val shortName: String, +) : ParamTypeCheckProcessor(psiDaoMethod, shortName) { + /** + * Checks the parameters of the DAO method. + * + * This method validates the parameters of the DAO method to ensure compliance + * with the requirements for methods annotated with @Procedure. + * + * @param holder The ProblemsHolder instance used to report validation issues. + */ + override fun checkParams(holder: ProblemsHolder) { + val params = method.parameterList.parameters + var paramAnnotationType: ProcedureFunctionParamAnnotationType? = null + val psiDaoMethod = PsiDaoMethod(method.project, method) + params.forEach { param: PsiParameter -> + val paramAnnotation = + param.annotations.firstOrNull { annotation -> + paramAnnotationType = + ProcedureFunctionParamAnnotationType.entries.find { it.fqdn == annotation.qualifiedName } + paramAnnotationType != null + } + if (paramAnnotation == null || paramAnnotationType == null) { + ValidationMethodParamsProcedureAnnotationResult( + param.nameIdentifier ?: return, + shortName, + ).highlightElement(holder) + return + } + checkParamType(psiDaoMethod, paramAnnotationType, param, holder) + } + } + + /** + * Validates the type of parameter based on its annotation. + * + * @param paramAnnotationType The type of the annotation on the parameter. + * @param param The parameter to be validated. + * @param holder The ProblemsHolder instance used to report validation issues. + */ + private fun checkParamType( + psiDaoMethod: PsiDaoMethod, + paramAnnotationType: ProcedureFunctionParamAnnotationType, + param: PsiParameter, + holder: ProblemsHolder, + ) { + val identifier = param.nameIdentifier ?: return + paramAnnotationType.checkParamType(psiDaoMethod, identifier, param.type, param.project, shortName, holder) + } +} diff --git a/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/paramtype/ScriptParamTypeCheckProcessor.kt b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/paramtype/ScriptParamTypeCheckProcessor.kt new file mode 100644 index 00000000..7d6d985e --- /dev/null +++ b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/paramtype/ScriptParamTypeCheckProcessor.kt @@ -0,0 +1,67 @@ +/* + * 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.paramtype + +import com.intellij.codeInspection.ProblemsHolder +import org.domaframework.doma.intellij.common.psi.PsiDaoMethod +import org.domaframework.doma.intellij.common.validation.result.ValidationMethodParamsEmptyResult +import org.domaframework.doma.intellij.common.validation.result.ValidationResult + +/** + * Processor for checking the parameter types of DAO methods annotated with @Script. + * + * This class validates the parameters of DAO methods to ensure they meet the requirements + * for methods annotated with @Script. It performs checks such as: + * - Ensuring the method has no parameters. + * + * @property psiDaoMethod The DAO method to be checked. + * @property shortName The short name of the annotation being processed. + */ +class ScriptParamTypeCheckProcessor( + psiDaoMethod: PsiDaoMethod, + private val shortName: String, +) : ParamTypeCheckProcessor(psiDaoMethod, shortName) { + /** + * Checks the parameters of the DAO method. + * + * This method validates the parameters of the DAO method to ensure compliance + * with the requirements for methods annotated with @Script. + * + * @param holder The ProblemsHolder instance used to report validation issues. + */ + override fun checkParams(holder: ProblemsHolder) { + checkMethodCount()?.highlightElement(holder) + } + + /** + * Checks if the method has the correct number of parameters. + * + * This method ensures that the method has no parameters. + * + * @return A ValidationResult if the parameter count is invalid, or null if valid. + */ + override fun checkMethodCount(): ValidationResult? { + // Script methods should not have any parameters + return if (method.parameterList.parameters.isNotEmpty()) { + ValidationMethodParamsEmptyResult( + method.nameIdentifier, + shortName, + ) + } else { + null + } + } +} diff --git a/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/paramtype/SelectParamTypeCheckProcessor.kt b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/paramtype/SelectParamTypeCheckProcessor.kt new file mode 100644 index 00000000..45f9c574 --- /dev/null +++ b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/paramtype/SelectParamTypeCheckProcessor.kt @@ -0,0 +1,194 @@ +/* + * 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.paramtype + +import com.intellij.codeInspection.ProblemsHolder +import com.intellij.psi.PsiClassType +import com.intellij.psi.PsiParameter +import com.intellij.psi.PsiType +import org.domaframework.doma.intellij.common.psi.PsiDaoMethod +import org.domaframework.doma.intellij.common.psi.PsiTypeChecker +import org.domaframework.doma.intellij.common.util.DomaClassName +import org.domaframework.doma.intellij.common.validation.result.ValidationMethodNotSelectStreamParamResult +import org.domaframework.doma.intellij.common.validation.result.ValidationMethodProcedureParamsSupportGenericParamResult +import org.domaframework.doma.intellij.common.validation.result.ValidationMethodSelectStrategyParamResult +import org.domaframework.doma.intellij.extension.getJavaClazz +import org.domaframework.doma.intellij.extension.psi.getSuperType +import org.domaframework.doma.intellij.extension.psi.isDomain +import org.domaframework.doma.intellij.extension.psi.isEntity + +class SelectParamTypeCheckProcessor( + private val psiDaoMethod: PsiDaoMethod, + private val shortName: String, +) : ParamTypeCheckProcessor(psiDaoMethod, shortName) { + private class StrategyParam( + val fieldName: String = "", + parentClassName: String?, + ) { + private val isSelectType: Boolean = parentClassName == DomaClassName.SELECT_TYPE.className + + fun isStream(): Boolean = fieldName == "STREAM" && isSelectType + + fun isCollect(): Boolean = fieldName == "COLLECT" && isSelectType + } + + override fun checkParamType(paramType: PsiType): Boolean { + if (PsiTypeChecker.isBaseClassType(paramType)) return true + + if (DomaClassName.isOptionalWrapperType(paramType.canonicalText)) { + return true + } + + if (DomaClassName.OPTIONAL.isTargetClassNameStartsWith(paramType.canonicalText)) { + val paramClassType = paramType as? PsiClassType ?: return false + val optionalParam = paramClassType.parameters.firstOrNull() + return optionalParam?.let { + val optionalParamClass = project.getJavaClazz(it.canonicalText) + optionalParamClass?.isDomain() == true || + PsiTypeChecker.isBaseClassType(it) || + optionalParamClass?.isEntity() == true + } == true + } + + val paramClass = project.getJavaClazz(paramType.canonicalText) + return paramClass?.isDomain() == true || paramClass?.isEntity() == true + } + + override fun checkParams(holder: ProblemsHolder) { + val methodAnnotationFqdn = psiDaoMethod.daoType.fqdn + val methodAnnotation = getAnnotation(methodAnnotationFqdn) ?: return + val strategyOption = getDaoPsiReferenceOption(methodAnnotation, "strategy") + val strategyParam = + if (strategyOption == null) { + null + } else { + StrategyParam( + strategyOption.name, + strategyOption.type.canonicalText, + ) + } + if (strategyParam == null) { + checkStrategyOption(holder) + return + } + + if (strategyParam.isStream()) { + checkStream(holder) + } + + if (strategyParam.isCollect()) { + checkCollect(holder) + } + } + + private fun checkStream(holder: ProblemsHolder) { + val result = + ValidationMethodSelectStrategyParamResult( + method.nameIdentifier, + shortName, + "STREAM", + DomaClassName.JAVA_FUNCTION.getGenericParamCanonicalText(DomaClassName.JAVA_STREAM.className), + ) + val function = getMethodParamTargetType(DomaClassName.JAVA_FUNCTION.className) + if (function == null) { + result.highlightElement(holder) + return + } + + val functionFirstParam = (function.type as? PsiClassType)?.parameters?.firstOrNull() + if (functionFirstParam == null || + !DomaClassName.JAVA_STREAM.isTargetClassNameStartsWith(functionFirstParam.canonicalText) + ) { + result.highlightElement(holder) + return + } + + // Check if the first parameter of the function is a stream type + val streamTargetParam = (functionFirstParam as? PsiClassType)?.parameters?.firstOrNull() + if (streamTargetParam == null) { + generateTargetTypeResult("Unknown").highlightElement(holder) + return + } + + val streamTargetTypeCanonicalText = streamTargetParam.canonicalText + if (DomaClassName.MAP.isTargetClassNameStartsWith(streamTargetTypeCanonicalText)) { + if (checkMapType(streamTargetTypeCanonicalText)) { + generateTargetTypeResult(streamTargetTypeCanonicalText).highlightElement(holder) + } + return + } + + if (!checkParamType(streamTargetParam)) { + generateTargetTypeResult(streamTargetTypeCanonicalText).highlightElement(holder) + } + } + + private fun checkCollect(holder: ProblemsHolder) { + val result = + ValidationMethodSelectStrategyParamResult( + method.nameIdentifier, + shortName, + "COLLECT", + DomaClassName.JAVA_COLLECTOR.className, + ) + val collection = getMethodParamTargetType(DomaClassName.JAVA_COLLECTOR.className) + if (collection == null) { + result.highlightElement(holder) + return + } + + val collectorTargetParam = (collection.type as? PsiClassType)?.parameters?.firstOrNull() + if (collectorTargetParam == null) { + generateTargetTypeResult("Unknown").highlightElement(holder) + return + } + + val streamTargetTypeCanonicalText = collectorTargetParam.canonicalText + if (DomaClassName.MAP.isTargetClassNameStartsWith(streamTargetTypeCanonicalText)) { + if (checkMapType(streamTargetTypeCanonicalText)) { + generateTargetTypeResult(streamTargetTypeCanonicalText).highlightElement(holder) + } + return + } + + if (!checkParamType(collectorTargetParam)) { + generateTargetTypeResult(streamTargetTypeCanonicalText).highlightElement(holder) + } + } + + private fun checkStrategyOption(holder: ProblemsHolder) { + val function = getMethodParamTargetType(DomaClassName.JAVA_FUNCTION.className) + if (function != null) { + ValidationMethodNotSelectStreamParamResult( + method.nameIdentifier, + shortName, + ).highlightElement(holder) + } + } + + private fun getMethodParamTargetType(typeName: String): PsiParameter? = + method.parameterList.parameters.find { param -> + (param.type as? PsiClassType)?.getSuperType(typeName) != null + } + + fun generateTargetTypeResult(streamParamTypeName: String): ValidationMethodProcedureParamsSupportGenericParamResult = + ValidationMethodProcedureParamsSupportGenericParamResult( + method.nameIdentifier, + shortName, + streamParamTypeName, + DomaClassName.JAVA_STREAM.className, + ) +} diff --git a/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/paramtype/SqlProcessorParamTypeCheckProcessor.kt b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/paramtype/SqlProcessorParamTypeCheckProcessor.kt new file mode 100644 index 00000000..4c35b6e5 --- /dev/null +++ b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/paramtype/SqlProcessorParamTypeCheckProcessor.kt @@ -0,0 +1,99 @@ +/* + * 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.paramtype + +import androidx.compose.compiler.plugins.kotlin.lower.fastForEachIndexed +import com.intellij.codeInspection.ProblemsHolder +import com.intellij.psi.PsiClassType +import com.intellij.psi.PsiType +import org.domaframework.doma.intellij.common.psi.PsiDaoMethod +import org.domaframework.doma.intellij.common.util.DomaClassName +import org.domaframework.doma.intellij.common.validation.result.ValidationMethodBiFunctionParamResult +import org.domaframework.doma.intellij.common.validation.result.ValidationMethodHasRequireClassParamResult +import org.domaframework.doma.intellij.extension.psi.DomaAnnotationType + +/** + * Processor for checking the parameter types of DAO methods annotated with @SqlProcessor. + * + * This class validates the parameters of DAO methods to ensure they meet the requirements + * for methods annotated with @SqlProcessor. It performs checks such as: + * - Ensuring the method has a parameter of type BiFunction. + * - Validating the types of the BiFunction parameters. + * + * @property psiDaoMethod The DAO method to be checked. + * @property shortName The short name of the annotation being processed. + */ +class SqlProcessorParamTypeCheckProcessor( + psiDaoMethod: PsiDaoMethod, + private val shortName: String, +) : ParamTypeCheckProcessor(psiDaoMethod, shortName) { + private val biFunctionClassName = DomaClassName.BI_FUNCTION.className + + /** + * Checks the parameters of the DAO method. + * + * This method validates the parameters of the DAO method to ensure compliance + * with the requirements for methods annotated with @SqlProcessor. + * + * @param holder The ProblemsHolder instance used to report validation issues. + */ + override fun checkParams(holder: ProblemsHolder) { + val parameters = method.parameterList.parameters + val biFunctionParam = + parameters.firstOrNull { param -> + param.type.canonicalText.startsWith(biFunctionClassName) + } + if (biFunctionParam == null) { + ValidationMethodHasRequireClassParamResult( + method.nameIdentifier, + shortName, + DomaAnnotationType.SqlProcessor, + "BiFunction", + ).highlightElement(holder) + return + } + + val biFunctionClassType = (biFunctionParam.type as? PsiClassType) + val identifier = biFunctionParam.nameIdentifier ?: return + biFunctionClassType?.parameters?.fastForEachIndexed { index, param -> + if (param == null || !checkBiFunctionParam(index, param)) { + ValidationMethodBiFunctionParamResult( + identifier, + shortName, + index, + ).highlightElement(holder) + } + } + } + + /** + * Validates the type of BiFunction parameter. + * + * @param index The index of the BiFunction parameter. + * @param paramType The type of the BiFunction parameter. + * @return True if the parameter type is valid, false otherwise. + */ + private fun checkBiFunctionParam( + index: Int, + paramType: PsiType, + ): Boolean = + when (index) { + 0 -> paramType.canonicalText == DomaClassName.CONFIG.className + 1 -> paramType.canonicalText == DomaClassName.PREPARED_SQL.className + 2 -> true + else -> false + } +} diff --git a/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/paramtype/UpdateParamTypeCheckProcessor.kt b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/paramtype/UpdateParamTypeCheckProcessor.kt new file mode 100644 index 00000000..a996b6d3 --- /dev/null +++ b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/paramtype/UpdateParamTypeCheckProcessor.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.processor.paramtype + +import com.intellij.codeInspection.ProblemsHolder +import org.domaframework.doma.intellij.common.psi.PsiDaoMethod +import org.domaframework.doma.intellij.common.validation.result.ValidationMethodParamEntityResult +import org.domaframework.doma.intellij.extension.getJavaClazz +import org.domaframework.doma.intellij.extension.psi.isEntity + +/** + * Processor for checking the parameter types of DAO methods annotated with @Insert,@Update,@Delete. + * + * This class validates the parameters of DAO methods to ensure they meet the requirements + * for methods annotated with @Insert,@Update,@Delete. It performs checks such as: + * - Ensuring the method has exactly one parameter. + * - Verifying that the parameter is of an entity type. + * + * @property psiDaoMethod The DAO method to be checked. + * @property shortName The short name of the annotation being processed. + */ +class UpdateParamTypeCheckProcessor( + private val psiDaoMethod: PsiDaoMethod, + private val shortName: String, +) : ParamTypeCheckProcessor(psiDaoMethod, shortName) { + /** + * Checks the parameters of the DAO method. + * + * This method validates the parameters of the DAO method to ensure compliance + * with the requirements for methods annotated with @Insert,@Update,@Delete. If the method uses + * SQL annotations or SQL file options, the validation is skipped. + * + * @param holder The ProblemsHolder instance used to report validation issues. + */ + override fun checkParams(holder: ProblemsHolder) { + if (psiDaoMethod.useSqlAnnotation() || psiDaoMethod.sqlFileOption) { + return + } + + // Check if the method has exactly one parameter + checkMethodCount()?.let { result -> + result.highlightElement(holder) + return + } + + // Check if the method has a parameter of type entity + val param = method.parameterList.parameters.firstOrNull() + val paramClass = project.getJavaClazz(param?.type?.canonicalText ?: "") + val identifier = param?.nameIdentifier ?: return + if (paramClass == null || !paramClass.isEntity()) { + ValidationMethodParamEntityResult( + identifier, + shortName, + ).highlightElement(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/returntype/BatchAnnotationReturnTypeCheckProcessor.kt similarity index 98% rename from src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/BatchAnnotationReturnTypeCheckProcessor.kt rename to src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/returntype/BatchAnnotationReturnTypeCheckProcessor.kt index f97f1677..f8791cd5 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/BatchAnnotationReturnTypeCheckProcessor.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/returntype/BatchAnnotationReturnTypeCheckProcessor.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.domaframework.doma.intellij.inspection.dao.processor +package org.domaframework.doma.intellij.inspection.dao.processor.returntype import com.intellij.psi.PsiType import com.intellij.psi.PsiTypes @@ -30,7 +30,7 @@ import org.domaframework.doma.intellij.common.validation.result.ValidationResult */ class BatchAnnotationReturnTypeCheckProcessor( private val psiDaoMethod: PsiDaoMethod, - shortName: String, + private val shortName: String, ) : ReturnTypeCheckerProcessor(psiDaoMethod, shortName) { /** * Checks the return type of the DAO method. 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/returntype/MultiInsertAnnotationReturnTypeCheckProcessor.kt similarity index 94% rename from src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/MultiInsertAnnotationReturnTypeCheckProcessor.kt rename to src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/returntype/MultiInsertAnnotationReturnTypeCheckProcessor.kt index 7b9a2a33..548ca22f 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/MultiInsertAnnotationReturnTypeCheckProcessor.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/returntype/MultiInsertAnnotationReturnTypeCheckProcessor.kt @@ -13,13 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.domaframework.doma.intellij.inspection.dao.processor +package org.domaframework.doma.intellij.inspection.dao.processor.returntype 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.util.DomaClassName 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 @@ -40,8 +41,6 @@ class MultiInsertAnnotationReturnTypeCheckProcessor( * @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 @@ -76,8 +75,8 @@ class MultiInsertAnnotationReturnTypeCheckProcessor( if (paramPsiType == null) return null val returnTypeName = returnType?.canonicalText ?: "" - val methodResultClassName = "java.util.List" - val actualResultTypeText = "$methodResultClassName<${paramPsiType.canonicalText}>" + val methodResultClassName = DomaClassName.LIST + val actualResultTypeText = methodResultClassName.getGenericParamCanonicalText(paramPsiType.canonicalText) return if (actualResultTypeText != returnTypeName) { ValidationReturnTypeForMultiInsertReturningResult( 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/returntype/ProcedureAnnotationReturnTypeCheckProcessor.kt similarity index 99% rename from src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/ProcedureAnnotationReturnTypeCheckProcessor.kt rename to src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/returntype/ProcedureAnnotationReturnTypeCheckProcessor.kt index 09b2360d..fc24a6ac 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/ProcedureAnnotationReturnTypeCheckProcessor.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/returntype/ProcedureAnnotationReturnTypeCheckProcessor.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.domaframework.doma.intellij.inspection.dao.processor +package org.domaframework.doma.intellij.inspection.dao.processor.returntype import com.intellij.psi.PsiTypes import org.domaframework.doma.intellij.common.psi.PsiDaoMethod 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/returntype/ReturnTypeCheckerProcessor.kt similarity index 87% rename from src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/ReturnTypeCheckerProcessor.kt rename to src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/returntype/ReturnTypeCheckerProcessor.kt index c139e5b8..c1b3aa91 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/ReturnTypeCheckerProcessor.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/returntype/ReturnTypeCheckerProcessor.kt @@ -13,24 +13,25 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.domaframework.doma.intellij.inspection.dao.processor +package org.domaframework.doma.intellij.inspection.dao.processor.returntype 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.util.DomaClassName 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 +import org.domaframework.doma.intellij.extension.psi.getClassAnnotation abstract class ReturnTypeCheckerProcessor( private val psiDaoMethod: PsiDaoMethod, private val shortName: String, ) { - protected val returningFqn = "org.seasar.doma.Returning" + protected val returningFqn = DomaClassName.RETURNING.className protected val method = psiDaoMethod.psiMethod protected val project = method.project protected val returnType = psiDaoMethod.psiMethod.returnType @@ -41,10 +42,11 @@ abstract class ReturnTypeCheckerProcessor( protected fun isImmutableEntity(canonicalText: String): Boolean { val returnTypeClass = method.project.getJavaClazz(canonicalText) - val entity = returnTypeClass?.getEntityAnnotation() ?: return false + val entity = returnTypeClass?.getClassAnnotation(DomaClassName.ENTITY.className) ?: return false return entity.let { entity -> AnnotationUtil.getBooleanAttributeValue(entity, "immutable") == true - } == true + } == true || + returnTypeClass.isRecord == true } protected fun hasReturingOption(): Boolean { @@ -66,9 +68,9 @@ abstract class ReturnTypeCheckerProcessor( return returningOption } - protected fun generatePsiTypeReturnTypeResult(methodOtherReturnType: PsiType): ValidationResult? { - return if (returnType != methodOtherReturnType) { - return ValidationReturnTypeResult( + protected fun generatePsiTypeReturnTypeResult(methodOtherReturnType: PsiType): ValidationResult? = + if (returnType != methodOtherReturnType) { + ValidationReturnTypeResult( method.nameIdentifier, shortName, methodOtherReturnType.presentableText, @@ -76,7 +78,6 @@ abstract class ReturnTypeCheckerProcessor( } else { null } - } protected fun generateResultReturnTypeImmutable( annotation: DomaAnnotationType, diff --git a/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/returntype/ScriptAnnotationReturnTypeCheckProcessor.kt b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/returntype/ScriptAnnotationReturnTypeCheckProcessor.kt new file mode 100644 index 00000000..29054068 --- /dev/null +++ b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/returntype/ScriptAnnotationReturnTypeCheckProcessor.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.returntype + +import com.intellij.psi.PsiTypes +import org.domaframework.doma.intellij.common.psi.PsiDaoMethod +import org.domaframework.doma.intellij.common.validation.result.ValidationResult + +class ScriptAnnotationReturnTypeCheckProcessor( + 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/SqlProcessorAnnotationReturnTypeCheckProcessor.kt b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/returntype/SqlProcessorAnnotationReturnTypeCheckProcessor.kt similarity index 87% rename from src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/SqlProcessorAnnotationReturnTypeCheckProcessor.kt rename to src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/returntype/SqlProcessorAnnotationReturnTypeCheckProcessor.kt index b7fb5e61..d9fc4a2d 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/SqlProcessorAnnotationReturnTypeCheckProcessor.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/returntype/SqlProcessorAnnotationReturnTypeCheckProcessor.kt @@ -13,13 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.domaframework.doma.intellij.inspection.dao.processor +package org.domaframework.doma.intellij.inspection.dao.processor.returntype 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.util.DomaClassName import org.domaframework.doma.intellij.common.validation.result.ValidationResult import org.domaframework.doma.intellij.common.validation.result.ValidationSqlProcessorReturnResult @@ -33,6 +34,8 @@ class SqlProcessorAnnotationReturnTypeCheckProcessor( psiDaoMethod: PsiDaoMethod, private val shortName: String, ) : ReturnTypeCheckerProcessor(psiDaoMethod, shortName) { + private val biFunctionClassName = DomaClassName.BI_FUNCTION.className + /** * Checks the return type of the DAO method. * @@ -40,7 +43,10 @@ class SqlProcessorAnnotationReturnTypeCheckProcessor( */ override fun checkReturnType(): ValidationResult? { val parameters = method.parameterList.parameters - val biFunctionParam = parameters.firstOrNull() ?: return null + val biFunctionParam = + parameters.firstOrNull { param -> + param.type.canonicalText.startsWith(biFunctionClassName) + } ?: return null val convertOptional = PsiClassTypeUtil.convertOptionalType(biFunctionParam.type, project) val parameterType = convertOptional as PsiClassReferenceType return checkReturnTypeBiFunctionParam(parameterType) @@ -53,7 +59,7 @@ class SqlProcessorAnnotationReturnTypeCheckProcessor( * @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 + if (!parameterType.canonicalText.startsWith(biFunctionClassName)) return null val parameterTypeParams = parameterType.reference.typeParameters if (parameterTypeParams.size < 3) return null @@ -63,7 +69,7 @@ class SqlProcessorAnnotationReturnTypeCheckProcessor( val nestClass: PsiType = PsiClassTypeUtil.convertOptionalType(nestPsiType, project) - if (nestClass.canonicalText != "java.lang.Void") { + if (nestClass.canonicalText != DomaClassName.VOID.className) { val methodReturnType = method.returnType val returnTypeCheckResult = (nestClass.canonicalText == "?" && methodReturnType?.canonicalText == "R") || 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/returntype/UpdateAnnotationReturnTypeCheckProcessor.kt similarity index 96% rename from src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/UpdateAnnotationReturnTypeCheckProcessor.kt rename to src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/returntype/UpdateAnnotationReturnTypeCheckProcessor.kt index a8270a75..98fedfb0 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/UpdateAnnotationReturnTypeCheckProcessor.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/processor/returntype/UpdateAnnotationReturnTypeCheckProcessor.kt @@ -13,14 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.domaframework.doma.intellij.inspection.dao.processor +package org.domaframework.doma.intellij.inspection.dao.processor.returntype 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.common.validation.result.ValidationReturnTypeUpdateReturningResult import org.domaframework.doma.intellij.extension.getJavaClazz import org.domaframework.doma.intellij.extension.psi.isEntity @@ -71,7 +71,7 @@ class UpdateAnnotationReturnTypeCheckProcessor( */ private fun checkReturnTypeWithReturning(paramClass: PsiParameter): ValidationResult? { if (returnType == null) { - return ValidationReturnTypeForReturningResult( + return ValidationReturnTypeUpdateReturningResult( paramClass.type.presentableText, method.nameIdentifier, shortName, @@ -83,7 +83,7 @@ class UpdateAnnotationReturnTypeCheckProcessor( val returnTypeClass = project.getJavaClazz(checkReturnType.canonicalText) return if (returnTypeClass?.isEntity() != true || returnType.canonicalText != paramClass.type.canonicalText) { - ValidationReturnTypeForReturningResult( + ValidationReturnTypeUpdateReturningResult( paramClass.type.presentableText, method.nameIdentifier, shortName, diff --git a/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/provider/UsedDaoMethodArgsVariableProvider.kt b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/provider/DaoMethodParamTypeProvider.kt similarity index 85% rename from src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/provider/UsedDaoMethodArgsVariableProvider.kt rename to src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/provider/DaoMethodParamTypeProvider.kt index ede3c6d9..7970245e 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/provider/UsedDaoMethodArgsVariableProvider.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/provider/DaoMethodParamTypeProvider.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.UsedDaoMethodArgsVariableInspection +import org.domaframework.doma.intellij.inspection.dao.inspector.DaoMethodParamTypeInspection -class UsedDaoMethodArgsVariableProvider : InspectionToolProvider { +class DaoMethodParamTypeProvider : InspectionToolProvider { override fun getInspectionClasses(): Array> = arrayOf( - UsedDaoMethodArgsVariableInspection::class.java, + DaoMethodParamTypeInspection::class.java, ) } 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/DaoMethodReturnTypeProvider.kt similarity index 84% rename from src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/provider/DaoMethodReturnTypeVariableProvider.kt rename to src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/provider/DaoMethodReturnTypeProvider.kt index baa643cd..caf4f4a4 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/provider/DaoMethodReturnTypeVariableProvider.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/provider/DaoMethodReturnTypeProvider.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.DaoMethodReturnTypeVariableInspection +import org.domaframework.doma.intellij.inspection.dao.inspector.DaoMethodReturnTypeInspection -class DaoMethodReturnTypeVariableProvider : InspectionToolProvider { +class DaoMethodReturnTypeProvider : InspectionToolProvider { override fun getInspectionClasses(): Array> = arrayOf( - DaoMethodReturnTypeVariableInspection::class.java, + DaoMethodReturnTypeInspection::class.java, ) } diff --git a/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/provider/UsedDaoMethodParamProvider.kt b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/provider/UsedDaoMethodParamProvider.kt new file mode 100644 index 00000000..51d5eb79 --- /dev/null +++ b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/provider/UsedDaoMethodParamProvider.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.UsedDaoMethodParamInspection + +class UsedDaoMethodParamProvider : InspectionToolProvider { + override fun getInspectionClasses(): Array> = + arrayOf( + UsedDaoMethodParamInspection::class.java, + ) +} diff --git a/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/visitor/DaoMethodParamTypeInspectionVisitor.kt b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/visitor/DaoMethodParamTypeInspectionVisitor.kt new file mode 100644 index 00000000..94262a6a --- /dev/null +++ b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/visitor/DaoMethodParamTypeInspectionVisitor.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.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.paramtype.BatchParamTypeCheckProcessor +import org.domaframework.doma.intellij.inspection.dao.processor.paramtype.MultiInsertParamTypeCheckProcessor +import org.domaframework.doma.intellij.inspection.dao.processor.paramtype.ParamTypeCheckProcessor +import org.domaframework.doma.intellij.inspection.dao.processor.paramtype.ProcedureParamTypeCheckProcessor +import org.domaframework.doma.intellij.inspection.dao.processor.paramtype.ScriptParamTypeCheckProcessor +import org.domaframework.doma.intellij.inspection.dao.processor.paramtype.SelectParamTypeCheckProcessor +import org.domaframework.doma.intellij.inspection.dao.processor.paramtype.SqlProcessorParamTypeCheckProcessor +import org.domaframework.doma.intellij.inspection.dao.processor.paramtype.UpdateParamTypeCheckProcessor + +class DaoMethodParamTypeInspectionVisitor( + 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: ParamTypeCheckProcessor? = getParamTypeCheckProcessor(psiDaoMethod) + processor?.checkParams(holder) + } + + private fun getParamTypeCheckProcessor(psiDaoMethod: PsiDaoMethod): ParamTypeCheckProcessor? = + when (psiDaoMethod.daoType) { + DomaAnnotationType.Insert, DomaAnnotationType.Update, DomaAnnotationType.Delete -> { + UpdateParamTypeCheckProcessor(psiDaoMethod, this.shortName) + } + + DomaAnnotationType.BatchInsert, DomaAnnotationType.BatchUpdate, DomaAnnotationType.BatchDelete -> { + BatchParamTypeCheckProcessor(psiDaoMethod, this.shortName) + } + + DomaAnnotationType.Procedure, DomaAnnotationType.Function -> { + ProcedureParamTypeCheckProcessor(psiDaoMethod, this.shortName) + } + DomaAnnotationType.SqlProcessor -> { + SqlProcessorParamTypeCheckProcessor( + psiDaoMethod, + this.shortName, + ) + } + DomaAnnotationType.MultiInsert -> + MultiInsertParamTypeCheckProcessor( + psiDaoMethod, + this.shortName, + ) + DomaAnnotationType.Script -> { + ScriptParamTypeCheckProcessor( + psiDaoMethod, + this.shortName, + ) + } + + DomaAnnotationType.Select -> { + SelectParamTypeCheckProcessor( + psiDaoMethod, + this.shortName, + ) + } + DomaAnnotationType.Sql, 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/DaoMethodRelatedSqlVisitor.kt similarity index 98% rename from src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/visitor/DaoMethodVariableSqlVisitor.kt rename to src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/visitor/DaoMethodRelatedSqlVisitor.kt index d8b188ff..b044aac7 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/DaoMethodRelatedSqlVisitor.kt @@ -26,7 +26,7 @@ import org.domaframework.doma.intellij.psi.SqlElForDirective import org.domaframework.doma.intellij.psi.SqlElPrimaryExpr import org.domaframework.doma.intellij.psi.SqlTypes -class DaoMethodVariableSqlVisitor( +class DaoMethodRelatedSqlVisitor( private val args: List, private val elements: MutableList, private val deplicateForItemElements: MutableList, 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/DaoMethodReturnTypeInspectionVisitor.kt similarity index 81% rename from src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/visitor/DaoMethodReturnTypeVariableInspectionVisitor.kt rename to src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/visitor/DaoMethodReturnTypeInspectionVisitor.kt index 72e215ca..90aa0b24 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/visitor/DaoMethodReturnTypeVariableInspectionVisitor.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/visitor/DaoMethodReturnTypeInspectionVisitor.kt @@ -22,14 +22,15 @@ 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 +import org.domaframework.doma.intellij.inspection.dao.processor.returntype.BatchAnnotationReturnTypeCheckProcessor +import org.domaframework.doma.intellij.inspection.dao.processor.returntype.MultiInsertAnnotationReturnTypeCheckProcessor +import org.domaframework.doma.intellij.inspection.dao.processor.returntype.ProcedureAnnotationReturnTypeCheckProcessor +import org.domaframework.doma.intellij.inspection.dao.processor.returntype.ReturnTypeCheckerProcessor +import org.domaframework.doma.intellij.inspection.dao.processor.returntype.ScriptAnnotationReturnTypeCheckProcessor +import org.domaframework.doma.intellij.inspection.dao.processor.returntype.SqlProcessorAnnotationReturnTypeCheckProcessor +import org.domaframework.doma.intellij.inspection.dao.processor.returntype.UpdateAnnotationReturnTypeCheckProcessor -class DaoMethodReturnTypeVariableInspectionVisitor( +class DaoMethodReturnTypeInspectionVisitor( private val holder: ProblemsHolder, private val shortName: String, ) : JavaElementVisitor() { @@ -68,7 +69,13 @@ class DaoMethodReturnTypeVariableInspectionVisitor( psiDaoMethod, this.shortName, ) + DomaAnnotationType.Script -> { + ScriptAnnotationReturnTypeCheckProcessor( + psiDaoMethod, + this.shortName, + ) + } - DomaAnnotationType.Select, DomaAnnotationType.Sql, DomaAnnotationType.Script, DomaAnnotationType.Unknown -> null + else -> null } } diff --git a/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/visitor/UsedDaoMethodArgsVariableInspectionVisitor.kt b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/visitor/UsedDaoMethodParamInspectionVisitor.kt similarity index 96% rename from src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/visitor/UsedDaoMethodArgsVariableInspectionVisitor.kt rename to src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/visitor/UsedDaoMethodParamInspectionVisitor.kt index 9636409d..aeda9c84 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/visitor/UsedDaoMethodArgsVariableInspectionVisitor.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/visitor/UsedDaoMethodParamInspectionVisitor.kt @@ -32,7 +32,7 @@ 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 UsedDaoMethodArgsVariableInspectionVisitor( +class UsedDaoMethodParamInspectionVisitor( private val holder: ProblemsHolder, ) : JavaElementVisitor() { override fun visitMethod(method: PsiMethod) { @@ -85,7 +85,7 @@ class UsedDaoMethodArgsVariableInspectionVisitor( val elements = mutableListOf() val deplicateForItemElements = mutableListOf() - sqlFile.accept(DaoMethodVariableSqlVisitor(args, elements, deplicateForItemElements)) + sqlFile.accept(DaoMethodRelatedSqlVisitor(args, elements, deplicateForItemElements)) val result = DaoMethodVariableVisitorResult(elements, deplicateForItemElements) return result } diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index 67871af6..975b1d5b 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -49,8 +49,9 @@ - - + + + diff --git a/src/main/resources/inspectionDescriptions/org.domaframework.doma.intellij.param.html b/src/main/resources/inspectionDescriptions/org.domaframework.doma.intellij.param.html new file mode 100644 index 00000000..6b0979cc --- /dev/null +++ b/src/main/resources/inspectionDescriptions/org.domaframework.doma.intellij.param.html @@ -0,0 +1,8 @@ + + +

+ This inspection checks that the parameters of DAO methods are properly annotated with Doma's parameter annotations. + It ensures that each parameter is annotated appropriately to maintain consistency and correctness in data access operations. +

+ + \ No newline at end of file diff --git a/src/main/resources/messages/DomaToolsBundle.properties b/src/main/resources/messages/DomaToolsBundle.properties index 2d5cd80b..d7990ffa 100644 --- a/src/main/resources/messages/DomaToolsBundle.properties +++ b/src/main/resources/messages/DomaToolsBundle.properties @@ -14,8 +14,19 @@ 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.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.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 +inspection.invalid.dao.select.param.strategy.require.type=When you specify SelectType.{0} for the strategy element of @Select, the "{1}" parameter is required for the method +inspection.invalid.dao.select.param.notFound.strategy.stream=When you use the "java.util.function.Function" parameter, SelectStrategyType.STREAM must be specified for the strategy element of @Select +inspection.invalid.dao.returnType.immutable=If a method annotated with @{0} targets immutable entities for insertion, the return type must be {1}<{2}> +inspection.invalid.dao.params.count=The number of parameters must be one +inspection.invalid.dao.params.empty=The number of parameters must be zero +inspection.invalid.dao.params.entity=The parameter type must be an entity class +inspection.invalid.dao.procedure.params.type=The parameter type annotated with @{0} must be "{1}" +inspection.invalid.dao.params.require.type=When you annotate the method with @{0}, the {1} parameter is required for the method +inspection.invalid.dao.params.require.iterable.entity=The argument must be an Iterable subclass that has an Entity class as a parameter +inspection.invalid.dao.procedure.params.require.annotation=The parameters of the method annotated with @Function or @Procedure must be annotated with either of @In, @InOut, @Out or @ResultSet +inspection.invalid.dao.procedure.params.in.type={0} is not supported as the type of the parameter annotated with @In +inspection.invalid.dao.procedure.params.support.generic.param="{0}" is illegal as the type argument of "{1}" \ 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 4c27b0eb..35a02cf3 100644 --- a/src/main/resources/messages/DomaToolsBundle_ja.properties +++ b/src/main/resources/messages/DomaToolsBundle_ja.properties @@ -13,9 +13,20 @@ inspection.invalid.sql.classpath=\u5B58\u5728\u3057\u306A\u3044\u30D1\u30C3\u30B inspection.invalid.sql.iterable=\u30EB\u30FC\u30D7\u30C7\u30A3\u30EC\u30AF\u30C6\u30A3\u30D6\u306B\u4F7F\u7528\u3067\u304D\u308B\u578B\u306F\u0049\u0074\u0065\u0072\u0061\u0062\u006C\u0065\u578B\u3067\u3059 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.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\u006EFunction\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.select.param.strategy.require.type=\u0040\u0053\u0065\u006C\u0065\u0063\u0074\u3067\u0073\u0074\u0072\u0061\u0074\u0065\u0067\u0079\u30AA\u30D7\u30B7\u30E7\u30F3\u306B\u0053\u0065\u006C\u0065\u0063\u0074\u0054\u0079\u0070\u0065\u002E{0}\u3092\u6307\u5B9A\u3059\u308B\u5834\u5408\u3001\u30E1\u30BD\u30C3\u30C9\u306B{1}\u578B\u306E\u30D1\u30E9\u30E1\u30FC\u30BF\u304C\u5FC5\u8981\u3067\u3059 +inspection.invalid.dao.select.param.notFound.strategy.stream=\u300Cjava.util.function.Function\u300D\u30D1\u30E9\u30E1\u30FC\u30BF\u3092\u4F7F\u7528\u3059\u308B\u5834\u5408\u3001@Select\u306E\u6226\u7565\u8981\u7D20\u306BSelectStrategyType.STREAM\u3092\u6307\u5B9A\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059 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 +inspection.invalid.dao.params.count=\u5F15\u6570\u306E\u6570\u306F1\u3064\u3067\u306A\u3051\u308C\u3070\u306A\u308A\u307E\u305B\u3093 +inspection.invalid.dao.params.empty=\u5F15\u6570\u306E\u6570\u306F0\u3067\u306A\u3051\u308C\u3070\u306A\u308A\u307E\u305B\u3093 +inspection.invalid.dao.params.entity=\u5F15\u6570\u306E\u578B\u306F\u30A8\u30F3\u30C6\u30A3\u30C6\u30A3\u30AF\u30E9\u30B9\u3067\u306A\u3051\u308C\u3070\u306A\u308A\u307E\u305B\u3093 +inspection.invalid.dao.procedure.params.type=@{0}\u304C\u4ED8\u4E0E\u3055\u308C\u305F\u5F15\u6570\u306E\u578B\u306F"{1}"\u3067\u306A\u3051\u308C\u3070\u306A\u308A\u307E\u305B\u3093 +inspection.invalid.dao.params.require.type=@{0}\u304C\u4ED8\u4E0E\u3055\u308C\u305F\u5834\u5408\u3001\u305D\u306E\u30E1\u30BD\u30C3\u30C9\u306B{1}\u5F15\u6570\u304C\u5FC5\u8981\u3067\u3059 +inspection.invalid.dao.params.require.iterable.entity=\u5F15\u6570\u306F\u30A8\u30F3\u30C6\u30A3\u30C6\u30A3\u30AF\u30E9\u30B9\u3092\u578B\u5F15\u6570\u306B\u6301\u3064Iterable\u306E\u30B5\u30D6\u30AF\u30E9\u30B9\u3067\u306A\u3051\u308C\u3070\u306A\u308A\u307E\u305B\u3093 +inspection.invalid.dao.procedure.params.require.annotation=@Function\u307E\u305F\u306F@Procedure\u304C\u4ED8\u4E0E\u3055\u308C\u305F\u30E1\u30BD\u30C3\u30C9\u306E\u5F15\u6570\u306F@In\u3001@InOut\u3001@Out\u3001@ResultSet\u306E\u3044\u305A\u308C\u304B\u3092\u4ED8\u4E0E\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059 +inspection.invalid.dao.procedure.params.in.type=@In\u304C\u4ED8\u4E0E\u3055\u308C\u305F\u5F15\u6570\u306E\u578B\u3068\u3057\u3066{0}\u306F\u30B5\u30DD\u30FC\u30C8\u3055\u308C\u307E\u305B\u3093 +inspection.invalid.dao.procedure.params.support.generic.param="{0}"\u306F"{1}"\u306E\u578B\u5F15\u6570\u3068\u3057\u3066\u4E0D\u6B63\u3067\u3059 \ No newline at end of file diff --git a/src/test/kotlin/org/domaframework/doma/intellij/DomaSqlTest.kt b/src/test/kotlin/org/domaframework/doma/intellij/DomaSqlTest.kt index a4316805..a0c69321 100644 --- a/src/test/kotlin/org/domaframework/doma/intellij/DomaSqlTest.kt +++ b/src/test/kotlin/org/domaframework/doma/intellij/DomaSqlTest.kt @@ -205,7 +205,8 @@ open class DomaSqlTest : LightJavaCodeInsightFixtureTestCase() { } fun findDaoClass(testDaoName: String): PsiClass { - val dao = myFixture.findClass("doma.example.dao.$testDaoName") + val daoName = testDaoName.replace("/", ".") + val dao = myFixture.findClass("doma.example.dao.$daoName") assertNotNull("Not Found [$testDaoName]", dao) return dao } diff --git a/src/test/kotlin/org/domaframework/doma/intellij/inspection/dao/AnnotationParamTypeCheckInspectionTest.kt b/src/test/kotlin/org/domaframework/doma/intellij/inspection/dao/AnnotationParamTypeCheckInspectionTest.kt new file mode 100644 index 00000000..44da2ed7 --- /dev/null +++ b/src/test/kotlin/org/domaframework/doma/intellij/inspection/dao/AnnotationParamTypeCheckInspectionTest.kt @@ -0,0 +1,81 @@ +/* + * 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.DaoMethodParamTypeInspection + +/** + * Test class for annotation parameter type check inspection. + */ +class AnnotationParamTypeCheckInspectionTest : DomaSqlTest() { + private val testDaoNames = + listOf( + "InsertUpdateDeleteParamTestDao", + "BatchInsertUpdateDeleteParamTestDao", + "MultiInsertParamTestDao", + "ProcedureParamTestDao", + "ScriptParamTestDao", + "SqlProcessorParamTestDao", + "SelectParamTestDao", + ) + private val daoPackage = "inspection/paramtype" + + override fun setUp() { + super.setUp() + myFixture.enableInspections(DaoMethodParamTypeInspection()) + addEntityJavaFile("Pckt.java") + addEntityJavaFile("Packet.java") + testDaoNames.forEach { daoName -> + addDaoJavaFile("$daoPackage/$daoName.java") + } + } + + fun testSelectParam() { + val dao = findDaoClass("$daoPackage.SelectParamTestDao") + myFixture.testHighlighting(false, false, false, dao.containingFile.virtualFile) + } + + fun testInsertUpdateDeleteParam() { + val dao = findDaoClass("$daoPackage.InsertUpdateDeleteParamTestDao") + myFixture.testHighlighting(false, false, false, dao.containingFile.virtualFile) + } + + fun testBatchInsertUpdateDeleteParam() { + val dao = findDaoClass("$daoPackage.BatchInsertUpdateDeleteParamTestDao") + myFixture.testHighlighting(false, false, false, dao.containingFile.virtualFile) + } + + fun testMultiInsertParam() { + val dao = findDaoClass("$daoPackage.MultiInsertParamTestDao") + myFixture.testHighlighting(false, false, false, dao.containingFile.virtualFile) + } + + fun testProcedureParam() { + val dao = findDaoClass("$daoPackage.ProcedureParamTestDao") + myFixture.testHighlighting(false, false, false, dao.containingFile.virtualFile) + } + + fun testScriptParam() { + val dao = findDaoClass("$daoPackage.ScriptParamTestDao") + myFixture.testHighlighting(false, false, false, dao.containingFile.virtualFile) + } + + fun testSqlProcessorParam() { + val dao = findDaoClass("$daoPackage.SqlProcessorParamTestDao") + myFixture.testHighlighting(false, false, false, dao.containingFile.virtualFile) + } +} 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 index 9e4784e0..c59426cc 100644 --- a/src/test/kotlin/org/domaframework/doma/intellij/inspection/dao/AnnotationReturnTypeCheckInspectionTest.kt +++ b/src/test/kotlin/org/domaframework/doma/intellij/inspection/dao/AnnotationReturnTypeCheckInspectionTest.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.DaoMethodReturnTypeVariableInspection +import org.domaframework.doma.intellij.inspection.dao.inspector.DaoMethodReturnTypeInspection /** * Test class for annotation return type check inspection. @@ -40,7 +40,7 @@ class AnnotationReturnTypeCheckInspectionTest : DomaSqlTest() { // Entity classes addEntityJavaFile("Packet.java") addEntityJavaFile("Pckt.java") - myFixture.enableInspections(DaoMethodReturnTypeVariableInspection()) + myFixture.enableInspections(DaoMethodReturnTypeInspection()) } fun testUpdateAnnotationReturnTypeCheckProcessor() { 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 cda2ae31..a98ecd28 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.UsedDaoMethodArgsVariableInspection +import org.domaframework.doma.intellij.inspection.dao.inspector.UsedDaoMethodParamInspection /** * 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(UsedDaoMethodArgsVariableInspection()) + myFixture.enableInspections(UsedDaoMethodParamInspection()) } /** 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 index 4358e1c7..b5917b06 100644 --- 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 @@ -11,10 +11,10 @@ public interface BatchReturnTypeDao { int[] batchInsertReturnsIntArray(List e); @BatchUpdate - String batchUpdateReturnsString(List e); + String batchUpdateReturnsString(List e); @BatchDelete - int[] batchDeleteReturnsIntWithImmutable(List e); + 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 index a5ceb3c9..3e49d110 100644 --- 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 @@ -11,7 +11,7 @@ public interface MultiInsertReturnTypeDao { int multiInsertReturnsInt(List e); @MultiInsert - String multiInsertReturnsString(List e); + String multiInsertReturnsString(List e); @MultiInsert(returning = @Returning) List multiInsertReturningList(List e); @@ -20,7 +20,7 @@ public interface MultiInsertReturnTypeDao { String ">multiInsertReturningString(List e); @MultiInsert - int multiInsertReturnsIntWithImmutable(List e); + 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 index 5da218eb..9fd69631 100644 --- 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 @@ -7,5 +7,5 @@ public interface ProcedureReturnTypeDao { @Procedure void callProcedureReturnsVoid(); @Procedure - int callProcedureReturnsInt(); + 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 index 6194a8d2..b74f4da3 100644 --- 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 @@ -14,11 +14,11 @@ public interface SqlProcessorReturnTypeDao { R processSqlReturnsR(BiFunction handler); @SqlProcessor - String processSqlReturnsString(BiFunction handler); + String processSqlReturnsString(BiFunction handler); @SqlProcessor void processSqlReturnsVoid(BiFunction handler); @SqlProcessor - String processSqlReturnsStringWithVoidHandler(BiFunction handler); + String processSqlReturnsStringWithVoidHandler(BiFunction handler); } 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 index b0e87e79..7e6b505d 100644 --- 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 @@ -11,7 +11,7 @@ public interface UpdateReturnTypeDao { int insertReturnsInt(Packet e); @Update - String updateReturnsString(Packet e); + String updateReturnsString(Packet e); @Delete(returning = @Returning) Packet deleteReturningEntity(Packet e); @@ -23,6 +23,6 @@ public interface UpdateReturnTypeDao { Result updateReturnsResultWithImmutable(Pckt e); @Update - int updateReturnsIntWithImmutable(Pckt e); + int updateReturnsIntWithImmutable(Pckt e); } diff --git a/src/test/testData/src/main/java/doma/example/dao/inspection/paramtype/BatchInsertUpdateDeleteParamTestDao.java b/src/test/testData/src/main/java/doma/example/dao/inspection/paramtype/BatchInsertUpdateDeleteParamTestDao.java new file mode 100644 index 00000000..9b6a6119 --- /dev/null +++ b/src/test/testData/src/main/java/doma/example/dao/inspection/paramtype/BatchInsertUpdateDeleteParamTestDao.java @@ -0,0 +1,49 @@ +package doma.example.dao.inspection.paramtype; + +import doma.example.entity.*; +import org.seasar.doma.*; +import org.seasar.doma.jdbc.BatchResult; + +import java.util.List; +import java.util.Optional; + +@Dao +public interface BatchInsertUpdateDeleteParamTestDao { + + @BatchInsert + int[] batchInsertWrapper(List ids); + + @BatchUpdate + int[] batchInsertEmpNotList(Pckt pckt); + + @BatchInsert + @Sql("insert into values (/*id*/0)") + int[] batchInsertWithSqlAnnotation(Integer id); + + @BatchUpdate + int[] batchInsertEmpNotList(List pckts,String name); + + @BatchUpdate + int[] batchInsertEmp(List pckts); + + @BatchUpdate + BatchResult batchInsertEmpResult(List pckts); + + @BatchUpdate + BatchResult batchInsertResult(List packets); + + @BatchUpdate + int[] batchInsertOptional(List> packets); + + @BatchUpdate + @Sql("insert into values (/*packets.id*/0, /*packets.name*/'name')") + BatchResult> batchInsertResultWithSql(List> packets); + + @BatchUpdate + @Sql("insert into values (/*packets.id*/0, /*packets.name*/'name')") + int[] batchInsertWithSql(List> packets); + + @BatchUpdate + int[] batchInsert(List packets); +} + diff --git a/src/test/testData/src/main/java/doma/example/dao/inspection/paramtype/InsertUpdateDeleteParamTestDao.java b/src/test/testData/src/main/java/doma/example/dao/inspection/paramtype/InsertUpdateDeleteParamTestDao.java new file mode 100644 index 00000000..429a7e75 --- /dev/null +++ b/src/test/testData/src/main/java/doma/example/dao/inspection/paramtype/InsertUpdateDeleteParamTestDao.java @@ -0,0 +1,29 @@ +package doma.example.dao.inspection.paramtype; + +import doma.example.entity.*; +import org.seasar.doma.Dao; +import org.seasar.doma.Delete; +import org.seasar.doma.Insert; +import org.seasar.doma.Update; +import org.seasar.doma.Sql; + +@Dao +public interface InsertUpdateDeleteParamTestDao { + + @Insert + int insertEntity(Packet packet); + + @Insert + int insertPrimitive(Integer id); + + @Update + int updateNoParams(); + + @Delete + int deleteMultipleParams(Packet packet, String name); + + @Insert + @Sql("insert into Packet (id, name) values (/* id */0, /* name */'test')") + int insertWithSqlAnnotation(Integer id, String name); + +} diff --git a/src/test/testData/src/main/java/doma/example/dao/inspection/paramtype/MultiInsertParamTestDao.java b/src/test/testData/src/main/java/doma/example/dao/inspection/paramtype/MultiInsertParamTestDao.java new file mode 100644 index 00000000..454de5ed --- /dev/null +++ b/src/test/testData/src/main/java/doma/example/dao/inspection/paramtype/MultiInsertParamTestDao.java @@ -0,0 +1,38 @@ +package doma.example.dao.inspection.paramtype; + +import doma.example.entity.*; +import org.seasar.doma.*; +import org.seasar.doma.jdbc.MultiResult; + +import java.util.List; + +@Dao +public interface MultiInsertParamTestDao { + + @MultiInsert + int multiInsertNotList(Pckt Pckt); + + @MultiInsert + int multiInsertAnyParams(List PcktList, String name); + + @MultiInsert + int multiInsertNotEntityIterable(List PcktList); + + @MultiInsert + int[] multiInsert(List PcktList); + + @MultiInsert + MultiResult multiInsertNoMatchResult(List PcktList); + + @MultiInsert + MultiResult multiInsertResult(List PcktList); + + @MultiInsert + MultiResult multiInsertPacket(List PacketList); + + @MultiInsert(returning = @Returning) + int[] multiInsertReturning(List Pckts); + + @MultiInsert(returning = @Returning) + List multiInsertReturningList(List Pckts); +} diff --git a/src/test/testData/src/main/java/doma/example/dao/inspection/paramtype/ProcedureParamTestDao.java b/src/test/testData/src/main/java/doma/example/dao/inspection/paramtype/ProcedureParamTestDao.java new file mode 100644 index 00000000..708fff5b --- /dev/null +++ b/src/test/testData/src/main/java/doma/example/dao/inspection/paramtype/ProcedureParamTestDao.java @@ -0,0 +1,26 @@ +package doma.example.dao.inspection.paramtype; + +import org.seasar.doma.*; +import org.seasar.doma.jdbc.Reference; +import doma.example.entity.*; + +import java.util.List; +import java.util.Map; +import java.util.Optional; + +@Dao +public interface ProcedureParamTestDao { + + @Procedure + void executeNotAnnotation(@In Integer inParam,@InOut Reference inOurPatam, @Out Reference outParam); + + @Procedure + void executeValidType(@In Reference inParam + , @InOut Integer inOurPatam + , @Out String outParam + , @ResultSet Optional optional); + + @Function + int executeFuncValidType(@Out Reference> out,@ResultSet List> optional); +} + diff --git a/src/test/testData/src/main/java/doma/example/dao/inspection/paramtype/ScriptParamTestDao.java b/src/test/testData/src/main/java/doma/example/dao/inspection/paramtype/ScriptParamTestDao.java new file mode 100644 index 00000000..31b48f09 --- /dev/null +++ b/src/test/testData/src/main/java/doma/example/dao/inspection/paramtype/ScriptParamTestDao.java @@ -0,0 +1,14 @@ +package doma.example.dao.inspection.paramtype; + +import org.seasar.doma.*; + +@Dao +public interface ScriptParamTestDao { + + @Script + void scriptString(String script); + + @Script + void scriptInt(int value); +} + diff --git a/src/test/testData/src/main/java/doma/example/dao/inspection/paramtype/SelectParamTestDao.java b/src/test/testData/src/main/java/doma/example/dao/inspection/paramtype/SelectParamTestDao.java new file mode 100644 index 00000000..b3bb11b8 --- /dev/null +++ b/src/test/testData/src/main/java/doma/example/dao/inspection/paramtype/SelectParamTestDao.java @@ -0,0 +1,60 @@ +package doma.example.dao.inspection.paramtype; + +import org.seasar.doma.*; +import org.seasar.doma.message.Message; +import doma.example.entity.*; + +import java.math.BigDecimal; +import java.util.Optional; +import java.util.stream.Collector; +import java.util.stream.Stream; +import java.util.function.Function; + +@Dao +public interface SelectParamTestDao { + + @Select + Pckt selectPcktById(Integer id); + + @Select + @Sql("SELECT * FROM packet WHERE id = /* pckt.id */0") + Pckt selectEmp(Pckt pckt); + + @Select(strategy = SelectType.STREAM) + @Sql("Select 10000 from user where name = /* name */'name' and salary = /* salary */0") + Stream \" parameter is required for the method">selectReturnStreamWithStreamOption(String name, BigDecimal salary); + + @Select + @Sql("Select 10000 from user") + Stream selectReturnStreamWithOutStreamOption(Function, BigDecimal> streams); + + @Select(strategy = SelectType.STREAM) + @Sql("Select 10000 from user") + Integer selectReturnStream(Function, BigDecimal> stream); + + @Select(strategy = SelectType.STREAM) + @Sql("Select 10000 from user") + BigDecimal selectStream(Function, BigDecimal> stream); + + @Suppress(messages = { Message.DOMA4274 }) + @Select + @Sql("Select 10000 from user where name = /* name */'name' and salary = /* salary */0") + Stream selectReturnStream(String name, BigDecimal salary); + + @Select + @Sql("select * from packet where salary > /* salary */0") + Pckt selectCollectNotOption(BigDecimal salary, Collector collector); + + @Select(strategy = SelectType.COLLECT) + @Sql("select * from packet where salary > /* salary */0") + Pckt selectWithOutCollector(BigDecimal salary, Packet packet); + + @Select(strategy = SelectType.COLLECT) + @Sql("select * from emp where salary > /* salary */0") + Optional selectCollectInValidParamResult(BigDecimal salary,Collector> collector); + + @Select(strategy = SelectType.COLLECT) + @Sql("select * from emp where salary > /* salary */0") + Pckt selectCollectAccumulation(BigDecimal salary, Collector collector); +} + diff --git a/src/test/testData/src/main/java/doma/example/dao/inspection/paramtype/SqlProcessorParamTestDao.java b/src/test/testData/src/main/java/doma/example/dao/inspection/paramtype/SqlProcessorParamTestDao.java new file mode 100644 index 00000000..fcb31a4c --- /dev/null +++ b/src/test/testData/src/main/java/doma/example/dao/inspection/paramtype/SqlProcessorParamTestDao.java @@ -0,0 +1,35 @@ +package doma.example.dao.inspection.paramtype; + +import org.seasar.doma.*; +import doma.example.entity.*; +import java.util.function.BiFunction; +import org.seasar.doma.jdbc.Config; +import org.seasar.doma.jdbc.PreparedSql; + +@Dao +public interface SqlProcessorParamTestDao { + + @SqlProcessor + @Sql("") + R executeNotBiFunction(Integer id); + + @SqlProcessor + @Sql("") + R executeBiFunctionNotConfig(BiFunction func); + + @SqlProcessor + R executeBiFunctionNotPreparedSql(BiFunction func); + + @SqlProcessor + R executeR(Integer id,BiFunction func); + + @SqlProcessor + Integer executeInteger(Integer id,BiFunction func); + + @SqlProcessor + Pckt executePckt(BiFunction func); + + @SqlProcessor + R execute(BiFunction func); +} +