From 881913e499c0843fcd0853c9e62b1785af2db580 Mon Sep 17 00:00:00 2001 From: xterao Date: Wed, 30 Apr 2025 18:57:03 +0900 Subject: [PATCH 1/2] Add SQL test data validation inspections --- .../result/ValidationTestDataResult.kt | 44 +++++++++ .../SqlBindVariableValidInspector.kt | 2 +- ...ataAfterBlockCommentValidValidInspector.kt | 44 +++++++++ ...lTestDataAfterBlockCommentValidProvider.kt | 27 ++++++ .../sql/{ => visitor}/SqlInspectionVisitor.kt | 49 +--------- .../SqlTestDataAfterBlockCommentVisitor.kt | 91 +++++++++++++++++++ .../inspection/sql/visitor/SqlVisitorBase.kt | 70 ++++++++++++++ src/main/resources/META-INF/plugin.xml | 1 + ...work.doma.intellij.existaftertestdata.html | 7 ++ ...amework.doma.intellij.variablechecker.html | 2 +- .../messages/DomaToolsBundle.properties | 3 +- .../messages/DomaToolsBundle_ja.properties | 3 +- 12 files changed, 292 insertions(+), 51 deletions(-) create mode 100644 src/main/kotlin/org/domaframework/doma/intellij/common/sql/validator/result/ValidationTestDataResult.kt create mode 100644 src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/inspector/SqlTestDataAfterBlockCommentValidValidInspector.kt create mode 100644 src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/provider/SqlTestDataAfterBlockCommentValidProvider.kt rename src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/{ => visitor}/SqlInspectionVisitor.kt (81%) create mode 100644 src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/visitor/SqlTestDataAfterBlockCommentVisitor.kt create mode 100644 src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/visitor/SqlVisitorBase.kt create mode 100644 src/main/resources/inspectionDescriptions/org.domaframework.doma.intellij.existaftertestdata.html diff --git a/src/main/kotlin/org/domaframework/doma/intellij/common/sql/validator/result/ValidationTestDataResult.kt b/src/main/kotlin/org/domaframework/doma/intellij/common/sql/validator/result/ValidationTestDataResult.kt new file mode 100644 index 00000000..e01e0b95 --- /dev/null +++ b/src/main/kotlin/org/domaframework/doma/intellij/common/sql/validator/result/ValidationTestDataResult.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.sql.validator.result + +import com.intellij.codeInspection.ProblemsHolder +import com.intellij.openapi.project.Project +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 ValidationTestDataResult( + override val identify: PsiElement?, + override val shortName: String = "", +) : ValidationResult(identify, null, shortName) { + override fun setHighlight( + highlightRange: TextRange, + identify: PsiElement, + holder: ProblemsHolder, + parent: PsiParentClass?, + project: Project, + ) { + val project = identify.project + holder.registerProblem( + identify, + MessageBundle.message("inspection.invalid.sql.testdata"), + problemHighlightType(project, shortName), + highlightRange, + ) + } +} diff --git a/src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/inspector/SqlBindVariableValidInspector.kt b/src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/inspector/SqlBindVariableValidInspector.kt index ea2b4ec7..e43062ee 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/inspector/SqlBindVariableValidInspector.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/inspector/SqlBindVariableValidInspector.kt @@ -18,7 +18,7 @@ package org.domaframework.doma.intellij.inspection.sql.inspector import com.intellij.codeHighlighting.HighlightDisplayLevel import com.intellij.codeInspection.LocalInspectionTool import com.intellij.codeInspection.ProblemsHolder -import org.domaframework.doma.intellij.inspection.sql.SqlInspectionVisitor +import org.domaframework.doma.intellij.inspection.sql.visitor.SqlInspectionVisitor import org.domaframework.doma.intellij.psi.SqlVisitor /** diff --git a/src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/inspector/SqlTestDataAfterBlockCommentValidValidInspector.kt b/src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/inspector/SqlTestDataAfterBlockCommentValidValidInspector.kt new file mode 100644 index 00000000..ad51432e --- /dev/null +++ b/src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/inspector/SqlTestDataAfterBlockCommentValidValidInspector.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.inspection.sql.inspector + +import com.intellij.codeHighlighting.HighlightDisplayLevel +import com.intellij.codeInspection.LocalInspectionTool +import com.intellij.codeInspection.ProblemsHolder +import org.domaframework.doma.intellij.inspection.sql.visitor.SqlTestDataAfterBlockCommentVisitor +import org.domaframework.doma.intellij.psi.SqlVisitor + +/** + * Code inspection for SQL bind variables + */ +class SqlTestDataAfterBlockCommentValidValidInspector : LocalInspectionTool() { + override fun getDisplayName(): String = "Check whether test data exists after the bind variable" + + override fun getShortName(): String = "org.domaframework.doma.intellij.existaftertestdata" + + override fun getGroupDisplayName(): String = "DomaTools" + + override fun isEnabledByDefault(): Boolean = true + + override fun getDefaultLevel(): HighlightDisplayLevel = HighlightDisplayLevel.Companion.ERROR + + override fun runForWholeFile(): Boolean = true + + override fun buildVisitor( + holder: ProblemsHolder, + isOnTheFly: Boolean, + ): SqlVisitor = SqlTestDataAfterBlockCommentVisitor(holder, this.shortName) +} diff --git a/src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/provider/SqlTestDataAfterBlockCommentValidProvider.kt b/src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/provider/SqlTestDataAfterBlockCommentValidProvider.kt new file mode 100644 index 00000000..1a2cd90e --- /dev/null +++ b/src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/provider/SqlTestDataAfterBlockCommentValidProvider.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.sql.provider + +import com.intellij.codeInspection.InspectionToolProvider +import com.intellij.codeInspection.LocalInspectionTool +import org.domaframework.doma.intellij.inspection.sql.inspector.SqlTestDataAfterBlockCommentValidValidInspector + +class SqlTestDataAfterBlockCommentValidProvider : InspectionToolProvider { + override fun getInspectionClasses(): Array> = + arrayOf( + SqlTestDataAfterBlockCommentValidValidInspector::class.java, + ) +} diff --git a/src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/SqlInspectionVisitor.kt b/src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/visitor/SqlInspectionVisitor.kt similarity index 81% rename from src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/SqlInspectionVisitor.kt rename to src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/visitor/SqlInspectionVisitor.kt index 3f805683..610e2923 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/SqlInspectionVisitor.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/visitor/SqlInspectionVisitor.kt @@ -13,11 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.domaframework.doma.intellij.inspection.sql +package org.domaframework.doma.intellij.inspection.sql.visitor import com.intellij.codeInspection.ProblemsHolder -import com.intellij.lang.injection.InjectedLanguageManager -import com.intellij.openapi.project.Project import com.intellij.psi.PsiElement import com.intellij.psi.PsiFile import com.intellij.psi.PsiLiteralExpression @@ -42,25 +40,14 @@ import org.domaframework.doma.intellij.inspection.ForDirectiveInspection import org.domaframework.doma.intellij.psi.SqlElFieldAccessExpr import org.domaframework.doma.intellij.psi.SqlElForDirective import org.domaframework.doma.intellij.psi.SqlElIdExpr -import org.domaframework.doma.intellij.psi.SqlElNewExpr import org.domaframework.doma.intellij.psi.SqlElPrimaryExpr import org.domaframework.doma.intellij.psi.SqlElStaticFieldAccessExpr import org.domaframework.doma.intellij.psi.SqlTypes -import org.domaframework.doma.intellij.psi.SqlVisitor class SqlInspectionVisitor( private val holder: ProblemsHolder, private val shortName: String, -) : SqlVisitor() { - var file: PsiFile? = null - - private fun setFile(element: PsiElement): Boolean { - if (file == null) { - file = element.containingFile - } - return false - } - +) : SqlVisitorBase() { override fun visitElement(element: PsiElement) { if (setFile(element)) return val visitFile: PsiFile = file ?: return @@ -135,38 +122,6 @@ class SqlInspectionVisitor( } } - /** - * For processing inside Sql annotations, get it as an injected custom language - */ - private fun initInjectionElement( - basePsiFile: PsiFile, - project: Project, - literal: PsiLiteralExpression, - ): PsiFile? = - when (isJavaOrKotlinFileType(basePsiFile)) { - true -> { - val injectedLanguageManager = - InjectedLanguageManager.getInstance(project) - injectedLanguageManager - .getInjectedPsiFiles(literal) - ?.firstOrNull() - ?.first as? PsiFile - } - - false -> null - } - - private fun isLiteralOrStatic(targetElement: PsiElement): Boolean = - ( - targetElement.firstChild?.elementType == SqlTypes.EL_STRING || - targetElement.firstChild?.elementType == SqlTypes.EL_CHAR || - targetElement.firstChild?.elementType == SqlTypes.EL_NUMBER || - targetElement.firstChild?.elementType == SqlTypes.EL_NULL || - targetElement.firstChild?.elementType == SqlTypes.BOOLEAN || - targetElement.firstChild is SqlElNewExpr || - targetElement.text.startsWith("@") - ) - private fun getFieldAccessBlocks(element: SqlElFieldAccessExpr): List { val blockElements = element.accessElements (blockElements.firstOrNull() as? SqlElPrimaryExpr) diff --git a/src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/visitor/SqlTestDataAfterBlockCommentVisitor.kt b/src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/visitor/SqlTestDataAfterBlockCommentVisitor.kt new file mode 100644 index 00000000..41271db9 --- /dev/null +++ b/src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/visitor/SqlTestDataAfterBlockCommentVisitor.kt @@ -0,0 +1,91 @@ +/* + * 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.sql.visitor + +import com.intellij.codeInspection.ProblemsHolder +import com.intellij.psi.PsiComment +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiFile +import com.intellij.psi.PsiLiteralExpression +import com.intellij.psi.util.PsiTreeUtil +import org.domaframework.doma.intellij.common.isInjectionSqlFile +import org.domaframework.doma.intellij.common.isJavaOrKotlinFileType +import org.domaframework.doma.intellij.common.sql.validator.result.ValidationTestDataResult +import org.domaframework.doma.intellij.psi.SqlBlockComment +import org.domaframework.doma.intellij.psi.SqlElElseifDirective +import org.domaframework.doma.intellij.psi.SqlElForDirective +import org.domaframework.doma.intellij.psi.SqlElIfDirective +import org.domaframework.doma.intellij.psi.SqlTypes +import org.toml.lang.psi.ext.elementType + +class SqlTestDataAfterBlockCommentVisitor( + private val holder: ProblemsHolder, + private val shortName: String, +) : SqlVisitorBase() { + override fun visitElement(element: PsiElement) { + if (setFile(element)) return + val visitFile: PsiFile = file ?: return + if (isJavaOrKotlinFileType(visitFile) && element is PsiLiteralExpression) { + val injectionFile = initInjectionElement(visitFile, element.project, element) ?: return + injectionFile.accept(this) + super.visitElement(element) + } + if (isInjectionSqlFile(visitFile)) { + element.acceptChildren(this) + } + } + + override fun visitBlockComment(element: SqlBlockComment) { + super.visitBlockComment(element) + if (hasOtherBindVariable(element)) return + + val nextElement = element.nextSibling ?: return + if (isSqlLiteral(nextElement)) return + + val result = ValidationTestDataResult(element, shortName) + result.highlightElement(holder) + } + + /** + * Check to Exist other bind variable in the block comment + */ + private fun hasOtherBindVariable(element: PsiElement): Boolean { + val directive = + PsiTreeUtil.getChildOfType(element, SqlElForDirective::class.java) + ?: PsiTreeUtil.getChildOfType(element, SqlElIfDirective::class.java) + ?: PsiTreeUtil.getChildOfType(element, SqlElElseifDirective::class.java) + val endDirective = + PsiTreeUtil + .getChildrenOfType(element, PsiElement::class.java) + ?.find { + it.elementType == SqlTypes.EL_END || + it.elementType == SqlTypes.HASH || + it.elementType == SqlTypes.EL_POPULATE + } + if (directive != null || endDirective != null) return true + + val content = PsiTreeUtil.getChildOfType(element, PsiComment::class.java) + return content != null + } + + private fun isSqlLiteral(element: PsiElement): Boolean = + element.elementType == SqlTypes.STRING || + element.elementType == SqlTypes.BOOLEAN || + element.elementType == SqlTypes.NUMBER || + element.elementType == SqlTypes.NULL || + listOf("true", "false", "null").contains(element.text) || + element.text.matches(Regex("^\\d+$")) +} diff --git a/src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/visitor/SqlVisitorBase.kt b/src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/visitor/SqlVisitorBase.kt new file mode 100644 index 00000000..67fab189 --- /dev/null +++ b/src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/visitor/SqlVisitorBase.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.sql.visitor + +import com.intellij.lang.injection.InjectedLanguageManager +import com.intellij.openapi.project.Project +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiFile +import com.intellij.psi.PsiLiteralExpression +import com.intellij.psi.util.elementType +import org.domaframework.doma.intellij.common.isJavaOrKotlinFileType +import org.domaframework.doma.intellij.psi.SqlElNewExpr +import org.domaframework.doma.intellij.psi.SqlTypes +import org.domaframework.doma.intellij.psi.SqlVisitor + +open class SqlVisitorBase : SqlVisitor() { + var file: PsiFile? = null + + protected fun setFile(element: PsiElement): Boolean { + if (file == null) { + file = element.containingFile + } + return false + } + + /** + * For processing inside Sql annotations, get it as an injected custom language + */ + protected fun initInjectionElement( + basePsiFile: PsiFile, + project: Project, + literal: PsiLiteralExpression, + ): PsiFile? = + when (isJavaOrKotlinFileType(basePsiFile)) { + true -> { + val injectedLanguageManager = + InjectedLanguageManager.getInstance(project) + injectedLanguageManager + .getInjectedPsiFiles(literal) + ?.firstOrNull() + ?.first as? PsiFile + } + + false -> null + } + + protected fun isLiteralOrStatic(targetElement: PsiElement): Boolean = + ( + targetElement.firstChild?.elementType == SqlTypes.EL_STRING || + targetElement.firstChild?.elementType == SqlTypes.EL_CHAR || + targetElement.firstChild?.elementType == SqlTypes.EL_NUMBER || + targetElement.firstChild?.elementType == SqlTypes.EL_NULL || + targetElement.firstChild?.elementType == SqlTypes.BOOLEAN || + targetElement.firstChild is SqlElNewExpr || + targetElement.text.startsWith("@") + ) +} diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index 8aeef742..14b1d974 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -51,6 +51,7 @@ + + +

+ Displays an error or warning if there is no test data after a bind variable. +

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

- Doma Tools displays warnings or errors for unused method arguments in SQL + Doma Tools displays warnings or errors for unused method arguments in SQL.

\ No newline at end of file diff --git a/src/main/resources/messages/DomaToolsBundle.properties b/src/main/resources/messages/DomaToolsBundle.properties index d686a372..0d5f6acb 100644 --- a/src/main/resources/messages/DomaToolsBundle.properties +++ b/src/main/resources/messages/DomaToolsBundle.properties @@ -5,4 +5,5 @@ inspection.sql.not.exist.error=SQL file does not exist inspector.invalid.class.property=The field or method [{1}] does not exist in the class [{0}] inspection.dao.method.variable.error=There are unused parameters in the SQL [{0}] inspector.invalid.dao.parameter=The bind variable [{1}] does not exist in the Dao method [{0}] -config.enable.sql.format=Enable SQL Format \ No newline at end of file +config.enable.sql.format=Enable SQL Format +inspection.invalid.sql.testdata=Bind variables must be followed by test data \ 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 ec5a9853..165a838b 100644 --- a/src/main/resources/messages/DomaToolsBundle_ja.properties +++ b/src/main/resources/messages/DomaToolsBundle_ja.properties @@ -5,4 +5,5 @@ inspection.sql.not.exist.error=SQL\u30D5\u30A1\u30A4\u30EB\u304C\u5B58\u5728\u30 inspector.invalid.class.property=\u30AF\u30E9\u30B9[{0}]\u306B\u5B58\u5728\u3057\u306A\u3044\u30D5\u30A3\u30FC\u30EB\u30C9\u3001\u307E\u305F\u306F\u30E1\u30BD\u30C3\u30C9\u304C\u4F7F\u7528\u3055\u308C\u3066\u3044\u307E\u3059:[{1}] inspection.dao.method.variable.error=SQL\u3067\u4F7F\u7528\u3055\u308C\u3066\u3044\u306A\u3044\u5F15\u6570\u304C\u3042\u308A\u307E\u3059[{0}] inspector.invalid.dao.parameter=Dao\u30E1\u30BD\u30C3\u30C9[{0}]\u306B\u5B58\u5728\u3057\u306A\u3044\u30D0\u30A4\u30F3\u30C9\u5909\u6570\u304C\u4F7F\u7528\u3055\u308C\u3066\u3044\u307E\u3059:[{1}] -config.enable.sql.format=SQL\u30D5\u30A9\u30FC\u30DE\u30C3\u30C8\u3092\u6709\u52B9\u5316 \ No newline at end of file +config.enable.sql.format=SQL\u30D5\u30A9\u30FC\u30DE\u30C3\u30C8\u3092\u6709\u52B9\u5316 +inspection.invalid.sql.testdata=\u30D0\u30A4\u30F3\u30C9\u5909\u6570\u306E\u5F8C\u308D\u306B\u306F\u30C6\u30B9\u30C8\u30C7\u30FC\u30BF\u304C\u5FC5\u8981\u3067\u3059 \ No newline at end of file From b91947de30d90a8dc96b104fc9cbaccac774bec5 Mon Sep 17 00:00:00 2001 From: xterao Date: Thu, 1 May 2025 10:29:17 +0900 Subject: [PATCH 2/2] Add TestDataCheckInspection TestCase --- .../inspection/sql/TestDataCheckTest.kt | 91 +++++++++++++++++++ .../dao/inspection/TestDataCheckDao.java | 32 +++++++ .../bindVariableDirective.sql | 7 ++ .../TestDataCheckDao/commentBlock.sql | 11 +++ .../conditionAndLoopDirective.sql | 10 ++ .../TestDataCheckDao/invalidTestData.sql | 7 ++ .../TestDataCheckDao/literalDirective.sql | 7 ++ .../TestDataCheckDao/populateDirective.sql | 3 + 8 files changed, 168 insertions(+) create mode 100644 src/test/kotlin/org/domaframework/doma/intellij/inspection/sql/TestDataCheckTest.kt create mode 100644 src/test/testData/src/main/java/doma/example/dao/inspection/TestDataCheckDao.java create mode 100644 src/test/testData/src/main/resources/META-INF/doma/example/dao/inspection/TestDataCheckDao/bindVariableDirective.sql create mode 100644 src/test/testData/src/main/resources/META-INF/doma/example/dao/inspection/TestDataCheckDao/commentBlock.sql create mode 100644 src/test/testData/src/main/resources/META-INF/doma/example/dao/inspection/TestDataCheckDao/conditionAndLoopDirective.sql create mode 100644 src/test/testData/src/main/resources/META-INF/doma/example/dao/inspection/TestDataCheckDao/invalidTestData.sql create mode 100644 src/test/testData/src/main/resources/META-INF/doma/example/dao/inspection/TestDataCheckDao/literalDirective.sql create mode 100644 src/test/testData/src/main/resources/META-INF/doma/example/dao/inspection/TestDataCheckDao/populateDirective.sql diff --git a/src/test/kotlin/org/domaframework/doma/intellij/inspection/sql/TestDataCheckTest.kt b/src/test/kotlin/org/domaframework/doma/intellij/inspection/sql/TestDataCheckTest.kt new file mode 100644 index 00000000..8d30b0e2 --- /dev/null +++ b/src/test/kotlin/org/domaframework/doma/intellij/inspection/sql/TestDataCheckTest.kt @@ -0,0 +1,91 @@ +/* + * 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.sql + +import org.domaframework.doma.intellij.DomaSqlTest +import org.domaframework.doma.intellij.inspection.sql.inspector.SqlTestDataAfterBlockCommentValidValidInspector + +class TestDataCheckTest : DomaSqlTest() { + private val testDaoName = "TestDataCheckDao" + private val packageName = "inspection" + + override fun setUp() { + super.setUp() + addDaoJavaFile( + "$packageName/$testDaoName.java", + ) + addSqlFile( + "$packageName/$testDaoName/literalDirective.sql", + "$packageName/$testDaoName/bindVariableDirective.sql", + "$packageName/$testDaoName/conditionAndLoopDirective.sql", + "$packageName/$testDaoName/commentBlock.sql", + "$packageName/$testDaoName/populateDirective.sql", + "$packageName/$testDaoName/invalidTestData.sql", + ) + myFixture.enableInspections(SqlTestDataAfterBlockCommentValidValidInspector()) + } + + fun testLiteralDirective() { + val sqlFile = findSqlFile("$packageName/$testDaoName/literalDirective.sql") + assertNotNull("Not Found SQL File", sqlFile) + if (sqlFile == null) return + + myFixture.testHighlighting(false, false, false, sqlFile) + } + + fun testBindVariableDirective() { + val sqlFile = findSqlFile("$packageName/$testDaoName/bindVariableDirective.sql") + assertNotNull("Not Found SQL File", sqlFile) + if (sqlFile == null) return + + myFixture.testHighlighting(false, false, false, sqlFile) + } + + fun testConditionAndLoopDirective() { + val sqlFile = findSqlFile("$packageName/$testDaoName/conditionAndLoopDirective.sql") + assertNotNull("Not Found SQL File", sqlFile) + if (sqlFile == null) return + + myFixture.testHighlighting(false, false, false, sqlFile) + } + + fun testCommentBlock() { + val sqlFile = + findSqlFile("$packageName/$testDaoName/commentBlock.sql") + assertNotNull("Not Found SQL File", sqlFile) + if (sqlFile == null) return + + myFixture.testHighlighting(false, false, false, sqlFile) + } + + fun testPopulateDirective() { + val sqlFile = + findSqlFile("$packageName/$testDaoName/populateDirective.sql") + assertNotNull("Not Found SQL File", sqlFile) + if (sqlFile == null) return + + myFixture.testHighlighting(false, false, false, sqlFile) + } + + fun testInvalidTestData() { + val sqlFile = + findSqlFile("$packageName/$testDaoName/invalidTestData.sql") + assertNotNull("Not Found SQL File", sqlFile) + if (sqlFile == null) return + + myFixture.testHighlighting(false, false, false, sqlFile) + } +} diff --git a/src/test/testData/src/main/java/doma/example/dao/inspection/TestDataCheckDao.java b/src/test/testData/src/main/java/doma/example/dao/inspection/TestDataCheckDao.java new file mode 100644 index 00000000..0f603b96 --- /dev/null +++ b/src/test/testData/src/main/java/doma/example/dao/inspection/TestDataCheckDao.java @@ -0,0 +1,32 @@ +package doma.example.dao.inspection; + +import doma.example.entity.*: +import org.seasar.doma.*; +import org.seasar.doma.jdbc.Config; +import org.seasar.doma.jdbc.PreparedSql; +import org.seasar.doma.jdbc.SelectOptions; + +import java.util.List; +import java.util.function.BiFunction; + +@Dao +interface TestDataCheckDao { + + @Select + EmployeeSummary literalDirective(String literalName, Integer literalId, Integer literalAge); + + @Insert(sqlFile=true) + int bindVariableDirective(Employee employee); + + @Select + List conditionAndLoopDirective(List projects,LocalDate referenceDate); + + @Select + Employee commentBlock(Integer id); + + @Update(sqlFile=true) + int populateDirective(Employee employee); + + @Insert(sqlFile=true) + int invalidTestData(Employee employee); +} \ No newline at end of file diff --git a/src/test/testData/src/main/resources/META-INF/doma/example/dao/inspection/TestDataCheckDao/bindVariableDirective.sql b/src/test/testData/src/main/resources/META-INF/doma/example/dao/inspection/TestDataCheckDao/bindVariableDirective.sql new file mode 100644 index 00000000..c78405b6 --- /dev/null +++ b/src/test/testData/src/main/resources/META-INF/doma/example/dao/inspection/TestDataCheckDao/bindVariableDirective.sql @@ -0,0 +1,7 @@ +INSERT INTO employee + (employee_id + , employee_name + , department_name) + VALUES ( /* employee.employeeId */0 + , /* employee.employeeName */ + , /* employee.department */) diff --git a/src/test/testData/src/main/resources/META-INF/doma/example/dao/inspection/TestDataCheckDao/commentBlock.sql b/src/test/testData/src/main/resources/META-INF/doma/example/dao/inspection/TestDataCheckDao/commentBlock.sql new file mode 100644 index 00000000..86c720b6 --- /dev/null +++ b/src/test/testData/src/main/resources/META-INF/doma/example/dao/inspection/TestDataCheckDao/commentBlock.sql @@ -0,0 +1,11 @@ +-- This Comment Line +SELECT e.employee_id AS employeeId + , e.employee_name AS employeeName + , e.department_name AS departmentName + /** + This is a comment block + */ + FROM employee e + /*%! This comment will be removed */ + WHERE e.employee_id = /*^ id */ + AND e.age >= /*^ literalAge */99 \ No newline at end of file diff --git a/src/test/testData/src/main/resources/META-INF/doma/example/dao/inspection/TestDataCheckDao/conditionAndLoopDirective.sql b/src/test/testData/src/main/resources/META-INF/doma/example/dao/inspection/TestDataCheckDao/conditionAndLoopDirective.sql new file mode 100644 index 00000000..c8f461da --- /dev/null +++ b/src/test/testData/src/main/resources/META-INF/doma/example/dao/inspection/TestDataCheckDao/conditionAndLoopDirective.sql @@ -0,0 +1,10 @@ +SELECT * + FROM employee + WHERE join_at <= /* referenceDate */ + /*%for project : projects */ + employee_name LIKE /* project.projectName */'hoge' + /*%if project_has_next */ + /*# "or" */ + /*%end */ + /*%end*/ + OR salary > 1000 diff --git a/src/test/testData/src/main/resources/META-INF/doma/example/dao/inspection/TestDataCheckDao/invalidTestData.sql b/src/test/testData/src/main/resources/META-INF/doma/example/dao/inspection/TestDataCheckDao/invalidTestData.sql new file mode 100644 index 00000000..b256a6d6 --- /dev/null +++ b/src/test/testData/src/main/resources/META-INF/doma/example/dao/inspection/TestDataCheckDao/invalidTestData.sql @@ -0,0 +1,7 @@ +INSERT INTO employee + (employee_id + , employee_name + , department_name) + VALUES ( /* employee.employeeId */0 + , /* employee.employeeName */'name' + , /* employee.department */department) diff --git a/src/test/testData/src/main/resources/META-INF/doma/example/dao/inspection/TestDataCheckDao/literalDirective.sql b/src/test/testData/src/main/resources/META-INF/doma/example/dao/inspection/TestDataCheckDao/literalDirective.sql new file mode 100644 index 00000000..a34978c9 --- /dev/null +++ b/src/test/testData/src/main/resources/META-INF/doma/example/dao/inspection/TestDataCheckDao/literalDirective.sql @@ -0,0 +1,7 @@ +SELECT e.employee_id AS employeeId + , e.employee_name AS employeeName + , e.department_name AS departmentName + FROM employee e + WHERE e.employee_id = /*^ literalId */ + AND e.employee_name = /*^ literalName */ + AND e.age >= /*^ literalAge */99 diff --git a/src/test/testData/src/main/resources/META-INF/doma/example/dao/inspection/TestDataCheckDao/populateDirective.sql b/src/test/testData/src/main/resources/META-INF/doma/example/dao/inspection/TestDataCheckDao/populateDirective.sql new file mode 100644 index 00000000..8c0d8118 --- /dev/null +++ b/src/test/testData/src/main/resources/META-INF/doma/example/dao/inspection/TestDataCheckDao/populateDirective.sql @@ -0,0 +1,3 @@ +UPDATE employee + SET /*%populate*/id = id + WHERE rank < /* emplotee.rank */