Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Resolves bundle issue. #441

Merged
merged 1 commit into from
Jul 28, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.autonomousapps.jvm

import com.autonomousapps.jvm.projects.TestBundleProject
import com.autonomousapps.jvm.projects.TestDependenciesProject

import static com.autonomousapps.utils.Runner.build
Expand All @@ -21,4 +22,19 @@ final class TestDependenciesSpec extends AbstractJvmSpec {
where:
gradleVersion << gradleVersions()
}

def "bundles work for test dependencies (#gradleVersion)"() {
given:
def project = new TestBundleProject()
gradleProject = project.gradleProject

when:
build(gradleVersion, gradleProject.rootDir, ':buildHealth')

then:
assertThat(actualAdvice()).containsExactlyElementsIn(project.expectedAdvice)

where:
gradleVersion << gradleVersions()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package com.autonomousapps.jvm.projects

import com.autonomousapps.AbstractProject
import com.autonomousapps.advice.Advice
import com.autonomousapps.kit.GradleProject
import com.autonomousapps.kit.Plugin
import com.autonomousapps.kit.Source
import com.autonomousapps.kit.SourceType

import static com.autonomousapps.kit.Dependency.junit
import static com.autonomousapps.kit.Dependency.kotestAssertions
import static java.util.Collections.emptyList

final class TestBundleProject extends AbstractProject {

private static final junit = junit('testImplementation')
private static final kotest = kotestAssertions('testImplementation')

final GradleProject gradleProject

TestBundleProject() {
this.gradleProject = build()
}

private GradleProject build() {
def builder = newGradleProjectBuilder()
builder.withSubproject('proj') { s ->
s.sources = sources
s.withBuildScript { bs ->
bs.plugins = [Plugin.kotlinPluginNoVersion]
bs.dependencies = [kotest, junit]
}
}
builder.withRootProject {
it.withBuildScript { bs ->
bs.additions = """
dependencyAnalysis {
dependencies {
bundle('kotest-assertions') {
includeDependency('io.kotest:kotest-assertions-core-jvm')
includeDependency('io.kotest:kotest-assertions-shared-jvm')
}
}
}
""".stripIndent()
}
}

def project = builder.build()
project.writer().write()
return project
}

private List<Source> sources = [
new Source(
SourceType.KOTLIN, "Main", "com/example",
"""\
package com.example

class Main {
fun magic() = 42
}
""".stripIndent()
),
new Source(
SourceType.KOTLIN, "MainTest", "com/example",
"""\
package com.example

import io.kotest.matchers.shouldBe
import org.junit.Test

class MainTest {
@Test
public fun test() {
"a" shouldBe "b"
}
}
""".stripIndent(),
'test'
)
]

final List<Advice> expectedAdvice = emptyList()
}
73 changes: 36 additions & 37 deletions src/main/kotlin/com/autonomousapps/DependencyAnalysisPlugin.kt
Original file line number Diff line number Diff line change
Expand Up @@ -601,19 +601,21 @@ class DependencyAnalysisPlugin : Plugin<Project> {
tasks.register<AnalyzeJarTask>("analyzeJar$variantTaskName") {
val compileClasspath = configurations.getByName(dependencyAnalyzer.compileConfigurationName)
this.compileClasspath = compileClasspath
artifactFiles.setFrom(compileClasspath
.incoming
.artifactViewFor(dependencyAnalyzer.attributeValueJar)
.artifacts
.artifactFiles
artifactFiles.setFrom(
compileClasspath
.incoming
.artifactViewFor(dependencyAnalyzer.attributeValueJar)
.artifacts
.artifactFiles
)
val testCompileClasspath = configurations.findByName(dependencyAnalyzer.testCompileConfigurationName)
this.testCompileClasspath = testCompileClasspath
testArtifactFiles.setFrom(testCompileClasspath
?.incoming
?.artifactViewFor(dependencyAnalyzer.attributeValueJar)
?.artifacts
?.artifactFiles
testArtifactFiles.setFrom(
testCompileClasspath
?.incoming
?.artifactViewFor(dependencyAnalyzer.attributeValueJar)
?.artifacts
?.artifactFiles
)

allArtifacts.set(artifactsReportTask.flatMap { it.output })
Expand Down Expand Up @@ -730,13 +732,9 @@ class DependencyAnalysisPlugin : Plugin<Project> {
// A report of all unused dependencies and used-transitive dependencies
val misusedDependenciesTask =
tasks.register<DependencyMisuseTask>("misusedDependencies$variantTaskName") {
val compileConfiguration = configurations.getByName(dependencyAnalyzer.compileConfigurationName)
artifactFiles = compileConfiguration
.incoming
.artifactViewFor(dependencyAnalyzer.attributeValueJar)
.artifacts
.artifactFiles
[email protected] = compileConfiguration
jarAttr.set(dependencyAnalyzer.attributeValueJar)
compileConfiguration = configurations.getByName(dependencyAnalyzer.compileConfigurationName)
testCompileConfiguration = configurations.findByName(dependencyAnalyzer.testCompileConfigurationName)

declaredDependencies.set(analyzeJarTask.flatMap { it.allComponentsReport })
usedClasses.set(analyzeClassesTask.flatMap { it.output })
Expand Down Expand Up @@ -802,6 +800,23 @@ class DependencyAnalysisPlugin : Plugin<Project> {
storeAbiDumpOutput(it, variantName)
}

// Produces a json and graphviz file representing the dependency graph
val graphTask = tasks.register<DependencyGraphPerVariant>("graph$variantTaskName") {
jarAttr.set(dependencyAnalyzer.attributeValueJar)
compileClasspath = configurations.getByName(dependencyAnalyzer.compileConfigurationName)
testCompileClasspath = configurations.findByName(dependencyAnalyzer.testCompileConfigurationName)

projectPath.set([email protected])

compileOutputJson.set(outputPaths.compileGraphPath)
compileOutputDot.set(outputPaths.compileGraphDotPath)
testCompileOutputJson.set(outputPaths.testCompileGraphPath)
testCompileOutputDot.set(outputPaths.testCompileGraphDotPath)
}
aggregateGraphTask.configure {
graphs.add(graphTask.flatMap { it.compileOutputJson })
}

// Optionally transforms and prints advice to console
val advicePrinterTask = tasks.register<AdvicePrinterTask>("advicePrinter$variantTaskName")

Expand All @@ -820,6 +835,9 @@ class DependencyAnalysisPlugin : Plugin<Project> {
serviceLoaders.set(serviceLoaderTask.flatMap { it.output })
usedVariantDependencies.set(misusedDependenciesTask.flatMap { it.outputUsedVariantDependencies })

compileGraph.set(graphTask.flatMap { it.compileOutputJson })
testCompileGraph.set(graphTask.flatMap { it.testCompileOutputJson })

dependenciesHandler = getExtension().dependenciesHandler

dataBindingEnabled.set(dependencyAnalyzer.isDataBindingEnabled)
Expand Down Expand Up @@ -857,25 +875,6 @@ class DependencyAnalysisPlugin : Plugin<Project> {
adviceConsoleReportTxt.set(outputPaths.adviceConsoleTxtPath)
}

// Produces a json and graphviz file representing the dependency graph
val graphTask = tasks.register<DependencyGraphPerVariant>("graph$variantTaskName") {
val compileClasspath = configurations.getByName(dependencyAnalyzer.compileConfigurationName)
this.compileClasspath = compileClasspath
compileClasspathArtifacts.setFrom(compileClasspath
.incoming
.artifactViewFor(dependencyAnalyzer.attributeValueJar)
.artifacts
.artifactFiles
)
projectPath.set([email protected])

outputJson.set(outputPaths.graphPath)
outputDot.set(outputPaths.graphDotPath)
}
aggregateGraphTask.configure {
graphs.add(graphTask.flatMap { it.outputJson })
}

// Produces a report consolidating all information about dependencies in one place, for
// ReasonTask to use as an input
val reasonableDepsTask = tasks.register<ReasonableDependencyTask>("reasonableDepsReport$variantTaskName") {
Expand Down Expand Up @@ -909,7 +908,7 @@ class DependencyAnalysisPlugin : Plugin<Project> {

// Emits to console the reason for a piece of advice
tasks.register<ReasonTask>("reason$variantTaskName") {
graph.set(graphTask.flatMap { it.outputJson })
graph.set(graphTask.flatMap { it.compileOutputJson })
advice.set(adviceTask.flatMap { it.adviceReport })
reasonableDependenciesReport.set(reasonableDepsTask.flatMap { it.output })

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ data class ComponentWithTransitives(
val usedTransitiveDependencies: MutableSet<Dependency>?
) : HasDependency, Comparable<ComponentWithTransitives> {

override fun compareTo(other: ComponentWithTransitives): Int {
return dependency.compareTo(other.dependency)
}
val identifier: String = dependency.identifier

override fun compareTo(other: ComponentWithTransitives) = dependency.compareTo(other.dependency)
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,7 @@ data class TransitiveDependency(
val variants: Set<String> = emptySet()
) : HasDependency, Comparable<TransitiveDependency> {

val identifier: String = dependency.identifier

override fun compareTo(other: TransitiveDependency): Int = dependency.compareTo(other.dependency)
}
6 changes: 4 additions & 2 deletions src/main/kotlin/com/autonomousapps/graph/ShortestPath.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ import java.util.*

internal class ShortestPath(
graph: DependencyGraph,
source: Node
source: String
) {

constructor(graph: DependencyGraph, source: Node) : this(graph, source.identifier)

private val distTo = linkedMapOf<String, Float>()
private val edgeTo = linkedMapOf<String, Edge>()

Expand All @@ -18,7 +20,7 @@ internal class ShortestPath(
for (node in graph.nodes()) {
distTo[node.identifier] = Float.POSITIVE_INFINITY
}
distTo[source.identifier] = 0f
distTo[source] = 0f

// visit vertices in topological order
val top = Topological(graph)
Expand Down
1 change: 0 additions & 1 deletion src/main/kotlin/com/autonomousapps/internal/JarAnalyzer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import org.gradle.api.artifacts.component.ProjectComponentIdentifier
import org.gradle.api.artifacts.result.DependencyResult
import org.gradle.api.artifacts.result.ResolvedDependencyResult
import org.gradle.api.logging.Logger
import java.util.zip.ZipException
import java.util.zip.ZipFile

/**
Expand Down
8 changes: 5 additions & 3 deletions src/main/kotlin/com/autonomousapps/internal/OutputPaths.kt
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,10 @@ internal class OutputPaths(private val project: Project, variantName: String) {
*/

private val graphDir = "${variantDirectory}/graph"
val graphPath = layout("${graphDir}/graph.json")
val graphDotPath = layout("${graphDir}/graph.gv")
val compileGraphPath = layout("${graphDir}/graph-compile.json")
val testCompileGraphPath = layout("${graphDir}/graph-test-compile.json")
val compileGraphDotPath = layout("${graphDir}/graph-compile.gv")
val testCompileGraphDotPath = layout("${graphDir}/graph-test-compile.gv")
val reasonableDependenciesPath = layout("${intermediatesDir}/reasonable-dependencies.json")
val graphReasonPath = layout("${graphDir}/graph-reason.gv")

Expand Down Expand Up @@ -148,7 +150,7 @@ fun getAbiAnalysisPath(variantName: String) =
"${getVariantDirectory(variantName)}/intermediates/abi.json"

fun getGraphPerVariantPath(variantName: String) =
"${getVariantDirectory(variantName)}/graph/graph.json"
"${getVariantDirectory(variantName)}/graph/graph-compile.json"

fun getAdvicePath(variantName: String) = "${getVariantDirectory(variantName)}/advice.json"
fun getAdviceConsolePath(variantName: String) =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,12 @@ internal class Advisor(
val changeToImpl = computeImplDepsWronglyDeclared(unusedDependencies)

if (dependencyBundles.isNotEmpty()) {
filterSpecBuilder.dependencyBundleFilter = DependencyBundleFilter(dependencyBundles)
filterSpecBuilder.dependencyBundleFilter = DependencyBundleFilter(
bundles = dependencyBundles,
compileGraph = filterSpecBuilder.compileGraph,
testCompileGraph = filterSpecBuilder.testCompileGraph,
transitives = filterSpecBuilder.usedTransitiveComponents
)
}

// update filterSpecBuilder with ktxFilter
Expand Down
Loading