Scripting: move gradle specific logic to idea-gradle

This commit is contained in:
Sergey Rostov
2019-11-06 13:27:39 +03:00
committed by Natalia Selezneva
parent 0fb58ed94c
commit fc100d13dd
8 changed files with 178 additions and 138 deletions
@@ -1,137 +0,0 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.core.script.configuration
import com.intellij.openapi.fileEditor.FileDocumentManager
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.registry.Registry
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiManager
import com.intellij.psi.PsiRecursiveElementVisitor
import com.intellij.psi.PsiWhiteSpace
import com.intellij.psi.impl.source.tree.LeafPsiElement
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import org.jetbrains.kotlin.idea.core.script.configuration.cache.CachedConfigurationInputs
import org.jetbrains.kotlin.idea.core.script.configuration.listener.DefaultScriptChangeListener
import org.jetbrains.kotlin.idea.core.script.configuration.listener.ScriptConfigurationUpdater
import org.jetbrains.kotlin.idea.core.script.configuration.loader.DefaultScriptConfigurationLoader
import org.jetbrains.kotlin.idea.core.script.configuration.loader.ScriptConfigurationLoadingContext
import org.jetbrains.kotlin.idea.core.util.EDT
import org.jetbrains.kotlin.idea.util.application.runReadAction
import org.jetbrains.kotlin.idea.util.application.runWriteAction
import org.jetbrains.kotlin.psi.KtCallExpression
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtScriptInitializer
import org.jetbrains.kotlin.psi.psiUtil.getChildrenOfType
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
class GradleScriptListener : DefaultScriptChangeListener() {
private val listenGradleRelatedFiles = false // todo
override fun editorActivated(file: KtFile, updater: ScriptConfigurationUpdater): Boolean {
if (!isGradleKotlinScript(file.virtualFile)) return false
if (listenGradleRelatedFiles) {
updater.ensureUpToDatedConfigurationSuggested(file)
// todo: force reload if related files changed
} else {
// configuration will be reloaded after editor activation, even it is already up-to-date
// this is required for Gradle scripts, since it's classpath may depend on other files (`.properties` for example)
updater.forceConfigurationReload(file)
}
return true
}
}
class GradleScriptConfigurationLoader(project: Project) : DefaultScriptConfigurationLoader(project) {
private val useProjectImport: Boolean
get() = Registry.`is`("kotlin.gradle.scripts.useIdeaProjectImport", false)
override fun shouldRunInBackground(scriptDefinition: ScriptDefinition): Boolean {
return if (useProjectImport) false else super.shouldRunInBackground(scriptDefinition)
}
override fun loadDependencies(
isFirstLoad: Boolean,
ktFile: KtFile,
scriptDefinition: ScriptDefinition,
context: ScriptConfigurationLoadingContext
): Boolean {
if (!isGradleKotlinScript(ktFile.originalFile.virtualFile)) return false
if (useProjectImport) {
// do nothing, project import notification will be already showed
// and configuration for gradle build scripts will be saved at the end of import
// todo: use default configuration loader for out-of-project scripts?
return true
} else {
// Gradle read files from FS
GlobalScope.launch(EDT(project)) {
runWriteAction {
FileDocumentManager.getInstance().saveAllDocuments()
}
}
return super.loadDependencies(isFirstLoad, ktFile, scriptDefinition, context)
}
}
override fun getInputsStamp(virtualFile: VirtualFile, file: KtFile): CachedConfigurationInputs {
return getGradleScriptInputsStamp(project, virtualFile, file) ?: super.getInputsStamp(virtualFile, file)
}
}
data class GradleKotlinScriptConfigurationInputs(
val buildScriptAndPluginsSections: String
) : CachedConfigurationInputs {
override fun isUpToDate(project: Project, file: VirtualFile, ktFile: KtFile?): Boolean {
val actualStamp = getGradleScriptInputsStamp(project, file, ktFile)
return actualStamp == this
}
}
fun isGradleKotlinScript(virtualFile: VirtualFile) = virtualFile.name.endsWith(".gradle.kts")
fun getGradleScriptInputsStamp(
project: Project,
file: VirtualFile,
givenKtFile: KtFile? = null
): GradleKotlinScriptConfigurationInputs? {
if (!isGradleKotlinScript(file)) return null
return runReadAction {
val ktFile = givenKtFile ?: PsiManager.getInstance(project).findFile(file) as? KtFile
if (ktFile != null) {
val result = StringBuilder()
ktFile.script?.blockExpression
?.getChildrenOfType<KtScriptInitializer>()
?.forEach {
val call = it.children.singleOrNull() as? KtCallExpression
val callRef = call?.firstChild?.text
if (callRef == "buildscript" || callRef == "plugins") {
result.append(callRef)
val lambda = call.lambdaArguments.singleOrNull()
lambda?.accept(object : PsiRecursiveElementVisitor(false) {
override fun visitElement(element: PsiElement) {
super.visitElement(element)
when (element) {
is PsiWhiteSpace -> if (element.text.contains("\n")) result.append("\n")
is LeafPsiElement -> result.append(element.text)
}
}
})
result.append("\n")
}
}
GradleKotlinScriptConfigurationInputs(result.toString())
} else null
}
}
@@ -25,7 +25,7 @@ import com.intellij.pom.Navigatable
import org.jetbrains.kotlin.idea.core.script.ScriptConfigurationManager
import org.jetbrains.kotlin.idea.core.script.configuration.cache.CachedConfigurationInputs
import org.jetbrains.kotlin.idea.core.script.configuration.cache.ScriptConfigurationSnapshot
import org.jetbrains.kotlin.idea.core.script.configuration.getGradleScriptInputsStamp
import org.jetbrains.kotlin.idea.script.getGradleScriptInputsStamp
import org.jetbrains.kotlin.scripting.definitions.findScriptDefinition
import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationWrapper
import org.jetbrains.kotlin.scripting.resolve.VirtualFileScriptSource
@@ -0,0 +1,20 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.script
import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.VirtualFile
import org.jetbrains.kotlin.idea.core.script.configuration.cache.CachedConfigurationInputs
import org.jetbrains.kotlin.psi.KtFile
data class GradleKotlinScriptConfigurationInputs(
val buildScriptAndPluginsSections: String
) : CachedConfigurationInputs {
override fun isUpToDate(project: Project, file: VirtualFile, ktFile: KtFile?): Boolean {
val actualStamp = getGradleScriptInputsStamp(project, file, ktFile)
return actualStamp == this
}
}
@@ -0,0 +1,60 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.script
import com.intellij.openapi.fileEditor.FileDocumentManager
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.registry.Registry
import com.intellij.openapi.vfs.VirtualFile
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import org.jetbrains.kotlin.idea.core.script.configuration.cache.CachedConfigurationInputs
import org.jetbrains.kotlin.idea.core.script.configuration.loader.DefaultScriptConfigurationLoader
import org.jetbrains.kotlin.idea.core.script.configuration.loader.ScriptConfigurationLoadingContext
import org.jetbrains.kotlin.idea.core.util.EDT
import org.jetbrains.kotlin.idea.util.application.runWriteAction
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
class GradleScriptConfigurationLoader(project: Project) : DefaultScriptConfigurationLoader(project) {
private val useProjectImport: Boolean
get() = Registry.`is`("kotlin.gradle.scripts.useIdeaProjectImport", false)
override fun shouldRunInBackground(scriptDefinition: ScriptDefinition): Boolean {
return if (useProjectImport) false else super.shouldRunInBackground(scriptDefinition)
}
override fun loadDependencies(
isFirstLoad: Boolean,
virtualFile: VirtualFile,
scriptDefinition: ScriptDefinition,
context: ScriptConfigurationLoadingContext
): Boolean {
if (!isGradleKotlinScript(virtualFile)) return false
if (useProjectImport) {
// do nothing, project import notification will be already showed
// and configuration for gradle build scripts will be saved at the end of import
// todo: use default configuration loader for out-of-project scripts?
return true
} else {
// Gradle read files from FS
GlobalScope.launch(EDT(project)) {
runWriteAction {
FileDocumentManager.getInstance().saveAllDocuments()
}
}
return super.loadDependencies(isFirstLoad, virtualFile, scriptDefinition, context)
}
}
override fun getInputsStamp(virtualFile: VirtualFile, file: KtFile): CachedConfigurationInputs {
return getGradleScriptInputsStamp(project, virtualFile, file)
?: super.getInputsStamp(virtualFile, file)
}
}
@@ -0,0 +1,28 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.script
import org.jetbrains.kotlin.idea.core.script.configuration.listener.DefaultScriptChangeListener
import org.jetbrains.kotlin.idea.core.script.configuration.listener.ScriptConfigurationUpdater
import org.jetbrains.kotlin.psi.KtFile
class GradleScriptListener : DefaultScriptChangeListener() {
private val listenGradleRelatedFiles = false // todo
override fun editorActivated(file: KtFile, updater: ScriptConfigurationUpdater): Boolean {
if (!isGradleKotlinScript(file.virtualFile)) return false
if (listenGradleRelatedFiles) {
updater.ensureUpToDatedConfigurationSuggested(file)
// todo: force reload if related files changed
} else {
// configuration will be reloaded after editor activation, even it is already up-to-date
// this is required for Gradle scripts, since it's classpath may depend on other files (`.properties` for example)
updater.forceConfigurationReload(file)
}
return true
}
}
@@ -0,0 +1,59 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.script
import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiManager
import com.intellij.psi.PsiRecursiveElementVisitor
import com.intellij.psi.PsiWhiteSpace
import com.intellij.psi.impl.source.tree.LeafPsiElement
import org.jetbrains.kotlin.idea.util.application.runReadAction
import org.jetbrains.kotlin.psi.KtCallExpression
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtScriptInitializer
import org.jetbrains.kotlin.psi.psiUtil.getChildrenOfType
fun isGradleKotlinScript(virtualFile: VirtualFile) = virtualFile.name.endsWith(".gradle.kts")
fun getGradleScriptInputsStamp(
project: Project,
file: VirtualFile,
givenKtFile: KtFile? = null
): GradleKotlinScriptConfigurationInputs? {
if (!isGradleKotlinScript(file)) return null
return runReadAction {
val ktFile = givenKtFile ?: PsiManager.getInstance(project).findFile(file) as? KtFile
if (ktFile != null) {
val result = StringBuilder()
ktFile.script?.blockExpression
?.getChildrenOfType<KtScriptInitializer>()
?.forEach {
val call = it.children.singleOrNull() as? KtCallExpression
val callRef = call?.firstChild?.text
if (callRef == "buildscript" || callRef == "plugins") {
result.append(callRef)
val lambda = call.lambdaArguments.singleOrNull()
lambda?.accept(object : PsiRecursiveElementVisitor(false) {
override fun visitElement(element: PsiElement) {
super.visitElement(element)
when (element) {
is PsiWhiteSpace -> if (element.text.contains("\n")) result.append("\n")
is LeafPsiElement -> result.append(element.text)
}
}
})
result.append("\n")
}
}
GradleKotlinScriptConfigurationInputs(result.toString())
} else null
}
}
+5
View File
@@ -12,6 +12,11 @@
<scriptDiagnosticFixProvider implementation="org.jetbrains.kotlin.idea.scripting.gradle.GradleScriptDiagnosticFixProvider"/>
</extensions>
<extensions defaultExtensionNs="org.jetbrains.kotlin.scripting.idea">
<listener implementation="org.jetbrains.kotlin.idea.script.GradleScriptListener"/>
<loader implementation="org.jetbrains.kotlin.idea.script.GradleScriptConfigurationLoader"/>
</extensions>
<extensions defaultExtensionNs="org.jetbrains.plugins.gradle">
<orderEnumerationHandlerFactory implementation="org.jetbrains.kotlin.idea.gradle.execution.KotlinGradleOrderEnumerationHandler$Factory" order="first"/>
<projectResolve implementation="org.jetbrains.kotlin.idea.configuration.KotlinMPPGradleProjectResolver"/>
+5
View File
@@ -12,6 +12,11 @@
<scriptDiagnosticFixProvider implementation="org.jetbrains.kotlin.idea.scripting.gradle.GradleScriptDiagnosticFixProvider"/>
</extensions>
<extensions defaultExtensionNs="org.jetbrains.kotlin.scripting.idea">
<listener implementation="org.jetbrains.kotlin.idea.script.GradleScriptListener"/>
<loader implementation="org.jetbrains.kotlin.idea.script.GradleScriptConfigurationLoader"/>
</extensions>
<extensions defaultExtensionNs="org.jetbrains.plugins.gradle">
<orderEnumerationHandlerFactory implementation="org.jetbrains.kotlin.idea.gradle.execution.KotlinGradleOrderEnumerationHandler$Factory" order="first"/>
<projectResolve implementation="org.jetbrains.kotlin.idea.configuration.KotlinMPPGradleProjectResolver"/>