Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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,
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -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)
}
Original file line number Diff line number Diff line change
@@ -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<Class<out LocalInspectionTool>> =
arrayOf(
SqlTestDataAfterBlockCommentValidValidInspector::class.java,
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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<SqlElIdExpr> {
val blockElements = element.accessElements
(blockElements.firstOrNull() as? SqlElPrimaryExpr)
Expand Down
Original file line number Diff line number Diff line change
@@ -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+$"))
}
Original file line number Diff line number Diff line change
@@ -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("@")
)
}
1 change: 1 addition & 0 deletions src/main/resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
<inspectionToolProvider implementation="org.domaframework.doma.intellij.inspection.dao.provider.SqlFileExistProvider" />
<inspectionToolProvider implementation="org.domaframework.doma.intellij.inspection.sql.provider.SqlBindVariableValidProvider" />
<inspectionToolProvider implementation="org.domaframework.doma.intellij.inspection.dao.provider.DaoMethodVariableProvider" />
<inspectionToolProvider implementation="org.domaframework.doma.intellij.inspection.sql.provider.SqlTestDataAfterBlockCommentValidProvider" />

<!-- Completion -->
<completion.contributor language="DomaSql"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<html lang="en">
<body>
<p>
Displays an error or warning if there is no test data after a bind variable.
</p>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<html lang="en">
<body>
<p>
Doma Tools displays warnings or errors for unused method arguments in SQL
Doma Tools displays warnings or errors for unused method arguments in SQL.
</p>
</body>
</html>
Loading