Try to approximate "build.gradle.kts" script dependencies on first access
This is a hacky solution to prevent whole file being highlighted as unresolved while we wait for gradle response
This commit is contained in:
+1
-1
@@ -45,7 +45,7 @@ data class ScriptModuleInfo(
|
||||
override val moduleOrigin: ModuleOrigin
|
||||
get() = ModuleOrigin.OTHER
|
||||
|
||||
val externalDependencies: ScriptDependencies?
|
||||
val externalDependencies: ScriptDependencies
|
||||
get() = ScriptDependenciesManager.getInstance(project).getScriptDependencies(scriptFile)
|
||||
|
||||
override val name: Name = Name.special("<script ${scriptFile.name} ${scriptDefinition.name}>")
|
||||
|
||||
@@ -58,6 +58,8 @@ class ScriptDependenciesCache(private val project: Project) {
|
||||
NonClasspathDirectoriesScope(allLibrarySources)
|
||||
}
|
||||
|
||||
fun <T> inspectCache(body: (Map<String, ScriptDependencies>) -> T): T = cacheLock.read { body(cache) }
|
||||
|
||||
private fun onChange(file: VirtualFile?) {
|
||||
this::allScriptsClasspath.clearValue()
|
||||
this::allScriptsClasspathScope.clearValue()
|
||||
|
||||
+1
-1
@@ -51,7 +51,7 @@ class ScriptDependenciesManager internal constructor(
|
||||
}
|
||||
|
||||
fun getScriptClasspath(file: VirtualFile): List<VirtualFile> = toVfsRoots(cacheUpdater.getCurrentDependencies(file).classpath)
|
||||
fun getScriptDependencies(file: VirtualFile) = cacheUpdater.getCurrentDependencies(file)
|
||||
fun getScriptDependencies(file: VirtualFile): ScriptDependencies = cacheUpdater.getCurrentDependencies(file)
|
||||
|
||||
private fun reloadScriptDefinitions() {
|
||||
val def = makeScriptDefsFromTemplatesProviderExtensions(
|
||||
|
||||
+34
-10
@@ -18,7 +18,6 @@ package org.jetbrains.kotlin.idea.core.script
|
||||
|
||||
import com.intellij.openapi.application.Application
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.application.ModalityState
|
||||
import com.intellij.openapi.components.ServiceManager
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.project.isProjectOrWorkspaceFile
|
||||
@@ -35,11 +34,13 @@ import kotlinx.coroutines.experimental.Job
|
||||
import kotlinx.coroutines.experimental.asCoroutineDispatcher
|
||||
import kotlinx.coroutines.experimental.launch
|
||||
import org.jetbrains.annotations.TestOnly
|
||||
import org.jetbrains.kotlin.extensions.ProjectExtensionDescriptor
|
||||
import org.jetbrains.kotlin.idea.core.util.EDT
|
||||
import org.jetbrains.kotlin.idea.core.util.cancelOnDisposal
|
||||
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
||||
import org.jetbrains.kotlin.psi.NotNullableUserDataProperty
|
||||
import org.jetbrains.kotlin.script.*
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import java.util.concurrent.Executors
|
||||
import kotlin.script.experimental.dependencies.AsyncDependenciesResolver
|
||||
@@ -77,20 +78,33 @@ internal class ScriptDependenciesUpdater(
|
||||
fun getCurrentDependencies(file: VirtualFile): ScriptDependencies {
|
||||
cache[file]?.let { return it }
|
||||
|
||||
tryLoadingFromDisk(file)
|
||||
val loaded = tryLoadingFromDisk(file)
|
||||
|
||||
if (!loaded) {
|
||||
tryUsingDefault(file)
|
||||
}
|
||||
|
||||
updateCache(listOf(file))
|
||||
|
||||
return cache[file] ?: ScriptDependencies.Empty
|
||||
}
|
||||
|
||||
private fun tryLoadingFromDisk(file: VirtualFile) {
|
||||
ScriptDependenciesFileAttribute.read(file)?.let { deserialized ->
|
||||
val rootsChanged = cache.hasNotCachedRoots(deserialized)
|
||||
cache.save(file, deserialized)
|
||||
if (rootsChanged) {
|
||||
notifyRootsChanged()
|
||||
}
|
||||
private fun tryUsingDefault(file: VirtualFile) {
|
||||
val defaults = DefaultScriptDependenciesProvider.getInstances(project).firstNotNullResult { it.defaultDependenciesFor(file) } ?: return
|
||||
saveToCache(defaults, file)
|
||||
}
|
||||
|
||||
private fun tryLoadingFromDisk(file: VirtualFile): Boolean {
|
||||
val deserializedDependencies = ScriptDependenciesFileAttribute.read(file) ?: return false
|
||||
saveToCache(deserializedDependencies, file)
|
||||
return true
|
||||
}
|
||||
|
||||
private fun saveToCache(deserialized: ScriptDependencies, file: VirtualFile) {
|
||||
val rootsChanged = cache.hasNotCachedRoots(deserialized)
|
||||
cache.save(file, deserialized)
|
||||
if (rootsChanged) {
|
||||
notifyRootsChanged()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -280,4 +294,14 @@ private object TimeStamps {
|
||||
}
|
||||
|
||||
@set: TestOnly
|
||||
var Application.isScriptDependenciesUpdaterDisabled by NotNullableUserDataProperty(Key.create("SCRIPT_DEPENDENCIES_UPDATER_DISABLED"), false)
|
||||
var Application.isScriptDependenciesUpdaterDisabled by NotNullableUserDataProperty(Key.create("SCRIPT_DEPENDENCIES_UPDATER_DISABLED"), false)
|
||||
|
||||
interface DefaultScriptDependenciesProvider {
|
||||
fun defaultDependenciesFor(scriptFile: VirtualFile): ScriptDependencies?
|
||||
|
||||
companion object : ProjectExtensionDescriptor<DefaultScriptDependenciesProvider>(
|
||||
"org.jetbrains.kotlin.defaultScriptDependenciesProvider",
|
||||
DefaultScriptDependenciesProvider::class.java
|
||||
)
|
||||
|
||||
}
|
||||
+37
-1
@@ -20,7 +20,9 @@ import com.intellij.execution.configurations.CommandLineTokenizer
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import org.gradle.tooling.ProjectConnection
|
||||
import org.jetbrains.kotlin.gradle.kdsl.DEFAULT_SCRIPT_NAME
|
||||
import org.jetbrains.kotlin.lexer.KotlinLexer
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.script.ScriptTemplatesProvider
|
||||
@@ -28,6 +30,7 @@ import org.jetbrains.plugins.gradle.service.execution.GradleExecutionHelper
|
||||
import org.jetbrains.plugins.gradle.settings.GradleExecutionSettings
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
import kotlin.script.experimental.dependencies.ScriptDependencies
|
||||
|
||||
abstract class AbstractGradleScriptTemplatesProvider(
|
||||
project: Project, override val id: String, private val templateClass: String, private val dependencySelector: Regex
|
||||
@@ -164,4 +167,37 @@ class TopLevelSectionTokensEnumerator(script: CharSequence, identifier: String)
|
||||
fun topLevelSectionCodeTextTokens(script: CharSequence, sectionIdentifier: String): Sequence<CharSequence> =
|
||||
TopLevelSectionTokensEnumerator(script, sectionIdentifier).asSequence()
|
||||
.filter { it.tokenType !in KtTokens.WHITE_SPACE_OR_COMMENT_BIT_SET }
|
||||
.map { it.tokenSequence }
|
||||
.map { it.tokenSequence }
|
||||
|
||||
|
||||
private const val KOTLIN_BUILD_FILE_NAME = DEFAULT_SCRIPT_NAME
|
||||
|
||||
class GradleScriptDefaultDependenciesProvider(
|
||||
private val scriptDependenciesCache: ScriptDependenciesCache
|
||||
) : DefaultScriptDependenciesProvider {
|
||||
override fun defaultDependenciesFor(scriptFile: VirtualFile): ScriptDependencies? {
|
||||
if (scriptFile.name != KOTLIN_BUILD_FILE_NAME) return null
|
||||
|
||||
return previouslyAnalyzedScriptsCombinedDependencies().takeUnless { it.classpath.isEmpty() }
|
||||
}
|
||||
|
||||
private fun previouslyAnalyzedScriptsCombinedDependencies(): ScriptDependencies {
|
||||
val sources = mutableListOf<File>()
|
||||
val binaries = mutableListOf<File>()
|
||||
val imports = mutableListOf<String>()
|
||||
|
||||
scriptDependenciesCache.inspectCache { cache ->
|
||||
cache.entries.filter { it.key.endsWith(KOTLIN_BUILD_FILE_NAME) }
|
||||
.map { it.value }.forEach {
|
||||
sources += it.sources
|
||||
binaries += it.classpath
|
||||
imports += it.imports
|
||||
}
|
||||
}
|
||||
return ScriptDependencies(
|
||||
classpath = binaries.distinct(),
|
||||
sources = sources.distinct(),
|
||||
imports = imports.distinct()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,5 +51,8 @@
|
||||
interface="com.intellij.ide.util.projectWizard.ModuleBuilder"/>
|
||||
<extensionPoint name="gradleFrameworkSupport"
|
||||
interface="org.jetbrains.kotlin.gradle.kdsl.frameworkSupport.GradleFrameworkSupportProvider"/>
|
||||
<extensionPoint name="defaultScriptDependenciesProvider"
|
||||
interface="org.jetbrains.kotlin.idea.core.script.DefaultScriptDependenciesProvider"
|
||||
area="IDEA_PROJECT"/>
|
||||
</extensionPoints>
|
||||
</idea-plugin>
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
<gradleProjectImportHandler implementation="org.jetbrains.kotlin.allopen.ide.AllOpenGradleProjectImportHandler"/>
|
||||
<gradleProjectImportHandler implementation="org.jetbrains.kotlin.noarg.ide.NoArgGradleProjectImportHandler"/>
|
||||
<gradleProjectImportHandler implementation="org.jetbrains.kotlin.samWithReceiver.ide.SamWithReceiverGradleProjectImportHandler"/>
|
||||
<defaultScriptDependenciesProvider implementation="org.jetbrains.kotlin.idea.core.script.GradleScriptDefaultDependenciesProvider"/>
|
||||
|
||||
<projectConfigurator implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleModuleConfigurator"/>
|
||||
<projectConfigurator implementation="org.jetbrains.kotlin.idea.configuration.KotlinJsGradleModuleConfigurator"/>
|
||||
|
||||
Reference in New Issue
Block a user