Skip to content

Commit 5df4fcb

Browse files
committed
✨ Android compatibility
Add experimental support for android source sets Fixes #49
1 parent 2fd551f commit 5df4fcb

File tree

3 files changed

+78
-20
lines changed

3 files changed

+78
-20
lines changed

plugin-gradle/src/main/groovy/de/obqo/decycle/gradle/DecyclePlugin.groovy

+51-20
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import org.gradle.api.Project
66
import org.gradle.api.Task
77
import org.gradle.api.artifacts.Configuration
88
import org.gradle.api.plugins.JavaBasePlugin
9+
910
/**
1011
* @author Oliver Becker
1112
*/
@@ -16,9 +17,10 @@ class DecyclePlugin implements Plugin<Project> {
1617
@Override
1718
void apply(final Project project) {
1819
Properties props = new Properties()
19-
getClass().classLoader.getResource("META-INF/gradle-plugins/de.obqo.decycle.properties").withInputStream { stream ->
20-
props.load(stream)
21-
}
20+
getClass().classLoader.getResource("META-INF/gradle-plugins/de.obqo.decycle.properties")
21+
.withInputStream { stream ->
22+
props.load(stream)
23+
}
2224

2325
// create a runner task that runs all single decycle tasks
2426
final Task decycleRunnerTask = project.tasks.create(TASK_NAME)
@@ -39,35 +41,64 @@ class DecyclePlugin implements Plugin<Project> {
3941
decycle "de.obqo.decycle:decycle-lib:${toolVersion}"
4042
}
4143

42-
def sources = configuration.sourceSets
44+
def isAndroidProject = project.hasProperty("android")
45+
46+
def sources = isAndroidProject ? configuration.androidSourceSets : configuration.sourceSets
4347
if (sources.empty) {
44-
def projectSources = project.findProperty("sourceSets")
45-
if (projectSources == null) {
46-
throw new GradleException("No source sets found. Did you forget to apply the 'java' plugin?")
48+
def projectSources
49+
if (isAndroidProject) {
50+
projectSources = project.android.sourceSets
51+
} else {
52+
projectSources = project.findProperty("sourceSets")
53+
if (projectSources == null) {
54+
throw new GradleException("No source sets found. Did you forget to apply the 'java' plugin?")
55+
}
4756
}
4857
sources = projectSources.asMap.values()
4958
}
5059

5160
// create decycle work tasks, one for each source set
5261
sources.forEach { source ->
53-
def name = source.name
54-
55-
DecycleTask decycleWorkTask = project.tasks.create(TASK_NAME + name.capitalize(), DecycleTask)
56-
decycleWorkTask.
57-
description = "Checks the ${name} sources for package cycles and other custom constraints"
58-
decycleWorkTask.group = JavaBasePlugin.VERIFICATION_GROUP
59-
decycleWorkTask.configuration.set(configuration)
60-
decycleWorkTask.classpath.set(source.output)
61-
decycleWorkTask.reportFile.set(new File(project.buildDir, "reports/decycle/${name}.html"))
62-
decycleWorkTask.reportTitle.set(project.name + " | " + name);
63-
decycleWorkTask.workerClasspath.set(workerClasspath)
62+
def name = isAndroidProject ? adjustSourceSetName(source.name) : source.name
63+
def output = isAndroidProject
64+
// TODO is there a better way to resolve the output (classes) directory in android projects?
65+
? project.files(project.layout.buildDirectory.dir("tmp/kotlin-classes/$name"),
66+
project.layout.buildDirectory.dir("intermediates/javac/$name"))
67+
: source.output
68+
def compileTaskName = isAndroidProject
69+
// TODO is there a better way to determine the compile task for each source set in android projects?
70+
? "compile" + name.capitalize() + "JavaWithJavac"
71+
: source.classesTaskName
72+
def compileTask = project.tasks.findByPath(compileTaskName)
73+
if (compileTask != null) { // ignore android source sets without compile task
74+
DecycleTask decycleWorkTask = project.tasks.create(TASK_NAME + name.capitalize(), DecycleTask)
75+
decycleWorkTask.
76+
description = "Checks the ${name} sources for package cycles and other custom constraints"
77+
decycleWorkTask.group = JavaBasePlugin.VERIFICATION_GROUP
78+
decycleWorkTask.configuration.set(configuration)
79+
decycleWorkTask.classpath.set(output)
80+
decycleWorkTask.reportFile.set(new File(project.buildDir, "reports/decycle/${name}.html"))
81+
decycleWorkTask.reportTitle.set(project.name + " | " + name)
82+
decycleWorkTask.workerClasspath.set(workerClasspath)
6483

65-
// set task dependencies, e.g. decycle -> decycleTest -> testClasses
66-
decycleRunnerTask.dependsOn(decycleWorkTask.dependsOn(project.tasks[source.classesTaskName]))
84+
// set task dependencies, e.g. decycle -> decycleTest -> testClasses
85+
decycleRunnerTask.dependsOn(decycleWorkTask.dependsOn(compileTask))
86+
} else {
87+
project.getLogger().info(
88+
"Decycle : Ignore sourceSet $name – cannot determine the corresponding compile task")
89+
}
6790
}
6891

6992
// finally make task 'check' depend on the runner task
7093
project.tasks[JavaBasePlugin.CHECK_TASK_NAME].dependsOn decycleRunnerTask
7194
}
7295
}
96+
97+
private static String adjustSourceSetName(String sourceSetName) {
98+
switch (sourceSetName) {
99+
case "testDebug": return "debugUnitTest"
100+
case "testRelease": return "releaseUnitTest"
101+
default: return sourceSetName
102+
}
103+
}
73104
}

