Skip to content

Commit ec24833

Browse files
committed
Use javaparser.org to parse module-info.java
1 parent db04701 commit ec24833

File tree

5 files changed

+97
-44
lines changed

5 files changed

+97
-44
lines changed

build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ configurations.compileClasspath {
1111

1212
dependencies {
1313
implementation("org.ow2.asm:asm:9.9")
14+
implementation("com.github.javaparser:javaparser-core:3.28.0")
1415
compileOnly("org.gradlex:extra-java-module-info:1.13.1")
1516
compileOnly("com.autonomousapps:dependency-analysis-gradle-plugin:3.5.1")
1617
}

gradle/verification-keyring.keys

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1754,3 +1754,16 @@ CgkQuhmUn6JgkhZmBQEA3b5QhIg4LhToSGJ0sI3mPr270z+Sefyl/L8s2i7ZJKEA
17541754
/1su4aPLl+FaeuZHpInOy991PXFh+IJICL1irc2DfV4G
17551755
=stfL
17561756
-----END PGP PUBLIC KEY BLOCK-----
1757+
1758+
id 6DE9B8077FBB2F8A019F4904BD17A565509DEE20
1759+
uid jean-pierre.lerbscher@jperf.com
1760+
-----BEGIN PGP PUBLIC KEY BLOCK-----
1761+
1762+
xjMEZl2j9RYJKwYBBAHaRw8BAQdAPzZyNkr92xKYzBrTOsN8Fwy9l2W0ez4Hu0t3
1763+
/MoohtG0H2plYW4tcGllcnJlLmxlcmJzY2hlckBqcGVyZi5jb23OOARmXaP1Egor
1764+
BgEEAZdVAQUBAQdAoTUzjZPhQLyzRo9jIO8TrgC+mfazNL5gB+fOWhB//T4DAQgH
1765+
wn4EGBYKACYWIQRt6bgHf7svigGfSQS9F6VlUJ3uIAUCZl2j9QIbDAUJBaOKqwAK
1766+
CRC9F6VlUJ3uIIpxAP9MihNcqlK2wPp2uURiLmw16dN3o50gxWeLMjBxethg0gD/
1767+
VLRHao8huHsPY9XMrgbHSNLZOT7geBJOdvwrTRTy3A0=
1768+
=BzAO
1769+
-----END PGP PUBLIC KEY BLOCK-----

gradle/verification-metadata.xml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,11 @@
1717
<trust file="asciidoctor-gradle-jvm-4.0.5.jar"/>
1818
</trusted-artifacts>
1919
<trusted-keys>
20-
<!-- PRODUCTION CODE: ASM -->
20+
<!-- PRODUCTION CODE -->
2121
<!-- ✅ Signed by Eric Bruneton - ASM -->
2222
<trusted-key id="A5BD02B93E7A40482EB1D66A5F69AD087600B22C" group="org.ow2.asm" name="asm"/>
23+
<!-- ✅ Signed by Jean Pierre Lerbscher - JAVA PARSER -->
24+
<trusted-key id="6DE9B8077FBB2F8A019F4904BD17A565509DEE20" group="com.github.javaparser" name="javaparser-core"/>
2325
<!-- ✅ Signed by Tony Robalik - DAGP -->
2426
<trusted-key id="CF4B3A3F53BEF9A2CE2CBFB895962C5E716C39AA" group="com.autonomousapps" name="dependency-analysis-gradle-plugin"/>
2527
<!-- ✅ Signed by Square (squareup.com) -->

src/main/java/org/gradlex/javamodule/dependencies/internal/utils/ModuleInfo.java

Lines changed: 76 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,25 @@
33

44
import static org.gradlex.javamodule.dependencies.internal.utils.ModuleNamingUtil.sourceSetToModuleName;
55

6+
import com.github.javaparser.JavaParser;
7+
import com.github.javaparser.ast.CompilationUnit;
8+
import com.github.javaparser.ast.Node;
9+
import com.github.javaparser.ast.expr.Name;
10+
import com.github.javaparser.ast.modules.ModuleDeclaration;
11+
import com.github.javaparser.ast.modules.ModuleDirective;
12+
import com.github.javaparser.ast.modules.ModuleProvidesDirective;
13+
import com.github.javaparser.ast.modules.ModuleRequiresDirective;
14+
import com.github.javaparser.ast.nodeTypes.NodeWithIdentifier;
15+
import com.github.javaparser.ast.nodeTypes.NodeWithName;
616
import java.io.Serializable;
717
import java.util.ArrayList;
8-
import java.util.Arrays;
918
import java.util.Collections;
19+
import java.util.LinkedHashMap;
1020
import java.util.List;
21+
import java.util.Map;
1122
import java.util.Objects;
23+
import java.util.Optional;
24+
import java.util.stream.Collectors;
1225
import org.jspecify.annotations.Nullable;
1326

1427
public class ModuleInfo implements Serializable {
@@ -29,18 +42,34 @@ public String literal() {
2942

3043
public static final ModuleInfo EMPTY = new ModuleInfo("");
3144

32-
private String moduleName = "";
45+
private final String moduleName;
46+
private final Map<String, String> imports;
3347
private final List<String> requires = new ArrayList<>();
3448
private final List<String> requiresTransitive = new ArrayList<>();
3549
private final List<String> requiresStatic = new ArrayList<>();
3650
private final List<String> requiresStaticTransitive = new ArrayList<>();
3751
private final List<String> requiresRuntime = new ArrayList<>();
52+
private final Map<String, List<String>> provides = new LinkedHashMap<>();
3853

3954
public ModuleInfo(String moduleInfoFileContent) {
40-
boolean insideComment = false;
41-
for (String line : moduleInfoFileContent.split("\n")) {
42-
insideComment = parse(line, insideComment);
43-
}
55+
Optional<CompilationUnit> result =
56+
new JavaParser().parse(moduleInfoFileContent).getResult();
57+
if (!result.isPresent() || !result.get().getModule().isPresent()) {
58+
moduleName = "";
59+
imports = Collections.emptyMap();
60+
return;
61+
}
62+
63+
ModuleDeclaration moduleDeclaration = result.get().getModule().get();
64+
moduleName = moduleDeclaration.getNameAsString();
65+
imports = processImports(result.get());
66+
processDirectives(moduleDeclaration.getDirectives());
67+
}
68+
69+
private Map<String, String> processImports(CompilationUnit cu) {
70+
return cu.getImports().stream()
71+
.map(NodeWithName::getName)
72+
.collect(Collectors.toMap(NodeWithIdentifier::getId, Node::toString));
4473
}
4574

4675
public String getModuleName() {
@@ -66,6 +95,10 @@ public List<String> get(Directive directive) {
6695
return Collections.emptyList();
6796
}
6897

98+
public Map<String, List<String>> getProvides() {
99+
return provides;
100+
}
101+
69102
@Nullable
70103
public String moduleNamePrefix(String projectName, String sourceSetName, boolean fail) {
71104
if (moduleName.equals(projectName)) {
@@ -90,44 +123,47 @@ public String moduleNamePrefix(String projectName, String sourceSetName, boolean
90123
return null;
91124
}
92125

93-
/**
94-
* @return true, if we are inside a multi-line comment after this line
95-
*/
96-
private boolean parse(String moduleLine, boolean insideComment) {
97-
if (insideComment) {
98-
return !moduleLine.contains("*/");
126+
private void processDirectives(List<ModuleDirective> directives) {
127+
for (ModuleDirective d : directives) {
128+
if (d instanceof ModuleRequiresDirective) {
129+
ModuleRequiresDirective directive = (ModuleRequiresDirective) d;
130+
String identifier = directive.getNameAsString();
131+
if (directive.isStatic() && directive.isTransitive()) {
132+
requiresStaticTransitive.add(identifier);
133+
} else if (directive.isTransitive()) {
134+
requiresTransitive.add(identifier);
135+
} else if (directive.isStatic()) {
136+
requiresStatic.add(identifier);
137+
} else if (isRuntime(directive)) {
138+
requiresRuntime.add(identifier);
139+
} else {
140+
requires.add(identifier);
141+
}
142+
}
143+
if (d instanceof ModuleProvidesDirective) {
144+
ModuleProvidesDirective directive = (ModuleProvidesDirective) d;
145+
String name = qualifiedName(directive.getName());
146+
List<String> with = provides.computeIfAbsent(name, k -> new ArrayList<>());
147+
with.addAll(
148+
directive.getWith().stream().map(this::qualifiedName).collect(Collectors.toList()));
149+
}
99150
}
151+
}
100152

101-
List<String> tokens = Arrays.asList(moduleLine
102-
.replace(";", "")
103-
.replace("{", "")
104-
.replace("}", "")
105-
.replace(RUNTIME_KEYWORD, "runtime")
106-
.replaceAll("/\\*.*?\\*/", " ")
107-
.trim()
108-
.split("\\s+"));
109-
int singleLineCommentStartIndex = tokens.indexOf("//");
110-
if (singleLineCommentStartIndex >= 0) {
111-
tokens = tokens.subList(0, singleLineCommentStartIndex);
112-
}
153+
private static boolean isRuntime(ModuleRequiresDirective directive) {
154+
return directive
155+
.getName()
156+
.getComment()
157+
.map(c -> "runtime".equals(c.getContent().trim()))
158+
.orElse(false);
159+
}
113160

114-
if (tokens.contains("module")) {
115-
moduleName = tokens.get(tokens.size() - 1);
116-
}
117-
if (tokens.size() > 1 && tokens.get(0).equals("requires")) {
118-
if (tokens.size() > 3 && tokens.contains("static") && tokens.contains("transitive")) {
119-
requiresStaticTransitive.add(tokens.get(3));
120-
} else if (tokens.size() > 2 && tokens.contains("transitive")) {
121-
requiresTransitive.add(tokens.get(2));
122-
} else if (tokens.size() > 2 && tokens.contains("static")) {
123-
requiresStatic.add(tokens.get(2));
124-
} else if (tokens.size() > 2 && tokens.contains("runtime")) {
125-
requiresRuntime.add(tokens.get(2));
126-
} else {
127-
requires.add(tokens.get(1));
128-
}
161+
private String qualifiedName(Name name) {
162+
if (imports.containsKey(name.getId())) {
163+
return imports.get(name.getId());
164+
} else {
165+
return name.toString();
129166
}
130-
return moduleLine.lastIndexOf("/*") > moduleLine.lastIndexOf("*/");
131167
}
132168

133169
@Override

src/main/java/org/gradlex/javamodule/dependencies/internal/utils/ModuleInfoCache.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,11 +101,12 @@ public Collection<LocalModule> getAllLocalModules() {
101101
}
102102

103103
private boolean maybePutModuleInfo(File folder, ProviderFactory providers) {
104+
if (moduleInfo.containsKey(folder)) {
105+
return true;
106+
}
104107
Provider<ModuleInfo> moduleInfoProvider = provideModuleInfo(folder, providers);
105108
if (moduleInfoProvider.isPresent()) {
106-
if (!moduleInfo.containsKey(folder)) {
107-
moduleInfo.put(folder, moduleInfoProvider.get());
108-
}
109+
moduleInfo.put(folder, moduleInfoProvider.get());
109110
return true;
110111
}
111112
return false;

0 commit comments

Comments
 (0)