From 52315106e859959f33f925a2ad84a2533fc32e61 Mon Sep 17 00:00:00 2001 From: Andrey Uskov Date: Mon, 6 May 2019 18:34:34 +0300 Subject: [PATCH] Create source sets for generated by kapt sources during import #KT-30739 Fixed --- .../kotlin/gradle/KaptImportingTest.kt | 85 +++++++++++++++++++ .../kotlin/gradle/KaptImportingTest.kt.as33 | 0 .../kotlin/gradle/KaptImportingTest.kt.as34 | 0 .../modulePerSourceSet/build.gradle | 20 +++++ .../modulePerSourceSetDisabled/build.gradle | 20 +++++ .../kapt/idea/KaptProjectResolverExtension.kt | 26 ++++-- .../idea/KaptProjectResolverExtension.kt.as33 | 26 ++++-- .../idea/KaptProjectResolverExtension.kt.as34 | 26 ++++-- 8 files changed, 176 insertions(+), 27 deletions(-) create mode 100644 idea/idea-gradle/tests/org/jetbrains/kotlin/gradle/KaptImportingTest.kt create mode 100644 idea/idea-gradle/tests/org/jetbrains/kotlin/gradle/KaptImportingTest.kt.as33 create mode 100644 idea/idea-gradle/tests/org/jetbrains/kotlin/gradle/KaptImportingTest.kt.as34 create mode 100644 idea/testData/gradle/kaptImportingTest/modulePerSourceSet/build.gradle create mode 100644 idea/testData/gradle/kaptImportingTest/modulePerSourceSetDisabled/build.gradle diff --git a/idea/idea-gradle/tests/org/jetbrains/kotlin/gradle/KaptImportingTest.kt b/idea/idea-gradle/tests/org/jetbrains/kotlin/gradle/KaptImportingTest.kt new file mode 100644 index 00000000000..7dd1b4c4179 --- /dev/null +++ b/idea/idea-gradle/tests/org/jetbrains/kotlin/gradle/KaptImportingTest.kt @@ -0,0 +1,85 @@ +/* + * 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.gradle + +import com.intellij.openapi.roots.DependencyScope +import org.jetbrains.jps.model.java.JavaResourceRootType +import org.jetbrains.jps.model.java.JavaSourceRootType +import org.jetbrains.kotlin.idea.codeInsight.gradle.MultiplePluginVersionGradleImportingTestCase +import org.junit.Test + +class KaptImportingTest : MultiplePluginVersionGradleImportingTestCase() { + + override fun isApplicableTest(): Boolean { + return !gradleVersion.startsWith("3") + } + + fun importProject(modulePerSourceSet: Boolean) { + currentExternalProjectSettings.isResolveModulePerSourceSet = modulePerSourceSet + val isCreateEmptyContentRootDirectories = currentExternalProjectSettings.isCreateEmptyContentRootDirectories + currentExternalProjectSettings.isCreateEmptyContentRootDirectories = true + try { + super.importProject() + } finally { + currentExternalProjectSettings.isCreateEmptyContentRootDirectories = isCreateEmptyContentRootDirectories + } + } + + @Test + fun testModulePerSourceSet() { + configureByFiles() + importProject(true) + + checkProjectStructure(myProject, projectPath, true, true, true) { + module("project") + module("project_main") { + sourceFolder("build/generated/source/kapt/main", JavaSourceRootType.SOURCE) + sourceFolder("build/generated/source/kaptKotlin/main", JavaSourceRootType.SOURCE) + sourceFolder("src/main/java", JavaSourceRootType.SOURCE) + sourceFolder("src/main/kotlin", JavaSourceRootType.SOURCE) + sourceFolder("src/main/resources", JavaResourceRootType.RESOURCE) + libraryDependency("Gradle: kaptGeneratedClasses", DependencyScope.COMPILE) + } + module("project_test") { + sourceFolder("build/generated/source/kapt/test", JavaSourceRootType.TEST_SOURCE) + sourceFolder("build/generated/source/kaptKotlin/test", JavaSourceRootType.TEST_SOURCE) + sourceFolder("src/test/java", JavaSourceRootType.TEST_SOURCE) + sourceFolder("src/test/kotlin", JavaSourceRootType.TEST_SOURCE) + sourceFolder("src/test/resources", JavaResourceRootType.TEST_RESOURCE) + moduleDependency("project_main", DependencyScope.COMPILE) + libraryDependency("Gradle: kaptGeneratedClasses", DependencyScope.COMPILE) + } + } + } + + @Test + fun testModulePerSourceSetDisabled() { + configureByFiles() + importProject(false) + + checkProjectStructure(myProject, projectPath, true, true, true) { + module("project") { + sourceFolder("build/generated/source/kapt/main", JavaSourceRootType.SOURCE) + sourceFolder("build/generated/source/kaptKotlin/main", JavaSourceRootType.SOURCE) + sourceFolder("src/main/java", JavaSourceRootType.SOURCE) + sourceFolder("src/main/kotlin", JavaSourceRootType.SOURCE) + sourceFolder("src/main/resources", JavaResourceRootType.RESOURCE) + sourceFolder("build/generated/source/kapt/test", JavaSourceRootType.TEST_SOURCE) + sourceFolder("build/generated/source/kaptKotlin/test", JavaSourceRootType.TEST_SOURCE) + sourceFolder("src/test/java", JavaSourceRootType.TEST_SOURCE) + sourceFolder("src/test/kotlin", JavaSourceRootType.TEST_SOURCE) + sourceFolder("src/test/resources", JavaResourceRootType.TEST_RESOURCE) + libraryDependency("Gradle: kaptGeneratedClasses", DependencyScope.COMPILE) + } + + } + } + + override fun testDataDirName(): String { + return "kaptImportingTest" + } + +} \ No newline at end of file diff --git a/idea/idea-gradle/tests/org/jetbrains/kotlin/gradle/KaptImportingTest.kt.as33 b/idea/idea-gradle/tests/org/jetbrains/kotlin/gradle/KaptImportingTest.kt.as33 new file mode 100644 index 00000000000..e69de29bb2d diff --git a/idea/idea-gradle/tests/org/jetbrains/kotlin/gradle/KaptImportingTest.kt.as34 b/idea/idea-gradle/tests/org/jetbrains/kotlin/gradle/KaptImportingTest.kt.as34 new file mode 100644 index 00000000000..e69de29bb2d diff --git a/idea/testData/gradle/kaptImportingTest/modulePerSourceSet/build.gradle b/idea/testData/gradle/kaptImportingTest/modulePerSourceSet/build.gradle new file mode 100644 index 00000000000..1e5f598222b --- /dev/null +++ b/idea/testData/gradle/kaptImportingTest/modulePerSourceSet/build.gradle @@ -0,0 +1,20 @@ +buildscript { + apply from: "include.gradle" + ext.kotlin_version = gradleKotlinPluginVersion('1.3.10') + repositories { + google() + jcenter() + + } + dependencies { + classpath 'com.android.tools.build:gradle:3.2.0' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +plugins { + id 'java' +} + +apply plugin: 'kotlin' +apply plugin: 'kotlin-kapt' diff --git a/idea/testData/gradle/kaptImportingTest/modulePerSourceSetDisabled/build.gradle b/idea/testData/gradle/kaptImportingTest/modulePerSourceSetDisabled/build.gradle new file mode 100644 index 00000000000..1e5f598222b --- /dev/null +++ b/idea/testData/gradle/kaptImportingTest/modulePerSourceSetDisabled/build.gradle @@ -0,0 +1,20 @@ +buildscript { + apply from: "include.gradle" + ext.kotlin_version = gradleKotlinPluginVersion('1.3.10') + repositories { + google() + jcenter() + + } + dependencies { + classpath 'com.android.tools.build:gradle:3.2.0' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +plugins { + id 'java' +} + +apply plugin: 'kotlin' +apply plugin: 'kotlin-kapt' diff --git a/plugins/kapt3/kapt3-idea/src/org/jetbrains/kotlin/kapt/idea/KaptProjectResolverExtension.kt b/plugins/kapt3/kapt3-idea/src/org/jetbrains/kotlin/kapt/idea/KaptProjectResolverExtension.kt index a2c1ecd67f5..43ee32348cf 100644 --- a/plugins/kapt3/kapt3-idea/src/org/jetbrains/kotlin/kapt/idea/KaptProjectResolverExtension.kt +++ b/plugins/kapt3/kapt3-idea/src/org/jetbrains/kotlin/kapt/idea/KaptProjectResolverExtension.kt @@ -79,23 +79,31 @@ class KaptProjectResolverExtension : AbstractProjectResolverExtension() { if (kaptModel != null && kaptModel.isEnabled) { for (sourceSet in kaptModel.sourceSets) { - val sourceSetDataNode = ideModule.findGradleSourceSet(sourceSet.sourceSetName) ?: continue + val parentDataNode = ideModule.findParentForSourceSetDataNode(sourceSet.sourceSetName) ?: continue fun addSourceSet(path: String, type: ExternalSystemSourceType) { val contentRootData = ContentRootData(GRADLE_SYSTEM_ID, path) contentRootData.storePath(type, path) - sourceSetDataNode.createChild(ProjectKeys.CONTENT_ROOT, contentRootData) + parentDataNode.createChild(ProjectKeys.CONTENT_ROOT, contentRootData) } - val sourceType = if (sourceSet.isTest) ExternalSystemSourceType.TEST_GENERATED else ExternalSystemSourceType.SOURCE_GENERATED + val sourceType = + if (sourceSet.isTest) ExternalSystemSourceType.TEST_GENERATED else ExternalSystemSourceType.SOURCE_GENERATED sourceSet.generatedSourcesDirFile?.let { addSourceSet(it.absolutePath, sourceType) } sourceSet.generatedKotlinSourcesDirFile?.let { addSourceSet(it.absolutePath, sourceType) } sourceSet.generatedClassesDirFile?.let { generatedClassesDir -> val libraryData = LibraryData(GRADLE_SYSTEM_ID, "kaptGeneratedClasses") - libraryData.addPath(LibraryPathType.BINARY, generatedClassesDir.absolutePath) - val libraryDependencyData = LibraryDependencyData(sourceSetDataNode.data, libraryData, LibraryLevel.MODULE) - sourceSetDataNode.createChild(ProjectKeys.LIBRARY_DEPENDENCY, libraryDependencyData) + val existingNode = + parentDataNode.children.map { (it.data as? LibraryDependencyData)?.target } + .firstOrNull { it?.externalName == libraryData.externalName } + if (existingNode != null) { + existingNode.addPath(LibraryPathType.BINARY, generatedClassesDir.absolutePath) + } else { + libraryData.addPath(LibraryPathType.BINARY, generatedClassesDir.absolutePath) + val libraryDependencyData = LibraryDependencyData(parentDataNode.data, libraryData, LibraryLevel.MODULE) + parentDataNode.createChild(ProjectKeys.LIBRARY_DEPENDENCY, libraryDependencyData) + } } } } @@ -103,17 +111,17 @@ class KaptProjectResolverExtension : AbstractProjectResolverExtension() { super.populateModuleExtraModels(gradleModule, ideModule) } - private fun DataNode.findGradleSourceSet(sourceSetName: String): DataNode? { + private fun DataNode.findParentForSourceSetDataNode(sourceSetName: String): DataNode? { val moduleName = data.id for (child in children) { val gradleSourceSetData = child.data as? GradleSourceSetData ?: continue if (gradleSourceSetData.id == "$moduleName:$sourceSetName") { @Suppress("UNCHECKED_CAST") - return child as DataNode? + return child as? DataNode } } - return null + return this } } diff --git a/plugins/kapt3/kapt3-idea/src/org/jetbrains/kotlin/kapt/idea/KaptProjectResolverExtension.kt.as33 b/plugins/kapt3/kapt3-idea/src/org/jetbrains/kotlin/kapt/idea/KaptProjectResolverExtension.kt.as33 index a2c1ecd67f5..43ee32348cf 100644 --- a/plugins/kapt3/kapt3-idea/src/org/jetbrains/kotlin/kapt/idea/KaptProjectResolverExtension.kt.as33 +++ b/plugins/kapt3/kapt3-idea/src/org/jetbrains/kotlin/kapt/idea/KaptProjectResolverExtension.kt.as33 @@ -79,23 +79,31 @@ class KaptProjectResolverExtension : AbstractProjectResolverExtension() { if (kaptModel != null && kaptModel.isEnabled) { for (sourceSet in kaptModel.sourceSets) { - val sourceSetDataNode = ideModule.findGradleSourceSet(sourceSet.sourceSetName) ?: continue + val parentDataNode = ideModule.findParentForSourceSetDataNode(sourceSet.sourceSetName) ?: continue fun addSourceSet(path: String, type: ExternalSystemSourceType) { val contentRootData = ContentRootData(GRADLE_SYSTEM_ID, path) contentRootData.storePath(type, path) - sourceSetDataNode.createChild(ProjectKeys.CONTENT_ROOT, contentRootData) + parentDataNode.createChild(ProjectKeys.CONTENT_ROOT, contentRootData) } - val sourceType = if (sourceSet.isTest) ExternalSystemSourceType.TEST_GENERATED else ExternalSystemSourceType.SOURCE_GENERATED + val sourceType = + if (sourceSet.isTest) ExternalSystemSourceType.TEST_GENERATED else ExternalSystemSourceType.SOURCE_GENERATED sourceSet.generatedSourcesDirFile?.let { addSourceSet(it.absolutePath, sourceType) } sourceSet.generatedKotlinSourcesDirFile?.let { addSourceSet(it.absolutePath, sourceType) } sourceSet.generatedClassesDirFile?.let { generatedClassesDir -> val libraryData = LibraryData(GRADLE_SYSTEM_ID, "kaptGeneratedClasses") - libraryData.addPath(LibraryPathType.BINARY, generatedClassesDir.absolutePath) - val libraryDependencyData = LibraryDependencyData(sourceSetDataNode.data, libraryData, LibraryLevel.MODULE) - sourceSetDataNode.createChild(ProjectKeys.LIBRARY_DEPENDENCY, libraryDependencyData) + val existingNode = + parentDataNode.children.map { (it.data as? LibraryDependencyData)?.target } + .firstOrNull { it?.externalName == libraryData.externalName } + if (existingNode != null) { + existingNode.addPath(LibraryPathType.BINARY, generatedClassesDir.absolutePath) + } else { + libraryData.addPath(LibraryPathType.BINARY, generatedClassesDir.absolutePath) + val libraryDependencyData = LibraryDependencyData(parentDataNode.data, libraryData, LibraryLevel.MODULE) + parentDataNode.createChild(ProjectKeys.LIBRARY_DEPENDENCY, libraryDependencyData) + } } } } @@ -103,17 +111,17 @@ class KaptProjectResolverExtension : AbstractProjectResolverExtension() { super.populateModuleExtraModels(gradleModule, ideModule) } - private fun DataNode.findGradleSourceSet(sourceSetName: String): DataNode? { + private fun DataNode.findParentForSourceSetDataNode(sourceSetName: String): DataNode? { val moduleName = data.id for (child in children) { val gradleSourceSetData = child.data as? GradleSourceSetData ?: continue if (gradleSourceSetData.id == "$moduleName:$sourceSetName") { @Suppress("UNCHECKED_CAST") - return child as DataNode? + return child as? DataNode } } - return null + return this } } diff --git a/plugins/kapt3/kapt3-idea/src/org/jetbrains/kotlin/kapt/idea/KaptProjectResolverExtension.kt.as34 b/plugins/kapt3/kapt3-idea/src/org/jetbrains/kotlin/kapt/idea/KaptProjectResolverExtension.kt.as34 index a2c1ecd67f5..43ee32348cf 100644 --- a/plugins/kapt3/kapt3-idea/src/org/jetbrains/kotlin/kapt/idea/KaptProjectResolverExtension.kt.as34 +++ b/plugins/kapt3/kapt3-idea/src/org/jetbrains/kotlin/kapt/idea/KaptProjectResolverExtension.kt.as34 @@ -79,23 +79,31 @@ class KaptProjectResolverExtension : AbstractProjectResolverExtension() { if (kaptModel != null && kaptModel.isEnabled) { for (sourceSet in kaptModel.sourceSets) { - val sourceSetDataNode = ideModule.findGradleSourceSet(sourceSet.sourceSetName) ?: continue + val parentDataNode = ideModule.findParentForSourceSetDataNode(sourceSet.sourceSetName) ?: continue fun addSourceSet(path: String, type: ExternalSystemSourceType) { val contentRootData = ContentRootData(GRADLE_SYSTEM_ID, path) contentRootData.storePath(type, path) - sourceSetDataNode.createChild(ProjectKeys.CONTENT_ROOT, contentRootData) + parentDataNode.createChild(ProjectKeys.CONTENT_ROOT, contentRootData) } - val sourceType = if (sourceSet.isTest) ExternalSystemSourceType.TEST_GENERATED else ExternalSystemSourceType.SOURCE_GENERATED + val sourceType = + if (sourceSet.isTest) ExternalSystemSourceType.TEST_GENERATED else ExternalSystemSourceType.SOURCE_GENERATED sourceSet.generatedSourcesDirFile?.let { addSourceSet(it.absolutePath, sourceType) } sourceSet.generatedKotlinSourcesDirFile?.let { addSourceSet(it.absolutePath, sourceType) } sourceSet.generatedClassesDirFile?.let { generatedClassesDir -> val libraryData = LibraryData(GRADLE_SYSTEM_ID, "kaptGeneratedClasses") - libraryData.addPath(LibraryPathType.BINARY, generatedClassesDir.absolutePath) - val libraryDependencyData = LibraryDependencyData(sourceSetDataNode.data, libraryData, LibraryLevel.MODULE) - sourceSetDataNode.createChild(ProjectKeys.LIBRARY_DEPENDENCY, libraryDependencyData) + val existingNode = + parentDataNode.children.map { (it.data as? LibraryDependencyData)?.target } + .firstOrNull { it?.externalName == libraryData.externalName } + if (existingNode != null) { + existingNode.addPath(LibraryPathType.BINARY, generatedClassesDir.absolutePath) + } else { + libraryData.addPath(LibraryPathType.BINARY, generatedClassesDir.absolutePath) + val libraryDependencyData = LibraryDependencyData(parentDataNode.data, libraryData, LibraryLevel.MODULE) + parentDataNode.createChild(ProjectKeys.LIBRARY_DEPENDENCY, libraryDependencyData) + } } } } @@ -103,17 +111,17 @@ class KaptProjectResolverExtension : AbstractProjectResolverExtension() { super.populateModuleExtraModels(gradleModule, ideModule) } - private fun DataNode.findGradleSourceSet(sourceSetName: String): DataNode? { + private fun DataNode.findParentForSourceSetDataNode(sourceSetName: String): DataNode? { val moduleName = data.id for (child in children) { val gradleSourceSetData = child.data as? GradleSourceSetData ?: continue if (gradleSourceSetData.id == "$moduleName:$sourceSetName") { @Suppress("UNCHECKED_CAST") - return child as DataNode? + return child as? DataNode } } - return null + return this } }