### Eclipse Workspace Patch 1.0
#P org.eclipse.jdt.core.tests.model
Index: src/org/eclipse/jdt/core/tests/formatter/FormatterCommentsMassiveTests.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterCommentsMassiveTests.java,v
retrieving revision 1.21
diff -u -r1.21 FormatterCommentsMassiveTests.java
--- src/org/eclipse/jdt/core/tests/formatter/FormatterCommentsMassiveTests.java 29 May 2008 09:31:52 -0000 1.21
+++ src/org/eclipse/jdt/core/tests/formatter/FormatterCommentsMassiveTests.java 13 Jun 2008 16:21:14 -0000
@@ -15,12 +15,10 @@
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.StringTokenizer;
import junit.framework.AssertionFailedError;
import junit.framework.ComparisonFailure;
@@ -30,16 +28,9 @@
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.formatter.CodeFormatter;
-import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;
import org.eclipse.jdt.core.tests.model.ModelTestsUtil;
import org.eclipse.jdt.core.tests.util.Util;
-import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
-import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
-import org.eclipse.jdt.internal.compiler.parser.Scanner;
-import org.eclipse.jdt.internal.core.util.CodeSnippetParsingUtil;
-import org.eclipse.jdt.internal.core.util.SimpleDocument;
import org.eclipse.jdt.internal.formatter.DefaultCodeFormatter;
import org.eclipse.jdt.internal.formatter.DefaultCodeFormatterOptions;
import org.eclipse.text.edits.TextEdit;
@@ -102,77 +93,106 @@
* linesLeading
(e.g. ignore white spaces at the beginning of the
* lines, including the star inside javadoc or block comments):
*
tags (blank lines) have been found"); - } - System.out.println(); - if (sFailures > 0) { - System.out.println("List of files with different output "+failuresType+":"); - for (int i=0; i0) { - System.out.println("List of files with different output "+failuresType+" (due to old formatter bugs):"); - for (int i=0; i 0) { - System.out.println("List of files with different line leading spaces "+failuresType+":"); - for (int i=0; i 0) { + System.out.print(size); + System.out.print(" file"); + if (size == 1) { + System.out.print(" has "); + } else { + System.out.print("s have "); + } + System.out.print(FAILURES[i]); + System.out.println('!'); } } - if (swFailures > 0) { - System.out.println("List of files with different spaces "+failuresType+":"); - for (int i=0; i 0) { + System.out.println("List of file(s) with "+FAILURES[i]+":"); + for (int j=0; j 3 || end < (length - 2)) { - this.changedHeaderFooter++; - return comment.substring(start, end); - } - return comment; -} - -private String cleanBlankLinesAfterLineComment(String comment) { - int length = comment.length(); - if (comment.charAt(length-1) == '\n') { - length--; - if (comment.charAt(length-1) == '\r') { - length--; - } - return comment.substring(0, length); - } - return comment; -} - -private String cleanCodeTags(String comment) { - if (comment.indexOf(" ") < 0) return comment; - StringTokenizer tokenizer = new StringTokenizer(comment, "\r\n\f"); - StringBuffer buffer = new StringBuffer(); - while (tokenizer.hasMoreTokens()) { - String line = tokenizer.nextToken(); - if (line.indexOf("
") >= 0) { - while (line.indexOf("") < 0) { - line = tokenizer.nextToken(); - } - } else { - buffer.append(line); - buffer.append("\n"); - } - } - this.changedCodeTags++; - return buffer.toString(); -} - -private String cleanPreTags(String comment) { - if (comment.indexOf("") < 0) return comment; - StringTokenizer tokenizer = new StringTokenizer(comment, "\r\n\f"); - StringBuffer buffer = new StringBuffer(); - StringBuffer emptyLines = new StringBuffer(); - String previousLine = null; - while (tokenizer.hasMoreTokens()) { - String line = tokenizer.nextToken(); - if (line.trim() == "*") { - if (previousLine == null || previousLine.indexOf("") < 0) { - buffer.append(line); - buffer.append("\n"); - continue; - } else { - emptyLines.append(line); - emptyLines.append("\n"); - } - } else if (line.indexOf("") < 0) { - buffer.append(emptyLines); - emptyLines.setLength(0); - } - buffer.append(line); - buffer.append("\n"); - } else { - buffer.append(line); - buffer.append("\n"); - } - previousLine = line; + if (ASSERT_EQUALS_STRINGS) { + assertEquals(message, expected, actual); + } else { + assertTrue(message, actual.equals(expected)); } - this.changedPreTags++; - return buffer.toString(); } DefaultCodeFormatter codeFormatter() { - DefaultCodeFormatterOptions preferences = DefaultCodeFormatterOptions.getEclipseDefaultSettings(); - DefaultCodeFormatter codeFormatter = new DefaultCodeFormatter(preferences); + DefaultCodeFormatter codeFormatter = new DefaultCodeFormatter(this.preferences, getDefaultCompilerOptions()); return codeFormatter; } void compareFormattedSource() throws IOException, Exception { - DefaultCodeFormatter codeFormatter = codeFormatter(); String source = new String(org.eclipse.jdt.internal.compiler.util.Util.getFileCharContent(this.file, null)); try { - if ("comments".equals(COMPARE)) { - String[] oldFormattedComments = formattedComments(source, true); - String[] newFormattedComments = formattedComments(source, false); - int length = oldFormattedComments == null ? 0 : oldFormattedComments.length; - this.abortOnFailure = false; - assertEquals("Unexpected number of comments!", length, newFormattedComments == null ? 0 : newFormattedComments.length); - for (int i=0; i") >= 0) { - while (line.indexOf("
") < 0) { - line = tokenizer.nextToken(); - } - } else if (emptyLines.length() != 0) { - if (line.indexOf("0) { // block comments have positive start position - commentKind = CodeFormatter.K_MULTI_LINE_COMMENT; - } else { - commentStart = -commentStart; - commentKind = CodeFormatter.K_SINGLE_LINE_COMMENT; - } - } - if (commentStart >= headerEndPosition) { - int indentationLevel = getIndentationLevel(scanner, commentStart); - formattedComments[i] = runFormatter(codeFormatter, source.substring(commentStart, commentEnd), commentKind, indentationLevel, 0, commentEnd - commentStart, LINE_SEPARATOR); - } - } - SimpleDocument document = new SimpleDocument(source); - for (int i=length-1; i>=0; i--) { - if (formattedComments[i] != null) { - int[] positions = commentsPositions[i]; - int commentStart = positions [0]; - int commentEnd = positions [1]; - if (commentEnd < 0) { // line or block comments have negative end position - commentEnd = -commentEnd; - if (commentStart < 0) { // line comments have negative start position - commentStart = -commentStart; - } - } - document.replace(commentStart, commentEnd - commentStart, formattedComments[i]); - } - } - String newSource = document.get(); - String oldResult = runFormatter(codeFormatter, newSource, CodeFormatter.K_COMPILATION_UNIT, 0, 0, newSource.length(), null); - return oldResult == null ? newSource : oldResult; - } - finally { - DefaultCodeFormatter.ENABLE_NEW_COMMENTS_FORMAT = enableNewCommentFormatter; - } -} -private String[] formattedComments(String source, boolean old) { - boolean enableNewCommentFormatter = DefaultCodeFormatter.ENABLE_NEW_COMMENTS_FORMAT; - try { - DefaultCodeFormatter.ENABLE_NEW_COMMENTS_FORMAT = !old; - DefaultCodeFormatter codeFormatter = codeFormatter(); - Scanner scanner = new Scanner(true, true, false/*nls*/, ClassFileConstants.JDK1_4/*sourceLevel*/, null/*taskTags*/, null/*taskPriorities*/, true/*taskCaseSensitive*/); - CodeSnippetParsingUtil codeSnippetParsingUtil = new CodeSnippetParsingUtil(); - CompilationUnitDeclaration compilationUnitDeclaration = codeSnippetParsingUtil.parseCompilationUnit(source.toCharArray(), getDefaultCompilerOptions(), true); - final TypeDeclaration[] types = compilationUnitDeclaration.types; - int headerEndPosition = types == null ? compilationUnitDeclaration.sourceEnd : types[0].declarationSourceStart; - scanner.setSource(source.toCharArray()); - scanner.lineEnds = codeSnippetParsingUtil.recordedParsingInformation.lineEnds; - int[][] commentsPositions = compilationUnitDeclaration.comments; - int length = commentsPositions == null ? 0 : commentsPositions.length; - String[] formattedComments = new String[length]; - for (int i=0; i 0) { // block comments have positive start position - commentKind = CodeFormatter.K_MULTI_LINE_COMMENT; - } else { - commentStart = -commentStart; - commentKind = CodeFormatter.K_SINGLE_LINE_COMMENT; - } - } - if (commentStart >= headerEndPosition) { - int indentationLevel = getIndentationLevel(scanner, commentStart); - formattedComments[i] = runFormatter(codeFormatter, source.substring(commentStart, commentEnd), commentKind, indentationLevel, 0, commentEnd - commentStart, LINE_SEPARATOR); - } - } - return formattedComments; - } - finally { - DefaultCodeFormatter.ENABLE_NEW_COMMENTS_FORMAT = enableNewCommentFormatter; - } -} - -private int getIndentationLevel(Scanner scanner, int position) { - int indentationLevel = 0; - int numberOfIndentations = 0; - int indentationSize; - try { - indentationSize = Integer.parseInt(DefaultCodeFormatterConstants.FORMATTER_TAB_SIZE); - } catch (NumberFormatException nfe) { - indentationSize = 4; - } - int lineNumber = scanner.getLineNumber(position); - int lineStart = scanner.getLineStart(lineNumber); - scanner.resetTo(lineStart, position-1); - while (!scanner.atEnd()) { - int ch = scanner.getNextChar(); - switch (ch) { - case '\n': - indentationLevel = 0; - numberOfIndentations = 0; - break; - case '\t': - numberOfIndentations++; - indentationLevel = numberOfIndentations * indentationSize; - break; - default: - indentationLevel++; - if ((indentationLevel%indentationSize) == 0) { - numberOfIndentations++; - } - break; - } - } - if ((indentationLevel%indentationSize) != 0) { - numberOfIndentations++; - indentationLevel = numberOfIndentations * indentationSize; - } - return numberOfIndentations; -} - private Map getDefaultCompilerOptions() { Map optionsMap = new HashMap(30); optionsMap.put(CompilerOptions.OPTION_LocalVariableAttribute, CompilerOptions.DO_NOT_GENERATE); @@ -751,8 +462,8 @@ optionsMap.put(CompilerOptions.OPTION_ReportUnusedDeclaredThrownException, CompilerOptions.IGNORE); optionsMap.put(CompilerOptions.OPTION_ReportUnusedDeclaredThrownExceptionWhenOverriding, CompilerOptions.DISABLED); optionsMap.put(CompilerOptions.OPTION_ReportUnqualifiedFieldAccess, CompilerOptions.IGNORE); - optionsMap.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_4); - optionsMap.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_2); + optionsMap.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_6); + optionsMap.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_6); optionsMap.put(CompilerOptions.OPTION_TaskTags, ""); //$NON-NLS-1$ optionsMap.put(CompilerOptions.OPTION_TaskPriorities, ""); //$NON-NLS-1$ optionsMap.put(CompilerOptions.OPTION_TaskCaseSensitive, CompilerOptions.DISABLED); @@ -761,7 +472,7 @@ optionsMap.put(CompilerOptions.OPTION_ReportSpecialParameterHidingField, CompilerOptions.DISABLED); optionsMap.put(CompilerOptions.OPTION_MaxProblemPerUnit, String.valueOf(100)); optionsMap.put(CompilerOptions.OPTION_InlineJsr, CompilerOptions.DISABLED); - optionsMap.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_5); + optionsMap.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_6); return optionsMap; } @@ -769,62 +480,107 @@ int length = EXPECTED_FAILURES.length; for (int i=0; i = 0) { + FAILURES[REFORMATTING_EXPECTED_FAILURE].failures.add(this.path); return true; } } return false; } +/* +private boolean runFormatterWithoutComments(CodeFormatter codeFormatter, String source, int kind, int indentationLevel, int offset, int length, String lineSeparator) { + DefaultCodeFormatterOptions preferencesWithoutComment = DefaultCodeFormatterOptions.getEclipseDefaultSettings(); + preferencesWithoutComment.comment_format_line_comment = false; + preferencesWithoutComment.comment_format_block_comment = false; + preferencesWithoutComment.comment_format_javadoc_comment = false; + DefaultCodeFormatter codeFormatterWithoutComment = new DefaultCodeFormatter(preferencesWithoutComment); + + TextEdit edit = codeFormatterWithoutComment.format(kind, source, offset, length, indentationLevel, lineSeparator);//$NON-NLS-1$ + if (edit == null) return false; + String initialResult = org.eclipse.jdt.internal.core.util.Util.editedString(source, edit); + + int count = 1; + String result = initialResult; + String previousResult = result; + while (count++ < FORMAT_REPEAT) { + edit = codeFormatterWithoutComment.format(kind, result, 0, result.length(), indentationLevel, lineSeparator);//$NON-NLS-1$ + if (edit == null) return false; + previousResult = result; + result = org.eclipse.jdt.internal.core.util.Util.editedString(result, edit); + } + return previousResult.equals(result); +} +*/ + String runFormatter(CodeFormatter codeFormatter, String source, int kind, int indentationLevel, int offset, int length, String lineSeparator) { TextEdit edit = codeFormatter.format(kind, source, offset, length, indentationLevel, lineSeparator);//$NON-NLS-1$ - if (edit == null) return null; - String result = org.eclipse.jdt.internal.core.util.Util.editedString(source, edit); + try { + assertNotNull("Formatted source should not be null!", edit); + } + catch (ComparisonFailure cf) { + FAILURES[NO_OUTPUT_FAILURE].failures.add(this.path); + throw cf; + } + catch (AssertionFailedError afe) { + FAILURES[NO_OUTPUT_FAILURE].failures.add(this.path); + throw afe; + } + String initialResult = org.eclipse.jdt.internal.core.util.Util.editedString(source, edit); int count = 1; - if (COMPARE == null && length == source.length()) { - String previousResult = result; - while (count++ < FORMAT_REPEAT) { - edit = codeFormatter.format(kind, result, 0, result.length(), indentationLevel, lineSeparator);//$NON-NLS-1$ - if (edit == null) return null; - previousResult = result; - result = org.eclipse.jdt.internal.core.util.Util.editedString(result, edit); - } - if (!previousResult.equals(result)) { - switch (IGNORE_SPACES) { - case ALL_SPACES: - String trimmedExpected = ModelTestsUtil.removeWhiteSpace(previousResult); - String trimmedActual= ModelTestsUtil.removeWhiteSpace(result); - if (trimmedExpected.equals(trimmedActual)) { - this.whitespacesFailures.add(this.path); - this.hasSpaceFailure = true; - return previousResult; - } - break; - case LINES_LEADING_SPACES: - trimmedExpected = ModelTestsUtil.trimLinesLeadingWhitespaces(previousResult); - trimmedActual= ModelTestsUtil.trimLinesLeadingWhitespaces(result); - if (trimmedExpected.equals(trimmedActual)) { - this.leadingWhitespacesFailures.add(this.path); - this.hasSpaceFailure = true; - return previousResult; - } - if (ModelTestsUtil.removeWhiteSpace(previousResult).equals(ModelTestsUtil.removeWhiteSpace(result))) { - this.whitespacesFailures.add(this.path); - this.hasSpaceFailure = true; - return previousResult; - } - break; - } - if (!isExpectedFailure()) { - String counterString = counterToString(count-1); - assertSourceEquals(counterString+" formatting is different from first one!", Util.convertToIndependantLineDelimiter(previousResult), Util.convertToIndependantLineDelimiter(result)); + String result = initialResult; + String previousResult = result; + while (count++ < FORMAT_REPEAT) { + edit = codeFormatter.format(kind, result, 0, result.length(), indentationLevel, lineSeparator);//$NON-NLS-1$ + if (edit == null) return null; + previousResult = result; + result = org.eclipse.jdt.internal.core.util.Util.editedString(result, edit); + } + if (!previousResult.equals(result)) { + + // Try to compare without leading spaces + String trimmedExpected = ModelTestsUtil.trimLinesLeadingWhitespaces(previousResult); + String trimmedActual= ModelTestsUtil.trimLinesLeadingWhitespaces(result); + if (trimmedExpected.equals(trimmedActual)) { + FAILURES[REFORMATTING_LEADING_FAILURE].failures.add(this.path); + this.hasSpaceFailure = true; + return initialResult; + } + + // Try to compare without spaces at all + if (ModelTestsUtil.removeWhiteSpace(previousResult).equals(ModelTestsUtil.removeWhiteSpace(result))) { + FAILURES[REFORMATTING_WHITESPACES_FAILURE].failures.add(this.path); + this.hasSpaceFailure = true; + return initialResult; + } + + /* + // Try to see if the formatting also fails without comments + if (!runFormatterWithoutComments(null, source, kind, indentationLevel, offset, length, lineSeparator)) { + return initialResult; + } + + // format without comments is OK => there's a problem with comment formatting + String counterString = counterToString(count-1); + assertSourceEquals(counterString+" formatting is different from first one!", previousResult, result); + */ + if (!isExpectedFailure()) { + String counterString = counterToString(count-1); + try { + assertSourceEquals(counterString+" formatting is different from first one!", previousResult, result); + } + catch (ComparisonFailure cf) { + FAILURES[REFORMATTING_FAILURE].failures.add(this.path); + throw cf; + } + catch (AssertionFailedError afe) { + FAILURES[REFORMATTING_FAILURE].failures.add(this.path); + throw afe; } - result = previousResult; } } - return result; + return initialResult; } public void testCompare() throws IOException, Exception { Index: src/org/eclipse/jdt/core/tests/formatter/FormatterCommentsBugsTest.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterCommentsBugsTest.java,v retrieving revision 1.11 diff -u -r1.11 FormatterCommentsBugsTest.java --- src/org/eclipse/jdt/core/tests/formatter/FormatterCommentsBugsTest.java 29 May 2008 09:28:37 -0000 1.11 +++ src/org/eclipse/jdt/core/tests/formatter/FormatterCommentsBugsTest.java 13 Jun 2008 16:21:14 -0000 @@ -977,4 +977,206 @@ 1 /* indentation level */ ); } + +/** + * @bug 236230: [formatter] SIOOBE while formatting a compilation unit. + * @test Ensure that no exception occurs while formatting + * @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=236230" + */ +public void testBug236230() throws JavaModelException { + String source = + "/**\n" + + " * Need a javadoc comment before to get the exception.\n" + + " */\n" + + "public class Test {\n" + + "\n" + + " /**\n" + + " * If there is an authority, it is:\n" + + " *
\n" + + " * //authority/device/pathSegment1/pathSegment2...\n" + + " */\n" + + " public String devicePath() {\n" + + " return null;\n" + + " }\n" + + "}\n"; + formatSource(source, + "/**\n" + + " * Need a javadoc comment before to get the exception.\n" + + " */\n" + + "public class Test {\n" + + "\n" + + " /**\n" + + " *\n" + + " * If there is an authority, it is:\n" + + " * \n" + + " *
\n" + + " * // authority/device/pathSegment1/pathSegment2...\n" + + " *\n" + + " */\n" + + " public String devicePath() {\n" + + " return null;\n" + + " }\n" + + "}\n" + ); +} +public void testBug236230b() throws JavaModelException { + String source = + "/**\n" + + " * Need a javadoc comment before to get the exception.\n" + + " */\n" + + "public class Test {\n" + + "\n" + + " /**\n" + + " *If there is an authority, it is:\n" + + " *
//authority/device/pathSegment1/pathSegment2...\n" + + " */\n" + + " public String devicePath() {\n" + + " return null;\n" + + " }\n" + + "}\n"; + formatSource(source, + "/**\n" + + " * Need a javadoc comment before to get the exception.\n" + + " */\n" + + "public class Test {\n" + + "\n" + + " /**\n" + + " *\n" + + " * If there is an authority, it is:\n" + + " * \n" + + " *
\n" + + " * // authority/device/pathSegment1/pathSegment2...\n" + + " *\n" + + " */\n" + + " public String devicePath() {\n" + + " return null;\n" + + " }\n" + + "}\n" + ); +} +public void testBug236230c() throws JavaModelException { + this.preferences.comment_format_header = true; + String source = + "/**\n" + + " * Need a javadoc comment before to get the exception.\n" + + " */\n" + + "public class Test {\n" + + "\n" + + " /**\n" + + " *If there is an authority, it is:\n" + + " *
\n" + + " import java.util.List;\n" + + " // CU snippet\n" + + " public class X implements List {}\n" + + "\n" + + " */\n" + + " public String devicePath() {\n" + + " return null;\n" + + " }\n" + + "}\n"; + formatSource(source, + "/**\n" + + " * Need a javadoc comment before to get the exception.\n" + + " */\n" + + "public class Test {\n" + + "\n" + + " /**\n" + + " *\n" + + " * If there is an authority, it is:\n" + + " * \n" + + " *
\n" + + " * import java.util.List;\n" + + " * \n" + + " * // CU snippet\n" + + " * public class X implements List {\n" + + " * }\n" + + " *\n" + + " */\n" + + " public String devicePath() {\n" + + " return null;\n" + + " }\n" + + "}\n" + ); +} +public void testBug236230d() throws JavaModelException { + String source = + "/**\n" + + " * Need a javadoc comment before to get the exception.\n" + + " */\n" + + "public class Test {\n" + + "\n" + + " /**\n" + + " *If there is an authority, it is:\n" + + " *
\n" + + " //class body snippet\n" + + " public class X {}\n" + + "\n" + + " */\n" + + " public String devicePath() {\n" + + " return null;\n" + + " }\n" + + "}\n"; + // TODO (frederic) line comment should be formatted when F_INCLUDE_COMMENTS + // flag will work for all snippet kinds + formatSource(source, + "/**\n" + + " * Need a javadoc comment before to get the exception.\n" + + " */\n" + + "public class Test {\n" + + "\n" + + " /**\n" + + " *\n" + + " * If there is an authority, it is:\n" + + " * \n" + + " *
\n" + + " * //class body snippet\n" + + " * public class X {\n" + + " * }\n" + + " *\n" + + " */\n" + + " public String devicePath() {\n" + + " return null;\n" + + " }\n" + + "}\n" + ); +} +// Following tests showed possible regressions while implementing the fix... +public void testBug236230e() throws JavaModelException { + String source = + "public class X02 {\n" + + "\n" + + "\n" + + " /**\n" + + " /**\n" + + " * Removes the Java nature from the project.\n" + + " */\n" + + " void foo() {\n" + + " }\n" + + "}\n"; + formatSource(source, + "public class X02 {\n" + + "\n" + + " /**\n" + + " * /** Removes the Java nature from the project.\n" + + " */\n" + + " void foo() {\n" + + " }\n" + + "}\n" + ); +} +public void testBug236230f() throws JavaModelException { + String source = + "public class X03 {\n" + + " /** The value of System.getProperty(\"java.version\"). **/\n" + + " static final String JAVA_VERSION = System.getProperty(\"java.version\");\n" + + "\n" + + "}\n"; + formatSource(source, + "public class X03 {\n" + + " /** The value of System.getProperty(\"java.version\"). **/\n" + + " static final String JAVA_VERSION = System.getProperty(\"java.version\");\n" + + "\n" + + "}\n" + ); +} } Index: src/org/eclipse/jdt/core/tests/dom/ASTConverterJavadocTest.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterJavadocTest.java,v retrieving revision 1.79 diff -u -r1.79 ASTConverterJavadocTest.java --- src/org/eclipse/jdt/core/tests/dom/ASTConverterJavadocTest.java 27 May 2008 23:59:54 -0000 1.79 +++ src/org/eclipse/jdt/core/tests/dom/ASTConverterJavadocTest.java 13 Jun 2008 16:21:14 -0000 @@ -30,6 +30,30 @@ import org.eclipse.jdt.core.dom.*; 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: + *+ * public void testXXX() throws JavaModelException { + * verifyComments("testXXX"); + * } + *+ * + * 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 comparision 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. + */ public class ASTConverterJavadocTest extends ConverterTestSetup { // Flag to know whether Converter directory should be copied from org.eclipse.jdt.core.tests.model project @@ -244,221 +268,6 @@ return runConversion(source, unitName, project); } -// NOT USED -// class ASTConverterJavadocFlattener extends ASTVisitor { -// -// /** -// * The string buffer into which the serialized representation of the AST is -// * written. -// */ -// private StringBuffer buffer; -// -// private String comment; -// -// /** -// * Creates a new AST printer. -// */ -// ASTConverterJavadocFlattener(String comment) { -// buffer = new StringBuffer(); -// comment = comment; -// } -// -// /** -// * Returns the string accumulated in the visit. -// * -// * @return the serialized -// */ -// public String getResult() { -// return buffer.toString(); -// } -// -// /** -// * Resets this printer so that it can be used again. -// */ -// public void reset() { -// buffer.setLength(0); -// } -// -// /* -// * @see ASTVisitor#visit(ArrayType) -// */ -// public boolean visit(ArrayType node) { -// node.getComponentType().accept(this); -// buffer.append("[]");//$NON-NLS-1$ -// return false; -// } -// -// /* -// * @see ASTVisitor#visit(BlockComment) -// * @since 3.0 -// */ -// public boolean visit(BlockComment node) { -// buffer.append(comment); -// return false; -// } -// -// /* -// * @see ASTVisitor#visit(Javadoc) -// */ -// public boolean visit(Javadoc node) { -// -// // ignore deprecated node.getComment() -// buffer.append("/**");//$NON-NLS-1$ -// ASTNode e = null; -// int start = 3; -// for (Iterator it = node.tags().iterator(); it.hasNext(); ) { -// e = (ASTNode) it.next(); -// try { -// buffer.append(comment.substring(start, e.getStartPosition()-node.getStartPosition())); -// start = e.getStartPosition()-node.getStartPosition(); -// } catch (IndexOutOfBoundsException ex) { -// // do nothing -// } -// e.accept(this); -// start += e.getLength(); -// } -// buffer.append(comment.substring(start, node.getLength())); -// return false; -// } -// -// /* -// * @see ASTVisitor#visit(LineComment) -// * @since 3.0 -// */ -// public boolean visit(LineComment node) { -// buffer.append(comment); -// return false; -// } -// -// /* -// * @see ASTVisitor#visit(MemberRef) -// * @since 3.0 -// */ -// public boolean visit(MemberRef node) { -// if (node.getQualifier() != null) { -// node.getQualifier().accept(this); -// } -// buffer.append("#");//$NON-NLS-1$ -// node.getName().accept(this); -// return true; -// } -// -// /* -// * @see ASTVisitor#visit(MethodRef) -// * @since 3.0 -// */ -// public boolean visit(MethodRef node) { -// if (node.getQualifier() != null) { -// node.getQualifier().accept(this); -// } -// buffer.append("#");//$NON-NLS-1$ -// node.getName().accept(this); -// buffer.append("(");//$NON-NLS-1$ -// for (Iterator it = node.parameters().iterator(); it.hasNext(); ) { -// MethodRefParameter e = (MethodRefParameter) it.next(); -// e.accept(this); -// if (it.hasNext()) { -// buffer.append(",");//$NON-NLS-1$ -// } -// } -// buffer.append(")");//$NON-NLS-1$ -// return true; -// } -// -// /* -// * @see ASTVisitor#visit(MethodRefParameter) -// * @since 3.0 -// */ -// public boolean visit(MethodRefParameter node) { -// node.getType().accept(this); -// if (node.getName() != null) { -// buffer.append(" ");//$NON-NLS-1$ -// node.getName().accept(this); -// } -// return true; -// } -// -// /* -// * @see ASTVisitor#visit(TagElement) -// * @since 3.0 -// */ -// public boolean visit(TagElement node) { -// Javadoc javadoc = null; -// int start = 0; -// if (node.isNested()) { -// // nested tags are always enclosed in braces -// buffer.append("{");//$NON-NLS-1$ -// javadoc = (Javadoc) node.getParent().getParent(); -// start++; -// } else { -// javadoc = (Javadoc) node.getParent(); -// } -// start += node.getStartPosition()-javadoc.getStartPosition(); -// if (node.getTagName() != null) { -// buffer.append(node.getTagName()); -// start += node.getTagName().length(); -// } -// for (Iterator it = node.fragments().iterator(); it.hasNext(); ) { -// ASTNode e = (ASTNode) it.next(); -// try { -// buffer.append(comment.substring(start, e.getStartPosition()-javadoc.getStartPosition())); -// start = e.getStartPosition()-javadoc.getStartPosition(); -// } catch (IndexOutOfBoundsException ex) { -// // do nothing -// } -// start += e.getLength(); -// e.accept(this); -// } -// if (node.isNested()) { -// buffer.append("}");//$NON-NLS-1$ -// } -// return true; -// } -// -// /* -// * @see ASTVisitor#visit(TextElement) -// * @since 3.0 -// */ -// public boolean visit(TextElement node) { -// buffer.append(node.getText()); -// return false; -// } -// -// /* -// * @see ASTVisitor#visit(PrimitiveType) -// */ -// public boolean visit(PrimitiveType node) { -// buffer.append(node.getPrimitiveTypeCode().toString()); -// return false; -// } -// -// /* -// * @see ASTVisitor#visit(QualifiedName) -// */ -// public boolean visit(QualifiedName node) { -// node.getQualifier().accept(this); -// buffer.append(".");//$NON-NLS-1$ -// node.getName().accept(this); -// return false; -// } -// -// /* -// * @see ASTVisitor#visit(SimpleName) -// */ -// public boolean visit(SimpleName node) { -// buffer.append(node.getIdentifier()); -// return false; -// } -// -// /* -// * @see ASTVisitor#visit(SimpleName) -// */ -// public boolean visit(SimpleType node) { -// node.getName().accept(this); -// return false; -// } -// } - private char getNextChar(char[] source, int idx) { // get next char char ch = source[idx]; @@ -820,7 +629,7 @@ */ private void verifyPositions(Javadoc docComment, char[] source) { boolean stop = stopOnFailure; -// stopOnFailure = false; + stopOnFailure = false; // Verify javadoc start and end position int start = docComment.getStartPosition(); int end = start+docComment.getLength()-1; @@ -845,7 +654,12 @@ assumeTrue(prefix+"Misplaced javadoc end at <"+tagStart+'>', source[tagStart-1] == '*' && source[tagStart] == '/'); assumeEquals(prefix+"Wrong javadoc length at <"+end+">: ", tagStart, end); stopOnFailure = stop; - assertTrue(!stop || failures.size()==0); + if (stop && failures.size() > 0) { + String expected = new String(source, docComment.getStartPosition(), docComment.getLength()); + ASTConverterJavadocFlattener flattener = new ASTConverterJavadocFlattener(expected); + docComment.accept(flattener); + assertEquals("Unexpected errors while verifying javadoc comment positions!", expected, flattener.getResult()); + } } /** Index: src/org/eclipse/jdt/core/tests/dom/ASTConverterJavadocFlattener.java =================================================================== RCS file: src/org/eclipse/jdt/core/tests/dom/ASTConverterJavadocFlattener.java diff -N src/org/eclipse/jdt/core/tests/dom/ASTConverterJavadocFlattener.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/jdt/core/tests/dom/ASTConverterJavadocFlattener.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,236 @@ +/******************************************************************************* + * Copyright (c) 2000, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.core.tests.dom; + +import java.util.Iterator; + +import org.eclipse.jdt.core.dom.*; + +public class ASTConverterJavadocFlattener extends ASTVisitor { + + /** + * The string buffer into which the serialized representation of the AST is + * written. + */ + private StringBuffer buffer; + private int indent = 0; + private String comment; + +/** + * Creates a new AST printer. + */ +ASTConverterJavadocFlattener(String comment) { + buffer = new StringBuffer(); + this.comment = comment; +} + +/** + * Returns the string accumulated in the visit. + * + * @return the serialized + */ +public String getResult() { + return buffer.toString(); +} + +/** + * Resets this printer so that it can be used again. + */ +public void reset() { + buffer.setLength(0); +} + +/* + * @see ASTVisitor#visit(ArrayType) + */ +public boolean visit(ArrayType node) { + node.getComponentType().accept(this); + buffer.append("[]");//$NON-NLS-1$ + return false; +} + +/* + * @see ASTVisitor#visit(BlockComment) + * @since 3.0 + */ +public boolean visit(BlockComment node) { + buffer.append(comment); + return false; +} + +/* + * @see ASTVisitor#visit(Javadoc) + */ +public boolean visit(Javadoc javadoc) { + printIndent(); + this.buffer.append("/**");//$NON-NLS-1$ + for (Iterator it = javadoc.tags().iterator(); it.hasNext(); ) { + ASTNode e = (ASTNode) it.next(); + e.accept(this); + } + this.buffer.append("\n */\n");//$NON-NLS-1$ + return false; +} + +private void printIndent() { + for (int i=0; i0 && end >= this.javadocTextEnd) { - // Special case on javadoc text end, need to retrieve the space - // position by rescanning the text - int restart = this.spacePosition == -1 ? start : this.spacePosition; - this.scanner.resetTo(restart, end-1/* before last star*/); - try { - if (this.scanner.getNextToken() == TerminalTokens.TokenNameEOF) { - textEnd = this.spacePosition; - } - } - catch (InvalidInputException iie) { - // do nothing - } - } - FormatJavadocText text = new FormatJavadocText(start, textEnd-1, lineStart, htmlIndex, htmlDepth); + FormatJavadocText text = new FormatJavadocText(start, end-1, lineStart, htmlIndex, htmlDepth); previousBlock.addText(text); previousBlock.sourceStart = previousStart; if (lineStart == previousBlock.lineStart) { Index: formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatter.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatter.java,v retrieving revision 1.72 diff -u -r1.72 DefaultCodeFormatter.java --- formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatter.java 21 May 2008 10:58:04 -0000 1.72 +++ formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatter.java 13 Jun 2008 16:21:16 -0000 @@ -25,6 +25,7 @@ import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; import org.eclipse.jdt.internal.compiler.parser.Scanner; +import org.eclipse.jdt.internal.compiler.parser.TerminalTokens; import org.eclipse.jdt.internal.compiler.util.Util; import org.eclipse.jdt.internal.core.util.CodeSnippetParsingUtil; import org.eclipse.jdt.internal.formatter.comment.CommentRegion; @@ -487,8 +488,9 @@ private TextEdit probeFormatting(String source, int indentationLevel, String lineSeparator, IRegion[] regions, boolean includeComments) { if (PROBING_SCANNER == null) { - // scanner use to check if the kind could be K_JAVA_DOC, K_MULTI_LINE_COMMENT or K_SINGLE_LINE_COMMENT - PROBING_SCANNER = new Scanner(true, true, false/*nls*/, ClassFileConstants.JDK1_3, ClassFileConstants.JDK1_3, null/*taskTags*/, null/*taskPriorities*/, true/*taskCaseSensitive*/); + // scanner use to check if the kind could be K_JAVA_DOC, K_MULTI_LINE_COMMENT or K_SINGLE_LINE_COMMENT + // do not tokenize white spaces to get single comments even with spaces before... + PROBING_SCANNER = new Scanner(true, false/*do not tokenize whitespaces*/, false/*nls*/, ClassFileConstants.JDK1_6, ClassFileConstants.JDK1_6, null/*taskTags*/, null/*taskPriorities*/, true/*taskCaseSensitive*/); } PROBING_SCANNER.setSource(source.toCharArray()); @@ -496,22 +498,22 @@ int offset = coveredRegion.getOffset(); int length = coveredRegion.getLength(); - PROBING_SCANNER.resetTo(offset, offset + length); + PROBING_SCANNER.resetTo(offset, offset + length - 1); try { int kind = -1; switch(PROBING_SCANNER.getNextToken()) { case ITerminalSymbols.TokenNameCOMMENT_BLOCK : - if (PROBING_SCANNER.getCurrentTokenEndPosition() == offset + length - 1) { + if (PROBING_SCANNER.getNextToken() == TerminalTokens.TokenNameEOF) { kind = K_MULTI_LINE_COMMENT; } break; case ITerminalSymbols.TokenNameCOMMENT_LINE : - if (PROBING_SCANNER.getCurrentTokenEndPosition() == offset + length - 1) { + if (PROBING_SCANNER.getNextToken() == TerminalTokens.TokenNameEOF) { kind = K_SINGLE_LINE_COMMENT; } break; case ITerminalSymbols.TokenNameCOMMENT_JAVADOC : - if (PROBING_SCANNER.getCurrentTokenEndPosition() == offset + length - 1) { + if (PROBING_SCANNER.getNextToken() == TerminalTokens.TokenNameEOF) { kind = K_JAVA_DOC; } break; Index: compiler/org/eclipse/jdt/internal/compiler/parser/AbstractCommentParser.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/AbstractCommentParser.java,v retrieving revision 1.75 diff -u -r1.75 AbstractCommentParser.java --- compiler/org/eclipse/jdt/internal/compiler/parser/AbstractCommentParser.java 15 May 2008 17:45:49 -0000 1.75 +++ compiler/org/eclipse/jdt/internal/compiler/parser/AbstractCommentParser.java 13 Jun 2008 16:21:16 -0000 @@ -62,7 +62,7 @@ protected int javadocTextStart, javadocTextEnd = -1; protected int firstTagPosition; protected int index, lineEnd; - protected int tokenPreviousPosition, lastIdentifierEndPosition, starPosition, spacePosition; + protected int tokenPreviousPosition, lastIdentifierEndPosition, starPosition; protected int textStart, memberStart; protected int tagSourceStart, tagSourceEnd; protected int inlineTagStart; @@ -133,7 +133,6 @@ this.deprecated = false; this.lastLinePtr = getLineNumber(javadocEnd); this.textStart = -1; - this.spacePosition = -1; char previousChar = 0; int invalidTagLineEnd = -1; int invalidInlineTagLineEnd = -1; @@ -163,9 +162,13 @@ this.javadocTextStart = this.index; } this.lineEnd = (this.linePtr == this.lastLinePtr) ? this.javadocEnd: this.scanner.getLineEnd(this.linePtr) - 1; + this.javadocTextEnd = this.javadocEnd - 2; // supposed text end, it will be refined later... // Loop on each comment character + int textEndPosition = -1; while (!abort && this.index < this.javadocEnd) { + + // Store previous position and char previousPosition = this.index; previousChar = nextCharacter; @@ -206,10 +209,6 @@ this.sourceParser.problemReporter().javadocUnterminatedInlineTag(this.inlineTagStart, end); } validComment = false; - int textEndPosition = previousPosition; - if (isFormatterParser && ScannerHelper.isWhitespace(previousChar)) { - textEndPosition = this.spacePosition; - } if (this.textStart != -1 && this.textStart < textEndPosition) { if (pushText) pushText(this.textStart, textEndPosition); } @@ -219,10 +218,6 @@ } if (previousChar == '{') { if (this.textStart != -1) { - int textEndPosition = this.inlineTagStart; - if (isFormatterParser && this.spacePosition == (this.inlineTagStart-1)) { - textEndPosition = this.spacePosition; - } if (this.textStart < textEndPosition) { if (pushText) pushText(this.textStart, textEndPosition); } @@ -230,11 +225,7 @@ this.inlineTagStarted = true; invalidInlineTagLineEnd = this.lineEnd; } else if (this.textStart != -1 && this.textStart < invalidTagLineEnd) { - int textEndPosition = invalidTagLineEnd; - if (isFormatterParser && ScannerHelper.isWhitespace(previousChar)) { - textEndPosition = this.spacePosition; - } - if (pushText) pushText(this.textStart, textEndPosition); + if (pushText) pushText(this.textStart, invalidTagLineEnd); } this.scanner.resetTo(this.index, this.javadocEnd); this.currentTokenType = -1; // flush token cache at line begin @@ -250,27 +241,26 @@ } this.textStart = this.tagSourceEnd+1; invalidTagLineEnd = this.lineEnd; + textEndPosition = this.index; } } catch (InvalidInputException e) { consumeToken(); } - } else if (verifText && this.tagValue == TAG_RETURN_VALUE && this.returnStatement != null) { - refreshReturnStatement(); - } else if (isFormatterParser) { - if (this.textStart == -1) this.textStart = previousPosition; + } else { + textEndPosition = this.index; + if (verifText && this.tagValue == TAG_RETURN_VALUE && this.returnStatement != null) { + refreshReturnStatement(); + } else if (isFormatterParser) { + if (this.textStart == -1) this.textStart = previousPosition; + } } this.lineStarted = true; break; case '\r': case '\n': if (this.lineStarted) { - int textEndPosition = previousPosition; - if (isFormatterParser) { - if (ScannerHelper.isWhitespace(previousChar)) { - textEndPosition = this.spacePosition; - } else { - this.spacePosition = previousPosition; - } + if (isFormatterParser && !ScannerHelper.isWhitespace(previousChar)) { + textEndPosition = previousPosition; } if (this.textStart != -1 && this.textStart < textEndPosition) { if (pushText) pushText(this.textStart, textEndPosition); @@ -287,10 +277,6 @@ } if (this.inlineTagStarted) { if (pushText) { - int textEndPosition = previousPosition; - if (isFormatterParser && ScannerHelper.isWhitespace(previousChar)) { - textEndPosition = this.spacePosition; - } if (this.lineStarted && this.textStart != -1 && this.textStart < textEndPosition) { pushText(this.textStart, textEndPosition); } @@ -304,6 +290,7 @@ } } this.lineStarted = true; + textEndPosition = this.index; break; case '{' : if (verifText && this.tagValue == TAG_RETURN_VALUE && this.returnStatement != null) { @@ -318,15 +305,14 @@ this.sourceParser.problemReporter().javadocUnterminatedInlineTag(this.inlineTagStart, end); } if (pushText) { - int textEndPosition = previousPosition; - if (isFormatterParser && ScannerHelper.isWhitespace(previousChar)) { - textEndPosition = this.spacePosition; - } if (this.lineStarted && this.textStart != -1 && this.textStart < textEndPosition) { pushText(this.textStart, textEndPosition); } refreshInlineTagPosition(textEndPosition); } + textEndPosition = this.index; + } else if (peekChar() != '@') { + textEndPosition = this.index; } if (!this.lineStarted) { this.textStart = previousPosition; @@ -352,9 +338,13 @@ case '\u000c' : /* FORM FEED */ case ' ' : /* SPACE */ case '\t' : /* HORIZONTAL TABULATION */ - // Store first space position while formatting - if (isFormatterParser && !ScannerHelper.isWhitespace(previousChar)) { - this.spacePosition = previousPosition; + // Do not include trailing spaces in text while formatting + if (isFormatterParser) { + if (!ScannerHelper.isWhitespace(previousChar)) { + textEndPosition = previousPosition; + } + } else if (this.lineStarted) { + textEndPosition = this.index; } break; case '/': @@ -368,8 +358,10 @@ // html tags are meaningful for formatter parser int initialIndex = this.index; this.scanner.resetTo(this.index, this.javadocEnd); - int endTextPosition = ScannerHelper.isWhitespace(previousChar) ? this.spacePosition : previousPosition; - if (parseHtmlTag(previousPosition, endTextPosition)) { + if (!ScannerHelper.isWhitespace(previousChar)) { + textEndPosition = previousPosition; + } + if (parseHtmlTag(previousPosition, textEndPosition)) { break; } if (this.abort) return false; @@ -384,6 +376,7 @@ this.textStart = previousPosition; } this.lineStarted = true; + textEndPosition = this.index; break; } } @@ -398,18 +391,14 @@ this.sourceParser.problemReporter().javadocUnterminatedInlineTag(this.inlineTagStart, end); } if (pushText) { - int textEndPosition = this.javadocTextEnd; - if (isFormatterParser && ScannerHelper.isWhitespace(previousChar)) { - textEndPosition = this.spacePosition; - } if (this.lineStarted && this.textStart != -1 && this.textStart < textEndPosition) { pushText(this.textStart, textEndPosition); } refreshInlineTagPosition(textEndPosition); } this.inlineTagStarted = false; - } else if (pushText && this.lineStarted && this.textStart != -1 && this.textStart <= this.javadocTextEnd) { - pushText(this.textStart, this.starPosition); + } else if (pushText && this.lineStarted && this.textStart != -1 && this.textStart <= textEndPosition) { + pushText(this.textStart, textEndPosition); } updateDocComment(); } catch (Exception ex) { @@ -1539,13 +1528,12 @@ * Note that end of comment may be preceding by several contiguous '*' chars. */ protected boolean verifyEndLine(int textPosition) { - boolean isDomParser = (this.kind & DOM_PARSER) != 0; - boolean isFormatterParser = (this.kind & FORMATTER_COMMENT_PARSER) != 0; + boolean domParser = (this.kind & DOM_PARSER) != 0; // Special case for inline tag if (this.inlineTagStarted) { // expecting closing brace if (peekChar() == '}') { - if (isDomParser || isFormatterParser) { + if (domParser) { createTag(); pushText(textPosition, this.starPosition); } @@ -1556,30 +1544,21 @@ int startPosition = this.index; int previousPosition = this.index; - int spacePos = this.index; this.starPosition = -1; char ch = readChar(); - char previousChar = ch; nextChar: while (true) { switch (ch) { case '\r': case '\n': - if (isDomParser || isFormatterParser) { + if (domParser) { createTag(); - int textEndPosition = previousPosition; - if (isFormatterParser && ScannerHelper.isWhitespace(previousChar)) { - textEndPosition = spacePos; - } - pushText(textPosition, textEndPosition); + pushText(textPosition, previousPosition); } this.index = previousPosition; return true; case '\u000c' : /* FORM FEED */ case ' ' : /* SPACE */ case '\t' : /* HORIZONTAL TABULATION */ - if (isFormatterParser && previousChar != ch && !ScannerHelper.isWhitespace(previousChar)) { - this.spacePosition = previousPosition; - } if (this.starPosition >= 0) break nextChar; break; case '*': @@ -1587,13 +1566,9 @@ break; case '/': if (this.starPosition >= textPosition) { - if (isDomParser || isFormatterParser) { + if (domParser) { createTag(); - int textEndPosition = this.starPosition; - if (isFormatterParser && ScannerHelper.isWhitespace(previousChar)) { - textEndPosition = this.spacePosition; - } - pushText(textPosition, textEndPosition); + pushText(textPosition, this.starPosition); } return true; } @@ -1603,7 +1578,6 @@ } previousPosition = this.index; - previousChar = ch; ch = readChar(); } this.index = startPosition;