plugin-gradle/src/main/java/de/obqo/decycle/gradle/DecycleConfiguration.java

+10
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import java.util.ArrayList;
55
import java.util.List;
66

7+
import org.gradle.api.Named;
78
import org.gradle.api.tasks.SourceSet;
89

910
/**
@@ -16,6 +17,7 @@ class DecycleConfiguration implements Serializable {
1617
private static final long serialVersionUID = 10L;
1718

1819
private final transient List<SourceSet> sourceSets = new ArrayList<>();
20+
private final transient List<Named> androidSourceSets = new ArrayList<>();
1921
private final List<String> includings = new ArrayList<>();
2022
private final List<String> excludings = new ArrayList<>();
2123
private final List<IgnoreConfig> ignoredDeps = new ArrayList<>();
@@ -27,10 +29,18 @@ List<SourceSet> getSourceSets() {
2729
return this.sourceSets;
2830
}
2931

32+
public List<Named> getAndroidSourceSets() {
33+
return this.androidSourceSets;
34+
}
35+
3036
void addSourceSet(final SourceSet sourceSet) {
3137
this.sourceSets.add(sourceSet);
3238
}
3339

40+
void addAndroidSourceSet(final Named sourceSet) {
41+
this.androidSourceSets.add(sourceSet);
42+
}
43+
3444
List<String> getIncludings() {
3545
return this.includings;
3646
}

plugin-gradle/src/main/java/de/obqo/decycle/gradle/DecycleExtension.java

+17
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import org.gradle.api.Action;
88
import org.gradle.api.GradleException;
9+
import org.gradle.api.Named;
910
import org.gradle.api.NamedDomainObjectContainer;
1011
import org.gradle.api.NamedDomainObjectProvider;
1112
import org.gradle.api.Project;
@@ -59,6 +60,22 @@ public void sourceSets(final NamedDomainObjectProvider<?>... sourceSets) {
5960
}
6061
}
6162

63+
/**
64+
* Declare the source sets to checked by decycle. Will be used for android source sets.
65+
*
66+
* @param sourceSets the source sets to be checked
67+
*/
68+
public void sourceSets(final Named... sourceSets) {
69+
for (final Named sourceSet : sourceSets) {
70+
if (!sourceSet.getClass().getName().contains("com.android.build.gradle.internal.api.DefaultAndroidSourceSet")) {
71+
throw new GradleException(String.format(
72+
"decycle: passed value to sourceSets is not a SourceSet, encountered %s",
73+
sourceSet));
74+
}
75+
this.configuration.addAndroidSourceSet(sourceSet);
76+
}
77+
}
78+
6279
public void including(final String... includings) {
6380
for (final String including : includings) {
6481
this.configuration.addIncluding(including);

0 commit comments

Comments
 (0)