improved PHP Completion for -> operator
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / compiler / parser / UnitParser.java
1 package net.sourceforge.phpdt.internal.compiler.parser;
2
3
4 import net.sourceforge.phpdt.core.IJavaModelMarker;
5 import net.sourceforge.phpdt.core.compiler.IProblem;
6 import net.sourceforge.phpdt.internal.compiler.CompilationResult;
7 import net.sourceforge.phpdt.internal.compiler.env.ICompilationUnit;
8 import net.sourceforge.phpdt.internal.compiler.problem.AbortCompilation;
9 import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter;
10 import net.sourceforge.phpeclipse.internal.compiler.ast.CompilationUnitDeclaration;
11 import net.sourceforge.phpeclipse.internal.compiler.ast.ConstructorDeclaration;
12 import net.sourceforge.phpeclipse.internal.compiler.ast.FieldDeclaration;
13 import net.sourceforge.phpeclipse.internal.compiler.ast.Initializer;
14 import net.sourceforge.phpeclipse.internal.compiler.ast.MethodDeclaration;
15 import net.sourceforge.phpeclipse.internal.compiler.ast.TypeDeclaration;
16
17 import org.eclipse.core.resources.IMarker;
18 import org.eclipse.core.resources.IResource;
19 import org.eclipse.core.runtime.CoreException;
20
21 /**
22  * 
23  * 
24  */
25 public class UnitParser extends Parser {
26
27   public UnitParser(ProblemReporter problemReporter) { //, boolean optimizeStringLiterals, boolean assertMode) {
28     super(problemReporter);
29     nestedMethod = new int[30];
30     
31     //          this.optimizeStringLiterals = optimizeStringLiterals;
32     //          this.assertMode = assertMode;
33     //          this.initializeScanner();
34     astLengthStack = new int[50];
35     //          expressionLengthStack = new int[30];
36     //          intStack = new int[50];
37     //          identifierStack = new char[30][];
38     //          identifierLengthStack = new int[30];
39     //          nestedMethod = new int[30];
40     //          realBlockStack = new int[30];
41     //          identifierPositionStack = new long[30];
42     //          variablesCounter = new int[30];
43   }
44
45   public void goForConstructorBody() {
46     //tells the scanner to go for compilation unit parsing
47
48     firstToken = TokenNameEQUAL_EQUAL;
49     scanner.recordLineSeparator = false;
50   }
51   public void goForExpression() {
52     //tells the scanner to go for an expression parsing
53
54     firstToken = TokenNameREMAINDER;
55     scanner.recordLineSeparator = false;
56   }
57   public void goForCompilationUnit() {
58     //tells the scanner to go for compilation unit parsing
59
60     firstToken = TokenNamePLUS_PLUS;
61     scanner.linePtr = -1;
62     scanner.foundTaskCount = 0;
63     scanner.recordLineSeparator = true;
64     //          scanner.currentLine= null;
65   }
66   public void goForInitializer() {
67     //tells the scanner to go for initializer parsing
68
69     firstToken = TokenNameRIGHT_SHIFT;
70     scanner.recordLineSeparator = false;
71   }
72   public void goForMethodBody() {
73     //tells the scanner to go for method body parsing
74
75     firstToken = TokenNameMINUS_MINUS;
76     scanner.recordLineSeparator = false;
77   }
78   public void initialize(boolean phpMode) {
79     super.initialize(phpMode);
80     //positionning the parser for a new compilation unit
81     //avoiding stack reallocation and all that....
82     //          astPtr = -1;
83     //          astLengthPtr = -1;
84     //          expressionPtr = -1;
85     //          expressionLengthPtr = -1;
86     //          identifierPtr = -1;     
87     //          identifierLengthPtr     = -1;
88     //          intPtr = -1;
89     //          nestedMethod[nestedType = 0] = 0; // need to reset for further reuse
90     //          variablesCounter[nestedType] = 0;
91     //          dimensions = 0 ;
92     //          realBlockPtr = -1;
93     //          endStatementPosition = 0;
94
95     //remove objects from stack too, while the same parser/compiler couple is
96     //re-used between two compilations ....
97
98     //          int astLength = astStack.length;
99     //          if (noAstNodes.length < astLength){
100     //                  noAstNodes = new AstNode[astLength];
101     //                  //System.out.println("Resized AST stacks : "+ astLength);
102     //          
103     //          }
104     //          System.arraycopy(noAstNodes, 0, astStack, 0, astLength);
105     //
106     //          int expressionLength = expressionStack.length;
107     //          if (noExpressions.length < expressionLength){
108     //                  noExpressions = new Expression[expressionLength];
109     //                  //System.out.println("Resized EXPR stacks : "+ expressionLength);
110     //          }
111     //          System.arraycopy(noExpressions, 0, expressionStack, 0, expressionLength);
112
113     // reset scanner state
114     scanner.commentPtr = -1;
115     scanner.foundTaskCount = 0;
116     scanner.eofPosition = Integer.MAX_VALUE;
117
118     //          resetModifiers();
119     //
120     //          // recovery
121     //          lastCheckPoint = -1;
122     //          currentElement = null;
123     //          restartRecovery = false;
124     //          hasReportedError = false;
125     //          recoveredStaticInitializerStart = 0;
126     //          lastIgnoredToken = -1;
127     //          lastErrorEndPosition = -1;
128     //          listLength = 0;
129   }
130
131   // A P I
132
133   public CompilationUnitDeclaration parse(ICompilationUnit sourceUnit, CompilationResult compilationResult, boolean phpMode) {
134     // parses a compilation unit and manages error handling (even bugs....)
135
136     CompilationUnitDeclaration unit;
137     try {
138       /* automaton initialization */
139       initialize(phpMode);
140       goForCompilationUnit();
141
142       /* scanner initialization */
143       scanner.setSource(sourceUnit.getContents());
144
145       /* unit creation */
146       referenceContext =
147         compilationUnit = new CompilationUnitDeclaration(problemReporter, compilationResult, scanner.source.length);
148       // TODO TypeDeclaration test
149       //      TypeDeclaration typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult);
150       //      typeDecl.sourceStart = 0;
151       //      typeDecl.sourceEnd = 10;
152       //      typeDecl.name = new char[]{'t', 'e','s','t'};
153       //      this.compilationUnit.types = new ArrayList();
154       //      this.compilationUnit.types.add(typeDecl);
155       /* run automaton */
156       super.parse();
157 //      //              TODO jsurfer start 
158 //      if (sourceUnit instanceof BasicCompilationUnit) {
159 //        storeProblemsFor(((BasicCompilationUnit)sourceUnit).getResource(), compilationResult.getAllProblems());
160 //      }
161 //      // jsurfer end
162     
163     } finally {
164       unit = compilationUnit;
165       compilationUnit = null; // reset parser
166     }
167     return unit;
168   }
169   /**
170                  * Creates a marker from each problem and adds it to the resource.
171                  * The marker is as follows:
172                  *   - its type is T_PROBLEM
173                  *   - its plugin ID is the JavaBuilder's plugin ID
174                  *       - its message is the problem's message
175                  *       - its priority reflects the severity of the problem
176                  *       - its range is the problem's range
177                  *       - it has an extra attribute "ID" which holds the problem's id
178                  */
179   protected void storeProblemsFor(IResource resource, IProblem[] problems) throws CoreException {
180     if (resource == null || problems == null || problems.length == 0)
181       return;
182
183     for (int i = 0, l = problems.length; i < l; i++) {
184       IProblem problem = problems[i];
185       int id = problem.getID();
186       if (id != IProblem.Task) {
187         IMarker marker = resource.createMarker(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER);
188         marker.setAttributes(
189           new String[] {
190             IMarker.MESSAGE,
191             IMarker.SEVERITY,
192             IJavaModelMarker.ID,
193             IMarker.CHAR_START,
194             IMarker.CHAR_END,
195             IMarker.LINE_NUMBER,
196             IJavaModelMarker.ARGUMENTS },
197           new Object[] {
198             problem.getMessage(),
199             new Integer(problem.isError() ? IMarker.SEVERITY_ERROR : IMarker.SEVERITY_WARNING),
200             new Integer(id),
201             new Integer(problem.getSourceStart()),
202             new Integer(problem.getSourceEnd() + 1),
203             new Integer(problem.getSourceLineNumber()),
204             net.sourceforge.phpdt.internal.core.util.Util.getProblemArgumentsForMarker(problem.getArguments())});
205       }
206
207     }
208   }
209
210
211   // A P I
212
213   public void parse(ConstructorDeclaration cd, CompilationUnitDeclaration unit) {
214     //only parse the method body of cd
215     //fill out its statements
216
217     //convert bugs into parse error
218
219     initialize(false);
220     goForConstructorBody();
221     nestedMethod[nestedType]++;
222
223     referenceContext = cd;
224     compilationUnit = unit;
225
226     scanner.resetTo(cd.sourceEnd + 1, cd.declarationSourceEnd);
227     try {
228       parse();
229     } catch (AbortCompilation ex) {
230       lastAct = ERROR_ACTION;
231     
232     } finally {
233       nestedMethod[nestedType]--;
234     }
235
236     if (lastAct == ERROR_ACTION) {
237       initialize(false);
238       return;
239     }
240
241     //statements
242     //  cd.explicitDeclarations = realBlockStack[realBlockPtr--];
243     //  int length;
244     //  if ((length = astLengthStack[astLengthPtr--]) != 0) {
245     //          astPtr -= length;
246     //          if (astStack[astPtr + 1] instanceof ExplicitConstructorCall)
247     //                  //avoid a isSomeThing that would only be used here BUT what is faster between two alternatives ?
248     //                  {
249     //                  System.arraycopy(
250     //                          astStack, 
251     //                          astPtr + 2, 
252     //                          cd.statements = new Statement[length - 1], 
253     //                          0, 
254     //                          length - 1); 
255     //                  cd.constructorCall = (ExplicitConstructorCall) astStack[astPtr + 1];
256     //          } else { //need to add explicitly the super();
257     //                  System.arraycopy(
258     //                          astStack, 
259     //                          astPtr + 1, 
260     //                          cd.statements = new Statement[length], 
261     //                          0, 
262     //                          length); 
263     //                  cd.constructorCall = SuperReference.implicitSuperConstructorCall();
264     //          }
265     //  } else {
266     //          cd.constructorCall = SuperReference.implicitSuperConstructorCall();
267     //  }
268     //
269     //  if (cd.constructorCall.sourceEnd == 0) {
270     //          cd.constructorCall.sourceEnd = cd.sourceEnd;
271     //          cd.constructorCall.sourceStart = cd.sourceStart;
272     //  }
273   }
274   // A P I
275
276   public void parse(FieldDeclaration field, TypeDeclaration type, CompilationUnitDeclaration unit, char[] initializationSource) {
277     //only parse the initializationSource of the given field
278
279     //convert bugs into parse error
280
281     initialize(false);
282     goForExpression();
283     nestedMethod[nestedType]++;
284
285     referenceContext = type;
286     compilationUnit = unit;
287
288     scanner.setSource(initializationSource);
289     scanner.resetTo(0, initializationSource.length - 1);
290     try {
291       parse();
292     } catch (AbortCompilation ex) {
293       lastAct = ERROR_ACTION;
294     } finally {
295       nestedMethod[nestedType]--;
296     }
297
298     //  if (lastAct == ERROR_ACTION) {
299     //          return;
300     //  }
301     //
302     //  field.initialization = expressionStack[expressionPtr];
303     //  
304     //  // mark field with local type if one was found during parsing
305     //  if ((type.bits & AstNode.HasLocalTypeMASK) != 0) {
306     //          field.bits |= AstNode.HasLocalTypeMASK;
307     //  }       
308   }
309   // A P I
310
311   public void parse(Initializer ini, TypeDeclaration type, CompilationUnitDeclaration unit) {
312     //only parse the method body of md
313     //fill out method statements
314
315     //convert bugs into parse error
316
317     initialize(false);
318     goForInitializer();
319     nestedMethod[nestedType]++;
320
321     referenceContext = type;
322     compilationUnit = unit;
323
324     scanner.resetTo(ini.sourceStart, ini.sourceEnd); // just on the beginning {
325     try {
326       parse();
327     } catch (AbortCompilation ex) {
328       lastAct = ERROR_ACTION;
329     } finally {
330       nestedMethod[nestedType]--;
331     }
332
333     //  if (lastAct == ERROR_ACTION) {
334     //          return;
335     //  }
336     //
337     //  ini.block = ((Initializer) astStack[astPtr]).block;
338     //  
339     //  // mark initializer with local type if one was found during parsing
340     //  if ((type.bits & AstNode.HasLocalTypeMASK) != 0) {
341     //          ini.bits |= AstNode.HasLocalTypeMASK;
342     //  }       
343   }
344   // A P I
345
346   public void parse(MethodDeclaration md, CompilationUnitDeclaration unit) {
347 //  TODO jsurfer - make the parse process work on methods ?
348     return; 
349     
350 //    //only parse the method body of md
351 //    //fill out method statements
352 //
353 //    //convert bugs into parse error
354 //
355 //    if (md.isAbstract())
356 //      return;
357 //    //        if (md.isNative())
358 //    //                return;
359 //    //        if ((md.modifiers & AccSemicolonBody) != 0)
360 //    //                return;
361 //
362 //    initialize(false);
363 //    goForMethodBody();
364 //    nestedMethod[nestedType]++;
365 //
366 //    referenceContext = md;
367 //    compilationUnit = unit;
368 //
369 //    scanner.resetTo(md.sourceEnd + 1, md.declarationSourceEnd);
370 //   
371 //    // reset the scanner to parser from { down to }
372 //    try {
373 //      parse();
374 //    } catch (AbortCompilation ex) {
375 //      lastAct = ERROR_ACTION;
376 //    } finally {
377 //      nestedMethod[nestedType]--;
378 //    }
379 //
380 //    //        if (lastAct == ERROR_ACTION) {
381 //    //                return;
382 //    //        }
383 //    //
384 //    //        //refill statements
385 //    //        md.explicitDeclarations = realBlockStack[realBlockPtr--];
386 //    //        int length;
387 //    //        if ((length = astLengthStack[astLengthPtr--]) != 0)
388 //    //                System.arraycopy(
389 //    //                        astStack, 
390 //    //                        (astPtr -= length) + 1, 
391 //    //                        md.statements = new Statement[length], 
392 //    //                        0, 
393 //    //                        length); 
394   }
395
396   // A P I
397
398   public CompilationUnitDeclaration parse(ICompilationUnit sourceUnit, CompilationResult compilationResult, int start, int end) {
399     // parses a compilation unit and manages error handling (even bugs....)
400
401     CompilationUnitDeclaration unit;
402     try {
403       /* automaton initialization */
404       initialize(false);
405       goForCompilationUnit();
406
407       /* scanner initialization */
408       scanner.setSource(sourceUnit.getContents());
409       scanner.resetTo(start, end);
410       /* unit creation */
411       referenceContext =
412         compilationUnit = new CompilationUnitDeclaration(problemReporter, compilationResult, scanner.source.length);
413       /* run automaton */
414       parse();
415     } catch (SyntaxError syntaxError) {
416       // 
417     } finally {
418       unit = compilationUnit;
419       compilationUnit = null; // reset parser
420     }
421     return unit;
422   }
423
424   public CompilationUnitDeclaration dietParse(ICompilationUnit sourceUnit, CompilationResult compilationResult) {
425         return dietParse(sourceUnit, compilationResult, false);
426   }
427   public CompilationUnitDeclaration dietParse(ICompilationUnit sourceUnit, CompilationResult compilationResult, boolean phpMode) {
428
429     CompilationUnitDeclaration parsedUnit;
430     boolean old = diet;
431     try {
432       diet = true;
433       parsedUnit = parse(sourceUnit, compilationResult, phpMode);
434     } finally {
435       diet = old;
436     }
437     return parsedUnit;
438   }
439 }