MPP: Fix import failure in the case unresolved dependency is found

Instead report unresolved dependencies in Gradle build results

 #KT-27029 Fixed
This commit is contained in:
Alexey Sedunov
2018-09-24 20:37:32 +03:00
parent 99f63f2ebd
commit 5b8208c751
12 changed files with 302 additions and 49 deletions
@@ -338,12 +338,76 @@ class NewMultiplatformProjectImportingTest : GradleImportingTestCase() {
}
}
@Test
fun testUnresolvedDependency() {
createProjectSubFile(
"build.gradle",
"""
buildscript {
repositories {
mavenLocal()
jcenter()
maven { url 'https://dl.bintray.com/kotlin/kotlin-dev' }
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
}
}
allprojects {
repositories {
mavenLocal()
jcenter()
maven { url 'https://dl.bintray.com/kotlin/kotlin-dev' }
}
}
apply plugin: 'kotlin-multiplatform'
kotlin {
sourceSets {
jvmMain {
dependencies {
implementation 'my.lib:unresolved'
}
}
}
targets {
fromPreset(presets.jvmWithJava, 'jvm')
}
}
""".trimIndent()
)
importProject()
checkProjectStructure(
exhaustiveSourceSourceRootList = false,
exhaustiveDependencyList = false
) {
module("project")
module("project_commonMain")
module("project_commonTest")
module("project_jvmMain")
module("project_jvmTest")
module("project_main")
module("project_test")
}
}
private fun checkProjectStructure(
exhaustiveModuleList: Boolean = true,
exhaustiveSourceSourceRootList: Boolean = true,
exhaustiveDependencyList: Boolean = true,
body: ProjectInfo.() -> Unit = {}
) {
checkProjectStructure(myProject, projectPath, exhaustiveModuleList, exhaustiveSourceSourceRootList, body)
checkProjectStructure(
myProject,
projectPath,
exhaustiveModuleList,
exhaustiveSourceSourceRootList,
exhaustiveDependencyList,
body)
}
override fun importProject() {
@@ -37,7 +37,8 @@ class ProjectInfo(
project: Project,
internal val projectPath: String,
internal val exhaustiveModuleList: Boolean,
internal val exhaustiveSourceSourceRootList: Boolean
internal val exhaustiveSourceSourceRootList: Boolean,
internal val exhaustiveDependencyList: Boolean
) {
internal val messageCollector = MessageCollector()
private val moduleManager = ModuleManager.getInstance(project)
@@ -202,16 +203,18 @@ class ModuleInfo(
fun run(body: ModuleInfo.() -> Unit = {}) {
body()
val actualDependencyNames = rootModel
.orderEntries
.filter { it is ModuleOrderEntry || it is LibraryOrderEntry }
.map { it.presentableName }
.sorted()
val expectedDependencyNames = expectedDependencyNames.sorted()
if (actualDependencyNames != expectedDependencyNames) {
projectInfo.messageCollector.report(
"Module '${module.name}': Expected dependency list $expectedDependencyNames doesn't match the actual one: $actualDependencyNames"
)
if (projectInfo.exhaustiveDependencyList) {
val actualDependencyNames = rootModel
.orderEntries
.filter { it is ModuleOrderEntry || it is LibraryOrderEntry }
.map { it.presentableName }
.sorted()
val expectedDependencyNames = expectedDependencyNames.sorted()
if (actualDependencyNames != expectedDependencyNames) {
projectInfo.messageCollector.report(
"Module '${module.name}': Expected dependency list $expectedDependencyNames doesn't match the actual one: $actualDependencyNames"
)
}
}
if (projectInfo.exhaustiveSourceSourceRootList) {
@@ -244,7 +247,14 @@ fun checkProjectStructure(
projectPath: String,
exhaustiveModuleList: Boolean,
exhaustiveSourceSourceRootList: Boolean,
exhaustiveDependencyList: Boolean,
body: ProjectInfo.() -> Unit = {}
) {
ProjectInfo(project, projectPath, exhaustiveModuleList, exhaustiveSourceSourceRootList).run(body)
ProjectInfo(
project,
projectPath,
exhaustiveModuleList,
exhaustiveSourceSourceRootList,
exhaustiveDependencyList
).run(body)
}
@@ -12,6 +12,7 @@ dependencies {
compile(project(":kotlin-stdlib"))
compile(project(":compiler:cli-common"))
compile(intellijPluginDep("gradle"))
compileOnly(intellijDep()) { includeJars("slf4j-api-1.7.25") }
}
sourceSets {
@@ -0,0 +1,25 @@
description = "Kotlin Gradle Tooling support"
plugins {
kotlin("jvm")
id("jps-compatible")
}
jvmTarget = "1.6"
dependencies {
compile(project(":kotlin-stdlib"))
compile(project(":compiler:cli-common"))
compile(intellijPluginDep("gradle"))
compileOnly(intellijDep()) { includeJars("slf4j-api-1.7.10") }
}
sourceSets {
"main" { projectDefault() }
"test" {}
}
runtimeJar()
ideaPlugin()
@@ -0,0 +1,25 @@
description = "Kotlin Gradle Tooling support"
plugins {
kotlin("jvm")
id("jps-compatible")
}
jvmTarget = "1.6"
dependencies {
compile(project(":kotlin-stdlib"))
compile(project(":compiler:cli-common"))
compile(intellijPluginDep("gradle"))
compileOnly(intellijDep()) { includeJars("slf4j-api-1.7.10") }
}
sourceSets {
"main" { projectDefault() }
"test" {}
}
runtimeJar()
ideaPlugin()
@@ -0,0 +1,25 @@
description = "Kotlin Gradle Tooling support"
plugins {
kotlin("jvm")
id("jps-compatible")
}
jvmTarget = "1.6"
dependencies {
compile(project(":kotlin-stdlib"))
compile(project(":compiler:cli-common"))
compile(intellijPluginDep("gradle"))
compileOnly(intellijDep()) { includeJars("slf4j-api-1.7.10") }
}
sourceSets {
"main" { projectDefault() }
"test" {}
}
runtimeJar()
ideaPlugin()
@@ -0,0 +1,25 @@
description = "Kotlin Gradle Tooling support"
plugins {
kotlin("jvm")
id("jps-compatible")
}
jvmTarget = "1.6"
dependencies {
compile(project(":kotlin-stdlib"))
compile(project(":compiler:cli-common"))
compile(intellijPluginDep("gradle"))
compileOnly(intellijDep()) { includeJars("slf4j-api-1.7.10") }
}
sourceSets {
"main" { projectDefault() }
"test" {}
}
runtimeJar()
ideaPlugin()
@@ -103,7 +103,7 @@ class KotlinGradleModelBuilder : AbstractKotlinGradleModelBuilder() {
return try {
javaClass.getDeclaredMethod(methodName).invoke(this) as List<String>
}
catch (e : NoSuchMethodException) {
catch (e : Exception) {
// No argument accessor method is available
emptyList()
}
@@ -13,15 +13,16 @@ import org.gradle.api.artifacts.Dependency
import org.gradle.api.artifacts.component.ProjectComponentIdentifier
import org.gradle.api.file.FileCollection
import org.gradle.api.file.SourceDirectorySet
import org.gradle.api.logging.Logging
import org.gradle.api.provider.Property
import org.jetbrains.plugins.gradle.model.*
import org.jetbrains.plugins.gradle.tooling.ErrorMessageBuilder
import org.jetbrains.plugins.gradle.tooling.ModelBuilderService
import org.jetbrains.plugins.gradle.tooling.util.DependencyResolver
import org.jetbrains.plugins.gradle.tooling.util.resolve.DependencyResolverImpl
import org.jetbrains.plugins.gradle.tooling.util.SourceSetCachedFinder
import org.jetbrains.plugins.gradle.tooling.util.resolve.DependencyResolverImpl
import java.io.File
import java.lang.Exception
import java.lang.reflect.Method
class KotlinMPPGradleModelBuilder : ModelBuilderService {
override fun getErrorMessageBuilder(project: Project, e: Exception): ErrorMessageBuilder {
@@ -47,9 +48,20 @@ class KotlinMPPGradleModelBuilder : ModelBuilderService {
val targets = buildTargets(sourceSetMap, dependencyResolver, project) ?: return null
computeSourceSetsDeferredInfo(sourceSets, targets)
val coroutinesState = getCoroutinesState(project)
reportUnresolvedDependencies(targets)
return KotlinMPPGradleModelImpl(sourceSetMap, targets, ExtraFeaturesImpl(coroutinesState))
}
private fun reportUnresolvedDependencies(targets: Collection<KotlinTarget>) {
targets
.asSequence()
.flatMap { it.compilations.asSequence() }
.flatMap { it.dependencies.asSequence() }
.mapNotNull { (it as? UnresolvedExternalDependency)?.failureMessage }
.toSet()
.forEach { logger.warn(it) }
}
private fun Project.getChildProjectByPath(path: String): Project? {
var project = this
for (name in path.split(":").asSequence().drop(1)) {
@@ -286,19 +298,20 @@ class KotlinMPPGradleModelBuilder : ModelBuilderService {
}
}
@Suppress("UNCHECKED_CAST")
private fun safelyGetArguments(compileKotlinTask: Task, accessor: Method?) = try {
accessor?.invoke(compileKotlinTask) as? List<String>
} catch (e: Exception) {
logger.info(e.message, e)
null
} ?: emptyList()
private fun buildCompilationArguments(compileKotlinTask: Task): KotlinCompilationArguments? {
val compileTaskClass = compileKotlinTask.javaClass
val getCurrentArguments = compileTaskClass.getMethodOrNull("getSerializedCompilerArguments")
val getDefaultArguments = compileTaskClass.getMethodOrNull("getDefaultSerializedCompilerArguments")
//TODO: Hack for KotlinNativeCompile
if (getCurrentArguments == null || getDefaultArguments == null) {
return KotlinCompilationArgumentsImpl(emptyList(), emptyList())
}
@Suppress("UNCHECKED_CAST")
val currentArguments = getCurrentArguments(compileKotlinTask) as? List<String> ?: return null
@Suppress("UNCHECKED_CAST")
val defaultArguments = getDefaultArguments(compileKotlinTask) as? List<String> ?: return null
val currentArguments = safelyGetArguments(compileKotlinTask, getCurrentArguments)
val defaultArguments = safelyGetArguments(compileKotlinTask, getDefaultArguments)
return KotlinCompilationArgumentsImpl(defaultArguments, currentArguments)
}
@@ -369,4 +382,8 @@ class KotlinMPPGradleModelBuilder : ModelBuilderService {
}
}
}
companion object {
private val logger = Logging.getLogger(KotlinMPPGradleModelBuilder::class.java)
}
}
@@ -13,6 +13,7 @@ import org.gradle.api.artifacts.Dependency
import org.gradle.api.artifacts.component.ProjectComponentIdentifier
import org.gradle.api.file.FileCollection
import org.gradle.api.file.SourceDirectorySet
import org.gradle.api.logging.Logging
import org.jetbrains.plugins.gradle.model.*
import org.jetbrains.plugins.gradle.tooling.ErrorMessageBuilder
import org.jetbrains.plugins.gradle.tooling.ModelBuilderService
@@ -20,7 +21,7 @@ import org.jetbrains.plugins.gradle.tooling.util.DependencyResolver
import org.jetbrains.plugins.gradle.tooling.util.DependencyResolverImpl
import org.jetbrains.plugins.gradle.tooling.util.SourceSetCachedFinder
import java.io.File
import java.lang.Exception
import java.lang.reflect.Method
class KotlinMPPGradleModelBuilder : ModelBuilderService {
override fun getErrorMessageBuilder(project: Project, e: Exception): ErrorMessageBuilder {
@@ -46,9 +47,20 @@ class KotlinMPPGradleModelBuilder : ModelBuilderService {
val targets = buildTargets(sourceSetMap, dependencyResolver, project) ?: return null
computeSourceSetsDeferredInfo(sourceSets, targets)
val coroutinesState = getCoroutinesState(project)
reportUnresolvedDependencies(targets)
return KotlinMPPGradleModelImpl(sourceSetMap, targets, ExtraFeaturesImpl(coroutinesState))
}
private fun reportUnresolvedDependencies(targets: Collection<KotlinTarget>) {
targets
.asSequence()
.flatMap { it.compilations.asSequence() }
.flatMap { it.dependencies.asSequence() }
.mapNotNull { (it as? UnresolvedExternalDependency)?.failureMessage }
.toSet()
.forEach { logger.warn(it) }
}
private fun Project.getChildProjectByPath(path: String): Project? {
var project = this
for (name in path.split(":").asSequence().drop(1)) {
@@ -285,14 +297,20 @@ class KotlinMPPGradleModelBuilder : ModelBuilderService {
}
}
@Suppress("UNCHECKED_CAST")
private fun safelyGetArguments(compileKotlinTask: Task, accessor: Method?) = try {
accessor?.invoke(compileKotlinTask) as? List<String>
} catch (e: Exception) {
logger.info(e.message, e)
null
} ?: emptyList()
private fun buildCompilationArguments(compileKotlinTask: Task): KotlinCompilationArguments? {
val compileTaskClass = compileKotlinTask.javaClass
val getCurrentArguments = compileTaskClass.getMethodOrNull("getSerializedCompilerArguments") ?: return null
val getDefaultArguments = compileTaskClass.getMethodOrNull("getDefaultSerializedCompilerArguments") ?: return null
@Suppress("UNCHECKED_CAST")
val currentArguments = getCurrentArguments(compileKotlinTask) as? List<String> ?: return null
@Suppress("UNCHECKED_CAST")
val defaultArguments = getDefaultArguments(compileKotlinTask) as? List<String> ?: return null
val getCurrentArguments = compileTaskClass.getMethodOrNull("getSerializedCompilerArguments")
val getDefaultArguments = compileTaskClass.getMethodOrNull("getDefaultSerializedCompilerArguments")
val currentArguments = safelyGetArguments(compileKotlinTask, getCurrentArguments)
val defaultArguments = safelyGetArguments(compileKotlinTask, getDefaultArguments)
return KotlinCompilationArgumentsImpl(defaultArguments, currentArguments)
}
@@ -358,4 +376,8 @@ class KotlinMPPGradleModelBuilder : ModelBuilderService {
}
}
}
companion object {
private val logger = Logging.getLogger(KotlinMPPGradleModelBuilder::class.java)
}
}
@@ -13,6 +13,7 @@ import org.gradle.api.artifacts.Dependency
import org.gradle.api.artifacts.component.ProjectComponentIdentifier
import org.gradle.api.file.FileCollection
import org.gradle.api.file.SourceDirectorySet
import org.gradle.api.logging.Logging
import org.gradle.api.provider.Property
import org.jetbrains.plugins.gradle.model.*
import org.jetbrains.plugins.gradle.tooling.ErrorMessageBuilder
@@ -21,7 +22,7 @@ import org.jetbrains.plugins.gradle.tooling.util.DependencyResolver
import org.jetbrains.plugins.gradle.tooling.util.DependencyResolverImpl
import org.jetbrains.plugins.gradle.tooling.util.SourceSetCachedFinder
import java.io.File
import java.lang.Exception
import java.lang.reflect.Method
class KotlinMPPGradleModelBuilder : ModelBuilderService {
override fun getErrorMessageBuilder(project: Project, e: Exception): ErrorMessageBuilder {
@@ -47,9 +48,20 @@ class KotlinMPPGradleModelBuilder : ModelBuilderService {
val targets = buildTargets(sourceSetMap, dependencyResolver, project) ?: return null
computeSourceSetsDeferredInfo(sourceSets, targets)
val coroutinesState = getCoroutinesState(project)
reportUnresolvedDependencies(targets)
return KotlinMPPGradleModelImpl(sourceSetMap, targets, ExtraFeaturesImpl(coroutinesState))
}
private fun reportUnresolvedDependencies(targets: Collection<KotlinTarget>) {
targets
.asSequence()
.flatMap { it.compilations.asSequence() }
.flatMap { it.dependencies.asSequence() }
.mapNotNull { (it as? UnresolvedExternalDependency)?.failureMessage }
.toSet()
.forEach { logger.warn(it) }
}
private fun Project.getChildProjectByPath(path: String): Project? {
var project = this
for (name in path.split(":").asSequence().drop(1)) {
@@ -286,19 +298,20 @@ class KotlinMPPGradleModelBuilder : ModelBuilderService {
}
}
@Suppress("UNCHECKED_CAST")
private fun safelyGetArguments(compileKotlinTask: Task, accessor: Method?) = try {
accessor?.invoke(compileKotlinTask) as? List<String>
} catch (e: Exception) {
logger.info(e.message, e)
null
} ?: emptyList()
private fun buildCompilationArguments(compileKotlinTask: Task): KotlinCompilationArguments? {
val compileTaskClass = compileKotlinTask.javaClass
val getCurrentArguments = compileTaskClass.getMethodOrNull("getSerializedCompilerArguments")
val getDefaultArguments = compileTaskClass.getMethodOrNull("getDefaultSerializedCompilerArguments")
//TODO: Hack for KotlinNativeCompile
if (getCurrentArguments == null || getDefaultArguments == null) {
return KotlinCompilationArgumentsImpl(emptyList(), emptyList())
}
@Suppress("UNCHECKED_CAST")
val currentArguments = getCurrentArguments(compileKotlinTask) as? List<String> ?: return null
@Suppress("UNCHECKED_CAST")
val defaultArguments = getDefaultArguments(compileKotlinTask) as? List<String> ?: return null
val currentArguments = safelyGetArguments(compileKotlinTask, getCurrentArguments)
val defaultArguments = safelyGetArguments(compileKotlinTask, getDefaultArguments)
return KotlinCompilationArgumentsImpl(defaultArguments, currentArguments)
}
@@ -369,4 +382,8 @@ class KotlinMPPGradleModelBuilder : ModelBuilderService {
}
}
}
companion object {
private val logger = Logging.getLogger(KotlinMPPGradleModelBuilder::class.java)
}
}
@@ -13,6 +13,7 @@ import org.gradle.api.artifacts.Dependency
import org.gradle.api.artifacts.component.ProjectComponentIdentifier
import org.gradle.api.file.FileCollection
import org.gradle.api.file.SourceDirectorySet
import org.gradle.api.logging.Logging
import org.jetbrains.plugins.gradle.model.*
import org.jetbrains.plugins.gradle.tooling.ErrorMessageBuilder
import org.jetbrains.plugins.gradle.tooling.ModelBuilderService
@@ -20,7 +21,7 @@ import org.jetbrains.plugins.gradle.tooling.util.DependencyResolver
import org.jetbrains.plugins.gradle.tooling.util.DependencyResolverImpl
import org.jetbrains.plugins.gradle.tooling.util.SourceSetCachedFinder
import java.io.File
import java.lang.Exception
import java.lang.reflect.Method
class KotlinMPPGradleModelBuilder : ModelBuilderService {
override fun getErrorMessageBuilder(project: Project, e: Exception): ErrorMessageBuilder {
@@ -46,9 +47,20 @@ class KotlinMPPGradleModelBuilder : ModelBuilderService {
val targets = buildTargets(sourceSetMap, dependencyResolver, project) ?: return null
computeSourceSetsDeferredInfo(sourceSets, targets)
val coroutinesState = getCoroutinesState(project)
reportUnresolvedDependencies(targets)
return KotlinMPPGradleModelImpl(sourceSetMap, targets, ExtraFeaturesImpl(coroutinesState))
}
private fun reportUnresolvedDependencies(targets: Collection<KotlinTarget>) {
targets
.asSequence()
.flatMap { it.compilations.asSequence() }
.flatMap { it.dependencies.asSequence() }
.mapNotNull { (it as? UnresolvedExternalDependency)?.failureMessage }
.toSet()
.forEach { logger.warn(it) }
}
private fun Project.getChildProjectByPath(path: String): Project? {
var project = this
for (name in path.split(":").asSequence().drop(1)) {
@@ -285,14 +297,20 @@ class KotlinMPPGradleModelBuilder : ModelBuilderService {
}
}
@Suppress("UNCHECKED_CAST")
private fun safelyGetArguments(compileKotlinTask: Task, accessor: Method?) = try {
accessor?.invoke(compileKotlinTask) as? List<String>
} catch (e: Exception) {
logger.info(e.message, e)
null
} ?: emptyList()
private fun buildCompilationArguments(compileKotlinTask: Task): KotlinCompilationArguments? {
val compileTaskClass = compileKotlinTask.javaClass
val getCurrentArguments = compileTaskClass.getMethodOrNull("getSerializedCompilerArguments") ?: return null
val getDefaultArguments = compileTaskClass.getMethodOrNull("getDefaultSerializedCompilerArguments") ?: return null
@Suppress("UNCHECKED_CAST")
val currentArguments = getCurrentArguments(compileKotlinTask) as? List<String> ?: return null
@Suppress("UNCHECKED_CAST")
val defaultArguments = getDefaultArguments(compileKotlinTask) as? List<String> ?: return null
val getCurrentArguments = compileTaskClass.getMethodOrNull("getSerializedCompilerArguments")
val getDefaultArguments = compileTaskClass.getMethodOrNull("getDefaultSerializedCompilerArguments")
val currentArguments = safelyGetArguments(compileKotlinTask, getCurrentArguments)
val defaultArguments = safelyGetArguments(compileKotlinTask, getDefaultArguments)
return KotlinCompilationArgumentsImpl(defaultArguments, currentArguments)
}
@@ -358,4 +376,8 @@ class KotlinMPPGradleModelBuilder : ModelBuilderService {
}
}
}
companion object {
private val logger = Logging.getLogger(KotlinMPPGradleModelBuilder::class.java)
}
}