Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ configurations.compileClasspath {

dependencies {
implementation("org.ow2.asm:asm:9.9")
implementation("com.github.javaparser:javaparser-core:3.28.0")
compileOnly("org.gradlex:extra-java-module-info:1.13.1")
compileOnly("com.autonomousapps:dependency-analysis-gradle-plugin:3.5.1")
}
Expand Down
13 changes: 13 additions & 0 deletions gradle/verification-keyring.keys
Original file line number Diff line number Diff line change
Expand Up @@ -1754,3 +1754,16 @@ CgkQuhmUn6JgkhZmBQEA3b5QhIg4LhToSGJ0sI3mPr270z+Sefyl/L8s2i7ZJKEA
/1su4aPLl+FaeuZHpInOy991PXFh+IJICL1irc2DfV4G
=stfL
-----END PGP PUBLIC KEY BLOCK-----

id 6DE9B8077FBB2F8A019F4904BD17A565509DEE20
uid jean-pierre.lerbscher@jperf.com
-----BEGIN PGP PUBLIC KEY BLOCK-----

xjMEZl2j9RYJKwYBBAHaRw8BAQdAPzZyNkr92xKYzBrTOsN8Fwy9l2W0ez4Hu0t3
/MoohtG0H2plYW4tcGllcnJlLmxlcmJzY2hlckBqcGVyZi5jb23OOARmXaP1Egor
BgEEAZdVAQUBAQdAoTUzjZPhQLyzRo9jIO8TrgC+mfazNL5gB+fOWhB//T4DAQgH
wn4EGBYKACYWIQRt6bgHf7svigGfSQS9F6VlUJ3uIAUCZl2j9QIbDAUJBaOKqwAK
CRC9F6VlUJ3uIIpxAP9MihNcqlK2wPp2uURiLmw16dN3o50gxWeLMjBxethg0gD/
VLRHao8huHsPY9XMrgbHSNLZOT7geBJOdvwrTRTy3A0=
=BzAO
-----END PGP PUBLIC KEY BLOCK-----
4 changes: 3 additions & 1 deletion gradle/verification-metadata.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@
<trust file="asciidoctor-gradle-jvm-4.0.5.jar"/>
</trusted-artifacts>
<trusted-keys>
<!-- PRODUCTION CODE: ASM -->
<!-- PRODUCTION CODE -->
<!-- ✅ Signed by Eric Bruneton - ASM -->
<trusted-key id="A5BD02B93E7A40482EB1D66A5F69AD087600B22C" group="org.ow2.asm" name="asm"/>
<!-- ✅ Signed by Jean Pierre Lerbscher - JAVA PARSER -->
<trusted-key id="6DE9B8077FBB2F8A019F4904BD17A565509DEE20" group="com.github.javaparser" name="javaparser-core"/>
<!-- ✅ Signed by Tony Robalik - DAGP -->
<trusted-key id="CF4B3A3F53BEF9A2CE2CBFB895962C5E716C39AA" group="com.autonomousapps" name="dependency-analysis-gradle-plugin"/>
<!-- ✅ Signed by Square (squareup.com) -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,25 @@

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

import com.github.javaparser.JavaParser;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.Node;
import com.github.javaparser.ast.expr.Name;
import com.github.javaparser.ast.modules.ModuleDeclaration;
import com.github.javaparser.ast.modules.ModuleDirective;
import com.github.javaparser.ast.modules.ModuleProvidesDirective;
import com.github.javaparser.ast.modules.ModuleRequiresDirective;
import com.github.javaparser.ast.nodeTypes.NodeWithIdentifier;
import com.github.javaparser.ast.nodeTypes.NodeWithName;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
import org.jspecify.annotations.Nullable;

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

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

private String moduleName = "";
private final String moduleName;
private final Map<String, String> imports;
private final List<String> requires = new ArrayList<>();
private final List<String> requiresTransitive = new ArrayList<>();
private final List<String> requiresStatic = new ArrayList<>();
private final List<String> requiresStaticTransitive = new ArrayList<>();
private final List<String> requiresRuntime = new ArrayList<>();
private final Map<String, List<String>> provides = new LinkedHashMap<>();

public ModuleInfo(String moduleInfoFileContent) {
boolean insideComment = false;
for (String line : moduleInfoFileContent.split("\n")) {
insideComment = parse(line, insideComment);
}
Optional<CompilationUnit> result =
new JavaParser().parse(moduleInfoFileContent).getResult();
if (!result.isPresent() || !result.get().getModule().isPresent()) {
moduleName = "";
imports = Collections.emptyMap();
return;
}

ModuleDeclaration moduleDeclaration = result.get().getModule().get();
moduleName = moduleDeclaration.getNameAsString();
imports = processImports(result.get());
processDirectives(moduleDeclaration.getDirectives());
}

private Map<String, String> processImports(CompilationUnit cu) {
return cu.getImports().stream()
.map(NodeWithName::getName)
.collect(Collectors.toMap(NodeWithIdentifier::getId, Node::toString));
}

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

public Map<String, List<String>> getProvides() {
return provides;
}

@Nullable
public String moduleNamePrefix(String projectName, String sourceSetName, boolean fail) {
if (moduleName.equals(projectName)) {
Expand All @@ -90,44 +123,47 @@ public String moduleNamePrefix(String projectName, String sourceSetName, boolean
return null;
}

/**
* @return true, if we are inside a multi-line comment after this line
*/
private boolean parse(String moduleLine, boolean insideComment) {
if (insideComment) {
return !moduleLine.contains("*/");
private void processDirectives(List<ModuleDirective> directives) {
for (ModuleDirective d : directives) {
if (d instanceof ModuleRequiresDirective) {
ModuleRequiresDirective directive = (ModuleRequiresDirective) d;
String identifier = directive.getNameAsString();
if (directive.isStatic() && directive.isTransitive()) {
requiresStaticTransitive.add(identifier);
} else if (directive.isTransitive()) {
requiresTransitive.add(identifier);
} else if (directive.isStatic()) {
requiresStatic.add(identifier);
} else if (isRuntime(directive)) {
requiresRuntime.add(identifier);
} else {
requires.add(identifier);
}
}
if (d instanceof ModuleProvidesDirective) {
ModuleProvidesDirective directive = (ModuleProvidesDirective) d;
String name = qualifiedName(directive.getName());
List<String> with = provides.computeIfAbsent(name, k -> new ArrayList<>());
with.addAll(
directive.getWith().stream().map(this::qualifiedName).collect(Collectors.toList()));
}
}
}

List<String> tokens = Arrays.asList(moduleLine
.replace(";", "")
.replace("{", "")
.replace("}", "")
.replace(RUNTIME_KEYWORD, "runtime")
.replaceAll("/\\*.*?\\*/", " ")
.trim()
.split("\\s+"));
int singleLineCommentStartIndex = tokens.indexOf("//");
if (singleLineCommentStartIndex >= 0) {
tokens = tokens.subList(0, singleLineCommentStartIndex);
}
private static boolean isRuntime(ModuleRequiresDirective directive) {
return directive
.getName()
.getComment()
.map(c -> "runtime".equals(c.getContent().trim()))
.orElse(false);
}

if (tokens.contains("module")) {
moduleName = tokens.get(tokens.size() - 1);
}
if (tokens.size() > 1 && tokens.get(0).equals("requires")) {
if (tokens.size() > 3 && tokens.contains("static") && tokens.contains("transitive")) {
requiresStaticTransitive.add(tokens.get(3));
} else if (tokens.size() > 2 && tokens.contains("transitive")) {
requiresTransitive.add(tokens.get(2));
} else if (tokens.size() > 2 && tokens.contains("static")) {
requiresStatic.add(tokens.get(2));
} else if (tokens.size() > 2 && tokens.contains("runtime")) {
requiresRuntime.add(tokens.get(2));
} else {
requires.add(tokens.get(1));
}
private String qualifiedName(Name name) {
if (imports.containsKey(name.getId())) {
return imports.get(name.getId());
} else {
return name.toString();
}
return moduleLine.lastIndexOf("/*") > moduleLine.lastIndexOf("*/");
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,11 +101,12 @@ public Collection<LocalModule> getAllLocalModules() {
}

private boolean maybePutModuleInfo(File folder, ProviderFactory providers) {
if (moduleInfo.containsKey(folder)) {
return true;
}
Provider<ModuleInfo> moduleInfoProvider = provideModuleInfo(folder, providers);
if (moduleInfoProvider.isPresent()) {
if (!moduleInfo.containsKey(folder)) {
moduleInfo.put(folder, moduleInfoProvider.get());
}
moduleInfo.put(folder, moduleInfoProvider.get());
return true;
}
return false;
Expand Down
Loading