From c73a9f7eea3c230c23ddd8a317d24fbf7843576e Mon Sep 17 00:00:00 2001 From: robekras Date: Fri, 30 Dec 2011 11:18:02 +0000 Subject: [PATCH 1/1] 1) Fixed issue #764: Ignore strings when looking for single line comments. --- .../phpdt/internal/ui/text/PHPCodeReader.java | 338 ++++++++++++-------- 1 files changed, 206 insertions(+), 132 deletions(-) diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/PHPCodeReader.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/PHPCodeReader.java index fffffda..96d65c8 100644 --- a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/PHPCodeReader.java +++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/PHPCodeReader.java @@ -20,22 +20,15 @@ public class PHPCodeReader extends SingleCharReader { /** The EOF character */ public static final int EOF = -1; - private boolean fSkipComments = false; - - private boolean fSkipStrings = false; - - private boolean fForward = false; - + private boolean fSkipStrings = false; + private boolean fForward = false; + private IDocument fDocument; - - private int fOffset; - - private int fEnd = -1; - - private int fCachedLineNumber = -1; - - private int fCachedLineOffset = -1; + + private int fOffset; // The current text position within the editor's text + private int fEnd = -1; + private int fCachedLineNumber = -1; // Holds the last line we checked for single line comments public PHPCodeReader() { } @@ -93,76 +86,91 @@ public class PHPCodeReader extends SingleCharReader { } } - private void gotoCommentEnd() throws BadLocationException { - while (fOffset < fEnd) { - char current = fDocument.getChar(fOffset++); + private int gotoCommentEnd (int nTextPos) throws BadLocationException { + while (nTextPos < fEnd) { + char current = fDocument.getChar (nTextPos++); + if (current == '*') { - if (fOffset < fEnd && fDocument.getChar(fOffset) == '/') { - ++fOffset; - return; + if ((nTextPos < fEnd) && + (fDocument.getChar (nTextPos) == '/')) { + ++nTextPos; + + return nTextPos; } } } + + return nTextPos; } - private void gotoStringEnd(char delimiter) throws BadLocationException { - while (fOffset < fEnd) { - char current = fDocument.getChar(fOffset++); - if (current == '\\') { - // ignore escaped characters - ++fOffset; - } else if (current == delimiter) { - return; + /** + * + * @param delimiter + * @throws BadLocationException + */ + private int gotoStringEnd (int nTextPos, char delimiter) throws BadLocationException { + while (nTextPos < fEnd) { // If long as we are not at the end of text + char current = fDocument.getChar (nTextPos++); + + if (current == '\\') { // ignore escaped characters + ++nTextPos; + } + else if (current == delimiter) { + return nTextPos; } } + + return nTextPos; // End position } - private void gotoLineEnd() throws BadLocationException { - int line = fDocument.getLineOfOffset(fOffset); - fOffset = fDocument.getLineOffset(line + 1); + /** + * + * @param nTextPos The current text position + * + * @return The position of the start of next line + * + * @throws BadLocationException + */ + private int gotoLineEnd (int nTextPos) throws BadLocationException { + int line = fDocument.getLineOfOffset (nTextPos); // Get the line number of the current text position + + return fDocument.getLineOffset (line + 1); } - private int readForwards() throws BadLocationException { + private int readForwards () throws BadLocationException { while (fOffset < fEnd) { char current = fDocument.getChar(fOffset++); switch (current) { - case '"': - case '\'': - - if (fSkipStrings) { - gotoStringEnd(current); - continue; - } - - return current; - case '#': - - if (fSkipComments && fOffset < fEnd) { - gotoLineEnd(); - continue; - } - - return current; - - case '/': - - if (fSkipComments && fOffset < fEnd) { - char next = fDocument.getChar(fOffset); - if (next == '*') { - // a comment starts, advance to the comment end - ++fOffset; - gotoCommentEnd(); - continue; - } else if (next == '/') { - // '//'-comment starts, advance to the line end - gotoLineEnd(); - continue; - } - } - - return current; - + case '"': + case '\'': + if (fSkipStrings) { + fOffset = gotoStringEnd (fOffset, current); + continue; + } + return current; + + case '#': + if (fSkipComments && fOffset < fEnd) { + fOffset = gotoLineEnd (fOffset); + continue; + } + return current; + + case '/': + if (fSkipComments && fOffset < fEnd) { + char next = fDocument.getChar(fOffset); + + if (next == '*') { // A comment starts, advance to the comment end + ++fOffset; + fOffset = gotoCommentEnd (fOffset); + continue; + } else if (next == '/') { // '//'-comment starts, advance to the line end + fOffset = gotoLineEnd (fOffset); + continue; + } + } + return current; } return current; @@ -171,86 +179,152 @@ public class PHPCodeReader extends SingleCharReader { return EOF; } - private void handleSingleLineComment() throws BadLocationException { - int line = fDocument.getLineOfOffset(fOffset); - if (line < fCachedLineNumber) { - fCachedLineNumber = line; - fCachedLineOffset = fDocument.getLineOffset(line); - int offset = fOffset; - while (fCachedLineOffset < offset) { - char current = fDocument.getChar(offset--); - - if (current == '/' && fCachedLineOffset <= offset - && fDocument.getChar(offset) == '/') { - fOffset = offset; - return; - } - - if (current == '#' && fCachedLineOffset <= offset) { - fOffset = offset; - return; + /** + * Check whether the current line contains a single line comment. + * If it contains a single line comment (// or #), than set fOffset (the global character index) + * to the character just before the single line comment. + * + * @throws BadLocationException + */ + + private void handleSingleLineComment () throws BadLocationException { + char current; + int line = fDocument.getLineOfOffset (fOffset); // Get the line number which belongs to the current text position fOffset + + if (line < fCachedLineNumber) { // If we didn't parse this line already + fCachedLineNumber = line; // Remember this line for the next time (so we don't search again!) + int nOffset = fDocument.getLineOffset (line); // Get the start position of current line + + while (nOffset < fOffset) { // As long as the text position is within the current line + current = fDocument.getChar (nOffset); // Get the character from the current text position + + switch (current) { + case '/': + if (fDocument.getChar (nOffset + 1) == '/') { // If the following character is '/' + fOffset = nOffset - 1; + + return; + } + break; + + case '#': + fOffset = nOffset - 1; + return; + + case '"': // It's a string start quote + case '\'': + nOffset++; // Set to next character + + while (nOffset < fOffset) { // As long as we are within the same line + char cChar = fDocument.getChar (nOffset++); + + if (cChar == '\\') { // Ignore escaped characters + ++nOffset; + } + else if (cChar == current) { // If end of string found + break; + } + } + break; } + + nOffset++; // Go for the next character } } } - private void gotoCommentStart() throws BadLocationException { - while (0 < fOffset) { - char current = fDocument.getChar(fOffset--); - if (current == '*' && 0 <= fOffset - && fDocument.getChar(fOffset) == '/') - return; + /** + * We search the for the block comment start sequence "/*" + * + * The returned value points to the '/' + * + * @throws BadLocationException + * + * @return The new text position + */ + + private int gotoCommentStart (int nTextPos) throws BadLocationException { + while (0 < nTextPos) { // As long as we are not at the start of the editor text + char current = fDocument.getChar (nTextPos--); // Get the character from the current text position + + if ((current == '*') && // If current character is a '*' + (0 <= nTextPos) && // and if we are not yet at the start of the editor text + (fDocument.getChar (nTextPos) == '/')) { // and the previous character is a '/', + return nTextPos; // We found the block comment start "/*" + } } + + return nTextPos; } - private void gotoStringStart(char delimiter) throws BadLocationException { - while (0 < fOffset) { - char current = fDocument.getChar(fOffset); - if (current == delimiter) { - if (!(0 <= fOffset && fDocument.getChar(fOffset - 1) == '\\')) - return; + /** + * The string closing quote has been found, when reading the editor text backwards. + * So we have to search for the start of the string + * + * The returned value points to '"' or ''' + * + * @param delimiter The string double quote '"' or single ''' quote we search for + * + * @throws BadLocationException + */ + private int gotoStringStart (int nTextPos, char delimiter) throws BadLocationException { + while (0 < nTextPos) { // As long as we are not at the start of the editor text + char current = fDocument.getChar (nTextPos); // Get the character from the current text position + + if (current == delimiter) { // If we found the same character ('"' or ''') again, we have found the string start + if (!(0 <= nTextPos && + fDocument.getChar (nTextPos - 1) == '\\')) // If the character before the string quote is not an '/' + return nTextPos; // we found the string start } - --fOffset; + + --nTextPos; // Go one character back } + + return nTextPos; } + /** + * Read the editor text backwards + * + */ + private int readBackwards() throws BadLocationException { - - while (0 < fOffset) { - --fOffset; - - handleSingleLineComment(); - - char current = fDocument.getChar(fOffset); - switch (current) { - case '/': - - if (fSkipComments && fOffset > 1) { - char next = fDocument.getChar(fOffset - 1); - if (next == '*') { - // a comment ends, advance to the comment start - fOffset -= 2; - gotoCommentStart(); - continue; - } - } - - return current; - case '"': - case '\'': - - if (fSkipStrings) { - --fOffset; - gotoStringStart(current); - continue; - } - - return current; + char current; // The character on position fOffset + + while (0 < fOffset) { // As long as we are not at the beginning of the editor text + --fOffset; // Step back one character + + handleSingleLineComment (); // Search for a single line comment within the current line + // If there is a single line comment, fOffset is set to position just before the single line comment + + current = fDocument.getChar (fOffset); // Read the current character + switch (current) { // Process the current character + case '/': // Is it a single line comment? + if (fSkipComments && // When comments should be skipped when parsing + fOffset > 1) { // and if there is indeed an additional character before that '/' + char prev = fDocument.getChar (fOffset - 1); // Look at the character in front of the '/' + + if (prev == '*') { // If '*' than a block comment ends here, advance to the comment start + fOffset -= 2; // Set character pointer to character before "*/" + fOffset = gotoCommentStart (fOffset); // and search for the starting "/*" of the block comment + continue; + } + } + return current; // No block comment end, so return the current character + + case '"': // Is it a string double quote closing '"'? + case '\'': // or a string single quote closing '''? + if (fSkipStrings) { // If we should skip strings when parsing + --fOffset; // Set pointer one before the string closing quote + fOffset = gotoStringStart (fOffset, current);// and search the start of string ('"' or ''') + continue; + } + return current; // No string skip, so return the current character } - return current; + return current; // No string and no comment } - return EOF; + return EOF; // When the start of the text has been found } } -- 1.7.1