blob: 6f9649704db1bc53ce7df0de3f9332aadb2c1bb8 [file] [log] [blame]
/*******************************************************************************
* 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;
}
}
}