Skip to content
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
Expand Up @@ -58,11 +58,16 @@ public class ComposableStabilityCollector(private val project: Project) {
val contentRoots = moduleRootManager.contentRoots

for (contentRoot in contentRoots) {
// Look for build/stability/stability-info.json
val jsonFile = File(contentRoot.path, "build/stability/stability-info.json")
if (!jsonFile.exists()) {
continue
}
// Look for stability-info.json in build/stability/ (supports both old and new layouts)
val stabilityDir = File(contentRoot.path, "build/stability")
val legacyFile = File(stabilityDir, "stability-info.json")
val jsonFile = if (legacyFile.exists()) {
legacyFile
} else {
stabilityDir.listFiles { file -> file.isDirectory }
?.map { File(it, "stability-info.json") }
?.firstOrNull { it.exists() }
} ?: continue

try {
val jsonContent = jsonFile.readText()
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ kotlin.mpp.androidGradlePluginCompatibility.nowarn=true

# Maven publishing
GROUP=com.github.skydoves
VERSION_NAME=0.7.4
VERSION_NAME=0.7.5-SNAPSHOT

POM_URL=https://github.com/skydoves/compose-stability-analyzer/
POM_SCM_URL=https://github.com/skydoves/compose-stability-analyzer/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public class StabilityAnalyzerGradlePlugin : KotlinCompilerPluginSupportPlugin {

// This version should match the version in gradle.properties
// Update this when bumping the library version
private const val VERSION = "0.7.4"
private const val VERSION = "0.7.5-SNAPSHOT"

// Compiler option keys
private const val OPTION_ENABLED = "enabled"
Expand All @@ -73,9 +73,9 @@ public class StabilityAnalyzerGradlePlugin : KotlinCompilerPluginSupportPlugin {
registerTasksAndroid(target, extension, androidComponents)
}

// Add output parameter to the Kotlin tasks to ensure it is compatible with the Build Cache
// Per-task output directory to avoid shared output conflicts with other plugins (Issue #153)
target.tasks.withType(KotlinCompile::class.java).configureEach {
val stabilityDir = target.layout.buildDirectory.dir("stability").get()
val stabilityDir = target.layout.buildDirectory.dir("stability/$name")
outputs.dir(stabilityDir).optional(true)
}
}
Expand All @@ -91,7 +91,9 @@ public class StabilityAnalyzerGradlePlugin : KotlinCompilerPluginSupportPlugin {
) {
projectName.set(target.name)
stabilityInputFiles.setFrom(
target.layout.buildDirectory.file("stability/stability-info.json"),
target.fileTree(target.layout.buildDirectory.dir("stability")) {
include("*/stability-info.json")
},
)
outputDir.set(extension.stabilityValidation.outputDir)
ignoredPackages.set(extension.stabilityValidation.ignoredPackages)
Expand All @@ -107,7 +109,9 @@ public class StabilityAnalyzerGradlePlugin : KotlinCompilerPluginSupportPlugin {
) {
projectName.set(target.name)
stabilityInputFiles.from(
target.layout.buildDirectory.file("stability/stability-info.json"),
target.fileTree(target.layout.buildDirectory.dir("stability")) {
include("*/stability-info.json")
},
)
stabilityReferenceFiles.from(extension.stabilityValidation.outputDir)
ignoredPackages.set(extension.stabilityValidation.ignoredPackages)
Expand Down Expand Up @@ -158,7 +162,9 @@ public class StabilityAnalyzerGradlePlugin : KotlinCompilerPluginSupportPlugin {
) {
projectName.set(target.name)
stabilityInputFiles.setFrom(
target.layout.buildDirectory.file("stability/stability-info.json"),
target.layout.buildDirectory.file(
"stability/compile${variantNameUpperCase}Kotlin/stability-info.json",
),
)
outputDir.set(extension.stabilityValidation.outputDir)
ignoredPackages.set(extension.stabilityValidation.ignoredPackages)
Expand All @@ -175,7 +181,9 @@ public class StabilityAnalyzerGradlePlugin : KotlinCompilerPluginSupportPlugin {
) {
projectName.set(target.name)
stabilityInputFiles.from(
target.layout.buildDirectory.file("stability/stability-info.json"),
target.layout.buildDirectory.file(
"stability/compile${variantNameUpperCase}Kotlin/stability-info.json",
),
)
stabilityReferenceFiles.from(extension.stabilityValidation.outputDir)
ignoredPackages.set(extension.stabilityValidation.ignoredPackages)
Expand Down Expand Up @@ -266,8 +274,10 @@ public class StabilityAnalyzerGradlePlugin : KotlinCompilerPluginSupportPlugin {
return project.provider {
val projectDependencies = collectProjectDependencies(project)

// Write project dependencies to a file to avoid empty string issues with SubpluginOption
val stabilityDir = project.layout.buildDirectory.dir("stability").get().asFile
// Per-compilation output directory to avoid shared output conflicts (Issue #153)
val compileTaskName = kotlinCompilation.compileTaskProvider.name
val stabilityDir = project.layout.buildDirectory
.dir("stability/$compileTaskName").get().asFile
stabilityDir.mkdirs()
val dependenciesFile = java.io.File(stabilityDir, "project-dependencies.txt")
dependenciesFile.writeText(projectDependencies.joinToString("\n"))
Expand Down Expand Up @@ -356,7 +366,6 @@ public class StabilityAnalyzerGradlePlugin : KotlinCompilerPluginSupportPlugin {

// Configure dependencies lazily using TaskProvider
stabilityDumpTask.configure {
// Use provider to lazily collect Kotlin compile task names
dependsOn(
includeTestsProvider.map { includeTests ->
project.tasks.matching { task ->
Expand All @@ -365,27 +374,9 @@ public class StabilityAnalyzerGradlePlugin : KotlinCompilerPluginSupportPlugin {
}
},
)

if (filter != null) {
// For now, stability check compiler plugin still creates the same files
// for different variant tasks. That means that even though our variant task
// is not dependent on the other-variant kotlin tasks, it is still implicitly coupled
// with them as it reads the same files. To mitigate for this,
// we tell Gradle that this task must run after any kotlin tasks, even
// if their variant does not match ours
mustRunAfter(
includeTestsProvider.map { includeTests ->
project.tasks.matching { task ->
isKotlinTaskApplicable(task.name, includeTests) &&
!task.name.contains(filter)
}
},
)
}
}

stabilityCheckTask.configure {
// Use provider to lazily collect Kotlin compile task names
dependsOn(
includeTestsProvider.map { includeTests ->
project.tasks.matching { task ->
Expand All @@ -394,26 +385,6 @@ public class StabilityAnalyzerGradlePlugin : KotlinCompilerPluginSupportPlugin {
}
},
)

if (filter != null) {
// For now, stability check compiler plugin still creates the same files
// for different variant tasks. That means that even though our variant task
// is not dependent on the other-variant kotlin tasks, it is still implicitly coupled
// with them as it reads the same files. To mitigate for this,
// we tell Gradle that this task must run after any kotlin tasks, even
// if their variant does not match ours
mustRunAfter(
includeTestsProvider.map { includeTests ->
project.tasks.matching { task ->
isKotlinTaskApplicable(
task.name,
includeTests,
) &&
!task.name.contains(filter)
}
},
)
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,8 @@ public abstract class StabilityCheckTask : DefaultTask() {

@TaskAction
public fun check() {
val inputFile = stabilityInputFiles.files.firstOrNull()
if (inputFile == null || !inputFile.exists()) {
val inputFile = stabilityInputFiles.files.firstOrNull { it.exists() }
if (inputFile == null) {
// If the file doesn't exist, it means the module has no composable functions
// This is expected for modules like activities or utilities without composables
logger.lifecycle(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,8 @@ public abstract class StabilityDumpTask : DefaultTask() {

@TaskAction
public fun dump() {
val inputFile = stabilityInputFiles.singleOrNull()
if (inputFile == null || !inputFile.exists()) {
val inputFile = stabilityInputFiles.files.firstOrNull { it.exists() }
if (inputFile == null) {
// If the file doesn't exist, it means the module has no composable functions
// This is expected for modules like activities or utilities without composables
logger.lifecycle("ℹ️ No composables found in :${projectName.get()}, skipping stability dump")
Expand Down
Loading