| /******************************************************************************* |
| * Copyright (c) 2000, 2009 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.internal.compiler; |
| |
| import org.eclipse.jdt.core.compiler.CharOperation; |
| import org.eclipse.jdt.internal.compiler.parser.JavadocParser; |
| import org.eclipse.jdt.internal.compiler.parser.Parser; |
| import org.eclipse.jdt.internal.compiler.parser.ScannerHelper; |
| import org.eclipse.jdt.internal.compiler.parser.TerminalTokens; |
| |
| public class SourceJavadocParser extends JavadocParser { |
| |
| // Store categories identifiers parsed in javadoc |
| int categoriesPtr = -1; |
| char[][] categories = CharOperation.NO_CHAR_CHAR; |
| |
| public SourceJavadocParser(Parser sourceParser) { |
| super(sourceParser); |
| this.kind = SOURCE_PARSER | TEXT_VERIF; |
| } |
| |
| public boolean checkDeprecation(int commentPtr) { |
| this.categoriesPtr = -1; |
| boolean result = super.checkDeprecation(commentPtr); |
| if (this.categoriesPtr > -1) { |
| System.arraycopy(this.categories, 0, this.categories = new char[this.categoriesPtr+1][], 0, this.categoriesPtr+1); |
| } else { |
| this.categories = CharOperation.NO_CHAR_CHAR; |
| } |
| return result; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.jdt.internal.compiler.parser.AbstractCommentParser#parseIdentifierTag() |
| */ |
| protected boolean parseIdentifierTag(boolean report) { |
| int end = this.lineEnd+1; |
| if (super.parseIdentifierTag(report) && this.index <= end) { |
| if (this.tagValue == TAG_CATEGORY_VALUE) { |
| // Store first category id |
| int length = this.categories.length; |
| if (++this.categoriesPtr >= length) { |
| System.arraycopy(this.categories, 0, this.categories = new char[length+5][], 0, length); |
| length += 5; |
| } |
| this.categories[this.categoriesPtr] = this.identifierStack[this.identifierPtr--]; |
| // Store optional additional category identifiers |
| consumeToken(); |
| while (this.index < end) { |
| if (readTokenSafely() == TerminalTokens.TokenNameIdentifier && (this.scanner.currentCharacter == ' ' || ScannerHelper.isWhitespace(this.scanner.currentCharacter))) { |
| if (this.index > (this.lineEnd+1)) break; |
| // valid additional identifier |
| if (++this.categoriesPtr >= length) { |
| System.arraycopy(this.categories, 0, this.categories = new char[length+5][], 0, length); |
| length += 5; |
| } |
| this.categories[this.categoriesPtr] = this.scanner.getCurrentIdentifierSource(); |
| consumeToken(); |
| } else { |
| // TODO (frederic) raise warning for invalid syntax when javadoc spec will be finalized... |
| break; |
| } |
| } |
| // Reset position to end of line |
| this.index = end; |
| this.scanner.currentPosition = end; |
| consumeToken(); |
| } |
| return true; |
| } |
| return false; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.jdt.internal.compiler.parser.JavadocParser#parseSimpleTag() |
| */ |
| protected void parseSimpleTag() { |
| |
| // Read first char |
| // readChar() code is inlined to balance additional method call in checkDeprectation(int) |
| char first = this.source[this.index++]; |
| if (first == '\\' && this.source[this.index] == 'u') { |
| int c1, c2, c3, c4; |
| int pos = this.index; |
| this.index++; |
| while (this.source[this.index] == 'u') |
| this.index++; |
| if (!(((c1 = ScannerHelper.getNumericValue(this.source[this.index++])) > 15 || c1 < 0) |
| || ((c2 = ScannerHelper.getNumericValue(this.source[this.index++])) > 15 || c2 < 0) |
| || ((c3 = ScannerHelper.getNumericValue(this.source[this.index++])) > 15 || c3 < 0) |
| || ((c4 = ScannerHelper.getNumericValue(this.source[this.index++])) > 15 || c4 < 0))) { |
| first = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4); |
| } else { |
| this.index = pos; |
| } |
| } |
| |
| // switch on first tag char |
| switch (first) { |
| case 'd': // perhaps @deprecated tag? |
| if ((readChar() == 'e') && |
| (readChar() == 'p') && (readChar() == 'r') && |
| (readChar() == 'e') && (readChar() == 'c') && |
| (readChar() == 'a') && (readChar() == 't') && |
| (readChar() == 'e') && (readChar() == 'd')) { |
| // ensure the tag is properly ended: either followed by a space, a tab, line end or asterisk. |
| char c = readChar(); |
| if (ScannerHelper.isWhitespace(c) || c == '*') { |
| this.tagValue = TAG_DEPRECATED_VALUE; |
| this.deprecated = true; |
| } |
| } |
| break; |
| case 'c': // perhaps @category tag? |
| if ((readChar() == 'a') && |
| (readChar() == 't') && (readChar() == 'e') && |
| (readChar() == 'g') && (readChar() == 'o') && |
| (readChar() == 'r') && (readChar() == 'y')) { |
| // ensure the tag is properly ended: either followed by a space, a tab, line end or asterisk. |
| char c = readChar(); |
| if (ScannerHelper.isWhitespace(c) || c == '*') { |
| this.tagValue = TAG_CATEGORY_VALUE; |
| if (this.scanner.source == null) { |
| this.scanner.setSource(this.source); |
| } |
| this.scanner.resetTo(this.index, this.scanner.eofPosition); |
| parseIdentifierTag(false); // Do not report missing identifier |
| } |
| } |
| break; |
| } |
| } |
| |
| } |