Skip to content

Commit

Permalink
fix: getDocComment returns the complete Javadoc comment, incl. tags (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
monperrus authored and pvojtechovsky committed Jan 16, 2018
1 parent 8f39127 commit 033d6b0
Show file tree
Hide file tree
Showing 9 changed files with 62 additions and 8 deletions.
3 changes: 3 additions & 0 deletions src/main/java/spoon/reflect/code/CtComment.java
Original file line number Diff line number Diff line change
Expand Up @@ -80,4 +80,7 @@ enum CommentType {

@Override
CtComment clone();

/** Utility method to for casting the object, throws an exception if not of the correct type */
CtJavaDoc asJavaDoc();
}
8 changes: 7 additions & 1 deletion src/main/java/spoon/reflect/declaration/CtElement.java
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,13 @@ <A extends Annotation> CtAnnotation<A> getAnnotation(

/**
* Returns the text of the documentation ("javadoc") comment of this
* element. The documentation is also accessible via {@link #getComments()}.
* element. It contains the text of Javadoc together with the tags.
*
* If one only wants only the text without the tag, one can call `getComments().get(0).getContent()`
*
* If one wants to analyze the tags, one can call `getComments().get(0).asJavaDoc().getTags()`
*
* See also {@link #getComments()}.and {@link spoon.reflect.code.CtJavaDoc}
*/
@DerivedProperty
String getDocComment();
Expand Down
3 changes: 3 additions & 0 deletions src/main/java/spoon/reflect/factory/CodeFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -673,6 +673,9 @@ public CtCodeSnippetStatement createCodeSnippetStatement(String statement) {
* @return a new CtComment
*/
public CtComment createComment(String content, CtComment.CommentType type) {
if (type == CtComment.CommentType.JAVADOC) {
return factory.Core().createJavaDoc().setContent(content);
}
return factory.Core().createComment().setContent(content).setCommentType(type);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ private CtComment parseTags(CtComment comment, String commentContent) {
String currentTagContent = "";
CtJavaDocTag.TagType currentTag = null;

// TODO: remove the " *", see spoon.test.javadoc.JavaDocTest.testJavaDocReprint()
String[] lines = commentContent.split("\n");
for (int i = 0; i < lines.length; i++) {
String line = lines[i].trim();
Expand Down
9 changes: 9 additions & 0 deletions src/main/java/spoon/support/reflect/code/CtCommentImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import spoon.reflect.annotations.MetamodelPropertyField;
import spoon.reflect.code.CtComment;
import spoon.reflect.code.CtJavaDoc;
import spoon.reflect.path.CtRole;
import spoon.reflect.visitor.CtVisitor;

Expand Down Expand Up @@ -105,4 +106,12 @@ public int hashCode() {
public CtComment clone() {
return (CtComment) super.clone();
}

@Override
public CtJavaDoc asJavaDoc() {
if (this instanceof CtJavaDoc) {
return (CtJavaDoc) this;
}
throw new IllegalStateException("not a javadoc comment");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
import org.apache.log4j.Logger;
import spoon.reflect.annotations.MetamodelPropertyField;
import spoon.reflect.code.CtComment;
import spoon.reflect.code.CtJavaDoc;
import spoon.reflect.code.CtJavaDocTag;
import spoon.reflect.cu.SourcePosition;
import spoon.reflect.declaration.CtAnnotation;
import spoon.reflect.declaration.CtElement;
Expand Down Expand Up @@ -172,10 +174,15 @@ public List<CtAnnotation<? extends Annotation>> getAnnotations() {
public String getDocComment() {
for (CtComment ctComment : comments) {
if (ctComment.getCommentType() == CtComment.CommentType.JAVADOC) {
return ctComment.getContent();
StringBuffer result = new StringBuffer();
result.append(ctComment.getContent() + System.lineSeparator());
for (CtJavaDocTag tag: ((CtJavaDoc) ctComment).getTags()) {
result.append(tag.toString()); // the tag already contains a new line
}
return result.toString();
}
}
return null;
return "";
}

public SourcePosition getPosition() {
Expand Down
25 changes: 25 additions & 0 deletions src/test/java/spoon/test/javadoc/JavaDocTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,31 @@ public void testJavaDocReprint() throws Exception {
+ " return null;" + System.lineSeparator()
+ " }" + System.lineSeparator()
+ "}", aClass.toString());

// contract: getDocComment never returns null, it returns an empty string if no comment
assertEquals("", aClass.getDocComment());

// contract: getDocComment returns the comment content together with the tag content
assertEquals("Creates an annotation type." + System.lineSeparator()
+ "* @param owner" + System.lineSeparator()
+ " * \t\tthe package of the annotation type" + System.lineSeparator()
+ "* @param simpleName" + System.lineSeparator()
+ " * \t\tthe name of annotation" + System.lineSeparator()
, aClass.getMethodsByName("create").get(0).getDocComment());
assertEquals(2, aClass.getMethodsByName("create").get(0).getComments().get(0).asJavaDoc().getTags().size());

// JavaDocTest#testJavaDocReprint()
// good first bug to welcome new contributors
// uncomment the assertion and get it passing!
// there remains a minor problem with tags, they are printed with the "* " before the content
// and the spaces before the * are not consistently handled
// here is the correct assertion
// assertEquals("Creates an annotation type." + System.lineSeparator()
// + "@param owner" + System.lineSeparator()
// + " \t\tthe package of the annotation type" + System.lineSeparator()
// + " @param simpleName" + System.lineSeparator()
// + " \t\tthe name of annotation" + System.lineSeparator()
// , aClass.getMethodsByName("create").get(0).getDocComment());
}

@Test
Expand Down
4 changes: 2 additions & 2 deletions src/test/java/spoon/test/pkg/PackageTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public void testPackage() throws Exception {

CtPackage ctPackage = clazz.getPackage();
Assert.assertEquals("spoon.test.pkg.name", ctPackage.getQualifiedName());
Assert.assertNull(ctPackage.getDocComment());
Assert.assertEquals("", ctPackage.getDocComment());
assertTrue(CtPackage.class.isAssignableFrom(ctPackage.getParent().getClass()));

ctPackage = (CtPackage) ctPackage.getParent();
Expand All @@ -76,7 +76,7 @@ public void testPackage() throws Exception {

ctPackage = (CtPackage) ctPackage.getParent();
Assert.assertEquals("spoon.test", ctPackage.getQualifiedName());
Assert.assertNull(ctPackage.getDocComment());
Assert.assertEquals("", ctPackage.getDocComment());
}

@Test
Expand Down
6 changes: 3 additions & 3 deletions src/test/java/spoon/test/template/TemplateTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -256,20 +256,20 @@ class Context {
* Generated by spoon.test.template.testclasses.inheritance.SubTemplate#var(SubTemplate.java:51)
* Generated by spoon.test.template.testclasses.inheritance.SubTemplate$InnerClass(SubTemplate.java:76)
*/
private static final Pattern generatedByRE = Pattern.compile("Generated by ([^$#\\(]+)([^\\(]*)\\(([^\\.]+)\\.java:(\\d+)\\)");
private static final Pattern generatedByRE = Pattern.compile(".*Generated by ([^$#\\(]+)([^\\(]*)\\(([^\\.]+)\\.java:(\\d+)\\).*", Pattern.MULTILINE | Pattern.DOTALL);
private static final Pattern typeMemberRE = Pattern.compile("[^\\.$#]+$");

private void assertCommentHasGeneratedBy(CtElement e, String templateQName, Map<CtElement, String> elementToGeneratedByMember) {
String docComment = e.getDocComment();
String generatedByMember = elementToGeneratedByMember.get(e);
if (generatedByMember == null) {
assertNull(docComment);
assertEquals("", docComment);
// assertTrue(e.getPosition()==null || e.getPosition() instanceof NoSourcePosition);
} else {
assertNotNull("Javadoc comment is missing for "+e.toString(), docComment);
int idx = docComment.indexOf("Generated by");
assertTrue("Javadoc comment doesn't contain Generated by. There is:\n"+docComment, idx>=0);
Matcher m = generatedByRE.matcher(docComment.substring(idx));
Matcher m = generatedByRE.matcher(docComment);
assertTrue("Unexpected Generated by:\n"+docComment, m.matches());
assertEquals(templateQName, m.group(1));
assertEquals(generatedByMember, m.group(2));
Expand Down

0 comments on commit 033d6b0

Please sign in to comment.