Introduce default ScriptTemplate for Gradle scripts
^KT-23228 Fixed
This commit is contained in:
+7
-7
@@ -46,9 +46,6 @@ class ScriptDefinitionsManager(private val project: Project): ScriptDefinitionPr
|
|||||||
private var definitionsByContributor = mutableMapOf<ScriptDefinitionContributor, List<KotlinScriptDefinition>>()
|
private var definitionsByContributor = mutableMapOf<ScriptDefinitionContributor, List<KotlinScriptDefinition>>()
|
||||||
private var definitions: List<KotlinScriptDefinition> = emptyList()
|
private var definitions: List<KotlinScriptDefinition> = emptyList()
|
||||||
|
|
||||||
var hasFailedDefinitions = false
|
|
||||||
private set
|
|
||||||
|
|
||||||
fun reloadDefinitionsBy(contributor: ScriptDefinitionContributor) = lock.write {
|
fun reloadDefinitionsBy(contributor: ScriptDefinitionContributor) = lock.write {
|
||||||
val notLoadedYet = definitions.isEmpty()
|
val notLoadedYet = definitions.isEmpty()
|
||||||
if (notLoadedYet) return
|
if (notLoadedYet) return
|
||||||
@@ -57,8 +54,6 @@ class ScriptDefinitionsManager(private val project: Project): ScriptDefinitionPr
|
|||||||
|
|
||||||
definitionsByContributor[contributor] = contributor.safeGetDefinitions()
|
definitionsByContributor[contributor] = contributor.safeGetDefinitions()
|
||||||
|
|
||||||
hasFailedDefinitions = getContributors().any { it.isError() }
|
|
||||||
|
|
||||||
updateDefinitions()
|
updateDefinitions()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,6 +67,13 @@ class ScriptDefinitionsManager(private val project: Project): ScriptDefinitionPr
|
|||||||
return definitionsByContributor[contributor] ?: emptyList()
|
return definitionsByContributor[contributor] ?: emptyList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getContributorForDefinition(scriptDefinition: KotlinScriptDefinition): ScriptDefinitionContributor {
|
||||||
|
for ((contributor, definitions) in definitionsByContributor) {
|
||||||
|
if (definitions.contains(scriptDefinition)) return contributor
|
||||||
|
}
|
||||||
|
throw error("Unknown definition: ${scriptDefinition.name}")
|
||||||
|
}
|
||||||
|
|
||||||
private fun currentDefinitions(): List<KotlinScriptDefinition> {
|
private fun currentDefinitions(): List<KotlinScriptDefinition> {
|
||||||
val hasDefinitions = definitions.isNotEmpty()
|
val hasDefinitions = definitions.isNotEmpty()
|
||||||
when {
|
when {
|
||||||
@@ -105,8 +107,6 @@ class ScriptDefinitionsManager(private val project: Project): ScriptDefinitionPr
|
|||||||
definitionsByContributor[contributor] = definitions
|
definitionsByContributor[contributor] = definitions
|
||||||
}
|
}
|
||||||
|
|
||||||
hasFailedDefinitions = getContributors().any { it.isError() }
|
|
||||||
|
|
||||||
updateDefinitions()
|
updateDefinitions()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+5
-9
@@ -41,7 +41,6 @@ import org.jetbrains.annotations.TestOnly
|
|||||||
import org.jetbrains.kotlin.extensions.ProjectExtensionDescriptor
|
import org.jetbrains.kotlin.extensions.ProjectExtensionDescriptor
|
||||||
import org.jetbrains.kotlin.idea.core.util.EDT
|
import org.jetbrains.kotlin.idea.core.util.EDT
|
||||||
import org.jetbrains.kotlin.idea.core.util.cancelOnDisposal
|
import org.jetbrains.kotlin.idea.core.util.cancelOnDisposal
|
||||||
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
|
|
||||||
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
||||||
import org.jetbrains.kotlin.psi.NotNullableUserDataProperty
|
import org.jetbrains.kotlin.psi.NotNullableUserDataProperty
|
||||||
import org.jetbrains.kotlin.script.*
|
import org.jetbrains.kotlin.script.*
|
||||||
@@ -127,10 +126,6 @@ class ScriptDependenciesUpdater(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun performUpdate(file: VirtualFile) {
|
private fun performUpdate(file: VirtualFile) {
|
||||||
if (ScriptDefinitionsManager.getInstance(project).hasFailedDefinitions && !ProjectRootsUtil.isProjectSourceFile(project, file)) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
val scriptDef = scriptDefinitionProvider.findScriptDefinition(file) ?: return
|
val scriptDef = scriptDefinitionProvider.findScriptDefinition(file) ?: return
|
||||||
when (scriptDef.dependencyResolver) {
|
when (scriptDef.dependencyResolver) {
|
||||||
is AsyncDependenciesResolver, is LegacyResolverWrapper -> {
|
is AsyncDependenciesResolver, is LegacyResolverWrapper -> {
|
||||||
@@ -212,7 +207,7 @@ class ScriptDependenciesUpdater(
|
|||||||
}
|
}
|
||||||
ServiceManager.getService(project, ScriptReportSink::class.java)?.attachReports(file, result.reports)
|
ServiceManager.getService(project, ScriptReportSink::class.java)?.attachReports(file, result.reports)
|
||||||
val resultingDependencies = (result.dependencies ?: ScriptDependencies.Empty).adjustByDefinition(scriptDef)
|
val resultingDependencies = (result.dependencies ?: ScriptDependencies.Empty).adjustByDefinition(scriptDef)
|
||||||
if (saveNewDependencies(resultingDependencies, file)) {
|
if (saveNewDependencies(resultingDependencies, file, scriptDef)) {
|
||||||
notifyRootsChanged()
|
notifyRootsChanged()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -221,15 +216,16 @@ class ScriptDependenciesUpdater(
|
|||||||
|
|
||||||
fun updateSync(file: VirtualFile, scriptDef: KotlinScriptDefinition): Boolean {
|
fun updateSync(file: VirtualFile, scriptDef: KotlinScriptDefinition): Boolean {
|
||||||
val newDeps = contentLoader.loadContentsAndResolveDependencies(scriptDef, file) ?: ScriptDependencies.Empty
|
val newDeps = contentLoader.loadContentsAndResolveDependencies(scriptDef, file) ?: ScriptDependencies.Empty
|
||||||
return saveNewDependencies(newDeps, file)
|
return saveNewDependencies(newDeps, file, scriptDef)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun saveNewDependencies(
|
private fun saveNewDependencies(
|
||||||
new: ScriptDependencies,
|
new: ScriptDependencies,
|
||||||
file: VirtualFile
|
file: VirtualFile,
|
||||||
|
scriptDef: KotlinScriptDefinition
|
||||||
): Boolean {
|
): Boolean {
|
||||||
val rootsChanged = cache.hasNotCachedRoots(new)
|
val rootsChanged = cache.hasNotCachedRoots(new)
|
||||||
if (cache.save(file, new)) {
|
if (cache.save(file, new) && !ScriptDefinitionsManager.getInstance(project).getContributorForDefinition(scriptDef).isError()) {
|
||||||
file.scriptDependencies = new
|
file.scriptDependencies = new
|
||||||
}
|
}
|
||||||
return rootsChanged
|
return rootsChanged
|
||||||
|
|||||||
+44
-6
@@ -22,12 +22,16 @@ import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskId
|
|||||||
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskNotificationListenerAdapter
|
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskNotificationListenerAdapter
|
||||||
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskType
|
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskType
|
||||||
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil
|
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil
|
||||||
|
import com.intellij.openapi.fileTypes.LanguageFileType
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.openapi.vfs.VirtualFile
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
import org.gradle.tooling.ProjectConnection
|
import org.gradle.tooling.ProjectConnection
|
||||||
|
import org.jetbrains.kotlin.idea.KotlinFileType
|
||||||
import org.jetbrains.kotlin.idea.framework.GRADLE_SYSTEM_ID
|
import org.jetbrains.kotlin.idea.framework.GRADLE_SYSTEM_ID
|
||||||
import org.jetbrains.kotlin.lexer.KotlinLexer
|
import org.jetbrains.kotlin.lexer.KotlinLexer
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.psi.KtScript
|
||||||
import org.jetbrains.kotlin.script.KotlinScriptDefinition
|
import org.jetbrains.kotlin.script.KotlinScriptDefinition
|
||||||
import org.jetbrains.plugins.gradle.config.GradleSettingsListenerAdapter
|
import org.jetbrains.plugins.gradle.config.GradleSettingsListenerAdapter
|
||||||
import org.jetbrains.plugins.gradle.service.execution.GradleExecutionHelper
|
import org.jetbrains.plugins.gradle.service.execution.GradleExecutionHelper
|
||||||
@@ -39,9 +43,14 @@ import org.jetbrains.plugins.gradle.util.GradleConstants
|
|||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.concurrent.atomic.AtomicBoolean
|
import java.util.concurrent.atomic.AtomicBoolean
|
||||||
|
import kotlin.reflect.KClass
|
||||||
import kotlin.script.dependencies.Environment
|
import kotlin.script.dependencies.Environment
|
||||||
|
import kotlin.script.dependencies.ScriptContents
|
||||||
|
import kotlin.script.experimental.dependencies.DependenciesResolver
|
||||||
|
import kotlin.script.experimental.dependencies.DependenciesResolver.ResolveResult
|
||||||
import kotlin.script.experimental.dependencies.ScriptDependencies
|
import kotlin.script.experimental.dependencies.ScriptDependencies
|
||||||
|
import kotlin.script.experimental.dependencies.ScriptReport
|
||||||
|
import kotlin.script.templates.standard.ScriptTemplateWithArgs
|
||||||
|
|
||||||
class GradleScriptDefinitionsContributor(private val project: Project) : ScriptDefinitionContributor {
|
class GradleScriptDefinitionsContributor(private val project: Project) : ScriptDefinitionContributor {
|
||||||
|
|
||||||
@@ -109,7 +118,12 @@ class GradleScriptDefinitionsContributor(private val project: Project) : ScriptD
|
|||||||
return kotlinDslTemplates
|
return kotlinDslTemplates
|
||||||
}
|
}
|
||||||
|
|
||||||
return tryToLoadOldBuildScriptDefinition()
|
val default = tryToLoadOldBuildScriptDefinition()
|
||||||
|
if (default.isNotEmpty()) {
|
||||||
|
return default
|
||||||
|
}
|
||||||
|
|
||||||
|
return listOf(ErrorGradleScriptDefinition())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun tryToLoadOldBuildScriptDefinition(): List<KotlinScriptDefinition> {
|
private fun tryToLoadOldBuildScriptDefinition(): List<KotlinScriptDefinition> {
|
||||||
@@ -137,7 +151,7 @@ class GradleScriptDefinitionsContributor(private val project: Project) : ScriptD
|
|||||||
} catch (t: Throwable) {
|
} catch (t: Throwable) {
|
||||||
// TODO: review exception handling
|
// TODO: review exception handling
|
||||||
failedToLoad.set(true)
|
failedToLoad.set(true)
|
||||||
emptyList()
|
listOf(ErrorGradleScriptDefinition(t.message))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -168,10 +182,10 @@ class GradleScriptDefinitionsContributor(private val project: Project) : ScriptD
|
|||||||
}
|
}
|
||||||
|
|
||||||
val gradleSettings = ExternalSystemApiUtil.getSettings(project, GradleConstants.SYSTEM_ID)
|
val gradleSettings = ExternalSystemApiUtil.getSettings(project, GradleConstants.SYSTEM_ID)
|
||||||
if (gradleSettings.getLinkedProjectsSettings().isEmpty()) return emptyList()
|
if (gradleSettings.getLinkedProjectsSettings().isEmpty()) error("Project '${project.name}' isn't linked with Gradle")
|
||||||
|
|
||||||
val projectSettings =
|
val projectSettings = gradleSettings.getLinkedProjectsSettings().filterIsInstance<GradleProjectSettings>().firstOrNull()
|
||||||
gradleSettings.getLinkedProjectsSettings().filterIsInstance<GradleProjectSettings>().firstOrNull() ?: return emptyList()
|
?: error("Project '${project.name}' isn't linked with Gradle")
|
||||||
|
|
||||||
val gradleExeSettings = ExternalSystemApiUtil.getExecutionSettings<GradleExecutionSettings>(
|
val gradleExeSettings = ExternalSystemApiUtil.getExecutionSettings<GradleExecutionSettings>(
|
||||||
project,
|
project,
|
||||||
@@ -207,6 +221,30 @@ class GradleScriptDefinitionsContributor(private val project: Project) : ScriptD
|
|||||||
ScriptDefinitionsManager.getInstance(project).reloadDefinitionsBy(this)
|
ScriptDefinitionsManager.getInstance(project).reloadDefinitionsBy(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class ErrorGradleScriptDefinition(message: String? = null) : KotlinScriptDefinition(ScriptTemplateWithArgs::class) {
|
||||||
|
override val name: String = "Default Kotlin Gradle Script"
|
||||||
|
override val fileType: LanguageFileType = KotlinFileType.INSTANCE
|
||||||
|
override val annotationsForSamWithReceivers: List<String> = emptyList()
|
||||||
|
override val acceptedAnnotations: List<KClass<out Annotation>> = emptyList()
|
||||||
|
|
||||||
|
override val dependencyResolver: DependenciesResolver = ErrorScriptDependenciesResolver(message)
|
||||||
|
|
||||||
|
override fun getScriptName(script: KtScript) =
|
||||||
|
Name.identifier(script.containingKtFile.name.removeSuffix(GradleConstants.KOTLIN_DSL_SCRIPT_EXTENSION))
|
||||||
|
|
||||||
|
override fun isScript(fileName: String): Boolean =
|
||||||
|
fileName.endsWith(GradleConstants.KOTLIN_DSL_SCRIPT_EXTENSION)
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ErrorScriptDependenciesResolver(private val message: String? = null) : DependenciesResolver {
|
||||||
|
override fun resolve(scriptContents: ScriptContents, environment: Environment): ResolveResult {
|
||||||
|
return ResolveResult.Failure(
|
||||||
|
ScriptReport(
|
||||||
|
message ?: "Failed to load script definitions by ${GradleScriptDefinitionsContributor::class.java.name}"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ReloadGradleTemplatesOnSync : ExternalSystemTaskNotificationListenerAdapter() {
|
class ReloadGradleTemplatesOnSync : ExternalSystemTaskNotificationListenerAdapter() {
|
||||||
|
|||||||
Reference in New Issue
Block a user