Fixed bugs item #1240435
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpeclipse / builder / IdentifierIndexManager.java
index 262d596..277a54f 100644 (file)
@@ -41,7 +41,25 @@ public class IdentifierIndexManager {
     private int fToken;
 
     public LineCreator() {
-      fScanner = new Scanner(true, false, false, false, true, null, null);
+      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);
+      //      line.append("\to"); // Offset
+      //      line.append(fScanner.getCurrentTokenStartPosition());
     }
 
     /**
@@ -72,7 +90,7 @@ public class IdentifierIndexManager {
         line.append(phpdocLength);
       }
     }
-    
+
     private void addClassVariableInformation(char typeOfIdentifier, char[] identifier, StringBuffer line, int phpdocOffset,
         int phpdocLength) {
       line.append('\t');
@@ -80,7 +98,7 @@ public class IdentifierIndexManager {
       line.append(identifier);
       line.append("\to"); // Offset
       // we don't store the '$' in the index for class variables:
-      line.append(fScanner.getCurrentTokenStartPosition()+1);
+      line.append(fScanner.getCurrentTokenStartPosition() + 1);
       if (phpdocOffset >= 0) {
         line.append("\tp"); // phpdoc offset
         line.append(phpdocOffset);
@@ -92,54 +110,48 @@ public class IdentifierIndexManager {
     /**
      * Get 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
-        //        e.printStackTrace();
+    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));
       }
-      fToken = TokenNameERROR;
+      return;
+      //      } catch (InvalidInputException e) {
+      //        // ignore errors
+      //        // e.printStackTrace();
+      //      }
+      //      fToken = TokenNameERROR;
     }
 
     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 == TokenNamevar || fToken == TokenNamestatic || fToken == TokenNamefinal || fToken == TokenNamepublic
-              || fToken == TokenNameprotected || fToken == TokenNameprivate) {
-            while (fToken == TokenNamevar || fToken == TokenNamestatic || fToken == TokenNamefinal || fToken == TokenNamepublic
-                || fToken == TokenNameprotected || fToken == TokenNameprivate) {
-              getNextToken();
-            }  
-            if (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);
-              getNextToken();
-            }
-          } else if (fToken == TokenNamefunction) {
+          if (fToken == TokenNamefunction) {
             getNextToken();
             if (fToken == TokenNameAND) {
               getNextToken();
@@ -167,6 +179,30 @@ public class IdentifierIndexManager {
               ident = fScanner.getCurrentIdentifierSource();
               addIdentifierInformation('c', ident, buf, phpdocOffset, phpdocLength);
               getNextToken();
+              if (fToken == TokenNameextends) {
+                getNextToken();
+                while (fToken == TokenNameIdentifier) {
+                  ident = fScanner.getCurrentIdentifierSource();
+                  // extends ident
+                  addIdentifierInformation('e', ident, buf);
+                  getNextToken();
+                  if (fToken == TokenNameCOMMA) {
+                    getNextToken();
+                  }
+                }
+              }
+              if (fToken == TokenNameimplements) {
+                getNextToken();
+                while (fToken == TokenNameIdentifier) {
+                  ident = fScanner.getCurrentIdentifierSource();
+                  // implements ident
+                  addIdentifierInformation('e', ident, buf);
+                  getNextToken();
+                  if (fToken == TokenNameCOMMA) {
+                    getNextToken();
+                  }
+                }
+              }
               //skip tokens for classname, extends and others until we have
               // the opening '{'
               while (fToken != TokenNameLBRACE && fToken != TokenNameEOF && fToken != TokenNameERROR) {
@@ -174,7 +210,23 @@ public class IdentifierIndexManager {
               }
               parseDeclarations(ident, buf, true);
             }
-          } else if (fToken == TokenNameIdentifier) {
+          } 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) {
+              getNextToken();
+            }
+            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);
+              getNextToken();
+              if (fToken == TokenNameCOMMA) {
+                getNextToken();
+              }
+            }
+          } 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'
@@ -185,6 +237,10 @@ public class IdentifierIndexManager {
                   ident = fScanner.getCurrentStringLiteralSource();
                   addIdentifierInformation('d', ident, buf, phpdocOffset, phpdocLength);
                   getNextToken();
+                } else if (fToken == TokenNameStringSingleQuote) {
+                  ident = fScanner.getCurrentStringLiteralSource();
+                  addIdentifierInformation('d', ident, buf, phpdocOffset, phpdocLength);
+                  getNextToken();
                 }
               }
             }
@@ -211,6 +267,8 @@ public class IdentifierIndexManager {
             getNextToken();
           }
         }
+      } catch (InvalidInputException e) {
+        // ignore errors
       } catch (SyntaxError e) {
         // TODO Auto-generated catch block
         e.printStackTrace();
@@ -221,19 +279,26 @@ public class IdentifierIndexManager {
       char[] ident;
       String identifier;
       int counter = 0;
+      boolean hasModifiers = false;
       int phpdocOffset = -1;
       int phpdocLength = -1;
       fScanner.setSource(charArray);
       fScanner.setPHPMode(false);
       fToken = TokenNameEOF;
-      getNextToken();
       try {
+        getNextToken();
         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;
             }
@@ -255,6 +320,30 @@ public class IdentifierIndexManager {
               ident = fScanner.getCurrentIdentifierSource();
               addIdentifierInformation('c', ident, buf, phpdocOffset, phpdocLength);
               getNextToken();
+              if (fToken == TokenNameextends) {
+                getNextToken();
+                while (fToken == TokenNameIdentifier) {
+                  ident = fScanner.getCurrentIdentifierSource();
+                  // extends ident
+                  addIdentifierInformation('e', ident, buf);
+                  getNextToken();
+                  if (fToken == TokenNameCOMMA) {
+                    getNextToken();
+                  }
+                }
+              }
+              if (fToken == TokenNameimplements) {
+                getNextToken();
+                while (fToken == TokenNameIdentifier) {
+                  ident = fScanner.getCurrentIdentifierSource();
+                  // implements ident
+                  addIdentifierInformation('e', ident, buf);
+                  getNextToken();
+                  if (fToken == TokenNameCOMMA) {
+                    getNextToken();
+                  }
+                }
+              }
               //skip fTokens for classname, extends and others until we have
               // the opening '{'
               while (fToken != TokenNameLBRACE && fToken != TokenNameEOF && fToken != TokenNameERROR) {
@@ -267,7 +356,7 @@ public class IdentifierIndexManager {
             ident = fScanner.getCurrentIdentifierSource();
             addIdentifierInformation('g', ident, buf, phpdocOffset, phpdocLength);
             getNextToken();
-          } else if (fToken == TokenNameIdentifier) {
+          } 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'
@@ -278,6 +367,10 @@ public class IdentifierIndexManager {
                   ident = fScanner.getCurrentStringLiteralSource();
                   addIdentifierInformation('d', ident, buf, phpdocOffset, phpdocLength);
                   getNextToken();
+                } else if (fToken == TokenNameStringSingleQuote) {
+                  ident = fScanner.getCurrentStringLiteralSource();
+                  addIdentifierInformation('d', ident, buf, phpdocOffset, phpdocLength);
+                  getNextToken();
                 }
               }
             }
@@ -285,6 +378,8 @@ public class IdentifierIndexManager {
             getNextToken();
           }
         }
+      } catch (InvalidInputException e) {
+        // ignore errors
       } catch (SyntaxError e) {
         // TODO Auto-generated catch block
         e.printStackTrace();
@@ -390,6 +485,76 @@ public class IdentifierIndexManager {
    * @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;
@@ -400,106 +565,138 @@ public class IdentifierIndexManager {
     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 'd':
-        // define
-        identifier = token.substring(1);
-        phpIdentifier = new PHPIdentifierLocation(identifier, PHPIdentifier.DEFINE, phpFileName);
-        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 '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;
+    try {
+      if (tokenizer.hasMoreTokens()) {
+        phpFileName = tokenizer.nextToken();
+        //System.out.println(token);
+      } else {
+        return;
       }
-      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;
+      // 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 <class name>
+          // not in map
+          identifier = null;
+          phpIdentifier = null;
+          if (allClassNames != null) {
+            String extName = token.substring(1);
+            if (!allClassNames.contains(extName)) {
+              allClassNames.add(extName);
             }
           }
-          if (flag == false) {
+          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 <class name>
+          // 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) {
-    fFileMap.put(phpFileName, line);
+
     //    }
   }
 
@@ -604,6 +801,11 @@ public class IdentifierIndexManager {
         identifier = token.substring(1);
         phpIdentifier = new PHPIdentifierLocation(identifier, PHPIdentifier.DEFINE, phpFileName);
         break;
+      case 'e':
+        // extends <class name>
+        identifier = null;
+        phpIdentifier = null;
+        break;
       case 'f':
         // function name
         identifier = token.substring(1);
@@ -614,6 +816,11 @@ public class IdentifierIndexManager {
         identifier = token.substring(1);
         phpIdentifier = new PHPIdentifierLocation(identifier, PHPIdentifier.GLOBAL_VARIABLE, phpFileName);
         break;
+      case 'i':
+        // implements <class name>
+        identifier = null;
+        phpIdentifier = null;
+        break;
       case 'k':
         // constructor function name
         identifier = token.substring(1);