From 5b8208c75159c214a721222d4646728b2d7dedc7 Mon Sep 17 00:00:00 2001 From: Alexey Sedunov Date: Mon, 24 Sep 2018 20:37:32 +0300 Subject: [PATCH] MPP: Fix import failure in the case unresolved dependency is found Instead report unresolved dependencies in Gradle build results #KT-27029 Fixed --- .../NewMultiplatformProjectImportingTest.kt | 66 ++++++++++++++++++- .../kotlin/gradle/projectStructureDSL.kt | 34 ++++++---- idea/kotlin-gradle-tooling/build.gradle.kts | 1 + .../build.gradle.kts.173 | 25 +++++++ .../build.gradle.kts.181 | 25 +++++++ .../build.gradle.kts.as31 | 25 +++++++ .../build.gradle.kts.as32 | 25 +++++++ .../src/KotlinGradleModelBuilder.kt | 2 +- .../src/KotlinMPPGradleModelBuilder.kt | 39 +++++++---- .../src/KotlinMPPGradleModelBuilder.kt.173 | 36 ++++++++-- .../src/KotlinMPPGradleModelBuilder.kt.181 | 37 ++++++++--- .../src/KotlinMPPGradleModelBuilder.kt.as31 | 36 ++++++++-- 12 files changed, 302 insertions(+), 49 deletions(-) create mode 100644 idea/kotlin-gradle-tooling/build.gradle.kts.173 create mode 100644 idea/kotlin-gradle-tooling/build.gradle.kts.181 create mode 100644 idea/kotlin-gradle-tooling/build.gradle.kts.as31 create mode 100644 idea/kotlin-gradle-tooling/build.gradle.kts.as32 diff --git a/idea/idea-gradle/tests/org/jetbrains/kotlin/gradle/NewMultiplatformProjectImportingTest.kt b/idea/idea-gradle/tests/org/jetbrains/kotlin/gradle/NewMultiplatformProjectImportingTest.kt index 0aa926e75e8..958f57abc5c 100644 --- a/idea/idea-gradle/tests/org/jetbrains/kotlin/gradle/NewMultiplatformProjectImportingTest.kt +++ b/idea/idea-gradle/tests/org/jetbrains/kotlin/gradle/NewMultiplatformProjectImportingTest.kt @@ -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() { diff --git a/idea/idea-gradle/tests/org/jetbrains/kotlin/gradle/projectStructureDSL.kt b/idea/idea-gradle/tests/org/jetbrains/kotlin/gradle/projectStructureDSL.kt index 60176ff3def..09dd98a7b2f 100644 --- a/idea/idea-gradle/tests/org/jetbrains/kotlin/gradle/projectStructureDSL.kt +++ b/idea/idea-gradle/tests/org/jetbrains/kotlin/gradle/projectStructureDSL.kt @@ -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) } \ No newline at end of file diff --git a/idea/kotlin-gradle-tooling/build.gradle.kts b/idea/kotlin-gradle-tooling/build.gradle.kts index 9ccb34f80a6..cf021f020c7 100644 --- a/idea/kotlin-gradle-tooling/build.gradle.kts +++ b/idea/kotlin-gradle-tooling/build.gradle.kts @@ -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 { diff --git a/idea/kotlin-gradle-tooling/build.gradle.kts.173 b/idea/kotlin-gradle-tooling/build.gradle.kts.173 new file mode 100644 index 00000000000..1b609295537 --- /dev/null +++ b/idea/kotlin-gradle-tooling/build.gradle.kts.173 @@ -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() diff --git a/idea/kotlin-gradle-tooling/build.gradle.kts.181 b/idea/kotlin-gradle-tooling/build.gradle.kts.181 new file mode 100644 index 00000000000..1b609295537 --- /dev/null +++ b/idea/kotlin-gradle-tooling/build.gradle.kts.181 @@ -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() diff --git a/idea/kotlin-gradle-tooling/build.gradle.kts.as31 b/idea/kotlin-gradle-tooling/build.gradle.kts.as31 new file mode 100644 index 00000000000..1b609295537 --- /dev/null +++ b/idea/kotlin-gradle-tooling/build.gradle.kts.as31 @@ -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() diff --git a/idea/kotlin-gradle-tooling/build.gradle.kts.as32 b/idea/kotlin-gradle-tooling/build.gradle.kts.as32 new file mode 100644 index 00000000000..1b609295537 --- /dev/null +++ b/idea/kotlin-gradle-tooling/build.gradle.kts.as32 @@ -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() diff --git a/idea/kotlin-gradle-tooling/src/KotlinGradleModelBuilder.kt b/idea/kotlin-gradle-tooling/src/KotlinGradleModelBuilder.kt index d71e80e4562..4c5d3c9c002 100644 --- a/idea/kotlin-gradle-tooling/src/KotlinGradleModelBuilder.kt +++ b/idea/kotlin-gradle-tooling/src/KotlinGradleModelBuilder.kt @@ -103,7 +103,7 @@ class KotlinGradleModelBuilder : AbstractKotlinGradleModelBuilder() { return try { javaClass.getDeclaredMethod(methodName).invoke(this) as List } - catch (e : NoSuchMethodException) { + catch (e : Exception) { // No argument accessor method is available emptyList() } diff --git a/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModelBuilder.kt b/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModelBuilder.kt index dfedc0bfa36..7fb5eb2fa6a 100644 --- a/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModelBuilder.kt +++ b/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModelBuilder.kt @@ -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) { + 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 + } 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 ?: return null - @Suppress("UNCHECKED_CAST") - val defaultArguments = getDefaultArguments(compileKotlinTask) as? List ?: 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) + } } \ No newline at end of file diff --git a/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModelBuilder.kt.173 b/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModelBuilder.kt.173 index 138444b648f..8ea271d97b8 100644 --- a/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModelBuilder.kt.173 +++ b/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModelBuilder.kt.173 @@ -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) { + 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 + } 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 ?: return null - @Suppress("UNCHECKED_CAST") - val defaultArguments = getDefaultArguments(compileKotlinTask) as? List ?: 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) + } } \ No newline at end of file diff --git a/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModelBuilder.kt.181 b/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModelBuilder.kt.181 index 2fb80934c6a..da8ea09d000 100644 --- a/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModelBuilder.kt.181 +++ b/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModelBuilder.kt.181 @@ -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) { + 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 + } 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 ?: return null - @Suppress("UNCHECKED_CAST") - val defaultArguments = getDefaultArguments(compileKotlinTask) as? List ?: 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) + } } \ No newline at end of file diff --git a/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModelBuilder.kt.as31 b/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModelBuilder.kt.as31 index 138444b648f..8ea271d97b8 100644 --- a/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModelBuilder.kt.as31 +++ b/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModelBuilder.kt.as31 @@ -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) { + 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 + } 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 ?: return null - @Suppress("UNCHECKED_CAST") - val defaultArguments = getDefaultArguments(compileKotlinTask) as? List ?: 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) + } } \ No newline at end of file