blob: 354c453f2ddde668b443fb3d0c5f3a2c2033847a [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2009 QNX Software Systems 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:
* QNX Software Systems - Initial API and implementation
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.Region;
/**
* This is a helper class for the text editor to be able to determine, given a
* particular offset in a document, various candidates segments for things like
* context help, proposals and hovering.
*/
public class CWordFinder {
private static final char CBRACE_L = '{';
private static final char CBRACE_R = '}';
private static final char PAREN_R = ')';
/**
* This method determines for a given offset into a given document what the
* region is which defines the current word. A word is defined as a contiguous
* sequence of C-identifier characters. So assuming that | indicates the current
* cursor position:
* <pre>
* |afunction(int a, int b) --> word = afunction
* afunc|tion(int a, int b) --> word = afunction
* afunction|(int a, int b) --> word = afunction
* afunction(|int a, int b) --> word = int
* afunction(int a,| int b) --> word = length 0
* afunction(|) --> word = length 0
* </pre>
*
* @param document
* The document to be examined
* @param offset
* The offset into the document where a word should be
* identified.
* @return The region defining the current word, which may be a region of
* length 0 if the offset is not in a word, or null if there is an
* error accessing the document data.
*/
public static IRegion findWord(IDocument document, int offset) {
int start = -2;
int end = -1;
try {
int pos = offset;
char c;
while (--pos >= 0) {
c = document.getChar(pos);
if (!Character.isJavaIdentifierPart(c)) {
break;
}
}
start = pos;
pos = offset;
int length = document.getLength();
while (pos < length) {
c = document.getChar(pos);
if (!Character.isJavaIdentifierPart(c))
break;
++pos;
}
end = pos;
} catch (BadLocationException x) {
}
if (start >= -1 && end > -1) {
if (start == offset && end == offset)
return new Region(offset, 0);
else if (start == offset)
return new Region(start, end - start);
else
return new Region(start + 1, end - start - 1);
}
return null;
}
/**
* This method will determine the region for the name of the function within
* which the current offset is contained.
*
* @param document
* The document to be examined
* @param offset
* The offset into the document where a word should be
* identified.
* @return The region defining the current word, which may be a region of
* length 0 if the offset is not in a function, or null if there is
* an error accessing the document data.
*/
public static IRegion findFunction(IDocument document, int offset) {
int leftbracket = -1;
int leftbracketcount = 0;
int rightbracket = -1;
int rightbracketcount = 0;
int functionstart = -1;
int functionend = -1;
try {
int length = document.getLength();
int pos;
char c;
//Find most relevant right bracket from our position
pos = offset;
rightbracketcount = leftbracketcount = 0;
while (pos < length) {
c = document.getChar(pos);
if (c == ')') {
rightbracketcount++;
if (rightbracketcount >= leftbracketcount) {
rightbracket = pos;
break;
}
}
if (c == '(') {
leftbracketcount++;
}
if (c == ';') {
break;
}
pos++;
}
if (rightbracket == -1) {
return new Region(offset, 0);
}
// Now backtrack our way from the right bracket to the left
pos = rightbracket;
rightbracketcount = leftbracketcount = 0;
while (pos >= 0) {
c = document.getChar(pos);
if (c == ')') {
rightbracketcount++;
}
if (c == '(') {
leftbracketcount++;
if (leftbracketcount >= rightbracketcount) {
leftbracket = pos;
break;
}
}
if (c == ';') {
break;
}
pos--;
}
if (leftbracket == -1) {
return new Region(offset, 0);
}
// Now work our way to the function name
pos = leftbracket - 1;
while (pos >= 0) {
c = document.getChar(pos);
if (functionend == -1 && c == ' ') {
pos--;
continue;
}
if (!Character.isJavaIdentifierPart(c)) {
break;
}
functionstart = pos;
if (functionend == -1) {
functionend = pos;
}
pos--;
}
} catch (BadLocationException x) {
/* Ignore */
}
if (functionstart > -1 && functionend > -1) {
return new Region(functionstart, functionend - functionstart + 1);
}
return null;
}
/**
* This method will determine whether current offset is contained
* in any function's body or it's outside it.
*
* @param document
* The document to be examined
* @param offset
* The offset into the document
* @return
* <code>true</code> if there is no function body around offset
* <code>false</code> otherwise
*/
public static boolean isGlobal(IDocument document, int offset) {
try {
int pos = offset;
int bracketcount = 0;
char c;
// Find left curled brace from our position
while (pos > 0) {
c = document.getChar(pos--);
if (c == CBRACE_R) {
bracketcount++; // take into account nested blocks
} else if (c == CBRACE_L) {
if (bracketcount-- == 0) {
do {
c = document.getChar(pos--);
if (c == PAREN_R)
return false;
} while (Character.isWhitespace(c));
// Container block seems to be not a function or statement body
pos++; // step back one symbol
bracketcount = 0; // let's search for upper block
}
}
}
} catch (BadLocationException x) {
// Ignore
}
return true; // return true in case of unknown result or exception
}
/**
* Searches for line feed symbols in string.
* First met '\r' or '\n' is treated as LF symbol
*
* @param s
* string to search in.
* @return number of LFs met.
*/
public static int countLFs (String s) {
int counter = 0;
char lf = 0;
char c;
for (int i= 0; i < s.length(); i++) {
c = s.charAt(i);
if (lf == 0) {
if (c == '\n' || c == '\r') {
lf = c;
counter++;
}
} else if (lf == c) {
counter++;
}
}
return counter;
}
/**
* Checks whether the string contains any C-block delimiters ( { } )
*
* @param s
* text to check
* @return true if curled brace found.
*/
public static boolean hasCBraces (String s) {
if (s.indexOf(CBRACE_L) > -1 || s.indexOf(CBRACE_R) > -1)
return true;
return false;
}
}