X-Git-Url: http://git.phpeclipse.com diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/parser/Scanner.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/parser/Scanner.java index a1127f5..751e8c0 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/parser/Scanner.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/parser/Scanner.java @@ -39,7 +39,9 @@ public class Scanner implements IScanner, ITerminalSymbols { public boolean phpMode = false; - public Stack encapsedStringStack = null; + public boolean phpExpressionTag = false; + +// public Stack encapsedStringStack = null; public char currentCharacter; @@ -126,6 +128,17 @@ public class Scanner implements IScanner, ITerminalSymbols { charArray_v = new char[] { 'v' }, charArray_w = new char[] { 'w' }, charArray_x = new char[] { 'x' }, charArray_y = new char[] { 'y' }, charArray_z = new char[] { 'z' }; + static final char[] charArray_va = new char[] { '$', 'a' }, charArray_vb = new char[] { '$', 'b' }, charArray_vc = new char[] { + '$', + 'c' }, charArray_vd = new char[] { '$', 'd' }, charArray_ve = new char[] { '$', 'e' }, + charArray_vf = new char[] { '$', 'f' }, charArray_vg = new char[] { '$', 'g' }, charArray_vh = new char[] { '$', 'h' }, + charArray_vi = new char[] { '$', 'i' }, charArray_vj = new char[] { '$', 'j' }, charArray_vk = new char[] { '$', 'k' }, + charArray_vl = new char[] { '$', 'l' }, charArray_vm = new char[] { '$', 'm' }, charArray_vn = new char[] { '$', 'n' }, + charArray_vo = new char[] { '$', 'o' }, charArray_vp = new char[] { '$', 'p' }, charArray_vq = new char[] { '$', 'q' }, + charArray_vr = new char[] { '$', 'r' }, charArray_vs = new char[] { '$', 's' }, charArray_vt = new char[] { '$', 't' }, + charArray_vu = new char[] { '$', 'u' }, charArray_vv = new char[] { '$', 'v' }, charArray_vw = new char[] { '$', 'w' }, + charArray_vx = new char[] { '$', 'x' }, charArray_vy = new char[] { '$', 'y' }, charArray_vz = new char[] { '$', 'z' }; + static final char[] initCharArray = new char[] { '\u0000', '\u0000', '\u0000', '\u0000', '\u0000', '\u0000' }; static final int TableSize = 30, InternalTableSize = 6; @@ -192,25 +205,36 @@ public class Scanner implements IScanner, ITerminalSymbols { public char[][] taskTags = null; public char[][] taskPriorities = null; + public boolean isTaskCaseSensitive = true; + public static final boolean DEBUG = false; public static final boolean TRACE = false; public ICompilationUnit compilationUnit = null; + + /** + * Determines if the specified character is permissible as the first character in a PHP identifier or variable + * + * The '$' character for PHP variables is regarded as a correct first character ! + * + */ + public static boolean isPHPIdentOrVarStart(char ch) { + return Character.isLetter(ch) || (ch == '$') || (ch == '_') || (0x7F <= ch && ch <= 0xFF); + } + /** - * Determines if the specified character is permissible - * as the first character in a PHP identifier. + * Determines if the specified character is permissible as the first character in a PHP identifier. * - * The '$' character for HP variables isn't regarded as the first character ! + * The '$' character for PHP variables isn't regarded as the first character ! */ public static boolean isPHPIdentifierStart(char ch) { return Character.isLetter(ch) || (ch == '_') || (0x7F <= ch && ch <= 0xFF); } /** - * Determines if the specified character may be part of a PHP - * identifier as other than the first character + * Determines if the specified character may be part of a PHP identifier as other than the first character */ public static boolean isPHPIdentifierPart(char ch) { return Character.isLetterOrDigit(ch) || (ch == '_') || (0x7F <= ch && ch <= 0xFF); @@ -311,6 +335,13 @@ public class Scanner implements IScanner, ITerminalSymbols { return result; } + public final char[] getRawTokenSourceEnd() { + int length = this.eofPosition - this.currentPosition - 1; + char[] sourceEnd = new char[length]; + System.arraycopy(this.source, this.currentPosition, sourceEnd, 0, length); + return sourceEnd; + } + public int getCurrentTokenStartPosition() { return this.startPosition; } @@ -335,6 +366,7 @@ public class Scanner implements IScanner, ITerminalSymbols { // } return result; } + /* * Search the source position corresponding to the end of a given line number * @@ -920,6 +952,10 @@ public class Scanner implements IScanner, ITerminalSymbols { withoutUnicodePtr--; } } + } else if ((currentCharacter == '\r') || (currentCharacter == '\n')) { + if (recordLineSeparator) { + pushLineSeparator(); + } } // consume next character unicodeAsBackSlash = false; @@ -1016,6 +1052,10 @@ public class Scanner implements IScanner, ITerminalSymbols { withoutUnicodePtr--; } } + } else if ((currentCharacter == '\r') || (currentCharacter == '\n')) { + if (recordLineSeparator) { + pushLineSeparator(); + } } // consume next character unicodeAsBackSlash = false; @@ -1063,36 +1103,12 @@ public class Scanner implements IScanner, ITerminalSymbols { public void consumeStringLiteral() throws InvalidInputException { try { + boolean openDollarBrace = false; // consume next character unicodeAsBackSlash = false; currentCharacter = source[currentPosition++]; - // if (((currentCharacter = source[currentPosition++]) == '\\') - // && (source[currentPosition] == 'u')) { - // getNextUnicodeChar(); - // } else { - // if (withoutUnicodePtr != 0) { - // withoutUnicodeBuffer[++withoutUnicodePtr] = - // currentCharacter; - // } - // } - while (currentCharacter != '"') { + while (currentCharacter != '"' || openDollarBrace) { /** ** in PHP \r and \n are valid in string literals *** */ - // if ((currentCharacter == '\n') - // || (currentCharacter == '\r')) { - // // relocate if finding another quote fairly close: thus unicode - // '/u000D' will be fully consumed - // for (int lookAhead = 0; lookAhead < 50; lookAhead++) { - // if (currentPosition + lookAhead == source.length) - // break; - // if (source[currentPosition + lookAhead] == '\n') - // break; - // if (source[currentPosition + lookAhead] == '\"') { - // currentPosition += lookAhead + 1; - // break; - // } - // } - // throw new InvalidInputException(INVALID_CHAR_IN_STRING); - // } if (currentCharacter == '\\') { int escapeSize = currentPosition; boolean backSlashAsUnicodeInString = unicodeAsBackSlash; @@ -1112,18 +1128,23 @@ public class Scanner implements IScanner, ITerminalSymbols { withoutUnicodePtr--; } } + } else if (currentCharacter == '$' && source[currentPosition] == '{') { + openDollarBrace = true; + } else if (currentCharacter == '{' && source[currentPosition] == '$') { + openDollarBrace = true; + } else if (currentCharacter == '}') { + openDollarBrace = false; + } else if ((currentCharacter == '\r') || (currentCharacter == '\n')) { + if (recordLineSeparator) { + pushLineSeparator(); + } } // consume next character unicodeAsBackSlash = false; currentCharacter = source[currentPosition++]; - // if (((currentCharacter = source[currentPosition++]) == '\\') - // && (source[currentPosition] == 'u')) { - // getNextUnicodeChar(); - // } else { if (withoutUnicodePtr != 0) { withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter; } - // } } } catch (IndexOutOfBoundsException e) { // reset end position for error reporting @@ -1158,8 +1179,9 @@ public class Scanner implements IScanner, ITerminalSymbols { } public int getNextToken() throws InvalidInputException { + phpExpressionTag = false; if (!phpMode) { - return getInlinedHTML(currentPosition); + return getInlinedHTMLToken(currentPosition); } if (phpMode) { this.wasAcr = false; @@ -1173,133 +1195,139 @@ public class Scanner implements IScanner, ITerminalSymbols { withoutUnicodePtr = 0; //start with a new token char encapsedChar = ' '; - if (!encapsedStringStack.isEmpty()) { - encapsedChar = ((Character) encapsedStringStack.peek()).charValue(); - } - if (encapsedChar != '$' && encapsedChar != ' ') { - currentCharacter = source[currentPosition++]; - if (currentCharacter == encapsedChar) { - switch (currentCharacter) { - case '`': - return TokenNameEncapsedString0; - case '\'': - return TokenNameEncapsedString1; - case '"': - return TokenNameEncapsedString2; - } - } - while (currentCharacter != encapsedChar) { - /** ** in PHP \r and \n are valid in string literals *** */ - switch (currentCharacter) { - case '\\': - int escapeSize = currentPosition; - boolean backSlashAsUnicodeInString = unicodeAsBackSlash; - //scanEscapeCharacter make a side effect on this value and - // we need the previous value few lines down this one - scanDoubleQuotedEscapeCharacter(); - escapeSize = currentPosition - escapeSize; - if (withoutUnicodePtr == 0) { - //buffer all the entries that have been left aside.... - withoutUnicodePtr = currentPosition - escapeSize - 1 - startPosition; - System.arraycopy(source, startPosition, withoutUnicodeBuffer, 1, withoutUnicodePtr); - withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter; - } else { //overwrite the / in the buffer - withoutUnicodeBuffer[withoutUnicodePtr] = currentCharacter; - if (backSlashAsUnicodeInString) { //there are TWO \ in - withoutUnicodePtr--; - } - } - break; - case '$': - if (isPHPIdentifierStart(source[currentPosition]) || source[currentPosition] == '{') { - currentPosition--; - encapsedStringStack.push(new Character('$')); - return TokenNameSTRING; - } - break; - case '{': - if (source[currentPosition] == '$') { // CURLY_OPEN - currentPosition--; - encapsedStringStack.push(new Character('$')); - return TokenNameSTRING; - } - } - // consume next character - unicodeAsBackSlash = false; - currentCharacter = source[currentPosition++]; - if (withoutUnicodePtr != 0) { - withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter; - } - // } - } // end while - currentPosition--; - return TokenNameSTRING; - } + // if (!encapsedStringStack.isEmpty()) { + // encapsedChar = ((Character) encapsedStringStack.peek()).charValue(); + // } + // if (encapsedChar != '$' && encapsedChar != ' ') { + // currentCharacter = source[currentPosition++]; + // if (currentCharacter == encapsedChar) { + // switch (currentCharacter) { + // case '`': + // return TokenNameEncapsedString0; + // case '\'': + // return TokenNameEncapsedString1; + // case '"': + // return TokenNameEncapsedString2; + // } + // } + // while (currentCharacter != encapsedChar) { + // /** ** in PHP \r and \n are valid in string literals *** */ + // switch (currentCharacter) { + // case '\\': + // int escapeSize = currentPosition; + // boolean backSlashAsUnicodeInString = unicodeAsBackSlash; + // //scanEscapeCharacter make a side effect on this value and + // // we need the previous value few lines down this one + // scanDoubleQuotedEscapeCharacter(); + // escapeSize = currentPosition - escapeSize; + // if (withoutUnicodePtr == 0) { + // //buffer all the entries that have been left aside.... + // withoutUnicodePtr = currentPosition - escapeSize - 1 - startPosition; + // System.arraycopy(source, startPosition, withoutUnicodeBuffer, 1, withoutUnicodePtr); + // withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter; + // } else { //overwrite the / in the buffer + // withoutUnicodeBuffer[withoutUnicodePtr] = currentCharacter; + // if (backSlashAsUnicodeInString) { //there are TWO \ in + // withoutUnicodePtr--; + // } + // } + // break; + // case '\r': + // case '\n': + // if (recordLineSeparator) { + // pushLineSeparator(); + // } + // break; + // case '$': + // if (isPHPIdentifierStart(source[currentPosition]) || source[currentPosition] == '{') { + // currentPosition--; + // encapsedStringStack.push(new Character('$')); + // return TokenNameSTRING; + // } + // break; + // case '{': + // if (source[currentPosition] == '$') { // CURLY_OPEN + // currentPosition--; + // encapsedStringStack.push(new Character('$')); + // return TokenNameSTRING; + // } + // } + // // consume next character + // unicodeAsBackSlash = false; + // currentCharacter = source[currentPosition++]; + // if (withoutUnicodePtr != 0) { + // withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter; + // } + // // } + // } // end while + // currentPosition--; + // return TokenNameSTRING; + // } // ---------Consume white space and handles startPosition--------- int whiteStart = currentPosition; startPosition = currentPosition; currentCharacter = source[currentPosition++]; - if (encapsedChar == '$') { - switch (currentCharacter) { - case '\\': - currentCharacter = source[currentPosition++]; - return TokenNameSTRING; - case '{': - if (encapsedChar == '$') { - if (getNextChar('$')) - return TokenNameLBRACE_DOLLAR; - } - return TokenNameLBRACE; - case '}': - return TokenNameRBRACE; - case '[': - return TokenNameLBRACKET; - case ']': - return TokenNameRBRACKET; - case '\'': - if (tokenizeStrings) { - consumeStringConstant(); - return TokenNameStringSingleQuote; - } - return TokenNameEncapsedString1; - case '"': - return TokenNameEncapsedString2; - case '`': - if (tokenizeStrings) { - consumeStringInterpolated(); - return TokenNameStringInterpolated; - } - return TokenNameEncapsedString0; - case '-': - if (getNextChar('>')) - return TokenNameMINUS_GREATER; - return TokenNameSTRING; - default: - if (currentCharacter == '$') { - int oldPosition = currentPosition; - try { - currentCharacter = source[currentPosition++]; - if (currentCharacter == '{') { - return TokenNameDOLLAR_LBRACE; - } - if (isPHPIdentifierStart(currentCharacter)) { - return scanIdentifierOrKeyword(true); - } else { - currentPosition = oldPosition; - return TokenNameSTRING; - } - } catch (IndexOutOfBoundsException e) { - currentPosition = oldPosition; - return TokenNameSTRING; - } - } - if (isPHPIdentifierStart(currentCharacter)) - return scanIdentifierOrKeyword(false); - if (Character.isDigit(currentCharacter)) - return scanNumber(false); - return TokenNameERROR; - } - } + // if (encapsedChar == '$') { + // switch (currentCharacter) { + // case '\\': + // currentCharacter = source[currentPosition++]; + // return TokenNameSTRING; + // case '{': + // if (encapsedChar == '$') { + // if (getNextChar('$')) + // return TokenNameLBRACE_DOLLAR; + // } + // return TokenNameLBRACE; + // case '}': + // return TokenNameRBRACE; + // case '[': + // return TokenNameLBRACKET; + // case ']': + // return TokenNameRBRACKET; + // case '\'': + // if (tokenizeStrings) { + // consumeStringConstant(); + // return TokenNameStringSingleQuote; + // } + // return TokenNameEncapsedString1; + // case '"': + // return TokenNameEncapsedString2; + // case '`': + // if (tokenizeStrings) { + // consumeStringInterpolated(); + // return TokenNameStringInterpolated; + // } + // return TokenNameEncapsedString0; + // case '-': + // if (getNextChar('>')) + // return TokenNameMINUS_GREATER; + // return TokenNameSTRING; + // default: + // if (currentCharacter == '$') { + // int oldPosition = currentPosition; + // try { + // currentCharacter = source[currentPosition++]; + // if (currentCharacter == '{') { + // return TokenNameDOLLAR_LBRACE; + // } + // if (isPHPIdentifierStart(currentCharacter)) { + // return scanIdentifierOrKeyword(true); + // } else { + // currentPosition = oldPosition; + // return TokenNameSTRING; + // } + // } catch (IndexOutOfBoundsException e) { + // currentPosition = oldPosition; + // return TokenNameSTRING; + // } + // } + // if (isPHPIdentifierStart(currentCharacter)) + // return scanIdentifierOrKeyword(false); + // if (Character.isDigit(currentCharacter)) + // return scanNumber(false); + // return TokenNameERROR; + // } + // } // boolean isWhiteSpace; while ((currentCharacter == ' ') || Character.isWhitespace(currentCharacter)) { @@ -1505,7 +1533,7 @@ public class Scanner implements IScanner, ITerminalSymbols { phpMode = true; return TokenNameINLINE_HTML; } - return getInlinedHTML(currentPosition - 2); + return getInlinedHTMLToken(currentPosition - 2); } return TokenNameQUESTION; case ':': @@ -1518,21 +1546,21 @@ public class Scanner implements IScanner, ITerminalSymbols { consumeStringConstant(); return TokenNameStringSingleQuote; case '"': - if (tokenizeStrings) { +// if (tokenizeStrings) { consumeStringLiteral(); return TokenNameStringDoubleQuote; - } - return TokenNameEncapsedString2; +// } +// return TokenNameEncapsedString2; case '`': - if (tokenizeStrings) { +// if (tokenizeStrings) { consumeStringInterpolated(); return TokenNameStringInterpolated; - } - return TokenNameEncapsedString0; +// } +// return TokenNameEncapsedString0; case '#': case '/': { char startChar = currentCharacter; - if (getNextChar('=') && startChar=='/') { + if (getNextChar('=') && startChar == '/') { return TokenNameDIVIDE_EQUAL; } int test; @@ -1755,7 +1783,7 @@ public class Scanner implements IScanner, ITerminalSymbols { return TokenNameCOMMENT_PHPDOC; return TokenNameCOMMENT_BLOCK; } - + if (this.taskTags != null) { checkTaskTag(this.startPosition, this.currentPosition); } @@ -1804,45 +1832,11 @@ public class Scanner implements IScanner, ITerminalSymbols { return TokenNameEOF; } - private int getInlinedHTML(int start) throws InvalidInputException { - int token = getInlinedHTMLToken(start); - if (token == TokenNameINLINE_HTML) { - // Stack stack = new Stack(); - // // scan html for errors - // Source inlinedHTMLSource = new Source(new String(source, startPosition, currentPosition - startPosition)); - // int lastPHPEndPos=0; - // for (Iterator i=inlinedHTMLSource.getNextTagIterator(0); i.hasNext();) { - // Tag tag=(Tag)i.next(); - // - // if (tag instanceof StartTag) { - // StartTag startTag=(StartTag)tag; - // // System.out.println("startTag: "+tag); - // if (startTag.isServerTag()) { - // // TODO : what to do with a server tag ? - // } else { - // // do whatever with HTML start tag - // // use startTag.getElement() to find the element corresponding - // // to this start tag which may be useful if you implement code - // // folding etc - // stack.push(startTag); - // } - // } else { - // EndTag endTag=(EndTag)tag; - // StartTag stag = (StartTag) stack.peek(); - //// System.out.println("endTag: "+tag); - // // do whatever with HTML end tag. - // } - // } - } - return token; - } - /** * @return * @throws InvalidInputException */ private int getInlinedHTMLToken(int start) throws InvalidInputException { - // int htmlPosition = start; if (currentPosition > source.length) { currentPosition = source.length; return TokenNameEOF; @@ -1854,9 +1848,14 @@ public class Scanner implements IScanner, ITerminalSymbols { if (currentCharacter == '<') { if (getNextChar('?')) { currentCharacter = source[currentPosition++]; - if ((currentCharacter == ' ') || Character.isWhitespace(currentCharacter)) { + if ((currentCharacter != 'P') && (currentCharacter != 'p')) { + if (currentCharacter != '=') { // = 0) { + test = getNextChar('P', 'p'); if (test >= 0) { - test = getNextChar('P', 'p'); - if (test >= 0) { - // 0 - && this.foundTaskPositions[this.foundTaskCount - 1][0] >= commentStart) { - return; - } - int foundTaskIndex = this.foundTaskCount; - char previous = src[commentStart+1]; // should be '*' or '/' - nextChar : for ( - int i = commentStart + 2; i < commentEnd && i < this.eofPosition; i++) { - char[] tag = null; - char[] priority = null; - // check for tag occurrence only if not ambiguous with javadoc tag - if (previous != '@') { - nextTag : for (int itag = 0; itag < this.taskTags.length; itag++) { - tag = this.taskTags[itag]; - int tagLength = tag.length; - if (tagLength == 0) continue nextTag; - - // ensure tag is not leaded with letter if tag starts with a letter - if (Character.isJavaIdentifierStart(tag[0])) { - if (Character.isJavaIdentifierPart(previous)) { - continue nextTag; - } - } - - for (int t = 0; t < tagLength; t++) { - char sc, tc; - int x = i+t; - if (x >= this.eofPosition || x >= commentEnd) continue nextTag; - if ((sc = src[i + t]) != (tc = tag[t])) { // case sensitive check - if (this.isTaskCaseSensitive || (Character.toLowerCase(sc) != Character.toLowerCase(tc))) { // case insensitive check - continue nextTag; - } - } - } - // ensure tag is not followed with letter if tag finishes with a letter - if (i+tagLength < commentEnd && Character.isJavaIdentifierPart(src[i+tagLength-1])) { - if (Character.isJavaIdentifierPart(src[i + tagLength])) - continue nextTag; - } - if (this.foundTaskTags == null) { - this.foundTaskTags = new char[5][]; - this.foundTaskMessages = new char[5][]; - this.foundTaskPriorities = new char[5][]; - this.foundTaskPositions = new int[5][]; - } else if (this.foundTaskCount == this.foundTaskTags.length) { - System.arraycopy(this.foundTaskTags, 0, this.foundTaskTags = new char[this.foundTaskCount * 2][], 0, this.foundTaskCount); - System.arraycopy(this.foundTaskMessages, 0, this.foundTaskMessages = new char[this.foundTaskCount * 2][], 0, this.foundTaskCount); - System.arraycopy(this.foundTaskPriorities, 0, this.foundTaskPriorities = new char[this.foundTaskCount * 2][], 0, this.foundTaskCount); - System.arraycopy(this.foundTaskPositions, 0, this.foundTaskPositions = new int[this.foundTaskCount * 2][], 0, this.foundTaskCount); - } - - priority = this.taskPriorities != null && itag < this.taskPriorities.length - ? this.taskPriorities[itag] - : null; - - this.foundTaskTags[this.foundTaskCount] = tag; - this.foundTaskPriorities[this.foundTaskCount] = priority; - this.foundTaskPositions[this.foundTaskCount] = new int[] { i, i + tagLength - 1 }; - this.foundTaskMessages[this.foundTaskCount] = CharOperation.NO_CHAR; - this.foundTaskCount++; - i += tagLength - 1; // will be incremented when looping - break nextTag; - } - } - previous = src[i]; - } - for (int i = foundTaskIndex; i < this.foundTaskCount; i++) { - // retrieve message start and end positions - int msgStart = this.foundTaskPositions[i][0] + this.foundTaskTags[i].length; - int max_value = i + 1 < this.foundTaskCount - ? this.foundTaskPositions[i + 1][0] - 1 - : commentEnd - 1; - // at most beginning of next task - if (max_value < msgStart) { - max_value = msgStart; // would only occur if tag is before EOF. - } - int end = -1; - char c; - for (int j = msgStart; j < max_value; j++) { - if ((c = src[j]) == '\n' || c == '\r') { - end = j - 1; - break; - } - } - if (end == -1) { - for (int j = max_value; j > msgStart; j--) { - if ((c = src[j]) == '*') { - end = j - 1; - break; - } - } - if (end == -1) - end = max_value; - } - if (msgStart == end) - continue; // empty - // trim the message - while (CharOperation.isWhitespace(src[end]) && msgStart <= end) - end--; - while (CharOperation.isWhitespace(src[msgStart]) && msgStart <= end) - msgStart++; - // update the end position of the task - this.foundTaskPositions[i][1] = end; - // get the message source - final int messageLength = end - msgStart + 1; - char[] message = new char[messageLength]; - System.arraycopy(src, msgStart, message, 0, messageLength); - this.foundTaskMessages[i] = message; - } -} + //chech presence of task: tags + //TODO (frederic) see if we need to take unicode characters into account... + public void checkTaskTag(int commentStart, int commentEnd) { + char[] src = this.source; + + // only look for newer task: tags + if (this.foundTaskCount > 0 && this.foundTaskPositions[this.foundTaskCount - 1][0] >= commentStart) { + return; + } + int foundTaskIndex = this.foundTaskCount; + char previous = src[commentStart + 1]; // should be '*' or '/' + nextChar: for (int i = commentStart + 2; i < commentEnd && i < this.eofPosition; i++) { + char[] tag = null; + char[] priority = null; + // check for tag occurrence only if not ambiguous with javadoc tag + if (previous != '@') { + nextTag: for (int itag = 0; itag < this.taskTags.length; itag++) { + tag = this.taskTags[itag]; + int tagLength = tag.length; + if (tagLength == 0) + continue nextTag; + + // ensure tag is not leaded with letter if tag starts with a letter + if (Scanner.isPHPIdentifierStart(tag[0])) { + if (Scanner.isPHPIdentifierPart(previous)) { + continue nextTag; + } + } + + for (int t = 0; t < tagLength; t++) { + char sc, tc; + int x = i + t; + if (x >= this.eofPosition || x >= commentEnd) + continue nextTag; + if ((sc = src[i + t]) != (tc = tag[t])) { // case sensitive check + if (this.isTaskCaseSensitive || (Character.toLowerCase(sc) != Character.toLowerCase(tc))) { // case insensitive check + continue nextTag; + } + } + } + // ensure tag is not followed with letter if tag finishes with a letter + if (i + tagLength < commentEnd && Scanner.isPHPIdentifierPart(src[i + tagLength - 1])) { + if (Scanner.isPHPIdentifierPart(src[i + tagLength])) + continue nextTag; + } + if (this.foundTaskTags == null) { + this.foundTaskTags = new char[5][]; + this.foundTaskMessages = new char[5][]; + this.foundTaskPriorities = new char[5][]; + this.foundTaskPositions = new int[5][]; + } else if (this.foundTaskCount == this.foundTaskTags.length) { + System.arraycopy(this.foundTaskTags, 0, this.foundTaskTags = new char[this.foundTaskCount * 2][], 0, + this.foundTaskCount); + System.arraycopy(this.foundTaskMessages, 0, this.foundTaskMessages = new char[this.foundTaskCount * 2][], 0, + this.foundTaskCount); + System.arraycopy(this.foundTaskPriorities, 0, this.foundTaskPriorities = new char[this.foundTaskCount * 2][], 0, + this.foundTaskCount); + System.arraycopy(this.foundTaskPositions, 0, this.foundTaskPositions = new int[this.foundTaskCount * 2][], 0, + this.foundTaskCount); + } + + priority = this.taskPriorities != null && itag < this.taskPriorities.length ? this.taskPriorities[itag] : null; + + this.foundTaskTags[this.foundTaskCount] = tag; + this.foundTaskPriorities[this.foundTaskCount] = priority; + this.foundTaskPositions[this.foundTaskCount] = new int[] { i, i + tagLength - 1 }; + this.foundTaskMessages[this.foundTaskCount] = CharOperation.NO_CHAR; + this.foundTaskCount++; + i += tagLength - 1; // will be incremented when looping + break nextTag; + } + } + previous = src[i]; + } + for (int i = foundTaskIndex; i < this.foundTaskCount; i++) { + // retrieve message start and end positions + int msgStart = this.foundTaskPositions[i][0] + this.foundTaskTags[i].length; + int max_value = i + 1 < this.foundTaskCount ? this.foundTaskPositions[i + 1][0] - 1 : commentEnd - 1; + // at most beginning of next task + if (max_value < msgStart) { + max_value = msgStart; // would only occur if tag is before EOF. + } + int end = -1; + char c; + for (int j = msgStart; j < max_value; j++) { + if ((c = src[j]) == '\n' || c == '\r') { + end = j - 1; + break; + } + } + if (end == -1) { + for (int j = max_value; j > msgStart; j--) { + if ((c = src[j]) == '*') { + end = j - 1; + break; + } + } + if (end == -1) + end = max_value; + } + if (msgStart == end) + continue; // empty + // trim the message + while (CharOperation.isWhitespace(src[end]) && msgStart <= end) + end--; + while (CharOperation.isWhitespace(src[msgStart]) && msgStart <= end) + msgStart++; + // update the end position of the task + this.foundTaskPositions[i][1] = end; + // get the message source + final int messageLength = end - msgStart + 1; + char[] message = new char[messageLength]; + System.arraycopy(src, msgStart, message, 0, messageLength); + this.foundTaskMessages[i] = message; + } + } // chech presence of task: tags -// public void checkTaskTag(int commentStart, int commentEnd) { -// // only look for newer task: tags -// if (this.foundTaskCount > 0 && this.foundTaskPositions[this.foundTaskCount - 1][0] >= commentStart) { -// return; -// } -// int foundTaskIndex = this.foundTaskCount; -// nextChar: for (int i = commentStart; i < commentEnd && i < this.eofPosition; i++) { -// char[] tag = null; -// char[] priority = null; -// // check for tag occurrence -// nextTag: for (int itag = 0; itag < this.taskTags.length; itag++) { -// tag = this.taskTags[itag]; -// priority = this.taskPriorities != null && itag < this.taskPriorities.length ? this.taskPriorities[itag] : null; -// int tagLength = tag.length; -// for (int t = 0; t < tagLength; t++) { -// if (this.source[i + t] != tag[t]) -// continue nextTag; -// } -// if (this.foundTaskTags == null) { -// this.foundTaskTags = new char[5][]; -// this.foundTaskMessages = new char[5][]; -// this.foundTaskPriorities = new char[5][]; -// this.foundTaskPositions = new int[5][]; -// } else if (this.foundTaskCount == this.foundTaskTags.length) { -// System.arraycopy(this.foundTaskTags, 0, this.foundTaskTags = new char[this.foundTaskCount * 2][], 0, this.foundTaskCount); -// System.arraycopy(this.foundTaskMessages, 0, this.foundTaskMessages = new char[this.foundTaskCount * 2][], 0, -// this.foundTaskCount); -// System.arraycopy(this.foundTaskPriorities, 0, this.foundTaskPriorities = new char[this.foundTaskCount * 2][], 0, -// this.foundTaskCount); -// System.arraycopy(this.foundTaskPositions, 0, this.foundTaskPositions = new int[this.foundTaskCount * 2][], 0, -// this.foundTaskCount); -// } -// this.foundTaskTags[this.foundTaskCount] = tag; -// this.foundTaskPriorities[this.foundTaskCount] = priority; -// this.foundTaskPositions[this.foundTaskCount] = new int[] { i, i + tagLength - 1 }; -// this.foundTaskMessages[this.foundTaskCount] = CharOperation.NO_CHAR; -// this.foundTaskCount++; -// i += tagLength - 1; // will be incremented when looping -// } -// } -// for (int i = foundTaskIndex; i < this.foundTaskCount; i++) { -// // retrieve message start and end positions -// int msgStart = this.foundTaskPositions[i][0] + this.foundTaskTags[i].length; -// int max_value = i + 1 < this.foundTaskCount ? this.foundTaskPositions[i + 1][0] - 1 : commentEnd - 1; -// // at most beginning of next task -// if (max_value < msgStart) -// max_value = msgStart; // would only occur if tag is before EOF. -// int end = -1; -// char c; -// for (int j = msgStart; j < max_value; j++) { -// if ((c = this.source[j]) == '\n' || c == '\r') { -// end = j - 1; -// break; -// } -// } -// if (end == -1) { -// for (int j = max_value; j > msgStart; j--) { -// if ((c = this.source[j]) == '*') { -// end = j - 1; -// break; -// } -// } -// if (end == -1) -// end = max_value; -// } -// if (msgStart == end) -// continue; // empty -// // trim the message -// while (CharOperation.isWhitespace(source[end]) && msgStart <= end) -// end--; -// while (CharOperation.isWhitespace(source[msgStart]) && msgStart <= end) -// msgStart++; -// // update the end position of the task -// this.foundTaskPositions[i][1] = end; -// // get the message source -// final int messageLength = end - msgStart + 1; -// char[] message = new char[messageLength]; -// System.arraycopy(source, msgStart, message, 0, messageLength); -// this.foundTaskMessages[i] = message; -// } -// } + // public void checkTaskTag(int commentStart, int commentEnd) { + // // only look for newer task: tags + // if (this.foundTaskCount > 0 && this.foundTaskPositions[this.foundTaskCount - 1][0] >= commentStart) { + // return; + // } + // int foundTaskIndex = this.foundTaskCount; + // nextChar: for (int i = commentStart; i < commentEnd && i < this.eofPosition; i++) { + // char[] tag = null; + // char[] priority = null; + // // check for tag occurrence + // nextTag: for (int itag = 0; itag < this.taskTags.length; itag++) { + // tag = this.taskTags[itag]; + // priority = this.taskPriorities != null && itag < this.taskPriorities.length ? this.taskPriorities[itag] : null; + // int tagLength = tag.length; + // for (int t = 0; t < tagLength; t++) { + // if (this.source[i + t] != tag[t]) + // continue nextTag; + // } + // if (this.foundTaskTags == null) { + // this.foundTaskTags = new char[5][]; + // this.foundTaskMessages = new char[5][]; + // this.foundTaskPriorities = new char[5][]; + // this.foundTaskPositions = new int[5][]; + // } else if (this.foundTaskCount == this.foundTaskTags.length) { + // System.arraycopy(this.foundTaskTags, 0, this.foundTaskTags = new char[this.foundTaskCount * 2][], 0, this.foundTaskCount); + // System.arraycopy(this.foundTaskMessages, 0, this.foundTaskMessages = new char[this.foundTaskCount * 2][], 0, + // this.foundTaskCount); + // System.arraycopy(this.foundTaskPriorities, 0, this.foundTaskPriorities = new char[this.foundTaskCount * 2][], 0, + // this.foundTaskCount); + // System.arraycopy(this.foundTaskPositions, 0, this.foundTaskPositions = new int[this.foundTaskCount * 2][], 0, + // this.foundTaskCount); + // } + // this.foundTaskTags[this.foundTaskCount] = tag; + // this.foundTaskPriorities[this.foundTaskCount] = priority; + // this.foundTaskPositions[this.foundTaskCount] = new int[] { i, i + tagLength - 1 }; + // this.foundTaskMessages[this.foundTaskCount] = CharOperation.NO_CHAR; + // this.foundTaskCount++; + // i += tagLength - 1; // will be incremented when looping + // } + // } + // for (int i = foundTaskIndex; i < this.foundTaskCount; i++) { + // // retrieve message start and end positions + // int msgStart = this.foundTaskPositions[i][0] + this.foundTaskTags[i].length; + // int max_value = i + 1 < this.foundTaskCount ? this.foundTaskPositions[i + 1][0] - 1 : commentEnd - 1; + // // at most beginning of next task + // if (max_value < msgStart) + // max_value = msgStart; // would only occur if tag is before EOF. + // int end = -1; + // char c; + // for (int j = msgStart; j < max_value; j++) { + // if ((c = this.source[j]) == '\n' || c == '\r') { + // end = j - 1; + // break; + // } + // } + // if (end == -1) { + // for (int j = max_value; j > msgStart; j--) { + // if ((c = this.source[j]) == '*') { + // end = j - 1; + // break; + // } + // } + // if (end == -1) + // end = max_value; + // } + // if (msgStart == end) + // continue; // empty + // // trim the message + // while (CharOperation.isWhitespace(source[end]) && msgStart <= end) + // end--; + // while (CharOperation.isWhitespace(source[msgStart]) && msgStart <= end) + // msgStart++; + // // update the end position of the task + // this.foundTaskPositions[i][1] = end; + // // get the message source + // final int messageLength = end - msgStart + 1; + // char[] message = new char[messageLength]; + // System.arraycopy(source, msgStart, message, 0, messageLength); + // this.foundTaskMessages[i] = message; + // } + // } } \ No newline at end of file