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) {
92 int phpdocOffset = -1;
93 int phpdocLength = -1;
96 while (fToken != TokenNameEOF && fToken != TokenNameERROR) {
98 if (fToken == TokenNameCOMMENT_PHPDOC) {
99 phpdocOffset = fScanner.getCurrentTokenStartPosition();
100 phpdocLength = fScanner.getCurrentTokenEndPosition() - fScanner.getCurrentTokenStartPosition() + 1;
102 if (fToken == TokenNameEOF || fToken == TokenNameERROR) {
106 if (fToken == TokenNamevar) {
108 if (fToken == TokenNameVariable) {
109 ident = fScanner.getCurrentIdentifierSource();
110 addIdentifierInformation('v', ident, buf, phpdocOffset, phpdocLength);
113 } else if (fToken == TokenNamefunction) {
115 if (fToken == TokenNameAND) {
118 if (fToken == TokenNameIdentifier) {
119 ident = fScanner.getCurrentIdentifierSource();
120 addIdentifierInformation('m', ident, buf, phpdocOffset, phpdocLength);
122 parseDeclarations(buf, true);
124 } else if (fToken == TokenNameclass) {
126 if (fToken == TokenNameIdentifier) {
127 ident = fScanner.getCurrentIdentifierSource();
128 addIdentifierInformation('c', ident, buf, phpdocOffset, phpdocLength);
131 //skip tokens for classname, extends and others until we have the opening '{'
132 while (fToken != TokenNameLBRACE && fToken != TokenNameEOF && fToken != TokenNameERROR) {
135 parseDeclarations(buf, true);
137 } else if (fToken == TokenNamedefine) {
139 if (fToken == TokenNameLPAREN) {
141 if (fToken == TokenNameStringLiteral) {
142 ident = fScanner.getCurrentStringLiteralSource();
143 addIdentifierInformation('d', ident, buf, phpdocOffset, phpdocLength);
147 } else if ((fToken == TokenNameLBRACE) || (fToken == TokenNameDOLLAR_LBRACE)) {
150 } else if (fToken == TokenNameRBRACE) {
153 if (counter == 0 && goBack) {
160 } catch (SyntaxError e) {
161 // TODO Auto-generated catch block
166 public void parseIdentifiers(char[] charArray, StringBuffer buf) {
170 int phpdocOffset = -1;
171 int phpdocLength = -1;
173 fScanner.setSource(charArray);
174 fScanner.setPHPMode(false);
175 fToken = TokenNameEOF;
179 while (fToken != TokenNameEOF && fToken != TokenNameERROR) {
181 if (fToken == TokenNameCOMMENT_PHPDOC) {
182 phpdocOffset = fScanner.getCurrentTokenStartPosition();
183 phpdocLength = fScanner.getCurrentTokenEndPosition() - fScanner.getCurrentTokenStartPosition() + 1;
185 if (fToken == TokenNameEOF || fToken == TokenNameERROR) {
189 if (fToken == TokenNamefunction) {
191 if (fToken == TokenNameAND) {
194 if (fToken == TokenNameIdentifier) {
195 ident = fScanner.getCurrentIdentifierSource();
196 addIdentifierInformation('f', ident, buf, phpdocOffset, phpdocLength);
198 parseDeclarations(buf, true);
200 } else if (fToken == TokenNameclass) {
202 if (fToken == TokenNameIdentifier) {
203 ident = fScanner.getCurrentIdentifierSource();
204 addIdentifierInformation('c', ident, buf, phpdocOffset, phpdocLength);
207 //skip fTokens for classname, extends and others until we have the opening '{'
208 while (fToken != TokenNameLBRACE && fToken != TokenNameEOF && fToken != TokenNameERROR) {
212 parseDeclarations(buf, true);
215 } else if (fToken == TokenNamedefine) {
217 if (fToken == TokenNameLPAREN) {
219 if (fToken == TokenNameStringLiteral) {
220 ident = fScanner.getCurrentStringLiteralSource();
221 addIdentifierInformation('d', ident, buf, phpdocOffset, phpdocLength);
229 } catch (SyntaxError e) {
230 // TODO Auto-generated catch block
236 private HashMap fFileMap;
237 private String fFilename;
238 private HashMap fIndentifierMap;
240 public IdentifierIndexManager(String filename) {
241 fFilename = filename;
247 * Add the information for a given IFile resource
250 public void addFile(IFile fileToParse) {
252 LineCreator lineCreator = new LineCreator();
254 iStream = fileToParse.getContents();
256 StringBuffer buf = new StringBuffer();
259 while ((c0 = iStream.read()) != (-1)) {
260 buf.append((char) c0);
262 } catch (IOException e) {
266 StringBuffer lineBuffer = new StringBuffer();
267 // lineBuffer.append(fileToParse.getLocation().toString());
268 lineBuffer.append(fileToParse.getFullPath().toString());
269 int lineLength = lineBuffer.length();
270 lineCreator.parseIdentifiers(buf.toString().toCharArray(), lineBuffer);
271 if (lineLength != lineBuffer.length()) {
272 addLine(lineBuffer.toString());
274 } catch (CoreException e1) {
275 // TODO Auto-generated catch block
276 e1.printStackTrace();
281 * Adds a line of the index file for function, class, class-method and class-variable names
285 private void addLine(String line) {
286 StringTokenizer tokenizer;
287 String phpFileName = null;
289 String identifier = null;
290 String classname = null;
291 String offset = null;
292 PHPIdentifierLocation phpIdentifier = null;
293 boolean tokenExists = false;
295 tokenizer = new StringTokenizer(line, "\t");
296 // first token contains the filename:
297 if (tokenizer.hasMoreTokens()) {
298 phpFileName = tokenizer.nextToken();
299 //System.out.println(token);
303 // all the other tokens are identifiers:
304 while (tokenizer.hasMoreTokens()) {
305 token = tokenizer.nextToken();
306 //System.out.println(token);
307 switch (token.charAt(0)) {
308 case 'c' : // class name
309 identifier = token.substring(1);
310 classname = identifier;
311 phpIdentifier = new PHPIdentifierLocation(identifier, PHPIdentifier.CLASS, phpFileName);
314 identifier = token.substring(1);
315 phpIdentifier = new PHPIdentifierLocation(identifier, PHPIdentifier.DEFINE, phpFileName);
317 case 'f' : // function name
318 identifier = token.substring(1);
319 phpIdentifier = new PHPIdentifierLocation(identifier, PHPIdentifier.FUNCTION, phpFileName);
321 case 'm' : //method inside a class
322 identifier = token.substring(1);
323 phpIdentifier = new PHPIdentifierLocation(identifier, PHPIdentifier.METHOD, phpFileName, classname);
325 case 'v' : // variable inside a class
326 identifier = token.substring(1);
327 phpIdentifier = new PHPIdentifierLocation(identifier, PHPIdentifier.VARIABLE, phpFileName, classname);
329 case 'o' : // offset information
331 if (phpIdentifier != null) {
332 offset = token.substring(1);
333 phpIdentifier.setOffset(Integer.parseInt(offset));
336 case 'p' : // PHPdoc offset information
338 if (phpIdentifier != null) {
339 offset = token.substring(1);
340 phpIdentifier.setPHPDocOffset(Integer.parseInt(offset));
343 case 'l' : // PHPdoc length information
345 if (phpIdentifier != null) {
346 offset = token.substring(1);
347 phpIdentifier.setPHPDocLength(Integer.parseInt(offset));
352 phpIdentifier = null;
355 if (identifier != null && phpIdentifier != null) {
357 ArrayList list = (ArrayList) fIndentifierMap.get(identifier);
359 list = new ArrayList();
360 list.add(phpIdentifier);
361 fIndentifierMap.put(identifier, list);
363 boolean flag = false;
364 for (int i = 0; i < list.size(); i++) {
365 if (list.get(i).equals(phpIdentifier)) {
371 list.add(phpIdentifier);
377 fFileMap.put(phpFileName, line);
382 * Change the information for a given IFile resource
385 public void changeFile(IFile fileToParse) {
386 removeFile(fileToParse);
387 addFile(fileToParse);
391 * Get a list of all PHPIdentifierLocation object's associated with an identifier
396 public List getLocations(String identifier) {
397 return (List) fIndentifierMap.get(identifier);
401 * Initialize (i.e. clear) the current index information
404 public void initialize() {
405 fIndentifierMap = new HashMap();
406 fFileMap = new HashMap();
409 private void readFile() {
411 FileReader fileReader;
413 fileReader = new FileReader(fFilename);
415 BufferedReader bufferedReader = new BufferedReader(fileReader);
418 while (bufferedReader.ready()) {
419 // all entries for one file are in a line
420 // separated by tabs !
421 line = bufferedReader.readLine();
426 } catch (FileNotFoundException e) {
428 // TODO DialogBox which asks the user if she/he likes to build new index?
429 } catch (IOException e) {
430 // TODO Auto-generated catch block
437 * Remove the information for a given IFile resource
440 public void removeFile(IFile fileToParse) {
441 // String line = (String) fFileMap.get(fileToParse.getLocation().toString());
442 String line = (String) fFileMap.get(fileToParse.getFullPath().toString());
449 * Removes a line of the index file for function, class, class-method and class-variable names
453 private void removeLine(String line) {
454 StringTokenizer tokenizer;
455 String phpFileName = null;
457 String identifier = null;
458 String classname = null;
459 PHPIdentifier phpIdentifier = null;
460 boolean tokenExists = false;
462 tokenizer = new StringTokenizer(line, "\t");
463 // first token contains the filename:
464 if (tokenizer.hasMoreTokens()) {
465 phpFileName = tokenizer.nextToken();
466 //System.out.println(token);
470 // all the other tokens are identifiers:
471 while (tokenizer.hasMoreTokens()) {
472 token = tokenizer.nextToken();
473 //System.out.println(token);
474 switch (token.charAt(0)) {
475 case 'c' : // class name
476 identifier = token.substring(1);
477 classname = identifier;
478 phpIdentifier = new PHPIdentifierLocation(identifier, PHPIdentifier.CLASS, phpFileName);
481 identifier = token.substring(1);
482 phpIdentifier = new PHPIdentifierLocation(identifier, PHPIdentifier.DEFINE, phpFileName);
484 case 'f' : // function name
485 identifier = token.substring(1);
486 phpIdentifier = new PHPIdentifierLocation(identifier, PHPIdentifier.FUNCTION, phpFileName);
488 case 'm' : //method inside a class
489 identifier = token.substring(1);
490 phpIdentifier = new PHPIdentifierLocation(identifier, PHPIdentifier.METHOD, phpFileName, classname);
492 case 'v' : // variable inside a class
493 identifier = token.substring(1);
494 phpIdentifier = new PHPIdentifierLocation(identifier, PHPIdentifier.VARIABLE, phpFileName, classname);
498 phpIdentifier = null;
501 if (identifier != null && phpIdentifier != null) {
502 ArrayList list = (ArrayList) fIndentifierMap.get(identifier);
505 for (int i = 0; i < list.size(); i++) {
506 if (list.get(i).equals(phpIdentifier)) {
511 if (list.size() == 0) {
512 fIndentifierMap.remove(identifier);
517 fFileMap.remove(phpFileName);
521 * Save the current index information in the projects index file
524 public void writeFile() {
525 FileWriter fileWriter;
527 fileWriter = new FileWriter(fFilename);
529 Collection collection = fFileMap.values();
530 Iterator iterator = collection.iterator();
531 while (iterator.hasNext()) {
532 line = (String) iterator.next();
533 fileWriter.write(line + '\n');
536 } catch (IOException e) {
537 // TODO Auto-generated catch block