Skip to content

Commit cd9e62e

Browse files
authored
feat: failure-on-cycles option (#7)
1 parent 9cde319 commit cd9e62e

File tree

16 files changed

+150
-16
lines changed

16 files changed

+150
-16
lines changed

.github/workflows/ci.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ jobs:
3535
- name: Plugin Test
3636
run: |
3737
./gradlew :heo-gradle-plugin:publishToMavenLocal
38-
./gradlew -PlocalPlugin :it:gradle-plugin:heoReport
38+
./gradlew -PlocalPlugin pluginTest
3939
- name: Create self report file
4040
if: success()
4141
run: |

README.md

+4-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ This tool relies on [graphviz](https://graphviz.org/). Please install graphviz f
1212

1313
- `d`: Enter the directory path.
1414
- `p`: Enter the package path.
15-
- `o`: Enter the destination file path.
15+
- `o`: (optional) Enter the destination file path.
16+
- `failure-on-cycles`: (optional) Enter whether to fail if a cycle occurs between modules.
1617

1718
```bash
1819
java -jar heo-cli-0.0.2.jar -d /Users/heowc/Projects/heo -p dev.heowc.heo
@@ -52,6 +53,8 @@ heo {
5253
directoryPath = "${rootDir}/heo-core" // The default is to use the root path.
5354
prefixPackage = "dev.heowc.heo.core" // The default is group.
5455
// destination // By default, the `reports/heo/index.png` image file is created under the build path.
56+
// failure-on-cycles // The default option is disabled,
57+
// and if enabled the task will fail if a cycle occurs.
5558
}
5659
```
5760

heo-cli/src/main/java/dev/heowc/heo/cli/HeoCliService.java

+6-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import java.util.List;
44

5+
import dev.heowc.heo.core.HeoException;
6+
57
import org.springframework.stereotype.Service;
68

79
import dev.heowc.heo.core.Module;
@@ -29,11 +31,14 @@ public HeoCliService(ModuleLoaderService moduleLoaderService,
2931
this.reportVisualizationService = reportVisualizationService;
3032
}
3133

32-
public void command(String directory, String rootPackage, String destination) {
34+
public void command(String directory, String rootPackage, String destination, HeoConfig heoConfig) {
3335
final List<Module> modules = moduleLoaderService.loads(directory, rootPackage);
3436
final DependencyAnalysisResult result =
3537
dependencyAnalysisService.analyzeProjectDependencies(modules, rootPackage);
3638
final String report = analysisReportService.createReport(result);
3739
reportVisualizationService.createFile(report, destination);
40+
if (heoConfig.failureOnCycles() && result.hasCycle()) {
41+
throw new HeoException("Cycles occurred");
42+
}
3843
}
3944
}

heo-cli/src/main/java/dev/heowc/heo/cli/HeoCommand.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,11 @@ public HeoCommand(HeoCliService service) {
1818
@Command(command = "heo")
1919
public void doHeo(@Option(shortNames = 'd', required = true) String directory,
2020
@Option(shortNames = 'p', required = true) String prefixPackage,
21-
@Option(shortNames = 'o') String destination) {
21+
@Option(shortNames = 'o') String destination,
22+
@Option(longNames = "failure-on-cycles", defaultValue = "false") boolean failureOnCycles) {
2223
if (StringUtils.isBlank(destination)) {
2324
destination = String.format("result-%s.png", System.currentTimeMillis());
2425
}
25-
service.command(directory, prefixPackage, destination);
26+
service.command(directory, prefixPackage, destination, new HeoConfig(failureOnCycles));
2627
}
2728
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package dev.heowc.heo.cli;
2+
3+
public record HeoConfig(boolean failureOnCycles) {
4+
5+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package dev.heowc.heo.core;
2+
3+
public class HeoException extends RuntimeException {
4+
5+
public HeoException(String message) {
6+
super(message);
7+
}
8+
}

heo-core/src/main/java/dev/heowc/heo/core/analysis/domain/DependencyAnalysisResult.java

+4
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,8 @@ public DomainGraph getDomainGraph() {
1919
public CycleDetector<String, DomainEdge> getCycleDetector() {
2020
return cycleDetector;
2121
}
22+
23+
public boolean hasCycle() {
24+
return cycleDetector.detectCycles();
25+
}
2226
}

heo-gradle-plugin/src/main/java/dev/heowc/heo/gradle/HeoPlugin.java

+18-9
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,19 @@
77
import java.nio.file.StandardCopyOption;
88
import java.util.List;
99

10+
import javax.annotation.Nullable;
11+
1012
import org.gradle.api.Plugin;
1113
import org.gradle.api.Project;
1214
import org.gradle.api.tasks.JavaExec;
1315

14-
import javax.annotation.Nullable;
15-
1616
public class HeoPlugin implements Plugin<Project> {
1717

1818
private static final String REPORT_PATH = "build/reports/heo";
1919

2020
@Override
2121
public void apply(Project project) {
22-
final HeoConfig config = project.getExtensions().create("heo", HeoConfig.class);
22+
final HeoPluginConfig config = project.getExtensions().create("heo", HeoPluginConfig.class);
2323
project.getTasks().register("heoReport", JavaExec.class, task -> {
2424
task.setGroup("heo");
2525
task.setDescription("Execute heo-cli");
@@ -37,24 +37,33 @@ public void apply(Project project) {
3737

3838
task.setMain("-jar");
3939
task.args(tempJar.getAbsolutePath());
40-
task.args(List.of("-d", determineDirectory(project, config.getDirectoryPath()),
41-
"-p", determinePrefixPackage(project, config.getPrefixPackage()),
42-
"-o", determineDestination(project, config.getDestination())));
40+
task.args(List.of(
41+
"-d", determineDirectory(project, config.getDirectoryPath()),
42+
"-p", determinePrefixPackage(project, config.getPrefixPackage()),
43+
"-o", determineDestination(project, config.getDestination()),
44+
"--failure-on-cycles", config.isFailureOnCycles()
45+
));
4346

4447
tempJar.deleteOnExit();
4548
});
4649
}
4750

4851
private static String determineDirectory(Project project, @Nullable String directoryPath) {
49-
return StringUtils.isBlank(directoryPath) ? project.getProjectDir().getAbsolutePath() : directoryPath;
52+
return StringUtils.isBlank(directoryPath)
53+
? project.getProjectDir().getAbsolutePath()
54+
: directoryPath;
5055
}
5156

5257
private static String determinePrefixPackage(Project project, @Nullable String prefixPackage) {
53-
return StringUtils.isBlank(prefixPackage) ? project.getGroup().toString() : prefixPackage;
58+
return StringUtils.isBlank(prefixPackage)
59+
? project.getGroup().toString()
60+
: prefixPackage;
5461
}
5562

5663
private static String determineDestination(Project project, @Nullable String destination) {
57-
return StringUtils.isBlank(destination) ? Path.of(project.getProjectDir().getAbsolutePath(), REPORT_PATH, "index.png").toString() : destination;
64+
return StringUtils.isBlank(destination)
65+
? Path.of(project.getProjectDir().getAbsolutePath(), REPORT_PATH, "index.png").toString()
66+
: destination;
5867
}
5968

6069
}

heo-gradle-plugin/src/main/java/dev/heowc/heo/gradle/HeoConfig.java heo-gradle-plugin/src/main/java/dev/heowc/heo/gradle/HeoPluginConfig.java

+10-1
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
package dev.heowc.heo.gradle;
22

3-
public class HeoConfig {
3+
public class HeoPluginConfig {
44

55
private String directoryPath;
66
private String prefixPackage;
77
private String destination;
8+
private boolean failureOnCycles;
89

910
public String getDirectoryPath() {
1011
return directoryPath;
@@ -29,4 +30,12 @@ public String getDestination() {
2930
public void setDestination(String destination) {
3031
this.destination = destination;
3132
}
33+
34+
public boolean isFailureOnCycles() {
35+
return failureOnCycles;
36+
}
37+
38+
public void setFailureOnCycles(boolean failureOnCycles) {
39+
this.failureOnCycles = failureOnCycles;
40+
}
3241
}

it/cycled-gradle-plugin/build.gradle

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
buildscript {
2+
repositories {
3+
mavenLocal()
4+
}
5+
dependencies {
6+
if (project.hasProperty('localPlugin')) {
7+
classpath "dev.heowc.heo:heo-gradle-plugin:${version}"
8+
}
9+
}
10+
}
11+
12+
if (project.hasProperty('localPlugin')) {
13+
apply plugin: 'dev.heowc.heo'
14+
apply plugin: 'java'
15+
16+
heo {
17+
directoryPath = "${rootDir}/it/cycled-gradle-plugin"
18+
prefixPackage = "dev.heowc.heo.it.cycled"
19+
failureOnCycles = true
20+
}
21+
22+
test {
23+
dependsOn 'pluginTest'
24+
}
25+
26+
tasks.register('pluginTest') {
27+
doLast {
28+
var failure = false
29+
try {
30+
tasks.heoReport.exec()
31+
} catch (Exception e) {
32+
failure = true
33+
}
34+
if (!failure) {
35+
throw new IllegalStateException("The task did not fail")
36+
}
37+
}
38+
}
39+
40+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package dev.heowc.heo.it.cycled;
2+
3+
public class CycledMain {
4+
5+
public static void main(String[] args) {
6+
}
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package dev.heowc.heo.it.cycled.a;
2+
3+
import dev.heowc.heo.it.cycled.b.B;
4+
5+
public class A {
6+
7+
private B b;
8+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package dev.heowc.heo.it.cycled.b;
2+
3+
import dev.heowc.heo.it.cycled.c.C;
4+
5+
public class B {
6+
7+
private C c;
8+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package dev.heowc.heo.it.cycled.c;
2+
3+
import dev.heowc.heo.it.cycled.a.A;
4+
5+
public class C {
6+
7+
private A a;
8+
}

it/gradle-plugin/build.gradle

+19
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,29 @@ buildscript {
1111

1212
if (project.hasProperty('localPlugin')) {
1313
apply plugin: 'dev.heowc.heo'
14+
apply plugin: 'java'
1415

1516
heo {
1617
directoryPath = "${rootDir}/heo-core"
1718
prefixPackage = "dev.heowc.heo.core"
1819
}
20+
21+
test {
22+
dependsOn 'pluginTest'
23+
}
24+
25+
tasks.register('pluginTest') {
26+
doLast {
27+
var failure = false
28+
try {
29+
tasks.heoReport.exec()
30+
} catch (Exception e) {
31+
failure = true
32+
}
33+
if (failure) {
34+
throw new IllegalStateException("The task did not succeed")
35+
}
36+
}
37+
}
1938
}
2039

settings.gradle

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,4 @@ include 'heo-cli'
1111
include 'heo-gradle-plugin'
1212

1313
include 'it:gradle-plugin'
14-
14+
include 'it:cycled-gradle-plugin'

0 commit comments

Comments
 (0)