From bd6481b9e8692d6f587f186614210b5021c10327 Mon Sep 17 00:00:00 2001 From: Natalia Selezneva Date: Tue, 1 Oct 2019 12:21:29 +0300 Subject: [PATCH] Add support for settings.gradle.kts configuring kotlin in project (KT-34114) ^KT-34114 Fixed --- .../GradleKotlinFrameworkSupportProvider.kt | 3 +- .../configuration/gradleModuleBuilderUtils.kt | 61 ++++++++++++++----- 2 files changed, 49 insertions(+), 15 deletions(-) diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/GradleKotlinFrameworkSupportProvider.kt b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/GradleKotlinFrameworkSupportProvider.kt index 588e2083521..dde26c5b154 100644 --- a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/GradleKotlinFrameworkSupportProvider.kt +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/GradleKotlinFrameworkSupportProvider.kt @@ -27,6 +27,7 @@ import com.intellij.openapi.roots.ModifiableModelsProvider import com.intellij.openapi.roots.ModifiableRootModel import com.intellij.openapi.vfs.LocalFileSystem import com.intellij.openapi.vfs.VfsUtil.createDirectoryIfMissing +import com.intellij.psi.PsiFile import org.jetbrains.kotlin.idea.KotlinIcons import org.jetbrains.kotlin.idea.formatter.KotlinStyleGuideCodeStyle import org.jetbrains.kotlin.idea.formatter.ProjectCodeStyleImporter @@ -156,7 +157,7 @@ abstract class GradleKotlinFrameworkSupportProvider( KotlinFUSLogger.log(FUSEventGroups.NPWizards, this.javaClass.simpleName) } - protected open fun updateSettingsScript(settingsBuilder: SettingsScriptBuilder, specifyPluginVersionIfNeeded: Boolean) {} + protected open fun updateSettingsScript(settingsBuilder: SettingsScriptBuilder, specifyPluginVersionIfNeeded: Boolean) {} protected abstract fun getDependencies(sdk: Sdk?): List protected open fun getTestDependencies(): List = listOf() diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/gradleModuleBuilderUtils.kt b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/gradleModuleBuilderUtils.kt index 375705ce710..d8c74b02269 100644 --- a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/gradleModuleBuilderUtils.kt +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/gradleModuleBuilderUtils.kt @@ -9,6 +9,7 @@ import com.intellij.framework.addSupport.FrameworkSupportInModuleConfigurable import com.intellij.ide.util.frameworkSupport.FrameworkSupportModel import com.intellij.openapi.externalSystem.model.project.ProjectId import com.intellij.openapi.module.Module +import com.intellij.openapi.project.Project import com.intellij.openapi.project.ProjectCoreUtil import com.intellij.openapi.roots.ModifiableModelsProvider import com.intellij.openapi.roots.ModifiableRootModel @@ -16,8 +17,11 @@ import com.intellij.openapi.util.Key import com.intellij.openapi.vfs.LocalFileSystem import com.intellij.openapi.vfs.VfsUtil import com.intellij.openapi.vfs.VirtualFile +import com.intellij.psi.PsiFile import com.intellij.psi.codeStyle.CodeStyleManager import org.jetbrains.kotlin.idea.core.util.toPsiFile +import org.jetbrains.kotlin.psi.KtFile +import org.jetbrains.kotlin.psi.KtPsiFactory import org.jetbrains.kotlin.psi.UserDataProperty import org.jetbrains.plugins.gradle.frameworkSupport.GradleFrameworkSupportProvider import org.jetbrains.plugins.gradle.service.project.wizard.GradleModuleBuilder @@ -27,7 +31,7 @@ import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory import java.io.File internal var Module.gradleModuleBuilder: GradleModuleBuilder? by UserDataProperty(Key.create("GRADLE_MODULE_BUILDER")) -private var Module.settingsScriptBuilder: SettingsScriptBuilder? by UserDataProperty(Key.create("SETTINGS_SCRIPT_BUILDER")) +private var Module.settingsScriptBuilder: SettingsScriptBuilder? by UserDataProperty(Key.create("SETTINGS_SCRIPT_BUILDER")) internal fun findSettingsGradleFile(module: Module): VirtualFile? { val contentEntryPath = module.gradleModuleBuilder?.contentEntryPath ?: return null @@ -35,10 +39,12 @@ internal fun findSettingsGradleFile(module: Module): VirtualFile? { val contentRootDir = File(contentEntryPath) val modelContentRootDir = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(contentRootDir) ?: return null return modelContentRootDir.findChild(GradleConstants.SETTINGS_FILE_NAME) - ?: module.project.baseDir.findChild(GradleConstants.SETTINGS_FILE_NAME) + ?: modelContentRootDir.findChild(GradleConstants.KOTLIN_DSL_SETTINGS_FILE_NAME) + ?: module.project.baseDir.findChild(GradleConstants.SETTINGS_FILE_NAME) + ?: module.project.baseDir.findChild(GradleConstants.KOTLIN_DSL_SETTINGS_FILE_NAME) } -class SettingsScriptBuilder(scriptFile: GroovyFile) { +abstract class SettingsScriptBuilder(val scriptFile: T) { private val builder = StringBuilder(scriptFile.text) private fun findBlockBody(blockName: String, startFrom: Int = 0): Int { @@ -81,7 +87,7 @@ class SettingsScriptBuilder(scriptFile: GroovyFile) { private fun getOrCreatePluginManagementBody() = getOrPrependTopLevelBlockBody("pluginManagement") - private fun addPluginRepositoryExpression(expression: String) { + protected fun addPluginRepositoryExpression(expression: String) { val repositoriesBody = getOrAppendInnerBlockBody("repositories", getOrCreatePluginManagementBody()) appendExpressionToBlockIfAbsent(expression, repositoriesBody) } @@ -90,9 +96,7 @@ class SettingsScriptBuilder(scriptFile: GroovyFile) { addPluginRepositoryExpression("mavenCentral()") } - fun addPluginRepository(repository: RepositoryDescription) { - addPluginRepositoryExpression(repository.toGroovyRepositorySnippet()) - } + abstract fun addPluginRepository(repository: RepositoryDescription) fun addResolutionStrategy(pluginId: String) { val resolutionStrategyBody = getOrAppendInnerBlockBody("resolutionStrategy", getOrCreatePluginManagementBody()) @@ -112,16 +116,48 @@ class SettingsScriptBuilder(scriptFile: GroovyFile) { } fun build() = builder.toString() + + abstract fun buildPsiFile(project: Project): T +} + + +class GroovySettingsScriptBuilder(scriptFile: GroovyFile): SettingsScriptBuilder(scriptFile) { + override fun addPluginRepository(repository: RepositoryDescription) { + addPluginRepositoryExpression(repository.toGroovyRepositorySnippet()) + } + + override fun buildPsiFile(project: Project): GroovyFile { + return GroovyPsiElementFactory + .getInstance(project) + .createGroovyFile(build(), false, null) + } +} +class KotlinSettingsScriptBuilder(scriptFile: KtFile): SettingsScriptBuilder(scriptFile) { + override fun addPluginRepository(repository: RepositoryDescription) { + addPluginRepositoryExpression(repository.toKotlinRepositorySnippet()) + } + + override fun buildPsiFile(project: Project): KtFile { + return KtPsiFactory(project).createFile(build()) + } } // Circumvent write actions and modify the file directly // TODO: Get rid of this hack when IDEA API allows manipulation of settings script similarly to the main script itself -internal fun updateSettingsScript(module: Module, updater: (SettingsScriptBuilder) -> Unit) { +internal fun updateSettingsScript(module: Module, updater: (SettingsScriptBuilder) -> Unit) { val storedSettingsBuilder = module.settingsScriptBuilder val settingsBuilder = storedSettingsBuilder - ?: (findSettingsGradleFile(module)?.toPsiFile(module.project) as? GroovyFile)?.let { SettingsScriptBuilder(it) } - ?: return + ?: (findSettingsGradleFile(module)?.toPsiFile(module.project))?.let { + if (it is KtFile) { + KotlinSettingsScriptBuilder(it) + } else if (it is GroovyFile) { + GroovySettingsScriptBuilder(it) + } else { + null + } + } + ?: return if (storedSettingsBuilder == null) { module.settingsScriptBuilder = settingsBuilder } @@ -140,10 +176,7 @@ internal fun flushSettingsGradleCopy(module: Module) { // and we will get KT-29333 problem). // TODO: get rid of file manipulations until project is opened val project = ProjectCoreUtil.theOnlyOpenProject() ?: module.project - val tmpFile = - GroovyPsiElementFactory - .getInstance(project) - .createGroovyFile(settingsScriptBuilder.build(), false, null) + val tmpFile = settingsScriptBuilder.buildPsiFile(project) CodeStyleManager.getInstance(project).reformat(tmpFile) VfsUtil.saveText(settingsFile, tmpFile.text) }