blob: 13405ab49aff1789462ac3ea4b810c548494c8b8 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2022 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.core.tests.dom;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.core.dom.Comment;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.JavaDocRegion;
import org.eclipse.jdt.core.dom.Javadoc;
import org.eclipse.jdt.core.dom.TagElement;
import org.eclipse.jdt.core.dom.TagProperty;
import org.eclipse.jdt.core.dom.TextElement;
import org.eclipse.jdt.internal.compiler.parser.JavadocTagConstants;
import org.eclipse.jdt.internal.compiler.parser.ScannerHelper;
/**
* Class to test DOM/AST nodes built for Javadoc comments.
*
* Most of tests are 'automatic'. It means that to add a new tests, you only need to
* create one or several CUs and put them in org.eclipse.jdt.core.model.tests/workspace/Converter/src/javadoc/testXXX
* folder and add the corresponding test in this class:
* <pre>
* public void testXXX() throws JavaModelException {
* verifyComments("testXXX");
* }
* </pre>
*
* Note that when a test fails, the easiest way to debug it is to open
* a runtime workbench, create a project 'Converter', delete the default 'src' source folder
* and replace it by a linked source to the 'src' folder of org.eclipse.jdt.core.model.tests/workspace/Converter/src
* in your workspace.
*
* Then open the CU on which the test fails in a ASTView and verify the offset/length
* of the offending node located at the positions displayed in the console when the test failed...
*
* Since 3.4, the failing test also provides the comparison between the source of the comment
* and the string get from the built DOM/AST nodes in the comment (see {@link ASTConverterJavadocFlattener})
* but this may be not enough to see precisely the origin of the problem.
*/
@SuppressWarnings({"rawtypes", "unchecked"})
public class ASTConverterJavadocTest_18 extends ConverterTestSetup {
// Flag to know whether Converter directory should be copied from org.eclipse.jdt.core.tests.model project
static protected boolean COPY_DIR = true;
// Test counters
protected static int[] TEST_COUNTERS = { 0, 0, 0, 0 };
// Unicode tests
protected static boolean UNICODE = false;
// Doc Comment support
static final String DOC_COMMENT_SUPPORT = System.getProperty("doc.support");
// List of comments read from source of test
private static final int LINE_COMMENT = 100;
private static final int BLOCK_COMMENT =200;
private static final int DOC_COMMENT = 300;
List comments = new ArrayList();
private String chars;
// List of tags contained in each comment read from test source.
List allTags = new ArrayList();
// tags inhibiting inline tags
static final String TAG_CODE = "code";
static final String TAG_LITERAL = "literal";
// Current compilation unit
protected ICompilationUnit sourceUnit;
// Test package binding
protected boolean resolveBinding = true;
protected boolean packageBinding = true;
// AST Level
protected int astLevel = AST.getJLSLatest();
protected int savedLevel;
// Debug
protected String prefix = "";
protected boolean debug = false;
protected StringBuffer problems;
protected String compilerOption = JavaCore.IGNORE;
protected List failures;
protected boolean stopOnFailure = true;
Map savedOptions = null;
protected ICompilationUnit moduleUnit;
private static String SNIPPET_TAG = '@' + new String(JavadocTagConstants.TAG_SNIPPET);
/**
* @param name
*/
public ASTConverterJavadocTest_18(String name) {
super(name);
}
public static Test suite() {
TestSuite suite = new Suite(ASTConverterJavadocTest_18.class.getName());
buildSuite(suite);
return suite;
}
public static void buildSuite(TestSuite suite) {
Class c = ASTConverterJavadocTest_18.class;
Method[] methods = c.getMethods();
for (int i = 0, max = methods.length; i < max; i++) {
if (methods[i].getName().startsWith("test")) { //$NON-NLS-1$
suite.addTest(new ASTConverterJavadocTest_18(methods[i].getName()));
}
}
}
/* (non-Javadoc)
* @see org.eclipse.jdt.core.tests.model.AbstractJavaModelTests#copyDirectory(java.io.File, java.io.File)
*/
@Override
protected void copyDirectory(File sourceDir, File targetDir) throws IOException {
if (COPY_DIR) {
super.copyDirectory(sourceDir, targetDir);
} else {
targetDir.mkdirs();
File sourceFile = new File(sourceDir, ".project");
File targetFile = new File(targetDir, ".project");
targetFile.createNewFile();
copy(sourceFile, targetFile);
sourceFile = new File(sourceDir, ".classpath");
targetFile = new File(targetDir, ".classpath");
targetFile.createNewFile();
copy(sourceFile, targetFile);
}
}
/* (non-Javadoc)
* @see junit.framework.TestCase#setUp()
*/
@Override
protected void setUp() throws Exception {
super.setUp();
TEST_COUNTERS[0]++;
this.failures = new ArrayList();
this.problems = new StringBuffer();
this.workingCopies = null;
this.savedLevel = this.astLevel;
}
/* (non-Javadoc)
* @see junit.framework.TestCase#tearDown()
*/
@Override
protected void tearDown() throws Exception {
int size = this.failures.size();
String title = size+" positions/bindings were incorrect in "+getName();
if (size == 0) {
TEST_COUNTERS[1]++;
} else if (this.problems.length() > 0) {
if (this.debug) {
System.out.println("Compilation warnings/errors occured:");
System.out.println(this.problems.toString());
}
TEST_COUNTERS[2]++;
} else {
TEST_COUNTERS[3]++;
System.out.println(title+":");
for (int i=0; i<size; i++) {
System.out.println(" - "+this.failures.get(i));
}
}
// if (!stopOnFailure) {
assertTrue(title, size==0 || this.problems.length() > 0);
// }
super.tearDown();
// Restore saved ast level
this.astLevel = this.savedLevel;
}
/* (non-Javadoc)
* @see junit.framework.TestCase#tearDown()
*/
@Override
public void tearDownSuite() throws Exception {
// put default options on project
if (this.currentProject != null && this.savedOptions != null) {
this.currentProject.setOptions(this.savedOptions);
}
super.tearDownSuite();
if (TEST_COUNTERS[0] != TEST_COUNTERS[1]) {
NumberFormat intFormat = NumberFormat.getInstance();
intFormat.setMinimumIntegerDigits(3);
intFormat.setMaximumIntegerDigits(3);
System.out.println("=====================================");
System.out.println(intFormat.format(TEST_COUNTERS[0])+" tests have been executed:");
System.out.println(" - "+intFormat.format(TEST_COUNTERS[1])+" tests have been actually executed.");
System.out.println(" - "+intFormat.format(TEST_COUNTERS[2])+" tests were skipped due to compilation errors.");
System.out.println(" - "+intFormat.format(TEST_COUNTERS[3])+" tests failed.");
}
}
@Override
public ASTNode runConversion(char[] source, String unitName, IJavaProject project) {
ASTParser parser = ASTParser.newParser(this.astLevel);
parser.setSource(source);
parser.setUnitName(unitName);
parser.setProject(project);
parser.setResolveBindings(this.resolveBinding);
return parser.createAST(null);
}
@Override
public ASTNode runConversion(char[] source, String unitName, IJavaProject project, Map options) {
if (project == null) {
ASTParser parser = ASTParser.newParser(this.astLevel);
parser.setSource(source);
parser.setUnitName(unitName);
parser.setCompilerOptions(options);
parser.setResolveBindings(this.resolveBinding);
return parser.createAST(null);
}
return runConversion(source, unitName, project);
}
private char getNextChar(char[] source, int idx) {
// get next char
char ch = source[idx];
int charLength = 1;
int pos = idx;
this.chars = null;
if (ch == '\\' && source[idx+1] == 'u') {
//-------------unicode traitement ------------
int c1, c2, c3, c4;
charLength++;
while (source[idx+charLength] == 'u') charLength++;
if (((c1 = ScannerHelper.getHexadecimalValue(source[idx+charLength++])) > 15 || c1 < 0)
|| ((c2 = ScannerHelper.getHexadecimalValue(source[idx+charLength++])) > 15 || c2 < 0)
|| ((c3 = ScannerHelper.getHexadecimalValue(source[idx+charLength++])) > 15 || c3 < 0)
|| ((c4 = ScannerHelper.getHexadecimalValue(source[idx+charLength++])) > 15 || c4 < 0)) {
return ch;
}
ch = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
this.chars = new String(source, pos, charLength);
}
return ch;
}
/*
* Convert Javadoc source to match Javadoc.toString().
* Store converted comments and their corresponding tags respectively
* in comments and allTags fields
*/
protected void setSourceComment(char[] source) throws ArrayIndexOutOfBoundsException {
this.comments = new ArrayList();
this.allTags = new ArrayList();
StringBuilder buffer = null;
int comment = 0;
boolean end = false, lineStarted = false;
String tag = null;
List tags = new ArrayList();
int length = source.length;
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=206345
// when parsing tags such as @code and @literal,
// any tag should be discarded and considered as plain text until
// properly closed with closing brace
boolean considerTagAsPlainText = false;
int openingBraces = 0;
char previousChar=0, currentChar=0;
for (int i=0; i<length;) {
previousChar = currentChar;
// get next char
currentChar = getNextChar(source, i);
i += (this.chars==null) ? 1 : this.chars.length();
switch (comment) {
case 0:
switch (currentChar) {
case '/':
comment = 1; // first char for comments...
buffer = new StringBuilder();
if (this.chars == null) buffer.append(currentChar);
else buffer.append(this.chars);
break;
case '\'':
while (i<length) {
// get next char
currentChar = getNextChar(source, i);
i += (this.chars==null) ? 1 : this.chars.length();
if (currentChar == '\\') {
// get next char
currentChar = getNextChar(source, i);
i += (this.chars==null) ? 1 : this.chars.length();
} else {
if (currentChar == '\'') {
break;
}
}
}
break;
case '"':
while (i<length) {
// get next char
currentChar = getNextChar(source, i);
i += (this.chars==null) ? 1 : this.chars.length();
if (currentChar == '\\') {
// get next char
currentChar = getNextChar(source, i);
i += (this.chars==null) ? 1 : this.chars.length();
} else {
if (currentChar == '"') {
// get next char
currentChar = getNextChar(source, i);
if (currentChar == '"') {
i += (this.chars==null) ? 1 : this.chars.length();
} else {
break;
}
}
}
}
break;
}
break;
case 1: // first '/' has been found...
switch (currentChar) {
case '/':
if (this.chars == null) buffer.append(currentChar);
else buffer.append(this.chars);
comment = LINE_COMMENT;
break;
case '*':
if (this.chars == null) buffer.append(currentChar);
else buffer.append(this.chars);
comment = 2; // next step
break;
default:
comment = 0;
break;
}
break;
case 2: // '/*' has been found...
if (currentChar == '*') {
comment = 3; // next step...
} else {
comment = BLOCK_COMMENT;
}
if (this.chars == null) buffer.append(currentChar);
else buffer.append(this.chars);
break;
case 3: // '/**' has bee found, verify that's not an empty block comment
if (currentChar == '/') { // empty block comment
if (this.chars == null) buffer.append(currentChar);
else buffer.append(this.chars);
this.comments.add(buffer.toString());
this.allTags.add(new ArrayList());
comment = 0;
break;
}
comment = DOC_COMMENT;
// $FALL-THROUGH$ - do not break, directly go to next case...
case DOC_COMMENT:
if (tag != null) { // a tag name is currently scanned
if (currentChar >= 'a' && currentChar <= 'z') {
tag += currentChar;
} else {
if (tag.equalsIgnoreCase(TAG_LITERAL) || tag.equalsIgnoreCase(TAG_CODE)) considerTagAsPlainText = true;
tags.add(tag);
tag = null;
}
}
// Some characters are special in javadoc comments
switch (currentChar) {
case '@':
if (!lineStarted) {
tag = "";
lineStarted = true;
} else if (previousChar == '{') {
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=206345
if (considerTagAsPlainText) {
openingBraces++;
} else {
tag = "";
lineStarted = true;
}
}
break;
case '\r':
case '\n':
lineStarted = false;
break;
case '*':
break;
case '}':
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=206345
if (considerTagAsPlainText) {
if (openingBraces > 0) {
openingBraces--;
} else {
considerTagAsPlainText = false;
}
}
break;
default:
if (!Character.isWhitespace(currentChar)) {
lineStarted = true;
}
}
// $FALL-THROUGH$ - common treatment for block and javadoc comments
case BLOCK_COMMENT:
if (this.chars == null) buffer.append(currentChar);
else buffer.append(this.chars);
if (end && currentChar == '/') {
comment = 0;
lineStarted = false;
this.comments.add(buffer.toString());
this.allTags.add(tags);
tags = new ArrayList();
}
end = currentChar == '*';
break;
case LINE_COMMENT:
if (currentChar == '\r' || currentChar == '\n') {
/*
if (currentChar == '\r' && source[i+1] == '\n') {
buffer.append(source[++i]);
}
*/
comment = 0;
this.comments.add(buffer.toString());
this.allTags.add(tags);
} else {
if (this.chars == null) buffer.append(currentChar);
else buffer.append(this.chars);
}
break;
default:
// do nothing
break;
}
}
}
/*
* Convert Javadoc source to match Javadoc.toString().
* Store converted comments and their corresponding tags respectively
* in comments and allTags fields
*/
char[] getUnicodeSource(char[] source) {
int length = source.length;
int unicodeLength = length*6;
char[] unicodeSource = new char[unicodeLength];
int u=0;
for (int i=0; i<length; i++) {
// get next char
if (source[i] == '\\' && source[i+1] == 'u') {
//-------------unicode traitement ------------
int c1, c2, c3, c4;
unicodeSource[u++] = source[i];
unicodeSource[u++] = source[++i];
if (((c1 = ScannerHelper.getHexadecimalValue(source[i+1])) > 15 || c1 < 0)
|| ((c2 = ScannerHelper.getHexadecimalValue(source[i+2])) > 15 || c2 < 0)
|| ((c3 = ScannerHelper.getHexadecimalValue(source[i+3])) > 15 || c3 < 0)
|| ((c4 = ScannerHelper.getHexadecimalValue(source[i+4])) > 15 || c4 < 0)) {
throw new RuntimeException("Invalid unicode in source at "+i);
}
for (int j=0; j<4; j++) unicodeSource[u++] = source[++i];
} else {
unicodeSource[u++] = '\\';
unicodeSource[u++] = 'u';
unicodeSource[u++] = '0';
unicodeSource[u++] = '0';
int val = source[i]/16;
unicodeSource[u++] = (char) (val<10 ? val+ 0x30 : val-10+0x61);
val = source[i]%16;
unicodeSource[u++] = (char) (val<10 ? val+ 0x30 : val-10+0x61);
}
}
// Return one well sized array
if (u != unicodeLength) {
char[] result = new char[u];
System.arraycopy(unicodeSource, 0, result, 0, u);
return result;
}
return unicodeSource;
}
/*
* Convert Javadoc source to match Javadoc.toString().
* Store converted comments and their corresponding tags respectively
* in comments and allTags fields
*/
char[] getUnixSource(char[] source) {
int length = source.length;
int unixLength = length;
char[] unixSource = new char[unixLength];
int u=0;
for (int i=0; i<length; i++) {
// get next char
if (source[i] == '\r' && source[i+1] == '\n') {
i++;
}
unixSource[u++] = source[i];
}
// Return one well sized array
if (u != unixLength) {
char[] result = new char[u];
System.arraycopy(unixSource, 0, result, 0, u);
return result;
}
return unixSource;
}
/*
* Return all tags number for a given Javadoc
*/
int allTags(Javadoc docComment) {
int all = 0;
// Count main tags
Iterator tags = docComment.tags().listIterator();
while (tags.hasNext()) {
TagElement tagElement = (TagElement) tags.next();
if (tagElement.getTagName() != null) {
all++;
}
Iterator fragments = tagElement.fragments().listIterator();
while (fragments.hasNext()) {
ASTNode node = (ASTNode) fragments.next();
if (node.getNodeType() == ASTNode.TAG_ELEMENT) {
all++;
}
}
}
return all;
}
/*
* Add a failure to the list. Use only one method as it easier to put breakpoint to
* debug failure when it occurs...
*/
private void addFailure(String msg) {
this.failures.add(msg);
}
/*
* Put the failure message in list instead of throwing exception immediately.
* This allow to store several failures per test...
* @see tearDown method which finally throws the execption to signal that test fails.
*/
protected void assumeTrue(String msg, boolean cond) {
if (!cond) {
addFailure(msg);
if (this.stopOnFailure) assertTrue(msg, cond);
}
}
/*
* Put the failure message in list instead of throwing exception immediately.
* This allow to store several failures per test...
* @see tearDown method which finally throws the execption to signal that test fails.
*/
protected void assumeNull(String msg, Object obj) {
if (obj != null) {
addFailure(msg);
if (this.stopOnFailure) assertNull(msg, obj);
}
}
/*
* Put the failure message in list instead of throwing exception immediately.
* This allow to store several failures per test...
* @see tearDown method which finally throws the execption to signal that test fails.
*/
protected void assumeNotNull(String msg, Object obj) {
if (obj == null) {
addFailure(msg);
if (this.stopOnFailure) assertNotNull(msg, obj);
}
}
/*
* Put the failure message in list instead of throwing exception immediately.
* This allow to store several failures per test...
* @see tearDown method which finally throws the execption to signal that test fails.
*/
protected void assumeEquals(String msg, int expected, int actual) {
if (expected != actual) {
addFailure(msg+", expected="+expected+" actual="+actual);
if (this.stopOnFailure) assertEquals(msg, expected, actual);
}
}
/*
* Put the failure message in list instead of throwing exception immediately.
* This allow to store several failures per test...
* @see tearDown method which finally throws the execption to signal that test fails.
*/
protected void assumeEquals(String msg, Object expected, Object actual) {
if (expected == null && actual == null)
return;
if (expected != null && expected.equals(actual))
return;
addFailure(msg+", expected:<"+expected+"> actual:<"+actual+'>');
if (this.stopOnFailure) assertEquals(msg, expected, actual);
}
/* (non-Javadoc)
* @see junit.framework.TestCase#setUp()
*/
protected void verifyComments(String test) throws JavaModelException {
ICompilationUnit[] units = getCompilationUnits("Converter" , "src", "javadoc."+test); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
for (int i=0; i<units.length; i++) {
verifyComments(units[i]);
}
}
/*
* Verify the comments of a compilation unit.
*/
protected void verifyWorkingCopiesComments() throws JavaModelException {
assumeNotNull("No working copies to verify!", this.workingCopies);
int length = this.workingCopies.length;
assumeTrue("We need to have at least one working copy to verify!", length>0);
for (int i=0; i<length; i++) {
verifyComments(this.workingCopies[i]);
}
}
/*
* Verify the comments of a compilation unit.
*/
protected CompilationUnit verifyComments(ICompilationUnit unit) throws JavaModelException {
// Get test file
this.sourceUnit = unit;
this.prefix = unit.getElementName()+": ";
// Get current project
String sourceStr = this.sourceUnit.getSource();
if (this.savedOptions != null && !this.sourceUnit.getJavaProject().getElementName().equals(this.currentProject.getElementName())) {
this.currentProject.setOptions(this.savedOptions);
this.savedOptions = null;
}
this.currentProject = this.sourceUnit.getJavaProject();
if (this.savedOptions == null) this.savedOptions = this.currentProject.getOptions(false);
// set up java project options
this.currentProject.setOption(JavaCore.COMPILER_PB_INVALID_JAVADOC, this.compilerOption);
this.currentProject.setOption(JavaCore.COMPILER_PB_MISSING_JAVADOC_TAGS, this.compilerOption);
this.currentProject.setOption(JavaCore.COMPILER_PB_MISSING_JAVADOC_COMMENTS, this.compilerOption);
this.currentProject.setOption(JavaCore.COMPILER_PB_METHOD_WITH_CONSTRUCTOR_NAME, JavaCore.IGNORE);
this.currentProject.setOption(JavaCore.COMPILER_DOC_COMMENT_SUPPORT, JavaCore.ENABLED);
// Verify source regardings converted comments
char[] source = sourceStr.toCharArray();
String fileName = unit.getPath().toString();
try {
return verifyComments(fileName, source);
}
catch (RuntimeException ex) {
TEST_COUNTERS[3]++;
throw ex;
}
}
protected CompilationUnit verifyComments(String fileName, char[] source) {
return verifyComments(fileName, source, null);
}
protected CompilationUnit verifyComments(String fileName, char[] source, Map options) {
// Verify comments either in unicode or not
char[] testedSource = source;
if (UNICODE) {
testedSource = getUnicodeSource(source);
}
// Get comments infos from test file
setSourceComment(testedSource);
// Create DOM AST nodes hierarchy
List unitComments = null;
String sourceLevel = null;
String complianceLevel = null;
if (this.currentProject != null) {
complianceLevel = this.currentProject.getOption(JavaCore.COMPILER_COMPLIANCE, true);
sourceLevel = this.currentProject.getOption(JavaCore.COMPILER_SOURCE, true);
this.currentProject.setOption(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_18);
this.currentProject.setOption(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_18);
}
CompilationUnit compilUnit = (CompilationUnit) runConversion(testedSource, fileName, this.currentProject, options);
if (this.compilerOption.equals(JavaCore.ERROR)) {
assumeEquals(this.prefix+"Unexpected problems", 0, compilUnit.getProblems().length); //$NON-NLS-1$
} else if (this.compilerOption.equals(JavaCore.WARNING)) {
IProblem[] problemsList = compilUnit.getProblems();
int length = problemsList.length;
if (length > 0) {
this.problems.append(" - "+this.prefix+length+" problems:"); //$NON-NLS-1$
for (int i = 0; i < problemsList.length; i++) {
this.problems.append(" + ");
this.problems.append(problemsList[i]);
this.problems.append("\n");
}
}
}
unitComments = compilUnit.getCommentList();
assumeNotNull(this.prefix+"Unexpected problems", unitComments);
// Basic comments verification
int size = unitComments.size();
assumeEquals(this.prefix+"Wrong number of comments!", this.comments.size(), size);
// Verify comments positions and bindings
for (int i=0; i<size; i++) {
Comment comment = (Comment) unitComments.get(i);
List tags = (List) this.allTags.get(i);
// Verify flattened content
String stringComment = (String) this.comments.get(i);
// ASTConverterJavadocFlattener printer = new ASTConverterJavadocFlattener(stringComment);
// comment.accept(printer);
String text = new String(testedSource, comment.getStartPosition(), comment.getLength());
assumeEquals(this.prefix+"Flattened comment does NOT match source!", stringComment, text);
// Verify javdoc tags positions and bindings
if (comment.isDocComment()) {
Javadoc docComment = (Javadoc)comment;
assumeEquals(this.prefix+"Invalid tags number in javadoc:\n"+docComment+"\n", tags.size(), allTags(docComment));
}
}
/* Verify each javadoc: not implemented yet
Iterator types = compilUnit.types().listIterator();
while (types.hasNext()) {
TypeDeclaration typeDeclaration = (TypeDeclaration) types.next();
verifyJavadoc(typeDeclaration.getJavadoc());
}
*/
if (sourceLevel != null) {
this.currentProject.setOption(JavaCore.COMPILER_COMPLIANCE, complianceLevel);
this.currentProject.setOption(JavaCore.COMPILER_SOURCE, sourceLevel);
}
// Return compilation unit for possible further verifications
return compilUnit;
}
private TagElement getSnippetTag(Javadoc docComment) {
TagElement snippet = null;
if (docComment != null) {
for (Object tag : docComment.tags()) {
if (tag instanceof TagElement) {
TagElement tagElement = (TagElement) tag;
if (SNIPPET_TAG.equals(tagElement.getTagName())) {
return tagElement;
}
List fragments = tagElement.fragments();
for (Object fragment : fragments) {
if (fragment instanceof TagElement) {
TagElement tagElem = (TagElement) fragment;
if (SNIPPET_TAG.equals(tagElem.getTagName())) {
return tagElem;
}
}
}
}
}
}
return snippet;
}
public void testSnippetStartJavadoc1() throws JavaModelException {
this.workingCopies = new ICompilationUnit[1];
this.workingCopies[0] = getWorkingCopy("/Converter_15_1/src/javadoc/X.java",
"package javadoc;\n" +
"public class X {\n" +
" /**\n" +
" * Below is an example snippet\n" +
" * {@snippet :\n" +
" * System.out.println(); \n" +
" * }\n" +
" */\n" +
" public static void foo(Object object) {\n" +
" }\n" +
"}\n"
);
CompilationUnit compilUnit = verifyComments(this.workingCopies[0]);
// Get comments
List unitComments = compilUnit.getCommentList();
int size = unitComments.size();
assertEquals("Wrong number of comments", 1, size);
Javadoc javadoc = (Javadoc) unitComments.get(0);
TagElement snippetTag = getSnippetTag(javadoc);
assertNotNull("Snippet Tag is not present", snippetTag);
Object validPorperty = snippetTag.getProperty(TagProperty.TAG_PROPERTY_SNIPPET_IS_VALID);
assertNotNull("Snippet Tag valid property not present", validPorperty);
assertEquals("Snippet should be valid", true, (validPorperty instanceof Boolean) ? ((Boolean)validPorperty).booleanValue() : false);
}
public void testSnippetStartJavadoc2() throws JavaModelException {
this.workingCopies = new ICompilationUnit[1];
this.workingCopies[0] = getWorkingCopy("/Converter_15_1/src/javadoc/X.java",
"package javadoc;\n" +
"public class X {\n" +
" /**\n" +
" * Below is an example snippet\n" +
" * {@snippet \n" +
" * \n" +
" * \n" +
" * \n" +
" *\n" +
" * :\n" +
" * System.out.println(); \n" +
" * }\n" +
" */\n" +
" public static void foo(Object object) {\n" +
" }\n" +
"}\n"
);
CompilationUnit compilUnit = verifyComments(this.workingCopies[0]);
// Get comments
List unitComments = compilUnit.getCommentList();
int size = unitComments.size();
assertEquals("Wrong number of comments", 1, size);
Javadoc javadoc = (Javadoc) unitComments.get(0);
TagElement snippetTag = getSnippetTag(javadoc);
assertNotNull("Snippet Tag is not present", snippetTag);
Object validPorperty = snippetTag.getProperty(TagProperty.TAG_PROPERTY_SNIPPET_IS_VALID);
assertNotNull("Snippet Tag valid property not present", validPorperty);
assertEquals("Snippet should be valid", true, (validPorperty instanceof Boolean) ? ((Boolean)validPorperty).booleanValue() : false);
}
public void testSnippetStartJavadoc3() throws JavaModelException {
this.workingCopies = new ICompilationUnit[1];
this.workingCopies[0] = getWorkingCopy("/Converter_15_1/src/javadoc/X.java",
"package javadoc;\n" +
"public class X {\n" +
" /**\n" +
" * Below is an example snippet\n" +
" * {@snippet \n" +
" * \n" +
" * \n" +
" \n" +
" *\n" +
" * :\n" +
" * System.out.println(); \n" +
" * }\n" +
" */\n" +
" public static void foo(Object object) {\n" +
" }\n" +
"}\n"
);
CompilationUnit compilUnit = verifyComments(this.workingCopies[0]);
// Get comments
List unitComments = compilUnit.getCommentList();
int size = unitComments.size();
assertEquals("Wrong number of comments", 1, size);
Javadoc javadoc = (Javadoc) unitComments.get(0);
TagElement snippetTag = getSnippetTag(javadoc);
assertNotNull("Snippet Tag is not present", snippetTag);
Object validPorperty = snippetTag.getProperty(TagProperty.TAG_PROPERTY_SNIPPET_IS_VALID);
assertNotNull("Snippet Tag valid property not present", validPorperty);
assertEquals("Snippet should be valid", true, (validPorperty instanceof Boolean) ? ((Boolean)validPorperty).booleanValue() : false);
}
public void testSnippetStartJavadoc4() throws JavaModelException {
this.workingCopies = new ICompilationUnit[1];
this.workingCopies[0] = getWorkingCopy("/Converter_15_1/src/javadoc/X.java",
"package javadoc;\n" +
"public class X {\n" +
" /**\n" +
" * Below is an example snippet\n" +
" * {@snippet \n" +
" * \n" +
" * \n" +
" \n" +
" *\n" +
" * : a\n" +
" * System.out.println(); \n" +
" * }\n" +
" */\n" +
" public static void foo(Object object) {\n" +
" }\n" +
"}\n"
);
CompilationUnit compilUnit = verifyComments(this.workingCopies[0]);
// Get comments
List unitComments = compilUnit.getCommentList();
int size = unitComments.size();
assertEquals("Wrong number of comments", 1, size);
Javadoc javadoc = (Javadoc) unitComments.get(0);
TagElement snippetTag = getSnippetTag(javadoc);
assertNotNull("Snippet Tag is not present", snippetTag);
Object validPorperty = snippetTag.getProperty(TagProperty.TAG_PROPERTY_SNIPPET_IS_VALID);
assertNotNull("Snippet Tag valid property not present", validPorperty);
assertEquals("Snippet should not be valid", false, (validPorperty instanceof Boolean) ? ((Boolean)validPorperty).booleanValue() : false);
}
public void testSnippetMultiLineTagsJavadoc1() throws JavaModelException {
this.workingCopies = new ICompilationUnit[1];
this.workingCopies[0] = getWorkingCopy("/Converter_15_1/src/javadoc/X.java",
"package javadoc;\n" +
"public class X {\n" +
" /**\n" +
" * Below is an example snippet\n" +
" * {@snippet :\n" +
" * //Starting Code // @highlight substring=\"out\" :\n" +
" * System.out.println(); // @highlight substring=\"print\"\n" +
" * }\n" +
" */\n" +
" public static void foo(Object object) {\n" +
" }\n" +
"}\n"
);
CompilationUnit compilUnit = verifyComments(this.workingCopies[0]);
// Get comments
List unitComments = compilUnit.getCommentList();
int size = unitComments.size();
assertEquals("Wrong number of comments", 1, size);
Javadoc javadoc = (Javadoc) unitComments.get(0);
TagElement snippetTag = getSnippetTag(javadoc);
assertNotNull("Snippet Tag is not present", snippetTag);
Object validPorperty = snippetTag.getProperty(TagProperty.TAG_PROPERTY_SNIPPET_IS_VALID);
assertNotNull("Snippet Tag valid property not present", validPorperty);
assertEquals("Snippet should be valid", true, (validPorperty instanceof Boolean) ? ((Boolean)validPorperty).booleanValue() : false);
List fragments = snippetTag.fragments();
assertEquals("Three fragments should be created", 3, fragments.size());
assertEquals("First Tag should be TextElement", true, fragments.get(0) instanceof TextElement);
assertEquals("Second Tag should be JavaDocRegion", true, fragments.get(1) instanceof JavaDocRegion);
JavaDocRegion region = (JavaDocRegion) fragments.get(1);
assertEquals("JavaDocRegion should be dummy", true, region.isDummyRegion());
assertEquals("third Tag should be TextElement", true, fragments.get(2) instanceof TextElement);
assertEquals("JavaDocRegion should have 2 tags", 2, region.tags().size());
assertEquals("JavaDocRegion should have 1 text fragmwent", 1, region.fragments().size());
}
public void testSnippetMultiLineTagsJavadoc2() throws JavaModelException {
this.workingCopies = new ICompilationUnit[1];
this.workingCopies[0] = getWorkingCopy("/Converter_15_1/src/javadoc/X.java",
"package javadoc;\n" +
"public class X {\n" +
" /**\n" +
" * Below is an example snippet\n" +
" * {@snippet :\n" +
" * //Starting Code // @highlight substring=\"out\" @highlight substring=\"Sys\" :\n" +
" * System.out.println(); // @highlight substring=\"print\"\n" +
" * }\n" +
" */\n" +
" public static void foo(Object object) {\n" +
" }\n" +
"}\n"
);
CompilationUnit compilUnit = verifyComments(this.workingCopies[0]);
// Get comments
List unitComments = compilUnit.getCommentList();
int size = unitComments.size();
assertEquals("Wrong number of comments", 1, size);
Javadoc javadoc = (Javadoc) unitComments.get(0);
TagElement snippetTag = getSnippetTag(javadoc);
assertNotNull("Snippet Tag is not present", snippetTag);
Object validPorperty = snippetTag.getProperty(TagProperty.TAG_PROPERTY_SNIPPET_IS_VALID);
assertNotNull("Snippet Tag valid property not present", validPorperty);
assertEquals("Snippet should be valid", true, (validPorperty instanceof Boolean) ? ((Boolean)validPorperty).booleanValue() : false);
List fragments = snippetTag.fragments();
assertEquals("Three fragments should be created", 3, fragments.size());
assertEquals("First Tag should be TextElement", true, fragments.get(0) instanceof TextElement);
assertEquals("Second Tag should be JavaDocRegion", true, fragments.get(1) instanceof JavaDocRegion);
JavaDocRegion region = (JavaDocRegion) fragments.get(1);
assertEquals("JavaDocRegion should be dummy", true, region.isDummyRegion());
assertEquals("third Tag should be TextElement", true, fragments.get(2) instanceof TextElement);
assertEquals("JavaDocRegion should have 3 tags", 3, region.tags().size());
assertEquals("JavaDocRegion should have 1 text fragmwent", 1, region.fragments().size());
}
public void testSnippetMultiLineTagsJavadoc3() throws JavaModelException {
this.workingCopies = new ICompilationUnit[1];
this.workingCopies[0] = getWorkingCopy("/Converter_15_1/src/javadoc/X.java",
"package javadoc;\n" +
"public class X {\n" +
" /**\n" +
" * Below is an example snippet\n" +
" * {@snippet :\n" +
" * //Starting Code // @highlight region substring=\"out\" :\n" +
" * System.out.println(); // @highlight substring=\"print\" @end\n" +
" * }\n" +
" */\n" +
" public static void foo(Object object) {\n" +
" }\n" +
"}\n"
);
CompilationUnit compilUnit = verifyComments(this.workingCopies[0]);
// Get comments
List unitComments = compilUnit.getCommentList();
int size = unitComments.size();
assertEquals("Wrong number of comments", 1, size);
Javadoc javadoc = (Javadoc) unitComments.get(0);
TagElement snippetTag = getSnippetTag(javadoc);
assertNotNull("Snippet Tag is not present", snippetTag);
Object validPorperty = snippetTag.getProperty(TagProperty.TAG_PROPERTY_SNIPPET_IS_VALID);
assertNotNull("Snippet Tag valid property not present", validPorperty);
assertEquals("Snippet should be valid", true, (validPorperty instanceof Boolean) ? ((Boolean)validPorperty).booleanValue() : false);
List fragments = snippetTag.fragments();
assertEquals("Four fragments should be created", 4, fragments.size());
assertEquals("First Tag should be TextElement", true, fragments.get(0) instanceof TextElement);
assertEquals("Second Tag should be JavaDocRegion", true, fragments.get(1) instanceof JavaDocRegion);
JavaDocRegion region = (JavaDocRegion) fragments.get(1);
assertEquals("JavaDocRegion should be dummy", false, region.isDummyRegion());
assertEquals("third Tag should be TextElement", true, fragments.get(2) instanceof TagElement);
TagElement tagElem = (TagElement) fragments.get(2);
assertEquals("third Tag should be TextElement", true, fragments.get(3) instanceof TextElement);
assertEquals("TagElement should have 1 fragment", 1, tagElem.fragments().size());
assertEquals("Tag element fragment should be TextElement", true, tagElem.fragments().get(0) instanceof TextElement);
TextElement textElem = (TextElement) tagElem.fragments().get(0);
List<JavaDocRegion> regions = snippetTag.tagRegionsContainingTextElement(textElem);
assertEquals("regions count should be 1", 1, regions.size());
assertEquals("original JavaDocRegion should be present here", true, regions.contains(region));
}
public void testSnippetMultiLineTagsJavadoc4() throws JavaModelException {
this.workingCopies = new ICompilationUnit[1];
this.workingCopies[0] = getWorkingCopy("/Converter_15_1/src/javadoc/X.java",
"package javadoc;\n" +
"public class X {\n" +
" /**\n" +
" * Below is an example snippet\n" +
" * {@snippet :\n" +
" * //Starting Code // @highlight substring=\"out\" :\n" +
" * System.out.println(); // @highlight substring=\"print\" :\n" +
" * System.out.println();\n" +
" * }\n" +
" */\n" +
" public static void foo(Object object) {\n" +
" }\n" +
"}\n"
);
CompilationUnit compilUnit = verifyComments(this.workingCopies[0]);
// Get comments
List unitComments = compilUnit.getCommentList();
int size = unitComments.size();
assertEquals("Wrong number of comments", 1, size);
Javadoc javadoc = (Javadoc) unitComments.get(0);
TagElement snippetTag = getSnippetTag(javadoc);
assertNotNull("Snippet Tag is not present", snippetTag);
Object validPorperty = snippetTag.getProperty(TagProperty.TAG_PROPERTY_SNIPPET_IS_VALID);
assertNotNull("Snippet Tag valid property not present", validPorperty);
assertEquals("Snippet should be valid", true, (validPorperty instanceof Boolean) ? ((Boolean)validPorperty).booleanValue() : false);
List fragments = snippetTag.fragments();
assertEquals("Four fragments should be created", 4, fragments.size());
assertEquals("First fragment should be TextElement", true, fragments.get(0) instanceof TextElement);
assertEquals("Second fragment should be TagElement", true, fragments.get(1) instanceof TagElement);
TagElement tagElem = (TagElement) fragments.get(1);
assertEquals("TagElement should have 1 fragment", 1, tagElem.fragments().size());
assertEquals("Tag element fragment should be TextElement", true, tagElem.fragments().get(0) instanceof TextElement);
assertEquals("Third fragment should be TagElement", true, fragments.get(1) instanceof TagElement);
tagElem = (TagElement) fragments.get(2);
assertEquals("TagElement should have 1 fragment", 1, tagElem.fragments().size());
assertEquals("Tag element fragment should be TextElement", true, tagElem.fragments().get(0) instanceof TextElement);
assertEquals("Fourth fragment should be TextElement", true, fragments.get(3) instanceof TextElement);
}
}