From 80f7dda6c787f05613cc27cdcf11b1d74cca2aa4 Mon Sep 17 00:00:00 2001 From: Ilya Chernikov Date: Thu, 28 Jul 2016 17:14:18 +0200 Subject: [PATCH] Update gradle script resolver environment: - JVM options from IDEA config to connect/run daemon with appropriate options (need to be tested) - A lexing function to allow gradle plugin to check whether dependency-defining part of the script is actually changed --- .../script/gradleScriptTemplateProvider.kt | 73 ++++++++++++++++++- 1 file changed, 70 insertions(+), 3 deletions(-) diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/gradleScriptTemplateProvider.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/gradleScriptTemplateProvider.kt index c08214f4441..a90ec97b1cb 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/gradleScriptTemplateProvider.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/gradleScriptTemplateProvider.kt @@ -16,13 +16,17 @@ package org.jetbrains.kotlin.idea.core.script +import com.intellij.execution.configurations.CommandLineTokenizer import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil import com.intellij.openapi.project.Project import org.gradle.tooling.ProjectConnection +import org.jetbrains.kotlin.lexer.KotlinLexer +import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.script.ScriptTemplateProvider import org.jetbrains.plugins.gradle.service.execution.GradleExecutionHelper import org.jetbrains.plugins.gradle.settings.GradleExecutionSettings import java.io.File +import java.util.* class GradleScriptTemplateProvider(project: Project): ScriptTemplateProvider { @@ -42,6 +46,15 @@ class GradleScriptTemplateProvider(project: Project): ScriptTemplateProvider { } } + private val gradleJvmOptions: List by lazy { + gradleExeSettings?.let { settings -> + CommandLineTokenizer(settings.daemonVmOptions).toList() + .mapNotNull { it?.let { it as? String } } + .filterNot { it.isBlank() } + .distinct() + } ?: emptyList() + } + override val id: String = "Gradle" override val version: Int = 1 override val isValid: Boolean get() = gradleExeSettings?.gradleHome != null @@ -54,12 +67,16 @@ class GradleScriptTemplateProvider(project: Project): ScriptTemplateProvider { ?.map { it.canonicalPath } ?: emptyList() } - override val environment: Map? by lazy { mapOf( + override val environment: Map? by lazy { + + mapOf( "gradleHome" to gradleExeSettings?.gradleHome?.let { File(it) }, "projectRoot" to (project.basePath ?: project.baseDir.canonicalPath)?.let { File(it) }, - "projectActionExecutor" to { action: (ProjectConnection) -> Unit -> + "gradleWithConnection" to { action: (ProjectConnection) -> Unit -> GradleExecutionHelper().execute(project.basePath!!, null) { action(it) } }, - "gradleJavaHome" to gradleExeSettings?.javaHome) + "gradleJavaHome" to gradleExeSettings?.javaHome, + "gradleJvmOptions" to gradleJvmOptions, + "getScriptSectionTokens" to ::topLevelSectionCodeTextTokens) } companion object { @@ -67,3 +84,53 @@ class GradleScriptTemplateProvider(project: Project): ScriptTemplateProvider { } } +class TopLevelSectionTokensEnumerator(script: CharSequence, identifier: String) : Enumeration { + + private val lexer = KotlinLexer().apply { + start(script) + var depth = 0 + + loop@ while (tokenType != null) { + when (tokenType) { + KtTokens.IDENTIFIER -> if (depth == 0 && tokenText == identifier) { + advance() + skipWhiteSpaceAndComments() + if (tokenType == KtTokens.LBRACE) + break@loop + } + KtTokens.LBRACE -> depth += 1 + KtTokens.RBRACE -> depth -= 1 + } + advance() + } + } + + private var depth = 1 + private var finished = false + + override fun hasMoreElements(): Boolean = !finished && lexer.tokenType != null + + override fun nextElement(): KotlinLexer = lexer.apply { + advance() + when (tokenType) { + KtTokens.LBRACE -> depth += 1 + KtTokens.RBRACE -> { + if (depth == 1) { + finished = true + } + depth -= 1 + } + } + } + + private fun KotlinLexer.skipWhiteSpaceAndComments() { + while (tokenType in KtTokens.WHITE_SPACE_OR_COMMENT_BIT_SET) { + advance() + } + } +} + +fun topLevelSectionCodeTextTokens(script: CharSequence, sectionIdentifier: String): Sequence = + TopLevelSectionTokensEnumerator(script, sectionIdentifier).asSequence() + .filter { it.tokenType !in KtTokens.WHITE_SPACE_OR_COMMENT_BIT_SET } + .map { it.tokenSequence } \ No newline at end of file