Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
```
Original file line number Diff line number Diff line change
@@ -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<VirtualFile>,
val moduleResourceDirectories: List<VirtualFile>,
val moduleTestSourceDirectories: List<VirtualFile>,
val moduleTestResourceDirectories: List<VirtualFile>,
)

// Cache for each module's directory information.
private val modulePathCache = ConcurrentHashMap<Module, ModulePaths>()

/**
* 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<VirtualFile>()
val resourceDirs = mutableListOf<VirtualFile>()
val testSourceDirs = mutableListOf<VirtualFile>()
val testResourceDirs = mutableListOf<VirtualFile>()

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<VirtualFile> =
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<VirtualFile> =
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()
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -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<Properties, last update time>
*/
private val configCache = ConcurrentHashMap<String, Pair<java.util.Properties, Long>>()

/**
* 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<VirtualFile>,
key: String,
): String? {
resourcePaths.forEach { resourcePath ->
if (resourcePath.isValid) {
val configVFile = resourcePath.findChild("doma.compile.config")
val cacheKey = "${project.basePath}/$resourcePath/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
}
}
Loading