001: /*******************************************************************************
002: * Copyright (c) 2000, 2006 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.jdt.internal.ui.text.javadoc;
011:
012: import java.util.ArrayList;
013: import java.util.List;
014:
015: import org.eclipse.core.runtime.Preferences;
016:
017: import org.eclipse.jface.preference.IPreferenceStore;
018:
019: import org.eclipse.jface.text.BadLocationException;
020: import org.eclipse.jface.text.IDocument;
021: import org.eclipse.jface.text.rules.ICharacterScanner;
022: import org.eclipse.jface.text.rules.IToken;
023: import org.eclipse.jface.text.rules.IWordDetector;
024: import org.eclipse.jface.text.rules.SingleLineRule;
025: import org.eclipse.jface.text.rules.Token;
026: import org.eclipse.jface.text.rules.WhitespaceRule;
027: import org.eclipse.jface.text.rules.WordRule;
028:
029: import org.eclipse.jdt.ui.text.IColorManager;
030: import org.eclipse.jdt.ui.text.IJavaColorConstants;
031:
032: import org.eclipse.jdt.internal.ui.text.CombinedWordRule;
033: import org.eclipse.jdt.internal.ui.text.JavaCommentScanner;
034: import org.eclipse.jdt.internal.ui.text.JavaWhitespaceDetector;
035: import org.eclipse.jdt.internal.ui.text.CombinedWordRule.CharacterBuffer;
036: import org.eclipse.jdt.internal.ui.text.CombinedWordRule.WordMatcher;
037:
038: /**
039: * A rule based JavaDoc scanner.
040: */
041: public final class JavaDocScanner extends JavaCommentScanner {
042:
043: /**
044: * Detector for HTML comment delimiters.
045: */
046: static class HTMLCommentDetector implements IWordDetector {
047:
048: /**
049: * @see IWordDetector#isWordStart(char)
050: */
051: public boolean isWordStart(char c) {
052: return (c == '<' || c == '-');
053: }
054:
055: /**
056: * @see IWordDetector#isWordPart(char)
057: */
058: public boolean isWordPart(char c) {
059: return (c == '-' || c == '!' || c == '>');
060: }
061: }
062:
063: class TagRule extends SingleLineRule {
064:
065: /*
066: * @see SingleLineRule
067: */
068: public TagRule(IToken token) {
069: super ("<", ">", token, (char) 0); //$NON-NLS-2$ //$NON-NLS-1$
070: }
071:
072: /*
073: * @see SingleLineRule
074: */
075: public TagRule(IToken token, char escapeCharacter) {
076: super ("<", ">", token, escapeCharacter); //$NON-NLS-2$ //$NON-NLS-1$
077: }
078:
079: private IToken evaluateToken() {
080: try {
081: final String token = getDocument().get(
082: getTokenOffset(), getTokenLength())
083: + "."; //$NON-NLS-1$
084:
085: int offset = 0;
086: char character = token.charAt(++offset);
087:
088: if (character == '/')
089: character = token.charAt(++offset);
090:
091: while (Character.isWhitespace(character))
092: character = token.charAt(++offset);
093:
094: while (Character.isLetterOrDigit(character))
095: character = token.charAt(++offset);
096:
097: while (Character.isWhitespace(character))
098: character = token.charAt(++offset);
099:
100: if (offset >= 2
101: && token.charAt(offset) == fEndSequence[0])
102: return fToken;
103:
104: } catch (BadLocationException exception) {
105: // Do nothing
106: }
107: return getToken(IJavaColorConstants.JAVADOC_DEFAULT);
108: }
109:
110: /*
111: * @see PatternRule#evaluate(ICharacterScanner)
112: */
113: public IToken evaluate(ICharacterScanner scanner) {
114: IToken result = super .evaluate(scanner);
115: if (result == fToken)
116: return evaluateToken();
117: return result;
118: }
119: }
120:
121: private static String[] fgTokenProperties = {
122: IJavaColorConstants.JAVADOC_KEYWORD,
123: IJavaColorConstants.JAVADOC_TAG,
124: IJavaColorConstants.JAVADOC_LINK,
125: IJavaColorConstants.JAVADOC_DEFAULT, TASK_TAG };
126:
127: public JavaDocScanner(IColorManager manager,
128: IPreferenceStore store, Preferences coreStore) {
129: super (manager, store, coreStore,
130: IJavaColorConstants.JAVADOC_DEFAULT, fgTokenProperties);
131: }
132:
133: /**
134: * Initialize with the given arguments
135: * @param manager Color manager
136: * @param store Preference store
137: *
138: * @since 3.0
139: */
140: public JavaDocScanner(IColorManager manager, IPreferenceStore store) {
141: this (manager, store, null);
142: }
143:
144: public IDocument getDocument() {
145: return fDocument;
146: }
147:
148: /*
149: * @see AbstractJavaScanner#createRules()
150: */
151: protected List createRules() {
152:
153: List list = new ArrayList();
154:
155: // Add rule for tags.
156: Token token = getToken(IJavaColorConstants.JAVADOC_TAG);
157: list.add(new TagRule(token));
158:
159: // Add rule for HTML comments
160: WordRule wordRule = new WordRule(new HTMLCommentDetector(),
161: token);
162: wordRule.addWord("<!--", token); //$NON-NLS-1$
163: wordRule.addWord("--!>", token); //$NON-NLS-1$
164: list.add(wordRule);
165:
166: // Add rule for links.
167: token = getToken(IJavaColorConstants.JAVADOC_LINK);
168: list.add(new SingleLineRule("{@link", "}", token)); //$NON-NLS-2$ //$NON-NLS-1$
169: list.add(new SingleLineRule("{@value", "}", token)); //$NON-NLS-2$ //$NON-NLS-1$
170:
171: // Add generic whitespace rule.
172: list.add(new WhitespaceRule(new JavaWhitespaceDetector()));
173:
174: list.addAll(super .createRules());
175: return list;
176: }
177:
178: /*
179: * @see org.eclipse.jdt.internal.ui.text.JavaCommentScanner#createMatchers()
180: */
181: protected List createMatchers() {
182: List list = super .createMatchers();
183:
184: // Add word rule for keywords.
185: final IToken token = getToken(IJavaColorConstants.JAVADOC_KEYWORD);
186: WordMatcher matcher = new CombinedWordRule.WordMatcher() {
187: public IToken evaluate(ICharacterScanner scanner,
188: CharacterBuffer word) {
189: int length = word.length();
190: if (length > 1 && word.charAt(0) == '@') {
191: int i = 0;
192: try {
193: for (; i <= length; i++)
194: scanner.unread();
195: int c = scanner.read();
196: i--;
197: if (c == '*'
198: || Character.isWhitespace((char) c)) {
199: scanner.unread();
200: return token;
201: }
202: } finally {
203: for (; i >= 0; i--)
204: scanner.read();
205: }
206: }
207: return Token.UNDEFINED;
208: }
209: };
210: list.add(matcher);
211:
212: return list;
213: }
214: }
|