201: KotlinDslScriptsModel: use ProjectModelContributor to process models

Instead of populateProjectExtraModels in Resolver
This commit is contained in:
Natalia Selezneva
2020-03-17 13:24:04 +03:00
parent 9e4c1ee4e8
commit 7f5715f5da
6 changed files with 174 additions and 75 deletions
@@ -45,7 +45,7 @@ class KotlinDslScriptModelResolver : KotlinDslScriptModelResolverCommon() {
root.projects.forEach {
if (it.projectIdentifier.projectPath == ":") {
resolverCtx.models.getModel(it, KotlinDslScriptsModel::class.java)?.let { model ->
processScriptModel(ideProject, model, it.projectIdentifier.projectPath)
processScriptModel(resolverCtx, model, it.projectIdentifier.projectPath)
}
}
}
@@ -43,7 +43,7 @@ class KotlinDslScriptModelResolver : KotlinDslScriptModelResolverCommon() {
root.modules.forEach {
if (it.gradleProject.parent == null) {
resolverCtx.getExtraProject(it, KotlinDslScriptsModel::class.java)?.let { model ->
processScriptModel(ideProject, model, it.name)
processScriptModel(resolverCtx, model, it.name)
}
}
}
@@ -0,0 +1,49 @@
/*
* 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 org.jetbrains.plugins.gradle.model.ClassSetImportModelProvider
import org.jetbrains.plugins.gradle.model.ProjectImportModelProvider
import org.gradle.tooling.model.kotlin.dsl.KotlinDslScriptsModel
import org.jetbrains.kotlin.idea.scripting.gradle.kotlinDslScriptsModelImportSupported
import org.jetbrains.plugins.gradle.service.project.ModifiableGradleProjectModel
import org.jetbrains.plugins.gradle.service.project.ProjectModelContributor
import org.jetbrains.plugins.gradle.service.project.ProjectResolverContext
import org.jetbrains.plugins.gradle.service.project.ToolingModelsProvider
class KotlinDslScriptModelResolver : KotlinDslScriptModelResolverCommon() {
override fun requiresTaskRunning() = true
override fun getModelProvider() = KotlinDslScriptModelProvider()
override fun getProjectsLoadedModelProvider(): ProjectImportModelProvider? {
return ClassSetImportModelProvider(
emptySet(),
setOf(KotlinDslScriptAdditionalTask::class.java)
)
}
}
@Suppress("UnstableApiUsage")
class KotlinDslScriptModelContributor : ProjectModelContributor {
override fun accept(
projectModelBuilder: ModifiableGradleProjectModel,
toolingModelsProvider: ToolingModelsProvider,
resolverContext: ProjectResolverContext
) {
if (!kotlinDslScriptsModelImportSupported(resolverContext.projectGradleVersion)) return
toolingModelsProvider.projects().forEach {
val projectIdentifier = it.projectIdentifier.projectPath
if (projectIdentifier == ":") {
val model = toolingModelsProvider.getProjectModel(it, KotlinDslScriptsModel::class.java)
if (model != null) {
processScriptModel(resolverContext, model, projectIdentifier)
}
}
}
}
}
@@ -6,14 +6,10 @@
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.*
import org.gradle.tooling.model.kotlin.dsl.KotlinDslScriptsModel
import org.jetbrains.kotlin.idea.KotlinIdeaGradleBundle
import org.jetbrains.plugins.gradle.service.project.AbstractProjectResolverExtension
internal val LOG = Logger.getInstance(KotlinDslScriptModelResolverCommon::class.java)
@@ -36,73 +32,4 @@ abstract class KotlinDslScriptModelResolverCommon : AbstractProjectResolverExten
override fun getExtraCommandLineArgs(): List<String> {
return listOf("-P$CORRELATION_ID_GRADLE_PROPERTY_NAME=${System.nanoTime()}")
}
@Suppress("unused")
protected fun KotlinDslScriptsModel.toListOfScriptModels(): List<KotlinDslScriptModel> =
scriptModels.map { (file, model) ->
val messages = mutableListOf<KotlinDslScriptModel.Message>()
model.exceptions.forEach {
val fromException = parsePositionFromException(it)
if (fromException != null) {
val (filePath, _) = fromException
if (filePath != file.path) return@forEach
}
messages.add(
KotlinDslScriptModel.Message(
KotlinDslScriptModel.Severity.ERROR,
it.substringBefore(System.lineSeparator()),
it,
fromException?.second
)
)
}
model.editorReports.forEach {
messages.add(
KotlinDslScriptModel.Message(
when (it.severity) {
EditorReportSeverity.WARNING -> KotlinDslScriptModel.Severity.WARNING
else -> KotlinDslScriptModel.Severity.ERROR
},
it.message,
position = KotlinDslScriptModel.Position(it.position?.line ?: 0, it.position?.column ?: 0)
)
)
}
// todo(KT-34440): take inputs snapshot before starting import
KotlinDslScriptModel(
file.absolutePath,
System.currentTimeMillis(),
model.classPath.map { it.absolutePath },
model.sourcePath.map { it.absolutePath },
model.implicitImports,
messages
)
}
protected fun processScriptModel(
ideProject: DataNode<ProjectData>,
model: KotlinDslScriptsModel,
projectName: String
) {
if (model is BrokenKotlinDslScriptsModel) {
LOG.error(
"Couldn't get KotlinDslScriptsModel for $projectName:\n${model.message}\n${model.stackTrace}"
)
} else {
val models = model.toListOfScriptModels()
resolverCtx.externalSystemTaskId.findProject()?.kotlinDslModels?.addAll(
models
)
if (models.containsErrors()) {
throw IllegalStateException(KotlinIdeaGradleBundle.message("title.kotlin.build.script"))
}
}
}
private fun Collection<KotlinDslScriptModel>.containsErrors(): Boolean {
return any { it.messages.any { it.severity == KotlinDslScriptModel.Severity.ERROR } }
}
}
@@ -10,6 +10,9 @@ import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskId
import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.VfsUtil
import com.intellij.openapi.vfs.VirtualFile
import org.gradle.tooling.model.kotlin.dsl.EditorReportSeverity
import org.gradle.tooling.model.kotlin.dsl.KotlinDslScriptsModel
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
@@ -27,6 +30,78 @@ import kotlin.script.experimental.jvm.JvmDependency
import kotlin.script.experimental.jvm.jdkHome
import kotlin.script.experimental.jvm.jvm
fun processScriptModel(
resolverCtx: ProjectResolverContext,
model: KotlinDslScriptsModel,
projectName: String
) {
if (model is BrokenKotlinDslScriptsModel) {
LOG.error(
"Couldn't get KotlinDslScriptsModel for $projectName:\n${model.message}\n${model.stackTrace}"
)
} else {
val models = model.toListOfScriptModels()
resolverCtx.externalSystemTaskId.findProject()?.kotlinDslModels?.addAll(
models
)
if (models.containsErrors()) {
throw IllegalStateException(KotlinIdeaGradleBundle.message("title.kotlin.build.script"))
}
if (models.containsErrors()) {
throw IllegalStateException(KotlinIdeaGradleBundle.message("title.kotlin.build.script"))
}
}
}
private fun Collection<KotlinDslScriptModel>.containsErrors(): Boolean {
return any { it.messages.any { it.severity == KotlinDslScriptModel.Severity.ERROR } }
}
private fun KotlinDslScriptsModel.toListOfScriptModels(): List<KotlinDslScriptModel> =
scriptModels.map { (file, model) ->
val messages = mutableListOf<KotlinDslScriptModel.Message>()
model.exceptions.forEach {
val fromException = parsePositionFromException(it)
if (fromException != null) {
val (filePath, _) = fromException
if (filePath != file.path) return@forEach
}
messages.add(
KotlinDslScriptModel.Message(
KotlinDslScriptModel.Severity.ERROR,
it.substringBefore(System.lineSeparator()),
it,
fromException?.second
)
)
}
model.editorReports.forEach {
messages.add(
KotlinDslScriptModel.Message(
when (it.severity) {
EditorReportSeverity.WARNING -> KotlinDslScriptModel.Severity.WARNING
else -> KotlinDslScriptModel.Severity.ERROR
},
it.message,
position = KotlinDslScriptModel.Position(it.position?.line ?: 0, it.position?.column ?: 0)
)
)
}
// todo(KT-34440): take inputs snapshot before starting import
KotlinDslScriptModel(
file.absolutePath,
System.currentTimeMillis(),
model.classPath.map { it.absolutePath },
model.sourcePath.map { it.absolutePath },
model.implicitImports,
messages
)
}
fun saveScriptModels(
project: Project,
task: ExternalSystemTaskId,
+48
View File
@@ -0,0 +1,48 @@
<idea-plugin>
<extensionPoints>
<extensionPoint qualifiedName="org.jetbrains.kotlin.gradleProjectImportHandler" area="IDEA_PROJECT"
interface="org.jetbrains.kotlin.idea.configuration.GradleProjectImportHandler"/>
<extensionPoint qualifiedName="org.jetbrains.kotlin.gradleModelFacade"
interface="org.jetbrains.kotlin.idea.inspections.gradle.KotlinGradleModelFacade"/>
</extensionPoints>
<extensions defaultExtensionNs="org.jetbrains.kotlin">
<buildSystemTypeDetector implementation="org.jetbrains.kotlin.idea.configuration.GradleDetector"/>
<scriptDiagnosticFixProvider implementation="org.jetbrains.kotlin.idea.scripting.gradle.GradleScriptDiagnosticFixProvider"/>
</extensions>
<extensions defaultExtensionNs="org.jetbrains.kotlin.scripting.idea">
<listener order="first" implementation="org.jetbrains.kotlin.idea.scripting.gradle.GradleScriptListener"/>
<loader order="first" implementation="org.jetbrains.kotlin.idea.scripting.gradle.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"/>
<testTasksProvider implementation="org.jetbrains.kotlin.idea.run.KotlinMPPGradleTestTasksProvider"/>
<projectModelContributor implementation="org.jetbrains.kotlin.idea.scripting.gradle.importing.KotlinDslScriptModelContributor"/>
</extensions>
<extensions defaultExtensionNs="com.intellij">
<projectTaskRunner implementation="org.jetbrains.kotlin.idea.gradle.execution.KotlinMPPGradleProjectTaskRunner" order="first, before gradle"/>
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.configuration.KotlinSourceSetDataService"/>
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleProjectSettingsDataService"/>
<externalSystemTaskNotificationListener implementation="org.jetbrains.kotlin.idea.scripting.gradle.importing.KotlinDslScriptModelsUpdater"/>
<registryKey key="kotlin.mpp.tests.force.gradle"
description="Run multi-platform tests with Gradle runner even if the platform runner is used by default.
This setting currently affects only HMPP projects. You may need to delete existing test configurations for the change to take place."
defaultValue="true"
restartRequired="false"/>
<projectService serviceImplementation="org.jetbrains.kotlin.idea.scripting.gradle.GradleScriptInputsWatcher"/>
</extensions>
<actions>
<action id="Kotlin.Gradle.ShowDslLogs" class="org.jetbrains.kotlin.idea.actions.ShowKotlinGradleDslLogs"
text="Show Kotlin Gradle DSL Logs" description="Show Kotlin Gradle DSL logs">
</action>
</actions>
</idea-plugin>