diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CCommentScanner.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CCommentScanner.java index 1785ff49f36..5d1a1e146ca 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CCommentScanner.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CCommentScanner.java @@ -21,7 +21,6 @@ import org.eclipse.jface.text.rules.IRule; import org.eclipse.cdt.ui.PreferenceConstants; import org.eclipse.cdt.ui.text.AbstractCScanner; import org.eclipse.cdt.ui.text.ITokenStoreFactory; -import org.eclipse.cdt.ui.text.TaskTagRule; /** * Default token-scanner used for plain (non-documentation-comment) single and multi-line comments, with awareness of @@ -42,9 +41,8 @@ public class CCommentScanner extends AbstractCScanner { protected List createRules(String defaultTokenProperty) { setDefaultReturnToken(getToken(defaultTokenProperty)); IPreferenceStore store= fTokenStore.getPreferenceStore(); - String taskWords= TaskTagRule.getTaskWords(store, null); - TaskTagRule taskTagRule= new TaskTagRule(getToken(TASK_TAG_KEY), taskWords); + TaskTagRule taskTagRule= new TaskTagRule(getToken(TASK_TAG_KEY), fDefaultReturnToken, store, null); addPropertyChangeParticipant(taskTagRule); - return Collections.singletonList((IRule)taskTagRule); + return Collections.singletonList((IRule) taskTagRule); } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CombinedWordRule.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CombinedWordRule.java new file mode 100644 index 00000000000..d6ce46e68da --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CombinedWordRule.java @@ -0,0 +1,370 @@ +/******************************************************************************* + * Copyright (c) 2000, 2007 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 + * Sergey Prigogin (Google) + *******************************************************************************/ +package org.eclipse.cdt.internal.ui.text; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.eclipse.core.runtime.Assert; + +import org.eclipse.jface.text.rules.ICharacterScanner; +import org.eclipse.jface.text.rules.IRule; +import org.eclipse.jface.text.rules.IToken; +import org.eclipse.jface.text.rules.IWordDetector; +import org.eclipse.jface.text.rules.Token; + +/** + * An implementation of IRule capable of detecting words. + *

+ * Word rules also allow for the association of tokens with specific words. + * That is, not only can the rule be used to provide tokens for exact matches, + * but also for the generalized notion of a word in the context in which it is used. + * A word rules uses a word detector to determine what a word is.

+ *

+ * This word rule allows a word detector to be shared among different word matchers. + * Its up to the word matchers to decide if a word matches and, in this a case, which + * token is associated with that word. + *

+ * + * @see IWordDetector + * @since 5.1 + */ +public class CombinedWordRule implements IRule { + + /** + * Word matcher, that associates matched words with tokens. + */ + public static class WordMatcher { + /** The table of predefined words and token for this matcher */ + private Map fWords= new HashMap(); + + /** + * Adds a word and the token to be returned if it is detected. + * + * @param word the word this rule will search for, may not be null + * @param token the token to be returned if the word has been found, may not be null + */ + public void addWord(String word, IToken token) { + Assert.isNotNull(word); + Assert.isNotNull(token); + + fWords.put(new CharacterBuffer(word), token); + } + + /** + * Returns the token associated to the given word and the scanner state. + * + * @param scanner the scanner + * @param word the word + * @return the token or null if none is associated by this matcher + */ + public IToken evaluate(ICharacterScanner scanner, CharacterBuffer word) { + IToken token= fWords.get(word); + if (token != null) + return token; + return Token.UNDEFINED; + } + + /** + * Removes all words. + */ + public void clearWords() { + fWords.clear(); + } + } + + /** + * Character buffer, mutable or suitable for use as key in hash maps. + */ + public static class CharacterBuffer { + /** Buffer content */ + private char[] fContent; + /** Buffer content size */ + private int fLength= 0; + + /** Is hash code cached? */ + private boolean fIsHashCached= false; + /** The hash code */ + private int fHashCode; + + /** + * Initialize with the given capacity. + * + * @param capacity the initial capacity + */ + public CharacterBuffer(int capacity) { + fContent= new char[capacity]; + } + + /** + * Initialize with the given content. + * + * @param content the initial content + */ + public CharacterBuffer(String content) { + fContent= content.toCharArray(); + fLength= content.length(); + } + + /** + * Empties this buffer. + */ + public void clear() { + fIsHashCached= false; + fLength= 0; + } + + /** + * Appends the given character to the buffer. + * + * @param c the character + */ + public void append(char c) { + fIsHashCached= false; + if (fLength == fContent.length) { + char[] old= fContent; + fContent= new char[old.length << 1]; + System.arraycopy(old, 0, fContent, 0, old.length); + } + fContent[fLength++]= c; + } + + /** + * Returns the length of the content. + * + * @return the length + */ + public int length() { + return fLength; + } + + /** + * Returns the content as string. + * + * @return the content + */ + @Override + public String toString() { + return new String(fContent, 0, fLength); + } + + /** + * Returns the character at the given position. + * + * @param i the position + * @return the character at position i + */ + public char charAt(int i) { + return fContent[i]; + } + + /* + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + if (fIsHashCached) + return fHashCode; + + int hash= 0; + for (int i= 0, n= fLength; i < n; i++) + hash= 29*hash + fContent[i]; + fHashCode= hash; + fIsHashCached= true; + return hash; + } + + /* + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (obj == this) + return true; + if (!(obj instanceof CharacterBuffer)) + return false; + CharacterBuffer buffer= (CharacterBuffer) obj; + int length= buffer.length(); + if (length != fLength) + return false; + for (int i= 0; i < length; i++) + if (buffer.charAt(i) != fContent[i]) + return false; + return true; + } + + /** + * Is the content equal to the given string? + * + * @param string the string + * @return true iff the content is the same character sequence as in the string + */ + public boolean equals(String string) { + int length= string.length(); + if (length != fLength) + return false; + for (int i= 0; i < length; i++) + if (string.charAt(i) != fContent[i]) + return false; + return true; + } + } + + /** Internal setting for the uninitialized column constraint */ + private static final int UNDEFINED= -1; + + /** The word detector used by this rule */ + private IWordDetector fDetector; + /** The default token to be returned on success and if nothing else has been specified. */ + private IToken fDefaultToken; + /** The column constraint */ + private int fColumn= UNDEFINED; + /** Buffer used for pattern detection */ + private CharacterBuffer fBuffer= new CharacterBuffer(16); + + /** List of word matchers */ + private List fMatchers= new ArrayList(); + + /** + * Creates a rule which, with the help of an word detector, will return the token + * associated with the detected word. If no token has been associated, the scanner + * will be rolled back and an undefined token will be returned in order to allow + * any subsequent rules to analyze the characters. + * + * @param detector the word detector to be used by this rule, may not be null + * + * @see WordMatcher#addWord(String, IToken) + */ + public CombinedWordRule(IWordDetector detector) { + this(detector, null, Token.UNDEFINED); + } + + /** + * Creates a rule which, with the help of an word detector, will return the token + * associated with the detected word. If no token has been associated, the + * specified default token will be returned. + * + * @param detector the word detector to be used by this rule, may not be null + * @param defaultToken the default token to be returned on success + * if nothing else is specified, may not be null + * + * @see WordMatcher#addWord(String, IToken) + */ + public CombinedWordRule(IWordDetector detector, IToken defaultToken) { + this(detector, null, defaultToken); + } + + /** + * Creates a rule which, with the help of an word detector, will return the token + * associated with the detected word. If no token has been associated, the scanner + * will be rolled back and an undefined token will be returned in order to allow + * any subsequent rules to analyze the characters. + * + * @param detector the word detector to be used by this rule, may not be null + * @param matcher the initial word matcher + * + * @see WordMatcher#addWord(String, IToken) + */ + public CombinedWordRule(IWordDetector detector, WordMatcher matcher) { + this(detector, matcher, Token.UNDEFINED); + } + + /** + * Creates a rule which, with the help of an word detector, will return the token + * associated with the detected word. If no token has been associated, the + * specified default token will be returned. + * + * @param detector the word detector to be used by this rule, may not be null + * @param matcher the initial word matcher + * @param defaultToken the default token to be returned on success + * if nothing else is specified, may not be null + * + * @see WordMatcher#addWord(String, IToken) + */ + public CombinedWordRule(IWordDetector detector, WordMatcher matcher, IToken defaultToken) { + + Assert.isNotNull(detector); + Assert.isNotNull(defaultToken); + + fDetector= detector; + fDefaultToken= defaultToken; + if (matcher != null) + addWordMatcher(matcher); + } + + /** + * Adds the given matcher. + * + * @param matcher the matcher + */ + public void addWordMatcher(WordMatcher matcher) { + fMatchers.add(matcher); + } + + /** + * Sets a column constraint for this rule. If set, the rule's token + * will only be returned if the pattern is detected starting at the + * specified column. If the column is smaller then 0, the column + * constraint is considered removed. + * + * @param column the column in which the pattern starts + */ + public void setColumnConstraint(int column) { + if (column < 0) + column= UNDEFINED; + fColumn= column; + } + + /* + * @see IRule#evaluate(ICharacterScanner) + */ + public IToken evaluate(ICharacterScanner scanner) { + int c= scanner.read(); + if (fDetector.isWordStart((char) c)) { + if (fColumn == UNDEFINED || (fColumn == scanner.getColumn() - 1)) { + + fBuffer.clear(); + do { + fBuffer.append((char) c); + c= scanner.read(); + } while (c != ICharacterScanner.EOF && fDetector.isWordPart((char) c)); + scanner.unread(); + + for (int i= 0, n= fMatchers.size(); i < n; i++) { + IToken token= fMatchers.get(i).evaluate(scanner, fBuffer); + if (!token.isUndefined()) + return token; + } + + if (fDefaultToken.isUndefined()) + unreadBuffer(scanner); + + return fDefaultToken; + } + } + + scanner.unread(); + return Token.UNDEFINED; + } + + /** + * Returns the characters in the buffer to the scanner. + * + * @param scanner the scanner to be used + */ + private void unreadBuffer(ICharacterScanner scanner) { + for (int i= fBuffer.length() - 1; i >= 0; i--) + scanner.unread(); + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/TaskTagRule.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/TaskTagRule.java new file mode 100644 index 00000000000..2b30f89631a --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/TaskTagRule.java @@ -0,0 +1,217 @@ +/******************************************************************************* + * 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 + * Anton Leherbauer (Wind River Systems) + * Sergey Prigogin (Google) + * Andrew Ferguson (Symbian) + *******************************************************************************/ +package org.eclipse.cdt.internal.ui.text; + +import java.util.HashMap; +import java.util.Map; +import java.util.StringTokenizer; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.Preferences; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.text.rules.ICharacterScanner; +import org.eclipse.jface.text.rules.IToken; +import org.eclipse.jface.text.rules.IWordDetector; +import org.eclipse.jface.text.rules.Token; +import org.eclipse.jface.util.PropertyChangeEvent; + +import org.eclipse.cdt.core.CCorePreferenceConstants; +import org.eclipse.cdt.ui.IPropertyChangeParticipant; + +/** + * Which words should be recognized as task tags is specified under {@link CCorePreferenceConstants#TODO_TASK_TAGS} as a + * comma delimited list. + *

+ * Clients may instantiate and subclass. + *

+ * + * @see CCorePreferenceConstants#TODO_TASK_TAGS + * @since 5.0 + */ +public final class TaskTagRule extends CombinedWordRule implements IPropertyChangeParticipant { + private static class TaskTagDetector implements IWordDetector { + public boolean isWordStart(char c) { + return c == '@' || c == '\\' || Character.isJavaIdentifierStart(c); + } + + public boolean isWordPart(char c) { + return c == '.' || c == '(' || c == ')' || c == ':' || Character.isJavaIdentifierPart(c); + } + } + + private class TaskTagMatcher extends WordMatcher { + + private IToken fToken; + /** + * Uppercase words + */ + private Map fUppercaseWords= new HashMap(); + /** + * true if task tag detection is case-sensitive. + */ + private boolean fCaseSensitive= true; + /** + * Buffer for uppercase word + */ + private CharacterBuffer fBuffer= new CharacterBuffer(16); + + public TaskTagMatcher(IToken token) { + fToken= token; + } + + /* + * @see org.eclipse.jdt.internal.ui.text.CombinedWordRule.WordMatcher#clearWords() + */ + @Override + public synchronized void clearWords() { + super.clearWords(); + fUppercaseWords.clear(); + } + + public synchronized void addTaskTags(String value) { + String[] taskTags= value.split(","); //$NON-NLS-1$ + for (String tag : taskTags) { + if (tag.length() > 0) { + addWord(tag, fToken); + } + } + } + + private String[] split(String value, String delimiters) { + StringTokenizer tokenizer= new StringTokenizer(value, delimiters); + int size= tokenizer.countTokens(); + String[] tokens= new String[size]; + int i= 0; + while (i < size) + tokens[i++]= tokenizer.nextToken(); + return tokens; + } + + /* + * @see org.eclipse.cdt.internal.ui.text.CombinedWordRule.WordMatcher#addWord(java.lang.String, org.eclipse.jface.text.rules.IToken) + */ + @Override + public synchronized void addWord(String word, IToken token) { + Assert.isNotNull(word); + Assert.isNotNull(token); + + super.addWord(word, token); + fUppercaseWords.put(new CharacterBuffer(word.toUpperCase()), token); + } + + /* + * @see org.eclipse.cdt.internal.ui.text.CombinedWordRule.WordMatcher#evaluate(org.eclipse.jface.text.rules.ICharacterScanner, org.eclipse.jdt.internal.ui.text.CombinedWordRule.CharacterBuffer) + */ + @Override + public synchronized IToken evaluate(ICharacterScanner scanner, CharacterBuffer word) { + if (fCaseSensitive) + return super.evaluate(scanner, word); + + fBuffer.clear(); + for (int i= 0, n= word.length(); i < n; i++) + fBuffer.append(Character.toUpperCase(word.charAt(i))); + + IToken token= fUppercaseWords.get(fBuffer); + if (token != null) + return token; + return Token.UNDEFINED; + } + + /** + * Enables/disables the case-sensitivity of the task tag detection. + * + * @param caseSensitive true iff case-sensitivity should be enabled + */ + public void setCaseSensitive(boolean caseSensitive) { + fCaseSensitive= caseSensitive; + } + } + + private static final String TODO_TASK_TAGS= CCorePreferenceConstants.TODO_TASK_TAGS; + private static final String TODO_TASK_CASE_SENSITIVE= CCorePreferenceConstants.TODO_TASK_CASE_SENSITIVE; + private TaskTagMatcher fMatcher; + + /** + * Creates a new task tag rule + * @param token the token to return for words recognized as task tags + * @param defaultToken + * @param preferenceStore + * @param corePreferences + */ + public TaskTagRule(IToken token, IToken defaultToken, IPreferenceStore preferenceStore, + Preferences corePreferences) { + super(new TaskTagDetector(), defaultToken); + fMatcher = new TaskTagMatcher(token); + addWordMatcher(fMatcher); + String taskWords= null; + if (preferenceStore.contains(TODO_TASK_TAGS)) { + taskWords= preferenceStore.getString(TODO_TASK_TAGS); + } else if (corePreferences != null) { + taskWords= corePreferences.getString(TODO_TASK_TAGS); + } + if (taskWords != null) { + addTaskTags(taskWords); + } + + boolean isCaseSensitive= true; + if (preferenceStore.contains(TODO_TASK_CASE_SENSITIVE)) { + isCaseSensitive= preferenceStore.getBoolean(TODO_TASK_CASE_SENSITIVE); + } else if (corePreferences != null) { + isCaseSensitive= corePreferences.getBoolean(TODO_TASK_CASE_SENSITIVE); + } + fMatcher.setCaseSensitive(isCaseSensitive); + } + + /** + * Removes the current list of words that should be + * recognized as task tags. + */ + public void clearTaskTags() { + fMatcher.clearWords(); + } + + /** + * Adds tags from the specified string as task tags. + * @param value a comma delimited list of words to recognize as task tags + */ + public void addTaskTags(String value) { + fMatcher.addTaskTags(value); + } + + /* + * @see org.eclipse.cdt.ui.IPropertyChangeParticipant#affectsBehavior(org.eclipse.jface.util.PropertyChangeEvent) + */ + public boolean affectsBehavior(PropertyChangeEvent event) { + return event.getProperty().equals(TODO_TASK_TAGS) || event.getProperty().equals(TODO_TASK_CASE_SENSITIVE); + } + + /* + * @see org.eclipse.cdt.ui.IPropertyChangeParticipant#adaptToPreferenceChange(org.eclipse.jface.util.PropertyChangeEvent) + */ + public void adaptToPreferenceChange(PropertyChangeEvent event) { + if (event.getProperty().equals(TODO_TASK_TAGS)) { + Object value= event.getNewValue(); + if (value instanceof String) { + synchronized (fMatcher) { + fMatcher.clearWords(); + fMatcher.addTaskTags((String) value); + } + } + } else if (event.getProperty().equals(TODO_TASK_CASE_SENSITIVE)) { + Object value= event.getNewValue(); + if (value instanceof String) + fMatcher.setCaseSensitive(Boolean.parseBoolean((String) value)); + } + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/text/TaskTagRule.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/text/TaskTagRule.java deleted file mode 100644 index 5065cab1419..00000000000 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/text/TaskTagRule.java +++ /dev/null @@ -1,122 +0,0 @@ -/******************************************************************************* - * 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 - * Anton Leherbauer (Wind River Systems) - * Sergey Prigogin (Google) - * Andrew Ferguson (Symbian) - *******************************************************************************/ -package org.eclipse.cdt.ui.text; - -import org.eclipse.core.runtime.Preferences; -import org.eclipse.jface.preference.IPreferenceStore; -import org.eclipse.jface.text.rules.IToken; -import org.eclipse.jface.text.rules.IWordDetector; -import org.eclipse.jface.text.rules.Token; -import org.eclipse.jface.text.rules.WordRule; -import org.eclipse.jface.util.PropertyChangeEvent; - -import org.eclipse.cdt.core.CCorePreferenceConstants; -import org.eclipse.cdt.ui.IPropertyChangeParticipant; - -/** - * - * Which words should be recognized as task tags is specified under {@link CCorePreferenceConstants#TODO_TASK_TAGS} as a - * comma delimited list. - *

- * Clients may instantiate and subclass. - *

- * - * @see CCorePreferenceConstants#TODO_TASK_TAGS - * @since 5.0 - */ -public final class TaskTagRule extends WordRule implements IPropertyChangeParticipant { - private static class TaskTagDetector implements IWordDetector { - public boolean isWordStart(char c) { - return Character.isLetter(c); - } - public boolean isWordPart(char c) { - return Character.isLetter(c); - } - } - - /** - * Convenience method for extracting a list of words that should be recognized as - * task labels from an {@link IPreferenceStore} and a backup {@link Preferences} - * @param preferenceStore - * @param corePreferences - * @return a list of words that should be recognized as task labels in the format - * expected by TaskTagRule - */ - public static String getTaskWords(IPreferenceStore preferenceStore, Preferences corePreferences) { - String result= null; - if (preferenceStore.contains(CCorePreferenceConstants.TODO_TASK_TAGS)) { - result= preferenceStore.getString(CCorePreferenceConstants.TODO_TASK_TAGS); - } else if (corePreferences != null) { - result= corePreferences.getString(CCorePreferenceConstants.TODO_TASK_TAGS); - } - return result; - } - - private IToken fToken; - - /** - * Creates a new task tag rule - * @param token the token to return for words recognized as task tags - * @param taskWords a comma delimited list of words to recognize as task tags - */ - public TaskTagRule(IToken token, String taskWords) { - super(new TaskTagDetector(), Token.UNDEFINED); - fToken= token; - if( taskWords!= null) { - addTaskTags(taskWords); - } - } - - /** - * Removes the current list of words that should be - * recognized as task tags. - */ - public void clearTaskTags() { - fWords.clear(); - } - - /** - * Adds tags from the specified string as task tags. - * @param value a comma delimited list of words to recognize as task tags - */ - public void addTaskTags(String value) { - String[] tasks= value.split(","); //$NON-NLS-1$ - for (int i= 0; i < tasks.length; i++) { - if (tasks[i].length() > 0) { - addWord(tasks[i], fToken); - } - } - } - - /* - * @see org.eclipse.cdt.ui.IPropertyChangeParticipant#affectsBehavior(org.eclipse.jface.util.PropertyChangeEvent) - */ - public boolean affectsBehavior(PropertyChangeEvent event) { - return event.getProperty().equals(CCorePreferenceConstants.TODO_TASK_TAGS); - } - - /* - * @see org.eclipse.cdt.ui.IPropertyChangeParticipant#adaptToPreferenceChange(org.eclipse.jface.util.PropertyChangeEvent) - */ - public void adaptToPreferenceChange(PropertyChangeEvent event) { - if (event.getProperty().equals(CCorePreferenceConstants.TODO_TASK_TAGS)) { - Object value= event.getNewValue(); - - if (value instanceof String) { - clearTaskTags(); - addTaskTags((String) value); - } - } - } -} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/text/doctools/generic/GenericTagCommentScanner.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/text/doctools/generic/GenericTagCommentScanner.java index 5c9738b2158..d311f9764c5 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/text/doctools/generic/GenericTagCommentScanner.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/text/doctools/generic/GenericTagCommentScanner.java @@ -26,11 +26,12 @@ import org.eclipse.cdt.ui.PreferenceConstants; import org.eclipse.cdt.ui.text.ICTokenScanner; import org.eclipse.cdt.ui.text.ITokenStore; import org.eclipse.cdt.ui.text.ITokenStoreFactory; -import org.eclipse.cdt.ui.text.TaskTagRule; + +import org.eclipse.cdt.internal.ui.text.TaskTagRule; /** - * ICTokenScanner which recognizes a specified set of tags, starting with a specified name. It is assumed this will be - * used within a single-line or multi-line comment context. + * ICTokenScanner which recognizes a specified set of tags, starting with a specified name. + * It is assumed this will be used within a single-line or multi-line comment context. * @since 5.0 * @noextend This class is not intended to be subclassed by clients. */ @@ -82,8 +83,8 @@ public class GenericTagCommentScanner extends BufferedRuleBasedScanner implement class TagDetector implements IWordDetector { public boolean isWordStart(char c) { - for(int i=0; i