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 (FileNotFoundException e) {
540 // ignore exception; project is deleted by user
541 } catch (IOException e) {
542 // TODO Auto-generated catch block