1 package net.sourceforge.phpdt.internal.compiler.parser;
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.ast.ASTNode;
8 import net.sourceforge.phpdt.internal.compiler.ast.CompilationUnitDeclaration;
9 import net.sourceforge.phpdt.internal.compiler.ast.ConstructorDeclaration;
10 import net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration;
11 import net.sourceforge.phpdt.internal.compiler.ast.Initializer;
12 import net.sourceforge.phpdt.internal.compiler.ast.MethodDeclaration;
13 import net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration;
14 import net.sourceforge.phpdt.internal.compiler.env.ICompilationUnit;
15 import net.sourceforge.phpdt.internal.compiler.problem.AbortCompilation;
16 import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter;
18 import org.eclipse.core.resources.IMarker;
19 import org.eclipse.core.resources.IResource;
20 import org.eclipse.core.runtime.CoreException;
26 public class UnitParser extends Parser {
28 public UnitParser(ProblemReporter problemReporter) { //, boolean optimizeStringLiterals, boolean assertMode) {
29 super(problemReporter);
30 nestedMethod = new int[30];
32 // this.optimizeStringLiterals = optimizeStringLiterals;
33 // this.assertMode = assertMode;
34 // this.initializeScanner();
35 astLengthStack = new int[50];
36 // expressionLengthStack = new int[30];
37 // intStack = new int[50];
38 // identifierStack = new char[30][];
39 // identifierLengthStack = new int[30];
40 // nestedMethod = new int[30];
41 // realBlockStack = new int[30];
42 // identifierPositionStack = new long[30];
43 // variablesCounter = new int[30];
46 public void goForConstructorBody() {
47 //tells the scanner to go for compilation unit parsing
49 firstToken = TokenNameEQUAL_EQUAL;
50 scanner.recordLineSeparator = false;
52 public void goForExpression() {
53 //tells the scanner to go for an expression parsing
55 firstToken = TokenNameREMAINDER;
56 scanner.recordLineSeparator = false;
58 public void goForCompilationUnit() {
59 //tells the scanner to go for compilation unit parsing
61 firstToken = TokenNamePLUS_PLUS;
63 scanner.foundTaskCount = 0;
64 scanner.recordLineSeparator = true;
65 // scanner.currentLine= null;
67 public void goForInitializer() {
68 //tells the scanner to go for initializer parsing
70 firstToken = TokenNameRIGHT_SHIFT;
71 scanner.recordLineSeparator = false;
73 public void goForMethodBody() {
74 //tells the scanner to go for method body parsing
76 firstToken = TokenNameMINUS_MINUS;
77 scanner.recordLineSeparator = false;
79 public void initialize(boolean phpMode) {
80 super.initialize(phpMode);
81 //positionning the parser for a new compilation unit
82 //avoiding stack reallocation and all that....
85 // expressionPtr = -1;
86 // expressionLengthPtr = -1;
87 // identifierPtr = -1;
88 // identifierLengthPtr = -1;
90 // nestedMethod[nestedType = 0] = 0; // need to reset for further reuse
91 // variablesCounter[nestedType] = 0;
94 // endStatementPosition = 0;
96 //remove objects from stack too, while the same parser/compiler couple is
97 //re-used between two compilations ....
99 // int astLength = astStack.length;
100 // if (noAstNodes.length < astLength){
101 // noAstNodes = new ASTNode[astLength];
102 // //System.out.println("Resized AST stacks : "+ astLength);
105 // System.arraycopy(noAstNodes, 0, astStack, 0, astLength);
107 // int expressionLength = expressionStack.length;
108 // if (noExpressions.length < expressionLength){
109 // noExpressions = new Expression[expressionLength];
110 // //System.out.println("Resized EXPR stacks : "+ expressionLength);
112 // System.arraycopy(noExpressions, 0, expressionStack, 0, expressionLength);
114 // reset scanner state
115 scanner.commentPtr = -1;
116 scanner.foundTaskCount = 0;
117 scanner.eofPosition = Integer.MAX_VALUE;
122 // lastCheckPoint = -1;
123 // currentElement = null;
124 // restartRecovery = false;
125 // hasReportedError = false;
126 // recoveredStaticInitializerStart = 0;
127 // lastIgnoredToken = -1;
128 // lastErrorEndPosition = -1;
134 public CompilationUnitDeclaration parse(ICompilationUnit sourceUnit, CompilationResult compilationResult, boolean phpMode) {
135 // parses a compilation unit and manages error handling (even bugs....)
137 CompilationUnitDeclaration unit;
139 /* automaton initialization */
141 goForCompilationUnit();
143 /* scanner initialization */
144 scanner.setSource(sourceUnit, sourceUnit.getContents());
148 compilationUnit = new CompilationUnitDeclaration(problemReporter, compilationResult, scanner.source.length);
149 // TODO TypeDeclaration test
150 // TypeDeclaration typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult);
151 // typeDecl.sourceStart = 0;
152 // typeDecl.sourceEnd = 10;
153 // typeDecl.name = new char[]{'t', 'e','s','t'};
154 // this.compilationUnit.types = new ArrayList();
155 // this.compilationUnit.types.add(typeDecl);
158 // // TODO jsurfer start
159 // if (sourceUnit instanceof BasicCompilationUnit) {
160 // storeProblemsFor(((BasicCompilationUnit)sourceUnit).getResource(), compilationResult.getAllProblems());
165 unit = compilationUnit;
166 compilationUnit = null; // reset parser
171 * Creates a marker from each problem and adds it to the resource.
172 * The marker is as follows:
173 * - its type is T_PROBLEM
174 * - its plugin ID is the JavaBuilder's plugin ID
175 * - its message is the problem's message
176 * - its priority reflects the severity of the problem
177 * - its range is the problem's range
178 * - it has an extra attribute "ID" which holds the problem's id
180 protected void storeProblemsFor(IResource resource, IProblem[] problems) throws CoreException {
181 if (resource == null || problems == null || problems.length == 0)
184 for (int i = 0, l = problems.length; i < l; i++) {
185 IProblem problem = problems[i];
186 int id = problem.getID();
187 if (id != IProblem.Task) {
188 IMarker marker = resource.createMarker(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER);
189 marker.setAttributes(
197 IJavaModelMarker.ARGUMENTS },
199 problem.getMessage(),
200 new Integer(problem.isError() ? IMarker.SEVERITY_ERROR : IMarker.SEVERITY_WARNING),
202 new Integer(problem.getSourceStart()),
203 new Integer(problem.getSourceEnd() + 1),
204 new Integer(problem.getSourceLineNumber()),
205 net.sourceforge.phpdt.internal.core.util.Util.getProblemArgumentsForMarker(problem.getArguments())});
214 public void parse(ConstructorDeclaration cd, CompilationUnitDeclaration unit) {
215 //only parse the method body of cd
216 //fill out its statements
218 //convert bugs into parse error
221 goForConstructorBody();
222 nestedMethod[nestedType]++;
224 referenceContext = cd;
225 compilationUnit = unit;
227 scanner.resetTo(cd.sourceEnd + 1, cd.declarationSourceEnd);
230 } catch (AbortCompilation ex) {
231 lastAct = ERROR_ACTION;
234 nestedMethod[nestedType]--;
237 if (lastAct == ERROR_ACTION) {
243 // cd.explicitDeclarations = realBlockStack[realBlockPtr--];
245 // if ((length = astLengthStack[astLengthPtr--]) != 0) {
247 // if (astStack[astPtr + 1] instanceof ExplicitConstructorCall)
248 // //avoid a isSomeThing that would only be used here BUT what is faster between two alternatives ?
253 // cd.statements = new Statement[length - 1],
256 // cd.constructorCall = (ExplicitConstructorCall) astStack[astPtr + 1];
257 // } else { //need to add explicitly the super();
261 // cd.statements = new Statement[length],
264 // cd.constructorCall = SuperReference.implicitSuperConstructorCall();
267 // cd.constructorCall = SuperReference.implicitSuperConstructorCall();
270 // if (cd.constructorCall.sourceEnd == 0) {
271 // cd.constructorCall.sourceEnd = cd.sourceEnd;
272 // cd.constructorCall.sourceStart = cd.sourceStart;
277 public void parse(FieldDeclaration field, TypeDeclaration type, CompilationUnitDeclaration unit, char[] initializationSource) {
278 //only parse the initializationSource of the given field
280 //convert bugs into parse error
284 nestedMethod[nestedType]++;
286 referenceContext = type;
287 compilationUnit = unit;
289 scanner.setSource(initializationSource);
290 scanner.resetTo(0, initializationSource.length - 1);
293 } catch (AbortCompilation ex) {
294 lastAct = ERROR_ACTION;
296 nestedMethod[nestedType]--;
299 // if (lastAct == ERROR_ACTION) {
303 // field.initialization = expressionStack[expressionPtr];
305 // // mark field with local type if one was found during parsing
306 // if ((type.bits & ASTNode.HasLocalTypeMASK) != 0) {
307 // field.bits |= ASTNode.HasLocalTypeMASK;
312 public void parse(Initializer ini, TypeDeclaration type, CompilationUnitDeclaration unit) {
313 //only parse the method body of md
314 //fill out method statements
316 //convert bugs into parse error
320 nestedMethod[nestedType]++;
322 referenceContext = type;
323 compilationUnit = unit;
325 scanner.resetTo(ini.sourceStart, ini.sourceEnd); // just on the beginning {
328 } catch (AbortCompilation ex) {
329 lastAct = ERROR_ACTION;
331 nestedMethod[nestedType]--;
334 // if (lastAct == ERROR_ACTION) {
338 // ini.block = ((Initializer) astStack[astPtr]).block;
340 // // mark initializer with local type if one was found during parsing
341 // if ((type.bits & ASTNode.HasLocalTypeMASK) != 0) {
342 // ini.bits |= ASTNode.HasLocalTypeMASK;
347 public void parse(MethodDeclaration md, CompilationUnitDeclaration unit) {
348 // TODO jsurfer - make the parse process work on methods ?
351 // //only parse the method body of md
352 // //fill out method statements
354 // //convert bugs into parse error
356 // if (md.isAbstract())
358 // // if (md.isNative())
360 // // if ((md.modifiers & AccSemicolonBody) != 0)
363 // initialize(false);
364 // goForMethodBody();
365 // nestedMethod[nestedType]++;
367 // referenceContext = md;
368 // compilationUnit = unit;
370 // scanner.resetTo(md.sourceEnd + 1, md.declarationSourceEnd);
372 // // reset the scanner to parser from { down to }
375 // } catch (AbortCompilation ex) {
376 // lastAct = ERROR_ACTION;
378 // nestedMethod[nestedType]--;
381 // // if (lastAct == ERROR_ACTION) {
385 // // //refill statements
386 // // md.explicitDeclarations = realBlockStack[realBlockPtr--];
388 // // if ((length = astLengthStack[astLengthPtr--]) != 0)
389 // // System.arraycopy(
391 // // (astPtr -= length) + 1,
392 // // md.statements = new Statement[length],
399 public CompilationUnitDeclaration parse(ICompilationUnit sourceUnit, CompilationResult compilationResult, int start, int end) {
400 // parses a compilation unit and manages error handling (even bugs....)
402 CompilationUnitDeclaration unit;
404 /* automaton initialization */
406 goForCompilationUnit();
408 /* scanner initialization */
409 scanner.setSource(sourceUnit, sourceUnit.getContents());
410 scanner.resetTo(start, end);
413 compilationUnit = new CompilationUnitDeclaration(problemReporter, compilationResult, scanner.source.length);
417 } catch (SyntaxError syntaxError) {
420 unit = compilationUnit;
421 compilationUnit = null; // reset parser
426 public CompilationUnitDeclaration dietParse(ICompilationUnit sourceUnit, CompilationResult compilationResult) {
427 return dietParse(sourceUnit, compilationResult, false);
429 public CompilationUnitDeclaration dietParse(ICompilationUnit sourceUnit, CompilationResult compilationResult, boolean phpMode) {
431 CompilationUnitDeclaration parsedUnit;
435 parsedUnit = parse(sourceUnit, compilationResult, phpMode);
442 public void getMethodBodies(CompilationUnitDeclaration unit) {
443 //fill the methods bodies in order for the code to be generated
445 if (unit == null) return;
447 if (unit.ignoreMethodBodies) {
448 unit.ignoreFurtherInvestigation = true;
450 // if initial diet parse did not work, no need to dig into method bodies.
453 if ((unit.bits & ASTNode.HasAllMethodBodies) != 0)
454 return; //work already done ...
456 //real parse of the method....
457 char[] contents = unit.compilationResult.compilationUnit.getContents();
458 this.scanner.setSource(contents);
460 // save existing values to restore them at the end of the parsing process
461 // see bug 47079 for more details
462 int[] oldLineEnds = this.scanner.lineEnds;
463 int oldLinePtr = this.scanner.linePtr;
465 final int[] lineSeparatorPositions = unit.compilationResult.lineSeparatorPositions;
466 this.scanner.lineEnds = lineSeparatorPositions;
467 this.scanner.linePtr = lineSeparatorPositions.length - 1;
469 // if (this.javadocParser != null && this.javadocParser.checkDocComment) {
470 // this.javadocParser.scanner.setSource(contents);
472 if (unit.types != null) {
473 for (int i = unit.types.size(); --i >= 0;)
474 ((TypeDeclaration)unit.types.get(i)).parseMethod(this, unit);
477 // tag unit has having read bodies
478 unit.bits |= ASTNode.HasAllMethodBodies;
480 // this is done to prevent any side effects on the compilation unit result
481 // line separator positions array.
482 this.scanner.lineEnds = oldLineEnds;
483 this.scanner.linePtr = oldLinePtr;