Skip to content

Commit a680143

Browse files
committed
fix: Fixes dependent source discovery
Parent directories for sources are now added to the compiler's source path so any types referenced in them that are available in the same directories can be found even when they are not explicitely mentioned in any `//SOURCES` lines. This also fixes the problem where adding a `//DEPS` line would cause the compiler to be unable to find those same types. Fixes #1502
1 parent 192972e commit a680143

File tree

9 files changed

+120
-2
lines changed

9 files changed

+120
-2
lines changed

itests/extending/Bar.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package extending;
2+
3+
public class Bar {}

itests/extending/Foo.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
///usr/bin/env jbang "$0" "$@" ; exit $?
2+
///DEPS com.github.lalyos:jfiglet:0.0.9
3+
4+
package extending;
5+
6+
public class Foo extends Bar {
7+
public static void main(String... args) {
8+
System.out.println("hello JBang");
9+
}
10+
}

src/main/java/dev/jbang/dependencies/ModularClassPath.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,16 @@ public List<String> getClassPaths() {
5050

5151
public String getClassPath() {
5252
if (classPath == null) {
53-
classPath = String.join(CP_SEPARATOR, getClassPaths());
53+
classPath = toClassPath(getClassPaths());
5454
}
5555

5656
return classPath;
5757
}
5858

59+
public static String toClassPath(List<String> pathElements) {
60+
return String.join(CP_SEPARATOR, pathElements);
61+
}
62+
5963
public String getManifestPath() {
6064
if (manifestPath == null) {
6165
manifestPath = artifacts.stream()

src/main/java/dev/jbang/source/ResourceRef.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ public boolean isStdin() {
3535
return originalResource != null && isStdin(originalResource);
3636
}
3737

38+
public boolean isFile() {
39+
return originalResource != null && Util.isValidPath(originalResource);
40+
}
41+
3842
@Nullable
3943
public Path getFile() {
4044
return file;

src/main/java/dev/jbang/source/Source.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
package dev.jbang.source;
22

3+
import java.nio.file.Path;
34
import java.util.Arrays;
5+
import java.util.Collections;
46
import java.util.List;
57
import java.util.Optional;
68
import java.util.function.Function;
79
import java.util.stream.Collectors;
810
import java.util.stream.Stream;
911

1012
import javax.annotation.Nonnull;
13+
import javax.annotation.Nullable;
1114

1215
import dev.jbang.cli.BaseCommand;
1316
import dev.jbang.cli.ExitException;
@@ -87,6 +90,29 @@ public ResourceRef getResourceRef() {
8790
return resourceRef;
8891
}
8992

93+
@Nullable
94+
public ResourceRef getSourceDirRef() {
95+
if (contents != null && resourceRef.isFile()) {
96+
Path parent = getResourceRef().getFile().getParent();
97+
Optional<String> pkg = getJavaPackage();
98+
if (pkg.isPresent()) {
99+
String[] elems = pkg.get().split("\\.");
100+
Collections.reverse(Arrays.asList(elems));
101+
for (String elem : elems) {
102+
if (parent != null && !elem.equals(parent.getFileName().toString())) {
103+
// if path doesn't match package we return null
104+
return null;
105+
}
106+
parent = parent.getParent();
107+
}
108+
}
109+
return ResourceRef.forFile(parent);
110+
} else {
111+
// If the resource isn't a local file we return null
112+
return null;
113+
}
114+
}
115+
90116
public Optional<String> getJavaPackage() {
91117
if (contents != null) {
92118
return Util.getSourcePackage(contents);
@@ -145,6 +171,10 @@ public Project updateProject(Project prj, ResourceResolver resolver) {
145171
if (!prj.getMainSourceSet().getSources().contains(getResourceRef())) {
146172
SourceSet ss = prj.getMainSourceSet();
147173
ss.addSource(this.getResourceRef());
174+
ResourceRef srcDir = getSourceDirRef();
175+
if (srcDir != null) {
176+
ss.addSourceDir(srcDir);
177+
}
148178
ss.addResources(tagReader.collectFiles(resourceRef,
149179
new SiblingResourceResolver(resourceRef, ResourceResolver.forResources())));
150180
ss.addDependencies(collectDependencies());

src/main/java/dev/jbang/source/SourceSet.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
import java.util.ArrayList;
55
import java.util.Collection;
66
import java.util.Collections;
7+
import java.util.HashSet;
78
import java.util.List;
9+
import java.util.Set;
810
import java.util.stream.Stream;
911

1012
import javax.annotation.Nonnull;
@@ -21,6 +23,7 @@
2123
public class SourceSet {
2224
private final List<ResourceRef> sources = new ArrayList<>();
2325
private final List<RefTarget> resources = new ArrayList<>();
26+
private final Set<ResourceRef> sourceDirs = new HashSet<>();
2427
private final List<String> dependencies = new ArrayList<>();
2528
private final List<String> classPaths = new ArrayList<>();
2629
private final List<String> compileOptions = new ArrayList<>();
@@ -67,6 +70,23 @@ public SourceSet addResources(Collection<RefTarget> resources) {
6770
return this;
6871
}
6972

73+
@Nonnull
74+
public Set<ResourceRef> getSourceDirs() {
75+
return Collections.unmodifiableSet(sourceDirs);
76+
}
77+
78+
@Nonnull
79+
public SourceSet addSourceDir(ResourceRef sourceDir) {
80+
sourceDirs.add(sourceDir);
81+
return this;
82+
}
83+
84+
@Nonnull
85+
public SourceSet addSourceDirs(Collection<ResourceRef> sourceDirs) {
86+
this.sourceDirs.addAll(sourceDirs);
87+
return this;
88+
}
89+
7090
@Nonnull
7191
public List<String> getDependencies() {
7292
return Collections.unmodifiableList(dependencies);

src/main/java/dev/jbang/source/buildsteps/CompileBuildStep.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
import dev.jbang.cli.ExitException;
1212
import dev.jbang.dependencies.MavenCoordinate;
13+
import dev.jbang.dependencies.ModularClassPath;
1314
import dev.jbang.source.Builder;
1415
import dev.jbang.source.Project;
1516
import dev.jbang.util.CommandBuffer;
@@ -42,10 +43,22 @@ protected Project compile() throws IOException {
4243
optionList.addAll(project.getMainSourceSet().getCompileOptions());
4344
String path = project.resolveClassPath().getClassPath();
4445
if (!Util.isBlankString(path)) {
45-
optionList.addAll(Arrays.asList("-classpath", path));
46+
optionList.add("-classpath");
47+
optionList.add(path);
4648
}
4749
optionList.addAll(Arrays.asList("-d", compileDir.toAbsolutePath().toString()));
4850

51+
// add -sourcepath for all source folders
52+
List<String> srcDirs = project .getMainSourceSet()
53+
.getSourceDirs()
54+
.stream()
55+
.map(d -> d.getFile().toString())
56+
.collect(Collectors.toList());
57+
if (!srcDirs.isEmpty()) {
58+
optionList.add("-sourcepath");
59+
optionList.add(ModularClassPath.toClassPath(srcDirs));
60+
}
61+
4962
// add source files to compile
5063
optionList.addAll(project .getMainSourceSet()
5164
.getSources()

src/main/java/dev/jbang/source/generators/JshCmdGenerator.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
import org.apache.commons.text.StringEscapeUtils;
1414

15+
import dev.jbang.dependencies.ModularClassPath;
1516
import dev.jbang.source.*;
1617
import dev.jbang.util.JavaUtil;
1718
import dev.jbang.util.Util;
@@ -98,6 +99,17 @@ protected List<String> generateCommandLineList() throws IOException {
9899
fullArgs.addAll(optionalArgs);
99100

100101
if (project.isJShell()) {
102+
// add -sourcepath for all source folders
103+
List<String> srcDirs = project .getMainSourceSet()
104+
.getSourceDirs()
105+
.stream()
106+
.map(d -> d.getFile().toString())
107+
.collect(Collectors.toList());
108+
if (!srcDirs.isEmpty()) {
109+
fullArgs.add("-C-sourcepath");
110+
fullArgs.add(ModularClassPath.toClassPath(srcDirs));
111+
}
112+
101113
ArrayList<ResourceRef> revSources = new ArrayList<>(project.getMainSourceSet().getSources());
102114
Collections.reverse(revSources);
103115
for (ResourceRef s : revSources) {

src/test/java/dev/jbang/source/TestBuilder.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,7 @@ void testAdditionalSourcesFolder() throws IOException {
204204
Util.setCwd(examplesTestFolder);
205205
String mainFile = examplesTestFolder.resolve("foo.java").toString();
206206
String incFile = examplesTestFolder.resolve("bar/Bar.java").toString();
207+
String srcPath = examplesTestFolder.resolve("bar") + File.pathSeparator + examplesTestFolder;
207208

208209
ProjectBuilder pb = ProjectBuilder.create();
209210
pb.additionalSources(Arrays.asList("bar"));
@@ -217,6 +218,7 @@ protected Builder<Project> getCompileBuildStep() {
217218
protected void runCompiler(List<String> optionList) {
218219
assertThat(optionList, hasItem(mainFile));
219220
assertThat(optionList, hasItem(incFile));
221+
assertThat(optionList, hasItems("-sourcepath", srcPath));
220222
// Skip the compiler
221223
}
222224
};
@@ -490,4 +492,24 @@ protected void runNativeBuilder(List<String> optionList) throws IOException {
490492
}
491493
}.setFresh(true).build();
492494
}
495+
496+
@Test
497+
void testMultiSourceWithDeps() throws IOException {
498+
Path foo = examplesTestFolder.resolve("extending").resolve("Foo.java");
499+
ProjectBuilder pb = ProjectBuilder.create();
500+
Project prj = pb.build(foo.toString());
501+
502+
new JavaSource.JavaAppBuilder(prj) {
503+
@Override
504+
protected Builder<Project> getCompileBuildStep() {
505+
return new JavaCompileBuildStep() {
506+
@Override
507+
protected void runCompiler(List<String> optionList) {
508+
assertThat(optionList, hasItems("-sourcepath", examplesTestFolder.toString(), foo.toString()));
509+
// Skip the compiler
510+
}
511+
};
512+
}
513+
}.setFresh(true).build();
514+
}
493515
}

0 commit comments

Comments
 (0)