diff --git a/README.md b/README.md index f970c166..a1ede659 100644 --- a/README.md +++ b/README.md @@ -97,4 +97,11 @@ Some functions of "Doma Tools" can be customized from the settings screen. - Customize action shortcut keys - Toggle the SQL formatting feature on or off - Specify the class names that define custom functions. - ![setting.png](images/setting.png) + +**If you want to use custom functions defined in your own ExpressionFunctions implementation class, +place a `doma.compile.config` file directly under the resources directory and describe the `doma.expr.functions` entry.** + +ex) doma.compile.config +```properties +doma.expr.functions=example.expression.MyExpressionFunctions +``` diff --git a/images/setting.png b/images/setting.png deleted file mode 100644 index 54cf66bf..00000000 Binary files a/images/setting.png and /dev/null differ diff --git a/src/main/kotlin/org/domaframework/doma/intellij/common/CommonPathParameter.kt b/src/main/kotlin/org/domaframework/doma/intellij/common/CommonPathParameter.kt new file mode 100644 index 00000000..6af8e78c --- /dev/null +++ b/src/main/kotlin/org/domaframework/doma/intellij/common/CommonPathParameter.kt @@ -0,0 +1,161 @@ +/* + * 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 + +import com.intellij.openapi.module.Module +import com.intellij.openapi.roots.ModuleRootManager +import com.intellij.openapi.vfs.VirtualFile +import org.jetbrains.jps.model.java.JavaResourceRootType +import org.jetbrains.jps.model.java.JavaSourceRootType +import java.util.concurrent.ConcurrentHashMap + +val RESOURCES_META_INF_PATH: String + get() = "META-INF" + +/** + * A utility for caching directory information on a per-module basis. + */ +object CommonPathParameterUtil { + /** + * Holds directory information for a module. + * + * @property moduleBasePath The base path of the module. + * @property moduleSourceDirectories List of source directories. + * @property moduleResourceDirectories List of resource directories. + * @property moduleTestSourceDirectories List of test source directories. + * @property moduleTestResourceDirectories List of test resource directories. + */ + data class ModulePaths( + val moduleBasePath: VirtualFile?, + val moduleSourceDirectories: List, + val moduleResourceDirectories: List, + val moduleTestSourceDirectories: List, + val moduleTestResourceDirectories: List, + ) + + // Cache for each module's directory information. + private val modulePathCache = ConcurrentHashMap() + + /** + * Returns the directory information for the specified module (uses cache if available). + * If the module's directory structure has changed, call [refreshModulePaths] to update the cache. + * + * @param module The module to retrieve directory information for. + * @return The cached or newly computed ModulePaths. + */ + fun getModulePaths(module: Module): ModulePaths = modulePathCache[module] ?: refreshModulePaths(module) + + /** + * Refreshes the directory information for the specified module and updates the cache. + * Call this method when the module's directory structure changes. + * + * @param module The module to refresh. + * @return The updated ModulePaths. + */ + fun refreshModulePaths(module: Module): ModulePaths { + var basePath: VirtualFile? = null + val sourceDirs = mutableListOf() + val resourceDirs = mutableListOf() + val testSourceDirs = mutableListOf() + val testResourceDirs = mutableListOf() + + val moduleManager = ModuleRootManager.getInstance(module) + moduleManager.contentEntries.firstOrNull()?.let { entry -> + basePath = entry.file + entry.sourceFolders.forEach { folder -> + val file = folder.file + if (file != null) { + when (folder.rootType) { + JavaSourceRootType.SOURCE -> sourceDirs.add(file) + JavaSourceRootType.TEST_SOURCE -> testSourceDirs.add(file) + JavaResourceRootType.RESOURCE -> resourceDirs.add(file) + JavaResourceRootType.TEST_RESOURCE -> testResourceDirs.add(file) + } + } + } + } + val paths = + ModulePaths( + basePath, + sourceDirs, + resourceDirs, + testSourceDirs, + testResourceDirs, + ) + modulePathCache[module] = paths + return paths + } + + /** + * Determines if the given file belongs to a test source or test resource directory. + * + * @param module The module to check. + * @param file The file to check. + * @return True if the file is in a test directory, false otherwise. + */ + fun isTest( + module: Module, + file: VirtualFile, + ): Boolean { + val paths = getModulePaths(module) + if (paths.moduleTestSourceDirectories.any { file.path.contains(it.path) }) return true + if (paths.moduleTestResourceDirectories.any { file.path.contains(it.path) }) return true + return false + } + + /** + * Returns the resource directories for the given file in the specified module. + * If the file is in a test directory, test resource directories are returned. + * + * @param module The module to check. + * @param file The file to check. + * @return List of resource directories. + */ + fun getResources( + module: Module, + file: VirtualFile, + ): List = + if (isTest(module, file)) { + getModulePaths(module).moduleTestResourceDirectories + } else { + getModulePaths(module).moduleResourceDirectories + } + + /** + * Returns the source directories for the given file in the specified module. + * If the file is in a test directory, test source directories are returned. + * + * @param module The module to check. + * @param file The file to check. + * @return List of source directories. + */ + fun getSources( + module: Module, + file: VirtualFile, + ): List = + if (isTest(module, file)) { + getModulePaths(module).moduleTestSourceDirectories + } else { + getModulePaths(module).moduleSourceDirectories + } + + /** + * Clears the module directory cache. Call this if the module structure changes. + */ + fun clearCache() { + modulePathCache.clear() + } +} diff --git a/src/main/kotlin/org/domaframework/doma/intellij/common/CommonPathParameterHelper.kt b/src/main/kotlin/org/domaframework/doma/intellij/common/CommonPathParameterHelper.kt deleted file mode 100644 index 49216d30..00000000 --- a/src/main/kotlin/org/domaframework/doma/intellij/common/CommonPathParameterHelper.kt +++ /dev/null @@ -1,110 +0,0 @@ -/* - * 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 - -import com.intellij.openapi.module.Module -import com.intellij.openapi.roots.ModuleRootManager -import com.intellij.openapi.vfs.VirtualFile -import org.jetbrains.jps.model.java.JavaResourceRootType -import org.jetbrains.jps.model.java.JavaSourceRootType - -val RESOURCES_META_INF_PATH: String - get() = "META-INF" - -class CommonPathParameter( - module: Module?, -) { - /** - * module base path ex)Absolute path of "/src/main" - */ - var moduleBasePath: VirtualFile? = null - - /** - * module source directories ex) Absolute path of "/src/main/java","/src/main/kotlin" - */ - var moduleSourceDirectories: MutableList = mutableListOf() - - /** - * module resource directory ex) Absolute path of "/src/main/resources" - */ - var moduleResourceDirectories: MutableList = mutableListOf() - - var moduleTestSourceDirectories: MutableList = mutableListOf() - var moduleTestResourceDirectories: MutableList = mutableListOf() - - init { - setModuleSourcesFiles(module) - } - - private fun setModuleSourcesFiles(module: Module?) { - if (module == null) return - - val modulemanager = ModuleRootManager.getInstance(module) - - moduleSourceDirectories.clear() - modulemanager?.contentEntries?.firstOrNull()?.let { entry -> - moduleBasePath = entry.file - entry.sourceFolders.map { folder -> - val file = folder.file - if (file != null) { - when (folder.rootType) { - JavaSourceRootType.SOURCE -> { - moduleSourceDirectories.add(file) - } - - JavaSourceRootType.TEST_SOURCE -> { - moduleTestSourceDirectories.add(file) - } - - JavaResourceRootType.RESOURCE -> { - moduleResourceDirectories.add(file) - } - - JavaResourceRootType.TEST_RESOURCE -> { - moduleTestResourceDirectories.add(file) - } - } - } - } - } - } - - fun isTest(file: VirtualFile): Boolean { - val testSource = - moduleTestSourceDirectories.firstOrNull { testSource -> - file.path.contains(testSource.path) - } - if (testSource != null) return true - - return moduleTestResourceDirectories.firstOrNull { testSource -> - file.path.contains(testSource.path) - } != null - } - - fun getResources(file: VirtualFile): MutableList = - if (isTest(file)) { - moduleTestResourceDirectories - } else { - moduleResourceDirectories - } - - fun getSources(file: VirtualFile): MutableList = - if (isTest(file)) { - moduleTestSourceDirectories - } else { - moduleSourceDirectories - } -} diff --git a/src/main/kotlin/org/domaframework/doma/intellij/common/config/DomaCompileConfigUtil.kt b/src/main/kotlin/org/domaframework/doma/intellij/common/config/DomaCompileConfigUtil.kt new file mode 100644 index 00000000..816f79ee --- /dev/null +++ b/src/main/kotlin/org/domaframework/doma/intellij/common/config/DomaCompileConfigUtil.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.common.config + +import com.intellij.openapi.project.Project +import com.intellij.openapi.vfs.VirtualFile +import org.domaframework.doma.intellij.common.CommonPathParameterUtil +import java.util.concurrent.ConcurrentHashMap + +object DomaCompileConfigUtil { + /** + * Cache: key=file path, value=Pair + */ + private val configCache = ConcurrentHashMap>() + + /** + * Get the value of the specified key from doma.compile.config + * @param project active project + * @param resourcePaths the path to the resource directories + * @param key the key to retrieve the value for + * @return the value associated with the key, or null if not found + */ + fun getConfigValue( + project: Project, + resourcePaths: List, + key: String, + ): String? { + resourcePaths.forEach { resourcePath -> + if (resourcePath.isValid) { + val configVFile = resourcePath.findChild("doma.compile.config") + val cacheKey = "${project.basePath}/${resourcePath.path}/doma.compile.config" + val lastModified = configVFile?.timeStamp ?: 0L + val cached = configCache[cacheKey] + + val props = + if (cached == null || cached.second != lastModified) { + val loadedProps = + configVFile?.inputStream?.use { input -> + java.util.Properties().apply { load(input) } + } ?: java.util.Properties() + configCache[cacheKey] = loadedProps to lastModified + loadedProps + } else { + cached.first + } + val propProperty = props.getProperty(key) + if (propProperty != null) return propProperty + } else { + CommonPathParameterUtil.clearCache() + } + } + return null + } +} diff --git a/src/main/kotlin/org/domaframework/doma/intellij/common/dao/DaoMethodUtil.kt b/src/main/kotlin/org/domaframework/doma/intellij/common/dao/DaoMethodUtil.kt index d488bd83..e6d4a5ba 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/common/dao/DaoMethodUtil.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/common/dao/DaoMethodUtil.kt @@ -27,7 +27,7 @@ import com.intellij.psi.PsiManager import com.intellij.psi.PsiMethod import com.intellij.psi.search.GlobalSearchScope import com.intellij.psi.util.PsiTreeUtil -import org.domaframework.doma.intellij.common.CommonPathParameter +import org.domaframework.doma.intellij.common.CommonPathParameterUtil import org.domaframework.doma.intellij.common.RESOURCES_META_INF_PATH import org.domaframework.doma.intellij.common.getExtension import org.domaframework.doma.intellij.common.getJarRoot @@ -76,8 +76,8 @@ fun findDaoMethod( .trim('.') val daoJavaFile = project.findFile(daoFile) - val paramParameter = CommonPathParameter(module) - findDaoClass(module, paramParameter.isTest(originalFile.virtualFile), daoClassName) + val isTest = CommonPathParameterUtil.isTest(module, originalFile.virtualFile) + findDaoClass(module, isTest, daoClassName) ?.let { daoClass -> val daoMethod = // TODO Support Kotlin Project @@ -144,12 +144,12 @@ private fun searchDaoFile( sqlFile: PsiFile, ): VirtualFile? { val contentRootPath = contentRoot?.path ?: return null - val pathParams = CommonPathParameter(module) + val pathParams = module?.let { CommonPathParameterUtil.getModulePaths(it) } ?: return null val moduleBaseName = pathParams.moduleBasePath?.nameWithoutExtension ?: "" // TODO: Add Support Kotlin val relativeDaoFilePaths = getDaoPathFromSqlFilePath(sqlFile, contentRoot.path) - val sources = pathParams.getSources(sqlFile.virtualFile) + val sources = CommonPathParameterUtil.getSources(module, sqlFile.virtualFile) if (contentRootPath.endsWith(moduleBaseName) == true) { sources.forEach { source -> @@ -189,8 +189,9 @@ private fun getDaoPathFromSqlFilePath( if (!relativeFilePath.startsWith("/")) { relativeFilePath = "/$relativeFilePath" } - val pathParams = CommonPathParameter(module) - val resources = pathParams.getResources(sqlFile.virtualFile) + val resources = + module?.let { CommonPathParameterUtil.getResources(it, sqlFile.virtualFile) } + ?: emptyList() return resources .firstOrNull { resource -> @@ -214,28 +215,18 @@ fun getRelativeSqlFilePathFromDaoFilePath( ): String { if (module == null) return "" val extension = daoFile.fileType.defaultExtension - val pathParams = CommonPathParameter(module) + val pathParams = CommonPathParameterUtil.getModulePaths(module) var relativeSqlFilePath = daoFile.path .replace(pathParams.moduleBasePath?.path ?: "", "") .replace(".$extension", "") - val isTest = pathParams.moduleTestSourceDirectories.firstOrNull { dir -> daoFile.path.contains(dir.path) } != null - if (isTest) { - pathParams.moduleTestSourceDirectories.forEach { source -> - relativeSqlFilePath = - relativeSqlFilePath.replace( - "/" + source.nameWithoutExtension, - RESOURCES_META_INF_PATH, - ) - } - } else { - pathParams.moduleSourceDirectories.forEach { source -> - relativeSqlFilePath = - relativeSqlFilePath.replace( - "/" + source.nameWithoutExtension, - RESOURCES_META_INF_PATH, - ) - } + val sources = CommonPathParameterUtil.getSources(module, daoFile) + sources.forEach { source -> + relativeSqlFilePath = + relativeSqlFilePath.replace( + "/" + source.nameWithoutExtension, + RESOURCES_META_INF_PATH, + ) } return relativeSqlFilePath } diff --git a/src/main/kotlin/org/domaframework/doma/intellij/common/psi/PsiDaoMethod.kt b/src/main/kotlin/org/domaframework/doma/intellij/common/psi/PsiDaoMethod.kt index b1a5c6e7..7b02a818 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/common/psi/PsiDaoMethod.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/common/psi/PsiDaoMethod.kt @@ -32,7 +32,7 @@ import com.intellij.psi.PsiManager import com.intellij.psi.PsiMethod import com.intellij.psi.PsiNameValuePair import com.intellij.util.IncorrectOperationException -import org.domaframework.doma.intellij.common.CommonPathParameter +import org.domaframework.doma.intellij.common.CommonPathParameterUtil import org.domaframework.doma.intellij.common.RESOURCES_META_INF_PATH import org.domaframework.doma.intellij.common.dao.getRelativeSqlFilePathFromDaoFilePath import org.domaframework.doma.intellij.common.getExtension @@ -72,8 +72,7 @@ class PsiDaoMethod( } private fun setTest() { - val pathParameter = CommonPathParameter(psiMethod.module) - isTest = pathParameter.isTest(daoFile) + psiMethod.module?.let { isTest = CommonPathParameterUtil.isTest(it, daoFile) } } private fun setSqlFileOption() { @@ -182,8 +181,10 @@ class PsiDaoMethod( val rootDir = psiProject.getContentRoot(daoFile) ?: return@runReadAction val sqlFile = File(sqlFilePath) val sqlFileName = sqlFile.name - val pathParams = CommonPathParameter(psiMethod.module) - val resourceDir = pathParams.getResources(daoFile).firstOrNull() ?: return@runReadAction + val resourceDir = + psiMethod.module + ?.let { CommonPathParameterUtil.getResources(it, daoFile).firstOrNull() } + ?: return@runReadAction val parentDir = "${resourceDir.nameWithoutExtension}/${sqlFile.parent?.replace("\\", "/")}" val parenDirPathSpirit = parentDir.split("/").toTypedArray() diff --git a/src/main/kotlin/org/domaframework/doma/intellij/common/sql/directive/StaticDirectiveHandler.kt b/src/main/kotlin/org/domaframework/doma/intellij/common/sql/directive/StaticDirectiveHandler.kt index eba78eb3..23c35473 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/common/sql/directive/StaticDirectiveHandler.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/common/sql/directive/StaticDirectiveHandler.kt @@ -93,7 +93,7 @@ class StaticDirectiveHandler( ): Boolean { if (BindDirectiveUtil.getDirectiveType(element) == DirectiveType.BUILT_IN) { val prefix = getBindSearchWord(element, bindText) - val collector = StaticBuildFunctionCollector(element.project, prefix) + val collector = StaticBuildFunctionCollector(element.containingFile, prefix) val candidates = collector.collect() candidates?.let { it1 -> result.addAllElements(it1) } return true diff --git a/src/main/kotlin/org/domaframework/doma/intellij/common/sql/directive/collector/StaticBuildFunctionCollector.kt b/src/main/kotlin/org/domaframework/doma/intellij/common/sql/directive/collector/StaticBuildFunctionCollector.kt index c11fd7b4..e045e236 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/common/sql/directive/collector/StaticBuildFunctionCollector.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/common/sql/directive/collector/StaticBuildFunctionCollector.kt @@ -18,39 +18,48 @@ package org.domaframework.doma.intellij.common.sql.directive.collector import com.intellij.codeInsight.lookup.AutoCompletionPolicy import com.intellij.codeInsight.lookup.LookupElement import com.intellij.codeInsight.lookup.LookupElementBuilder -import com.intellij.openapi.project.Project +import com.intellij.psi.PsiFile import com.intellij.psi.PsiMethod import com.intellij.psi.PsiModifier +import org.domaframework.doma.intellij.common.CommonPathParameterUtil +import org.domaframework.doma.intellij.common.config.DomaCompileConfigUtil import org.domaframework.doma.intellij.common.helper.ExpressionFunctionsHelper import org.domaframework.doma.intellij.extension.getJavaClazz -import org.domaframework.doma.intellij.setting.state.DomaToolsCustomFunctionSettings +import org.jetbrains.kotlin.idea.base.util.module class StaticBuildFunctionCollector( - private val project: Project, + private val file: PsiFile?, private val bind: String, ) : StaticDirectiveHandlerCollector() { public override fun collect(): List? { var functions = mutableSetOf() - val setting = DomaToolsCustomFunctionSettings.getInstance(project) - val state = setting.state - val customFunctions = state.customFunctionClassNames + val project = file?.project + val module = file?.module + val resourcePaths = + if (file?.virtualFile != null && module != null) { + CommonPathParameterUtil + .getResources(module, file.virtualFile) + } else { + emptyList() + } + + val customFunctionClassName = + project?.let { DomaCompileConfigUtil.getConfigValue(it, resourcePaths, "doma.expr.functions") } val expressionFunctionInterface = - ExpressionFunctionsHelper.setExpressionFunctionsInterface(project) + project?.let { ExpressionFunctionsHelper.setExpressionFunctionsInterface(it) } ?: return null - customFunctions.forEach { function -> - val expressionClazz = project.getJavaClazz(function) - if (expressionClazz != null && - ExpressionFunctionsHelper.isInheritor(expressionClazz) - ) { - val methods = expressionClazz.allMethods - functions.addAll( - methods.filter { - isPublicFunction(it) - }, - ) - } + val expressionClazz = customFunctionClassName?.let { project.getJavaClazz(it) } + if (expressionClazz != null && + ExpressionFunctionsHelper.isInheritor(expressionClazz) + ) { + val methods = expressionClazz.allMethods + functions.addAll( + methods.filter { + isPublicFunction(it) + }, + ) } if (functions.isEmpty()) { diff --git a/src/main/kotlin/org/domaframework/doma/intellij/common/sql/validator/result/ValidationInvalidExpressionFunctionsResult.kt b/src/main/kotlin/org/domaframework/doma/intellij/common/sql/validator/result/ValidationInvalidExpressionFunctionsResult.kt new file mode 100644 index 00000000..a7603d18 --- /dev/null +++ b/src/main/kotlin/org/domaframework/doma/intellij/common/sql/validator/result/ValidationInvalidExpressionFunctionsResult.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.sql.validator.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 + +/** + * Reports that the class configured in doma.compile.config + * is not an implementation of ExpressionFunctions. + */ +open class ValidationInvalidExpressionFunctionsResult( + 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.sql.notFound.expressionClass", + ), + problemHighlightType(project, shortName), + highlightRange, + ) + } +} diff --git a/src/main/kotlin/org/domaframework/doma/intellij/common/sql/validator/result/ValidationInvalidFunctionCallResult.kt b/src/main/kotlin/org/domaframework/doma/intellij/common/sql/validator/result/ValidationInvalidFunctionCallResult.kt index c9350143..f97d70cf 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/common/sql/validator/result/ValidationInvalidFunctionCallResult.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/common/sql/validator/result/ValidationInvalidFunctionCallResult.kt @@ -38,7 +38,7 @@ open class ValidationInvalidFunctionCallResult( holder.registerProblem( identify, MessageBundle.message( - "inspection.invalid.sql.customFunction", + "inspection.invalid.sql.notFound.customFunction", identify.text ?: "", ), problemHighlightType(project, shortName), diff --git a/src/main/kotlin/org/domaframework/doma/intellij/extension/ModuleExtensions.kt b/src/main/kotlin/org/domaframework/doma/intellij/extension/ModuleExtensions.kt index adb3d034..111f3c75 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/extension/ModuleExtensions.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/extension/ModuleExtensions.kt @@ -21,6 +21,7 @@ import com.intellij.openapi.vfs.VirtualFile import com.intellij.psi.JavaPsiFacade import com.intellij.psi.PsiClass import com.intellij.psi.search.GlobalSearchScope +import org.domaframework.doma.intellij.common.CommonPathParameterUtil import org.domaframework.doma.intellij.common.dao.getRelativeSqlFilePathFromDaoFilePath /** @@ -32,10 +33,10 @@ fun Module.getPackagePathFromDaoPath(daoFile: VirtualFile): VirtualFile? { contentRoot?.let { getRelativeSqlFilePathFromDaoFilePath(daoFile, this) } ?: "" - + val isTest = CommonPathParameterUtil.isTest(this, daoFile) return this.getResourcesSQLFile( packagePath, - false, + isTest, ) } diff --git a/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/inspector/SqlFileExistInspector.kt b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/inspector/SqlFileExistInspector.kt index b1ea94d6..5fc7333b 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/inspector/SqlFileExistInspector.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/inspection/dao/inspector/SqlFileExistInspector.kt @@ -46,6 +46,7 @@ class SqlFileExistInspector : AbstractBaseJavaLocalInspectionTool() { holder: ProblemsHolder, isOnTheFly: Boolean, ): PsiElementVisitor { + // TODO Support Kotlin Project return object : JavaElementVisitor() { override fun visitMethod(method: PsiMethod) { super.visitMethod(method) diff --git a/src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/processor/InspectionFunctionCallVisitorProcessor.kt b/src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/processor/InspectionFunctionCallVisitorProcessor.kt index eaa6f9a1..04ab7c45 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/processor/InspectionFunctionCallVisitorProcessor.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/inspection/sql/processor/InspectionFunctionCallVisitorProcessor.kt @@ -17,11 +17,15 @@ package org.domaframework.doma.intellij.inspection.sql.processor import com.intellij.codeInspection.ProblemsHolder import com.intellij.psi.PsiMethod +import org.domaframework.doma.intellij.common.CommonPathParameterUtil +import org.domaframework.doma.intellij.common.config.DomaCompileConfigUtil import org.domaframework.doma.intellij.common.helper.ExpressionFunctionsHelper +import org.domaframework.doma.intellij.common.sql.validator.result.ValidationInvalidExpressionFunctionsResult import org.domaframework.doma.intellij.common.sql.validator.result.ValidationInvalidFunctionCallResult +import org.domaframework.doma.intellij.common.sql.validator.result.ValidationResult import org.domaframework.doma.intellij.extension.getJavaClazz import org.domaframework.doma.intellij.psi.SqlElFunctionCallExpr -import org.domaframework.doma.intellij.setting.state.DomaToolsCustomFunctionSettings +import org.jetbrains.kotlin.idea.util.projectStructure.module class InspectionFunctionCallVisitorProcessor( val shortName: String, @@ -31,19 +35,30 @@ class InspectionFunctionCallVisitorProcessor( val project = element.project val expressionHelper = ExpressionFunctionsHelper val expressionFunctionalInterface = expressionHelper.setExpressionFunctionsInterface(project) - val functionName = element.elIdExpr - val expressionFunctionSetting = DomaToolsCustomFunctionSettings.getInstance(project) - val customFunctionClassNames = expressionFunctionSetting.state.customFunctionClassNames + val resources = + element.module + ?.let { CommonPathParameterUtil.getResources(it, element.containingFile.virtualFile) } + ?: emptyList() + val customFunctionClassName = DomaCompileConfigUtil.getConfigValue(project, resources, "doma.expr.functions") + + var result: ValidationResult = + ValidationInvalidFunctionCallResult( + functionName, + shortName, + ) var methods: Array = emptyArray() - for (clazz in customFunctionClassNames) { - val expressionClazz = project.getJavaClazz(clazz) - if (expressionClazz != null && expressionHelper.isInheritor(expressionClazz)) { + val expressionClazz = customFunctionClassName?.let { project.getJavaClazz(it) } + if (expressionClazz != null) { + if (expressionHelper.isInheritor(expressionClazz)) { methods = expressionClazz.findMethodsByName(functionName.text, true) - if (methods.isNotEmpty()) { - break - } + } else { + result = + ValidationInvalidExpressionFunctionsResult( + functionName, + shortName, + ) } } @@ -52,10 +67,7 @@ class InspectionFunctionCallVisitorProcessor( } if (methods.isEmpty()) { - ValidationInvalidFunctionCallResult( - functionName, - shortName, - ).highlightElement(holder) + result.highlightElement(holder) } } } diff --git a/src/main/kotlin/org/domaframework/doma/intellij/refactoring/dao/DaoMethodRenameProcessor.kt b/src/main/kotlin/org/domaframework/doma/intellij/refactoring/dao/DaoMethodRenameProcessor.kt index e442ff0c..959ed919 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/refactoring/dao/DaoMethodRenameProcessor.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/refactoring/dao/DaoMethodRenameProcessor.kt @@ -20,6 +20,7 @@ import com.intellij.psi.PsiMethod import com.intellij.refactoring.listeners.RefactoringElementListener import com.intellij.refactoring.rename.RenameJavaMethodProcessor import com.intellij.usageView.UsageInfo +import org.domaframework.doma.intellij.common.CommonPathParameterUtil import org.domaframework.doma.intellij.common.psi.PsiDaoMethod import org.domaframework.doma.intellij.common.util.PluginLoggerUtil @@ -42,6 +43,8 @@ class DaoMethodRenameProcessor : RenameJavaMethodProcessor() { usages: Array, listener: RefactoringElementListener?, ) { + // Clear module directory cache on refactoring + CommonPathParameterUtil.clearCache() val startTime = System.nanoTime() if (element is PsiMethod) { val psiDaoMethod = PsiDaoMethod(element.project, element) diff --git a/src/main/kotlin/org/domaframework/doma/intellij/refactoring/dao/DaoPackageRenameListenerProcessor.kt b/src/main/kotlin/org/domaframework/doma/intellij/refactoring/dao/DaoPackageRenameListenerProcessor.kt index 25106001..7397703f 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/refactoring/dao/DaoPackageRenameListenerProcessor.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/refactoring/dao/DaoPackageRenameListenerProcessor.kt @@ -29,7 +29,7 @@ import com.intellij.psi.PsiPackage import com.intellij.refactoring.listeners.RefactoringElementListener import com.intellij.refactoring.listeners.RefactoringElementListenerProvider import com.intellij.util.IncorrectOperationException -import org.domaframework.doma.intellij.common.CommonPathParameter +import org.domaframework.doma.intellij.common.CommonPathParameterUtil import org.domaframework.doma.intellij.common.RESOURCES_META_INF_PATH import org.domaframework.doma.intellij.common.dao.getDaoClass import org.domaframework.doma.intellij.common.util.PluginLoggerUtil @@ -53,6 +53,8 @@ class DaoPackageRenameListenerProcessor : RefactoringElementListenerProvider { return object : RefactoringElementListener { override fun elementMoved(newelement: PsiElement) { + // Clear module directory cache on refactoring + CommonPathParameterUtil.clearCache() if (newelement is PsiClass) { if (getDaoClass(newelement.containingFile) == null) return refactoringMoveClassFile(module, newelement) @@ -62,6 +64,8 @@ class DaoPackageRenameListenerProcessor : RefactoringElementListenerProvider { } override fun elementRenamed(newelement: PsiElement) { + // Clear module directory cache on refactoring + CommonPathParameterUtil.clearCache() if (newelement is PsiClass) return refactoringPackageRenameOrMove(module, newelement) } @@ -135,9 +139,8 @@ class DaoPackageRenameListenerProcessor : RefactoringElementListenerProvider { file: VirtualFile, moveFileName: String? = null, ) { - val pathParameter = CommonPathParameter(module) - val resources = pathParameter.getResources(file) - val isTest = pathParameter.isTest(file) + val resources = CommonPathParameterUtil.getResources(module, file) + val isTest = CommonPathParameterUtil.isTest(module, file) val baseDirs: List = resources.map { resource -> "${resource.path}/$RESOURCES_META_INF_PATH/" } val newPaths = baseDirs.map { baseDir -> "$baseDir/${newQualifiedName.replace(".", "/")}" } diff --git a/src/main/kotlin/org/domaframework/doma/intellij/refactoring/dao/DaoRenameProcessor.kt b/src/main/kotlin/org/domaframework/doma/intellij/refactoring/dao/DaoRenameProcessor.kt index 55231aa0..0a23ddce 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/refactoring/dao/DaoRenameProcessor.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/refactoring/dao/DaoRenameProcessor.kt @@ -19,6 +19,7 @@ import com.intellij.psi.PsiElement import com.intellij.refactoring.listeners.RefactoringElementListener import com.intellij.refactoring.rename.RenameJavaClassProcessor import com.intellij.usageView.UsageInfo +import org.domaframework.doma.intellij.common.CommonPathParameterUtil import org.domaframework.doma.intellij.common.dao.getDaoClass import org.domaframework.doma.intellij.common.util.PluginLoggerUtil import org.domaframework.doma.intellij.extension.getContentRoot @@ -57,5 +58,7 @@ class DaoRenameProcessor : RenameJavaClassProcessor() { "Rename", startTime, ) + // Clear module directory cache on refactoring + CommonPathParameterUtil.clearCache() } } diff --git a/src/main/kotlin/org/domaframework/doma/intellij/reference/SqlElFunctionCallExprReference.kt b/src/main/kotlin/org/domaframework/doma/intellij/reference/SqlElFunctionCallExprReference.kt index dc063451..2523d3e6 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/reference/SqlElFunctionCallExprReference.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/reference/SqlElFunctionCallExprReference.kt @@ -15,15 +15,16 @@ */ package org.domaframework.doma.intellij.reference -import com.intellij.psi.PsiClass import com.intellij.psi.PsiElement import com.intellij.psi.PsiFile import com.intellij.psi.PsiMethod +import org.domaframework.doma.intellij.common.CommonPathParameterUtil +import org.domaframework.doma.intellij.common.config.DomaCompileConfigUtil import org.domaframework.doma.intellij.common.helper.ExpressionFunctionsHelper import org.domaframework.doma.intellij.common.util.PluginLoggerUtil import org.domaframework.doma.intellij.extension.getJavaClazz import org.domaframework.doma.intellij.psi.SqlElFunctionCallExpr -import org.domaframework.doma.intellij.setting.state.DomaToolsCustomFunctionSettings +import org.jetbrains.kotlin.idea.base.util.module class SqlElFunctionCallExprReference( element: PsiElement, @@ -36,33 +37,35 @@ class SqlElFunctionCallExprReference( val variableName = functionCallExpr.elIdExpr.text ?: "" val project = element.project + val module = file.module val expressionFunctionsInterface = ExpressionFunctionsHelper.setExpressionFunctionsInterface(project) ?: return null - val setting = DomaToolsCustomFunctionSettings.getInstance(element.project) - val customFunctionClassNames = setting.state.customFunctionClassNames - val implementsClasses: MutableList = - customFunctionClassNames.mapNotNull { className -> - val expressionFunction = project.getJavaClazz(className) + val resourcePaths = + module?.let { + CommonPathParameterUtil + .getResources(it, file.virtualFile) + } ?: emptyList() + + val customFunctionClassName = DomaCompileConfigUtil.getConfigValue(project, resourcePaths, "doma.expr.functions") + + val implementsClass = + if (customFunctionClassName != null) { + val expressionFunction = project.getJavaClazz(customFunctionClassName) if (ExpressionFunctionsHelper.isInheritor(expressionFunction)) { expressionFunction } else { - null + expressionFunctionsInterface } - } as MutableList - - if (implementsClasses.isEmpty()) { - implementsClasses.add(expressionFunctionsInterface) - } + } else { + expressionFunctionsInterface + } var reference: PsiMethod? = null - implementsClasses.forEach { clazz -> - // TODO Type checking in parameters - val methods = clazz.findMethodsByName(variableName, true).firstOrNull() - if (methods != null) { - reference = methods - } + val methods = implementsClass?.findMethodsByName(variableName, true)?.firstOrNull() + if (methods != null) { + reference = methods } if (reference == null) { diff --git a/src/main/kotlin/org/domaframework/doma/intellij/setting/DomaToolsConfigurable.kt b/src/main/kotlin/org/domaframework/doma/intellij/setting/DomaToolsConfigurable.kt index d954c79b..5b277da0 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/setting/DomaToolsConfigurable.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/setting/DomaToolsConfigurable.kt @@ -18,7 +18,6 @@ package org.domaframework.doma.intellij.setting import com.intellij.openapi.options.Configurable import com.intellij.openapi.options.ConfigurationException import org.domaframework.doma.intellij.common.helper.ActiveProjectHelper -import org.domaframework.doma.intellij.setting.state.DomaToolsCustomFunctionSettings import org.domaframework.doma.intellij.setting.state.DomaToolsFormatEnableSettings import javax.swing.JComponent @@ -27,11 +26,9 @@ class DomaToolsConfigurable : Configurable { private val project = ActiveProjectHelper.getCurrentActiveProject() private var formatSettings: DomaToolsFormatEnableSettings? = null - private var customFunctionsSettings: DomaToolsCustomFunctionSettings? = null init { project?.let { - customFunctionsSettings = DomaToolsCustomFunctionSettings.getInstance(it) formatSettings = DomaToolsFormatEnableSettings.getInstance(it) } } @@ -42,21 +39,16 @@ class DomaToolsConfigurable : Configurable { override fun isModified(): Boolean { val enableFormatModified = formatSettings?.isModified(mySettingsComponent) != false - val customFunctionClassNamesModified = - customFunctionsSettings?.isModified(mySettingsComponent) != false - - return enableFormatModified || customFunctionClassNamesModified + return enableFormatModified } @Throws(ConfigurationException::class) override fun apply() { formatSettings?.apply(mySettingsComponent) - customFunctionsSettings?.apply(mySettingsComponent) } override fun reset() { formatSettings?.reset(mySettingsComponent) - customFunctionsSettings?.reset(mySettingsComponent) } override fun disposeUIResources() { diff --git a/src/main/kotlin/org/domaframework/doma/intellij/setting/SettingComponent.kt b/src/main/kotlin/org/domaframework/doma/intellij/setting/SettingComponent.kt index 3c0e27c6..e43bd98e 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/setting/SettingComponent.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/setting/SettingComponent.kt @@ -15,82 +15,17 @@ */ package org.domaframework.doma.intellij.setting -import com.intellij.ui.ToolbarDecorator import com.intellij.ui.components.JBCheckBox import com.intellij.ui.components.JBLabel -import com.intellij.ui.components.JBList import com.intellij.util.ui.FormBuilder -import com.intellij.util.ui.UIUtil.setEnabledRecursively import org.domaframework.doma.intellij.bundle.MessageBundle -import org.domaframework.doma.intellij.common.helper.ActiveProjectHelper -import org.domaframework.doma.intellij.common.helper.ExpressionFunctionsHelper -import org.domaframework.doma.intellij.extension.getJavaClazz import javax.swing.JPanel -import javax.swing.ListSelectionModel class SettingComponent { val panel: JPanel? private val enableFormatCheckBox = JBCheckBox() - private val customFunctionClassListModel = javax.swing.DefaultListModel() - private val customFunctionClassList = - JBList(customFunctionClassListModel).apply { - selectionMode = ListSelectionModel.SINGLE_SELECTION - emptyText.text = MessageBundle.message("config.custom.functions.dialog.example") - } - init { - val customFunctionPanel = - ToolbarDecorator - .createDecorator(customFunctionClassList) - .setAddAction { actionButton -> - val project = ActiveProjectHelper.getCurrentActiveProject() - if (project != null) { - val expressionFunction = ExpressionFunctionsHelper - val expressionFunctionInterface = - expressionFunction.setExpressionFunctionsInterface(project) - val dialog = - com.intellij.openapi.ui.InputValidatorEx { inputString -> - if (inputString.isNullOrBlank()) { - MessageBundle.message("config.custom.functions.dialog.error.blank") - } else if (expressionFunctionInterface != null) { - val expressionClazz = project.getJavaClazz(inputString) - if (expressionClazz == null || - !expressionFunction.isInheritor(expressionClazz) - ) { - MessageBundle.message("config.custom.functions.dialog.error.invalidClass") - } else { - null - } - } else { - null - } - } - val input = - com.intellij.openapi.ui.Messages.showInputDialog( - "${MessageBundle.message("config.custom.functions.dialog.message")}\n" + - MessageBundle.message("config.custom.functions.dialog.example"), - MessageBundle.message("config.custom.functions.dialog.title"), - null, - "", - dialog, - ) - - if (!input.isNullOrBlank()) { - customFunctionClassListModel.addElement(input.trim()) - } - } - }.setRemoveAction { actionButton -> - val idx = customFunctionClassList.selectedIndex - if (idx >= 0) customFunctionClassListModel.remove(idx) - }.disableUpDownActions() - .createPanel() - - // Disable customFunctionPanel if no active project is available - if (ActiveProjectHelper.getCurrentActiveProject() == null) { - setEnabledRecursively(customFunctionPanel, false) - } - this.panel = FormBuilder .createFormBuilder() @@ -99,11 +34,6 @@ class SettingComponent { enableFormatCheckBox, 1, false, - ).addLabeledComponent( - JBLabel(MessageBundle.message("config.custom.functions.title")), - customFunctionPanel, - 1, - false, ).addComponentFillVertically(JPanel(), 0) .panel } @@ -113,14 +43,4 @@ class SettingComponent { set(enabled) { enableFormatCheckBox.isSelected = enabled } - - var customFunctionClassNames: List - get() = - (0 until customFunctionClassListModel.size()).map { - customFunctionClassListModel.getElementAt(it) - } - set(value) { - customFunctionClassListModel.clear() - value.forEach { customFunctionClassListModel.addElement(it) } - } } diff --git a/src/main/kotlin/org/domaframework/doma/intellij/setting/state/DomaToolsCustomFunctionSettings.kt b/src/main/kotlin/org/domaframework/doma/intellij/setting/state/DomaToolsCustomFunctionSettings.kt deleted file mode 100644 index c82e2f53..00000000 --- a/src/main/kotlin/org/domaframework/doma/intellij/setting/state/DomaToolsCustomFunctionSettings.kt +++ /dev/null @@ -1,61 +0,0 @@ -/* - * 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.setting.state - -import com.intellij.openapi.components.PersistentStateComponent -import com.intellij.openapi.components.Service -import com.intellij.openapi.components.State -import com.intellij.openapi.components.Storage -import com.intellij.openapi.project.Project -import org.domaframework.doma.intellij.setting.SettingComponent - -@State( - name = "DomaToolsCustomFunctionSettings", - storages = [Storage("doma_tools_settings.xml")], -) -@Service(Service.Level.PROJECT) -class DomaToolsCustomFunctionSettings : - PersistentStateComponent, - DomaToolsSettings { - class State { - var customFunctionClassNames: MutableList = mutableListOf() - } - - private var state = State() - - override fun getState(): State = state - - override fun loadState(state: State) { - this.state = state - } - - override fun isModified(component: SettingComponent?): Boolean = component?.customFunctionClassNames != state.customFunctionClassNames - - override fun apply(component: SettingComponent?) { - state.customFunctionClassNames.clear() - component?.customFunctionClassNames?.let { state.customFunctionClassNames.addAll(it) } - } - - override fun reset(component: SettingComponent?) { - component?.let { - it.customFunctionClassNames = state.customFunctionClassNames - } - } - - companion object { - fun getInstance(project: Project): DomaToolsCustomFunctionSettings = project.getService(DomaToolsCustomFunctionSettings::class.java) - } -} diff --git a/src/main/resources/messages/DomaToolsBundle.properties b/src/main/resources/messages/DomaToolsBundle.properties index 9b8451b7..38c59f0c 100644 --- a/src/main/resources/messages/DomaToolsBundle.properties +++ b/src/main/resources/messages/DomaToolsBundle.properties @@ -2,12 +2,6 @@ jump.to.sql.tooltip.title=Open SQL file jump.to.dao.tooltip.title=Jump to Dao method definition generate.sql.quickfix.title=Create SQL file config.enable.sql.format=Enable SQL Format -config.custom.functions.title=Custom Functions -config.custom.functions.dialog.title=Add Custom Function Class -config.custom.functions.dialog.message=Enter the package name and class name of your custom function -config.custom.functions.dialog.error.blank=Please enter class name -config.custom.functions.dialog.error.invalidClass=Please register a class that implements "org.seasar.doma.expr.ExpressionFunctions" -config.custom.functions.dialog.example=(ex: com.example.MyExpressionFunctions) inspection.invalid.dao.notExistSql=SQL file does not exist inspection.invalid.sql.property=The field or method [{1}] does not exist in the class [{0}] inspection.invalid.dao.paramUse=There are unused parameters in the SQL [{0}] @@ -16,6 +10,7 @@ inspection.invalid.sql.topType=Can't get type of first element inspection.invalid.sql.staticProperty=[{0}] is not a public or static property in the class [{1}] inspection.invalid.sql.testdata=Bind variables must be followed by test data inspection.invalid.sql.classpath=A non-existent package or class name was specified [{0}] -inspection.invalid.sql.iterable=The type that can be used in the for directive is an Iterable type +inspection.invalid.sql.iterable=The type that can be used in the loop directive is an Iterable type inspection.invalid.dao.duplicate=An element name that is a duplicate of an element name defined in SQL is used -inspection.invalid.sql.customFunction=The function [{0}] is not defined in the registered custom function classes +inspection.invalid.sql.notFound.customFunction=An undefined built-in or custom function [{0}] is being called +inspection.invalid.sql.notFound.expressionClass=An invalid ExpressionFunctions implementation class is configured in doma.compile.config \ 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 7a81861c..f16ce948 100644 --- a/src/main/resources/messages/DomaToolsBundle_ja.properties +++ b/src/main/resources/messages/DomaToolsBundle_ja.properties @@ -2,12 +2,6 @@ jump.to.sql.tooltip.title=SQL\u30D5\u30A1\u30A4\u30EB\u3092\u958B\u304F jump.to.dao.tooltip.title=Dao\u30E1\u30BD\u30C3\u30C9\u5B9A\u7FA9\u306B\u9077\u79FB\u3059\u308B generate.sql.quickfix.title=SQL\u30D5\u30A1\u30A4\u30EB\u3092\u4F5C\u6210 config.enable.sql.format=SQL\u30D5\u30A9\u30FC\u30DE\u30C3\u30C8\u3092\u6709\u52B9\u5316 -config.custom.functions.title=\u30AB\u30B9\u30BF\u30E0\u95A2\u6570 -config.custom.functions.dialog.title=\u30AB\u30B9\u30BF\u30E0\u95A2\u6570\u30AF\u30E9\u30B9\u3092\u8FFD\u52A0 -config.custom.functions.dialog.message=\u30AB\u30B9\u30BF\u30E0\u95A2\u6570\u306E\u30D1\u30C3\u30B1\u30FC\u30B8\u540D\u3068\u30AF\u30E9\u30B9\u540D\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044 -config.custom.functions.dialog.example=(\u4F8B: com.example.MyExpressionFunctions) -config.custom.functions.dialog.error.blank=\u30AF\u30E9\u30B9\u540D\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044 -config.custom.functions.dialog.error.invalidClass="org.seasar.doma.expr.ExpressionFunctions"\u306E\u5B9F\u88C5\u30AF\u30E9\u30B9\u3092\u767B\u9332\u3057\u3066\u304F\u3060\u3055\u3044 inspection.invalid.dao.notExistSql=SQL\u30D5\u30A1\u30A4\u30EB\u304C\u5B58\u5728\u3057\u307E\u305B\u3093 inspection.invalid.sql.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.invalid.dao.paramUse=SQL\u3067\u4F7F\u7528\u3055\u308C\u3066\u3044\u306A\u3044\u5F15\u6570\u304C\u3042\u308A\u307E\u3059:[{0}] @@ -16,6 +10,7 @@ inspection.invalid.sql.topType=\u6700\u521D\u306E\u8981\u7D20\u306E\u578B\u304C\ inspection.invalid.sql.staticProperty=[{0}]\u0020\u306F\u30AF\u30E9\u30B9\u0020[{1}]\u0020\u306E\u0020\u0070\u0075\u0062\u006C\u0069\u0063\u0020\u307E\u305F\u0020\u0073\u0074\u0061\u0074\u0069\u0063\u0020\u30D7\u30ED\u30D1\u30C6\u30A3\u3067\u306F\u3042\u308A\u307E\u305B\u3093 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 inspection.invalid.sql.classpath=\u5B58\u5728\u3057\u306A\u3044\u30D1\u30C3\u30B1\u30FC\u30B8\u307E\u305F\u306F\u30AF\u30E9\u30B9\u540D\u304C\u6307\u5B9A\u3055\u308C\u307E\u3057\u305F\u3002:[{0}] -inspection.invalid.sql.iterable=\u0066\u006F\u0072\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.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.customFunction=\u767B\u9332\u3055\u308C\u305F\u30AB\u30B9\u30BF\u30E0\u95A2\u6570\u30AF\u30E9\u30B9\u306B\u5B9A\u7FA9\u3055\u308C\u3066\u3044\u306A\u3044\u95A2\u6570\u304C\u547C\u3073\u51FA\u3055\u308C\u3066\u3044\u307E\u3059:[{0}] +inspection.invalid.sql.notFound.customFunction=\u5B9A\u7FA9\u3055\u308C\u3066\u3044\u306A\u3044\u7D44\u307F\u8FBC\u307F\u95A2\u6570\u307E\u305F\u306F\u30AB\u30B9\u30BF\u30E0\u95A2\u6570\u304C\u547C\u3073\u51FA\u3055\u308C\u3066\u3044\u307E\u3059:[{0}] +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 \ 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 c3610368..b549c90a 100644 --- a/src/test/kotlin/org/domaframework/doma/intellij/DomaSqlTest.kt +++ b/src/test/kotlin/org/domaframework/doma/intellij/DomaSqlTest.kt @@ -28,10 +28,9 @@ import com.intellij.openapi.vfs.VirtualFile import com.intellij.psi.PsiClass import com.intellij.testFramework.PsiTestUtil import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase +import org.domaframework.doma.intellij.common.CommonPathParameterUtil import org.domaframework.doma.intellij.common.RESOURCES_META_INF_PATH import org.domaframework.doma.intellij.extension.getResourcesSQLFile -import org.domaframework.doma.intellij.setting.SettingComponent -import org.domaframework.doma.intellij.setting.state.DomaToolsCustomFunctionSettings import org.jetbrains.jps.model.java.JavaResourceRootType import org.jetbrains.jps.model.java.JavaSourceRootType import org.junit.Ignore @@ -68,6 +67,7 @@ open class DomaSqlTest : LightJavaCodeInsightFixtureTestCase() { override fun tearDown() { try { deleteSdk() + CommonPathParameterUtil.clearCache() } finally { super.tearDown() } @@ -169,7 +169,7 @@ open class DomaSqlTest : LightJavaCodeInsightFixtureTestCase() { ) } - fun addResourceEmptyFile(vararg sqlFileNames: String) { + fun addResourceEmptySqlFile(vararg sqlFileNames: String) { for (sqlFileName in sqlFileNames) { myFixture.addFileToProject( "main/$resourceRoot/$RESOURCES_META_INF_PATH/$packagePath/dao/$sqlFileName", @@ -178,6 +178,14 @@ open class DomaSqlTest : LightJavaCodeInsightFixtureTestCase() { } } + fun addResourceCompileFile(readFileName: String) { + val file = File("$testDataPath/$resourceRoot/$readFileName") + myFixture.addFileToProject( + "main/$resourceRoot/doma.compile.config", + file.readText(), + ) + } + fun addSqlFile(vararg sqlNames: String) { for (sqlName in sqlNames) { val file = File("$testDataPath/$resourceRoot/$RESOURCES_META_INF_PATH/$packagePath/dao/$sqlName") @@ -209,12 +217,4 @@ open class DomaSqlTest : LightJavaCodeInsightFixtureTestCase() { file.readText(), ) } - - protected fun settingCustomFunctions(newClassNames: MutableList) { - val settings = DomaToolsCustomFunctionSettings.getInstance(project) - val component = SettingComponent() - component.customFunctionClassNames = newClassNames.toMutableList() - settings.apply(component) - assertEquals(newClassNames, settings.getState().customFunctionClassNames) - } } diff --git a/src/test/kotlin/org/domaframework/doma/intellij/complate/sql/SqlCompleteTest.kt b/src/test/kotlin/org/domaframework/doma/intellij/complate/sql/SqlCompleteTest.kt index 589c46e2..fe637071 100644 --- a/src/test/kotlin/org/domaframework/doma/intellij/complate/sql/SqlCompleteTest.kt +++ b/src/test/kotlin/org/domaframework/doma/intellij/complate/sql/SqlCompleteTest.kt @@ -16,7 +16,6 @@ package org.domaframework.doma.intellij.complate.sql import org.domaframework.doma.intellij.DomaSqlTest -import org.domaframework.doma.intellij.inspection.sql.inspector.SqlBindVariableValidInspector /** * Code completion testing in SQL @@ -62,7 +61,6 @@ class SqlCompleteTest : DomaSqlTest() { "$testDaoName/completeImplementCustomFunction.sql", "$testDaoName/completeNotImplementCustomFunction.sql", ) - myFixture.enableInspections(SqlBindVariableValidInspector()) } fun testCompleteDaoArgument() { @@ -267,12 +265,16 @@ class SqlCompleteTest : DomaSqlTest() { "isNotBlank()", ), listOf( - "escape()", - "prefix()", - "infix()", - "suffix()", - "roundDownTimePart()", - "roundUpTimePart()", + "userId()", + "userName()", + "userAge()", + "langCode()", + "isGest()", + "getId()", + "getName()", + "getAge()", + "getLangCode()", + "isManager()", ), ) } @@ -403,9 +405,7 @@ class SqlCompleteTest : DomaSqlTest() { } fun testCompleteImplementCustomFunction() { - settingCustomFunctions( - mutableListOf("doma.example.expression.TestExpressionFunctions", "doma.example.expression.TestNotExpressionFunctions"), - ) + addResourceCompileFile("doma.compile.config") innerDirectiveCompleteTest( "$testDaoName/completeImplementCustomFunction.sql", listOf("userId()", "userName()", "userAge()"), @@ -424,9 +424,15 @@ class SqlCompleteTest : DomaSqlTest() { } fun testCompleteNotImplementCustomFunction() { + addResourceCompileFile("invalid.doma.compile.config") innerDirectiveCompleteTest( "$testDaoName/completeNotImplementCustomFunction.sql", - listOf("isEmpty()", "isBlank()", "isNotBlank()", "roundDownTimePart()"), + listOf( + "isEmpty()", + "isNotEmpty()", + "isBlank()", + "isNotBlank()", + ), listOf( "userId()", "userName()", diff --git a/src/test/kotlin/org/domaframework/doma/intellij/gutteraction/dao/DaoGenerateSqlActionTest.kt b/src/test/kotlin/org/domaframework/doma/intellij/gutteraction/dao/DaoGenerateSqlActionTest.kt index 7c8ebe38..7f6eaf82 100644 --- a/src/test/kotlin/org/domaframework/doma/intellij/gutteraction/dao/DaoGenerateSqlActionTest.kt +++ b/src/test/kotlin/org/domaframework/doma/intellij/gutteraction/dao/DaoGenerateSqlActionTest.kt @@ -60,7 +60,7 @@ class DaoGenerateSqlActionTest : DomaSqlTest() { "gutteraction/SqlProcessorGutterTestDao.java", ) - addResourceEmptyFile( + addResourceEmptySqlFile( "quickfix/SelectQuickFixTestDao/existsSQLFile.sql", "quickfix/InsertQuickFixTestDao/existsSQLFile.sql", "quickfix/UpdateQuickFixTestDao/existsSQLFile.sql", @@ -71,7 +71,7 @@ class DaoGenerateSqlActionTest : DomaSqlTest() { "quickfix/ScriptQuickFixTestDao/existsSQLFile.script", "quickfix/SqlProcessorQuickFixTestDao/existsSQLFile.sql", ) - addResourceEmptyFile( + addResourceEmptySqlFile( "gutteraction/SelectGutterTestDao/existsSQLFile1.sql", "gutteraction/InsertGutterTestDao/existsSQLFile2.sql", "gutteraction/UpdateGutterTestDao/existsSQLFile1.sql", diff --git a/src/test/kotlin/org/domaframework/doma/intellij/gutteraction/dao/DaoGutterActionTest.kt b/src/test/kotlin/org/domaframework/doma/intellij/gutteraction/dao/DaoGutterActionTest.kt index 5cd74efc..7c939d18 100644 --- a/src/test/kotlin/org/domaframework/doma/intellij/gutteraction/dao/DaoGutterActionTest.kt +++ b/src/test/kotlin/org/domaframework/doma/intellij/gutteraction/dao/DaoGutterActionTest.kt @@ -45,7 +45,7 @@ class DaoGutterActionTest : DomaSqlTest() { "$packageName/ScriptGutterTestDao.java", "$packageName/SqlProcessorGutterTestDao.java", ) - addResourceEmptyFile( + addResourceEmptySqlFile( "$packageName/SelectGutterTestDao/existsSQLFile1.sql", "$packageName/InsertGutterTestDao/existsSQLFile1.sql", "$packageName/UpdateGutterTestDao/existsSQLFile1.sql", @@ -56,7 +56,7 @@ class DaoGutterActionTest : DomaSqlTest() { "$packageName/ScriptGutterTestDao/existsSQLFile1.script", "$packageName/SqlProcessorGutterTestDao/existsSQLFile1.sql", ) - addResourceEmptyFile( + addResourceEmptySqlFile( "$packageName/SelectGutterTestDao/existsSQLFile2.sql", "$packageName/InsertGutterTestDao/existsSQLFile2.sql", "$packageName/UpdateGutterTestDao/existsSQLFile2.sql", @@ -67,7 +67,7 @@ class DaoGutterActionTest : DomaSqlTest() { "$packageName/ScriptGutterTestDao/existsSQLFile2.script", "$packageName/SqlProcessorGutterTestDao/existsSQLFile2.sql", ) - addResourceEmptyFile( + addResourceEmptySqlFile( "$packageName/BatchInsertGutterTestDao/existsSQLFile3.sql", "$packageName/BatchUpdateGutterTestDao/existsSQLFile3.sql", "$packageName/BatchDeleteGutterTestDao/existsSQLFile3.sql", diff --git a/src/test/kotlin/org/domaframework/doma/intellij/gutteraction/dao/DaoJumpActionTest.kt b/src/test/kotlin/org/domaframework/doma/intellij/gutteraction/dao/DaoJumpActionTest.kt index 0aad74bb..a3c66bd0 100644 --- a/src/test/kotlin/org/domaframework/doma/intellij/gutteraction/dao/DaoJumpActionTest.kt +++ b/src/test/kotlin/org/domaframework/doma/intellij/gutteraction/dao/DaoJumpActionTest.kt @@ -61,7 +61,7 @@ class DaoJumpActionTest : DomaSqlTest() { "$packageName/$notDisplayedPackage/SqlProcessorInvalidCaretTestDao.java", "$packageName/$notDisplayedPackage/InvalidCaretTestDao.java", ) - addResourceEmptyFile( + addResourceEmptySqlFile( "$packageName/SelectGutterTestDao/existsSQLFile1.sql", "$packageName/InsertGutterTestDao/existsSQLFile1.sql", "$packageName/UpdateGutterTestDao/existsSQLFile1.sql", @@ -72,7 +72,7 @@ class DaoJumpActionTest : DomaSqlTest() { "$packageName/ScriptGutterTestDao/existsSQLFile1.script", "$packageName/SqlProcessorGutterTestDao/existsSQLFile1.sql", ) - addResourceEmptyFile( + addResourceEmptySqlFile( "$packageName/SelectGutterTestDao/existsSQLFile2.sql", "$packageName/InsertGutterTestDao/existsSQLFile2.sql", "$packageName/UpdateGutterTestDao/existsSQLFile2.sql", diff --git a/src/test/kotlin/org/domaframework/doma/intellij/inspection/dao/DomaSqlExistTest.kt b/src/test/kotlin/org/domaframework/doma/intellij/inspection/dao/DomaSqlExistTest.kt index 965419a0..dbe714f4 100644 --- a/src/test/kotlin/org/domaframework/doma/intellij/inspection/dao/DomaSqlExistTest.kt +++ b/src/test/kotlin/org/domaframework/doma/intellij/inspection/dao/DomaSqlExistTest.kt @@ -32,7 +32,7 @@ class DomaSqlExistTest : DomaSqlTest() { "ScriptTestDao.java", "SqlProcessorTestDao.java", ) - addResourceEmptyFile( + addResourceEmptySqlFile( "SelectTestDao/existsSQLFile.sql", "InsertTestDao/existsSQLFile.sql", "UpdateTestDao/existsSQLFile.sql", diff --git a/src/test/kotlin/org/domaframework/doma/intellij/inspection/dao/DomaSqlQuickFixTest.kt b/src/test/kotlin/org/domaframework/doma/intellij/inspection/dao/DomaSqlQuickFixTest.kt index 7f4376a9..131d3adb 100644 --- a/src/test/kotlin/org/domaframework/doma/intellij/inspection/dao/DomaSqlQuickFixTest.kt +++ b/src/test/kotlin/org/domaframework/doma/intellij/inspection/dao/DomaSqlQuickFixTest.kt @@ -37,7 +37,7 @@ class DomaSqlQuickFixTest : DomaSqlTest() { "quickfix/SqlProcessorQuickFixTestDao.java", ) - addResourceEmptyFile( + addResourceEmptySqlFile( "quickfix/SelectQuickFixTestDao/existsSQLFile.sql", "quickfix/InsertQuickFixTestDao/existsSQLFile.sql", "quickfix/UpdateQuickFixTestDao/existsSQLFile.sql", diff --git a/src/test/kotlin/org/domaframework/doma/intellij/inspection/sql/ParameterDefinedTest.kt b/src/test/kotlin/org/domaframework/doma/intellij/inspection/sql/ParameterDefinedTest.kt index d68636ca..70d1eff5 100644 --- a/src/test/kotlin/org/domaframework/doma/intellij/inspection/sql/ParameterDefinedTest.kt +++ b/src/test/kotlin/org/domaframework/doma/intellij/inspection/sql/ParameterDefinedTest.kt @@ -16,7 +16,6 @@ package org.domaframework.doma.intellij.inspection.sql import org.domaframework.doma.intellij.DomaSqlTest -import org.domaframework.doma.intellij.common.helper.ActiveProjectHelper import org.domaframework.doma.intellij.inspection.sql.inspector.SqlBindVariableValidInspector /** @@ -41,6 +40,7 @@ class ParameterDefinedTest : DomaSqlTest() { "$testDaoName/bindVariableForItemHasNextAndIndex.sql", "$testDaoName/optionalDaoParameterFieldAccess.sql", "$testDaoName/implementCustomFunctions.sql", + "$testDaoName/invalidImplementCustomFunctions.sql", ) myFixture.enableInspections(SqlBindVariableValidInspector()) } @@ -126,13 +126,7 @@ class ParameterDefinedTest : DomaSqlTest() { } fun testImplementCustomFunctions() { - if (project != null) { - ActiveProjectHelper.setCurrentActiveProject(project) - } - settingCustomFunctions( - mutableListOf("doma.example.expression.TestExpressionFunctions", "doma.example.expression.TestNotExpressionFunctions"), - ) - + addResourceCompileFile("doma.compile.config") val sqlFile = findSqlFile("$testDaoName/implementCustomFunctions.sql") assertNotNull("Not Found SQL File", sqlFile) @@ -140,4 +134,14 @@ class ParameterDefinedTest : DomaSqlTest() { myFixture.testHighlighting(false, false, false, sqlFile) } + + fun testInvalidImplementCustomFunctions() { + addResourceCompileFile("invalid.doma.compile.config") + val sqlFile = + findSqlFile("$testDaoName/invalidImplementCustomFunctions.sql") + assertNotNull("Not Found SQL File", sqlFile) + if (sqlFile == null) return + + myFixture.testHighlighting(false, false, false, sqlFile) + } } diff --git a/src/test/kotlin/org/domaframework/doma/intellij/refactor/DaoMethodRenameTestCase.kt b/src/test/kotlin/org/domaframework/doma/intellij/refactor/DaoMethodRenameTestCase.kt index c8c004e7..7a1f1782 100644 --- a/src/test/kotlin/org/domaframework/doma/intellij/refactor/DaoMethodRenameTestCase.kt +++ b/src/test/kotlin/org/domaframework/doma/intellij/refactor/DaoMethodRenameTestCase.kt @@ -29,7 +29,7 @@ class DaoMethodRenameTestCase : DomaSqlTest() { "RenameDaoMethodWithoutSql.java", "RenameDaoMethodNotExistSql.java", ) - addResourceEmptyFile( + addResourceEmptySqlFile( "RenameDaoMethod/renameDaoMethodName.sql", "RenameDao/renameDaoClassName.sql", ) diff --git a/src/test/kotlin/org/domaframework/doma/intellij/reference/SqlReferenceTestCase.kt b/src/test/kotlin/org/domaframework/doma/intellij/reference/SqlReferenceTestCase.kt index f12c6fc8..4ca2746a 100644 --- a/src/test/kotlin/org/domaframework/doma/intellij/reference/SqlReferenceTestCase.kt +++ b/src/test/kotlin/org/domaframework/doma/intellij/reference/SqlReferenceTestCase.kt @@ -128,9 +128,7 @@ class SqlReferenceTestCase : DomaSqlTest() { } fun testReferenceCustomFunction() { - settingCustomFunctions( - mutableListOf("doma.example.expression.TestExpressionFunctions", "doma.example.expression.TestNotExpressionFunctions"), - ) + addResourceCompileFile("doma.compile.config") referenceTest( "referenceCustomFunction", mapOf( diff --git a/src/test/kotlin/org/domaframework/doma/intellij/setting/state/DomaToolsCustomFunctionSettingsTest.kt b/src/test/kotlin/org/domaframework/doma/intellij/setting/state/DomaToolsCustomFunctionSettingsTest.kt deleted file mode 100644 index 96c726f1..00000000 --- a/src/test/kotlin/org/domaframework/doma/intellij/setting/state/DomaToolsCustomFunctionSettingsTest.kt +++ /dev/null @@ -1,78 +0,0 @@ -/* - * 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.setting.state - -import org.domaframework.doma.intellij.DomaSqlTest -import org.domaframework.doma.intellij.setting.SettingComponent - -class DomaToolsCustomFunctionSettingsTest : DomaSqlTest() { - private val packageName = "doma.example.expression" - - override fun setUp() { - super.setUp() - } - - fun testCustomFunctionClassNamesPersistence() { - val settings = DomaToolsCustomFunctionSettings.getInstance(project) - val testClassNames = - mutableListOf( - "$packageName.TestExpressionFunctions", - "$packageName.TestNotExpressionFunctions", - ) - settings.getState().customFunctionClassNames = testClassNames.toMutableList() - - val loaded = DomaToolsCustomFunctionSettings.State() - loaded.customFunctionClassNames = testClassNames.toMutableList() - settings.loadState(loaded) - - assertEquals(testClassNames, settings.getState().customFunctionClassNames) - } - - fun testApplyAndReset() { - val settings = DomaToolsCustomFunctionSettings.getInstance(project) - val component = SettingComponent() - val initialClassNames = mutableListOf("$packageName.TestExpressionFunctions") - val newClassNames = mutableListOf("$packageName.TestExpressionFunctions", "$packageName.TestNotExpressionFunctions") - - // init - settings.getState().customFunctionClassNames = initialClassNames.toMutableList() - settings.reset(component) - assertEquals(initialClassNames, component.customFunctionClassNames) - - // apply - component.customFunctionClassNames = newClassNames.toMutableList() - settings.apply(component) - assertEquals(newClassNames, settings.getState().customFunctionClassNames) - - // reset - settings.getState().customFunctionClassNames = initialClassNames.toMutableList() - settings.reset(component) - assertEquals(initialClassNames, component.customFunctionClassNames) - } - - fun testIsModified() { - val settings = DomaToolsCustomFunctionSettings.getInstance(project) - val component = SettingComponent() - val classNames = mutableListOf("$packageName.TestExpressionFunctions") - settings.getState().customFunctionClassNames = classNames.toMutableList() - component.customFunctionClassNames = classNames.toMutableList() - assertFalse(settings.isModified(component)) - - val addClassNames = mutableListOf("$packageName.TestExpressionFunctions", "$packageName.TestNotExpressionFunctions") - component.customFunctionClassNames = addClassNames - assertTrue(settings.isModified(component)) - } -} diff --git a/src/test/testData/src/main/java/doma/example/dao/EmployeeSummaryDao.java b/src/test/testData/src/main/java/doma/example/dao/EmployeeSummaryDao.java index 96f34b78..a91d8085 100644 --- a/src/test/testData/src/main/java/doma/example/dao/EmployeeSummaryDao.java +++ b/src/test/testData/src/main/java/doma/example/dao/EmployeeSummaryDao.java @@ -42,4 +42,7 @@ interface EmployeeSummaryDao { @Select EmployeeSummary implementCustomFunctions(EmployeeSummary employee); + + @Select + EmployeeSummary invalidImplementCustomFunctions(EmployeeSummary employee); } \ No newline at end of file diff --git a/src/test/testData/src/main/resources/META-INF/doma/example/dao/EmployeeSummaryDao/bindVariableForNonEntityClass.sql b/src/test/testData/src/main/resources/META-INF/doma/example/dao/EmployeeSummaryDao/bindVariableForNonEntityClass.sql index 0019dc19..088258e0 100644 --- a/src/test/testData/src/main/resources/META-INF/doma/example/dao/EmployeeSummaryDao/bindVariableForNonEntityClass.sql +++ b/src/test/testData/src/main/resources/META-INF/doma/example/dao/EmployeeSummaryDao/bindVariableForNonEntityClass.sql @@ -25,9 +25,9 @@ AND pe.end_date >= CURRENT_DATE /*%end*/ -- Reference error for a non-existent field - /*%for child : employee.projectIds */ + /*%for child : employee.projectIds */ -- An error occurred because the referenced element was not correctly defined. - AND pe.parent_project = /* child.projectId */0 + AND pe.parent_project = /* child.projectId */0 -- Reference error for a non-existent method AND pe.member_id IN /* employee.getTopProject() */(0,1,2) /*%end */ diff --git a/src/test/testData/src/main/resources/META-INF/doma/example/dao/EmployeeSummaryDao/implementCustomFunctions.sql b/src/test/testData/src/main/resources/META-INF/doma/example/dao/EmployeeSummaryDao/implementCustomFunctions.sql index b2e0ffc5..e9ab7543 100644 --- a/src/test/testData/src/main/resources/META-INF/doma/example/dao/EmployeeSummaryDao/implementCustomFunctions.sql +++ b/src/test/testData/src/main/resources/META-INF/doma/example/dao/EmployeeSummaryDao/implementCustomFunctions.sql @@ -6,5 +6,5 @@ SELECT WHERE p.employee_id = /* employee.employeeId */0 AND p.user_id = /* employee.userId */0 OR is_gest = /* @isGest() */false - OR flag = /* @authUser() */false - AND lang = /* @getLangCode() */'en' \ No newline at end of file + OR flag = /* @authUser() */false + AND lang = /* @getLangCode() */'en' \ No newline at end of file diff --git a/src/test/testData/src/main/resources/META-INF/doma/example/dao/EmployeeSummaryDao/invalidImplementCustomFunctions.sql b/src/test/testData/src/main/resources/META-INF/doma/example/dao/EmployeeSummaryDao/invalidImplementCustomFunctions.sql new file mode 100644 index 00000000..1404a4e4 --- /dev/null +++ b/src/test/testData/src/main/resources/META-INF/doma/example/dao/EmployeeSummaryDao/invalidImplementCustomFunctions.sql @@ -0,0 +1,10 @@ +SELECT + e.employee_id + , u.user_id + , u.user_name + FROM user u + WHERE p.employee_id = /* employee.employeeId */0 + AND p.user_id = /* employee.userId */0 + OR is_gest = /* @isManager() */false + OR flag = /* @authUser() */false + AND lang = /* @isBlank() */'en' \ No newline at end of file diff --git a/src/test/testData/src/main/resources/META-INF/doma/example/dao/SqlCompleteTestDao/completeImplementCustomFunction.sql b/src/test/testData/src/main/resources/META-INF/doma/example/dao/SqlCompleteTestDao/completeImplementCustomFunction.sql index f710b860..a80d8421 100644 --- a/src/test/testData/src/main/resources/META-INF/doma/example/dao/SqlCompleteTestDao/completeImplementCustomFunction.sql +++ b/src/test/testData/src/main/resources/META-INF/doma/example/dao/SqlCompleteTestDao/completeImplementCustomFunction.sql @@ -1,4 +1,4 @@ SELECT * FROM project WHERE project_id = /* project.projectId */0 AND manager = /* project.manager.userId */0 -AND lang = /* @use() */'en' \ No newline at end of file +AND lang = /* @use() */'en' diff --git a/src/test/testData/src/main/resources/doma.compile.config b/src/test/testData/src/main/resources/doma.compile.config new file mode 100644 index 00000000..675caf75 --- /dev/null +++ b/src/test/testData/src/main/resources/doma.compile.config @@ -0,0 +1 @@ +doma.expr.functions=doma.example.expression.TestExpressionFunctions \ No newline at end of file diff --git a/src/test/testData/src/main/resources/invalid.doma.compile.config b/src/test/testData/src/main/resources/invalid.doma.compile.config new file mode 100644 index 00000000..9e6a1191 --- /dev/null +++ b/src/test/testData/src/main/resources/invalid.doma.compile.config @@ -0,0 +1 @@ +doma.expr.functions=doma.example.expression.TestNotExpressionFunctions \ No newline at end of file