1 package net.sourceforge.phpeclipse.builder;
 
   3 import java.io.BufferedReader;
 
   4 import java.io.FileNotFoundException;
 
   5 import java.io.FileReader;
 
   6 import java.io.FileWriter;
 
   7 import java.io.IOException;
 
   8 import java.io.InputStream;
 
   9 import java.util.ArrayList;
 
  10 import java.util.Collection;
 
  11 import java.util.HashMap;
 
  12 import java.util.Iterator;
 
  13 import java.util.List;
 
  14 import java.util.StringTokenizer;
 
  16 import net.sourceforge.phpdt.core.compiler.ITerminalSymbols;
 
  17 import net.sourceforge.phpdt.core.compiler.InvalidInputException;
 
  18 import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
 
  19 import net.sourceforge.phpdt.internal.compiler.parser.SyntaxError;
 
  20 import net.sourceforge.phpeclipse.mover.obfuscator.PHPIdentifier;
 
  22 import org.eclipse.core.resources.IFile;
 
  23 import org.eclipse.core.runtime.CoreException;
 
  26  * Manages the identifer index information for a specific project
 
  29 public class IdentifierIndexManager {
 
  31   public class LineCreator implements ITerminalSymbols {
 
  33     private Scanner fScanner;
 
  36     public LineCreator() {
 
  37       fScanner = new Scanner(true, false);
 
  41      * Add the information of the current identifier to the line
 
  43      * @param typeOfIdentifier the type of the identifier ('c'lass, 'd'efine, 'f'unction, 'm'ethod, 'v'ariable)
 
  44      * @param identifier current identifier
 
  45      * @param line Buffer for the current index line
 
  46      * @param phpdocOffset the offset of the PHPdoc comment if available
 
  47      * @param phpdocLength the length of the PHPdoc comment if available
 
  49     private void addIdentifierInformation(
 
  50       char typeOfIdentifier,
 
  57       line.append(typeOfIdentifier);
 
  58       line.append(identifier);
 
  59       line.append("\to"); // Offset 
 
  60       line.append(fScanner.getCurrentTokenStartPosition());
 
  61       if (phpdocOffset >= 0) {
 
  62         line.append("\tp"); // phpdoc offset
 
  63         line.append(phpdocOffset);
 
  64         line.append("\tl"); // phpdoc length
 
  65         line.append(phpdocLength);
 
  70      * Get the next token from input
 
  72     private void getNextToken() {
 
  74         fToken = fScanner.getNextToken();
 
  76           int currentEndPosition = fScanner.getCurrentTokenEndPosition();
 
  77           int currentStartPosition = fScanner.getCurrentTokenStartPosition();
 
  79           System.out.print(currentStartPosition + "," + currentEndPosition + ": ");
 
  80           System.out.println(fScanner.toStringAction(fToken));
 
  83       } catch (InvalidInputException e) {
 
  86       fToken = TokenNameERROR;
 
  89     private void parseDeclarations(StringBuffer buf, boolean goBack) {
 
  93       int phpdocOffset = -1;
 
  94       int phpdocLength = -1;
 
  97         while (fToken != TokenNameEOF && fToken != TokenNameERROR) {
 
  99           if (fToken == TokenNameCOMMENT_PHPDOC) {
 
 100             phpdocOffset = fScanner.getCurrentTokenStartPosition();
 
 101             phpdocLength = fScanner.getCurrentTokenEndPosition() - fScanner.getCurrentTokenStartPosition() + 1;
 
 103             if (fToken == TokenNameEOF || fToken == TokenNameERROR) {
 
 107           if (fToken == TokenNamevar) {
 
 109             if (fToken == TokenNameVariable) {
 
 110               ident = fScanner.getCurrentIdentifierSource();
 
 111                                                         classVariable = new char[ident.length-1];
 
 112                                                         System.arraycopy(ident, 1, classVariable, 0, ident.length-1);
 
 113               addIdentifierInformation('v', classVariable, buf, phpdocOffset, phpdocLength);
 
 116           } else if (fToken == TokenNamefunction) {
 
 118             if (fToken == TokenNameAND) {
 
 121             if (fToken == TokenNameIdentifier) {
 
 122               ident = fScanner.getCurrentIdentifierSource();
 
 123               addIdentifierInformation('m', ident, buf, phpdocOffset, phpdocLength);
 
 125               parseDeclarations(buf, true);
 
 127           } else if (fToken == TokenNameclass) {
 
 129             if (fToken == TokenNameIdentifier) {
 
 130               ident = fScanner.getCurrentIdentifierSource();
 
 131               addIdentifierInformation('c', ident, buf, phpdocOffset, phpdocLength);
 
 134               //skip tokens for classname, extends and others until we have the opening '{'
 
 135               while (fToken != TokenNameLBRACE && fToken != TokenNameEOF && fToken != TokenNameERROR) {
 
 138               parseDeclarations(buf, true);
 
 140           } else if (fToken == TokenNamedefine) {
 
 142             if (fToken == TokenNameLPAREN) {
 
 144               if (fToken == TokenNameStringLiteral) {
 
 145                 ident = fScanner.getCurrentStringLiteralSource();
 
 146                 addIdentifierInformation('d', ident, buf, phpdocOffset, phpdocLength);
 
 150           } else if ((fToken == TokenNameLBRACE) || (fToken == TokenNameDOLLAR_LBRACE)) {
 
 153           } else if (fToken == TokenNameRBRACE) {
 
 156             if (counter == 0 && goBack) {
 
 163       } catch (SyntaxError e) {
 
 164         // TODO Auto-generated catch block
 
 169     public void parseIdentifiers(char[] charArray, StringBuffer buf) {
 
 173       int phpdocOffset = -1;
 
 174       int phpdocLength = -1;
 
 176       fScanner.setSource(charArray);
 
 177       fScanner.setPHPMode(false);
 
 178       fToken = TokenNameEOF;
 
 182         while (fToken != TokenNameEOF && fToken != TokenNameERROR) {
 
 184           if (fToken == TokenNameCOMMENT_PHPDOC) {
 
 185             phpdocOffset = fScanner.getCurrentTokenStartPosition();
 
 186             phpdocLength = fScanner.getCurrentTokenEndPosition() - fScanner.getCurrentTokenStartPosition() + 1;
 
 188             if (fToken == TokenNameEOF || fToken == TokenNameERROR) {
 
 192           if (fToken == TokenNamefunction) {
 
 194             if (fToken == TokenNameAND) {
 
 197             if (fToken == TokenNameIdentifier) {
 
 198               ident = fScanner.getCurrentIdentifierSource();
 
 199               addIdentifierInformation('f', ident, buf, phpdocOffset, phpdocLength);
 
 201               parseDeclarations(buf, true);
 
 203           } else if (fToken == TokenNameclass) {
 
 205             if (fToken == TokenNameIdentifier) {
 
 206               ident = fScanner.getCurrentIdentifierSource();
 
 207               addIdentifierInformation('c', ident, buf, phpdocOffset, phpdocLength);
 
 210               //skip fTokens for classname, extends and others until we have the opening '{'
 
 211               while (fToken != TokenNameLBRACE && fToken != TokenNameEOF && fToken != TokenNameERROR) {
 
 215               parseDeclarations(buf, true);
 
 218           } else if (fToken == TokenNamedefine) {
 
 220             if (fToken == TokenNameLPAREN) {
 
 222               if (fToken == TokenNameStringLiteral) {
 
 223                 ident = fScanner.getCurrentStringLiteralSource();
 
 224                 addIdentifierInformation('d', ident, buf, phpdocOffset, phpdocLength);
 
 232       } catch (SyntaxError e) {
 
 233         // TODO Auto-generated catch block
 
 239   private HashMap fFileMap;
 
 240   private String fFilename;
 
 241   private HashMap fIndentifierMap;
 
 243   public IdentifierIndexManager(String filename) {
 
 244     fFilename = filename;
 
 250    * Add the information for a given IFile resource
 
 253   public void addFile(IFile fileToParse) {
 
 255     LineCreator lineCreator = new LineCreator();
 
 257       iStream = fileToParse.getContents();
 
 259       StringBuffer buf = new StringBuffer();
 
 262         while ((c0 = iStream.read()) != (-1)) {
 
 263           buf.append((char) c0);
 
 265       } catch (IOException e) {
 
 269       StringBuffer lineBuffer = new StringBuffer();
 
 270       //      lineBuffer.append(fileToParse.getLocation().toString());
 
 271       lineBuffer.append(fileToParse.getFullPath().toString());
 
 272       int lineLength = lineBuffer.length();
 
 273       lineCreator.parseIdentifiers(buf.toString().toCharArray(), lineBuffer);
 
 274       if (lineLength != lineBuffer.length()) {
 
 275         addLine(lineBuffer.toString());
 
 277     } catch (CoreException e1) {
 
 278       // TODO Auto-generated catch block
 
 279       e1.printStackTrace();
 
 284    * Adds a line of the index file for function, class, class-method and class-variable names
 
 288   private void addLine(String line) {
 
 289     StringTokenizer tokenizer;
 
 290     String phpFileName = null;
 
 292     String identifier = null;
 
 293     String classname = null;
 
 294     String offset = null;
 
 295     PHPIdentifierLocation phpIdentifier = null;
 
 296     boolean tokenExists = false;
 
 298     tokenizer = new StringTokenizer(line, "\t");
 
 299     // first token contains the filename:
 
 300     if (tokenizer.hasMoreTokens()) {
 
 301       phpFileName = tokenizer.nextToken();
 
 302       //System.out.println(token);
 
 306     // all the other tokens are identifiers:
 
 307     while (tokenizer.hasMoreTokens()) {
 
 308       token = tokenizer.nextToken();
 
 309       //System.out.println(token);
 
 310       switch (token.charAt(0)) {
 
 311         case 'c' : // class name
 
 312           identifier = token.substring(1);
 
 313           classname = identifier;
 
 314           phpIdentifier = new PHPIdentifierLocation(identifier, PHPIdentifier.CLASS, phpFileName);
 
 317           identifier = token.substring(1);
 
 318           phpIdentifier = new PHPIdentifierLocation(identifier, PHPIdentifier.DEFINE, phpFileName);
 
 320         case 'f' : // function name
 
 321           identifier = token.substring(1);
 
 322           phpIdentifier = new PHPIdentifierLocation(identifier, PHPIdentifier.FUNCTION, phpFileName);
 
 324         case 'm' : //method inside a class
 
 325           identifier = token.substring(1);
 
 326           phpIdentifier = new PHPIdentifierLocation(identifier, PHPIdentifier.METHOD, phpFileName, classname);
 
 328         case 'v' : // variable inside a class
 
 329           identifier = token.substring(1);
 
 330           phpIdentifier = new PHPIdentifierLocation(identifier, PHPIdentifier.VARIABLE, phpFileName, classname);
 
 332         case 'o' : // offset information
 
 334           if (phpIdentifier != null) {
 
 335             offset = token.substring(1);
 
 336             phpIdentifier.setOffset(Integer.parseInt(offset));
 
 339         case 'p' : // PHPdoc offset information
 
 341           if (phpIdentifier != null) {
 
 342             offset = token.substring(1);
 
 343             phpIdentifier.setPHPDocOffset(Integer.parseInt(offset));
 
 346         case 'l' : // PHPdoc length information
 
 348           if (phpIdentifier != null) {
 
 349             offset = token.substring(1);
 
 350             phpIdentifier.setPHPDocLength(Integer.parseInt(offset));
 
 355           phpIdentifier = null;
 
 358       if (identifier != null && phpIdentifier != null) {
 
 360         ArrayList list = (ArrayList) fIndentifierMap.get(identifier);
 
 362           list = new ArrayList();
 
 363           list.add(phpIdentifier);
 
 364           fIndentifierMap.put(identifier, list);
 
 366           boolean flag = false;
 
 367           for (int i = 0; i < list.size(); i++) {
 
 368             if (list.get(i).equals(phpIdentifier)) {
 
 374             list.add(phpIdentifier);
 
 380       fFileMap.put(phpFileName, line);
 
 385    * Change the information for a given IFile resource
 
 388   public void changeFile(IFile fileToParse) {
 
 389     removeFile(fileToParse);
 
 390     addFile(fileToParse);
 
 394    * Get a list of all PHPIdentifierLocation object's associated with an identifier
 
 399   public List getLocations(String identifier) {
 
 400     return (List) fIndentifierMap.get(identifier);
 
 404    * Initialize (i.e. clear) the current index information
 
 407   public void initialize() {
 
 408     fIndentifierMap = new HashMap();
 
 409     fFileMap = new HashMap();
 
 412   private void readFile() {
 
 414     FileReader fileReader;
 
 416       fileReader = new FileReader(fFilename);
 
 418       BufferedReader bufferedReader = new BufferedReader(fileReader);
 
 421       while (bufferedReader.ready()) {
 
 422         // all entries for one file are in a line
 
 423         // separated by tabs !
 
 424         line = bufferedReader.readLine();
 
 429     } catch (FileNotFoundException e) {
 
 431       // TODO DialogBox which asks the user if she/he likes to build new index?
 
 432     } catch (IOException e) {
 
 433       // TODO Auto-generated catch block
 
 440    * Remove the information for a given IFile resource
 
 443   public void removeFile(IFile fileToParse) {
 
 444     //    String line = (String) fFileMap.get(fileToParse.getLocation().toString());
 
 445     String line = (String) fFileMap.get(fileToParse.getFullPath().toString());
 
 452    * Removes a line of the index file for function, class, class-method and class-variable names
 
 456   private void removeLine(String line) {
 
 457     StringTokenizer tokenizer;
 
 458     String phpFileName = null;
 
 460     String identifier = null;
 
 461     String classname = null;
 
 462     PHPIdentifier phpIdentifier = null;
 
 463     boolean tokenExists = false;
 
 465     tokenizer = new StringTokenizer(line, "\t");
 
 466     // first token contains the filename:
 
 467     if (tokenizer.hasMoreTokens()) {
 
 468       phpFileName = tokenizer.nextToken();
 
 469       //System.out.println(token);
 
 473     // all the other tokens are identifiers:
 
 474     while (tokenizer.hasMoreTokens()) {
 
 475       token = tokenizer.nextToken();
 
 476       //System.out.println(token);
 
 477       switch (token.charAt(0)) {
 
 478         case 'c' : // class name
 
 479           identifier = token.substring(1);
 
 480           classname = identifier;
 
 481           phpIdentifier = new PHPIdentifierLocation(identifier, PHPIdentifier.CLASS, phpFileName);
 
 484           identifier = token.substring(1);
 
 485           phpIdentifier = new PHPIdentifierLocation(identifier, PHPIdentifier.DEFINE, phpFileName);
 
 487         case 'f' : // function name
 
 488           identifier = token.substring(1);
 
 489           phpIdentifier = new PHPIdentifierLocation(identifier, PHPIdentifier.FUNCTION, phpFileName);
 
 491         case 'm' : //method inside a class
 
 492           identifier = token.substring(1);
 
 493           phpIdentifier = new PHPIdentifierLocation(identifier, PHPIdentifier.METHOD, phpFileName, classname);
 
 495         case 'v' : // variable inside a class
 
 496           identifier = token.substring(1);
 
 497           phpIdentifier = new PHPIdentifierLocation(identifier, PHPIdentifier.VARIABLE, phpFileName, classname);
 
 501           phpIdentifier = null;
 
 504       if (identifier != null && phpIdentifier != null) {
 
 505         ArrayList list = (ArrayList) fIndentifierMap.get(identifier);
 
 508           for (int i = 0; i < list.size(); i++) {
 
 509             if (list.get(i).equals(phpIdentifier)) {
 
 514           if (list.size() == 0) {
 
 515             fIndentifierMap.remove(identifier);
 
 520     fFileMap.remove(phpFileName);
 
 524    * Save the current index information in the projects index file
 
 527   public void writeFile() {
 
 528     FileWriter fileWriter;
 
 530       fileWriter = new FileWriter(fFilename);
 
 532       Collection collection = fFileMap.values();
 
 533       Iterator iterator = collection.iterator();
 
 534       while (iterator.hasNext()) {
 
 535         line = (String) iterator.next();
 
 536         fileWriter.write(line + '\n');
 
 539     } catch (IOException e) {
 
 540       // TODO Auto-generated catch block