diff options
7 files changed, 376 insertions, 44 deletions
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/JavadocBugsTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/JavadocBugsTest.java index 3f8d433821..5dfe4261db 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/JavadocBugsTest.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/JavadocBugsTest.java @@ -8500,6 +8500,15 @@ public void testBug267833_2() { } } } + for (int i=0; i < JavadocTagConstants.IN_SNIPPET_TAGS_LENGTH; i++) { + int length = JavadocTagConstants.IN_SNIPPET_TAGS[i].length; + for (int j=0; j < length; j++) { + if (tagName == JavadocTagConstants.IN_SNIPPET_TAGS[i][j]) { + assertEquals(JavadocTagConstants.JAVADOC_TAG_TYPE[index], JavadocTagConstants.TAG_TYPE_IN_SNIPPET); + continue nextTag; + } + } + } } assertEquals(JavadocTagConstants.JAVADOC_TAG_TYPE[index], JavadocTagConstants.TAG_TYPE_NONE); } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/AbstractCommentParser.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/AbstractCommentParser.java index cf5b5e7ed0..df5fe278ea 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/AbstractCommentParser.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/AbstractCommentParser.java @@ -17,8 +17,12 @@ *******************************************************************************/ package org.eclipse.jdt.internal.compiler.parser; +import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameEOF; + import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.core.compiler.InvalidInputException; @@ -89,6 +93,7 @@ public abstract class AbstractCommentParser implements JavadocTagConstants { protected int kind; protected int tagValue = NO_TAG_VALUE; protected int lastBlockTagValue = NO_TAG_VALUE; + protected boolean snippetInlineTagStarted = false; // Line pointers private int linePtr, lastLinePtr; @@ -1463,10 +1468,15 @@ public abstract class AbstractCommentParser implements JavadocTagConstants { this.scanner.tokenizeWhiteSpace = false; int previousPosition = -1; int openBraces = 1; + boolean parsingJava18Plus = this.scanner != null ? this.scanner.sourceLevel >= ClassFileConstants.JDK18 : false; + if (!parsingJava18Plus) { + throw new InvalidInputException(); + } try { createTag(); //pushSnippetTag(); int token = readTokenSafely(); + if (token != TerminalTokens.TokenNameCOLON) { throw new InvalidInputException(); } @@ -1475,43 +1485,32 @@ public abstract class AbstractCommentParser implements JavadocTagConstants { throw new InvalidInputException(); } consumeNewLine(); - // Get reference tokens - char nextCharacter = readChar(); - char previousChar = 0; + this.scanner.tokenizeWhiteSpace = true; int textEndPosition = this.index; this.textStart = this.index; - boolean isFormatterParser = (this.kind & FORMATTER_COMMENT_PARSER) != 0; - while (!this.abort && this.index < this.javadocEnd) { - // Consume rules depending on the read character - switch (nextCharacter) { - case '\r': - case '\n': - if (this.lineStarted) { - if (isFormatterParser && !ScannerHelper.isWhitespace(previousChar)) { - textEndPosition = previousPosition; - } - if (this.textStart != -1 && this.textStart < textEndPosition) { - pushSnippetText(this.textStart, textEndPosition); - } - } - this.lineStarted = false; - // Fix bug 51650 - this.textStart = -1; - break; - case '{': + while (this.index < this.scanner.eofPosition) { + this.index = this.scanner.currentPosition; + if (openBraces == 0) { + break; + } + previousPosition = this.index; + token = readTokenSafely(); + if (token == TerminalTokens.TokenNameEOF) { + break; + } + switch (token) { + case TerminalTokens.TokenNameLBRACE: openBraces++; textEndPosition = this.index; break; - case '}': + case TerminalTokens.TokenNameRBRACE: openBraces--; + textEndPosition = this.index; if (openBraces == 0) { if (this.lineStarted) { if (this.textStart == -1) { this.textStart = previousPosition; } - if (isFormatterParser && !ScannerHelper.isWhitespace(previousChar)) { - textEndPosition = previousPosition; - } if (this.textStart != -1 && this.textStart < this.index) { String textToBeAdded= new String( this.source, this.textStart, this.index-this.textStart); int iindex = textToBeAdded.indexOf('*'); @@ -1519,14 +1518,55 @@ public abstract class AbstractCommentParser implements JavadocTagConstants { textToBeAdded = textToBeAdded.substring(iindex+1); } if (!textToBeAdded.isBlank()) { - pushSnippetText(this.textStart, this.index-1); + pushSnippetText(this.textStart, this.index-1, false); } } } } + break; + case TerminalTokens.TokenNameWHITESPACE: + if (containsTokenNewLine(this.scanner.getCurrentTokenString())) { + if (this.lineStarted) { + if (this.textStart != -1 && this.textStart < textEndPosition) { + pushSnippetText(this.textStart, textEndPosition, true); + } + } + this.lineStarted = false; + // Fix bug 51650 + this.textStart = -1; + } + break; + case TerminalTokens.TokenNameCOMMENT_LINE: + String tokenString = this.scanner.getCurrentTokenString(); + boolean handleNow = handleCommentLineForCurrentLine(tokenString); + boolean valid = false; + Object innerTag = parseSnippetInlineTags(tokenString); + if (innerTag != null) { + valid = true; + } + if( valid && handleNow) { + addSnippetInnerTag(innerTag); + this.snippetInlineTagStarted = true; + } textEndPosition = this.index; + int textPos = previousPosition; + if (!valid) { + textPos = textEndPosition; + } + if (this.lineStarted) { + if (this.textStart == -1) { + this.textStart = previousPosition; + } + if (this.textStart != -1 && this.textStart < this.index) { + pushSnippetText(this.textStart, textPos, valid); + } + } + if (valid && !handleNow) { + addSnippetInnerTag(innerTag); + this.snippetInlineTagStarted = true; + } break; - default : + default: if (!this.lineStarted || this.textStart == -1) { this.textStart = previousPosition; } @@ -1534,14 +1574,9 @@ public abstract class AbstractCommentParser implements JavadocTagConstants { textEndPosition = this.index; break; } - previousPosition = this.index; - if (openBraces == 0) { - break; - } - nextCharacter = readChar(); + consumeToken(); } - } - catch (InvalidInputException ex) { + } catch (InvalidInputException ex) { if (this.reportProblems) this.sourceParser.problemReporter().javadocInvalidReference(currentPosition, getTokenEndPosition()); } finally { @@ -1555,6 +1590,157 @@ public abstract class AbstractCommentParser implements JavadocTagConstants { return false; } + private boolean handleCommentLineForCurrentLine(String tokenString) { + boolean handle = true; + if (tokenString != null) { + String processed= tokenString.trim(); + if (processed.endsWith(":")) { //$NON-NLS-1$ + handle = false; + } + } + return handle; + } + + protected Object parseSnippetInlineTags(String tokenString) { + int commentStart = this.scanner.getCurrentTokenStartPosition(); + Object inlineTag = null; + final String HIGHLIGHT = "highlight"; //$NON-NLS-1$ + final String SUBSTRING = "substring"; //$NON-NLS-1$ + final String REGEX = "regex"; //$NON-NLS-1$ + final String TYPE = "type"; //$NON-NLS-1$ + if (tokenString != null + && tokenString.length() > 2 + && tokenString.startsWith("//")) { //$NON-NLS-1$ + String tobeTokenized = tokenString.substring(2); + Scanner slScanner = new Scanner(false, false, false/* nls */, this.scanner.sourceLevel, + null/* taskTags */, null/* taskPriorities */, false/* taskCaseSensitive */, false); + slScanner.setSource(tobeTokenized.toCharArray()); + boolean atTokenStarted= false; + int atTokenPos = -1; + while (true) { + try { + int tokenType = slScanner.getNextToken(); + if (tokenType == TokenNameEOF) + break; + mainSwitch : switch (tokenType) { + case TerminalTokens.TokenNameAT : + atTokenStarted = true; + atTokenPos = slScanner.getCurrentTokenStartPosition(); + break; + case TerminalTokens.TokenNameIdentifier : + if (atTokenStarted) { + int curPos= slScanner.getCurrentTokenStartPosition(); + if (curPos != atTokenPos+1) { + return inlineTag; + } + String snippetDecorator = slScanner.getCurrentTokenString(); + int tokenStart= commentStart + slScanner.getCurrentTokenStartPosition()-1; + int tokenEnd= commentStart + slScanner.getCurrentTokenEndPosition(); + String newTagName= null; + switch(snippetDecorator) { + case HIGHLIGHT : + tokenStart= commentStart + 1 + slScanner.getCurrentTokenStartPosition(); + tokenEnd= tokenStart + 10; + newTagName = '@' + HIGHLIGHT; + Map<String, String> map = new HashMap<>(); + boolean breakToMainSwitch = false; + boolean createTag = false; + String attribute = null; + String value = null; + boolean processValue = false; + while (true) { + tokenType = slScanner.getNextToken(); + switch (tokenType) { + case TokenNameEOF: + createTag = true; + break; + case TerminalTokens.TokenNameAT: + if (!processValue) { + breakToMainSwitch = true; + createTag = true; + } + processValue= false; + break; + case TerminalTokens.TokenNameCOLON: + tokenType = slScanner.getNextToken(); + if (tokenType == TokenNameEOF) { + break; + } else { + return inlineTag; + } + case TerminalTokens.TokenNameIdentifier: + if (processValue) { + value = slScanner.getCurrentTokenString(); + if (map.get(attribute) == null) { + map.put(attribute, value); + if ((attribute.equals(SUBSTRING) && (map.get(REGEX) != null)) + || (attribute.equals(REGEX) && (map.get(SUBSTRING) != null))) { + return inlineTag; + } + } + processValue= false; + attribute = null; + } else { + attribute = slScanner.getCurrentTokenString(); + switch(attribute) { + case SUBSTRING : + case REGEX : + case TYPE : + default : + break; + } + } + break; + case TerminalTokens.TokenNameEQUAL: + if (attribute != null) { + processValue = true; + } + break; + case TerminalTokens.TokenNameStringLiteral: + if (processValue) { + value = slScanner.getCurrentTokenString(); + if (map.get(attribute) == null) { + map.put(attribute, value); + if ((attribute.equals(SUBSTRING) && (map.get(REGEX) != null)) + || (attribute.equals(REGEX) && (map.get(SUBSTRING) != null))) { + return inlineTag; + } + } + processValue= false; + attribute = null; + } + break; + } + if (createTag) { + break; + } + if (breakToMainSwitch) + break mainSwitch; + } + tokenEnd = tokenStart + slScanner.getCurrentTokenEndPosition(); + inlineTag = createSnippetInnerTag(newTagName, tokenStart, tokenEnd); + addTagProperties(inlineTag, map); + break; + default : + return false; + } + } + break; + default: + if (atTokenStarted) { + return false; + } + break; + } + + } catch (InvalidInputException e) { + // do nothing + } + } + } + return inlineTag; + } + private boolean isNextNonSpaceCharNewLine() { boolean consider = false; char ch = getChar(); @@ -1568,6 +1754,14 @@ public abstract class AbstractCommentParser implements JavadocTagConstants { return consider; } + private boolean containsTokenNewLine(String str) { + boolean consider = false; + if(str != null && str.contains(System.lineSeparator())) { + consider = true; + } + return consider; + } + private void consumeNewLine() { int lineSeperatorLength = System.lineSeparator().length(); for (int i=0; i< lineSeperatorLength; i++) { @@ -1724,10 +1918,16 @@ public abstract class AbstractCommentParser implements JavadocTagConstants { // do not store text by default } - protected void pushSnippetText(int start, int end) { + protected void pushSnippetText(int start, int end, boolean addNewLine) { // do not store text by default } + protected abstract Object createSnippetInnerTag(String tagName, int start, int end); + + protected abstract void addTagProperties(Object Tag, Map<String, String> map); + + protected abstract void addSnippetInnerTag(Object tag); + /* * Push a throws type ref in ast node stack. */ diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/JavadocParser.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/JavadocParser.java index 8610217426..6a7d590a67 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/JavadocParser.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/JavadocParser.java @@ -18,6 +18,7 @@ package org.eclipse.jdt.internal.compiler.parser; import java.util.List; +import java.util.Map; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.core.compiler.InvalidInputException; @@ -351,6 +352,21 @@ public class JavadocParser extends AbstractCommentParser { } @Override + protected Object createSnippetInnerTag(String tagName, int start, int end) { + return tagName; + } + + @Override + protected void addTagProperties(Object Tag, Map<String, String> map) { + return; + } + + @Override + protected void addSnippetInnerTag(Object tag) { + this.tagValue = TAG_OTHERS_VALUE; + } + + @Override protected Object createTypeReference(int primitiveToken) { TypeReference typeRef = null; int size = this.identifierLengthStack[this.identifierLengthPtr]; @@ -933,7 +949,7 @@ public class JavadocParser extends AbstractCommentParser { } @Override - protected void pushSnippetText(int start, int end) { + protected void pushSnippetText(int start, int end, boolean addNewLine) { // The tag gets its description => clear the flag this.tagWaitingForDescription = TAG_SNIPPET_VALUE; } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/JavadocTagConstants.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/JavadocTagConstants.java index 5bde2adad0..84cbce0d3c 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/JavadocTagConstants.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/JavadocTagConstants.java @@ -58,6 +58,7 @@ public interface JavadocTagConstants { public static final char[] TAG_IMPL_SPEC = "implSpec".toCharArray(); //$NON-NLS-1$ public static final char[] TAG_IMPL_NOTE = "implNote".toCharArray(); //$NON-NLS-1$ public static final char[] TAG_SNIPPET = "snippet".toCharArray(); //$NON-NLS-1$ + public static final char[] TAG_HIGHLIGHT = "highlight".toCharArray(); //$NON-NLS-1$ // tags lengthes public static final int TAG_DEPRECATED_LENGTH = TAG_DEPRECATED.length; @@ -90,6 +91,8 @@ public interface JavadocTagConstants { public static final int TAG_IMPL_SPEC_LENGTH = TAG_IMPL_SPEC.length; public static final int TAG_IMPL_NOTE_LENGTH = TAG_IMPL_NOTE.length; public static final int TAG_SNIPPET_LENGTH = TAG_SNIPPET.length; + public static final int TAG_HIGHLIGHT_LENGTH = TAG_HIGHLIGHT.length; + // tags value public static final int NO_TAG_VALUE = 0; @@ -123,6 +126,7 @@ public interface JavadocTagConstants { public static final int TAG_IMPL_SPEC_VALUE = 28; public static final int TAG_IMPL_NOTE_VALUE = 29; public static final int TAG_SNIPPET_VALUE = 30; + public static final int TAG_HIGHLIGHT_VALUE = 31; public static final int TAG_OTHERS_VALUE = 100; // Tag names array public static final char[][] TAG_NAMES = { @@ -157,6 +161,7 @@ public interface JavadocTagConstants { TAG_IMPL_SPEC, /* 28 */ TAG_IMPL_NOTE, /* 29 */ TAG_SNIPPET, /* 30 */ + TAG_HIGHLIGHT, /* 31 */ }; // tags expected positions @@ -256,6 +261,11 @@ public interface JavadocTagConstants { //since 18 { TAG_SNIPPET } }; + public static final char[][][] IN_SNIPPET_TAGS = { + //since 18 + { TAG_HIGHLIGHT } + }; + public final static int IN_SNIPPET_TAGS_LENGTH = IN_SNIPPET_TAGS.length; public final static int INLINE_TAGS_LENGTH = INLINE_TAGS.length; public final static int BLOCK_TAGS_LENGTH = BLOCK_TAGS.length; public final static int ALL_TAGS_LENGTH = BLOCK_TAGS_LENGTH+INLINE_TAGS_LENGTH; @@ -263,6 +273,7 @@ public interface JavadocTagConstants { public final static short TAG_TYPE_NONE = 0; public final static short TAG_TYPE_INLINE = 1; public final static short TAG_TYPE_BLOCK = 2; + public final static short TAG_TYPE_IN_SNIPPET = 3; public static final short[] JAVADOC_TAG_TYPE = { TAG_TYPE_NONE, // NO_TAG_VALUE = 0; TAG_TYPE_BLOCK, // TAG_DEPRECATED_VALUE = 1; @@ -295,7 +306,8 @@ public interface JavadocTagConstants { TAG_TYPE_BLOCK, // TAG_IMPL_SPEC = 28; TAG_TYPE_BLOCK, // TAG_IMPL_NOTE = 29; TAG_TYPE_INLINE, // TAG_SNIPPET_VALUE = 30; - }; + TAG_TYPE_IN_SNIPPET,// TAG_HIGHLIGHT_VALUE = 31; + }; /* * Tags usage */ diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AST.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AST.java index 88cde6419f..4dfd5b5e08 100644 --- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AST.java +++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AST.java @@ -2958,8 +2958,8 @@ public final class AST { * @return a new unparented tag element node * @since 3.29 BETA_JAVA 18 */ - public TagElement newTagProperty() { - TagElement result = new TagElement(this); + public TagProperty newTagProperty() { + TagProperty result = new TagProperty(this); return result; } diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DocCommentParser.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DocCommentParser.java index 1ff7496a24..b8c6536f47 100644 --- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DocCommentParser.java +++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DocCommentParser.java @@ -19,6 +19,7 @@ package org.eclipse.jdt.core.dom; import java.util.Iterator; import java.util.List; +import java.util.Map; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.core.compiler.InvalidInputException; @@ -259,6 +260,61 @@ class DocCommentParser extends AbstractCommentParser { } @Override + protected Object createSnippetInnerTag(String tagName, int start, int end) { + if (tagName != null) { + TagElement tagElement = this.ast.newTagElement(); + tagElement.setTagName(tagName.toString()); + if (this.astPtr == -1) { + return null; + } + tagElement.setSourceRange(start, end-start); + return tagElement; + } + return null; + } + + @Override + protected void addTagProperties(Object tag, Map<String, String> map) { + if (tag instanceof TagElement) { + TagElement tagElement = (TagElement) tag; + map.forEach((k, v) -> { + TagProperty tagProperty = this.ast.newTagProperty(); + tagProperty.setName(k); + tagProperty.setValue(v); + tagElement.tagProperties().add(tagProperty); + }); + } + } + + @Override + protected void addSnippetInnerTag(Object obj) { + if (obj instanceof TagElement) { + TagElement tagElement = (TagElement) obj; + TagElement previousTag = null; + if (this.astPtr == -1) { + return; + } else { + previousTag = (TagElement) this.astStack[this.astPtr]; + List fragments = previousTag.fragments(); + if (this.inlineTagStarted) { + int size = fragments.size(); + if (size == 0) { + //do nothing + } else { + // If last fragment is a tag, then use it as previous tag + ASTNode lastFragment = (ASTNode) fragments.get(size-1); + if (lastFragment.getNodeType() == ASTNode.TAG_ELEMENT) { + previousTag = (TagElement) lastFragment; + } + } + } + } + previousTag.fragments().add(tagElement); + } + } + + + @Override protected Object createTypeReference(int primitiveToken) { int size = this.identifierLengthStack[this.identifierLengthPtr]; String[] identifiers = new String[size]; @@ -813,14 +869,17 @@ class DocCommentParser extends AbstractCommentParser { } @Override - protected void pushSnippetText(int start, int end) { + protected void pushSnippetText(int start, int end, boolean addNewLine) { // Create text element TextElement text = this.ast.newTextElement(); String textToBeAdded= new String( this.source, start, end-start); int iindex = textToBeAdded.indexOf('*'); if (iindex > -1 && textToBeAdded.substring(0, iindex+1).trim().equals("*")) { //$NON-NLS-1$ - textToBeAdded = textToBeAdded.substring(iindex+1)+ System.lineSeparator(); + textToBeAdded = textToBeAdded.substring(iindex+1); + if (addNewLine) { + textToBeAdded += System.lineSeparator(); + } } text.setText(textToBeAdded); text.setSourceRange(start, end-start); @@ -837,6 +896,7 @@ class DocCommentParser extends AbstractCommentParser { previousStart = previousTag.getStartPosition(); } + TagElement prevTag = null; // If we're in a inline tag, then retrieve previous tag in its fragments List fragments = previousTag.fragments(); if (this.inlineTagStarted) { @@ -849,13 +909,42 @@ class DocCommentParser extends AbstractCommentParser { if (lastFragment.getNodeType() == ASTNode.TAG_ELEMENT) { previousTag = (TagElement) lastFragment; previousStart = previousTag.getStartPosition(); + if (this.snippetInlineTagStarted) { + fragments = previousTag.fragments(); + size = fragments.size(); + if (size == 0) { + //do nothing + } else { + lastFragment = (ASTNode) fragments.get(size-1); + if (lastFragment.getNodeType() == ASTNode.TAG_ELEMENT) { + prevTag = (TagElement) lastFragment; + this.snippetInlineTagStarted = false; + } + } + this.snippetInlineTagStarted = false; + } } } } + int finEnd = end; // Add the text - previousTag.fragments().add(text); - previousTag.setSourceRange(previousStart, end-previousStart); + if (prevTag != null) { + prevTag.fragments().add(text); + int curStart = prevTag.getStartPosition(); + int curEnd = curStart + prevTag.getLength(); + int finStart = start; + if (curStart < start) { + finStart = curStart; + } + if (curEnd > end) { + finEnd = curEnd; + } + prevTag.setSourceRange(finStart, finEnd - finStart); + } else { + previousTag.fragments().add(text); + } + previousTag.setSourceRange(previousStart, finEnd-previousStart); this.textStart = -1; } diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TagElement.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TagElement.java index e8e1835d37..7ed577e0ec 100644 --- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TagElement.java +++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TagElement.java @@ -275,6 +275,12 @@ public final class TagElement extends ASTNode implements IDocElement { public static final String TAG_SNIPPET = "@snippet"; //$NON-NLS-1$ /** + * Standard snippet doc tag name (value {@value}). + * @since 3.29 BETA_JAVA + */ + public static final String TAG_HIGHLIGHT = "@highlight"; //$NON-NLS-1$ + + /** * The tag name, or null if none; defaults to null. */ private String optionalTagName = null; |