33
44import 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 ;
616import java .io .Serializable ;
717import java .util .ArrayList ;
8- import java .util .Arrays ;
918import java .util .Collections ;
19+ import java .util .LinkedHashMap ;
1020import java .util .List ;
21+ import java .util .Map ;
1122import java .util .Objects ;
23+ import java .util .Optional ;
24+ import java .util .stream .Collectors ;
1225import org .jspecify .annotations .Nullable ;
1326
1427public 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
0 commit comments