X-Git-Url: http://git.phpeclipse.com diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/builder/IdentifierIndexManager.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/builder/IdentifierIndexManager.java index dd2672b..86de9b5 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/builder/IdentifierIndexManager.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/builder/IdentifierIndexManager.java @@ -1,5 +1,6 @@ package net.sourceforge.phpeclipse.builder; +import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.FileNotFoundException; import java.io.FileReader; @@ -8,439 +9,1028 @@ import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Collection; +import java.util.Comparator; import java.util.HashMap; import java.util.Iterator; import java.util.List; +import java.util.Set; +import java.util.SortedMap; import java.util.StringTokenizer; +import java.util.TreeMap; import net.sourceforge.phpdt.core.compiler.ITerminalSymbols; import net.sourceforge.phpdt.core.compiler.InvalidInputException; import net.sourceforge.phpdt.internal.compiler.parser.Scanner; import net.sourceforge.phpdt.internal.compiler.parser.SyntaxError; -import net.sourceforge.phpeclipse.mover.obfuscator.PHPIdentifier; +import net.sourceforge.phpdt.internal.compiler.util.Util; +import net.sourceforge.phpeclipse.PHPeclipsePlugin; +import net.sourceforge.phpeclipse.obfuscator.PHPIdentifier; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IStatus; /** * Manages the identifer index information for a specific project - * + * */ public class IdentifierIndexManager { + public class LineCreator implements ITerminalSymbols { + private Scanner fScanner; - public class LineCreator implements ITerminalSymbols { - - private Scanner fScanner; - private int fToken; - - public LineCreator() { - fScanner = new Scanner(false, false); - } - /** - * gets the next token from input - */ - private void getNextToken() { - - try { - fToken = fScanner.getNextToken(); - if (Scanner.DEBUG) { - int currentEndPosition = fScanner.getCurrentTokenEndPosition(); - int currentStartPosition = fScanner.getCurrentTokenStartPosition(); - - System.out.print(currentStartPosition + "," + currentEndPosition + ": "); - System.out.println(fScanner.toStringAction(fToken)); - } - return; - } catch (InvalidInputException e) { - // ignore errors - } - fToken = TokenNameERROR; - } - - private void parseDeclarations(StringBuffer buf, boolean goBack) { - char[] ident; - int counter = 0; - - try { - while (fToken != TokenNameEOF && fToken != TokenNameERROR) { - if (fToken == TokenNamevar) { - getNextToken(); - if (fToken == TokenNameVariable) { - ident = fScanner.getCurrentIdentifierSource(); - buf.append("\tv"); - buf.append(ident); - - getNextToken(); - } - } else if (fToken == TokenNamefunction) { - getNextToken(); - if (fToken == TokenNameAND) { - getNextToken(); - } - if (fToken == TokenNameIdentifier) { - ident = fScanner.getCurrentIdentifierSource(); - buf.append("\tm"); - buf.append(ident); - getNextToken(); - parseDeclarations(buf, true); - } - } else if (fToken == TokenNameclass) { - getNextToken(); - if (fToken == TokenNameIdentifier) { - ident = fScanner.getCurrentIdentifierSource(); - buf.append("\tc"); - buf.append(ident); - getNextToken(); - - //skip tokens for classname, extends and others until we have the opening '{' - while (fToken != TokenNameLBRACE && fToken != TokenNameEOF && fToken != TokenNameERROR) { - getNextToken(); - } - parseDeclarations(buf, true); - } - } else if ((fToken == TokenNameLBRACE) || (fToken == TokenNameDOLLAR_LBRACE)) { - getNextToken(); - counter++; - } else if (fToken == TokenNameRBRACE) { - getNextToken(); - --counter; - if (counter == 0 && goBack) { - return; - } - } else { - getNextToken(); - } - } - } catch (SyntaxError e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - - public void parseIdentifiers(char[] charArray, StringBuffer buf) { - char[] ident; - String identifier; - int counter = 0; - - fScanner.setSource(charArray); - fScanner.setPHPMode(false); - fToken = TokenNameEOF; - getNextToken(); - - try { - while (fToken != TokenNameEOF && fToken != TokenNameERROR) { - if (fToken == TokenNamefunction) { - getNextToken(); - if (fToken == TokenNameAND) { - getNextToken(); - } - if (fToken == TokenNameIdentifier) { - ident = fScanner.getCurrentIdentifierSource(); - buf.append("\tf"); - buf.append(ident); - getNextToken(); - parseDeclarations(buf, true); - } - } else if (fToken == TokenNameclass) { - getNextToken(); - if (fToken == TokenNameIdentifier) { - ident = fScanner.getCurrentIdentifierSource(); - buf.append("\tc"); - buf.append(ident); - getNextToken(); - - //skip fTokens for classname, extends and others until we have the opening '{' - while (fToken != TokenNameLBRACE && fToken != TokenNameEOF && fToken != TokenNameERROR) { - getNextToken(); - } - - parseDeclarations(buf, true); - - } - } else { - getNextToken(); - } - } - } catch (SyntaxError e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - } - - private HashMap fFileMap; - private String fFilename; - private HashMap fIndentifierMap; - - public IdentifierIndexManager(String filename) { - fFilename = filename; - initialize(); - readFile(); - } - - /** - * Add the information for a given IFile resource - * - */ - public void addFile(IFile fileToParse) { - InputStream iStream; - LineCreator lineCreator = new LineCreator(); - try { - iStream = fileToParse.getContents(); - - StringBuffer buf = new StringBuffer(); - int c0; - try { - while ((c0 = iStream.read()) != (-1)) { - buf.append((char) c0); - } - } catch (IOException e) { - return; - } - - StringBuffer lineBuffer = new StringBuffer(); - // lineBuffer.append(fileToParse.getLocation().toString()); - lineBuffer.append(fileToParse.getFullPath().toString()); - int lineLength = lineBuffer.length(); - lineCreator.parseIdentifiers(buf.toString().toCharArray(), lineBuffer); - if (lineLength != lineBuffer.length()) { - addLine(lineBuffer.toString()); - } - } catch (CoreException e1) { - // TODO Auto-generated catch block - e1.printStackTrace(); - } - } - - /** - * Adds a line of the index file for function, class, class-method and class-variable names - * - * @param line - */ - private void addLine(String line) { - StringTokenizer tokenizer; - String phpFileName = null; - String token; - String identifier = null; - String classname = null; - PHPIdentifier phpIdentifier = null; - boolean tokenExists = false; - - tokenizer = new StringTokenizer(line, "\t"); - // first token contains the filename: - if (tokenizer.hasMoreTokens()) { - phpFileName = tokenizer.nextToken(); - //System.out.println(token); - } else { - return; - } - // all the other tokens are identifiers: - while (tokenizer.hasMoreTokens()) { - token = tokenizer.nextToken(); - //System.out.println(token); - switch (token.charAt(0)) { - case 'c' : // class name - identifier = token.substring(1); - classname = identifier; - phpIdentifier = new PHPIdentifierLocation(identifier, PHPIdentifier.CLASS, phpFileName); - break; - case 'f' : // function name - identifier = token.substring(1); - phpIdentifier = new PHPIdentifierLocation(identifier, PHPIdentifier.FUNCTION, phpFileName); - break; - case 'm' : //method inside a class - identifier = token.substring(1); - phpIdentifier = new PHPIdentifierLocation(identifier, PHPIdentifier.METHOD, phpFileName, classname); - break; - case 'v' : // variable inside a class - identifier = token.substring(1); - phpIdentifier = new PHPIdentifierLocation(identifier, PHPIdentifier.VARIABLE, phpFileName, classname); - break; - default : - identifier = null; - phpIdentifier = null; - classname = null; - } - if (identifier != null && phpIdentifier != null) { - tokenExists = true; - ArrayList list = (ArrayList) fIndentifierMap.get(identifier); - if (list == null) { - list = new ArrayList(); - list.add(phpIdentifier); - fIndentifierMap.put(identifier, list); - } else { - boolean flag = false; - for (int i = 0; i < list.size(); i++) { - if (list.get(i).equals(phpIdentifier)) { - flag = true; - break; - } - } - if (flag == false) { - list.add(phpIdentifier); - } - } - } - } - if (tokenExists) { - fFileMap.put(phpFileName, line); - } - } - - /** - * Change the information for a given IFile resource - * - */ - public void changeFile(IFile fileToParse) { - removeFile(fileToParse); - addFile(fileToParse); - } - - /** - * Get a list of all PHPIdentifierLocation object's associated with an identifier - * - * @param identifier - * @return - */ - public List getLocations(String identifier) { - return (List) fIndentifierMap.get(identifier); - } - - /** - * Initialize (i.e. clear) the current index information - * - */ - public void initialize() { - fIndentifierMap = new HashMap(); - fFileMap = new HashMap(); - } - - private void readFile() { - - FileReader fileReader; - try { - fileReader = new FileReader(fFilename); - - BufferedReader bufferedReader = new BufferedReader(fileReader); - - String line; - while (bufferedReader.ready()) { - // all entries for one file are in a line - // separated by tabs ! - line = bufferedReader.readLine(); - addLine(line); - } - - fileReader.close(); - } catch (FileNotFoundException e) { - // ignore this - // TODO DialogBox which asks the user if she/he likes to build new index? - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - - } - - /** - * Remove the information for a given IFile resource - * - */ - public void removeFile(IFile fileToParse) { - // String line = (String) fFileMap.get(fileToParse.getLocation().toString()); - String line = (String) fFileMap.get(fileToParse.getFullPath().toString()); - if (line != null) { - removeLine(line); - } - } - - /** - * Removes a line of the index file for function, class, class-method and class-variable names - * - * @param line - */ - private void removeLine(String line) { - StringTokenizer tokenizer; - String phpFileName = null; - String token; - String identifier = null; - String classname = null; - PHPIdentifier phpIdentifier = null; - boolean tokenExists = false; - - tokenizer = new StringTokenizer(line, "\t"); - // first token contains the filename: - if (tokenizer.hasMoreTokens()) { - phpFileName = tokenizer.nextToken(); - //System.out.println(token); - } else { - return; - } - // all the other tokens are identifiers: - while (tokenizer.hasMoreTokens()) { - token = tokenizer.nextToken(); - //System.out.println(token); - switch (token.charAt(0)) { - case 'c' : // class name - identifier = token.substring(1); - classname = identifier; - phpIdentifier = new PHPIdentifierLocation(identifier, PHPIdentifier.CLASS, phpFileName); - break; - case 'f' : // function name - identifier = token.substring(1); - phpIdentifier = new PHPIdentifierLocation(identifier, PHPIdentifier.FUNCTION, phpFileName); - break; - case 'm' : //method inside a class - identifier = token.substring(1); - phpIdentifier = new PHPIdentifierLocation(identifier, PHPIdentifier.METHOD, phpFileName, classname); - break; - case 'v' : // variable inside a class - identifier = token.substring(1); - phpIdentifier = new PHPIdentifierLocation(identifier, PHPIdentifier.VARIABLE, phpFileName, classname); - break; - default : - identifier = null; - phpIdentifier = null; - classname = null; - } - if (identifier != null && phpIdentifier != null) { - ArrayList list = (ArrayList) fIndentifierMap.get(identifier); - if (list == null) { - } else { - for (int i = 0; i < list.size(); i++) { - if (list.get(i).equals(phpIdentifier)) { - list.remove(i); - break; - } - } - if (list.size() == 0) { - fIndentifierMap.remove(identifier); - } - } - } - } - fFileMap.remove(phpFileName); - } - - /** - * Save the current index information in the projects index file - * - */ - public void writeFile() { - FileWriter fileWriter; - try { - fileWriter = new FileWriter(fFilename); - String line; - Collection collection = fFileMap.values(); - Iterator iterator = collection.iterator(); - while (iterator.hasNext()) { - line = (String) iterator.next(); - fileWriter.write(line + '\n'); - } - fileWriter.close(); - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } + private int fToken; + + public LineCreator() { + fScanner = new Scanner(true, false, false, false, true, null, null, + true /* taskCaseSensitive */); + } + + /** + * Add the information of the current identifier to the line + * + * @param typeOfIdentifier + * the type of the identifier ('c'lass, 'd'efine, 'f'unction, + * 'm'ethod(class), 'v'ariable(class) 'g'lobal variable) + * @param identifier + * current identifier + * @param line + * Buffer for the current index line + */ + private void addIdentifierInformation(char typeOfIdentifier, + char[] identifier, StringBuffer line) { + line.append('\t'); + line.append(typeOfIdentifier); + line.append(identifier); + } + + /** + * Add the information of the current identifier to the line + * + * @param typeOfIdentifier + * the type of the identifier ('c'lass, 'd'efine, 'f'unction, + * 'm'ethod(class), 'v'ariable(class) 'g'lobal variable) + * @param identifier + * current identifier + * @param line + * Buffer for the current index line + * @param phpdocOffset + * the offset of the PHPdoc comment if available + * @param phpdocLength + * the length of the PHPdoc comment if available + */ + private void addIdentifierInformation(char typeOfIdentifier, + char[] identifier, StringBuffer line, int phpdocOffset, + int phpdocLength) { + line.append('\t'); + line.append(typeOfIdentifier); + line.append(identifier); + line.append("\to"); // Offset + line.append(fScanner.getCurrentTokenStartPosition()); + if (phpdocOffset >= 0) { + line.append("\tp"); // phpdoc offset + line.append(phpdocOffset); + line.append("\tl"); // phpdoc length + line.append(phpdocLength); + } + } + + private void addClassVariableInformation(char typeOfIdentifier, + char[] identifier, StringBuffer line, int phpdocOffset, + int phpdocLength) { + line.append('\t'); + line.append(typeOfIdentifier); + line.append(identifier); + line.append("\to"); // Offset + // we don't store the '$' in the index for class variables: + line.append(fScanner.getCurrentTokenStartPosition() + 1); + if (phpdocOffset >= 0) { + line.append("\tp"); // phpdoc offset + line.append(phpdocOffset); + line.append("\tl"); // phpdoc length + line.append(phpdocLength); + } + } + + /** + * Get the next token from input + */ + private void getNextToken() throws InvalidInputException { + // try { + fToken = fScanner.getNextToken(); + if (Scanner.DEBUG) { + int currentEndPosition = fScanner.getCurrentTokenEndPosition(); + int currentStartPosition = fScanner + .getCurrentTokenStartPosition(); + System.out.print(currentStartPosition + "," + + currentEndPosition + ": "); + System.out.println(fScanner.toStringAction(fToken)); + } + return; + } + + private void skipComments() + { + try { + getNextToken(); + while (fToken == TokenNameCOMMENT_BLOCK || fToken == TokenNameCOMMENT_PHPDOC) { + getNextToken(); + } + } catch (InvalidInputException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } + } + + private void parseDeclarations(char[] parent, StringBuffer buf, + boolean goBack) { + char[] ident; + char[] classVariable; + int counter = 0; + boolean hasModifiers = false; + int phpdocOffset = -1; + int phpdocLength = -1; + + try { + while (fToken != TokenNameEOF && fToken != TokenNameERROR) { + phpdocOffset = -1; + hasModifiers = false; + if (fToken == TokenNameCOMMENT_PHPDOC) { + phpdocOffset = fScanner.getCurrentTokenStartPosition(); + phpdocLength = fScanner.getCurrentTokenEndPosition() + - fScanner.getCurrentTokenStartPosition() + 1; + getNextToken(); + while (fToken == TokenNamestatic + || fToken == TokenNamefinal + || fToken == TokenNamepublic + || fToken == TokenNameprotected + || fToken == TokenNameprivate + || fToken == TokenNameabstract) { + hasModifiers = true; + getNextToken(); + } + if (fToken == TokenNameEOF || fToken == TokenNameERROR) { + break; + } + } + if (fToken == TokenNamefunction) { + skipComments(); + if (fToken == TokenNameAND) { + getNextToken(); + } + if (fToken == TokenNameIdentifier) { + ident = fScanner.getCurrentIdentifierSource(); + if (parent != null + && equalCharArrays(parent, ident)) { + // constructor function + addIdentifierInformation('k', ident, buf, + phpdocOffset, phpdocLength); + } else { + if (parent != null) { + // class method function + addIdentifierInformation('m', ident, buf, + phpdocOffset, phpdocLength); + } else { + // nested function ?! + addIdentifierInformation('f', ident, buf, + phpdocOffset, phpdocLength); + } + } + skipComments(); + parseDeclarations(null, buf, true); + } + } else if (fToken == TokenNameclass + || fToken == TokenNameinterface) { + skipComments(); + if (fToken == TokenNameIdentifier) { + ident = fScanner.getCurrentIdentifierSource(); + addIdentifierInformation('c', ident, buf, + phpdocOffset, phpdocLength); + skipComments(); + if (fToken == TokenNameextends) { + skipComments(); + while (fToken == TokenNameIdentifier) { + ident = fScanner + .getCurrentIdentifierSource(); + // extends ident + addIdentifierInformation('e', ident, buf); + skipComments(); + if (fToken == TokenNameCOMMA) { + skipComments(); + } + } + } + if (fToken == TokenNameimplements) { + skipComments(); + while (fToken == TokenNameIdentifier) { + ident = fScanner + .getCurrentIdentifierSource(); + // implements ident + addIdentifierInformation('e', ident, buf); + skipComments(); + if (fToken == TokenNameCOMMA) { + skipComments(); +// getNextToken(); + } + } + } + // skip tokens for classname, extends and others + // until we have + // the opening '{' + while (fToken != TokenNameLBRACE + && fToken != TokenNameEOF + && fToken != TokenNameERROR) { + getNextToken(); + } + parseDeclarations(ident, buf, true); + } + } else if (fToken == TokenNamevar || hasModifiers + || fToken == TokenNamestatic + || fToken == TokenNamefinal + || fToken == TokenNamepublic + || fToken == TokenNameprotected + || fToken == TokenNameprivate) { + while (fToken == TokenNamevar + || fToken == TokenNamestatic + || fToken == TokenNamefinal + || fToken == TokenNamepublic + || fToken == TokenNameprotected + || fToken == TokenNameprivate) { + skipComments(); + } + while (fToken == TokenNameVariable) { + ident = fScanner.getCurrentIdentifierSource(); + classVariable = new char[ident.length - 1]; + System.arraycopy(ident, 1, classVariable, 0, + ident.length - 1); + addClassVariableInformation('v', classVariable, + buf, phpdocOffset, phpdocLength); + skipComments(); + if (fToken == TokenNameCOMMA) { + skipComments(); + } + } + } else if (!hasModifiers && fToken == TokenNameIdentifier) { + ident = fScanner.getCurrentIdentifierSource(); + getNextToken(); + if (ident.length == 6 && ident[0] == 'd' + && ident[1] == 'e' && ident[2] == 'f' + && ident[3] == 'i' && ident[4] == 'n' + && ident[5] == 'e') { + if (fToken == TokenNameLPAREN) { + getNextToken(); + if (fToken == TokenNameStringDoubleQuote) { + ident = fScanner + .getCurrentStringLiteralSource(); + addIdentifierInformation('d', ident, buf, + phpdocOffset, phpdocLength); + getNextToken(); + } else if (fToken == TokenNameStringSingleQuote) { + ident = fScanner + .getCurrentStringLiteralSource(); + addIdentifierInformation('d', ident, buf, + phpdocOffset, phpdocLength); + getNextToken(); + } + } + } + } else if (fToken == TokenNameglobal) { + // global variable + while (fToken != TokenNameEOF + && fToken != TokenNameERROR + && fToken != TokenNameSEMICOLON + && fToken != TokenNameLBRACE + && fToken != TokenNameRBRACE) { + getNextToken(); + if (fToken == TokenNameVariable) { + ident = fScanner.getCurrentIdentifierSource(); + addIdentifierInformation('g', ident, buf, + phpdocOffset, phpdocLength); + } + } + } else if (fToken == TokenNameLBRACE) { + getNextToken(); + counter++; + } else if (fToken == TokenNameRBRACE) { + getNextToken(); + --counter; + if (counter == 0 && goBack) { + return; + } + } else { + getNextToken(); + } + } + } catch (InvalidInputException e) { + // ignore errors + } catch (SyntaxError e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + } + + synchronized public void parseIdentifiers(char[] charArray, + StringBuffer buf) { + char[] ident; + String identifier; + boolean hasModifiers = false; + int phpdocOffset = -1; + int phpdocLength = -1; + fScanner.setSource(charArray); + fScanner.setPHPMode(false); + fToken = TokenNameEOF; + + try { + getNextToken(); + while (fToken != TokenNameEOF) { // && fToken != + // TokenNameERROR) { + phpdocOffset = -1; + hasModifiers = false; + switch (fToken) { + case TokenNameCOMMENT_PHPDOC: + phpdocOffset = fScanner.getCurrentTokenStartPosition(); + phpdocLength = fScanner.getCurrentTokenEndPosition() + - fScanner.getCurrentTokenStartPosition() + 1; + getNextToken(); + while (fToken == TokenNamestatic + || fToken == TokenNamefinal + || fToken == TokenNamepublic + || fToken == TokenNameprotected + || fToken == TokenNameprivate + || fToken == TokenNameabstract) { + hasModifiers = true; + getNextToken(); + } + if (fToken == TokenNameEOF || fToken == TokenNameERROR) { + break; + } + break; + + case TokenNamefunction: + skipComments(); + if (fToken == TokenNameAND) { + getNextToken(); + } + if (fToken == TokenNameIdentifier) { + ident = fScanner.getCurrentIdentifierSource(); + addIdentifierInformation('f', ident, buf, + phpdocOffset, phpdocLength); + skipComments(); + if (fToken == TokenNameLPAREN) { + skipComments(); + do { + if (fToken == TokenNameVariable) { + ident = fScanner.getCurrentIdentifierSource(); + addIdentifierInformation('v', ident, buf, + phpdocOffset, phpdocLength); + skipComments(); + if (fToken == TokenNameCOMMA) { + skipComments(); + } + } +/* skipComments(); + if (fToken == TokenNameCOMMA) { + skipComments(); + }*/ + } while (fToken != TokenNameRPAREN ); + } + parseDeclarations(null, buf, true); + } + break; + + case TokenNameclass: + case TokenNameinterface: + skipComments(); + if (fToken == TokenNameIdentifier) { + ident = fScanner.getCurrentIdentifierSource(); + addIdentifierInformation('c', ident, buf, + phpdocOffset, phpdocLength); + skipComments(); + if (fToken == TokenNameextends) { + skipComments(); + while (fToken == TokenNameIdentifier) { + ident = fScanner + .getCurrentIdentifierSource(); + // extends ident + addIdentifierInformation('e', ident, buf); + skipComments(); + if (fToken == TokenNameCOMMA) { + skipComments(); + } + } + } + if (fToken == TokenNameimplements) { + skipComments(); + while (fToken == TokenNameIdentifier) { + ident = fScanner + .getCurrentIdentifierSource(); + // implements ident + addIdentifierInformation('e', ident, buf); + skipComments(); + if (fToken == TokenNameCOMMA) { + skipComments(); + } + } + } + // skip fTokens for classname, extends and others + // until we have + // the opening '{' + while (fToken != TokenNameLBRACE + && fToken != TokenNameEOF + && fToken != TokenNameERROR) { + getNextToken(); + } + parseDeclarations(ident, buf, true); + } + break; + + case TokenNameVariable: + // global variable + ident = fScanner.getCurrentIdentifierSource(); + addIdentifierInformation('g', ident, buf, phpdocOffset, + phpdocLength); + getNextToken(); + break; + + default: + getNextToken(); + } + + } + } catch (InvalidInputException e) { + // ignore errors + } catch (SyntaxError e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } + + class StringComparator implements Comparator { + public int compare(Object o1, Object o2) { + String s1 = (String) o1; + String s2 = (String) o2; + return s1.compareTo(s2); + // return s1.toUpperCase().compareTo(s2.toUpperCase()); + } + + public boolean equals(Object o) { + String s = (String) o; + return compare(this, o) == 0; + } + } + + private HashMap fFileMap; + + private String fFilename; + + private TreeMap fIndentifierMap; + + public IdentifierIndexManager(String filename) { + fFilename = filename; + initialize(); + readFile(); + } + + /** + * Check if 2 char arrays are equal + * + * @param a + * @param b + * @return + */ + private static boolean equalCharArrays(char[] a, char[] b) { + if (a.length != b.length) { + return false; + } + for (int i = 0; i < b.length; i++) { + if (a[i] != b[i]) { + return false; + } + } + return true; + } + + public LineCreator createLineCreator() { + return new LineCreator(); + } + + /** + * Add the information for a given IFile resource + * + */ + public void addFile(IFile fileToParse) { + LineCreator lineCreator = createLineCreator(); + try { + addInputStream(new BufferedInputStream(fileToParse.getContents()), + fileToParse.getProjectRelativePath().toString(), + lineCreator, fileToParse.getCharset()); + } catch (CoreException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } + } + + /** + * @param fileToParse + * @param lineCreator + * @throws CoreException + */ + public void addInputStream(InputStream stream, String filePath, + LineCreator lineCreator, String charset) throws CoreException { + try { + StringBuffer lineBuffer = new StringBuffer(); + lineBuffer.append(filePath); + lineCreator.parseIdentifiers(Util.getInputStreamAsCharArray(stream, + -1, charset), lineBuffer); + addLine(lineBuffer.toString()); + } catch (IOException e) { + e.printStackTrace(); + } finally { + try { + if (stream != null) { + stream.close(); + } + } catch (IOException e) { + // do nothing + } + } + } + + /** + * Adds a line of the index file for function, class, class-method and + * class-variable names + * + * @param line + */ + private void addLine(String line) { + addLine(fIndentifierMap, fFileMap, line, null); + } + + public TreeMap getIdentifiers(IFile file) { + TreeMap treeMap = new TreeMap(new StringComparator()); + addIdentifiers(treeMap, file); + return treeMap; + } + + public TreeMap getIdentifiers(String startClazz) { + TreeMap treeMap = new TreeMap(new StringComparator()); + addIdentifiers(treeMap, startClazz); + return treeMap; + } + + public void addIdentifiers(TreeMap treeMap, IFile file) { + String line = (String) fFileMap.get(file.getProjectRelativePath() + .toString()); + if (line != null) { + PHPIdentifierLocation ident; + ArrayList allClassNames = new ArrayList(); + addLine(treeMap, null, line, allClassNames); + int i = 0; + while (i < allClassNames.size()) { + String clazz = (String) allClassNames.get(i++); + addClassName(treeMap, clazz, allClassNames); + } + } + } + + public void addIdentifiers(TreeMap treeMap, String startClazz) { + PHPIdentifierLocation ident; + ArrayList allClassNames = new ArrayList(); + addClassName(treeMap, startClazz, allClassNames); + int i = 0; + while (i < allClassNames.size()) { + String clazz = (String) allClassNames.get(i++); + addClassName(treeMap, clazz, allClassNames); + } + } + + /** + * @param treeMap + * @param clazz + * @param allClassNames + */ + private boolean addClassName(TreeMap treeMap, String clazz, + List allClassNames) { + String line; + PHPIdentifierLocation ident; + List list = getLocations(clazz); + if (list == null) { + return false; + } + boolean result = false; + for (int i = 0; i < list.size(); i++) { + ident = (PHPIdentifierLocation) list.get(i); + if (ident.isClass()) { + line = (String) fFileMap.get(ident.getFilename()); + addLine(treeMap, null, line, allClassNames); + result = true; + } + } + return result; + } + + /** + * Adds a line of the index file for function, class, class-method and + * class-variable names + * + * @param line + */ + public void addLine(TreeMap treeMap, HashMap fileMap, String line, + List allClassNames) { + StringTokenizer tokenizer; + String phpFileName = null; + String token; + String identifier = null; + String classname = null; + String offset = null; + PHPIdentifierLocation phpIdentifier = null; + boolean tokenExists = false; + tokenizer = new StringTokenizer(line, "\t"); + // first token contains the filename: + try { + if (tokenizer.hasMoreTokens()) { + phpFileName = tokenizer.nextToken(); + // System.out.println(token); + } else { + return; + } + // all the other tokens are identifiers: + while (tokenizer.hasMoreTokens()) { + token = tokenizer.nextToken(); + // System.out.println(token); + switch (token.charAt(0)) { + case 'c': + // class name + identifier = token.substring(1); + classname = identifier; + phpIdentifier = new PHPIdentifierLocation(identifier, + PHPIdentifier.CLASS, phpFileName); + break; + case 'd': + // define + identifier = token.substring(1); + phpIdentifier = new PHPIdentifierLocation(identifier, + PHPIdentifier.DEFINE, phpFileName); + break; + case 'e': + // extends + // not in map + identifier = null; + phpIdentifier = null; + if (allClassNames != null) { + String extName = token.substring(1); + if (!allClassNames.contains(extName)) { + allClassNames.add(extName); + } + } + break; + case 'f': + // function name + identifier = token.substring(1); + phpIdentifier = new PHPIdentifierLocation(identifier, + PHPIdentifier.FUNCTION, phpFileName); + break; + case 'g': + // global variable + identifier = token.substring(1); + phpIdentifier = new PHPIdentifierLocation(identifier, + PHPIdentifier.GLOBAL_VARIABLE, phpFileName); + break; + case 'i': + // implements + // not in map + identifier = null; + phpIdentifier = null; + if (allClassNames != null) { + String implName = token.substring(1); + if (!allClassNames.contains(implName)) { + allClassNames.add(implName); + } + } + break; + case 'k': + // constructor function name + identifier = token.substring(1); + phpIdentifier = new PHPIdentifierLocation(identifier, + PHPIdentifier.CONSTRUCTOR, phpFileName); + break; + case 'm': + // method inside a class + identifier = token.substring(1); + phpIdentifier = new PHPIdentifierLocation(identifier, + PHPIdentifier.METHOD, phpFileName, classname); + break; + case 'v': + // variable inside a class + identifier = token.substring(1); + phpIdentifier = new PHPIdentifierLocation(identifier, + PHPIdentifier.VARIABLE, phpFileName, classname); + break; + case 'o': + // offset information + identifier = null; + if (phpIdentifier != null) { + offset = token.substring(1); + phpIdentifier.setOffset(Integer.parseInt(offset)); + } + break; + case 'p': + // PHPdoc offset information + identifier = null; + if (phpIdentifier != null) { + offset = token.substring(1); + phpIdentifier.setPHPDocOffset(Integer.parseInt(offset)); + } + break; + case 'l': + // PHPdoc length information + identifier = null; + if (phpIdentifier != null) { + offset = token.substring(1); + phpIdentifier.setPHPDocLength(Integer.parseInt(offset)); + } + break; + default: + PHPeclipsePlugin.log(IStatus.ERROR, + "Unknown token character in IdentifierIndexManager: " + + token.charAt(0)); + identifier = null; + phpIdentifier = null; + classname = null; + } + if (identifier != null && phpIdentifier != null) { + tokenExists = true; + ArrayList list = (ArrayList) treeMap.get(identifier); + if (list == null) { + list = new ArrayList(); + list.add(phpIdentifier); + treeMap.put(identifier, list); + } else { + boolean flag = false; + for (int i = 0; i < list.size(); i++) { + if (list.get(i).equals(phpIdentifier)) { + flag = true; + break; + } + } + if (flag == false) { + list.add(phpIdentifier); + } + } + } + } + if (fileMap != null) { + fileMap.put(phpFileName, line); + } + } catch (Throwable e) { + // write to workspace/.metadata/.log file + PHPeclipsePlugin.log(e); + } + // if (tokenExists) { + + // } + } + + /** + * Change the information for a given IFile resource + * + */ + public void changeFile(IFile fileToParse) { + removeFile(fileToParse); + addFile(fileToParse); + } + + /** + * Get a list of all PHPIdentifierLocation object's associated with an + * identifier + * + * @param identifier + * @return + */ + public List getLocations(String identifier) { + List list = (List) fIndentifierMap.get(identifier); + if (list != null) { + return list; + } + return new ArrayList(); + } + + /** + * Initialize (i.e. clear) the current index information + * + */ + public void initialize() { + fIndentifierMap = new TreeMap(new StringComparator()); + fFileMap = new HashMap(); + } + + private void readFile() { + FileReader fileReader; + try { + fileReader = new FileReader(fFilename); + BufferedReader bufferedReader = new BufferedReader(fileReader); + String line; + while (bufferedReader.ready()) { + // all entries for one file are in a line + // separated by tabs ! + line = bufferedReader.readLine(); + addLine(line); + } + fileReader.close(); + } catch (FileNotFoundException e) { + // ignore this + // TODO DialogBox which asks the user if she/he likes to build new + // index? + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + /** + * Remove the information for a given IFile resource + * + */ + public void removeFile(IFile fileToParse) { + // String line = (String) + // fFileMap.get(fileToParse.getLocation().toString()); + String line = (String) fFileMap.get(fileToParse + .getProjectRelativePath().toString()); + if (line != null) { + removeLine(line); + } + } + + /** + * Removes a line of the index file for function, class, class-method and + * class-variable names + * + * @param line + */ + private void removeLine(String line) { + StringTokenizer tokenizer; + String phpFileName = null; + String token; + String identifier = null; + String classname = null; + PHPIdentifier phpIdentifier = null; + boolean tokenExists = false; + tokenizer = new StringTokenizer(line, "\t"); + // first token contains the filename: + if (tokenizer.hasMoreTokens()) { + phpFileName = tokenizer.nextToken(); + // System.out.println(token); + } else { + return; + } + int offset = -1; + // all the other tokens are identifiers: + while (tokenizer.hasMoreTokens()) { + token = tokenizer.nextToken(); + // System.out.println(token); + switch (token.charAt(0)) { + case 'c': + // class name + identifier = token.substring(1); + classname = identifier; + phpIdentifier = new PHPIdentifierLocation(identifier, + PHPIdentifier.CLASS, phpFileName); + break; + case 'd': + // define + identifier = token.substring(1); + phpIdentifier = new PHPIdentifierLocation(identifier, + PHPIdentifier.DEFINE, phpFileName); + break; + case 'e': + // extends + identifier = null; + phpIdentifier = null; + break; + case 'f': + // function name + identifier = token.substring(1); + phpIdentifier = new PHPIdentifierLocation(identifier, + PHPIdentifier.FUNCTION, phpFileName); + break; + case 'g': + // global variable + identifier = token.substring(1); + phpIdentifier = new PHPIdentifierLocation(identifier, + PHPIdentifier.GLOBAL_VARIABLE, phpFileName); + break; + case 'i': + // implements + identifier = null; + phpIdentifier = null; + break; + case 'k': + // constructor function name + identifier = token.substring(1); + phpIdentifier = new PHPIdentifierLocation(identifier, + PHPIdentifier.CONSTRUCTOR, phpFileName); + break; + case 'm': + // method inside a class + identifier = token.substring(1); + phpIdentifier = new PHPIdentifierLocation(identifier, + PHPIdentifier.METHOD, phpFileName, classname); + break; + case 'o': + // offset information + identifier = null; + break; + case 'p': + // PHPdoc offset information + identifier = null; + break; + case 'l': + // PHPdoc length information + identifier = null; + break; + case 'v': + // variable inside a class + identifier = token.substring(1); + phpIdentifier = new PHPIdentifierLocation(identifier, + PHPIdentifier.VARIABLE, phpFileName, classname); + break; + default: + PHPeclipsePlugin.log(IStatus.ERROR, + "Unknown token character in IdentifierIndexManager: " + + token.charAt(0)); + identifier = null; + phpIdentifier = null; + classname = null; + } + if (identifier != null && phpIdentifier != null) { + ArrayList list = (ArrayList) fIndentifierMap.get(identifier); + if (list == null) { + } else { + for (int i = 0; i < list.size(); i++) { + if (list.get(i).equals(phpIdentifier)) { + list.remove(i); + break; + } + } + if (list.size() == 0) { + fIndentifierMap.remove(identifier); + } + } + } + } + fFileMap.remove(phpFileName); + } + + /** + * Save the current index information in the projects index file + * + */ + public void writeFile() { + FileWriter fileWriter; + try { + fileWriter = new FileWriter(fFilename); + String line; + Collection collection = fFileMap.values(); + Iterator iterator = collection.iterator(); + while (iterator.hasNext()) { + line = (String) iterator.next(); + fileWriter.write(line + '\n'); + } + fileWriter.close(); + } catch (FileNotFoundException e) { + // ignore exception; project is deleted by user + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + /** + * @param fromKey + * @param toKey + * @return + */ + public SortedMap getIdentifierMap() { + return fIndentifierMap; + } + + synchronized public List getFileList(String filePattern) { + Set set = fFileMap.keySet(); + if (set.isEmpty()) { + return null; + } + Iterator iter = set.iterator(); + ArrayList list = new ArrayList(); + String fileName; + int index; + while (iter.hasNext()) { + fileName = (String) iter.next(); + if ((index = fileName.indexOf(filePattern)) != -1 + && fileName.length() == (index + filePattern.length())) { + list.add(fileName); + } + } + return list; + } } \ No newline at end of file