package net.sourceforge.phpdt.internal.compiler.parser; import net.sourceforge.phpdt.core.IJavaModelMarker; import net.sourceforge.phpdt.core.compiler.IProblem; import net.sourceforge.phpdt.internal.compiler.CompilationResult; import net.sourceforge.phpdt.internal.compiler.env.ICompilationUnit; import net.sourceforge.phpdt.internal.compiler.problem.AbortCompilation; import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter; import net.sourceforge.phpeclipse.internal.compiler.ast.ASTNode; import net.sourceforge.phpeclipse.internal.compiler.ast.CompilationUnitDeclaration; import net.sourceforge.phpeclipse.internal.compiler.ast.ConstructorDeclaration; import net.sourceforge.phpeclipse.internal.compiler.ast.FieldDeclaration; import net.sourceforge.phpeclipse.internal.compiler.ast.Initializer; import net.sourceforge.phpeclipse.internal.compiler.ast.MethodDeclaration; import net.sourceforge.phpeclipse.internal.compiler.ast.TypeDeclaration; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; /** * * */ public class UnitParser extends Parser { public UnitParser(ProblemReporter problemReporter) { //, boolean optimizeStringLiterals, boolean assertMode) { super(problemReporter); nestedMethod = new int[30]; // this.optimizeStringLiterals = optimizeStringLiterals; // this.assertMode = assertMode; // this.initializeScanner(); astLengthStack = new int[50]; // expressionLengthStack = new int[30]; // intStack = new int[50]; // identifierStack = new char[30][]; // identifierLengthStack = new int[30]; // nestedMethod = new int[30]; // realBlockStack = new int[30]; // identifierPositionStack = new long[30]; // variablesCounter = new int[30]; } public void goForConstructorBody() { //tells the scanner to go for compilation unit parsing firstToken = TokenNameEQUAL_EQUAL; scanner.recordLineSeparator = false; } public void goForExpression() { //tells the scanner to go for an expression parsing firstToken = TokenNameREMAINDER; scanner.recordLineSeparator = false; } public void goForCompilationUnit() { //tells the scanner to go for compilation unit parsing firstToken = TokenNamePLUS_PLUS; scanner.linePtr = -1; scanner.foundTaskCount = 0; scanner.recordLineSeparator = true; // scanner.currentLine= null; } public void goForInitializer() { //tells the scanner to go for initializer parsing firstToken = TokenNameRIGHT_SHIFT; scanner.recordLineSeparator = false; } public void goForMethodBody() { //tells the scanner to go for method body parsing firstToken = TokenNameMINUS_MINUS; scanner.recordLineSeparator = false; } public void initialize(boolean phpMode) { super.initialize(phpMode); //positionning the parser for a new compilation unit //avoiding stack reallocation and all that.... // astPtr = -1; // astLengthPtr = -1; // expressionPtr = -1; // expressionLengthPtr = -1; // identifierPtr = -1; // identifierLengthPtr = -1; // intPtr = -1; // nestedMethod[nestedType = 0] = 0; // need to reset for further reuse // variablesCounter[nestedType] = 0; // dimensions = 0 ; // realBlockPtr = -1; // endStatementPosition = 0; //remove objects from stack too, while the same parser/compiler couple is //re-used between two compilations .... // int astLength = astStack.length; // if (noAstNodes.length < astLength){ // noAstNodes = new ASTNode[astLength]; // //System.out.println("Resized AST stacks : "+ astLength); // // } // System.arraycopy(noAstNodes, 0, astStack, 0, astLength); // // int expressionLength = expressionStack.length; // if (noExpressions.length < expressionLength){ // noExpressions = new Expression[expressionLength]; // //System.out.println("Resized EXPR stacks : "+ expressionLength); // } // System.arraycopy(noExpressions, 0, expressionStack, 0, expressionLength); // reset scanner state scanner.commentPtr = -1; scanner.foundTaskCount = 0; scanner.eofPosition = Integer.MAX_VALUE; // resetModifiers(); // // // recovery // lastCheckPoint = -1; // currentElement = null; // restartRecovery = false; // hasReportedError = false; // recoveredStaticInitializerStart = 0; // lastIgnoredToken = -1; // lastErrorEndPosition = -1; // listLength = 0; } // A P I public CompilationUnitDeclaration parse(ICompilationUnit sourceUnit, CompilationResult compilationResult, boolean phpMode) { // parses a compilation unit and manages error handling (even bugs....) CompilationUnitDeclaration unit; try { /* automaton initialization */ initialize(phpMode); goForCompilationUnit(); /* scanner initialization */ scanner.setSource(sourceUnit, sourceUnit.getContents()); /* unit creation */ referenceContext = compilationUnit = new CompilationUnitDeclaration(problemReporter, compilationResult, scanner.source.length); // TODO TypeDeclaration test // TypeDeclaration typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult); // typeDecl.sourceStart = 0; // typeDecl.sourceEnd = 10; // typeDecl.name = new char[]{'t', 'e','s','t'}; // this.compilationUnit.types = new ArrayList(); // this.compilationUnit.types.add(typeDecl); /* run automaton */ super.parse(); // // TODO jsurfer start // if (sourceUnit instanceof BasicCompilationUnit) { // storeProblemsFor(((BasicCompilationUnit)sourceUnit).getResource(), compilationResult.getAllProblems()); // } // // jsurfer end } finally { unit = compilationUnit; compilationUnit = null; // reset parser } return unit; } /** * Creates a marker from each problem and adds it to the resource. * The marker is as follows: * - its type is T_PROBLEM * - its plugin ID is the JavaBuilder's plugin ID * - its message is the problem's message * - its priority reflects the severity of the problem * - its range is the problem's range * - it has an extra attribute "ID" which holds the problem's id */ protected void storeProblemsFor(IResource resource, IProblem[] problems) throws CoreException { if (resource == null || problems == null || problems.length == 0) return; for (int i = 0, l = problems.length; i < l; i++) { IProblem problem = problems[i]; int id = problem.getID(); if (id != IProblem.Task) { IMarker marker = resource.createMarker(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER); marker.setAttributes( new String[] { IMarker.MESSAGE, IMarker.SEVERITY, IJavaModelMarker.ID, IMarker.CHAR_START, IMarker.CHAR_END, IMarker.LINE_NUMBER, IJavaModelMarker.ARGUMENTS }, new Object[] { problem.getMessage(), new Integer(problem.isError() ? IMarker.SEVERITY_ERROR : IMarker.SEVERITY_WARNING), new Integer(id), new Integer(problem.getSourceStart()), new Integer(problem.getSourceEnd() + 1), new Integer(problem.getSourceLineNumber()), net.sourceforge.phpdt.internal.core.util.Util.getProblemArgumentsForMarker(problem.getArguments())}); } } } // A P I public void parse(ConstructorDeclaration cd, CompilationUnitDeclaration unit) { //only parse the method body of cd //fill out its statements //convert bugs into parse error initialize(false); goForConstructorBody(); nestedMethod[nestedType]++; referenceContext = cd; compilationUnit = unit; scanner.resetTo(cd.sourceEnd + 1, cd.declarationSourceEnd); try { parse(); } catch (AbortCompilation ex) { lastAct = ERROR_ACTION; } finally { nestedMethod[nestedType]--; } if (lastAct == ERROR_ACTION) { initialize(false); return; } //statements // cd.explicitDeclarations = realBlockStack[realBlockPtr--]; // int length; // if ((length = astLengthStack[astLengthPtr--]) != 0) { // astPtr -= length; // if (astStack[astPtr + 1] instanceof ExplicitConstructorCall) // //avoid a isSomeThing that would only be used here BUT what is faster between two alternatives ? // { // System.arraycopy( // astStack, // astPtr + 2, // cd.statements = new Statement[length - 1], // 0, // length - 1); // cd.constructorCall = (ExplicitConstructorCall) astStack[astPtr + 1]; // } else { //need to add explicitly the super(); // System.arraycopy( // astStack, // astPtr + 1, // cd.statements = new Statement[length], // 0, // length); // cd.constructorCall = SuperReference.implicitSuperConstructorCall(); // } // } else { // cd.constructorCall = SuperReference.implicitSuperConstructorCall(); // } // // if (cd.constructorCall.sourceEnd == 0) { // cd.constructorCall.sourceEnd = cd.sourceEnd; // cd.constructorCall.sourceStart = cd.sourceStart; // } } // A P I public void parse(FieldDeclaration field, TypeDeclaration type, CompilationUnitDeclaration unit, char[] initializationSource) { //only parse the initializationSource of the given field //convert bugs into parse error initialize(false); goForExpression(); nestedMethod[nestedType]++; referenceContext = type; compilationUnit = unit; scanner.setSource(initializationSource); scanner.resetTo(0, initializationSource.length - 1); try { parse(); } catch (AbortCompilation ex) { lastAct = ERROR_ACTION; } finally { nestedMethod[nestedType]--; } // if (lastAct == ERROR_ACTION) { // return; // } // // field.initialization = expressionStack[expressionPtr]; // // // mark field with local type if one was found during parsing // if ((type.bits & ASTNode.HasLocalTypeMASK) != 0) { // field.bits |= ASTNode.HasLocalTypeMASK; // } } // A P I public void parse(Initializer ini, TypeDeclaration type, CompilationUnitDeclaration unit) { //only parse the method body of md //fill out method statements //convert bugs into parse error initialize(false); goForInitializer(); nestedMethod[nestedType]++; referenceContext = type; compilationUnit = unit; scanner.resetTo(ini.sourceStart, ini.sourceEnd); // just on the beginning { try { parse(); } catch (AbortCompilation ex) { lastAct = ERROR_ACTION; } finally { nestedMethod[nestedType]--; } // if (lastAct == ERROR_ACTION) { // return; // } // // ini.block = ((Initializer) astStack[astPtr]).block; // // // mark initializer with local type if one was found during parsing // if ((type.bits & ASTNode.HasLocalTypeMASK) != 0) { // ini.bits |= ASTNode.HasLocalTypeMASK; // } } // A P I public void parse(MethodDeclaration md, CompilationUnitDeclaration unit) { // TODO jsurfer - make the parse process work on methods ? return; // //only parse the method body of md // //fill out method statements // // //convert bugs into parse error // // if (md.isAbstract()) // return; // // if (md.isNative()) // // return; // // if ((md.modifiers & AccSemicolonBody) != 0) // // return; // // initialize(false); // goForMethodBody(); // nestedMethod[nestedType]++; // // referenceContext = md; // compilationUnit = unit; // // scanner.resetTo(md.sourceEnd + 1, md.declarationSourceEnd); // // // reset the scanner to parser from { down to } // try { // parse(); // } catch (AbortCompilation ex) { // lastAct = ERROR_ACTION; // } finally { // nestedMethod[nestedType]--; // } // // // if (lastAct == ERROR_ACTION) { // // return; // // } // // // // //refill statements // // md.explicitDeclarations = realBlockStack[realBlockPtr--]; // // int length; // // if ((length = astLengthStack[astLengthPtr--]) != 0) // // System.arraycopy( // // astStack, // // (astPtr -= length) + 1, // // md.statements = new Statement[length], // // 0, // // length); } // A P I public CompilationUnitDeclaration parse(ICompilationUnit sourceUnit, CompilationResult compilationResult, int start, int end) { // parses a compilation unit and manages error handling (even bugs....) CompilationUnitDeclaration unit; try { /* automaton initialization */ initialize(false); goForCompilationUnit(); /* scanner initialization */ scanner.setSource(sourceUnit, sourceUnit.getContents()); scanner.resetTo(start, end); /* unit creation */ referenceContext = compilationUnit = new CompilationUnitDeclaration(problemReporter, compilationResult, scanner.source.length); /* run automaton */ parse(); } catch (SyntaxError syntaxError) { // } finally { unit = compilationUnit; compilationUnit = null; // reset parser } return unit; } public CompilationUnitDeclaration dietParse(ICompilationUnit sourceUnit, CompilationResult compilationResult) { return dietParse(sourceUnit, compilationResult, false); } public CompilationUnitDeclaration dietParse(ICompilationUnit sourceUnit, CompilationResult compilationResult, boolean phpMode) { CompilationUnitDeclaration parsedUnit; boolean old = diet; try { diet = true; parsedUnit = parse(sourceUnit, compilationResult, phpMode); } finally { diet = old; } return parsedUnit; } public void getMethodBodies(CompilationUnitDeclaration unit) { //fill the methods bodies in order for the code to be generated if (unit == null) return; if (unit.ignoreMethodBodies) { unit.ignoreFurtherInvestigation = true; return; // if initial diet parse did not work, no need to dig into method bodies. } if ((unit.bits & ASTNode.HasAllMethodBodies) != 0) return; //work already done ... //real parse of the method.... char[] contents = unit.compilationResult.compilationUnit.getContents(); this.scanner.setSource(contents); // save existing values to restore them at the end of the parsing process // see bug 47079 for more details int[] oldLineEnds = this.scanner.lineEnds; int oldLinePtr = this.scanner.linePtr; final int[] lineSeparatorPositions = unit.compilationResult.lineSeparatorPositions; this.scanner.lineEnds = lineSeparatorPositions; this.scanner.linePtr = lineSeparatorPositions.length - 1; // if (this.javadocParser != null && this.javadocParser.checkDocComment) { // this.javadocParser.scanner.setSource(contents); // } if (unit.types != null) { for (int i = unit.types.size(); --i >= 0;) ((TypeDeclaration)unit.types.get(i)).parseMethod(this, unit); } // tag unit has having read bodies unit.bits |= ASTNode.HasAllMethodBodies; // this is done to prevent any side effects on the compilation unit result // line separator positions array. this.scanner.lineEnds = oldLineEnds; this.scanner.linePtr = oldLinePtr; } }