1 package com.github.javaparser.modules; 2 3 import com.github.javaparser.*; 4 import com.github.javaparser.ast.CompilationUnit; 5 import com.github.javaparser.ast.expr.IntegerLiteralExpr; 6 import com.github.javaparser.ast.expr.MarkerAnnotationExpr; 7 import com.github.javaparser.ast.expr.Name; 8 import com.github.javaparser.ast.expr.SingleMemberAnnotationExpr; 9 import com.github.javaparser.ast.modules.*; 10 import com.github.javaparser.printer.ConcreteSyntaxModel; 11 import org.junit.jupiter.api.Test; 12 13 import static com.github.javaparser.GeneratedJavaParserConstants.IDENTIFIER; 14 import static com.github.javaparser.ParserConfiguration.LanguageLevel.JAVA_9; 15 import static com.github.javaparser.Providers.provider; 16 import static com.github.javaparser.StaticJavaParser.parseName; 17 import static com.github.javaparser.utils.TestUtils.assertEqualsNoEol; 18 import static com.github.javaparser.utils.Utils.EOL; 19 import static org.assertj.core.api.Assertions.assertThat; 20 import static org.junit.jupiter.api.Assertions.*; 21 22 class ModuleDeclarationTest { 23 public static final JavaParser javaParser = new JavaParser(new ParserConfiguration().setLanguageLevel(JAVA_9)); 24 parse(String code)25 private CompilationUnit parse(String code) { 26 ParseResult<CompilationUnit> result = javaParser.parse(ParseStart.COMPILATION_UNIT, provider(code)); 27 if(!result.isSuccessful()){ 28 System.err.println(result); 29 } 30 return result.getResult().get(); 31 } 32 33 @Test moduleInfoKeywordsAreSeenAsIdentifiers()34 void moduleInfoKeywordsAreSeenAsIdentifiers() { 35 CompilationUnit cu = parse("class module { }"); 36 JavaToken moduleToken = cu.getClassByName("module").get().getName().getTokenRange().get().getBegin(); 37 assertEquals(IDENTIFIER, moduleToken.getKind()); 38 } 39 40 @Test issue988RequireTransitiveShouldRequireAModuleCalledTransitive()41 void issue988RequireTransitiveShouldRequireAModuleCalledTransitive() { 42 CompilationUnit cu = parse("module X { requires transitive; }"); 43 ModuleRequiresDirective requiresTransitive = (ModuleRequiresDirective) cu.getModule().get().getDirectives().get(0); 44 assertEquals("transitive", requiresTransitive.getNameAsString()); 45 assertEquals(IDENTIFIER, requiresTransitive.getName().getTokenRange().get().getBegin().getKind()); 46 } 47 48 @Test jlsExample1()49 void jlsExample1() { 50 CompilationUnit cu = parse( 51 "@Foo(1) @Foo(2) @Bar " + 52 "module M.N {" + 53 " requires A.B;" + 54 " requires transitive C.D;" + 55 " requires static E.F;" + 56 " requires transitive static G.H;" + 57 "" + 58 " exports P.Q;" + 59 " exports R.S to T1.U1, T2.U2;" + 60 "" + 61 " opens P.Q;" + 62 " opens R.S to T1.U1, T2.U2;" + 63 "" + 64 " uses V.W;" + 65 " provides X.Y with Z1.Z2, Z3.Z4;" + 66 "}"); 67 68 ModuleDeclaration module = cu.getModule().get(); 69 assertEquals("M.N", module.getNameAsString()); 70 assertFalse(module.isOpen()); 71 assertThat(module.getAnnotations()).containsExactly( 72 new SingleMemberAnnotationExpr(new Name("Foo"), new IntegerLiteralExpr("1")), 73 new SingleMemberAnnotationExpr(new Name("Foo"), new IntegerLiteralExpr("2")), 74 new MarkerAnnotationExpr(new Name("Bar"))); 75 76 ModuleRequiresDirective moduleRequiresStmt = module.getDirectives().get(0).asModuleRequiresStmt(); 77 assertThat(moduleRequiresStmt.getNameAsString()).isEqualTo("A.B"); 78 assertThat(moduleRequiresStmt.getModifiers()).isEmpty(); 79 80 ModuleExportsDirective moduleExportsStmt = module.getDirectives().get(5).asModuleExportsStmt(); 81 assertThat(moduleExportsStmt.getNameAsString()).isEqualTo("R.S"); 82 assertThat(moduleExportsStmt.getModuleNames()).containsExactly(parseName("T1.U1"), parseName("T2.U2")); 83 84 ModuleOpensDirective moduleOpensStmt = module.getDirectives().get(7).asModuleOpensStmt(); 85 assertThat(moduleOpensStmt.getNameAsString()).isEqualTo("R.S"); 86 assertThat(moduleOpensStmt.getModuleNames()).containsExactly(parseName("T1.U1"), parseName("T2.U2")); 87 88 ModuleUsesDirective moduleUsesStmt = module.getDirectives().get(8).asModuleUsesStmt(); 89 assertThat(moduleUsesStmt.getNameAsString()).isEqualTo("V.W"); 90 91 ModuleProvidesDirective moduleProvidesStmt = module.getDirectives().get(9).asModuleProvidesStmt(); 92 assertThat(moduleProvidesStmt.getNameAsString()).isEqualTo("X.Y"); 93 assertThat(moduleProvidesStmt.getWith()).containsExactly( 94 parseName("Z1.Z2"), 95 parseName("Z3.Z4")); 96 97 } 98 99 @Test jlsExample2HasAnOpenModule()100 void jlsExample2HasAnOpenModule() { 101 CompilationUnit cu = parse("open module M.N {}"); 102 103 ModuleDeclaration module = cu.getModule().get(); 104 assertEquals("M.N", module.getNameAsString()); 105 assertTrue(module.isOpen()); 106 } 107 108 @Test testPrettyPrinting()109 void testPrettyPrinting() { 110 CompilationUnit cu = parse( 111 "@Foo(1) @Foo(2) @Bar " + 112 "module M.N {" + 113 " requires A.B;" + 114 " requires transitive C.D;" + 115 " requires static E.F;" + 116 " requires static transitive G.H;" + 117 "" + 118 " exports P.Q;" + 119 " exports R.S to T1.U1, T2.U2;" + 120 "" + 121 " opens P.Q;" + 122 " opens R.S to T1.U1, T2.U2;" + 123 "" + 124 " uses V.W;" + 125 " provides X.Y with Z1.Z2, Z3.Z4;" + 126 "}"); 127 128 assertEquals( 129 "@Foo(1)" + EOL + 130 "@Foo(2)" + EOL + 131 "@Bar" + EOL + 132 "module M.N {" + EOL + 133 " requires A.B;" + EOL + 134 " requires transitive C.D;" + EOL + 135 " requires static E.F;" + EOL + 136 " requires static transitive G.H;" + EOL + 137 " exports P.Q;" + EOL + 138 " exports R.S to T1.U1, T2.U2;" + EOL + 139 " opens P.Q;" + EOL + 140 " opens R.S to T1.U1, T2.U2;" + EOL + 141 " uses V.W;" + EOL + 142 " provides X.Y with Z1.Z2, Z3.Z4;" + EOL + 143 "}" + EOL, cu.toString()); 144 145 } 146 147 @Test testCsmPrinting()148 void testCsmPrinting() { 149 CompilationUnit cu = parse( 150 "@Foo(1) @Foo(2) @Bar " + 151 "open module M.N {" + 152 " requires A.B;" + 153 " requires transitive C.D;" + 154 " requires static E.F;" + 155 " requires transitive static G.H;" + 156 "" + 157 " exports P.Q;" + 158 " exports R.S to T1.U1, T2.U2;" + 159 "" + 160 " opens P.Q;" + 161 " opens R.S to T1.U1, T2.U2;" + 162 "" + 163 " uses V.W;" + 164 " provides X.Y with Z1.Z2, Z3.Z4;" + 165 "}"); 166 167 assertEquals( 168 "@Foo(1)" + EOL + 169 "@Foo(2)" + EOL + 170 "@Bar" + EOL + 171 "open module M.N {" + EOL + 172 " requires A.B;" + EOL + 173 " requires transitive C.D;" + EOL + 174 " requires static E.F;" + EOL + 175 " requires transitive static G.H;" + EOL + 176 " exports P.Q;" + EOL + 177 " exports R.S to T1.U1, T2.U2;" + EOL + 178 " opens P.Q;" + EOL + 179 " opens R.S to T1.U1, T2.U2;" + EOL + 180 " uses V.W;" + EOL + 181 " provides X.Y with Z1.Z2, Z3.Z4;" + EOL + 182 "}" + EOL, ConcreteSyntaxModel.genericPrettyPrint(cu)); 183 184 } 185 186 @Test fluentInterface()187 void fluentInterface() { 188 ModuleDeclaration moduleDeclaration = new CompilationUnit() 189 .setModule("com.laamella.base") 190 .addSingleMemberAnnotation(SuppressWarnings.class, "\"module\"") 191 .addDirective("requires transitive java.desktop;") 192 .addDirective("exports com.laamella.base.entity.channel;") 193 .addDirective("exports com.laamella.base.entity.channel.internal to com.laamella.core;") 194 .addDirective("uses com.laamella.base.util.internal.FactoryDelegate;"); 195 196 moduleDeclaration.getDirectives() 197 .addLast(new ModuleExportsDirective() 198 .setName("foo.bar") 199 .addModuleName("other.foo") 200 .addModuleName("other.bar") 201 ); 202 203 moduleDeclaration 204 .addDirective(new ModuleExportsDirective() 205 .setName("foo.bar.x") 206 .addModuleName("other.foo") 207 .addModuleName("other.bar") 208 ); 209 210 assertEqualsNoEol("@SuppressWarnings(\"module\")\n" + 211 "module com.laamella.base {\n" + 212 " requires transitive java.desktop;\n" + 213 " exports com.laamella.base.entity.channel;\n" + 214 " exports com.laamella.base.entity.channel.internal to com.laamella.core;\n" + 215 " uses com.laamella.base.util.internal.FactoryDelegate;\n" + 216 " exports foo.bar to other.foo, other.bar;\n" + 217 " exports foo.bar.x to other.foo, other.bar;\n" + 218 "}\n", moduleDeclaration.toString()); 219 } 220 } 221