package spoon.test.comment; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringEscapeUtils; import org.junit.Test; import spoon.Launcher; import spoon.reflect.code.CtBinaryOperator; import spoon.reflect.code.CtComment; import spoon.reflect.code.CtConditional; import spoon.reflect.code.CtConstructorCall; import spoon.reflect.code.CtDo; import spoon.reflect.code.CtExpression; import spoon.reflect.code.CtFor; import spoon.reflect.code.CtIf; import spoon.reflect.code.CtInvocation; import spoon.reflect.code.CtLocalVariable; import spoon.reflect.code.CtNewArray; import spoon.reflect.code.CtReturn; import spoon.reflect.code.CtStatement; import spoon.reflect.code.CtSwitch; import spoon.reflect.code.CtSynchronized; import spoon.reflect.code.CtTry; import spoon.reflect.declaration.CtAnonymousExecutable; import spoon.reflect.declaration.CtClass; import spoon.reflect.declaration.CtConstructor; import spoon.reflect.declaration.CtElement; import spoon.reflect.declaration.CtField; import spoon.reflect.declaration.CtInterface; import spoon.reflect.declaration.CtMethod; import spoon.reflect.declaration.CtNamedElement; import spoon.reflect.declaration.CtPackage; import spoon.reflect.declaration.CtParameter; import spoon.reflect.declaration.ModifierKind; import spoon.reflect.factory.Factory; import spoon.reflect.factory.FactoryImpl; import spoon.reflect.visitor.filter.AbstractFilter; import spoon.reflect.visitor.filter.TypeFilter; import spoon.support.DefaultCoreFactory; import spoon.support.JavaOutputProcessor; import spoon.support.StandardEnvironment; import spoon.support.compiler.jdt.JDTSnippetCompiler; import spoon.test.comment.testclasses.BlockComment; import spoon.test.comment.testclasses.Comment1; import spoon.test.comment.testclasses.Comment2; import spoon.test.comment.testclasses.InlineComment; import java.io.FileOutputStream; import java.io.FileReader; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import static org.apache.commons.io.IOUtils.write; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; public class CommentTest { private String newLine = System.getProperty("line.separator"); private Factory getSpoonFactory() { final Launcher launcher = new Launcher(); launcher.run(new String[]{ "-i", "./src/test/java/spoon/test/comment/testclasses/", "-o", "./target/spooned/", "-c" }); return launcher.getFactory(); } private CtComment createFakeComment(Factory factory, String content) { return factory.Code().createInlineComment(content); } private CtComment createFakeBlockComment(Factory factory, String content) { return factory.Code().createComment(content, CtComment.CommentType.BLOCK); } @Test public void testCombinedPackageInfoComment() { Factory f = getSpoonFactory(); CtPackage p = f.Package().get("spoon.test.comment.testclasses"); String l_content = ((JavaOutputProcessor)f.getEnvironment().getDefaultFileGenerator()).getPrinter().printPackageInfo(p); String EOL = System.getProperty("line.separator"); assertEquals("/* comment1 */"+EOL+ "// comment2"+EOL+ "/**"+EOL+ " * Comment3"+EOL+ " */"+EOL+ "@java.lang.Deprecated"+EOL+ "package spoon.test.comment.testclasses;",l_content); } @Test public void testRemoveComment() { Factory f = getSpoonFactory(); CtClass<?> type = (CtClass<?>) f.Type().get(InlineComment.class); List<CtComment> comments = type.getComments(); assertEquals(3, comments.size()); type.removeComment(comments.get(0)); assertEquals(2, type.getComments().size()); } @Test public void testInLineComment() { Factory f = getSpoonFactory(); CtClass<?> type = (CtClass<?>) f.Type().get(InlineComment.class); String strType = type.toString(); List<CtComment> comments = type.getElements(new TypeFilter<CtComment>(CtComment.class)); // verify that the number of comment present in the AST is correct assertEquals(64, comments.size()); // verify that all comments present in the AST is printed for (CtComment comment : comments) { if (comment.getCommentType() == CtComment.CommentType.FILE) { // the header of the file is not printed with the toString continue; } assertNotNull(comment.getParent()); assertTrue(comment.toString() + ":" + comment.getParent() + " is not printed", strType.contains(comment.toString())); } assertEquals(3, type.getComments().size()); assertEquals(CtComment.CommentType.FILE, type.getComments().get(0).getCommentType()); assertEquals(createFakeComment(f, "comment class"), type.getComments().get(1)); CtField<?> field = type.getField("field"); assertEquals(3, field.getComments().size()); assertEquals(createFakeComment(f, "Comment Field"), field.getComments().get(0)); assertEquals("// Comment Field" + newLine + "// comment field 2" + newLine + "// comment in field" + newLine + "private int field = 10;", field.toString()); CtAnonymousExecutable ctAnonymousExecutable = type.getAnonymousExecutables().get(0); assertEquals(1, ctAnonymousExecutable.getComments().size()); assertEquals(createFakeComment(f, "comment static block"), ctAnonymousExecutable.getComments().get(0)); assertEquals(createFakeComment(f, "comment inside static"), ctAnonymousExecutable.getBody().getStatement(0)); assertEquals("// comment static block" + newLine + "static {" + newLine + " // comment inside static" + newLine + "}", ctAnonymousExecutable.toString()); CtConstructor constructor = type.getConstructor(); assertEquals(1, constructor.getComments().size()); assertEquals(createFakeComment(f, "comment constructor"), constructor.getComments().get(0)); // index 0 is the implicit super call assertEquals(createFakeComment(f, "Comment in constructor"), constructor.getBody().getStatement(1)); assertEquals("// comment constructor" + newLine + "public InlineComment() {" + newLine + " // Comment in constructor" + newLine + "}", constructor.toString()); CtMethod<Object> m = type.getMethod("m"); assertEquals(1, m.getComments().size()); assertEquals(createFakeComment(f, "comment method"), m.getComments().get(0)); assertEquals(createFakeComment(f, "comment empty method block"), m.getBody().getStatement(0)); assertEquals("// comment method" + newLine + "public void m() {" + newLine + " // comment empty method block" + newLine + "}", m.toString()); CtMethod<Object> m1 = type.getMethod("m1"); CtSwitch ctSwitch = m1.getBody().getStatement(0); assertEquals(createFakeComment(f, "comment switch"), ctSwitch.getComments().get(0)); assertEquals("// comment switch" + newLine + "switch (1) {" + newLine + " // before first case" + newLine + " case 0 :" + newLine + " // comment case 0: empty case" + newLine + " case 1 :" + newLine + " // comment case 1" + newLine + " int i = 0;" + newLine + " default :" + newLine + " // comment default" + newLine + "}", ctSwitch.toString()); CtFor ctFor = m1.getBody().getStatement(1); assertEquals(createFakeComment(f, "comment for"), ctFor.getComments().get(0)); assertEquals("// comment for" + newLine + "for (int i = 0; i < 10; i++) {" + newLine + " // comment for block" + newLine + "}", ctFor.toString()); CtIf ctIf = m1.getBody().getStatement(2); assertEquals(createFakeComment(f, "comment if"), ctIf.getComments().get(0)); assertEquals("// comment if" + newLine + "if ((1 % 2) == 0) {" + newLine + " // comment unary operator" + newLine + " (field)++;" + newLine + "}", ctIf.toString()); CtConstructorCall ctConstructorCall = m1.getBody().getStatement(3); assertEquals(createFakeComment(f, "comment constructor call"), ctConstructorCall.getComments().get(0)); assertEquals("// comment constructor call" + newLine + "new spoon.test.comment.testclasses.InlineComment()", ctConstructorCall.toString()); CtInvocation ctInvocation = m1.getBody().getStatement(4); assertEquals(createFakeComment(f, "comment invocation"), ctInvocation.getComments().get(0)); assertEquals("// comment invocation" + newLine + "this.m()", ctInvocation.toString()); CtLocalVariable ctLocalVariable = m1.getBody().getStatement(5); assertEquals(createFakeComment(f, "comment local variable"), ctLocalVariable.getComments().get(0)); assertEquals("// comment local variable" + newLine + "int i = 0", ctLocalVariable.toString()); CtLocalVariable ctLocalVariable2 = m1.getBody().getStatement(6); assertEquals(createFakeComment(f, "comment multi assignments"), ctLocalVariable2.getComments().get(0)); assertEquals("// comment multi assignments" + newLine + "int j = 2", ctLocalVariable2.toString()); CtDo ctDo = m1.getBody().getStatement(7); assertEquals(createFakeComment(f, "comment dowhile"), ctDo.getComments().get(0)); assertEquals("// comment dowhile" + newLine + "do {" + newLine + " // comment in do while" + newLine + " i++;" + newLine + " // comment end do while" + newLine + "} while (i < 10 )", ctDo.toString()); CtTry ctTry = m1.getBody().getStatement(8); assertEquals(createFakeComment(f, "comment try"), ctTry.getComments().get(0)); assertEquals("// comment try" + newLine + "try {" + newLine + " // comment in try" + newLine + " i++;" + newLine + "}// between" + newLine + "// try/catch" + newLine + " catch (java.lang.Exception e) {" + newLine + " // comment in catch" + newLine + "}", ctTry.toString()); CtSynchronized ctSynchronized = m1.getBody().getStatement(9); assertEquals(createFakeComment(f, "comment synchronized"), ctSynchronized.getComments().get(0)); assertEquals("// comment synchronized" + newLine + "synchronized(this) {" + newLine + " // comment in synchronized" + newLine + "}", ctSynchronized.toString()); CtLocalVariable ctLocalVariable1 = m1.getBody().getStatement(10); CtConditional ctConditional = (CtConditional) ctLocalVariable1.getDefaultExpression(); assertEquals(createFakeComment(f, "comment after condition CtConditional"), ctConditional.getCondition().getComments().get(0)); assertEquals(createFakeComment(f, "comment before then CtConditional"), ctConditional.getThenExpression().getComments().get(0)); assertEquals(createFakeComment(f, "comment after then CtConditional"), ctConditional.getThenExpression().getComments().get(1)); assertEquals(createFakeComment(f, "comment before else CtConditional"), ctConditional.getElseExpression().getComments().get(0)); assertEquals(createFakeComment(f, "comment after else CtConditional"), ctLocalVariable1.getComments().get(0)); assertEquals("java.lang.Double dou = (i == 1// comment after condition CtConditional" + newLine + ") ? // comment before then CtConditional" + newLine + "null// comment after then CtConditional" + newLine + " : // comment before else CtConditional" + newLine + "new java.lang.Double((j / ((double) (i - 1))))", ctLocalVariable1.toString()); CtNewArray ctNewArray = (CtNewArray) ((CtLocalVariable) m1.getBody().getStatement(11)).getDefaultExpression(); assertEquals(createFakeComment(f, "last comment at the end of array"), ctNewArray.getComments().get(0)); CtElement arrayValue = (CtElement) ctNewArray.getElements().get(0); assertEquals(createFakeComment(f, "comment before array value"), arrayValue.getComments().get(0)); assertEquals(createFakeComment(f, "comment after array value"), arrayValue.getComments().get(1)); CtLocalVariable ctLocalVariableString = m1.getBody().getStatement(12); assertEquals(createFakeComment(f, "comment multi line string"), ((CtBinaryOperator)((CtBinaryOperator)ctLocalVariableString.getDefaultExpression()).getRightHandOperand()).getLeftHandOperand().getComments().get(0)); assertEquals("\"\" + (\"\"// comment multi line string" + newLine + " + \"\")", ctLocalVariableString.getDefaultExpression().toString()); ctLocalVariable1 = m1.getBody().getStatement(13); ctConditional = (CtConditional) ctLocalVariable1.getDefaultExpression(); assertEquals("boolean c = (i == 1) ? // comment before then boolean CtConditional" + newLine + "i == 1// comment after then boolean CtConditional" + newLine + " : i == 2", ctLocalVariable1.toString()); CtReturn ctReturn = m1.getBody().getStatement(14); assertEquals(createFakeComment(f, "comment return"), ctReturn.getComments().get(0)); assertEquals("// comment return" + newLine + "return ", ctReturn.toString()); CtMethod m2 = type.getMethodsByName("m2").get(0); assertEquals(6, m2.getComments().size()); CtParameter ctParameter = (CtParameter) m2.getParameters().get(0); assertEquals(4, ctParameter.getComments().size()); assertEquals("// comment before type" + newLine + "// comment after parameter" + newLine + "// comment before throws" + newLine + "// comment before exception 1" + newLine + "// comment before exception 2" + newLine + "// comment before block" + newLine + "public void m2(// comment before name" + newLine + "// comment before parameters" + newLine + "// comment before type parameter" + newLine + "// comment before name parameter" + newLine + "int i) throws java.lang.Error, java.lang.Exception {" + newLine + "}", m2.toString()); } @Test public void testBlockComment() { Factory f = getSpoonFactory(); CtClass<?> type = (CtClass<?>) f.Type().get(BlockComment.class); String strType = type.toString(); List<CtComment> comments = type.getElements(new TypeFilter<CtComment>(CtComment.class)); // verify that the number of comment present in the AST is correct assertEquals(51, comments.size()); // verify that all comments present in the AST is printed for (CtComment comment : comments) { if (comment.getCommentType() == CtComment.CommentType.FILE) { // the header of the file is not printed with the toString continue; } assertNotNull(comment.getParent()); assertTrue(comment.toString() + ":" + comment.getParent() + " is not printed", strType.contains(comment.toString())); } assertEquals(4, type.getComments().size()); assertEquals(createFakeBlockComment(f, "comment class"), type.getComments().get(1)); CtField<?> field = type.getField("field"); assertEquals(2, field.getComments().size()); assertEquals(createFakeBlockComment(f, "Comment Field"), field.getComments().get(0)); assertEquals("/* Comment Field */" + newLine + "/* comment in field */" + newLine + "private int field = 10;", field.toString()); CtAnonymousExecutable ctAnonymousExecutable = type.getAnonymousExecutables().get(0); assertEquals(1, ctAnonymousExecutable.getComments().size()); assertEquals(createFakeBlockComment(f, "comment static block"), ctAnonymousExecutable.getComments().get(0)); assertEquals(createFakeBlockComment(f, "comment inside static"), ctAnonymousExecutable.getBody().getStatement(0)); assertEquals("/* comment static block */" + newLine + "static {" + newLine + " /* comment inside static */" + newLine + "}", ctAnonymousExecutable.toString()); CtConstructor constructor = type.getConstructor(); assertEquals(1, constructor.getComments().size()); assertEquals(createFakeBlockComment(f, "comment constructor"), constructor.getComments().get(0)); // index 0 is the implicit super call assertEquals(createFakeBlockComment(f, "Comment in constructor"), constructor.getBody().getStatement(1)); assertEquals("/* comment constructor */" + newLine + "public BlockComment() {" + newLine + " /* Comment in constructor */" + newLine + "}", constructor.toString()); CtMethod<Object> m = type.getMethod("m"); assertEquals(1, m.getComments().size()); assertEquals(createFakeBlockComment(f, "comment method"), m.getComments().get(0)); assertEquals(createFakeBlockComment(f, "comment empty method block"), m.getBody().getStatement(0)); assertEquals("/* comment method */" + newLine + "public void m() {" + newLine + " /* comment empty method block */" + newLine + "}", m.toString()); CtMethod<Object> m1 = type.getMethod("m1"); CtSwitch ctSwitch = m1.getBody().getStatement(0); assertEquals(createFakeBlockComment(f, "comment switch"), ctSwitch.getComments().get(0)); assertEquals("/* comment switch */" + newLine + "switch (1) {" + newLine + " /* before first case */" + newLine + " case 0 :" + newLine + " /* comment case 0: empty case */" + newLine + " case 1 :" + newLine + " /* comment case 1 */" + newLine + " int i = 0;" + newLine + " default :" + newLine + " /* comment default */" + newLine + "}", ctSwitch.toString()); CtFor ctFor = m1.getBody().getStatement(1); assertEquals(createFakeBlockComment(f, "comment for"), ctFor.getComments().get(0)); assertEquals("/* comment for */" + newLine + "for (int i = 0; i < 10; i++) {" + newLine + " /* comment for block */" + newLine + "}", ctFor.toString()); CtIf ctIf = m1.getBody().getStatement(2); assertEquals(createFakeBlockComment(f, "comment if"), ctIf.getComments().get(0)); assertEquals("/* comment if */" + newLine + "if ((1 % 2) == 0) {" + newLine + " /* comment unary operator */" + newLine + " (field)++;" + newLine + "}", ctIf.toString()); CtConstructorCall ctConstructorCall = m1.getBody().getStatement(3); assertEquals(createFakeBlockComment(f, "comment constructor call"), ctConstructorCall.getComments().get(0)); assertEquals("/* comment constructor call */" + newLine + "new spoon.test.comment.testclasses.BlockComment()", ctConstructorCall.toString()); CtInvocation ctInvocation = m1.getBody().getStatement(4); assertEquals(createFakeBlockComment(f, "comment invocation"), ctInvocation.getComments().get(0)); assertEquals("/* comment invocation */" + newLine + "this.m()", ctInvocation.toString()); CtLocalVariable ctLocalVariable = m1.getBody().getStatement(5); assertEquals(createFakeBlockComment(f, "comment local variable"), ctLocalVariable.getComments().get(0)); assertEquals("/* comment local variable */" + newLine + "int i = 0", ctLocalVariable.toString()); CtLocalVariable ctLocalVariable2 = m1.getBody().getStatement(6); assertEquals(createFakeBlockComment(f, "comment multi assignments"), ctLocalVariable2.getComments().get(0)); assertEquals("/* comment multi assignments */" + newLine + "int j = 2", ctLocalVariable2.toString()); CtDo ctDo = m1.getBody().getStatement(7); assertEquals(createFakeBlockComment(f, "comment dowhile"), ctDo.getComments().get(0)); assertEquals("/* comment dowhile */" + newLine + "do {" + newLine + " /* comment in do while */" + newLine + " i++;" + newLine + " /* comment end do while */" + newLine + "} while (i < 10 )", ctDo.toString()); CtTry ctTry = m1.getBody().getStatement(8); assertEquals(createFakeBlockComment(f, "comment try"), ctTry.getComments().get(0)); assertEquals("/* comment try */" + newLine + "try {" + newLine + " /* comment in try */" + newLine + " i++;" + newLine + "} catch (java.lang.Exception e) {" + newLine + " /* comment in catch */" + newLine + "}", ctTry.toString()); CtSynchronized ctSynchronized = m1.getBody().getStatement(9); assertEquals(createFakeBlockComment(f, "comment synchronized"), ctSynchronized.getComments().get(0)); assertEquals("/* comment synchronized */" + newLine + "synchronized(this) {" + newLine + " /* comment in synchronized */" + newLine + "}", ctSynchronized.toString()); CtReturn ctReturn = m1.getBody().getStatement(10); assertEquals(createFakeBlockComment(f, "comment return"), ctReturn.getComments().get(0)); assertEquals("/* comment return */" + newLine + "return ", ctReturn.toString()); CtMethod m2 = type.getMethodsByName("m2").get(0); assertEquals(6, m2.getComments().size()); CtParameter ctParameter = (CtParameter) m2.getParameters().get(0); assertEquals(4, ctParameter.getComments().size()); assertEquals("/* comment before type */" + newLine + "/* comment after parameter */" + newLine + "/* comment before throws */" + newLine + "/* comment before exception 1 */" + newLine + "/* comment before exception 2 */" + newLine + "/* comment before block */" + newLine + "public void m2(/* comment before name */" + newLine + "/* comment before parameters */" + newLine + "/* comment before type parameter */" + newLine + "/* comment before name parameter */" + newLine + "int i) throws java.lang.Error, java.lang.Exception {" + newLine + "}", m2.toString()); } @Test public void testInsertNewComment() { Factory f = getSpoonFactory(); CtClass<?> type = (CtClass<?>) f.Type().get(InlineComment.class); CtMethod method = f.Core().createMethod(); method.setSimpleName("newMethod"); method.setBody(f.Core().createBlock()); method.setType(f.Type().VOID_PRIMITIVE); type.addMethod(method); method.addComment(createFakeComment(f, "comment method")); method.getBody().addStatement(createFakeComment(f, "comment empty block")); assertEquals("// comment method" + newLine + "void newMethod() {" + newLine + " // comment empty block" + newLine + "}", method.toString()); method.getBody().removeStatement(method.getBody().getStatement(0)); CtLocalVariable<Integer> i = f.Code().createLocalVariable(f.Type().INTEGER_PRIMITIVE, "i", null); i.addComment(createFakeComment(f, "comment local variable")); method.getBody().addStatement(i); assertEquals("// comment method" + newLine + "void newMethod() {" + newLine + " // comment local variable" + newLine + " int i;" + newLine + "}", method.toString()); } @Test public void testCoreFactory() { Factory spoonFactory = getSpoonFactory(); CtComment comment = spoonFactory.Core().createComment(); assertEquals("/* */", comment.toString()); comment.setContent("comment"); assertEquals("/* comment */", comment.toString()); comment.setCommentType(CtComment.CommentType.INLINE); assertEquals(CtComment.CommentType.INLINE, comment.getCommentType()); assertEquals("// comment", comment.toString()); comment.setCommentType(CtComment.CommentType.BLOCK); assertEquals(CtComment.CommentType.BLOCK, comment.getCommentType()); } @Test public void testCodeFactory() { Factory spoonFactory = getSpoonFactory(); CtComment comment = spoonFactory.Code().createComment("comment", CtComment.CommentType.INLINE); assertEquals("// comment", comment.toString()); assertEquals(CtComment.CommentType.INLINE, comment.getCommentType()); comment = spoonFactory.Code().createInlineComment("comment"); assertEquals("// comment", comment.toString()); assertEquals(CtComment.CommentType.INLINE, comment.getCommentType()); } @Test public void testSnippedWithComments(){ Factory factory = new FactoryImpl(new DefaultCoreFactory(), new StandardEnvironment()); factory.getEnvironment().setNoClasspath(true); factory.getEnvironment().setCommentEnabled(true); String content = "//class comment\n" + "class PR {\n" + "/**\n * method javadoc comment */\n" + "public java.io.File foo(String p) {\n" + "/* method body comment*/\n" + " return /*inline comment*/ null;" + "}" + "};\n" + "// after class comment"; JDTSnippetCompiler builder = new JDTSnippetCompiler(factory, content); builder.build(); CtClass<?> clazz1 = (CtClass<?>) factory.Type().getAll().get(0); assertNotNull(clazz1); assertEquals(1, clazz1.getComments().size()); assertEquals("class comment", clazz1.getComments().get(0).getContent()); assertEquals(1, builder.getSnippetCompilationUnit().getDeclaredTypes().size()); assertTrue(clazz1==builder.getSnippetCompilationUnit().getDeclaredTypes().get(0)); CtMethod<?> methodString = (CtMethod<?>) clazz1.getMethods().toArray()[0]; assertEquals("java.io.File foo(java.lang.String)", methodString.getSignature()); assertEquals(1, methodString.getComments().size()); assertEquals("method javadoc comment", methodString.getComments().get(0).getContent()); CtReturn<?> returnSt = methodString.getBody().getStatement(0); assertEquals(2, returnSt.getComments().size()); assertEquals("method body comment", returnSt.getComments().get(0).getContent()); assertEquals("inline comment", returnSt.getComments().get(1).getContent()); } @Test public void testAddCommentsToSnippet() { Factory factory = new FactoryImpl(new DefaultCoreFactory(), new StandardEnvironment()); factory.getEnvironment().setNoClasspath(true); factory.getEnvironment().setCommentEnabled(true); CtStatement statement = factory.Code().createCodeSnippetStatement("System.out.println(\"Caenorhabditis\")"); CtComment comment = factory.createComment("My comment on my statement", CtComment.CommentType.INLINE); statement.addComment(comment); CtExpression expression = factory.Code().createCodeSnippetExpression("\"Caenorhabditis\" + \"Caenorhabditis\""); CtComment commentExpression = factory.createComment("My comment on my expression", CtComment.CommentType.INLINE); expression.addComment(commentExpression); assertEquals("// My comment on my statement" + newLine + "System.out.println(\"Caenorhabditis\")", statement.toString()); assertEquals("// My comment on my expression" + newLine + "\"Caenorhabditis\" + \"Caenorhabditis\"", expression.toString()); } @Test public void testDocumentationContract() throws Exception { // contract: all metamodel classes must be commented with an example. final Launcher launcher = new Launcher(); launcher.getEnvironment().setNoClasspath(true); launcher.getEnvironment().setCommentEnabled(true); // interfaces. launcher.addInputResource("./src/main/java/spoon/reflect/"); launcher.addInputResource("./src/main/java/spoon/support/reflect/"); launcher.buildModel(); StringBuffer codeElementsDocumentationPage = new StringBuffer(); codeElementsDocumentationPage.append(IOUtils.toString(new FileReader("doc/code_elements_header.md"))); codeElementsDocumentationPage.append("\n\n"); launcher.getModel().getElements(new TypeFilter<>(CtInterface.class)).stream().forEach(x -> { assertTrue(x.getSimpleName()+ " has no documentation", x.getDocComment() != null); assertTrue(x.getSimpleName()+ " has no documentation", x.getDocComment().length() > 0); // we only consider instantiable interfaces if (launcher.getModel().getElements(new AbstractFilter<CtElement>() { @Override public boolean matches(CtElement element) { return (element instanceof CtNamedElement) && ((CtNamedElement)element).getSimpleName().equals(x.getSimpleName()+"Impl") && (element instanceof CtClass) && !((CtClass)element).hasModifier(ModifierKind.ABSTRACT); } }).size() == 0 ) { return; } // we don't consider references if (x.getSimpleName().endsWith("Reference")) { return; } if (x.isSubtypeOf(launcher.getFactory().Type().get(CtStatement.class).getReference()) || x.isSubtypeOf(launcher.getFactory().Type().get(CtExpression.class).getReference()) ) { if (x.getSimpleName().equals("CtCodeSnippetStatement")) { return; } // no meaningful snippet if (x.getSimpleName().equals("CtCodeSnippetExpression")) { return; } // no meaningful snippet if (x.getSimpleName().equals("CtComment")) { return; } // no comment in snippet mode if (x.getSimpleName().equals("CtEnum")) { return; } // a statement in really rare cases if (x.getSimpleName().equals("CtAnnotationFieldAccess")) { return; } // too hard to snippetize codeElementsDocumentationPage.append("### "+x.getSimpleName()+"\n"); codeElementsDocumentationPage.append("[(javadoc)](http://spoon.gforge.inria.fr/mvnsites/spoon-core/apidocs/"+x.getQualifiedName().replace('.', '/')+".html)\n\n"); codeElementsDocumentationPage.append("```java"+"\n"); Pattern p = Pattern.compile("<pre>(.*?)</pre>", Pattern.CASE_INSENSITIVE | Pattern.DOTALL | Pattern.MULTILINE | Pattern.UNIX_LINES); Matcher m = p.matcher(x.getDocComment()); m.find(); do { String snippet = m.group(1); snippet = StringEscapeUtils.unescapeHtml4(snippet); // it must compile CtElement el = launcher.getFactory().Code().createCodeSnippetStatement(snippet).compile(); // the snippet contains this element assertTrue(snippet + " does not contain a " + x.getSimpleName(), el.getElements(new TypeFilter<>(x.getActualClass())).size() > 0); codeElementsDocumentationPage.append(snippet+"\n"); } while (m.find()) ; codeElementsDocumentationPage.append("```"+"\n"); } } ); try { assertEquals("doc outdated, please commit doc/code_elements.md", codeElementsDocumentationPage.toString(), IOUtils.toString(new FileReader("doc/code_elements.md"))); } finally { write(codeElementsDocumentationPage.toString(), new FileOutputStream("doc/code_elements.md")); } } @Test public void testCommentsInComment1And2() { Factory f = getSpoonFactory(); CtClass<?> type = (CtClass<?>) f.Type().get(Comment1.class); List<CtComment> comments = type.getElements(new TypeFilter<CtComment>(CtComment.class)); assertEquals(4, comments.size()); type = (CtClass<?>) f.Type().get(Comment2.class); comments = type.getElements(new TypeFilter<CtComment>(CtComment.class)); assertEquals(2, comments.size()); CtComment commentD = comments.get(1); assertEquals("D", commentD.getContent()); } }