gradle.kts: cache definitions

This commit is contained in:
Sergey Rostov
2020-05-01 00:24:22 +03:00
parent 1fdd1bcbf6
commit feac19f46e
4 changed files with 58 additions and 23 deletions
@@ -29,6 +29,7 @@ import com.intellij.util.containers.SLRUMap
import org.jetbrains.kotlin.idea.KotlinFileType import org.jetbrains.kotlin.idea.KotlinFileType
import org.jetbrains.kotlin.idea.caches.project.SdkInfo import org.jetbrains.kotlin.idea.caches.project.SdkInfo
import org.jetbrains.kotlin.idea.caches.project.getScriptRelatedModuleInfo import org.jetbrains.kotlin.idea.caches.project.getScriptRelatedModuleInfo
import org.jetbrains.kotlin.idea.core.script.configuration.CompositeScriptConfigurationManager
import org.jetbrains.kotlin.idea.core.script.settings.KotlinScriptingSettings import org.jetbrains.kotlin.idea.core.script.settings.KotlinScriptingSettings
import org.jetbrains.kotlin.idea.util.application.executeOnPooledThread import org.jetbrains.kotlin.idea.util.application.executeOnPooledThread
import org.jetbrains.kotlin.idea.util.application.getServiceSafe import org.jetbrains.kotlin.idea.util.application.getServiceSafe
@@ -82,9 +83,15 @@ class ScriptDefinitionsManager(private val project: Project) : LazyScriptDefinit
private val scriptDefinitionsCacheLock = ReentrantLock() private val scriptDefinitionsCacheLock = ReentrantLock()
private val scriptDefinitionsCache = SLRUMap<String, ScriptDefinition>(10, 10) private val scriptDefinitionsCache = SLRUMap<String, ScriptDefinition>(10, 10)
val configurations = (ScriptConfigurationManager.getInstance(project) as CompositeScriptConfigurationManager)
override fun findDefinition(script: SourceCode): ScriptDefinition? { override fun findDefinition(script: SourceCode): ScriptDefinition? {
val locationId = script.locationId ?: return null val locationId = script.locationId ?: return null
if (nonScriptId(locationId)) return null if (nonScriptId(locationId)) return null
val fastPath = configurations.tryGetScriptDefinitionFast(locationId)
if (fastPath != null) return fastPath
if (!isReady()) return null if (!isReady()) return null
val cached = scriptDefinitionsCacheLock.withLock { scriptDefinitionsCache.get(locationId) } val cached = scriptDefinitionsCacheLock.withLock { scriptDefinitionsCache.get(locationId) }
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.idea.core.script.configuration.utils.ScriptClassRoot
import org.jetbrains.kotlin.idea.core.script.configuration.utils.ScriptClassRootsUpdater import org.jetbrains.kotlin.idea.core.script.configuration.utils.ScriptClassRootsUpdater
import org.jetbrains.kotlin.idea.core.script.configuration.utils.getKtFile import org.jetbrains.kotlin.idea.core.script.configuration.utils.getKtFile
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationWrapper import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationWrapper
class CompositeScriptConfigurationManager(val project: Project) : ScriptConfigurationManager { class CompositeScriptConfigurationManager(val project: Project) : ScriptConfigurationManager {
@@ -31,6 +32,10 @@ class CompositeScriptConfigurationManager(val project: Project) : ScriptConfigur
val default = DefaultScriptingSupport(this) val default = DefaultScriptingSupport(this)
fun tryGetScriptDefinitionFast(locationId: String): ScriptDefinition? {
return classpathRoots.getLightScriptInfo(locationId)?.definition
}
private fun getOrLoadConfiguration( private fun getOrLoadConfiguration(
virtualFile: VirtualFile, virtualFile: VirtualFile,
preloadedKtFile: KtFile? = null preloadedKtFile: KtFile? = null
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.idea.core.script.LOG
import org.jetbrains.kotlin.idea.core.script.ScriptConfigurationManager.Companion.classpathEntryToVfs import org.jetbrains.kotlin.idea.core.script.ScriptConfigurationManager.Companion.classpathEntryToVfs
import org.jetbrains.kotlin.idea.core.script.ScriptConfigurationManager.Companion.toVfsRoots import org.jetbrains.kotlin.idea.core.script.ScriptConfigurationManager.Companion.toVfsRoots
import org.jetbrains.kotlin.idea.util.getProjectJdkTableSafe import org.jetbrains.kotlin.idea.util.getProjectJdkTableSafe
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationWrapper import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationWrapper
import java.io.File import java.io.File
import java.lang.ref.Reference import java.lang.ref.Reference
@@ -34,14 +35,14 @@ class ScriptClassRootsCache(
private val nonModulesSdks: Collection<Sdk>, private val nonModulesSdks: Collection<Sdk>,
val customDefinitionsUsed: Boolean val customDefinitionsUsed: Boolean
) { ) {
abstract class LightScriptInfo { abstract class LightScriptInfo(val definition: ScriptDefinition?) {
@Volatile @Volatile
var heavyCache: Reference<HeavyScriptInfo>? = null var heavyCache: Reference<HeavyScriptInfo>? = null
abstract fun buildConfiguration(): ScriptCompilationConfigurationWrapper? abstract fun buildConfiguration(): ScriptCompilationConfigurationWrapper?
} }
class DirectScriptInfo(val result: ScriptCompilationConfigurationWrapper) : LightScriptInfo() { class DirectScriptInfo(val result: ScriptCompilationConfigurationWrapper) : LightScriptInfo(null) {
override fun buildConfiguration(): ScriptCompilationConfigurationWrapper = result override fun buildConfiguration(): ScriptCompilationConfigurationWrapper = result
} }
@@ -9,10 +9,12 @@ import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.LocalFileSystem import com.intellij.openapi.vfs.LocalFileSystem
import com.intellij.openapi.vfs.VfsUtil import com.intellij.openapi.vfs.VfsUtil
import com.intellij.openapi.vfs.VirtualFile import com.intellij.openapi.vfs.VirtualFile
import org.jetbrains.kotlin.idea.core.script.ScriptDefinitionContributor
import org.jetbrains.kotlin.idea.core.script.configuration.utils.ScriptClassRootsCache import org.jetbrains.kotlin.idea.core.script.configuration.utils.ScriptClassRootsCache
import org.jetbrains.kotlin.idea.scripting.gradle.importing.KotlinDslScriptModel import org.jetbrains.kotlin.idea.scripting.gradle.importing.KotlinDslScriptModel
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
import org.jetbrains.kotlin.scripting.definitions.findScriptDefinition import org.jetbrains.kotlin.scripting.definitions.findScriptDefinition
import org.jetbrains.kotlin.scripting.resolve.KtFileScriptSource
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationWrapper import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationWrapper
import org.jetbrains.kotlin.scripting.resolve.VirtualFileScriptSource import org.jetbrains.kotlin.scripting.resolve.VirtualFileScriptSource
import org.jetbrains.kotlin.scripting.resolve.adjustByDefinition import org.jetbrains.kotlin.scripting.resolve.adjustByDefinition
@@ -74,23 +76,24 @@ sealed class GradleBuildRoot {
val javaHome = context.javaHome val javaHome = context.javaHome
javaHome?.let { builder.addSdk(it) } javaHome?.let { builder.addSdk(it) }
val anyScript = data.models.firstOrNull()?.let { val definitions = ScriptDefinitionContributor.EP_NAME.getExtensions(project)
LocalFileSystem.getInstance().findFileByPath(it.file) .filterIsInstance<GradleScriptDefinitionsContributor>()
} .single().definitions.toList()
val scriptDefinition: ScriptDefinition? = anyScript?.findScriptDefinition(project) val root = ScriptInfoRoot(this)
if (scriptDefinition != null) { builder.classes.addAll(data.templateClasspath)
builder.classes.addAll(data.templateClasspath) data.models.forEach { script ->
} val vFile = LocalFileSystem.getInstance().findFileByPath(script.file)
val def = if (vFile != null) {
val src = VirtualFileScriptSource(vFile)
definitions.firstOrNull { it.isScript(src) }
} else null
val root = ScriptInfoRoot(this, scriptDefinition) builder.scripts[script.file] = ScriptInfo(root, def, script)
data.models.forEach { builder.classes.addAll(script.classPath)
builder.scripts[it.file] = ScriptInfo(root, it) builder.sources.addAll(script.sourcePath)
builder.classes.addAll(it.classPath)
builder.sources.addAll(it.sourcePath)
} }
} }
@@ -98,37 +101,56 @@ sealed class GradleBuildRoot {
* Common info between scripts (to save bits inside ScriptInfo) * Common info between scripts (to save bits inside ScriptInfo)
*/ */
data class ScriptInfoRoot( data class ScriptInfoRoot(
val buildRoot: Imported, val buildRoot: Imported
val scriptDefinition: ScriptDefinition?
) )
data class ScriptInfo( class ScriptInfo(
val root: ScriptInfoRoot, val root: ScriptInfoRoot,
scriptDefinition: ScriptDefinition?,
val model: KotlinDslScriptModel val model: KotlinDslScriptModel
) : ScriptClassRootsCache.LightScriptInfo() { ) : ScriptClassRootsCache.LightScriptInfo(scriptDefinition) {
val buildRoot get() = root.buildRoot val buildRoot get() = root.buildRoot
override fun buildConfiguration(): ScriptCompilationConfigurationWrapper? { override fun buildConfiguration(): ScriptCompilationConfigurationWrapper? {
val javaHome = buildRoot.context.javaHome val javaHome = buildRoot.context.javaHome
val scriptDefinition = root.scriptDefinition
val scriptFile = File(model.file) val scriptFile = File(model.file)
val virtualFile = VfsUtil.findFile(scriptFile.toPath(), true)!! val virtualFile = VfsUtil.findFile(scriptFile.toPath(), true)!!
if (scriptDefinition == null) return null if (definition == null) return null
return ScriptCompilationConfigurationWrapper.FromCompilationConfiguration( return ScriptCompilationConfigurationWrapper.FromCompilationConfiguration(
VirtualFileScriptSource(virtualFile), VirtualFileScriptSource(virtualFile),
scriptDefinition.compilationConfiguration.with { definition.compilationConfiguration.with {
if (javaHome != null) { if (javaHome != null) {
jvm.jdkHome(javaHome) jvm.jdkHome(javaHome)
} }
defaultImports(model.imports) defaultImports(model.imports)
dependencies(JvmDependency(model.classPath.map { File(it) })) dependencies(JvmDependency(model.classPath.map { File(it) }))
ide.dependenciesSources(JvmDependency(model.sourcePath.map { File(it) })) ide.dependenciesSources(JvmDependency(model.sourcePath.map { File(it) }))
}.adjustByDefinition(scriptDefinition) }.adjustByDefinition(definition)
) )
} }
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as ScriptInfo
if (root != other.root) return false
if (model != other.model) return false
if (definition != other.definition) return false
return true
}
override fun hashCode(): Int {
var result = root.hashCode()
result = 31 * result + model.hashCode()
result = 31 * result + definition.hashCode()
return result
}
} }
} }
} }