From 9e99bca32285002640be2a324475349d654a219d Mon Sep 17 00:00:00 2001 From: Yan Zhulanow Date: Thu, 11 Apr 2019 02:43:17 +0300 Subject: [PATCH] Pill: Fix artifact generation --- .../main/kotlin/pill/kotlinPluginArtifact.kt | 157 +++++++++--------- buildSrc/src/main/kotlin/pill/parser.kt | 78 +++++---- buildSrc/src/main/kotlin/pill/plugin.kt | 6 +- 3 files changed, 121 insertions(+), 120 deletions(-) diff --git a/buildSrc/src/main/kotlin/pill/kotlinPluginArtifact.kt b/buildSrc/src/main/kotlin/pill/kotlinPluginArtifact.kt index 7581c97fe5c..5aa5036570d 100644 --- a/buildSrc/src/main/kotlin/pill/kotlinPluginArtifact.kt +++ b/buildSrc/src/main/kotlin/pill/kotlinPluginArtifact.kt @@ -5,11 +5,13 @@ package org.jetbrains.kotlin.pill import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar import org.gradle.api.Project import org.gradle.api.artifacts.Configuration +import org.gradle.api.artifacts.ProjectDependency import org.gradle.api.internal.file.copy.SingleParentCopySpec import org.gradle.api.plugins.JavaPlugin import org.gradle.api.tasks.Copy import org.gradle.jvm.tasks.Jar import org.gradle.kotlin.dsl.extra +import org.jetbrains.kotlin.pill.DependencyInfo.ResolvedDependencyInfo import org.jetbrains.kotlin.pill.ArtifactElement.* import org.jetbrains.kotlin.pill.POrderRoot.* import java.io.File @@ -34,6 +36,10 @@ sealed class ArtifactElement { myChildren += child } + fun add(children: List) { + myChildren += children + } + abstract fun render(context: PathContext): xml fun renderRecursively(context: PathContext): xml { @@ -102,99 +108,37 @@ sealed class ArtifactElement { } } -fun generateKotlinPluginArtifactFile(rootProject: Project): PFile { - val mainIdeaPluginTask = rootProject.tasks.getByName("ideaPlugin") - val gradleArtifactDir = File(rootProject.extra["ideaPluginDir"] as File, "lib") - - val ideaPluginTasks = mainIdeaPluginTask.taskDependencies - .getDependencies(mainIdeaPluginTask) - .filter { it.name == "ideaPlugin" } - .filterIsInstance() - +fun generateKotlinPluginArtifactFile(rootProject: Project, dependencyMappers: List): PFile { val root = Root() - // Copy kotlinc directory + fun Project.getProject(name: String) = findProject(name) ?: error("Cannot find project $name") + + val prepareIdeaPluginProject = rootProject.getProject(":prepare:idea-plugin") + val prepareJpsPluginProject = rootProject.getProject(":kotlin-jps-plugin") + root.add(Directory("kotlinc").apply { val kotlincDirectory = rootProject.extra["distKotlinHomeDir"].toString() add(DirectoryCopy(File(kotlincDirectory))) }) - for (task in ideaPluginTasks) { - val spec = task.rootSpec.children.filterIsInstance().singleOrNull() - ?: error("Copy spec is not unique in ${rootProject.name}. Available specs: ${task.rootSpec.children}") + root.add(Directory("lib").apply { + val librariesConfiguration = prepareIdeaPluginProject.configurations.getByName("libraries") + add(getArtifactElements(librariesConfiguration, dependencyMappers, false)) - val sourcePaths = spec.sourcePaths - for (sourcePath in sourcePaths) { - if (sourcePath is ShadowJar) { - if (sourcePath.project.path == ":prepare:idea-plugin") { - val kotlinPluginJar = Archive(sourcePath.archiveName).also { root.getDirectory("lib").add(it) } + add(Directory("jps").apply { + add(Archive(prepareJpsPluginProject.name).apply { + val embeddedConfiguration = prepareJpsPluginProject.configurations.getByName(EmbeddedComponents.CONFIGURATION_NAME) + add(getArtifactElements(embeddedConfiguration, dependencyMappers, true)) + }) + }) - kotlinPluginJar.add(FileCopy(File(rootProject.projectDir, "resources/kotlinManifest.properties"))) + add(Archive(prepareIdeaPluginProject.name + ".jar").apply { + add(FileCopy(File(rootProject.projectDir, "resources/kotlinManifest.properties"))) - for (jarFile in sourcePath.project.configurations.getByName(EmbeddedComponents.CONFIGURATION_NAME).resolve()) { - kotlinPluginJar.add(ExtractedDirectory(jarFile)) - } - - @Suppress("UNCHECKED_CAST") - for (projectPath in sourcePath.project.extra["projectsToShadow"] as List) { - val jpsModuleName = rootProject.findProject(projectPath)!!.name + ".src" - kotlinPluginJar.add(ModuleOutput(jpsModuleName)) - } - - continue - } - } - - fun fileCopySnapshotAware(file: File): FileCopy { - val SHAPSHOT_JAR_SUFFIX = "-SNAPSHOT.jar" - if (file.name.endsWith(SHAPSHOT_JAR_SUFFIX)) { - return FileCopy(file, file.name.dropLast(SHAPSHOT_JAR_SUFFIX.length).substringBeforeLast("-") + ".jar") - } - - return FileCopy(file) - } - - when (sourcePath) { - is Jar -> { - val targetDir = ("lib/" + task.destinationDir.toRelativeString(gradleArtifactDir)).withoutSlash() - - val archiveForJar = Archive(sourcePath.project.name + ".jar").apply { - if (task.project.plugins.hasPlugin(JavaPlugin::class.java)) { - add(ModuleOutput(sourcePath.project.name + ".src")) - } - root.getDirectory(targetDir).add(this) - } - - val embeddedComponents = sourcePath.project.configurations - .findByName(EmbeddedComponents.CONFIGURATION_NAME)?.resolvedConfiguration - - if (embeddedComponents != null) { - val configuration = CollectedConfiguration(embeddedComponents, Scope.COMPILE) - for (dependencyInfo in listOf(configuration).collectDependencies()) { - val dependency = (dependencyInfo as? DependencyInfo.ResolvedDependencyInfo)?.dependency ?: continue - - if (dependency.isModuleDependency) { - archiveForJar.add(ModuleOutput(dependency.moduleName + ".src")) - } else if (dependency.configuration == "tests-jar" || dependency.configuration == "jpsTest") { - error("Test configurations are not allowed here") - } else { - for (file in dependency.moduleArtifacts.map { it.file }) { - archiveForJar.add(ExtractedDirectory(file)) - } - } - } - } - } - is Configuration -> { - require(sourcePath.name == "sideJars") { "Configurations other than 'sideJars' are not supported" } - for (file in sourcePath.resolve()) { - root.getDirectory("lib").add(fileCopySnapshotAware(file)) - } - } - else -> error("${task.name} Unexpected task type ${task.javaClass.name}") - } - } - } + val embeddedConfiguration = prepareIdeaPluginProject.configurations.getByName(EmbeddedComponents.CONFIGURATION_NAME) + add(getArtifactElements(embeddedConfiguration, dependencyMappers, true)) + }) + }) val artifact = PArtifact("KotlinPlugin", File(rootProject.projectDir, "out/artifacts/Kotlin"), root) return PFile( @@ -203,3 +147,50 @@ fun generateKotlinPluginArtifactFile(rootProject: Project): PFile { ) } +private fun getArtifactElements( + configuration: Configuration, + dependencyMappers: List, + extractDependencies: Boolean +): List { + val resolved = configuration.resolvedConfiguration + val collected = CollectedConfiguration(resolved, Scope.COMPILE) + val dependencies = listOf(collected).collectDependencies() + + val mainRoots = mutableListOf() + val deferredRoots = mutableListOf() + + dependencies.forEach { it.processResolvedDependency(mainRoots, deferredRoots, dependencyMappers) } + + val artifacts = mutableListOf() + + for (dependency in configuration.allDependencies) { + if (dependency !is ProjectDependency) continue + + val project = dependency.dependencyProject + val moduleOutput = ModuleOutput(project.name + ".src") + + if (extractDependencies) { + artifacts += moduleOutput + } else { + artifacts += Archive(project.name + ".jar").apply { + add(moduleOutput) + } + } + + val embeddedConfiguration = project.configurations.findByName(EmbeddedComponents.CONFIGURATION_NAME) ?: continue + artifacts += getArtifactElements(embeddedConfiguration, dependencyMappers, extractDependencies) + } + + for (orderRoot in listOf(mainRoots, deferredRoots).flatten()) { + when (val dependency = orderRoot.dependency) { + is PDependency.Module -> {} // already added above + is PDependency.Library -> artifacts += ProjectLibrary(dependency.name) + is PDependency.ModuleLibrary -> { + val files = dependency.library.classes + artifacts += files.map(if (extractDependencies) ::ExtractedDirectory else ::FileCopy) + } + } + } + + return artifacts +} \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/pill/parser.kt b/buildSrc/src/main/kotlin/pill/parser.kt index 99784ac96fa..c125338cbed 100644 --- a/buildSrc/src/main/kotlin/pill/parser.kt +++ b/buildSrc/src/main/kotlin/pill/parser.kt @@ -376,7 +376,7 @@ private fun ParserContext.parseDependencies(project: Project, forTests: Boolean) return configurations } - nextDependency@ for (dependencyInfo in collectConfigurations().collectDependencies()) { + for (dependencyInfo in collectConfigurations().collectDependencies()) { val scope = dependencyInfo.scope if (dependencyInfo is DependencyInfo.CustomDependencyInfo) { @@ -387,46 +387,54 @@ private fun ParserContext.parseDependencies(project: Project, forTests: Boolean) continue } - val dependency = (dependencyInfo as DependencyInfo.ResolvedDependencyInfo).dependency - - for (mapper in dependencyMappers) { - if (dependency.configuration in mapper.configurations && mapper.predicate(dependency)) { - val mappedDependency = mapper.mapping(dependency) - - if (mappedDependency != null) { - val mainDependency = mappedDependency.main - if (mainDependency != null) { - mainRoots += POrderRoot(mainDependency, scope) - } - - for (deferredDep in mappedDependency.deferred) { - deferredRoots += POrderRoot(deferredDep, scope) - } - } - - continue@nextDependency - } - } - - mainRoots += if (dependency.isModuleDependency && scope != Scope.TEST) { - POrderRoot(PDependency.Module(dependency.moduleName + ".src"), scope) - } else if (dependency.configuration == "tests-jar" || dependency.configuration == "jpsTest") { - POrderRoot( - PDependency.Module(dependency.moduleName + ".test"), - scope, - isProductionOnTestDependency = true - ) - } else { - val classes = dependency.moduleArtifacts.map { it.file } - val library = PLibrary(dependency.moduleName, classes) - POrderRoot(PDependency.ModuleLibrary(library), scope) - } + dependencyInfo.processResolvedDependency(mainRoots, deferredRoots, dependencyMappers) } return removeDuplicates(mainRoots + deferredRoots) } } +fun DependencyInfo.processResolvedDependency( + mainConsumer: MutableList, + deferredConsumer: MutableList, + dependencyMappers: List +) { + val dependency = (this as? DependencyInfo.ResolvedDependencyInfo)?.dependency ?: return + + for (mapper in dependencyMappers) { + if (dependency.configuration in mapper.configurations && mapper.predicate(dependency)) { + val mappedDependency = mapper.mapping(dependency) + + if (mappedDependency != null) { + val mainDependency = mappedDependency.main + if (mainDependency != null) { + mainConsumer += POrderRoot(mainDependency, scope) + } + + for (deferredDep in mappedDependency.deferred) { + deferredConsumer += POrderRoot(deferredDep, scope) + } + } + + return + } + } + + mainConsumer += if (dependency.isModuleDependency && scope != Scope.TEST) { + POrderRoot(PDependency.Module(dependency.moduleName + ".src"), scope) + } else if (dependency.configuration == "tests-jar" || dependency.configuration == "jpsTest") { + POrderRoot( + PDependency.Module(dependency.moduleName + ".test"), + scope, + isProductionOnTestDependency = true + ) + } else { + val classes = dependency.moduleArtifacts.map { it.file } + val library = PLibrary(dependency.moduleName, classes) + POrderRoot(PDependency.ModuleLibrary(library), scope) + } +} + private fun resolveExtraDependencies(configuration: Configuration): List { return configuration.dependencies .filterIsInstance() diff --git a/buildSrc/src/main/kotlin/pill/plugin.kt b/buildSrc/src/main/kotlin/pill/plugin.kt index 63c6e1637f8..49abefe6218 100644 --- a/buildSrc/src/main/kotlin/pill/plugin.kt +++ b/buildSrc/src/main/kotlin/pill/plugin.kt @@ -141,7 +141,9 @@ class JpsCompatiblePlugin : Plugin { } val projectLibraries = getProjectLibraries(rootProject) - val parserContext = ParserContext(getDependencyMappers(projectLibraries), variant) + val dependencyMappers = getDependencyMappers(projectLibraries) + + val parserContext = ParserContext(dependencyMappers, variant) val jpsProject = parse(rootProject, projectLibraries, parserContext) .mapLibraries(this::attachPlatformSources, this::attachAsmSources) @@ -152,7 +154,7 @@ class JpsCompatiblePlugin : Plugin { removeJpsAndPillRunConfigurations() removeAllArtifactConfigurations() - generateKotlinPluginArtifactFile(rootProject).write() + generateKotlinPluginArtifactFile(rootProject, dependencyMappers).write() copyRunConfigurations() setOptionsForDefaultJunitRunConfiguration(rootProject)