diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/importing/KotlinDslScriptModel.kt b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/importing/KotlinDslScriptModel.kt index 11656eddc87..c42ddea554a 100644 --- a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/importing/KotlinDslScriptModel.kt +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/importing/KotlinDslScriptModel.kt @@ -5,19 +5,6 @@ package org.jetbrains.kotlin.idea.scripting.gradle.importing -import com.intellij.openapi.externalSystem.model.DataNode -import com.intellij.openapi.externalSystem.model.project.ProjectData -import com.intellij.openapi.util.Key -import org.jetbrains.kotlin.idea.util.NotNullableCopyableDataNodeUserDataProperty - -var DataNode.KOTLIN_DSL_SCRIPT_MODELS: MutableList - by NotNullableCopyableDataNodeUserDataProperty( - Key.create>( - "GRADLE_KOTLIN_BUILD_SCRIPTS" - ), - mutableListOf() - ) - data class KotlinDslScriptModel( val file: String, val inputsTimeStamp: Long, diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/importing/KotlinDslScriptModelDataService.kt b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/importing/KotlinDslScriptModelDataService.kt deleted file mode 100644 index bda07c0982e..00000000000 --- a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/importing/KotlinDslScriptModelDataService.kt +++ /dev/null @@ -1,160 +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.scripting.gradle.importing - -import com.intellij.openapi.components.service -import com.intellij.openapi.externalSystem.model.DataNode -import com.intellij.openapi.externalSystem.model.Key -import com.intellij.openapi.externalSystem.model.ProjectKeys -import com.intellij.openapi.externalSystem.model.project.ProjectData -import com.intellij.openapi.externalSystem.service.notification.ExternalSystemNotificationManager -import com.intellij.openapi.externalSystem.service.notification.NotificationCategory -import com.intellij.openapi.externalSystem.service.notification.NotificationData -import com.intellij.openapi.externalSystem.service.notification.NotificationSource -import com.intellij.openapi.externalSystem.service.project.IdeModelsProvider -import com.intellij.openapi.externalSystem.service.project.manage.AbstractProjectDataService -import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil -import com.intellij.openapi.fileEditor.OpenFileDescriptor -import com.intellij.openapi.project.Project -import com.intellij.openapi.vfs.VfsUtil -import com.intellij.openapi.vfs.VirtualFile -import com.intellij.pom.Navigatable -import org.jetbrains.kotlin.idea.KotlinIdeaGradleBundle -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.scripting.gradle.GradleScriptInputsWatcher -import org.jetbrains.kotlin.idea.scripting.gradle.getGradleScriptInputsStamp -import org.jetbrains.kotlin.idea.scripting.gradle.saveGradleProjectRootsAfterImport -import org.jetbrains.kotlin.scripting.definitions.findScriptDefinition -import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationWrapper -import org.jetbrains.kotlin.scripting.resolve.VirtualFileScriptSource -import org.jetbrains.kotlin.scripting.resolve.adjustByDefinition -import org.jetbrains.plugins.gradle.settings.GradleExecutionSettings -import org.jetbrains.plugins.gradle.util.GradleConstants -import java.io.File -import kotlin.script.experimental.api.* -import kotlin.script.experimental.jvm.JvmDependency -import kotlin.script.experimental.jvm.jdkHome -import kotlin.script.experimental.jvm.jvm - -class KotlinDslScriptModelDataService : AbstractProjectDataService() { - override fun getTargetDataKey(): Key = ProjectKeys.PROJECT - - override fun onSuccessImport( - imported: MutableCollection>, - projectData: ProjectData?, - project: Project, - modelsProvider: IdeModelsProvider - ) { - super.onSuccessImport(imported, projectData, project, modelsProvider) - - val projectDataNode = imported.singleOrNull() ?: return - val gradleKotlinBuildScripts = projectDataNode.KOTLIN_DSL_SCRIPT_MODELS - val buildScripts = gradleKotlinBuildScripts.toList() - gradleKotlinBuildScripts.clear() - - val gradleSettings = ExternalSystemApiUtil.getSettings(project, GradleConstants.SYSTEM_ID) - val projectRoot = projectData?.linkedExternalProjectPath ?: return - val projectSettings = gradleSettings.getLinkedProjectSettings(projectRoot) ?: return - - saveGradleProjectRootsAfterImport(projectSettings.modules.takeIf { it.isNotEmpty() } ?: setOf(projectRoot)) - - val gradleExeSettings = ExternalSystemApiUtil.getExecutionSettings( - project, - projectSettings.externalProjectPath, - GradleConstants.SYSTEM_ID - ) - val javaHome = File(gradleExeSettings.javaHome ?: return) - - val scriptConfigurations = mutableListOf>() - - buildScripts.forEach { buildScript -> - val scriptFile = File(buildScript.file) - val virtualFile = VfsUtil.findFile(scriptFile.toPath(), true)!! - - val inputs = getGradleScriptInputsStamp(project, virtualFile, givenTimeStamp = buildScript.inputsTimeStamp) - - val definition = virtualFile.findScriptDefinition(project) ?: return@forEach - - val configuration = - definition.compilationConfiguration.with { - jvm.jdkHome(javaHome) - defaultImports(buildScript.imports) - dependencies(JvmDependency(buildScript.classPath.map { File(it) })) - ide.dependenciesSources(JvmDependency(buildScript.sourcePath.map { File(it) })) - }.adjustByDefinition(definition) - - scriptConfigurations.add( - Pair( - virtualFile, - ScriptConfigurationSnapshot( - inputs ?: CachedConfigurationInputs.OutOfDate, - listOf(), - ScriptCompilationConfigurationWrapper.FromCompilationConfiguration( - VirtualFileScriptSource(virtualFile), - configuration - ) - ) - ) - ) - - buildScript.messages.forEach { - addBuildScriptDiagnosticMessage(it, virtualFile, project) - } - } - - project.service().saveCompilationConfigurationAfterImport(scriptConfigurations) - project.service().clearState() - } - - private fun addBuildScriptDiagnosticMessage( - message: KotlinDslScriptModel.Message, - virtualFile: VirtualFile, - project: Project - ) { - val notification = NotificationData( - KotlinIdeaGradleBundle.message("title.kotlin.build.script"), - message.text, - when (message.severity) { - KotlinDslScriptModel.Severity.WARNING -> NotificationCategory.WARNING - KotlinDslScriptModel.Severity.ERROR -> NotificationCategory.ERROR - }, - NotificationSource.PROJECT_SYNC - ) - - notification.navigatable = - LazyNavigatable( - virtualFile, - project, - message.position - ) - - ExternalSystemNotificationManager.getInstance(project).showNotification( - GradleConstants.SYSTEM_ID, - notification - ) - } - - class LazyNavigatable internal constructor( - private val virtualFile: VirtualFile, - private val project: Project, - val position: KotlinDslScriptModel.Position? - ) : Navigatable { - private val openFileDescriptor: Navigatable by lazy { - if (position != null) OpenFileDescriptor(project, virtualFile, position.line, position.column) - else OpenFileDescriptor(project, virtualFile, -1) - } - - override fun navigate(requestFocus: Boolean) { - if (openFileDescriptor.canNavigate()) openFileDescriptor.navigate(requestFocus) - } - - override fun canNavigate(): Boolean = virtualFile.exists() - - override fun canNavigateToSource(): Boolean = canNavigate() - } -} \ No newline at end of file diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/importing/KotlinDslScriptModelResolverCommon.kt b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/importing/KotlinDslScriptModelResolverCommon.kt index 8129ea08e46..339b8b4ee79 100644 --- a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/importing/KotlinDslScriptModelResolverCommon.kt +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/importing/KotlinDslScriptModelResolverCommon.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.idea.scripting.gradle.importing import com.intellij.openapi.diagnostic.Logger import com.intellij.openapi.externalSystem.model.DataNode import com.intellij.openapi.externalSystem.model.project.ProjectData +import com.intellij.openapi.externalSystem.util.Order import com.intellij.openapi.util.Pair import org.gradle.tooling.model.kotlin.dsl.EditorReportSeverity import org.gradle.tooling.model.kotlin.dsl.KotlinDslModelsParameters.* @@ -16,6 +17,7 @@ import org.jetbrains.plugins.gradle.service.project.AbstractProjectResolverExten internal val LOG = Logger.getInstance(KotlinDslScriptModelResolverCommon::class.java) +@Order(Integer.MIN_VALUE) // to be the first abstract class KotlinDslScriptModelResolverCommon : AbstractProjectResolverExtension() { override fun getExtraProjectModelClasses(): Set> { return setOf(KotlinDslScriptsModel::class.java) @@ -83,7 +85,9 @@ abstract class KotlinDslScriptModelResolverCommon : AbstractProjectResolverExten "Couldn't get KotlinDslScriptsModel for $projectName:\n${model.message}\n${model.stackTrace}" ) } else { - ideProject.KOTLIN_DSL_SCRIPT_MODELS.addAll(model.toListOfScriptModels()) + val models = model.toListOfScriptModels() + + saveScriptModels(resolverCtx, models) } } } \ No newline at end of file diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/importing/KotlinDslScrtiptModelProcessor.kt b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/importing/KotlinDslScrtiptModelProcessor.kt new file mode 100644 index 00000000000..a28e87af2bd --- /dev/null +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/scripting/gradle/importing/KotlinDslScrtiptModelProcessor.kt @@ -0,0 +1,157 @@ +/* + * Copyright 2010-2020 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.scripting.gradle.importing + +import com.intellij.build.SyncViewManager +import com.intellij.openapi.components.service +import com.intellij.openapi.externalSystem.service.execution.ExternalSystemEventDispatcher +import com.intellij.openapi.externalSystem.service.notification.ExternalSystemNotificationManager +import com.intellij.openapi.externalSystem.service.notification.NotificationCategory +import com.intellij.openapi.externalSystem.service.notification.NotificationData +import com.intellij.openapi.externalSystem.service.notification.NotificationSource +import com.intellij.openapi.fileEditor.OpenFileDescriptor +import com.intellij.openapi.project.Project +import com.intellij.openapi.vfs.VfsUtil +import com.intellij.openapi.vfs.VirtualFile +import com.intellij.pom.Navigatable +import org.jetbrains.kotlin.idea.KotlinIdeaGradleBundle +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.scripting.gradle.GradleScriptInputsWatcher +import org.jetbrains.kotlin.idea.scripting.gradle.getGradleScriptInputsStamp +import org.jetbrains.kotlin.idea.scripting.gradle.saveGradleProjectRootsAfterImport +import org.jetbrains.kotlin.scripting.definitions.findScriptDefinition +import org.jetbrains.kotlin.scripting.resolve.ScriptCompilationConfigurationWrapper +import org.jetbrains.kotlin.scripting.resolve.VirtualFileScriptSource +import org.jetbrains.kotlin.scripting.resolve.adjustByDefinition +import org.jetbrains.plugins.gradle.service.project.ProjectResolverContext +import org.jetbrains.plugins.gradle.util.GradleConstants +import java.io.File +import kotlin.script.experimental.api.* +import kotlin.script.experimental.jvm.JvmDependency +import kotlin.script.experimental.jvm.jdkHome +import kotlin.script.experimental.jvm.jvm + +fun saveScriptModels( + resolverContext: ProjectResolverContext, + models: List +) { + val task = resolverContext.externalSystemTaskId + val project = task.findProject() ?: return + val settings = resolverContext.settings ?: return + + val scriptConfigurations = mutableListOf>() + + val syncViewManager = project.service() + val buildEventDispatcher = + ExternalSystemEventDispatcher(task, syncViewManager) + + val javaHome = settings.javaHome?.let { File(it) } + models.forEach { buildScript -> + val scriptFile = File(buildScript.file) + val virtualFile = VfsUtil.findFile(scriptFile.toPath(), true)!! + + val inputs = getGradleScriptInputsStamp( + project, + virtualFile, + givenTimeStamp = buildScript.inputsTimeStamp + ) + + val definition = virtualFile.findScriptDefinition(project) ?: return@forEach + + val configuration = + definition.compilationConfiguration.with { + if (javaHome != null) { + jvm.jdkHome(javaHome) + } + defaultImports(buildScript.imports) + dependencies(JvmDependency(buildScript.classPath.map { + File( + it + ) + })) + ide.dependenciesSources(JvmDependency(buildScript.sourcePath.map { + File( + it + ) + })) + }.adjustByDefinition(definition) + + scriptConfigurations.add( + Pair( + virtualFile, + ScriptConfigurationSnapshot( + inputs + ?: CachedConfigurationInputs.OutOfDate, + listOf(), + ScriptCompilationConfigurationWrapper.FromCompilationConfiguration( + VirtualFileScriptSource(virtualFile), + configuration, + ), + ), + ), + ) + + buildScript.messages.forEach { + addBuildScriptDiagnosticMessage(it, virtualFile, project) + } + } + + saveGradleProjectRootsAfterImport( + scriptConfigurations.map { it.first.parent.path }.toSet() + ) + + project.service().saveCompilationConfigurationAfterImport(scriptConfigurations) + project.service().clearState() +} + +private fun addBuildScriptDiagnosticMessage( + message: KotlinDslScriptModel.Message, + virtualFile: VirtualFile, + project: Project +) { + val notification = NotificationData( + KotlinIdeaGradleBundle.message("title.kotlin.build.script"), + message.text, + when (message.severity) { + KotlinDslScriptModel.Severity.WARNING -> NotificationCategory.WARNING + KotlinDslScriptModel.Severity.ERROR -> NotificationCategory.ERROR + }, + NotificationSource.PROJECT_SYNC + ) + + notification.navigatable = + LazyNavigatable( + virtualFile, + project, + message.position + ) + + ExternalSystemNotificationManager.getInstance(project).showNotification( + GradleConstants.SYSTEM_ID, + notification + ) +} + +class LazyNavigatable internal constructor( + private val virtualFile: VirtualFile, + private val project: Project, + val position: KotlinDslScriptModel.Position? +) : Navigatable { + private val openFileDescriptor: Navigatable by lazy { + if (position != null) OpenFileDescriptor(project, virtualFile, position.line, position.column) + else OpenFileDescriptor(project, virtualFile, -1) + } + + override fun navigate(requestFocus: Boolean) { + if (openFileDescriptor.canNavigate()) openFileDescriptor.navigate(requestFocus) + } + + override fun canNavigate(): Boolean = virtualFile.exists() + + override fun canNavigateToSource(): Boolean = canNavigate() +} \ No newline at end of file diff --git a/idea/resources/META-INF/gradle.xml b/idea/resources/META-INF/gradle.xml index a295f8317f2..ec9c0ce20bd 100644 --- a/idea/resources/META-INF/gradle.xml +++ b/idea/resources/META-INF/gradle.xml @@ -27,7 +27,7 @@ - +