Skip to content

Commit

Permalink
Resolves bundle issue.
Browse files Browse the repository at this point in the history
* Now supports test dependencies.
* Now supports multiple hops between dependencies in a bundle.
  • Loading branch information
autonomousapps committed Jul 28, 2021
1 parent 9e2ebf2 commit 63b895a
Show file tree
Hide file tree
Showing 17 changed files with 455 additions and 167 deletions.
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
this@register.compileConfiguration = 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(this@analyzeDependencies.path)

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(this@analyzeDependencies.path)

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

0 comments on commit 63b895a

Please sign in to comment.