1 package net.sourceforge.phpdt.internal.compiler.parser;
3 import net.sourceforge.phpdt.core.IJavaModelMarker;
4 import net.sourceforge.phpdt.core.compiler.IProblem;
5 import net.sourceforge.phpdt.internal.compiler.CompilationResult;
6 import net.sourceforge.phpdt.internal.compiler.ast.ASTNode;
7 import net.sourceforge.phpdt.internal.compiler.ast.CompilationUnitDeclaration;
8 import net.sourceforge.phpdt.internal.compiler.ast.ConstructorDeclaration;
9 import net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration;
10 import net.sourceforge.phpdt.internal.compiler.ast.Initializer;
11 import net.sourceforge.phpdt.internal.compiler.ast.MethodDeclaration;
12 import net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration;
13 import net.sourceforge.phpdt.internal.compiler.env.ICompilationUnit;
14 import net.sourceforge.phpdt.internal.compiler.problem.AbortCompilation;
15 import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter;
17 import org.eclipse.core.resources.IMarker;
18 import org.eclipse.core.resources.IResource;
19 import org.eclipse.core.runtime.CoreException;
25 public class UnitParser extends Parser {
27 public UnitParser(ProblemReporter problemReporter) { // , boolean
28 // optimizeStringLiterals,
31 super(problemReporter);
32 nestedMethod = new int[30];
34 // this.optimizeStringLiterals = optimizeStringLiterals;
35 // this.assertMode = assertMode;
36 // this.initializeScanner();
37 astLengthStack = new int[50];
38 // expressionLengthStack = new int[30];
39 // intStack = new int[50];
40 // identifierStack = new char[30][];
41 // identifierLengthStack = new int[30];
42 // nestedMethod = new int[30];
43 // realBlockStack = new int[30];
44 // identifierPositionStack = new long[30];
45 // variablesCounter = new int[30];
48 public void goForConstructorBody() {
49 // tells the scanner to go for compilation unit parsing
51 firstToken = TokenNameEQUAL_EQUAL;
52 scanner.recordLineSeparator = false;
55 public void goForExpression() {
56 // tells the scanner to go for an expression parsing
58 firstToken = TokenNameREMAINDER;
59 scanner.recordLineSeparator = false;
62 public void goForCompilationUnit() {
63 // tells the scanner to go for compilation unit parsing
65 firstToken = TokenNamePLUS_PLUS;
67 scanner.foundTaskCount = 0;
68 scanner.recordLineSeparator = true;
69 // scanner.currentLine= null;
72 public void goForInitializer() {
73 // tells the scanner to go for initializer parsing
75 firstToken = TokenNameRIGHT_SHIFT;
76 scanner.recordLineSeparator = false;
79 public void goForMethodBody() {
80 // tells the scanner to go for method body parsing
82 firstToken = TokenNameMINUS_MINUS;
83 scanner.recordLineSeparator = false;
86 public void initialize(boolean phpMode) {
87 super.initialize(phpMode);
88 // positionning the parser for a new compilation unit
89 // avoiding stack reallocation and all that....
92 // expressionPtr = -1;
93 // expressionLengthPtr = -1;
94 // identifierPtr = -1;
95 // identifierLengthPtr = -1;
97 // nestedMethod[nestedType = 0] = 0; // need to reset for further reuse
98 // variablesCounter[nestedType] = 0;
100 // realBlockPtr = -1;
101 // endStatementPosition = 0;
103 // remove objects from stack too, while the same parser/compiler couple
105 // re-used between two compilations ....
107 // int astLength = astStack.length;
108 // if (noAstNodes.length < astLength){
109 // noAstNodes = new ASTNode[astLength];
110 // //System.out.println("Resized AST stacks : "+ astLength);
113 // System.arraycopy(noAstNodes, 0, astStack, 0, astLength);
115 // int expressionLength = expressionStack.length;
116 // if (noExpressions.length < expressionLength){
117 // noExpressions = new Expression[expressionLength];
118 // //System.out.println("Resized EXPR stacks : "+ expressionLength);
120 // System.arraycopy(noExpressions, 0, expressionStack, 0,
121 // expressionLength);
123 // reset scanner state
124 scanner.commentPtr = -1;
125 scanner.foundTaskCount = 0;
126 scanner.eofPosition = Integer.MAX_VALUE;
131 // lastCheckPoint = -1;
132 // currentElement = null;
133 // restartRecovery = false;
134 // hasReportedError = false;
135 // recoveredStaticInitializerStart = 0;
136 // lastIgnoredToken = -1;
137 // lastErrorEndPosition = -1;
143 public CompilationUnitDeclaration parse(ICompilationUnit sourceUnit,
144 CompilationResult compilationResult, boolean phpMode) {
145 // parses a compilation unit and manages error handling (even bugs....)
147 CompilationUnitDeclaration unit;
149 /* automaton initialization */
151 goForCompilationUnit();
153 /* scanner initialization */
154 scanner.setSource(sourceUnit, sourceUnit.getContents());
157 referenceContext = compilationUnit = new CompilationUnitDeclaration(
158 problemReporter, compilationResult, scanner.source.length);
159 // TODO TypeDeclaration test
160 // TypeDeclaration typeDecl = new
161 // TypeDeclaration(this.compilationUnit.compilationResult);
162 // typeDecl.sourceStart = 0;
163 // typeDecl.sourceEnd = 10;
164 // typeDecl.name = new char[]{'t', 'e','s','t'};
165 // this.compilationUnit.types = new ArrayList();
166 // this.compilationUnit.types.add(typeDecl);
169 // // TODO jsurfer start
170 // if (sourceUnit instanceof BasicCompilationUnit) {
171 // storeProblemsFor(((BasicCompilationUnit)sourceUnit).getResource(),
172 // compilationResult.getAllProblems());
177 unit = compilationUnit;
178 compilationUnit = null; // reset parser
184 * Creates a marker from each problem and adds it to the resource. The
185 * marker is as follows: - its type is T_PROBLEM - its plugin ID is the
186 * JavaBuilder's plugin ID - its message is the problem's message - its
187 * priority reflects the severity of the problem - its range is the
188 * problem's range - it has an extra attribute "ID" which holds the
191 protected void storeProblemsFor(IResource resource, IProblem[] problems)
192 throws CoreException {
193 if (resource == null || problems == null || problems.length == 0)
196 for (int i = 0, l = problems.length; i < l; i++) {
197 IProblem problem = problems[i];
198 int id = problem.getID();
199 if (id != IProblem.Task) {
200 IMarker marker = resource
201 .createMarker(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER);
204 new String[] { IMarker.MESSAGE,
205 IMarker.SEVERITY, IJavaModelMarker.ID,
206 IMarker.CHAR_START, IMarker.CHAR_END,
208 IJavaModelMarker.ARGUMENTS },
210 problem.getMessage(),
212 problem.isError() ? IMarker.SEVERITY_ERROR
213 : IMarker.SEVERITY_WARNING),
215 new Integer(problem.getSourceStart()),
216 new Integer(problem.getSourceEnd() + 1),
218 .getSourceLineNumber()),
219 net.sourceforge.phpdt.internal.core.util.Util
220 .getProblemArgumentsForMarker(problem
229 public void parse(ConstructorDeclaration cd, CompilationUnitDeclaration unit) {
230 // only parse the method body of cd
231 // fill out its statements
233 // convert bugs into parse error
236 goForConstructorBody();
237 nestedMethod[nestedType]++;
239 referenceContext = cd;
240 compilationUnit = unit;
242 scanner.resetTo(cd.sourceEnd + 1, cd.declarationSourceEnd);
245 } catch (AbortCompilation ex) {
246 lastAct = ERROR_ACTION;
249 nestedMethod[nestedType]--;
252 if (lastAct == ERROR_ACTION) {
258 // cd.explicitDeclarations = realBlockStack[realBlockPtr--];
260 // if ((length = astLengthStack[astLengthPtr--]) != 0) {
262 // if (astStack[astPtr + 1] instanceof ExplicitConstructorCall)
263 // //avoid a isSomeThing that would only be used here BUT what is faster
264 // between two alternatives ?
269 // cd.statements = new Statement[length - 1],
272 // cd.constructorCall = (ExplicitConstructorCall) astStack[astPtr + 1];
273 // } else { //need to add explicitly the super();
277 // cd.statements = new Statement[length],
280 // cd.constructorCall = SuperReference.implicitSuperConstructorCall();
283 // cd.constructorCall = SuperReference.implicitSuperConstructorCall();
286 // if (cd.constructorCall.sourceEnd == 0) {
287 // cd.constructorCall.sourceEnd = cd.sourceEnd;
288 // cd.constructorCall.sourceStart = cd.sourceStart;
294 public void parse(FieldDeclaration field, TypeDeclaration type,
295 CompilationUnitDeclaration unit, char[] initializationSource) {
296 // only parse the initializationSource of the given field
298 // convert bugs into parse error
302 nestedMethod[nestedType]++;
304 referenceContext = type;
305 compilationUnit = unit;
307 scanner.setSource(initializationSource);
308 scanner.resetTo(0, initializationSource.length - 1);
311 } catch (AbortCompilation ex) {
312 lastAct = ERROR_ACTION;
314 nestedMethod[nestedType]--;
317 // if (lastAct == ERROR_ACTION) {
321 // field.initialization = expressionStack[expressionPtr];
323 // // mark field with local type if one was found during parsing
324 // if ((type.bits & ASTNode.HasLocalTypeMASK) != 0) {
325 // field.bits |= ASTNode.HasLocalTypeMASK;
331 public void parse(Initializer ini, TypeDeclaration type,
332 CompilationUnitDeclaration unit) {
333 // only parse the method body of md
334 // fill out method statements
336 // convert bugs into parse error
340 nestedMethod[nestedType]++;
342 referenceContext = type;
343 compilationUnit = unit;
345 scanner.resetTo(ini.sourceStart, ini.sourceEnd); // just on the
349 } catch (AbortCompilation ex) {
350 lastAct = ERROR_ACTION;
352 nestedMethod[nestedType]--;
355 // if (lastAct == ERROR_ACTION) {
359 // ini.block = ((Initializer) astStack[astPtr]).block;
361 // // mark initializer with local type if one was found during parsing
362 // if ((type.bits & ASTNode.HasLocalTypeMASK) != 0) {
363 // ini.bits |= ASTNode.HasLocalTypeMASK;
369 public void parse(MethodDeclaration md, CompilationUnitDeclaration unit) {
370 // TODO jsurfer - make the parse process work on methods ?
373 // //only parse the method body of md
374 // //fill out method statements
376 // //convert bugs into parse error
378 // if (md.isAbstract())
380 // // if (md.isNative())
382 // // if ((md.modifiers & AccSemicolonBody) != 0)
385 // initialize(false);
386 // goForMethodBody();
387 // nestedMethod[nestedType]++;
389 // referenceContext = md;
390 // compilationUnit = unit;
392 // scanner.resetTo(md.sourceEnd + 1, md.declarationSourceEnd);
394 // // reset the scanner to parser from { down to }
397 // } catch (AbortCompilation ex) {
398 // lastAct = ERROR_ACTION;
400 // nestedMethod[nestedType]--;
403 // // if (lastAct == ERROR_ACTION) {
407 // // //refill statements
408 // // md.explicitDeclarations = realBlockStack[realBlockPtr--];
410 // // if ((length = astLengthStack[astLengthPtr--]) != 0)
411 // // System.arraycopy(
413 // // (astPtr -= length) + 1,
414 // // md.statements = new Statement[length],
421 public CompilationUnitDeclaration parse(ICompilationUnit sourceUnit,
422 CompilationResult compilationResult, int start, int end) {
423 // parses a compilation unit and manages error handling (even bugs....)
425 CompilationUnitDeclaration unit;
427 /* automaton initialization */
429 goForCompilationUnit();
431 /* scanner initialization */
432 scanner.setSource(sourceUnit, sourceUnit.getContents());
433 scanner.resetTo(start, end);
435 referenceContext = compilationUnit = new CompilationUnitDeclaration(
436 problemReporter, compilationResult, scanner.source.length);
440 } catch (SyntaxError syntaxError) {
443 unit = compilationUnit;
444 compilationUnit = null; // reset parser
449 public CompilationUnitDeclaration dietParse(ICompilationUnit sourceUnit,
450 CompilationResult compilationResult) {
451 return dietParse(sourceUnit, compilationResult, false);
454 public CompilationUnitDeclaration dietParse(ICompilationUnit sourceUnit,
455 CompilationResult compilationResult, boolean phpMode) {
457 CompilationUnitDeclaration parsedUnit;
461 parsedUnit = parse(sourceUnit, compilationResult, phpMode);
468 public void getMethodBodies(CompilationUnitDeclaration unit) {
469 // fill the methods bodies in order for the code to be generated
474 if (unit.ignoreMethodBodies) {
475 unit.ignoreFurtherInvestigation = true;
477 // if initial diet parse did not work, no need to dig into method
481 if ((unit.bits & ASTNode.HasAllMethodBodies) != 0)
482 return; // work already done ...
484 // real parse of the method....
485 char[] contents = unit.compilationResult.compilationUnit.getContents();
486 this.scanner.setSource(contents);
488 // save existing values to restore them at the end of the parsing
490 // see bug 47079 for more details
491 int[] oldLineEnds = this.scanner.lineEnds;
492 int oldLinePtr = this.scanner.linePtr;
494 final int[] lineSeparatorPositions = unit.compilationResult.lineSeparatorPositions;
495 this.scanner.lineEnds = lineSeparatorPositions;
496 this.scanner.linePtr = lineSeparatorPositions.length - 1;
498 // if (this.javadocParser != null && this.javadocParser.checkDocComment)
500 // this.javadocParser.scanner.setSource(contents);
502 if (unit.types != null) {
503 for (int i = unit.types.size(); --i >= 0;)
504 ((TypeDeclaration) unit.types.get(i)).parseMethod(this, unit);
507 // tag unit has having read bodies
508 unit.bits |= ASTNode.HasAllMethodBodies;
510 // this is done to prevent any side effects on the compilation unit
512 // line separator positions array.
513 this.scanner.lineEnds = oldLineEnds;
514 this.scanner.linePtr = oldLinePtr;