From 387838933f5e799cba00513d3470d750cf9eca08 Mon Sep 17 00:00:00 2001 From: WonChul Heo Date: Sun, 17 Nov 2024 20:47:57 +0900 Subject: [PATCH] fix: java class parsing failed (#23) --- .../java/dev/heowc/heo/cli/HeoCliService.java | 10 +++-- .../java/dev/heowc/heo/core/ParserConfig.java | 30 ++++++++++++++ .../analysis/domain/DependencyMapper.java | 40 +++++++++++-------- .../heo/core/loader/ModuleLoaderConfig.java | 4 ++ .../application/ModuleLoaderService.java | 22 ++++++---- .../heo/core/loader/domain/ModuleLoader.java | 23 +++++++---- .../java/dev/heowc/heo/gradle/HeoPlugin.java | 36 ++++++++++++----- it/cycled-gradle-plugin/build.gradle | 3 +- it/gradle-plugin/build.gradle | 1 + 9 files changed, 124 insertions(+), 45 deletions(-) create mode 100644 heo-core/src/main/java/dev/heowc/heo/core/ParserConfig.java create mode 100644 heo-core/src/main/java/dev/heowc/heo/core/loader/ModuleLoaderConfig.java diff --git a/heo-cli/src/main/java/dev/heowc/heo/cli/HeoCliService.java b/heo-cli/src/main/java/dev/heowc/heo/cli/HeoCliService.java index 757823c..452fc7f 100644 --- a/heo-cli/src/main/java/dev/heowc/heo/cli/HeoCliService.java +++ b/heo-cli/src/main/java/dev/heowc/heo/cli/HeoCliService.java @@ -2,13 +2,13 @@ import java.util.List; -import dev.heowc.heo.core.HeoException; - import org.springframework.stereotype.Service; +import dev.heowc.heo.core.HeoException; import dev.heowc.heo.core.Module; import dev.heowc.heo.core.analysis.application.DependencyAnalysisService; import dev.heowc.heo.core.analysis.domain.DependencyAnalysisResult; +import dev.heowc.heo.core.loader.ModuleLoaderConfig; import dev.heowc.heo.core.loader.application.ModuleLoaderService; import dev.heowc.heo.core.reporting.AnalysisReportService; import dev.heowc.heo.core.visualization.ReportVisualizationService; @@ -32,7 +32,7 @@ public HeoCliService(ModuleLoaderService moduleLoaderService, } public void command(String directory, String rootPackage, String destination, HeoConfig heoConfig) { - final List modules = moduleLoaderService.loads(directory, rootPackage); + final List modules = moduleLoaderService.loads(createConfig(directory, rootPackage)); final DependencyAnalysisResult result = dependencyAnalysisService.analyzeProjectDependencies(modules, rootPackage); final String report = analysisReportService.createReport(result); @@ -41,4 +41,8 @@ public void command(String directory, String rootPackage, String destination, He throw new HeoException("Cycles occurred"); } } + + private static ModuleLoaderConfig createConfig(String directory, String rootPackage) { + return new ModuleLoaderConfig(directory, rootPackage); + } } diff --git a/heo-core/src/main/java/dev/heowc/heo/core/ParserConfig.java b/heo-core/src/main/java/dev/heowc/heo/core/ParserConfig.java new file mode 100644 index 0000000..6e3a524 --- /dev/null +++ b/heo-core/src/main/java/dev/heowc/heo/core/ParserConfig.java @@ -0,0 +1,30 @@ +package dev.heowc.heo.core; + +import com.github.javaparser.JavaParser; +import com.github.javaparser.ParserConfiguration; +import com.github.javaparser.ParserConfiguration.LanguageLevel; +import com.github.javaparser.utils.ParserCollectionStrategy; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration(proxyBeanMethods = false) +class ParserConfig { + + @Bean + ParserConfiguration parserConfiguration() { + final ParserConfiguration configuration = new ParserConfiguration(); + configuration.setLanguageLevel(LanguageLevel.JAVA_17); + return configuration; + } + + @Bean + ParserCollectionStrategy parserCollectionStrategy(ParserConfiguration parserConfiguration) { + return new ParserCollectionStrategy(parserConfiguration); + } + + @Bean + JavaParser javaParser(ParserConfiguration parserConfiguration) { + return new JavaParser(parserConfiguration); + } +} diff --git a/heo-core/src/main/java/dev/heowc/heo/core/analysis/domain/DependencyMapper.java b/heo-core/src/main/java/dev/heowc/heo/core/analysis/domain/DependencyMapper.java index 9953ea7..45e0fa9 100644 --- a/heo-core/src/main/java/dev/heowc/heo/core/analysis/domain/DependencyMapper.java +++ b/heo-core/src/main/java/dev/heowc/heo/core/analysis/domain/DependencyMapper.java @@ -13,6 +13,8 @@ import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.Pair; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.github.javaparser.JavaParser; import com.github.javaparser.ParseResult; @@ -28,18 +30,11 @@ @DomainService public class DependencyMapper { - private final JavaParser javaParser = new JavaParser(); + private final Logger logger = LoggerFactory.getLogger(DependencyMapper.class); + private final JavaParser javaParser; - private static String toGroupId(GroupIdProvider groupIdProvider, String rootPackage, Module module) { - return groupIdProvider.groupId(rootPackage, module); - } - - private static BinaryOperator> merge() { - return (deps, deps2) -> { - final Set merged = new HashSet<>(deps); - merged.addAll(deps2); - return merged; - }; + public DependencyMapper(JavaParser javaParser) { + this.javaParser = javaParser; } public DomainGraph mapDependencies(List modules, String rootPackage) { @@ -48,16 +43,29 @@ public DomainGraph mapDependencies(List modules, String rootPackage) { final Map moduleGroup = modules.stream() .collect(Collectors.toUnmodifiableMap(Module::getIdentity, Function.identity())); - final Map> result = modules.stream() - .map(it -> toDependentModule(rootPackage, it, moduleGroup, - groupIdProvider)) - .collect(Collectors.toUnmodifiableMap(Pair::getKey, - Pair::getValue, merge())); + final Map> result = + modules.stream() + .map(it -> toDependentModule(rootPackage, it, moduleGroup, groupIdProvider)) + .peek(it -> logger.debug("module={}, dependent={}", + it.getKey(), it.getValue())) + .collect(Collectors.toUnmodifiableMap(Pair::getKey, Pair::getValue, merge())); graph.addVertex(result); graph.addEdge(result); return graph; } + private static String toGroupId(GroupIdProvider groupIdProvider, String rootPackage, Module module) { + return groupIdProvider.groupId(rootPackage, module); + } + + private static BinaryOperator> merge() { + return (deps, deps2) -> { + final Set merged = new HashSet<>(deps); + merged.addAll(deps2); + return merged; + }; + } + private Pair> toDependentModule(String rootPackage, Module module, Map moduleGroup, diff --git a/heo-core/src/main/java/dev/heowc/heo/core/loader/ModuleLoaderConfig.java b/heo-core/src/main/java/dev/heowc/heo/core/loader/ModuleLoaderConfig.java new file mode 100644 index 0000000..6170714 --- /dev/null +++ b/heo-core/src/main/java/dev/heowc/heo/core/loader/ModuleLoaderConfig.java @@ -0,0 +1,4 @@ +package dev.heowc.heo.core.loader; + +public record ModuleLoaderConfig(String projectDirectory, String rootPackage) { +} diff --git a/heo-core/src/main/java/dev/heowc/heo/core/loader/application/ModuleLoaderService.java b/heo-core/src/main/java/dev/heowc/heo/core/loader/application/ModuleLoaderService.java index b1dddb5..ab0d99d 100644 --- a/heo-core/src/main/java/dev/heowc/heo/core/loader/application/ModuleLoaderService.java +++ b/heo-core/src/main/java/dev/heowc/heo/core/loader/application/ModuleLoaderService.java @@ -4,24 +4,32 @@ import java.io.UncheckedIOException; import java.util.List; -import dev.heowc.heo.core.Module; -import dev.heowc.heo.core.loader.domain.ModuleLoader; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; +import com.github.javaparser.utils.ParserCollectionStrategy; + +import dev.heowc.heo.core.Module; +import dev.heowc.heo.core.loader.ModuleLoaderConfig; +import dev.heowc.heo.core.loader.domain.ModuleLoader; + @Service public class ModuleLoaderService { private final Logger logger = LoggerFactory.getLogger(ModuleLoaderService.class); + private final ParserCollectionStrategy parserCollectionStrategy; + + public ModuleLoaderService(ParserCollectionStrategy parserCollectionStrategy) { + this.parserCollectionStrategy = parserCollectionStrategy; + } - public List loads(String projectDirectory, String rootPackage) { + public List loads(ModuleLoaderConfig config) { try { - logger.info("Loading " + rootPackage + " from " + projectDirectory); - return new ModuleLoader(projectDirectory, rootPackage).loadModules(); + logger.info("Loading " + config.rootPackage() + " from " + config.projectDirectory()); + return new ModuleLoader(config, parserCollectionStrategy).loadModules(); } catch (IOException e) { - logger.error("Error while loading " + rootPackage + " from " + projectDirectory, e); + logger.error("Error while loading " + config.rootPackage() + " from " + config.projectDirectory(), e); throw new UncheckedIOException(e); } } diff --git a/heo-core/src/main/java/dev/heowc/heo/core/loader/domain/ModuleLoader.java b/heo-core/src/main/java/dev/heowc/heo/core/loader/domain/ModuleLoader.java index 1b9b2e2..199da82 100644 --- a/heo-core/src/main/java/dev/heowc/heo/core/loader/domain/ModuleLoader.java +++ b/heo-core/src/main/java/dev/heowc/heo/core/loader/domain/ModuleLoader.java @@ -5,6 +5,9 @@ import java.util.List; import java.util.stream.Stream; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import com.github.javaparser.ParseResult; import com.github.javaparser.ast.CompilationUnit; import com.github.javaparser.utils.ParserCollectionStrategy; @@ -12,9 +15,7 @@ import com.github.javaparser.utils.SourceRoot; import dev.heowc.heo.core.Module; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import dev.heowc.heo.core.loader.ModuleLoaderConfig; public class ModuleLoader { @@ -22,21 +23,29 @@ public class ModuleLoader { private final Path projectPath; private final String rootPackage; + private final ParserCollectionStrategy parserCollectionStrategy; + + public ModuleLoader(ModuleLoaderConfig config, ParserCollectionStrategy parserCollectionStrategy) { + this.projectPath = Path.of(config.projectDirectory()).toAbsolutePath(); + this.rootPackage = config.rootPackage(); + this.parserCollectionStrategy = parserCollectionStrategy; + } public ModuleLoader(String projectDirectory, String rootPackage) { - this.projectPath = Path.of(projectDirectory).toAbsolutePath(); - this.rootPackage = rootPackage; + this(new ModuleLoaderConfig(projectDirectory, rootPackage), + new ParserCollectionStrategy()); } public List loadModules() throws IOException { - final ProjectRoot projectRoot = new ParserCollectionStrategy().collect(projectPath); + final ProjectRoot projectRoot = parserCollectionStrategy.collect(projectPath); return projectRoot.getSourceRoots() .stream() .filter(ModuleLoader::ignoreNonMainSourceRoot) - .peek(it -> logger.info("Detected module (file://{})", it.getRoot())) + .peek(it -> logger.info("Detected source (file://{})", it.getRoot())) .flatMap(this::tryParseSources) .filter(it -> ignoreFile(it.getStorage().orElseThrow().getPath())) .map(ModuleLoader::extractModule) + .peek(it -> logger.debug("Extract module ({})", it)) .toList(); } diff --git a/heo-gradle-plugin/src/main/java/dev/heowc/heo/gradle/HeoPlugin.java b/heo-gradle-plugin/src/main/java/dev/heowc/heo/gradle/HeoPlugin.java index 22f9bee..3da208b 100644 --- a/heo-gradle-plugin/src/main/java/dev/heowc/heo/gradle/HeoPlugin.java +++ b/heo-gradle-plugin/src/main/java/dev/heowc/heo/gradle/HeoPlugin.java @@ -8,7 +8,11 @@ import java.nio.file.StandardCopyOption; import java.util.Collection; import java.util.List; +import java.util.Map; +import java.util.Map.Entry; import java.util.Objects; +import java.util.regex.Pattern; +import java.util.stream.Collectors; import java.util.stream.Stream; import javax.annotation.Nullable; @@ -21,6 +25,8 @@ public class HeoPlugin implements Plugin { private static final String REPORT_PATH = "build/reports/heo"; + private static final Pattern DOT_PATTERN = Pattern.compile("\\."); + private static final Pattern EQ_PATTERN = Pattern.compile("="); @Override public void apply(Project project) { @@ -43,18 +49,16 @@ public void apply(Project project) { task.setMain("-jar"); task.args(tempJar.getAbsolutePath()); task.args(arguments(project, config)); - + task.environment(environments(project, config)); tempJar.deleteOnExit(); }); } - private List arguments(Project project, HeoPluginConfig config) { - return Stream.concat(Stream.of("-d", determineDirectory(project, config.getDirectoryPath()), - "-p", determinePrefixPackage(project, config.getPrefixPackage()), - "-o", determineDestination(project, config.getDestination()), - "--failure-on-cycles", String.valueOf(config.isFailureOnCycles())), - logging(project, config.getLogging())) - .toList(); + private static List arguments(Project project, HeoPluginConfig config) { + return List.of("-d", determineDirectory(project, config.getDirectoryPath()), + "-p", determinePrefixPackage(project, config.getPrefixPackage()), + "-o", determineDestination(project, config.getDestination()), + "--failure-on-cycles", String.valueOf(config.isFailureOnCycles())); } private static String determineDirectory(Project project, @Nullable String directoryPath) { @@ -75,15 +79,25 @@ private static String determineDestination(Project project, @Nullable String des : destination; } - private Stream logging(Project project, @Nullable List logging) { + private static Map environments(Project project, HeoPluginConfig config) { + return logging(project, config.getLogging()) + .map(String::toUpperCase) + .map(it -> DOT_PATTERN.matcher(it).replaceAll("_")) + .map(it -> { + final String[] keyValue = EQ_PATTERN.split(it); + return Map.entry(keyValue[0], keyValue[1]); + }).collect(Collectors.toUnmodifiableMap(Entry::getKey, Entry::getValue)); + } + + private static Stream logging(Project project, @Nullable List logging) { if (project.getGradle().getStartParameter().getLogLevel() == LogLevel.DEBUG) { - return Stream.of("-Dlogging.level.root=DEBUG"); + return Stream.of("logging.level.root=DEBUG"); } return Stream.ofNullable(logging) .filter(Objects::nonNull) .flatMap(Collection::stream) .filter(Objects::nonNull) - .map(it -> "-Dlogging.level." + it); + .map(it -> "logging.level." + it); } } diff --git a/it/cycled-gradle-plugin/build.gradle b/it/cycled-gradle-plugin/build.gradle index 38f9d77..bd2bbcf 100644 --- a/it/cycled-gradle-plugin/build.gradle +++ b/it/cycled-gradle-plugin/build.gradle @@ -29,7 +29,8 @@ if (project.hasProperty('localPlugin')) { var failure = false try { tasks.heoReport.exec() - } catch (Exception e) { + } catch (Exception ignored) { + println("heoReport task failed") failure = true } if (!failure) { diff --git a/it/gradle-plugin/build.gradle b/it/gradle-plugin/build.gradle index fea3fa9..7f793a3 100644 --- a/it/gradle-plugin/build.gradle +++ b/it/gradle-plugin/build.gradle @@ -27,6 +27,7 @@ if (project.hasProperty('localPlugin')) { doLast { try { tasks.heoReport.exec() + println("heoReport task successful") } catch (Exception e) { throw new IllegalStateException("The task did not succeed", e) }