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,