/******************************************************************************* * Copyright (c) 2000, 2007 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.wst.jsdt.internal.compiler.parser; /** * Internal field structure for parsing recovery */ import org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode; import org.eclipse.wst.jsdt.internal.compiler.ast.AbstractMethodDeclaration; import org.eclipse.wst.jsdt.internal.compiler.ast.AbstractVariableDeclaration; import org.eclipse.wst.jsdt.internal.compiler.ast.Assignment; import org.eclipse.wst.jsdt.internal.compiler.ast.Block; import org.eclipse.wst.jsdt.internal.compiler.ast.CompilationUnitDeclaration; import org.eclipse.wst.jsdt.internal.compiler.ast.FieldDeclaration; import org.eclipse.wst.jsdt.internal.compiler.ast.FunctionExpression; import org.eclipse.wst.jsdt.internal.compiler.ast.ImportReference; import org.eclipse.wst.jsdt.internal.compiler.ast.LocalDeclaration; import org.eclipse.wst.jsdt.internal.compiler.ast.ProgramElement; import org.eclipse.wst.jsdt.internal.compiler.ast.Statement; import org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration; public class RecoveredUnit extends RecoveredElement { public CompilationUnitDeclaration unitDeclaration; // public RecoveredImport[] imports; // public int importCount; // public RecoveredType[] types; // public int typeCount; public RecoveredElement[] statements; public int statementCount; public RecoveredUnit(CompilationUnitDeclaration unitDeclaration, int bracketBalance, Parser parser){ super(null, bracketBalance, parser); this.unitDeclaration = unitDeclaration; } /* * Record a method declaration: should be attached to last type */ public RecoveredElement add(AbstractMethodDeclaration methodDeclaration, int bracketBalanceValue) { RecoveredMethod element = new RecoveredMethod(methodDeclaration, this, bracketBalanceValue, this.recoveringParser); addStatement(element); /* consider that if the opening brace was not found, it is there */ if (!foundOpeningBrace){ foundOpeningBrace = true; this.bracketBalance++; } /* if method not finished, then method becomes current */ if (methodDeclaration.declarationSourceEnd == 0) return element; return this; } /* * Record a field declaration: should be attached to last type */ public RecoveredElement add(FieldDeclaration fieldDeclaration, int bracketBalanceValue) { RecoveredField element; element = new RecoveredField(fieldDeclaration, this, bracketBalanceValue); addStatement(element); /* consider that if the opening brace was not found, it is there */ if (!foundOpeningBrace){ foundOpeningBrace = true; this.bracketBalance++; } /* if field not finished, then field becomes current */ if (fieldDeclaration.declarationSourceEnd == 0) return element; return this; } public RecoveredElement add(LocalDeclaration localDeclaration, int bracketBalanceValue) { RecoveredLocalVariable element; element = new RecoveredLocalVariable(localDeclaration, this, bracketBalanceValue); addStatement(element); /* consider that if the opening brace was not found, it is there */ if (!foundOpeningBrace){ foundOpeningBrace = true; this.bracketBalance++; } /* if field not finished, then field becomes current */ if (localDeclaration.declarationSourceEnd == 0) return element; return this; } public RecoveredElement add(ImportReference importReference, int bracketBalanceValue) { // if (this.imports == null) { // this.imports = new RecoveredImport[5]; // this.importCount = 0; // } else { // if (this.importCount == this.imports.length) { // System.arraycopy( // this.imports, // 0, // (this.imports = new RecoveredImport[2 * this.importCount]), // 0, // this.importCount); // } // } // RecoveredImport element = new RecoveredImport(importReference, this, bracketBalanceValue); // this.imports[this.importCount++] = element; // // /* if import not finished, then import becomes current */ // if (importReference.declarationSourceEnd == 0) return element; return this; } public RecoveredElement add(TypeDeclaration typeDeclaration, int bracketBalanceValue) { // if ((typeDeclaration.bits & ASTNode.IsAnonymousType) != 0){ // if (this.typeCount > 0) { // // add it to the last type // RecoveredType lastType = this.types[this.typeCount-1]; // lastType.bodyEnd = 0; // reopen type // lastType.typeDeclaration.bodyEnd = 0; // reopen type // lastType.typeDeclaration.declarationSourceEnd = 0; // reopen type // lastType.bracketBalance++; // expect one closing brace // return lastType.add(typeDeclaration, bracketBalanceValue); // } // } // if (this.types == null) { // this.types = new RecoveredType[5]; // this.typeCount = 0; // } else { // if (this.typeCount == this.types.length) { // System.arraycopy( // this.types, // 0, // (this.types = new RecoveredType[2 * this.typeCount]), // 0, // this.typeCount); // } // } // RecoveredType element = new RecoveredType(typeDeclaration, this, bracketBalanceValue); // this.types[this.typeCount++] = element; // // /* if type not finished, then type becomes current */ // if (typeDeclaration.declarationSourceEnd == 0) return element; return this; } private void addStatement(RecoveredElement statement) { if (this.statements == null) { this.statements = new RecoveredElement[5]; this.statementCount = 0; } else { if (this.statementCount == this.statements.length) { System.arraycopy( this.statements, 0, (this.statements = new RecoveredElement[2 * this.statementCount]), 0, this.statementCount); } } this.statements[this.statementCount++] = statement; } /* * Answer the associated parsed structure */ public ASTNode parseTree(){ return this.unitDeclaration; } /* * Answer the very source end of the corresponding parse node */ public int sourceEnd(){ return this.unitDeclaration.sourceEnd; } public String toString(int tab) { StringBuffer result = new StringBuffer(tabString(tab)); result.append("Recovered unit: [\n"); //$NON-NLS-1$ this.unitDeclaration.print(tab + 1, result); result.append(tabString(tab + 1)); result.append("]"); //$NON-NLS-1$ // if (this.imports != null) { // for (int i = 0; i < this.importCount; i++) { // result.append("\n"); //$NON-NLS-1$ // result.append(this.imports[i].toString(tab + 1)); // } // } if (this.statements != null) { for (int i = 0; i < this.statementCount; i++) { result.append("\n"); //$NON-NLS-1$ result.append(this.statements[i].toString(tab + 1)); } } return result.toString(); } public CompilationUnitDeclaration updatedCompilationUnitDeclaration(){ /* update imports */ // if (this.importCount > 0){ // ImportReference[] importRefences = new ImportReference[this.importCount]; // for (int i = 0; i < this.importCount; i++){ // importRefences[i] = this.imports[i].updatedImportReference(); // } // this.unitDeclaration.imports = importRefences; // } /* update types */ int sourceEnd=(this.unitDeclaration.sourceEnd>0)?this.unitDeclaration.sourceEnd:this.parser().scanner.eofPosition; if (this.statementCount > 0){ int existingCount = this.unitDeclaration.statements == null ? 0 : this.unitDeclaration.statements.length; ProgramElement[] stmts = new ProgramElement[existingCount + this.statementCount]; if (existingCount > 0){ System.arraycopy(this.unitDeclaration.statements, 0, stmts, 0, existingCount); } ASTNode astNode = this.statements[this.statementCount - 1].parseTree(); // may need to update the declarationSourceEnd of the last type if (astNode.sourceEnd == 0){ astNode.sourceEnd= sourceEnd; if (astNode instanceof Assignment) { Assignment assign=(Assignment)astNode; if (assign.expression instanceof FunctionExpression) { FunctionExpression functionExpression=(FunctionExpression)assign.expression; functionExpression.sourceEnd=astNode.sourceEnd; functionExpression.methodDeclaration.bodyEnd= functionExpression.methodDeclaration.sourceEnd=astNode.sourceEnd; } } // this.statements[this.statementCount - 1].updateSourceEndIfNecessary(sourceEnd)typeDeclaration.bodyEnd = this.unitDeclaration.sourceEnd; } if (astNode instanceof AbstractMethodDeclaration && ((AbstractMethodDeclaration)astNode).bodyEnd<=0) ((AbstractMethodDeclaration)astNode).bodyEnd=this.unitDeclaration.sourceEnd; int actualCount = existingCount; for (int i = 0; i < this.statementCount; i++){ ProgramElement updatedASTNode = this.statements[i].updatedASTNode(); if (updatedASTNode!=null && updatedASTNode.sourceEnd<=0 ) { updatedASTNode.sourceEnd=this.unitDeclaration.sourceEnd; } if (updatedASTNode instanceof AbstractMethodDeclaration && ((AbstractMethodDeclaration)updatedASTNode).bodyEnd<=0 ) ((AbstractMethodDeclaration)updatedASTNode).bodyEnd=this.unitDeclaration.sourceEnd; else if (updatedASTNode instanceof AbstractVariableDeclaration && ((AbstractVariableDeclaration)updatedASTNode).declarationSourceEnd<=0 ) ((AbstractVariableDeclaration)updatedASTNode).declarationSourceEnd=this.unitDeclaration.sourceEnd; // this.statements[i].updateParseTree(); // filter out local types (12454) // if ((typeDecl.bits & ASTNode.IsLocalType) == 0){ stmts[actualCount++] = updatedASTNode; // } } // if (actualCount != this.statementCount){ // System.arraycopy( // stmts, // 0, // stmts = new ProgramElement[existingCount+actualCount], // 0, // existingCount+actualCount); // } this.unitDeclaration.statements = stmts; } else if (this.unitDeclaration.statements==null) this.unitDeclaration.statements=new ProgramElement[0]; return this.unitDeclaration; } public RecoveredElement add(Block nestedBlockDeclaration, int bracketBalanceValue) { RecoveredBlock element = new RecoveredBlock(nestedBlockDeclaration, this, bracketBalanceValue); // if we have a pending Argument, promote it into the new block // if (this.pendingArgument != null){ // element.attach(this.pendingArgument); // this.pendingArgument = null; // } if(this.parser().statementRecoveryActivated) { this.addBlockStatement(element); } addStatement(element); if (nestedBlockDeclaration.sourceEnd == 0) return element; return this; } public RecoveredElement add(Statement statement, int bracketBalanceValue) { RecoveredStatement element = new RecoveredStatement(statement, this, bracketBalanceValue); addStatement(element); if (statement.sourceEnd == 0) return element; return this; } public void updateParseTree(){ this.updatedCompilationUnitDeclaration(); } /* * Update the sourceEnd of the corresponding parse node */ public void updateSourceEndIfNecessary(int bodyStart, int bodyEnd){ if (this.unitDeclaration.sourceEnd == 0) this.unitDeclaration.sourceEnd = bodyEnd; } public ProgramElement updatedASTNode() { //TODO: implement SHOULD NOT GET HERE throw new org.eclipse.wst.jsdt.core.UnimplementedException(); } public void updateFromParserState() { if (parser().astPtr>=0) { } } }