multi pom
This commit is contained in:
@@ -87,9 +87,11 @@ public class AnalysisResult {
|
||||
ep.setName(resolver.resolveValue(ep.getName(), properties));
|
||||
}
|
||||
if (ep.getMetadata() != null) {
|
||||
Map<String, String> resolvedMeta = new java.util.HashMap<>();
|
||||
for (var entry : ep.getMetadata().entrySet()) {
|
||||
entry.setValue(resolver.resolveValue(entry.getValue(), properties));
|
||||
resolvedMeta.put(entry.getKey(), resolver.resolveValue(entry.getValue(), properties));
|
||||
}
|
||||
ep.setMetadata(resolvedMeta);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ public class EntryPoint {
|
||||
private String name; // e.g., "POST /orders" or "Kafka Topic: orders"
|
||||
private final String className;
|
||||
private final String methodName;
|
||||
private final String sourceFile;
|
||||
private Map<String, String> metadata; // e.g., path, topic, exchange
|
||||
@Builder.Default
|
||||
private final List<Parameter> parameters = java.util.Collections.emptyList();
|
||||
|
||||
@@ -15,6 +15,7 @@ public class TriggerPoint {
|
||||
private String event;
|
||||
private final String className;
|
||||
private final String methodName;
|
||||
private final String sourceFile;
|
||||
private final String sourceModule;
|
||||
private final String stateMachineId; // Optional: to link to a specific SM instance
|
||||
private final int lineNumber;
|
||||
|
||||
@@ -82,40 +82,49 @@ public class SiblingDependencyResolver {
|
||||
Set<Path> siblings = new HashSet<>();
|
||||
Path pom = projectDir.resolve("pom.xml");
|
||||
if (Files.exists(pom)) {
|
||||
log.info("Found pom.xml at {}", pom);
|
||||
String content = Files.readString(pom);
|
||||
Matcher matcher = MAVEN_DEPENDENCY.matcher(content);
|
||||
|
||||
Set<String> targetArtifacts = new HashSet<>();
|
||||
while (matcher.find()) {
|
||||
targetArtifacts.add(matcher.group(2)); // Just tracking artifactId for simplicity
|
||||
Matcher matcher = Pattern.compile("<artifactId>(.*?)</artifactId>").matcher(content);
|
||||
// We want artifacts from the <dependencies> section
|
||||
int depsStart = content.indexOf("<dependencies>");
|
||||
int depsEnd = content.indexOf("</dependencies>");
|
||||
if (depsStart != -1 && depsEnd > depsStart) {
|
||||
String depsContent = content.substring(depsStart, depsEnd);
|
||||
Matcher depMatcher = Pattern.compile("<artifactId>(.*?)</artifactId>").matcher(depsContent);
|
||||
while (depMatcher.find()) {
|
||||
targetArtifacts.add(depMatcher.group(1));
|
||||
}
|
||||
}
|
||||
log.info("Found maven target artifacts: {}", targetArtifacts);
|
||||
|
||||
if (!targetArtifacts.isEmpty()) {
|
||||
Path rootDir = findMavenRoot(projectDir);
|
||||
log.info("Resolved Maven root to: {}", rootDir);
|
||||
if (rootDir != null) {
|
||||
// Find all pom.xml files in the workspace (excluding node_modules, build, etc.)
|
||||
try (Stream<Path> paths = Files.walk(rootDir)) {
|
||||
paths.filter(p -> p.getFileName().toString().equals("pom.xml")
|
||||
&& !p.toString().contains("/target/")
|
||||
&& !p.toString().contains("/node_modules/"))
|
||||
.forEach(p -> {
|
||||
try {
|
||||
String pContent = Files.readString(p);
|
||||
Matcher artMatcher = Pattern.compile("<artifactId>(.*?)</artifactId>").matcher(pContent);
|
||||
if (artMatcher.find()) {
|
||||
String artifactId = artMatcher.group(1);
|
||||
if (targetArtifacts.contains(artifactId)) {
|
||||
Path siblingDir = p.getParent();
|
||||
// Don't add ourselves
|
||||
if (!siblingDir.equals(projectDir)) {
|
||||
log.info("Discovered local Maven sibling dependency: {}", siblingDir);
|
||||
siblings.add(siblingDir);
|
||||
}
|
||||
}
|
||||
List<Path> allPoms = paths.filter(p -> p.getFileName().toString().equals("pom.xml"))
|
||||
.filter(p -> !p.toString().contains("/target/"))
|
||||
.collect(Collectors.toList());
|
||||
log.info("Scanned {} total pom.xml files under {}", allPoms.size(), rootDir);
|
||||
|
||||
for (Path p : allPoms) {
|
||||
try {
|
||||
String pContent = Files.readString(p);
|
||||
String artifactId = extractOwnArtifactId(pContent);
|
||||
log.info("Checking artifactId {} in {}", artifactId, p);
|
||||
if (artifactId != null && targetArtifacts.contains(artifactId)) {
|
||||
Path siblingDir = p.getParent();
|
||||
if (!siblingDir.equals(projectDir)) {
|
||||
log.info("Discovered local Maven sibling dependency: {}", siblingDir);
|
||||
siblings.add(siblingDir);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// ignore
|
||||
}
|
||||
});
|
||||
} catch (IOException e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -123,6 +132,21 @@ public class SiblingDependencyResolver {
|
||||
return siblings;
|
||||
}
|
||||
|
||||
private String extractOwnArtifactId(String pomContent) {
|
||||
// Strip <parent> block if it exists
|
||||
String content = pomContent;
|
||||
int parentEnd = pomContent.indexOf("</parent>");
|
||||
if (parentEnd != -1) {
|
||||
content = pomContent.substring(parentEnd);
|
||||
}
|
||||
|
||||
Matcher matcher = Pattern.compile("<artifactId>(.*?)</artifactId>").matcher(content);
|
||||
if (matcher.find()) {
|
||||
return matcher.group(1);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Path findMavenRoot(Path start) {
|
||||
Path current = start.toAbsolutePath();
|
||||
Path lastPomDir = null;
|
||||
|
||||
@@ -125,6 +125,7 @@ public class GenericEventDetector {
|
||||
.event(eventValue)
|
||||
.className(context.getFqn(type))
|
||||
.methodName(method != null ? method.getName().getIdentifier() : "initializer")
|
||||
.sourceFile(context.getRelativePath(context.getFqn(type)))
|
||||
.lineNumber(cu.getLineNumber(node.getStartPosition()))
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -26,12 +26,52 @@ public class SpringMvcDetector {
|
||||
if (isRestController(node)) {
|
||||
processController(node, entryPoints);
|
||||
}
|
||||
// Support WebFlux RouterFunction beans
|
||||
processRouterFunctions(node, entryPoints);
|
||||
return super.visit(node);
|
||||
}
|
||||
});
|
||||
return entryPoints;
|
||||
}
|
||||
|
||||
private void processRouterFunctions(TypeDeclaration td, List<EntryPoint> entryPoints) {
|
||||
for (MethodDeclaration method : td.getMethods()) {
|
||||
if (isBeanMethod(method) && method.getReturnType2() != null && method.getReturnType2().toString().contains("RouterFunction")) {
|
||||
method.accept(new ASTVisitor() {
|
||||
@Override
|
||||
public boolean visit(MethodInvocation call) {
|
||||
String name = call.getName().getIdentifier();
|
||||
String verb = getHttpVerb(name);
|
||||
if (verb != null && !call.arguments().isEmpty()) {
|
||||
Expression pathArg = (Expression) call.arguments().get(0);
|
||||
String path = constantResolver.resolve(pathArg, context);
|
||||
if (path == null) path = pathArg.toString().replaceAll("\"", "");
|
||||
|
||||
entryPoints.add(EntryPoint.builder()
|
||||
.type(EntryPoint.Type.REST)
|
||||
.name(verb + " " + path)
|
||||
.className(context.getFqn(td))
|
||||
.methodName(method.getName().getIdentifier())
|
||||
.sourceFile(context.getRelativePath(context.getFqn(td)))
|
||||
.metadata(Map.of("path", path, "verb", verb, "style", "WebFlux Functional"))
|
||||
.build());
|
||||
}
|
||||
return super.visit(call);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isBeanMethod(MethodDeclaration method) {
|
||||
for (Object mod : method.modifiers()) {
|
||||
if (mod instanceof Annotation ann && ann.getTypeName().getFullyQualifiedName().endsWith("Bean")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isRestController(TypeDeclaration node) {
|
||||
for (Object modifier : node.modifiers()) {
|
||||
if (modifier instanceof Annotation annotation) {
|
||||
@@ -123,6 +163,7 @@ public class SpringMvcDetector {
|
||||
.name(verb + " " + fullPath)
|
||||
.className(context.getFqn(controller))
|
||||
.methodName(method.getName().getIdentifier())
|
||||
.sourceFile(context.getRelativePath(context.getFqn(controller)))
|
||||
.metadata(metadata)
|
||||
.parameters(parameters)
|
||||
.build();
|
||||
|
||||
@@ -7,19 +7,7 @@ import click.kamil.springstatemachineexporter.model.State;
|
||||
import click.kamil.springstatemachineexporter.model.Transition;
|
||||
import click.kamil.springstatemachineexporter.model.TransitionType;
|
||||
import click.kamil.springstatemachineexporter.ast.common.CodebaseContext;
|
||||
import org.eclipse.jdt.core.dom.ASTVisitor;
|
||||
import org.eclipse.jdt.core.dom.ClassInstanceCreation;
|
||||
import org.eclipse.jdt.core.dom.CompilationUnit;
|
||||
import org.eclipse.jdt.core.dom.Expression;
|
||||
import org.eclipse.jdt.core.dom.IMethodBinding;
|
||||
import org.eclipse.jdt.core.dom.ASTNode;
|
||||
import org.eclipse.jdt.core.dom.LambdaExpression;
|
||||
import org.eclipse.jdt.core.dom.MethodDeclaration;
|
||||
import org.eclipse.jdt.core.dom.MethodInvocation;
|
||||
import org.eclipse.jdt.core.dom.SimpleName;
|
||||
import org.eclipse.jdt.core.dom.ITypeBinding;
|
||||
import org.eclipse.jdt.core.dom.MethodReference;
|
||||
import org.eclipse.jdt.core.dom.TypeDeclaration;
|
||||
import org.eclipse.jdt.core.dom.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
@@ -290,11 +278,30 @@ public class AstTransitionParser {
|
||||
for (MethodDeclaration md : td.getMethods()) {
|
||||
if (md.getName().getIdentifier().equals(binding.getName()) &&
|
||||
md.parameters().size() == binding.getParameterTypes().length) {
|
||||
|
||||
// Special case: if it's a getter/factory for Action/Guard, look into the return statement
|
||||
if (md.getBody() != null) {
|
||||
if (md.getBody().statements().size() == 1) {
|
||||
Object stmt = md.getBody().statements().get(0);
|
||||
if (stmt instanceof org.eclipse.jdt.core.dom.ReturnStatement rs) {
|
||||
Expression retExpr = rs.getExpression();
|
||||
if (isLambdaOrAnonymous(retExpr)) {
|
||||
return retExpr.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return md.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// FALLBACK: Manual resolution by name if binding failed
|
||||
TypeDeclaration currentClass = findEnclosingType(mi);
|
||||
if (currentClass != null) {
|
||||
return resolveMethodManually(mi.getName().getIdentifier(), currentClass, context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -322,12 +329,55 @@ public class AstTransitionParser {
|
||||
return null;
|
||||
}
|
||||
|
||||
private static String resolveMethodManually(String methodName, TypeDeclaration td, CodebaseContext context) {
|
||||
// Search in this class
|
||||
for (MethodDeclaration md : td.getMethods()) {
|
||||
if (md.getName().getIdentifier().equals(methodName)) {
|
||||
// Found it. Apply the return-statement-extraction logic here too
|
||||
if (md.getBody() != null && md.getBody().statements().size() == 1) {
|
||||
Object stmt = md.getBody().statements().get(0);
|
||||
if (stmt instanceof org.eclipse.jdt.core.dom.ReturnStatement rs) {
|
||||
Expression retExpr = rs.getExpression();
|
||||
if (isLambdaOrAnonymous(retExpr)) {
|
||||
return retExpr.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
return md.toString();
|
||||
}
|
||||
}
|
||||
|
||||
// Search in superclass
|
||||
if (td.getSuperclassType() != null) {
|
||||
String superName = td.getSuperclassType().toString();
|
||||
// Try to resolve simple name to FQN if possible, or just search by simple name
|
||||
TypeDeclaration superTd = context.getTypeDeclaration(superName);
|
||||
if (superTd != null) {
|
||||
return resolveMethodManually(methodName, superTd, context);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static TypeDeclaration findEnclosingType(ASTNode node) {
|
||||
ASTNode current = node;
|
||||
while (current != null) {
|
||||
if (current instanceof TypeDeclaration td) return td;
|
||||
current = current.getParent();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void parseGuard(Object arg, Transition t, CompilationUnit cu, CodebaseContext context) {
|
||||
QuotedExpression quotedExpr = QuotedExpression.of(arg);
|
||||
if (quotedExpr != null) {
|
||||
String internalLogic = extractInternalLogic(quotedExpr.getExpression(), cu, context);
|
||||
int lineNumber = cu.getLineNumber(quotedExpr.getExpression().getStartPosition());
|
||||
t.setGuard(Guard.of(quotedExpr.toStringWithoutQuotes(), isLambdaOrAnonymous(quotedExpr.getExpression()), internalLogic, lineNumber));
|
||||
TypeDeclaration td = findEnclosingType(quotedExpr.getExpression());
|
||||
String fqn = td != null ? context.getFqn(td) : null;
|
||||
String sourceFile = fqn != null ? context.getRelativePath(fqn) : null;
|
||||
t.setGuard(Guard.of(quotedExpr.toStringWithoutQuotes(), isLambdaOrAnonymous(quotedExpr.getExpression()), internalLogic, lineNumber, fqn, sourceFile));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -336,7 +386,10 @@ public class AstTransitionParser {
|
||||
if (quotedExpr != null) {
|
||||
String internalLogic = extractInternalLogic(quotedExpr.getExpression(), cu, context);
|
||||
int lineNumber = cu.getLineNumber(quotedExpr.getExpression().getStartPosition());
|
||||
t.getActions().add(Action.of(quotedExpr.toStringWithoutQuotes(), isLambdaOrAnonymous(quotedExpr.getExpression()), internalLogic, lineNumber));
|
||||
TypeDeclaration td = findEnclosingType(quotedExpr.getExpression());
|
||||
String fqn = td != null ? context.getFqn(td) : null;
|
||||
String sourceFile = fqn != null ? context.getRelativePath(fqn) : null;
|
||||
t.getActions().add(Action.of(quotedExpr.toStringWithoutQuotes(), isLambdaOrAnonymous(quotedExpr.getExpression()), internalLogic, lineNumber, fqn, sourceFile));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,9 @@ import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
public class CodebaseContext {
|
||||
private final Map<String, CompilationUnit> classes = new HashMap<>();
|
||||
private final Map<String, Path> classPaths = new HashMap<>();
|
||||
@@ -30,6 +32,23 @@ public class CodebaseContext {
|
||||
private Map<String, Map<String, String>> allProperties = new HashMap<>();
|
||||
private List<LibraryHint> libraryHints = new ArrayList<>();
|
||||
private final ObjectMapper objectMapper = new ObjectMapper();
|
||||
private Path projectRoot;
|
||||
|
||||
public void setProjectRoot(Path root) {
|
||||
this.projectRoot = root;
|
||||
}
|
||||
|
||||
public String getRelativePath(Path fullPath) {
|
||||
if (projectRoot != null && fullPath.isAbsolute() && fullPath.startsWith(projectRoot)) {
|
||||
return projectRoot.relativize(fullPath).toString();
|
||||
}
|
||||
return fullPath.getFileName().toString();
|
||||
}
|
||||
|
||||
public String getRelativePath(String fqn) {
|
||||
Path path = classPaths.get(fqn);
|
||||
return path != null ? getRelativePath(path) : null;
|
||||
}
|
||||
|
||||
public void loadLibraryHints(Path hintsFile) throws IOException {
|
||||
if (Files.exists(hintsFile)) {
|
||||
@@ -83,9 +102,10 @@ public class CodebaseContext {
|
||||
activeIgnore.addAll(customIgnorePatterns);
|
||||
|
||||
List<Path> javaFiles = FileUtils.findFilesWithExtension(rootDirs, ".java", activeIgnore);
|
||||
log.info("CodebaseContext found {} java files across {} root directories", javaFiles.size(), rootDirs.size());
|
||||
for (Path javaFile : javaFiles) {
|
||||
String source = Files.readString(javaFile);
|
||||
CompilationUnit cu = parse(source, javaFile.getFileName().toString());
|
||||
CompilationUnit cu = parse(source, javaFile.toAbsolutePath().toString());
|
||||
allCus.add(cu);
|
||||
|
||||
String packageName = cu.getPackage() != null ? cu.getPackage().getName().getFullyQualifiedName() : "";
|
||||
@@ -97,9 +117,9 @@ public class CodebaseContext {
|
||||
}
|
||||
}
|
||||
|
||||
private void indexType(TypeDeclaration td, String packageName, Path javaFile) {
|
||||
private void indexType(TypeDeclaration td, String parentFqn, Path javaFile) {
|
||||
String simpleName = td.getName().getIdentifier();
|
||||
String fqn = packageName.isEmpty() ? simpleName : packageName + "." + simpleName;
|
||||
String fqn = parentFqn.isEmpty() ? simpleName : parentFqn + "." + simpleName;
|
||||
|
||||
classes.put(fqn, (CompilationUnit) td.getRoot());
|
||||
classPaths.put(fqn, javaFile);
|
||||
@@ -118,6 +138,13 @@ public class CodebaseContext {
|
||||
String itfName = itf.toString();
|
||||
interfaceToImpls.computeIfAbsent(itfName, k -> new ArrayList<>()).add(fqn);
|
||||
}
|
||||
|
||||
// Recursively index nested types
|
||||
for (Object type : td.getTypes()) {
|
||||
if (type instanceof TypeDeclaration nestedTd) {
|
||||
indexType(nestedTd, fqn, javaFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<String> getImplementations(String interfaceName) {
|
||||
@@ -320,25 +347,38 @@ public class CodebaseContext {
|
||||
}
|
||||
|
||||
public String getFqn(TypeDeclaration td) {
|
||||
StringBuilder sb = new StringBuilder(td.getName().getIdentifier());
|
||||
ASTNode current = td.getParent();
|
||||
while (current instanceof TypeDeclaration parent) {
|
||||
sb.insert(0, parent.getName().getIdentifier() + ".");
|
||||
current = parent.getParent();
|
||||
}
|
||||
|
||||
CompilationUnit cu = (CompilationUnit) td.getRoot();
|
||||
String packageName = cu.getPackage() != null ? cu.getPackage().getName().getFullyQualifiedName() : "";
|
||||
String simpleName = td.getName().getIdentifier();
|
||||
return packageName.isEmpty() ? simpleName : packageName + "." + simpleName;
|
||||
String fqn = sb.toString();
|
||||
return packageName.isEmpty() ? fqn : packageName + "." + fqn;
|
||||
}
|
||||
|
||||
private TypeDeclaration findTypeInCu(CompilationUnit cu, String fqn) {
|
||||
String packageName = cu.getPackage() != null ? cu.getPackage().getName().getFullyQualifiedName() : "";
|
||||
for (Object type : cu.types()) {
|
||||
if (type instanceof TypeDeclaration td) {
|
||||
String simpleName = td.getName().getIdentifier();
|
||||
String typeFqn = packageName.isEmpty() ? simpleName : packageName + "." + simpleName;
|
||||
if (typeFqn.equals(fqn))
|
||||
return td;
|
||||
TypeDeclaration found = findNestedType(td, fqn);
|
||||
if (found != null) return found;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private TypeDeclaration findNestedType(TypeDeclaration td, String targetFqn) {
|
||||
if (getFqn(td).equals(targetFqn)) return td;
|
||||
for (TypeDeclaration nested : td.getTypes()) {
|
||||
TypeDeclaration found = findNestedType(nested, targetFqn);
|
||||
if (found != null) return found;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Path getPath(String className) {
|
||||
return classPaths.get(className);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package click.kamil.springstatemachineexporter.model;
|
||||
|
||||
public record Action(String expression, boolean isLambda, String internalLogic, Integer lineNumber) {
|
||||
public static Action of(String expression, boolean isLambda, String internalLogic, Integer lineNumber) {
|
||||
return expression != null ? new Action(expression, isLambda, internalLogic, lineNumber) : null;
|
||||
public record Action(String expression, boolean isLambda, String internalLogic, Integer lineNumber, String className, String sourceFile) {
|
||||
public static Action of(String expression, boolean isLambda, String internalLogic, Integer lineNumber, String className, String sourceFile) {
|
||||
return expression != null ? new Action(expression, isLambda, internalLogic, lineNumber, className, sourceFile) : null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package click.kamil.springstatemachineexporter.model;
|
||||
|
||||
public record Guard(String expression, boolean isLambda, String internalLogic, Integer lineNumber) {
|
||||
public static Guard of(String expression, boolean isLambda, String internalLogic, Integer lineNumber) {
|
||||
return expression != null ? new Guard(expression, isLambda, internalLogic, lineNumber) : null;
|
||||
public record Guard(String expression, boolean isLambda, String internalLogic, Integer lineNumber, String className, String sourceFile) {
|
||||
public static Guard of(String expression, boolean isLambda, String internalLogic, Integer lineNumber, String className, String sourceFile) {
|
||||
return expression != null ? new Guard(expression, isLambda, internalLogic, lineNumber, className, sourceFile) : null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,10 +68,23 @@ public class ExportService {
|
||||
allPaths.add(inputDir);
|
||||
allPaths.addAll(siblingResolver.resolveSiblings(inputDir));
|
||||
|
||||
context.setSourcepath(allPaths.stream()
|
||||
// Find project root (common ancestor)
|
||||
Path projectRoot = inputDir.toAbsolutePath();
|
||||
for (Path p : allPaths) {
|
||||
Path ap = p.toAbsolutePath();
|
||||
while (projectRoot != null && !ap.startsWith(projectRoot)) {
|
||||
projectRoot = projectRoot.getParent();
|
||||
}
|
||||
}
|
||||
context.setProjectRoot(projectRoot);
|
||||
log.info("Project root resolved to: {}", projectRoot);
|
||||
|
||||
List<String> sourcepaths = allPaths.stream()
|
||||
.map(p -> p.resolve("src/main/java").toString())
|
||||
.filter(p -> Files.exists(Path.of(p)))
|
||||
.collect(Collectors.toList()));
|
||||
.collect(Collectors.toList());
|
||||
log.info("Setting JDT sourcepath: {}", sourcepaths);
|
||||
context.setSourcepath(sourcepaths);
|
||||
context.setResolveBindings(true);
|
||||
|
||||
Path hintsFile = inputDir.resolve("hints.json");
|
||||
|
||||
Reference in New Issue
Block a user