Download
Getting Started
Members
Projects
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
More
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
Toggle navigation
Bugzilla – Attachment 33154 Details for
Bug 42253
[plan][dom/ast] Make AST more robust against syntax errors
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
Log In
[x]
|
Terms of Use
|
Copyright Agent
[patch]
Released code
patch014bugzilla.txt (text/plain), 122.75 KB, created by
David Audel
on 2006-01-17 13:44:19 EST
(
hide
)
Description:
Released code
Filename:
MIME Type:
Creator:
David Audel
Created:
2006-01-17 13:44:19 EST
Size:
122.75 KB
patch
obsolete
>### Eclipse Workspace Patch 1.0 >#P org.eclipse.jdt.core >Index: model/org/eclipse/jdt/internal/compiler/DocumentElementParser.java >=================================================================== >RCS file: /home/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/DocumentElementParser.java,v >retrieving revision 1.20 >diff -u -r1.20 DocumentElementParser.java >--- model/org/eclipse/jdt/internal/compiler/DocumentElementParser.java 11 Nov 2005 23:44:39 -0000 1.20 >+++ model/org/eclipse/jdt/internal/compiler/DocumentElementParser.java 17 Jan 2006 17:44:48 -0000 >@@ -62,6 +62,8 @@ > intArrayStack = new int[30][]; > this.options = options; > this.javadocParser.checkDocComment = false; >+ >+ this.setStatementsRecovery(false); > } > /* > * Will clear the comment stack when looking >Index: dom/org/eclipse/jdt/core/dom/ASTParser.java >=================================================================== >RCS file: /home/eclipse/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTParser.java,v >retrieving revision 1.48 >diff -u -r1.48 ASTParser.java >--- dom/org/eclipse/jdt/core/dom/ASTParser.java 17 Dec 2005 01:20:00 -0000 1.48 >+++ dom/org/eclipse/jdt/core/dom/ASTParser.java 17 Jan 2006 17:44:42 -0000 >@@ -26,6 +26,9 @@ > import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration; > import org.eclipse.jdt.internal.compiler.ast.Statement; > import org.eclipse.jdt.internal.compiler.env.IBinaryType; >+import org.eclipse.jdt.internal.compiler.parser.RecoveryScanner; >+import org.eclipse.jdt.internal.compiler.parser.RecoveryScannerData; >+import org.eclipse.jdt.internal.compiler.parser.Scanner; > import org.eclipse.jdt.internal.compiler.util.SuffixConstants; > import org.eclipse.jdt.internal.core.*; > import org.eclipse.jdt.internal.core.util.CodeSnippetParsingUtil; >@@ -914,7 +917,15 @@ > } > switch(this.astKind) { > case K_STATEMENTS : >- ConstructorDeclaration constructorDeclaration = codeSnippetParsingUtil.parseStatements(this.rawSource, this.sourceOffset, this.sourceLength, this.compilerOptions, true); >+ ConstructorDeclaration constructorDeclaration = codeSnippetParsingUtil.parseStatements(this.rawSource, this.sourceOffset, this.sourceLength, this.compilerOptions, true, true); >+ RecoveryScannerData data = constructorDeclaration.compilationResult.recoveryScannerData; >+ if(data != null) { >+ Scanner scanner = converter.scanner; >+ converter.scanner = new RecoveryScanner(scanner, data.removeUnused()); >+ converter.docParser.scanner = converter.scanner; >+ converter.scanner.setSource(scanner.source); >+ >+ } > RecordedParsingInformation recordedParsingInformation = codeSnippetParsingUtil.recordedParsingInformation; > int[][] comments = recordedParsingInformation.commentPositions; > if (comments != null) { >@@ -1000,6 +1011,8 @@ > private void propagateErrors(ASTNode astNode, IProblem[] problems) { > ASTSyntaxErrorPropagator syntaxErrorPropagator = new ASTSyntaxErrorPropagator(problems); > astNode.accept(syntaxErrorPropagator); >+ ASTRecoveryPropagator recoveryPropagator = new ASTRecoveryPropagator(problems); >+ astNode.accept(recoveryPropagator); > } > > private void rootNodeToCompilationUnit(AST ast, CompilationUnit compilationUnit, ASTNode node, RecordedParsingInformation recordedParsingInformation) { >Index: dom/org/eclipse/jdt/core/dom/ASTNode.java >=================================================================== >RCS file: /home/eclipse/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTNode.java,v >retrieving revision 1.66 >diff -u -r1.66 ASTNode.java >--- dom/org/eclipse/jdt/core/dom/ASTNode.java 17 Dec 2005 03:50:29 -0000 1.66 >+++ dom/org/eclipse/jdt/core/dom/ASTNode.java 17 Jan 2006 17:44:41 -0000 >@@ -1034,6 +1034,17 @@ > public static final int PROTECT = 4; > > /** >+ * Flag constant (bit mask, value 8) indicating that this node >+ * or a part of this node is recovered from source that contains >+ * a syntax error detected in the vicinity. >+ * <p> >+ * The standard parser (<code>ASTParser</code>) sets this >+ * flag on a node to indicate a recovered node. >+ * </p> >+ */ >+ public static final int RECOVERED = 8; >+ >+ /** > * int containing the node type in the top 16 bits and > * flags in the bottom 16 bits; none set by default. > * <p> >Index: dom/org/eclipse/jdt/core/dom/DefaultASTVisitor.java >=================================================================== >RCS file: /home/eclipse/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultASTVisitor.java,v >retrieving revision 1.2 >diff -u -r1.2 DefaultASTVisitor.java >--- dom/org/eclipse/jdt/core/dom/DefaultASTVisitor.java 23 Feb 2005 02:47:27 -0000 1.2 >+++ dom/org/eclipse/jdt/core/dom/DefaultASTVisitor.java 17 Jan 2006 17:44:42 -0000 >@@ -18,6 +18,14 @@ > public DefaultASTVisitor() { > super(); > } >+ >+ /** >+ * >+ */ >+ public DefaultASTVisitor(boolean visitDocTags) { >+ super(visitDocTags); >+ } >+ > protected boolean visitNode(ASTNode node) { > return true; > } >Index: dom/org/eclipse/jdt/core/dom/ASTConverter.java >=================================================================== >RCS file: /home/eclipse/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTConverter.java,v >retrieving revision 1.223 >diff -u -r1.223 ASTConverter.java >--- dom/org/eclipse/jdt/core/dom/ASTConverter.java 10 Jan 2006 21:01:06 -0000 1.223 >+++ dom/org/eclipse/jdt/core/dom/ASTConverter.java 17 Jan 2006 17:44:40 -0000 >@@ -46,6 +46,7 @@ > import org.eclipse.jdt.internal.compiler.lookup.BlockScope; > import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers; > import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; >+import org.eclipse.jdt.internal.compiler.parser.RecoveryScanner; > import org.eclipse.jdt.internal.compiler.parser.Scanner; > import org.eclipse.jdt.internal.compiler.parser.TerminalTokens; > >@@ -1190,6 +1191,10 @@ > } > > public CompilationUnit convert(org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration unit, char[] source) { >+ if(unit.compilationResult.recoveryScannerData != null) { >+ this.scanner = new RecoveryScanner(this.scanner, unit.compilationResult.recoveryScannerData.removeUnused()); >+ this.docParser.scanner = this.scanner; >+ } > this.compilationUnitSource = source; > this.compilationUnitSourceLength = source.length; > this.scanner.setSource(source, unit.compilationResult); >@@ -1248,6 +1253,8 @@ > } > ASTSyntaxErrorPropagator syntaxErrorPropagator = new ASTSyntaxErrorPropagator(resizedProblems); > compilationUnit.accept(syntaxErrorPropagator); >+ ASTRecoveryPropagator recoveryPropagator = new ASTRecoveryPropagator(resizedProblems); >+ compilationUnit.accept(recoveryPropagator); > compilationUnit.setProblems(resizedProblems); > } > if (this.resolveBindings) { >@@ -4237,23 +4244,6 @@ > return; > } > break; >- case TerminalTokens.TokenNameLBRACE : >- count++; >- break; >- case TerminalTokens.TokenNameRBRACE : >- count--; >- break; >- case TerminalTokens.TokenNameLPAREN : >- count++; >- break; >- case TerminalTokens.TokenNameRPAREN : >- count--; >- break; >- case TerminalTokens.TokenNameLBRACKET : >- count++; >- break; >- case TerminalTokens.TokenNameRBRACKET : >- count--; > } > } > } catch(InvalidInputException e) { >Index: compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java >=================================================================== >RCS file: /home/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java,v >retrieving revision 1.330 >diff -u -r1.330 Parser.java >--- compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java 25 Nov 2005 16:44:45 -0000 1.330 >+++ compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java 17 Jan 2006 17:44:28 -0000 >@@ -22,14 +22,18 @@ > > import org.eclipse.jdt.core.compiler.CharOperation; > import org.eclipse.jdt.core.compiler.InvalidInputException; >+import org.eclipse.jdt.internal.compiler.ASTVisitor; > import org.eclipse.jdt.internal.compiler.CompilationResult; > import org.eclipse.jdt.internal.compiler.ast.*; > import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; > import org.eclipse.jdt.internal.compiler.env.ICompilationUnit; > import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; > import org.eclipse.jdt.internal.compiler.impl.ReferenceContext; >+import org.eclipse.jdt.internal.compiler.lookup.BlockScope; >+import org.eclipse.jdt.internal.compiler.lookup.ClassScope; > import org.eclipse.jdt.internal.compiler.lookup.Binding; > import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers; >+import org.eclipse.jdt.internal.compiler.lookup.MethodScope; > import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; > import org.eclipse.jdt.internal.compiler.lookup.TypeIds; > import org.eclipse.jdt.internal.compiler.parser.diagnose.DiagnoseParser; >@@ -76,6 +80,11 @@ > > public static byte rhs[] = null; > >+ public static int[] reverse_index = null; >+ public static char[] recovery_templates_index = null; >+ public static char[] recovery_templates = null; >+ public static char[] statements_recovery_filter = null; >+ > public static long rules_compliance[] = null; > > public static final int RoundBracket = 0; >@@ -171,6 +180,17 @@ > public boolean reportOnlyOneSyntaxError = false; > public boolean reportSyntaxErrorIsRequired = true; > protected boolean restartRecovery; >+ >+ // statement recovery >+// public boolean statementRecoveryEnabled = true; >+ protected boolean methodRecoveryActivated = false; >+ protected boolean statementRecoveryActivated = false; >+ protected TypeDeclaration[] recoveredTypes; >+ protected int recoveredTypePtr; >+ protected int nextTypeStart; >+ >+ public RecoveryScanner recoveryScanner; >+ > //scanner token > public Scanner scanner; > protected int[] stack = new int[StackIncrement]; >@@ -298,6 +318,76 @@ > Collections.sort(entries); > buildFile(file, entries); > } >+private static void buildFilesForRecoveryTemplates( >+ String indexFilename, >+ String templatesFilename, >+ char[] newTerminalIndex, >+ char[] newNonTerminalIndex, >+ String[] newName, >+ char[] newLhs, >+ String[] tokens) throws IOException { >+ >+ int[] newReverse = computeReverseTable(newTerminalIndex, newNonTerminalIndex, newName); >+ >+ char[] newRecoveyTemplatesIndex = new char[newNonTerminalIndex.length]; >+ char[] newRecoveyTemplates = new char[newNonTerminalIndex.length]; >+ int newRecoveyTemplatesPtr = 0; >+ >+ for (int i = 0; i < tokens.length; i = i + 3) { >+ if("3".equals(tokens[i])) { //$NON-NLS-1$ >+ int length = newRecoveyTemplates.length; >+ if(length == newRecoveyTemplatesPtr + 1) { >+ System.arraycopy(newRecoveyTemplates, 0, newRecoveyTemplates = new char[length * 2], 0, length); >+ } >+ newRecoveyTemplates[newRecoveyTemplatesPtr++] = 0; >+ >+ int index = newLhs[Integer.parseInt(tokens[i + 1])]; >+ >+ newRecoveyTemplatesIndex[index] = (char)newRecoveyTemplatesPtr; >+ >+ String token = tokens[i + 2].trim(); >+ java.util.StringTokenizer st = new java.util.StringTokenizer(new String(token), " "); //$NON-NLS-1$ >+ String[] terminalNames = new String[st.countTokens()]; >+ int t = 0; >+ while (st.hasMoreTokens()) { >+ terminalNames[t++] = st.nextToken(); >+ } >+ >+ for (int j = 0; j < terminalNames.length; j++) { >+ int symbol = getSymbol(terminalNames[j], newName, newReverse); >+ if(symbol > -1) { >+ length = newRecoveyTemplates.length; >+ if(length == newRecoveyTemplatesPtr + 1) { >+ System.arraycopy(newRecoveyTemplates, 0, newRecoveyTemplates = new char[length * 2], 0, length); >+ } >+ newRecoveyTemplates[newRecoveyTemplatesPtr++] = (char)symbol; >+ } >+ } >+ } >+ } >+ newRecoveyTemplates[newRecoveyTemplatesPtr++] = 0; >+ System.arraycopy(newRecoveyTemplates, 0, newRecoveyTemplates = new char[newRecoveyTemplatesPtr], 0, newRecoveyTemplatesPtr); >+ >+ buildFileForTable(indexFilename, newRecoveyTemplatesIndex); >+ buildFileForTable(templatesFilename, newRecoveyTemplates); >+} >+private static void buildFilesForStatementsRecoveryFilter( >+ String filename, >+ char[] newNonTerminalIndex, >+ char[] newLhs, >+ String[] tokens) throws IOException { >+ >+ char[] newStatementsRecoveryFilter = new char[newNonTerminalIndex.length]; >+ >+ for (int i = 0; i < tokens.length; i = i + 3) { >+ if("4".equals(tokens[i])) { //$NON-NLS-1$ >+ int index = newLhs[Integer.parseInt(tokens[i + 1])]; >+ >+ newStatementsRecoveryFilter[index] = 1; >+ } >+ } >+ buildFileForTable(filename, newStatementsRecoveryFilter); >+ } > private static void buildFileForCompliance( > String file, > int length, >@@ -450,7 +540,7 @@ > buildFileOfIntFor(prefix + (++i) + ".rsc", "asr", tokens); //$NON-NLS-2$ //$NON-NLS-1$ > buildFileOfIntFor(prefix + (++i) + ".rsc", "nasb", tokens); //$NON-NLS-2$ //$NON-NLS-1$ > buildFileOfIntFor(prefix + (++i) + ".rsc", "nasr", tokens); //$NON-NLS-2$ //$NON-NLS-1$ >- buildFileOfIntFor(prefix + (++i) + ".rsc", "terminal_index", tokens); //$NON-NLS-2$ //$NON-NLS-1$ >+ char[] newTerminalIndex = buildFileOfIntFor(prefix + (++i) + ".rsc", "terminal_index", tokens); //$NON-NLS-2$ //$NON-NLS-1$ > char[] newNonTerminalIndex = buildFileOfIntFor(prefix + (++i) + ".rsc", "non_terminal_index", tokens); //$NON-NLS-1$ //$NON-NLS-2$ > buildFileOfIntFor(prefix + (++i) + ".rsc", "term_action", tokens); //$NON-NLS-2$ //$NON-NLS-1$ > >@@ -475,7 +565,7 @@ > System.out.println(Messages.parser_incorrectPath); > return; > } >- st = new java.util.StringTokenizer(new String(contents), "\t\n\r=#"); //$NON-NLS-1$ >+ st = new java.util.StringTokenizer(new String(contents), "\t\n\r#"); //$NON-NLS-1$ > tokens = new String[st.countTokens()]; > j = 0; > while (st.hasMoreTokens()) { >@@ -485,6 +575,22 @@ > buildFileForCompliance(prefix + (++i) + ".rsc", newRhs.length, tokens);//$NON-NLS-1$ > buildFileForReadableName(READABLE_NAMES_FILE+".properties", newLhs, newNonTerminalIndex, newName, tokens);//$NON-NLS-1$ > >+ buildFilesForRecoveryTemplates( >+ prefix + (++i) + ".rsc", //$NON-NLS-1$ >+ prefix + (++i) + ".rsc", //$NON-NLS-1$ >+ newTerminalIndex, >+ newNonTerminalIndex, >+ newName, >+ newLhs, >+ tokens); >+ >+ buildFilesForStatementsRecoveryFilter( >+ prefix + (++i) + ".rsc", //$NON-NLS-1$ >+ newNonTerminalIndex, >+ newLhs, >+ tokens); >+ >+ > System.out.println(Messages.parser_moveFiles); > } > public static int in_symbol(int state) { >@@ -526,6 +632,13 @@ > > readableName = readReadableNameTable(READABLE_NAMES_FILE_NAME); > >+ reverse_index = computeReverseTable(terminal_index, non_terminal_index, name); >+ >+ recovery_templates_index = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$ >+ recovery_templates = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$ >+ >+ statements_recovery_filter = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$ >+ > base_action = lhs; > } > public static int nasi(int state) { >@@ -537,6 +650,36 @@ > protected static int original_state(int state) { > return -base_check(state); > } >+protected static int[] computeReverseTable(char[] newTerminalIndex, char[] newNonTerminalIndex, String[] newName) { >+ int[] newReverseTable = new int[newName.length]; >+ for (int j = 0; j < newName.length; j++) { >+ found : { >+ for (int k = 0; k < newTerminalIndex.length; k++) { >+ if(newTerminalIndex[k] == j) { >+ newReverseTable[j] = k; >+ break found; >+ } >+ } >+ for (int k = 0; k < newNonTerminalIndex.length; k++) { >+ if(newNonTerminalIndex[k] == j) { >+ newReverseTable[j] = -k; >+ break found; >+ } >+ } >+ } >+ } >+ return newReverseTable; >+} >+ >+private static int getSymbol(String terminalName, String[] newName, int[] newReverse) { >+ for (int j = 0; j < newName.length; j++) { >+ if(terminalName.equals(newName[j])) { >+ return newReverse[j]; >+ } >+ } >+ return -1; >+} >+ > protected static byte[] readByteTable(String filename) throws java.io.IOException { > > //files are located at Parser.class directory >@@ -703,6 +846,8 @@ > > // javadoc support > this.javadocParser = new JavadocParser(this); >+ >+// this.statementRecoveryEnabled = this.options.performStatementsRecovery; > } > protected void annotationRecoveryCheckPoint(int start, int end) { > if(this.lastCheckPoint > start && this.lastCheckPoint < end) { >@@ -768,6 +913,9 @@ > if (this.referenceContext instanceof AbstractMethodDeclaration){ > element = new RecoveredMethod((AbstractMethodDeclaration) this.referenceContext, null, 0, this); > this.lastCheckPoint = ((AbstractMethodDeclaration) this.referenceContext).bodyStart; >+ if(this.statementRecoveryActivated) { >+ element = element.add(new Block(0), 0); >+ } > } else { > /* Initializer bodies are parsed in the context of the type declaration, we must thus search it inside */ > if (this.referenceContext instanceof TypeDeclaration){ >@@ -845,6 +993,29 @@ > element = element.add(importRef, 0); > this.lastCheckPoint = importRef.declarationSourceEnd + 1; > } >+ if(this.statementRecoveryActivated) { >+ if(node instanceof Block) { >+ Block block = (Block) node; >+ element = element.add(block, 0); >+ this.lastCheckPoint = block.sourceEnd + 1; >+ } else if(node instanceof LocalDeclaration) { >+ LocalDeclaration statement = (LocalDeclaration) node; >+ element = element.add(statement, 0); >+ this.lastCheckPoint = statement.sourceEnd + 1; >+ } else if(node instanceof Expression) { >+ Expression statement = (Expression) node; >+ element = element.add(statement, 0); >+ if(statement.statementEnd != -1) { >+ this.lastCheckPoint = statement.statementEnd + 1; >+ } else { >+ this.lastCheckPoint = statement.sourceEnd + 1; >+ } >+ } else if(node instanceof Statement) { >+ Statement statement = (Statement) node; >+ element = element.add(statement, 0); >+ this.lastCheckPoint = statement.sourceEnd + 1; >+ } >+ } > } > return element; > } >@@ -1133,7 +1304,8 @@ > annotationTypeDeclaration.javadoc = this.javadoc; > this.javadoc = null; > pushOnAstStack(annotationTypeDeclaration); >- if(options.sourceLevel < ClassFileConstants.JDK1_5 && >+ if(!this.statementRecoveryActivated && >+ options.sourceLevel < ClassFileConstants.JDK1_5 && > this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) { > this.problemReporter().invalidUsageOfAnnotationDeclarations(annotationTypeDeclaration); > } >@@ -2421,7 +2593,7 @@ > protected void consumeEmptyClassMemberDeclaration() { > // ClassMemberDeclaration ::= ';' > pushOnAstLengthStack(0); >- problemReporter().superfluousSemicolon(this.endPosition+1, this.endStatementPosition); >+ if(!this.statementRecoveryActivated) problemReporter().superfluousSemicolon(this.endPosition+1, this.endStatementPosition); > flushCommentsDefinedPriorTo(this.endStatementPosition); > } > protected void consumeEmptyMethodHeaderDefaultValue() { >@@ -2489,7 +2661,7 @@ > protected void consumeEmptyTypeDeclaration() { > // TypeDeclaration ::= ';' > pushOnAstLengthStack(0); >- problemReporter().superfluousSemicolon(this.endPosition+1, this.endStatementPosition); >+ if(!this.statementRecoveryActivated) problemReporter().superfluousSemicolon(this.endPosition+1, this.endStatementPosition); > flushCommentsDefinedPriorTo(this.endStatementPosition); > } > protected void consumeEnhancedForStatementHeaderInit(boolean hasModifiers) { >@@ -2539,6 +2711,8 @@ > localDeclaration, > this.intStack[this.intPtr--]); > pushOnAstStack(iteratorForStatement); >+ >+ iteratorForStatement.sourceEnd = localDeclaration.declarationSourceEnd; > } > protected void consumeEnhancedForStatementHeader(){ > // EnhancedForStatementHeader ::= EnhancedForStatementHeaderInit ':' Expression ')' >@@ -2547,7 +2721,10 @@ > this.expressionLengthPtr--; > final Expression collection = this.expressionStack[this.expressionPtr--]; > statement.collection = collection; >- if(options.sourceLevel < ClassFileConstants.JDK1_5 && >+ statement.sourceEnd = this.rParenPos; >+ >+ if(!this.statementRecoveryActivated && >+ options.sourceLevel < ClassFileConstants.JDK1_5 && > this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) { > this.problemReporter().invalidUsageOfForeachStatements(statement.elementVariable, collection); > } >@@ -2986,7 +3163,8 @@ > > this.listLength = 0; // will be updated when reading super-interfaces > >- if(options.sourceLevel < ClassFileConstants.JDK1_5 && >+ if(!this.statementRecoveryActivated && >+ options.sourceLevel < ClassFileConstants.JDK1_5 && > this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) { > //TODO this code will be never run while 'enum' is an identifier in 1.3 scanner > this.problemReporter().invalidUsageOfEnumDeclarations(enumDeclaration); >@@ -3146,7 +3324,9 @@ > protected void consumeExpressionStatement() { > // ExpressionStatement ::= StatementExpression ';' > this.expressionLengthPtr--; >- pushOnAstStack(this.expressionStack[this.expressionPtr--]); >+ Expression expression = this.expressionStack[this.expressionPtr--]; >+ expression.statementEnd = this.endStatementPosition; >+ pushOnAstStack(expression); > } > protected void consumeFieldAccess(boolean isSuperAccess) { > // FieldAccess ::= Primary '.' 'Identifier' >@@ -3290,10 +3470,12 @@ > this.listLength++; > > if(isVarArgs) { >- if (options.sourceLevel < ClassFileConstants.JDK1_5 && >+ if (!this.statementRecoveryActivated && >+ options.sourceLevel < ClassFileConstants.JDK1_5 && > this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) { > this.problemReporter().invalidUsageOfVarargs(arg); >- } else if (extendedDimensions > 0) { >+ } else if (!this.statementRecoveryActivated && >+ extendedDimensions > 0) { > this.problemReporter().illegalExtendedDimensions(arg); > } > } >@@ -3570,7 +3752,7 @@ > protected void consumeInvalidAnnotationTypeDeclaration() { > // BlockStatement ::= AnnotationTypeDeclaration > TypeDeclaration typeDecl = (TypeDeclaration) this.astStack[this.astPtr]; >- problemReporter().illegalLocalTypeDeclaration(typeDecl); >+ if(!this.statementRecoveryActivated) problemReporter().illegalLocalTypeDeclaration(typeDecl); > // remove the ast node created in interface header > this.astPtr--; > pushOnAstLengthStack(-1); >@@ -3623,7 +3805,7 @@ > // BlockStatement ::= InvalidInterfaceDeclaration > //InterfaceDeclaration ::= Modifiersopt 'interface' 'Identifier' ExtendsInterfacesopt InterfaceHeader InterfaceBody > TypeDeclaration typeDecl = (TypeDeclaration) this.astStack[this.astPtr]; >- problemReporter().illegalLocalTypeDeclaration(typeDecl); >+ if(!this.statementRecoveryActivated) problemReporter().illegalLocalTypeDeclaration(typeDecl); > // remove the ast node created in interface header > this.astPtr--; > pushOnAstLengthStack(-1); >@@ -3632,7 +3814,7 @@ > protected void consumeInvalidEnumDeclaration() { > // BlockStatement ::= EnumDeclaration > TypeDeclaration typeDecl = (TypeDeclaration) this.astStack[this.astPtr]; >- problemReporter().illegalLocalTypeDeclaration(typeDecl); >+ if(!this.statementRecoveryActivated) problemReporter().illegalLocalTypeDeclaration(typeDecl); > // remove the ast node created in interface header > this.astPtr--; > pushOnAstLengthStack(-1); >@@ -3668,7 +3850,7 @@ > md.declarationSourceEnd = flushCommentsDefinedPriorTo(this.endStatementPosition); > > // report the problem and continue the parsing - narrowing the problem onto the method >- problemReporter().abstractMethodNeedingNoBody(md); >+ if(!this.statementRecoveryActivated) problemReporter().abstractMethodNeedingNoBody(md); > } > protected void consumeLabel() { > // Do nothing >@@ -3728,7 +3910,8 @@ > markerAnnotation = new MarkerAnnotation(typeReference, this.intStack[this.intPtr--]); > markerAnnotation.declarationSourceEnd = markerAnnotation.sourceEnd; > pushOnExpressionStack(markerAnnotation); >- if(options.sourceLevel < ClassFileConstants.JDK1_5 && >+ if(!this.statementRecoveryActivated && >+ options.sourceLevel < ClassFileConstants.JDK1_5 && > this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) { > this.problemReporter().invalidUsageOfAnnotation(markerAnnotation); > } >@@ -4244,7 +4427,8 @@ > annotationRecoveryCheckPoint(normalAnnotation.sourceStart, normalAnnotation.declarationSourceEnd); > } > >- if(options.sourceLevel < ClassFileConstants.JDK1_5 && >+ if(!this.statementRecoveryActivated && >+ options.sourceLevel < ClassFileConstants.JDK1_5 && > this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) { > this.problemReporter().invalidUsageOfAnnotation(normalAnnotation); > } >@@ -4261,7 +4445,8 @@ > this.expressionLengthPtr--; > } > protected void consumeOnlyTypeArguments() { >- if(options.sourceLevel < ClassFileConstants.JDK1_5 && >+ if(!this.statementRecoveryActivated && >+ options.sourceLevel < ClassFileConstants.JDK1_5 && > this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) { > int length = this.genericsLengthStack[this.genericsLengthPtr]; > this.problemReporter().invalidUsageOfTypeArguments( >@@ -6259,7 +6444,8 @@ > annotationRecoveryCheckPoint(singleMemberAnnotation.sourceStart, singleMemberAnnotation.declarationSourceEnd); > } > >- if(options.sourceLevel < ClassFileConstants.JDK1_5 && >+ if(!this.statementRecoveryActivated && >+ options.sourceLevel < ClassFileConstants.JDK1_5 && > this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) { > this.problemReporter().invalidUsageOfAnnotation(singleMemberAnnotation); > } >@@ -6291,7 +6477,8 @@ > //this.endPosition is just before the ; > impt.declarationSourceStart = this.intStack[this.intPtr--]; > >- if(this.options.sourceLevel < ClassFileConstants.JDK1_5 && >+ if(!this.statementRecoveryActivated && >+ this.options.sourceLevel < ClassFileConstants.JDK1_5 && > this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) { > impt.modifiers = ClassFileConstants.AccDefault; // convert the static import reference to a non-static importe reference > this.problemReporter().invalidUsageOfStaticImports(impt); >@@ -6660,7 +6847,8 @@ > //this.endPosition is just before the ; > impt.declarationSourceStart = this.intStack[this.intPtr--]; > >- if(options.sourceLevel < ClassFileConstants.JDK1_5 && >+ if(!this.statementRecoveryActivated && >+ options.sourceLevel < ClassFileConstants.JDK1_5 && > this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) { > impt.modifiers = ClassFileConstants.AccDefault; // convert the static import reference to a non-static importe reference > this.problemReporter().invalidUsageOfStaticImports(impt); >@@ -6762,12 +6950,12 @@ > if (this.scanner.useAssertAsAnIndentifier && > this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) { > long positions = this.identifierPositionStack[this.identifierPtr]; >- problemReporter().useAssertAsAnIdentifier((int) (positions >>> 32), (int) positions); >+ if(!this.statementRecoveryActivated) problemReporter().useAssertAsAnIdentifier((int) (positions >>> 32), (int) positions); > } > if (this.scanner.useEnumAsAnIndentifier && > this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) { > long positions = this.identifierPositionStack[this.identifierPtr]; >- problemReporter().useEnumAsAnIdentifier((int) (positions >>> 32), (int) positions); >+ if(!this.statementRecoveryActivated) problemReporter().useEnumAsAnIdentifier((int) (positions >>> 32), (int) positions); > } > break; > case TokenNameinterface : >@@ -7091,7 +7279,8 @@ > concatGenericsLists(); > intPtr--; > >- if(options.sourceLevel < ClassFileConstants.JDK1_5 && >+ if(!this.statementRecoveryActivated && >+ options.sourceLevel < ClassFileConstants.JDK1_5 && > this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) { > int length = this.genericsLengthStack[this.genericsLengthPtr]; > this.problemReporter().invalidUsageOfTypeArguments( >@@ -7202,7 +7391,8 @@ > } > > >- if(options.sourceLevel < ClassFileConstants.JDK1_5&& >+ if(!this.statementRecoveryActivated && >+ options.sourceLevel < ClassFileConstants.JDK1_5&& > this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) { > int length = this.genericsLengthStack[this.genericsLengthPtr]; > this.problemReporter().invalidUsageOfTypeParameters( >@@ -7298,7 +7488,7 @@ > if (!post) { > this.intPtr--; > } >- problemReporter().invalidUnaryExpression(leftHandSide); >+ if(!this.statementRecoveryActivated) problemReporter().invalidUnaryExpression(leftHandSide); > } > } > protected void consumeVariableDeclarators() { >@@ -7678,14 +7868,18 @@ > > this.lastAct = act; > >- if (this.currentElement != null){ >- this.currentElement.topElement().updateParseTree(); >+ if(this.statementRecoveryActivated) { >+ RecoveredElement recoveredElement = this.buildInitialRecoveryState(); >+ recoveredElement.topElement().updateParseTree(); >+ if(this.hasError) this.resetStacks(); >+ } else if (this.currentElement != null){ > if (VERBOSE_RECOVERY){ > System.out.print(Messages.parser_syntaxRecovery); > System.out.println("--------------------------"); //$NON-NLS-1$ > System.out.println(this.compilationUnit); > System.out.println("----------------------------------"); //$NON-NLS-1$ > } >+ this.currentElement.topElement().updateParseTree(); > } else { > if (this.diet & VERBOSE_RECOVERY){ > System.out.print(Messages.parser_regularParse); >@@ -7696,7 +7890,7 @@ > } > persistLineSeparatorPositions(); > for (int i = 0; i < this.scanner.foundTaskCount; i++){ >- problemReporter().task( >+ if(!this.statementRecoveryActivated) problemReporter().task( > new String(this.scanner.foundTaskTags[i]), > new String(this.scanner.foundTaskMessages[i]), > this.scanner.foundTaskPriorities[i] == null ? null : new String(this.scanner.foundTaskPriorities[i]), >@@ -8187,7 +8381,7 @@ > ArrayInitializer arrayInitializer = (ArrayInitializer) this.expressionStack[this.expressionPtr--]; > this.expressionLengthPtr -- ; > // report a syntax error and abort parsing >- problemReporter().arrayConstantsOnlyInArrayInitializers(arrayInitializer.sourceStart, arrayInitializer.sourceEnd); >+ if(!this.statementRecoveryActivated) problemReporter().arrayConstantsOnlyInArrayInitializers(arrayInitializer.sourceStart, arrayInitializer.sourceEnd); > } > public void initialize() { > this.initialize(false); >@@ -8281,6 +8475,51 @@ > if (this.diet && (this.dietInt == 0)) > this.scanner.diet = true; > } >+private void jumpOverType(){ >+ if (this.recoveredTypes != null && this.nextTypeStart > -1 && this.nextTypeStart < this.scanner.currentPosition) { >+ TypeDeclaration typeDeclaration = this.recoveredTypes[this.recoveredTypePtr]; >+ boolean isAnonymous = typeDeclaration.allocation != null; >+ >+ int end = this.scanner.eofPosition; >+ this.scanner.resetTo(typeDeclaration.declarationSourceEnd + 1, end - 1); >+ if(!isAnonymous) { >+ pushOnAstStack(typeDeclaration); >+ if(this.astLengthPtr > 0) { >+ concatNodeLists(); >+ } >+ >+ if(this.currentElement != null) { >+ this.currentElement = this.currentElement.add(typeDeclaration, 0); >+ } >+ >+ try { >+ this.currentToken = this.scanner.getNextToken(); >+ } catch(InvalidInputException e){ >+ if (!this.hasReportedError){ >+ this.problemReporter().scannerError(this, e.getMessage()); >+ this.hasReportedError = true; >+ } >+ this.lastCheckPoint = this.scanner.currentPosition; >+ } >+ } else { >+ if(this.astPtr > -1 && this.astStack[this.astPtr] instanceof TypeDeclaration) { >+ this.astStack[astPtr] = typeDeclaration; >+ this.expressionStack[this.expressionPtr] = typeDeclaration.allocation; >+ } >+ this.currentToken = TokenNameRBRACE; >+ } >+ >+ if(++this.recoveredTypePtr < this.recoveredTypes.length) { >+ TypeDeclaration nextTypeDeclaration = this.recoveredTypes[this.recoveredTypePtr]; >+ this.nextTypeStart = >+ nextTypeDeclaration.allocation == null >+ ? nextTypeDeclaration.declarationSourceStart >+ : nextTypeDeclaration.bodyStart; >+ } else { >+ this.nextTypeStart = Integer.MAX_VALUE; >+ } >+ } >+} > protected void markEnclosingMemberWithLocalType() { > if (this.currentElement != null) return; // this is already done in the recovery code > for (int i = this.astPtr; i >= 0; i--) { >@@ -8485,6 +8724,7 @@ > protected void parse() { > if (DEBUG) System.out.println("-- ENTER INSIDE PARSE METHOD --"); //$NON-NLS-1$ > boolean isDietParse = this.diet; >+ boolean jumpOverTypeAfterReduce = false; > int oldFirstToken = getFirstToken(); > this.hasError = false; > >@@ -8533,7 +8773,10 @@ > } > this.lastCheckPoint = this.scanner.currentPosition; > this.restartRecovery = true; >- } >+ } >+ if(this.statementRecoveryActivated) { >+ jumpOverTypeAfterReduce = true; >+ } > act -= ERROR_ACTION; > > } else { >@@ -8550,6 +8793,9 @@ > this.lastCheckPoint = this.scanner.currentPosition; > this.restartRecovery = true; > } >+ if(this.statementRecoveryActivated) { >+ this.jumpOverType(); >+ } > continue ProcessTerminals; > } > break ProcessTerminals; >@@ -8560,6 +8806,12 @@ > consumeRule(act); > this.stateStackTop -= (rhs[act] - 1); > act = ntAction(this.stack[this.stateStackTop], lhs[act]); >+ if(this.statementRecoveryActivated && act > NUM_RULES) { >+ if(jumpOverTypeAfterReduce) { >+ this.jumpOverType(); >+ jumpOverTypeAfterReduce = false; >+ } >+ } > } while (act <= NUM_RULES); > } > endParse(act); >@@ -8568,10 +8820,41 @@ > if (tags != null) { > this.compilationUnit.nlsTags = tags; > } >+ > this.scanner.checkNonExternalizedStringLiterals = false; >- if (this.reportSyntaxErrorIsRequired && this.hasError) { >- reportSyntaxErrors(isDietParse, oldFirstToken); >- } >+ if (this.reportSyntaxErrorIsRequired && this.hasError && !this.statementRecoveryActivated) { >+ if(!this.options.performStatementsRecovery) { >+ reportSyntaxErrors(isDietParse, oldFirstToken); >+ } else { >+ RecoveryScannerData data = this.referenceContext.compilationResult().recoveryScannerData; >+ >+ if(this.recoveryScanner == null) { >+ this.recoveryScanner = new RecoveryScanner(this.scanner, data); >+ } else { >+ this.recoveryScanner.setData(data); >+ } >+ >+ this.recoveryScanner.setSource(scanner.source); >+ this.recoveryScanner.lineEnds = this.scanner.lineEnds; >+ this.recoveryScanner.linePtr = this.scanner.linePtr; >+ >+ reportSyntaxErrors(isDietParse, oldFirstToken); >+ >+ if(data == null) { >+ this.referenceContext.compilationResult().recoveryScannerData = >+ this.recoveryScanner.getData(); >+ } >+ >+ if (this.methodRecoveryActivated) { >+ this.methodRecoveryActivated = false; >+ this.recoverStatements(); >+ this.methodRecoveryActivated = true; >+ >+ this.lastAct = ERROR_ACTION; >+ } >+ } >+ } >+ > if (DEBUG) System.out.println("-- EXIT FROM PARSE METHOD --"); //$NON-NLS-1$ > } > public void parse(ConstructorDeclaration cd, CompilationUnitDeclaration unit) { >@@ -8583,6 +8866,11 @@ > > //convert bugs into parse error > >+ boolean oldMethodRecoveryActivated = this.methodRecoveryActivated; >+ if(this.options.performStatementsRecovery) { >+ this.methodRecoveryActivated = true; >+ } >+ > initialize(); > goForBlockStatementsopt(); > if (recordLineSeparator) { >@@ -8601,6 +8889,9 @@ > this.lastAct = ERROR_ACTION; > } finally { > this.nestedMethod[this.nestedType]--; >+ if(this.options.performStatementsRecovery) { >+ this.methodRecoveryActivated = oldMethodRecoveryActivated; >+ } > } > > checkNonNLSAfterBodyEnd(cd.declarationSourceEnd); >@@ -8613,7 +8904,7 @@ > //statements > cd.explicitDeclarations = this.realBlockStack[this.realBlockPtr--]; > int length; >- if ((length = this.astLengthStack[this.astLengthPtr--]) != 0) { >+ if (astLengthPtr > -1 && (length = this.astLengthStack[this.astLengthPtr--]) != 0) { > this.astPtr -= length; > if (this.astStack[this.astPtr + 1] instanceof ExplicitConstructorCall) > //avoid a isSomeThing that would only be used here BUT what is faster between two alternatives ? >@@ -8747,6 +9038,11 @@ > > //convert bugs into parse error > >+ boolean oldMethodRecoveryActivated = this.methodRecoveryActivated; >+ if(this.options.performStatementsRecovery) { >+ this.methodRecoveryActivated = true; >+ } >+ > initialize(); > goForBlockStatementsopt(); > this.nestedMethod[this.nestedType]++; >@@ -8762,6 +9058,9 @@ > this.lastAct = ERROR_ACTION; > } finally { > this.nestedMethod[this.nestedType]--; >+ if(this.options.performStatementsRecovery) { >+ this.methodRecoveryActivated = oldMethodRecoveryActivated; >+ } > } > > checkNonNLSAfterBodyEnd(initializer.declarationSourceEnd); >@@ -8773,7 +9072,7 @@ > //refill statements > initializer.block.explicitDeclarations = this.realBlockStack[this.realBlockPtr--]; > int length; >- if ((length = this.astLengthStack[this.astLengthPtr--]) > 0) { >+ if (astLengthPtr > -1 && (length = this.astLengthStack[this.astLengthPtr--]) > 0) { > System.arraycopy(this.astStack, (this.astPtr -= length) + 1, initializer.block.statements = new Statement[length], 0, length); > } else { > // check whether this block at least contains some comment in it >@@ -8801,6 +9100,11 @@ > if ((md.modifiers & ExtraCompilerModifiers.AccSemicolonBody) != 0) > return; > >+ boolean oldMethodRecoveryActivated = this.methodRecoveryActivated; >+ if(this.options.performStatementsRecovery) { >+ this.methodRecoveryActivated = true; >+ this.rParenPos = md.sourceEnd; >+ } > initialize(); > goForBlockStatementsopt(); > this.nestedMethod[this.nestedType]++; >@@ -8817,6 +9121,9 @@ > this.lastAct = ERROR_ACTION; > } finally { > this.nestedMethod[this.nestedType]--; >+ if(this.options.performStatementsRecovery) { >+ this.methodRecoveryActivated = oldMethodRecoveryActivated; >+ } > } > > checkNonNLSAfterBodyEnd(md.declarationSourceEnd); >@@ -8828,7 +9135,7 @@ > //refill statements > md.explicitDeclarations = this.realBlockStack[this.realBlockPtr--]; > int length; >- if ((length = this.astLengthStack[this.astLengthPtr--]) != 0) { >+ if (astLengthPtr > -1 && (length = this.astLengthStack[this.astLengthPtr--]) != 0) { > System.arraycopy( > this.astStack, > (this.astPtr -= length) + 1, >@@ -8871,7 +9178,7 @@ > return null; > } > int astLength; >- if ((astLength = this.astLengthStack[this.astLengthPtr--]) != 0) { >+ if (astLengthPtr > -1 && (astLength = this.astLengthStack[this.astLengthPtr--]) != 0) { > ASTNode[] result = new ASTNode[astLength]; > this.astPtr -= astLength; > System.arraycopy(this.astStack, this.astPtr + 1, result, 0, astLength); >@@ -8929,11 +9236,67 @@ > > return this.expressionStack[this.expressionPtr]; > } >+public void parseStatements(ReferenceContext rc, int start, int end, TypeDeclaration[] types, CompilationUnitDeclaration unit) { >+ boolean oldStatementRecoveryEnabled = this.statementRecoveryActivated; >+ this.statementRecoveryActivated = true; >+ >+ initialize(); >+ >+ goForBlockStatementsopt(); >+ this.nestedMethod[this.nestedType]++; >+ pushOnRealBlockStack(0); >+ >+ pushOnAstLengthStack(0); >+ >+ this.referenceContext = rc; >+ this.compilationUnit = unit; >+ >+ if(types != null && types.length > 0) { >+ this.recoveredTypes = types; >+ this.recoveredTypePtr = 0; >+ this.nextTypeStart = >+ this.recoveredTypes[0].allocation == null >+ ? this.recoveredTypes[0].declarationSourceStart >+ : this.recoveredTypes[0].bodyStart; >+ } else { >+ this.recoveredTypes = null; >+ this.recoveredTypePtr = -1; >+ this.nextTypeStart = -1; >+ } >+ >+ this.scanner.resetTo(start, end); >+ // reset the scanner to parser from { down to } >+ >+ this.lastCheckPoint = this.scanner.initialPosition; >+ >+ >+ this.stateStackTop = -1; >+ >+ try { >+ parse(); >+ } catch (AbortCompilation ex) { >+ this.lastAct = ERROR_ACTION; >+ } finally { >+ this.nestedMethod[this.nestedType]--; >+ this.recoveredTypes = null; >+ this.statementRecoveryActivated = oldStatementRecoveryEnabled; >+ } >+ >+ checkNonNLSAfterBodyEnd(end); >+} > public void persistLineSeparatorPositions() { > if (this.scanner.recordLineSeparator) { > this.compilationUnit.compilationResult.lineSeparatorPositions = this.scanner.getLineEnds(); > } > } >+/* >+ * Prepares the state of the parser to go for BlockStatements. >+ */ >+protected void prepareForBlockStatements() { >+ this.nestedMethod[this.nestedType = 0] = 1; >+ this.variablesCounter[this.nestedType] = 0; >+ this.realBlockStack[this.realBlockPtr = 1] = 0; >+} > /** > * Returns this parser's problem reporter initialized with its reference context. > * Also it is assumed that a problem is going to be reported, so initializes >@@ -9121,6 +9484,166 @@ > } > this.realBlockStack[this.realBlockPtr] = i; > } >+protected void recoverStatements() { >+ class MethodVisitor extends ASTVisitor { >+ public ASTVisitor typeVisitor; >+ >+ TypeDeclaration enclosingType; // used only for initializer >+ >+ TypeDeclaration[] types = new TypeDeclaration[0]; >+ int typePtr = -1; >+ public boolean visit(ConstructorDeclaration constructorDeclaration, ClassScope scope) { >+ typePtr = -1; >+ return true; >+ } >+ public boolean visit(Initializer initializer, MethodScope scope) { >+ typePtr = -1; >+ return true; >+ } >+ public boolean visit(MethodDeclaration methodDeclaration,ClassScope scope) { >+ typePtr = -1; >+ return true; >+ } >+ public boolean visit(TypeDeclaration typeDeclaration, BlockScope scope) { >+ return this.visit(typeDeclaration); >+ } >+ public boolean visit(TypeDeclaration typeDeclaration, ClassScope scope) { >+ return this.visit(typeDeclaration); >+ } >+ private boolean visit(TypeDeclaration typeDeclaration) { >+ if(this.types.length <= ++this.typePtr) { >+ int length = this.typePtr; >+ System.arraycopy(this.types, 0, this.types = new TypeDeclaration[length * 2 + 1], 0, length); >+ } >+ this.types[this.typePtr] = typeDeclaration; >+ return false; >+ } >+ public void endVisit(ConstructorDeclaration constructorDeclaration, ClassScope scope) { >+ this.endVisitMethod(constructorDeclaration, scope); >+ } >+ public void endVisit(MethodDeclaration methodDeclaration, ClassScope scope) { >+ this.endVisitMethod(methodDeclaration, scope); >+ } >+ private void endVisitMethod(AbstractMethodDeclaration methodDeclaration, ClassScope scope) { >+ TypeDeclaration[] foundTypes = null; >+ int length = 0; >+ if(this.typePtr > -1) { >+ length = this.typePtr + 1; >+ foundTypes = new TypeDeclaration[length]; >+ System.arraycopy(this.types, 0, foundTypes, 0, length); >+ } >+ ReferenceContext oldContext = Parser.this.referenceContext; >+ Parser.this.recoveryScanner.resetTo(methodDeclaration.bodyStart, methodDeclaration.bodyEnd); >+ Scanner oldScanner = Parser.this.scanner; >+ Parser.this.scanner = Parser.this.recoveryScanner; >+ Parser.this.parseStatements( >+ methodDeclaration, >+ methodDeclaration.bodyStart, >+ methodDeclaration.bodyEnd, >+ foundTypes, >+ compilationUnit); >+ Parser.this.scanner = oldScanner; >+ Parser.this.referenceContext = oldContext; >+ >+ for (int i = 0; i < length; i++) { >+ foundTypes[i].traverse(typeVisitor, scope); >+ } >+ } >+ public void endVisit(Initializer initializer, MethodScope scope) { >+ TypeDeclaration[] foundTypes = null; >+ int length = 0; >+ if(this.typePtr > -1) { >+ length = this.typePtr + 1; >+ foundTypes = new TypeDeclaration[length]; >+ System.arraycopy(this.types, 0, foundTypes, 0, length); >+ } >+ ReferenceContext oldContext = Parser.this.referenceContext; >+ Parser.this.recoveryScanner.resetTo(initializer.bodyStart, initializer.bodyEnd); >+ Scanner oldScanner = Parser.this.scanner; >+ Parser.this.scanner = Parser.this.recoveryScanner; >+ Parser.this.parseStatements( >+ this.enclosingType, >+ initializer.bodyStart, >+ initializer.bodyEnd, >+ foundTypes, >+ compilationUnit); >+ Parser.this.scanner = oldScanner; >+ Parser.this.referenceContext = oldContext; >+ >+ for (int i = 0; i < length; i++) { >+ foundTypes[i].traverse(typeVisitor, scope); >+ } >+ } >+ } >+ class TypeVisitor extends ASTVisitor { >+ public MethodVisitor methodVisitor; >+ >+ TypeDeclaration[] types = new TypeDeclaration[0]; >+ int typePtr = -1; >+ >+ public void endVisit(TypeDeclaration typeDeclaration, BlockScope scope) { >+ endVisitType(); >+ } >+ public void endVisit(TypeDeclaration typeDeclaration, ClassScope scope) { >+ endVisitType(); >+ } >+ private void endVisitType() { >+ this.typePtr--; >+ } >+ public boolean visit(TypeDeclaration typeDeclaration, BlockScope scope) { >+ return this.visit(typeDeclaration); >+ } >+ public boolean visit(TypeDeclaration typeDeclaration, ClassScope scope) { >+ return this.visit(typeDeclaration); >+ } >+ private boolean visit(TypeDeclaration typeDeclaration) { >+ if(this.types.length <= ++this.typePtr) { >+ int length = this.typePtr; >+ System.arraycopy(this.types, 0, this.types = new TypeDeclaration[length * 2 + 1], 0, length); >+ } >+ this.types[this.typePtr] = typeDeclaration; >+ return true; >+ } >+ public boolean visit(ConstructorDeclaration constructorDeclaration, ClassScope scope) { >+ if(constructorDeclaration.isDefaultConstructor()) return false; >+ >+ constructorDeclaration.traverse(methodVisitor, scope); >+ return false; >+ } >+ public boolean visit(Initializer initializer, MethodScope scope) { >+ methodVisitor.enclosingType = this.types[typePtr]; >+ initializer.traverse(methodVisitor, scope); >+ return false; >+ } >+ public boolean visit(MethodDeclaration methodDeclaration, ClassScope scope) { >+ methodDeclaration.traverse(methodVisitor, scope); >+ return false; >+ } >+ } >+ >+ MethodVisitor methodVisitor = new MethodVisitor(); >+ TypeVisitor typeVisitor = new TypeVisitor(); >+ methodVisitor.typeVisitor = typeVisitor; >+ typeVisitor.methodVisitor = methodVisitor; >+ >+ if(this.referenceContext instanceof AbstractMethodDeclaration) { >+ ((AbstractMethodDeclaration)this.referenceContext).traverse(methodVisitor, (ClassScope)null); >+ } else if(this.referenceContext instanceof TypeDeclaration) { >+ TypeDeclaration typeContext = (TypeDeclaration)this.referenceContext; >+ >+ int length = typeContext.fields.length; >+ for (int i = 0; i < length; i++) { >+ final FieldDeclaration fieldDeclaration = typeContext.fields[i]; >+ switch(fieldDeclaration.getKind()) { >+ case AbstractVariableDeclaration.INITIALIZER: >+ methodVisitor.enclosingType = typeContext; >+ ((Initializer) fieldDeclaration).traverse(methodVisitor, (MethodScope)null); >+ break; >+ } >+ } >+ } >+} >+ > public void recoveryExitFromVariable() { > if(this.currentElement != null && this.currentElement.parent != null) { > if(this.currentElement instanceof RecoveredLocalVariable) { >@@ -9202,16 +9725,15 @@ > int end = this.scanner.eofPosition <= Integer.MAX_VALUE ? this.scanner.eofPosition - 1 : this.scanner.eofPosition; > if(isDietParse) { > TypeDeclaration[] types = this.compilationUnit.types; >- > int[][] intervalToSkip = org.eclipse.jdt.internal.compiler.parser.diagnose.RangeUtil.computeDietRange(types); > DiagnoseParser diagnoseParser = new DiagnoseParser(this, oldFirstToken, start, end, intervalToSkip[0], intervalToSkip[1], intervalToSkip[2], this.options); >- diagnoseParser.diagnoseParse(); >+ diagnoseParser.diagnoseParse(false); > > reportSyntaxErrorsForSkippedMethod(types); > this.scanner.resetTo(start, end); > } else { > DiagnoseParser diagnoseParser = new DiagnoseParser(this, oldFirstToken, start, end, this.options); >- diagnoseParser.diagnoseParse(); >+ diagnoseParser.diagnoseParse(this.options.performStatementsRecovery); > } > } > private void reportSyntaxErrorsForSkippedMethod(TypeDeclaration[] types){ >@@ -9229,10 +9751,10 @@ > if(method.errorInSignature) { > if(method.isAnnotationMethod()) { > DiagnoseParser diagnoseParser = new DiagnoseParser(this, TokenNameQUESTION, method.declarationSourceStart, method.declarationSourceEnd, this.options); >- diagnoseParser.diagnoseParse(); >+ diagnoseParser.diagnoseParse(this.options.performStatementsRecovery); > } else { > DiagnoseParser diagnoseParser = new DiagnoseParser(this, TokenNameDIVIDE, method.declarationSourceStart, method.declarationSourceEnd, this.options); >- diagnoseParser.diagnoseParse(); >+ diagnoseParser.diagnoseParse(this.options.performStatementsRecovery); > } > > } >@@ -9247,7 +9769,7 @@ > Initializer initializer = (Initializer)fields[j]; > if(initializer.errorInSignature){ > DiagnoseParser diagnoseParser = new DiagnoseParser(this, TokenNameRIGHT_SHIFT, initializer.declarationSourceStart, initializer.declarationSourceEnd, this.options); >- diagnoseParser.diagnoseParse(); >+ diagnoseParser.diagnoseParse(this.options.performStatementsRecovery); > } > } > } >@@ -9292,24 +9814,43 @@ > * decide which grammar goal is activated. > */ > protected boolean resumeAfterRecovery() { >- >- // reset internal stacks >- this.resetStacks(); >- this.resetModifiers(); >+ if(!this.methodRecoveryActivated && !this.statementRecoveryActivated) { >+ >+ // reset internal stacks >+ this.resetStacks(); >+ this.resetModifiers(); >+ >+ /* attempt to move checkpoint location */ >+ if (!this.moveRecoveryCheckpoint()) { >+ return false; >+ } > >- /* attempt to move checkpoint location */ >- if (!this.moveRecoveryCheckpoint()) { >+ // only look for headers >+ if (this.referenceContext instanceof CompilationUnitDeclaration){ >+ goForHeaders(); >+ this.diet = true; // passed this point, will not consider method bodies >+ return true; >+ } >+ >+ // does not know how to restart > return false; >- } >- >- // only look for headers >- if (this.referenceContext instanceof CompilationUnitDeclaration){ >+ } else if(!this.statementRecoveryActivated) { >+ >+ // reset internal stacks >+ this.resetStacks(); >+ this.resetModifiers(); >+ >+ /* attempt to move checkpoint location */ >+ if (!this.moveRecoveryCheckpoint()) { >+ return false; >+ } >+ >+ // only look for headers > goForHeaders(); >- this.diet = true; // passed this point, will not consider method bodies > return true; >+ } else { >+ return false; > } >- // does not know how to restart >- return false; > } > protected boolean resumeOnSyntaxError() { > this.checkExternalizeStrings = false; >@@ -9335,6 +9876,9 @@ > /* attempt to reset state in order to resume to parse loop */ > return this.resumeAfterRecovery(); > } >+public void setStatementsRecovery(boolean enabled) { >+ this.options.performStatementsRecovery = enabled; >+} > public String toString() { > > >Index: compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredMethod.java >=================================================================== >RCS file: /home/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredMethod.java,v >retrieving revision 1.54 >diff -u -r1.54 RecoveredMethod.java >--- compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredMethod.java 10 Jan 2006 14:37:28 -0000 1.54 >+++ compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredMethod.java 17 Jan 2006 17:44:28 -0000 >@@ -207,7 +207,7 @@ > } > return this.parent.add(typeDeclaration, bracketBalanceValue); > } >- if ((typeDeclaration.bits & ASTNode.IsLocalType) != 0){ >+ if ((typeDeclaration.bits & ASTNode.IsLocalType) != 0 || this.parser().methodRecoveryActivated || this.parser().statementRecoveryActivated){ > if (methodBody == null){ > Block block = new Block(0); > block.sourceStart = methodDeclaration.bodyStart; >Index: compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredElement.java >=================================================================== >RCS file: /home/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredElement.java,v >retrieving revision 1.27 >diff -u -r1.27 RecoveredElement.java >--- compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredElement.java 23 Feb 2005 02:47:58 -0000 1.27 >+++ compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredElement.java 17 Jan 2006 17:44:28 -0000 >@@ -106,6 +106,15 @@ > this.updateSourceEndIfNecessary(this.previousAvailableLineEnd(typeDeclaration.declarationSourceStart - 1)); > return this.parent.add(typeDeclaration, bracketBalanceValue); > } >+protected void addBlockStatement(RecoveredBlock recoveredBlock) { >+ Block block = recoveredBlock.blockDeclaration; >+ if(block.statements != null) { >+ Statement[] statements = block.statements; >+ for (int i = 0; i < statements.length; i++) { >+ recoveredBlock.add(statements[i], 0); >+ } >+ } >+} > /* > * Answer the depth of this element, considering the parent link. > */ >Index: compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredBlock.java >=================================================================== >RCS file: /home/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredBlock.java,v >retrieving revision 1.34 >diff -u -r1.34 RecoveredBlock.java >--- compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredBlock.java 10 Jan 2006 14:37:28 -0000 1.34 >+++ compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredBlock.java 17 Jan 2006 17:44:28 -0000 >@@ -33,6 +33,8 @@ > super(block, parent, bracketBalance); > this.blockDeclaration = block; > this.foundOpeningBrace = true; >+ >+ this.preserveContent = this.parser().methodRecoveryActivated || this.parser().statementRecoveryActivated; > } > /* > * Record a nested block declaration >@@ -53,6 +55,9 @@ > element.attach(this.pendingArgument); > this.pendingArgument = null; > } >+ if(this.parser().statementRecoveryActivated) { >+ this.addBlockStatement(element); >+ } > this.attach(element); > if (nestedBlockDeclaration.sourceEnd == 0) return element; > return this; >Index: compiler/org/eclipse/jdt/internal/compiler/parser/Scanner.java >=================================================================== >RCS file: /home/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Scanner.java,v >retrieving revision 1.166 >diff -u -r1.166 Scanner.java >--- compiler/org/eclipse/jdt/internal/compiler/parser/Scanner.java 10 Nov 2005 15:43:36 -0000 1.166 >+++ compiler/org/eclipse/jdt/internal/compiler/parser/Scanner.java 17 Jan 2006 17:44:31 -0000 >@@ -410,7 +410,7 @@ > public int getCurrentTokenEndPosition(){ > return this.currentPosition - 1; > } >-public final char[] getCurrentTokenSource() { >+public char[] getCurrentTokenSource() { > // Return the token REAL source (aka unicodes are precomputed) > > char[] result; >Index: compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredType.java >=================================================================== >RCS file: /home/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredType.java,v >retrieving revision 1.55 >diff -u -r1.55 RecoveredType.java >--- compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredType.java 27 Oct 2005 13:03:07 -0000 1.55 >+++ compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredType.java 17 Jan 2006 17:44:29 -0000 >@@ -57,6 +57,8 @@ > if(this.foundOpeningBrace) { > this.bracketBalance++; > } >+ >+ this.preserveContent = this.parser().methodRecoveryActivated || this.parser().statementRecoveryActivated; > } > public RecoveredElement add(AbstractMethodDeclaration methodDeclaration, int bracketBalanceValue) { > >@@ -311,7 +313,7 @@ > return updatedType; > } > public TypeDeclaration updatedTypeDeclaration(){ >- >+ int lastEnd = typeDeclaration.bodyStart; > /* update member types */ > if (memberTypeCount > 0){ > int existingCount = typeDeclaration.memberTypes == null ? 0 : typeDeclaration.memberTypes.length; >@@ -329,6 +331,9 @@ > memberTypeDeclarations[existingCount + i] = memberTypes[i].updatedTypeDeclaration(); > } > typeDeclaration.memberTypes = memberTypeDeclarations; >+ if(memberTypeDeclarations[memberTypeDeclarations.length - 1].declarationSourceEnd > lastEnd) { >+ lastEnd = memberTypeDeclarations[memberTypeDeclarations.length - 1].declarationSourceEnd; >+ } > } > /* update fields */ > if (fieldCount > 0){ >@@ -347,6 +352,9 @@ > fieldDeclarations[existingCount + i] = fields[i].updatedFieldDeclaration(); > } > typeDeclaration.fields = fieldDeclarations; >+ if(fieldDeclarations[fieldDeclarations.length - 1].declarationSourceEnd > lastEnd) { >+ lastEnd = fieldDeclarations[fieldDeclarations.length - 1].declarationSourceEnd; >+ } > } > /* update methods */ > int existingCount = typeDeclaration.methods == null ? 0 : typeDeclaration.methods.length; >@@ -374,6 +382,9 @@ > methodDeclarations[existingCount + i] = updatedMethod; > } > typeDeclaration.methods = methodDeclarations; >+ if(methodDeclarations[methodDeclarations.length - 1].declarationSourceEnd > lastEnd) { >+ lastEnd = methodDeclarations[methodDeclarations.length - 1].declarationSourceEnd; >+ } > if (hasAbstractMethods) typeDeclaration.bits |= ASTNode.HasAbstractMethods; > hasConstructor = typeDeclaration.checkConstructors(this.parser()); > } else { >@@ -428,6 +439,10 @@ > } else if (parent instanceof RecoveredMethod){ > typeDeclaration.bits |= ASTNode.IsLocalType; > } >+ if(typeDeclaration.declarationSourceEnd == 0) { >+ typeDeclaration.declarationSourceEnd = lastEnd; >+ typeDeclaration.bodyEnd = lastEnd; >+ } > return typeDeclaration; > } > /* >Index: grammar/java_1_5.g >=================================================================== >RCS file: /home/eclipse/org.eclipse.jdt.core/grammar/java_1_5.g,v >retrieving revision 1.58 >diff -u -r1.58 java_1_5.g >--- grammar/java_1_5.g 7 Nov 2005 09:55:39 -0000 1.58 >+++ grammar/java_1_5.g 17 Jan 2006 17:44:44 -0000 >@@ -28,11 +28,15 @@ > > > $readableName >-/.1#$rule_number=./ >+/.1#$rule_number#./ > $compliance >-/.2#$rule_number=./ >+/.2#$rule_number#./ > $recovery >-/.2#$rule_number= recovery./ >+/.2#$rule_number# recovery./ >+$recovery_template >+/.3#$rule_number#./ >+$no_statements_recovery >+/.4#$rule_number# 1./ > -- here it starts really ------------------------------------------ > $Terminals > >@@ -483,6 +487,7 @@ > > ClassBody ::= '{' ClassBodyDeclarationsopt '}' > /:$readableName ClassBody:/ >+/:$no_statements_recovery:/ > > ClassBodyDeclarations ::= ClassBodyDeclaration > ClassBodyDeclarations ::= ClassBodyDeclarations ClassBodyDeclaration >@@ -612,6 +617,7 @@ > MethodHeaderRightParen ::= ')' > /.$putCase consumeMethodHeaderRightParen(); $break ./ > /:$readableName ):/ >+/:$recovery_template ):/ > > MethodHeaderExtendedDims ::= Dimsopt > /.$putCase consumeMethodHeaderExtendedDims(); $break ./ >@@ -656,6 +662,7 @@ > MethodBody ::= NestedMethod '{' BlockStatementsopt '}' > /.$putCase consumeMethodBody(); $break ./ > /:$readableName MethodBody:/ >+/:$no_statements_recovery:/ > > NestedMethod ::= $empty > /.$putCase consumeNestedMethod(); $break ./ >@@ -810,6 +817,7 @@ > ArrayInitializer ::= '{' PushLeftBrace VariableInitializers , '}' > /.$putCase consumeArrayInitializer(); $break ./ > /:$readableName ArrayInitializer:/ >+/:$recovery_template Identifier:/ > > VariableInitializers ::= VariableInitializer > VariableInitializers ::= VariableInitializers ',' VariableInitializer >@@ -1087,9 +1095,11 @@ > PushLPAREN ::= '(' > /.$putCase consumeLeftParen(); $break ./ > /:$readableName (:/ >+/:$recovery_template (:/ > PushRPAREN ::= ')' > /.$putCase consumeRightParen(); $break ./ > /:$readableName ):/ >+/:$recovery_template ):/ > > Primary -> PrimaryNoNewArray > Primary -> ArrayCreationWithArrayInitializer >@@ -1174,6 +1184,7 @@ > /.$putCase consumeClassBodyopt(); $break ./ > ClassBodyopt ::= EnterAnonymousClassBody ClassBody > /:$readableName ClassBody:/ >+/:$no_statements_recovery:/ > > EnterAnonymousClassBody ::= $empty > /.$putCase consumeEnterAnonymousClassBody(); $break ./ >@@ -1448,9 +1459,11 @@ > AssignmentOperator ::= '|=' > /.$putCase consumeAssignmentOperator(OR); $break ./ > /:$readableName AssignmentOperator:/ >+/:$recovery_template =:/ > > Expression -> AssignmentExpression > /:$readableName Expression:/ >+/:$recovery_template Identifier:/ > > -- The following rules are for optional nonterminals. > -- >Index: model/org/eclipse/jdt/internal/core/util/CodeSnippetParsingUtil.java >=================================================================== >RCS file: /home/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/CodeSnippetParsingUtil.java,v >retrieving revision 1.11 >diff -u -r1.11 CodeSnippetParsingUtil.java >--- model/org/eclipse/jdt/internal/core/util/CodeSnippetParsingUtil.java 28 Sep 2005 15:00:15 -0000 1.11 >+++ model/org/eclipse/jdt/internal/core/util/CodeSnippetParsingUtil.java 17 Jan 2006 17:44:49 -0000 >@@ -62,7 +62,8 @@ > new DefaultProblemFactory(Locale.getDefault())); > > CommentRecorderParser parser = new CommentRecorderParser(problemReporter, false); >- >+ parser.setStatementsRecovery(false); >+ > ICompilationUnit sourceUnit = > new CompilationUnit( > source, >@@ -158,11 +159,11 @@ > return result; > } > >- public ConstructorDeclaration parseStatements(char[] source, Map settings, boolean recordParsingInformation) { >- return parseStatements(source, 0, source.length, settings, recordParsingInformation); >+ public ConstructorDeclaration parseStatements(char[] source, Map settings, boolean recordParsingInformation, boolean enabledStatementRecovery) { >+ return parseStatements(source, 0, source.length, settings, recordParsingInformation, enabledStatementRecovery); > } > >- public ConstructorDeclaration parseStatements(char[] source, int offset, int length, Map settings, boolean recordParsingInformation) { >+ public ConstructorDeclaration parseStatements(char[] source, int offset, int length, Map settings, boolean recordParsingInformation, boolean enabledStatementRecovery) { > if (source == null) { > throw new IllegalArgumentException(); > } >@@ -172,6 +173,7 @@ > compilerOptions, > new DefaultProblemFactory(Locale.getDefault())); > CommentRecorderParser parser = new CommentRecorderParser(problemReporter, false); >+ parser.setStatementsRecovery(enabledStatementRecovery); > > ICompilationUnit sourceUnit = > new CompilationUnit( >Index: model/org/eclipse/jdt/core/JavaCore.java >=================================================================== >RCS file: /home/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java,v >retrieving revision 1.523 >diff -u -r1.523 JavaCore.java >--- model/org/eclipse/jdt/core/JavaCore.java 17 Jan 2006 09:35:51 -0000 1.523 >+++ model/org/eclipse/jdt/core/JavaCore.java 17 Jan 2006 17:44:47 -0000 >@@ -657,6 +657,13 @@ > /** > * Possible configurable option ID. > * @see #getDefaultOptions() >+ * @since 3.2 >+ */ >+ //TODO It is a temporary option. It will removed before 3.2 release >+ public static final String COMPILER_STATEMENTS_RECOVERY = PLUGIN_ID + ".compiler.statementsRecovery"; //$NON-NLS-1$ >+ /** >+ * Possible configurable option ID. >+ * @see #getDefaultOptions() > */ > public static final String CORE_JAVA_BUILD_ORDER = PLUGIN_ID + ".computeJavaBuildOrder"; //$NON-NLS-1$ > /** >Index: model/org/eclipse/jdt/internal/core/builder/AbstractImageBuilder.java >=================================================================== >RCS file: /home/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/AbstractImageBuilder.java,v >retrieving revision 1.81 >diff -u -r1.81 AbstractImageBuilder.java >--- model/org/eclipse/jdt/internal/core/builder/AbstractImageBuilder.java 13 Jan 2006 09:19:07 -0000 1.81 >+++ model/org/eclipse/jdt/internal/core/builder/AbstractImageBuilder.java 17 Jan 2006 17:44:49 -0000 >@@ -415,6 +415,7 @@ > > // enable the compiler reference info support > options.produceReferenceInfo = true; >+ options.performStatementsRecovery = false; > > org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment env = newCompiler.lookupEnvironment; > synchronized (env) { >Index: formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatter.java >=================================================================== >RCS file: /home/eclipse/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatter.java,v >retrieving revision 1.52 >diff -u -r1.52 DefaultCodeFormatter.java >--- formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatter.java 9 Sep 2005 15:43:05 -0000 1.52 >+++ formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatter.java 17 Jan 2006 17:44:43 -0000 >@@ -267,7 +267,7 @@ > return this.newCodeFormatter2.format(source, (Block) node); > } > >- ConstructorDeclaration constructorDeclaration = this.codeSnippetParsingUtil.parseStatements(source.toCharArray(), getDefaultCompilerOptions(), true); >+ ConstructorDeclaration constructorDeclaration = this.codeSnippetParsingUtil.parseStatements(source.toCharArray(), getDefaultCompilerOptions(), true, false); > > if (constructorDeclaration.statements == null) { > // a problem occured while parsing the source >@@ -469,7 +469,7 @@ > } > > // probe for statements >- ConstructorDeclaration constructorDeclaration = this.codeSnippetParsingUtil.parseStatements(source.toCharArray(), getDefaultCompilerOptions(), true); >+ ConstructorDeclaration constructorDeclaration = this.codeSnippetParsingUtil.parseStatements(source.toCharArray(), getDefaultCompilerOptions(), true, false); > if (constructorDeclaration.statements != null) { > if (USE_NEW_FORMATTER) { > ASTParser parser = ASTParser.newParser(AST.JLS3); >Index: compiler/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java >=================================================================== >RCS file: /home/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java,v >retrieving revision 1.28 >diff -u -r1.28 ForeachStatement.java >--- compiler/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java 13 Jan 2006 16:37:16 -0000 1.28 >+++ compiler/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java 17 Jan 2006 17:44:20 -0000 >@@ -329,7 +329,7 @@ > scope = new BlockScope(upperScope); > this.elementVariable.resolve(scope); // collection expression can see itemVariable > TypeBinding elementType = this.elementVariable.type.resolvedType; >- TypeBinding collectionType = this.collection.resolveType(scope); >+ TypeBinding collectionType = this.collection == null ? null : this.collection.resolveType(scope); > boolean hasError = elementType == null || collectionType == null; > > if (!hasError) { >Index: compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java >=================================================================== >RCS file: /home/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java,v >retrieving revision 1.91 >diff -u -r1.91 Expression.java >--- compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java 10 Jan 2006 14:37:27 -0000 1.91 >+++ compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java 17 Jan 2006 17:44:20 -0000 >@@ -178,6 +178,8 @@ > > public Constant constant; > >+ public int statementEnd = -1; >+ > //Some expression may not be used - from a java semantic point > //of view only - as statements. Other may. In order to avoid the creation > //of wrappers around expression in order to tune them as expression >Index: compiler/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java >=================================================================== >RCS file: /home/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java,v >retrieving revision 1.58 >diff -u -r1.58 CompilationUnitDeclaration.java >--- compiler/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java 13 Jan 2006 16:37:16 -0000 1.58 >+++ compiler/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java 17 Jan 2006 17:44:19 -0000 >@@ -130,6 +130,9 @@ > localType.enclosingCase = null; > } > } >+ >+ compilationResult.recoveryScannerData = null; // recovery is already done >+ > ClassFile[] classFiles = compilationResult.getClassFiles(); > for (int i = 0, max = classFiles.length; i < max; i++) { > // clear the classFile back pointer to the bindings >Index: compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java >=================================================================== >RCS file: /home/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java,v >retrieving revision 1.278 >diff -u -r1.278 ProblemReporter.java >--- compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java 10 Jan 2006 14:37:28 -0000 1.278 >+++ compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java 17 Jan 2006 17:44:36 -0000 >@@ -2628,6 +2628,8 @@ > public void invalidEnclosingType(Expression expression, TypeBinding type, ReferenceBinding enclosingType) { > > if (enclosingType.isAnonymousType()) enclosingType = enclosingType.superclass(); >+ if (enclosingType.sourceName.length == 0) return; >+ > int flag = IProblem.UndefinedType; // default > switch (type.problemId()) { > case ProblemReasons.NotFound : // 1 >@@ -2675,6 +2677,8 @@ > expression.sourceEnd); > } > public void invalidField(FieldReference fieldRef, TypeBinding searchedType) { >+ if(fieldRef.token.length == 0) return; >+ > int id = IProblem.UndefinedField; > FieldBinding field = fieldRef.binding; > final int sourceStart= (int) (fieldRef.nameSourcePosition >> 32); >@@ -2730,6 +2734,14 @@ > fieldRef.sourceEnd); > } > public void invalidField(NameReference nameRef, FieldBinding field) { >+ if (nameRef instanceof QualifiedNameReference) { >+ QualifiedNameReference ref = (QualifiedNameReference) nameRef; >+ char[] lastToken = ref.tokens[ref.tokens.length - 1]; >+ if (lastToken.length == 0) return; >+ } else { >+ SingleNameReference ref = (SingleNameReference) nameRef; >+ if (ref.token.length == 0) return; >+ } > int id = IProblem.UndefinedField; > switch (field.problemId()) { > case ProblemReasons.NotFound : >@@ -2786,6 +2798,9 @@ > //UndefinedField > //NotVisibleField > //AmbiguousField >+ >+ char[] lastToken = nameRef.tokens[nameRef.tokens.length - 1]; >+ if (lastToken.length == 0) return; > > if (searchedType.isBaseType()) { > this.handle( >@@ -2863,6 +2878,8 @@ > annotation.sourceEnd); > } > public void invalidMethod(MessageSend messageSend, MethodBinding method) { >+ if(messageSend.selector.length == 0) return; >+ > int id = IProblem.UndefinedMethod; //default... > MethodBinding shownMethod = method; > switch (method.problemId()) { >@@ -3148,26 +3165,31 @@ > int end = location.sourceEnd; > if (location instanceof QualifiedNameReference) { > QualifiedNameReference ref = (QualifiedNameReference) location; >+ if(ref.tokens[ref.tokens.length - 1].length == 0) return; > if (ref.indexOfFirstFieldBinding >= 1) > end = (int) ref.sourcePositions[ref.indexOfFirstFieldBinding - 1]; > } else if (location instanceof ArrayQualifiedTypeReference) { > ArrayQualifiedTypeReference arrayQualifiedTypeReference = (ArrayQualifiedTypeReference) location; >+ if(arrayQualifiedTypeReference.tokens[arrayQualifiedTypeReference.tokens.length - 1].length == 0) return; > long[] positions = arrayQualifiedTypeReference.sourcePositions; > end = (int) positions[positions.length - 1]; > } else if (location instanceof QualifiedTypeReference) { > QualifiedTypeReference ref = (QualifiedTypeReference) location; >+ if(ref.tokens[ref.tokens.length - 1].length == 0) return; > if (type instanceof ReferenceBinding) { > char[][] name = ((ReferenceBinding) type).compoundName; > end = (int) ref.sourcePositions[name.length - 1]; > } > } else if (location instanceof ImportReference) { > ImportReference ref = (ImportReference) location; >+ if (ref.tokens[ref.tokens.length - 1].length == 0) return; > if (type instanceof ReferenceBinding) { > char[][] name = ((ReferenceBinding) type).compoundName; > end = (int) ref.sourcePositions[name.length - 1]; > } > } else if (location instanceof ArrayTypeReference) { > ArrayTypeReference arrayTypeReference = (ArrayTypeReference) location; >+ if (arrayTypeReference.token.length == 0) return; > end = arrayTypeReference.originalSourceEnd; > } > this.handle( >@@ -5274,6 +5296,7 @@ > } > public void undefinedAnnotationValue(TypeBinding annotationType, MemberValuePair memberValuePair) { > String name = new String(memberValuePair.name); >+ if(name.length() == 0) return; > this.handle( > IProblem.UndefinedAnnotationMember, > new String[] { name, new String(annotationType.readableName())}, >@@ -5283,6 +5306,7 @@ > } > public void undefinedLabel(BranchStatement statement) { > String[] arguments = new String[] {new String(statement.label)}; >+ if (statement.label.length == 0) return; > this.handle( > IProblem.UndefinedLabel, > arguments, >@@ -5292,6 +5316,7 @@ > } > // can only occur inside binaries > public void undefinedTypeVariableSignature(char[] variableName, ReferenceBinding binaryType) { >+ if(variableName.length == 0) > this.handle( > IProblem.UndefinedTypeVariable, > new String[] {new String(variableName), new String(binaryType.readableName()) }, >@@ -5466,8 +5491,13 @@ > int end = nameRef.sourceEnd; > if (nameRef instanceof QualifiedNameReference) { > QualifiedNameReference ref = (QualifiedNameReference) nameRef; >+ char[] lastToken = ref.tokens[ref.tokens.length - 1]; >+ if (lastToken.length == 0) return; > if (ref.indexOfFirstFieldBinding >= 1) > end = (int) ref.sourcePositions[ref.indexOfFirstFieldBinding - 1]; >+ } else { >+ SingleNameReference ref = (SingleNameReference) nameRef; >+ if (ref.token.length == 0) return; > } > this.handle( > IProblem.UndefinedName, >Index: codeassist/org/eclipse/jdt/internal/codeassist/impl/AssistParser.java >=================================================================== >RCS file: /home/eclipse/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/AssistParser.java,v >retrieving revision 1.73 >diff -u -r1.73 AssistParser.java >--- codeassist/org/eclipse/jdt/internal/codeassist/impl/AssistParser.java 20 Oct 2005 13:26:47 -0000 1.73 >+++ codeassist/org/eclipse/jdt/internal/codeassist/impl/AssistParser.java 17 Jan 2006 17:44:19 -0000 >@@ -75,6 +75,8 @@ > public AssistParser(ProblemReporter problemReporter) { > super(problemReporter, true); > this.javadocParser.checkDocComment = false; >+ >+ this.setStatementsRecovery(false); > } > public abstract char[] assistIdentifier(); > public int bodyEnd(AbstractMethodDeclaration method){ >Index: batch/org/eclipse/jdt/internal/compiler/batch/Main.java >=================================================================== >RCS file: /home/eclipse/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java,v >retrieving revision 1.224 >diff -u -r1.224 Main.java >--- batch/org/eclipse/jdt/internal/compiler/batch/Main.java 17 Jan 2006 09:35:50 -0000 1.224 >+++ batch/org/eclipse/jdt/internal/compiler/batch/Main.java 17 Jan 2006 17:44:18 -0000 >@@ -2795,6 +2795,7 @@ > // set the non-externally configurable options. > this.compilerOptions.verbose = this.verbose; > this.compilerOptions.produceReferenceInfo = this.produceRefInfo; >+ this.compilerOptions.performStatementsRecovery = false; > try { > this.logger.startLoggingSources(); > batchCompiler.compile(getCompilationUnits()); >Index: compiler/org/eclipse/jdt/internal/compiler/parser/diagnose/DiagnoseParser.java >=================================================================== >RCS file: /home/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/diagnose/DiagnoseParser.java,v >retrieving revision 1.21 >diff -u -r1.21 DiagnoseParser.java >--- compiler/org/eclipse/jdt/internal/compiler/parser/diagnose/DiagnoseParser.java 17 Oct 2005 12:52:29 -0000 1.21 >+++ compiler/org/eclipse/jdt/internal/compiler/parser/diagnose/DiagnoseParser.java 17 Jan 2006 17:44:32 -0000 >@@ -14,6 +14,7 @@ > import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; > import org.eclipse.jdt.internal.compiler.parser.Parser; > import org.eclipse.jdt.internal.compiler.parser.ParserBasicInformation; >+import org.eclipse.jdt.internal.compiler.parser.RecoveryScanner; > import org.eclipse.jdt.internal.compiler.parser.TerminalTokens; > import org.eclipse.jdt.internal.compiler.problem.ProblemReporter; > >@@ -79,6 +80,10 @@ > > private Parser parser; > >+ private RecoveryScanner recoveryScanner; >+ >+ private boolean reportProblem; >+ > private class RepairCandidate { > public int symbol; > public int location; >@@ -145,6 +150,7 @@ > this.parser = parser; > this.options = options; > this.lexStream = new LexStream(BUFF_SIZE, parser.scanner, intervalStartToSkip, intervalEndToSkip, intervalFlagsToSkip, firstToken, start, end); >+ this.recoveryScanner = parser.recoveryScanner; > } > > private ProblemReporter problemReporter(){ >@@ -179,230 +185,242 @@ > } > > >- public void diagnoseParse() { >- lexStream.reset(); >- >- currentToken = lexStream.getToken(); >- >- int prev_pos; >- int pos; >- int next_pos; >- int act = START_STATE; >- >- reallocateStacks(); >- >- // >- // Start parsing >- // >- stateStackTop = 0; >- stack[stateStackTop] = act; >- >- int tok = lexStream.kind(currentToken); >- locationStack[stateStackTop] = currentToken; >- locationStartStack[stateStackTop] = lexStream.start(currentToken); >- >- boolean forceRecoveryAfterLBracketMissing = false; >-// int forceRecoveryToken = -1; >- >- // >- // Process a terminal >- // >- do { >+ public void diagnoseParse(boolean record) { >+ this.reportProblem = true; >+ boolean oldRecord = false; >+ if(this.recoveryScanner != null) { >+ oldRecord = this.recoveryScanner.record; >+ this.recoveryScanner.record = record; >+ } >+ try { >+ lexStream.reset(); >+ >+ currentToken = lexStream.getToken(); >+ >+ int prev_pos; >+ int pos; >+ int next_pos; >+ int act = START_STATE; >+ >+ reallocateStacks(); >+ > // >- // Synchronize state stacks and update the location stack >+ // Start parsing > // >- prev_pos = -1; >- prevStackTop = -1; >- >- next_pos = -1; >- nextStackTop = -1; >- >- pos = stateStackTop; >- tempStackTop = stateStackTop - 1; >- for (int i = 0; i <= stateStackTop; i++) >- tempStack[i] = stack[i]; >- >- act = Parser.tAction(act, tok); >+ stateStackTop = 0; >+ stack[stateStackTop] = act; >+ >+ int tok = lexStream.kind(currentToken); >+ locationStack[stateStackTop] = currentToken; >+ locationStartStack[stateStackTop] = lexStream.start(currentToken); >+ >+ boolean forceRecoveryAfterLBracketMissing = false; >+ // int forceRecoveryToken = -1; >+ > // >- // When a reduce action is encountered, we compute all REDUCE >- // and associated goto actions induced by the current token. >- // Eventually, a SHIFT, SHIFT-REDUCE, ACCEPT or ERROR action is >- // computed... >+ // Process a terminal > // >- while (act <= NUM_RULES) { >- do { >- tempStackTop -= (Parser.rhs[act]-1); >- act = Parser.ntAction(tempStack[tempStackTop], Parser.lhs[act]); >- } while(act <= NUM_RULES); >+ do { > // >- // ... Update the maximum useful position of the >- // (STATE_)STACK, push goto state into stack, and >- // compute next action on current symbol ... >+ // Synchronize state stacks and update the location stack > // >- if (tempStackTop + 1 >= stackLength) >- reallocateStacks(); >- pos = pos < tempStackTop ? pos : tempStackTop; >- tempStack[tempStackTop + 1] = act; >+ prev_pos = -1; >+ prevStackTop = -1; >+ >+ next_pos = -1; >+ nextStackTop = -1; >+ >+ pos = stateStackTop; >+ tempStackTop = stateStackTop - 1; >+ for (int i = 0; i <= stateStackTop; i++) >+ tempStack[i] = stack[i]; >+ > act = Parser.tAction(act, tok); >- } >- >- // >- // At this point, we have a shift, shift-reduce, accept or error >- // action. STACK contains the configuration of the state stack >- // prior to executing any action on curtok. next_stack contains >- // the configuration of the state stack after executing all >- // reduce actions induced by curtok. The variable pos indicates >- // the highest position in STACK that is still useful after the >- // reductions are executed. >- // >- while(act > ERROR_ACTION || act < ACCEPT_ACTION) { // SHIFT-REDUCE action or SHIFT action ? >- nextStackTop = tempStackTop + 1; >- for (int i = next_pos + 1; i <= nextStackTop; i++) >- nextStack[i] = tempStack[i]; >- >- for (int i = pos + 1; i <= nextStackTop; i++) { >- locationStack[i] = locationStack[stateStackTop]; >- locationStartStack[i] = locationStartStack[stateStackTop]; >- } >- > // >- // If we have a shift-reduce, process it as well as >- // the goto-reduce actions that follow it. >+ // When a reduce action is encountered, we compute all REDUCE >+ // and associated goto actions induced by the current token. >+ // Eventually, a SHIFT, SHIFT-REDUCE, ACCEPT or ERROR action is >+ // computed... > // >- if (act > ERROR_ACTION) { >- act -= ERROR_ACTION; >+ while (act <= NUM_RULES) { > do { >- nextStackTop -= (Parser.rhs[act]-1); >- act = Parser.ntAction(nextStack[nextStackTop], Parser.lhs[act]); >- } while(act <= NUM_RULES); >- pos = pos < nextStackTop ? pos : nextStackTop; >- } >- >- if (nextStackTop + 1 >= stackLength) >- reallocateStacks(); >- >- tempStackTop = nextStackTop; >- nextStack[++nextStackTop] = act; >- next_pos = nextStackTop; >- >- // >- // Simulate the parser through the next token without >- // destroying STACK or next_stack. >- // >- currentToken = lexStream.getToken(); >- tok = lexStream.kind(currentToken); >- act = Parser.tAction(act, tok); >- while(act <= NUM_RULES) { >- // >- // ... Process all goto-reduce actions following >- // reduction, until a goto action is computed ... >- // >- do { >- int lhs_symbol = Parser.lhs[act]; >- if(DEBUG) { >- System.out.println(Parser.name[Parser.non_terminal_index[lhs_symbol]]); >- } > tempStackTop -= (Parser.rhs[act]-1); >- act = (tempStackTop > next_pos >- ? tempStack[tempStackTop] >- : nextStack[tempStackTop]); >- act = Parser.ntAction(act, lhs_symbol); >- } while(act <= NUM_RULES); >- >+ act = Parser.ntAction(tempStack[tempStackTop], Parser.lhs[act]); >+ } while(act <= NUM_RULES); > // > // ... Update the maximum useful position of the >- // (STATE_)STACK, push GOTO state into stack, and >+ // (STATE_)STACK, push goto state into stack, and > // compute next action on current symbol ... > // > if (tempStackTop + 1 >= stackLength) > reallocateStacks(); >- >- next_pos = next_pos < tempStackTop ? next_pos : tempStackTop; >+ pos = pos < tempStackTop ? pos : tempStackTop; > tempStack[tempStackTop + 1] = act; > act = Parser.tAction(act, tok); > } >- >-// if((tok != TokenNameRBRACE || (forceRecoveryToken != currentToken && (lexStream.flags(currentToken) & LexStream.LBRACE_MISSING) != 0)) >-// && (lexStream.flags(currentToken) & LexStream.IS_AFTER_JUMP) !=0) { >-// act = ERROR_ACTION; >-// if(forceRecoveryToken != currentToken >-// && (lexStream.flags(currentToken) & LexStream.LBRACE_MISSING) != 0) { >-// forceRecoveryAfterLBracketMissing = true; >-// forceRecoveryToken = currentToken; >-// } >-// } >- >- // >- // No error was detected, Read next token into >- // PREVTOK element, advance CURTOK pointer and >- // update stacks. >- // >- if (act != ERROR_ACTION) { >- prevStackTop = stateStackTop; >- for (int i = prev_pos + 1; i <= prevStackTop; i++) >- prevStack[i] = stack[i]; >- prev_pos = pos; >- >- stateStackTop = nextStackTop; >- for (int i = pos + 1; i <= stateStackTop; i++) >- stack[i] = nextStack[i]; >- locationStack[stateStackTop] = currentToken; >- locationStartStack[stateStackTop] = lexStream.start(currentToken); >- pos = next_pos; >- } >- } >- >- // >- // At this stage, either we have an ACCEPT or an ERROR >- // action. >- // >- if (act == ERROR_ACTION) { >+ > // >- // An error was detected. >+ // At this point, we have a shift, shift-reduce, accept or error >+ // action. STACK contains the configuration of the state stack >+ // prior to executing any action on curtok. next_stack contains >+ // the configuration of the state stack after executing all >+ // reduce actions induced by curtok. The variable pos indicates >+ // the highest position in STACK that is still useful after the >+ // reductions are executed. > // >- RepairCandidate candidate = errorRecovery(currentToken, forceRecoveryAfterLBracketMissing); >- >- forceRecoveryAfterLBracketMissing = false; >- >- if(parser.reportOnlyOneSyntaxError) { >- return; >- } >- >- if(this.parser.problemReporter().options.maxProblemsPerUnit < this.parser.compilationUnit.compilationResult.problemCount) { >- return; >+ while(act > ERROR_ACTION || act < ACCEPT_ACTION) { // SHIFT-REDUCE action or SHIFT action ? >+ nextStackTop = tempStackTop + 1; >+ for (int i = next_pos + 1; i <= nextStackTop; i++) >+ nextStack[i] = tempStack[i]; >+ >+ for (int i = pos + 1; i <= nextStackTop; i++) { >+ locationStack[i] = locationStack[stateStackTop]; >+ locationStartStack[i] = locationStartStack[stateStackTop]; >+ } >+ >+ // >+ // If we have a shift-reduce, process it as well as >+ // the goto-reduce actions that follow it. >+ // >+ if (act > ERROR_ACTION) { >+ act -= ERROR_ACTION; >+ do { >+ nextStackTop -= (Parser.rhs[act]-1); >+ act = Parser.ntAction(nextStack[nextStackTop], Parser.lhs[act]); >+ } while(act <= NUM_RULES); >+ pos = pos < nextStackTop ? pos : nextStackTop; >+ } >+ >+ if (nextStackTop + 1 >= stackLength) >+ reallocateStacks(); >+ >+ tempStackTop = nextStackTop; >+ nextStack[++nextStackTop] = act; >+ next_pos = nextStackTop; >+ >+ // >+ // Simulate the parser through the next token without >+ // destroying STACK or next_stack. >+ // >+ currentToken = lexStream.getToken(); >+ tok = lexStream.kind(currentToken); >+ act = Parser.tAction(act, tok); >+ while(act <= NUM_RULES) { >+ // >+ // ... Process all goto-reduce actions following >+ // reduction, until a goto action is computed ... >+ // >+ do { >+ int lhs_symbol = Parser.lhs[act]; >+ if(DEBUG) { >+ System.out.println(Parser.name[Parser.non_terminal_index[lhs_symbol]]); >+ } >+ tempStackTop -= (Parser.rhs[act]-1); >+ act = (tempStackTop > next_pos >+ ? tempStack[tempStackTop] >+ : nextStack[tempStackTop]); >+ act = Parser.ntAction(act, lhs_symbol); >+ } while(act <= NUM_RULES); >+ >+ // >+ // ... Update the maximum useful position of the >+ // (STATE_)STACK, push GOTO state into stack, and >+ // compute next action on current symbol ... >+ // >+ if (tempStackTop + 1 >= stackLength) >+ reallocateStacks(); >+ >+ next_pos = next_pos < tempStackTop ? next_pos : tempStackTop; >+ tempStack[tempStackTop + 1] = act; >+ act = Parser.tAction(act, tok); >+ } >+ >+ // if((tok != TokenNameRBRACE || (forceRecoveryToken != currentToken && (lexStream.flags(currentToken) & LexStream.LBRACE_MISSING) != 0)) >+ // && (lexStream.flags(currentToken) & LexStream.IS_AFTER_JUMP) !=0) { >+ // act = ERROR_ACTION; >+ // if(forceRecoveryToken != currentToken >+ // && (lexStream.flags(currentToken) & LexStream.LBRACE_MISSING) != 0) { >+ // forceRecoveryAfterLBracketMissing = true; >+ // forceRecoveryToken = currentToken; >+ // } >+ // } >+ >+ // >+ // No error was detected, Read next token into >+ // PREVTOK element, advance CURTOK pointer and >+ // update stacks. >+ // >+ if (act != ERROR_ACTION) { >+ prevStackTop = stateStackTop; >+ for (int i = prev_pos + 1; i <= prevStackTop; i++) >+ prevStack[i] = stack[i]; >+ prev_pos = pos; >+ >+ stateStackTop = nextStackTop; >+ for (int i = pos + 1; i <= stateStackTop; i++) >+ stack[i] = nextStack[i]; >+ locationStack[stateStackTop] = currentToken; >+ locationStartStack[stateStackTop] = lexStream.start(currentToken); >+ pos = next_pos; >+ } > } >- >- act = stack[stateStackTop]; >- >+ > // >- // If the recovery was successful on a nonterminal candidate, >- // parse through that candidate and "read" the next token. >+ // At this stage, either we have an ACCEPT or an ERROR >+ // action. > // >- if (candidate.symbol == 0) { >- break; >- } else if (candidate.symbol > NT_OFFSET) { >- int lhs_symbol = candidate.symbol - NT_OFFSET; >- if(DEBUG) { >- System.out.println(Parser.name[Parser.non_terminal_index[lhs_symbol]]); >+ if (act == ERROR_ACTION) { >+ // >+ // An error was detected. >+ // >+ RepairCandidate candidate = errorRecovery(currentToken, forceRecoveryAfterLBracketMissing); >+ >+ forceRecoveryAfterLBracketMissing = false; >+ >+ if(parser.reportOnlyOneSyntaxError) { >+ return; > } >- act = Parser.ntAction(act, lhs_symbol); >- while(act <= NUM_RULES) { >- stateStackTop -= (Parser.rhs[act]-1); >- act = Parser.ntAction(stack[stateStackTop], Parser.lhs[act]); >+ >+ if(this.parser.problemReporter().options.maxProblemsPerUnit < this.parser.compilationUnit.compilationResult.problemCount) { >+ if(this.recoveryScanner == null) return; >+ this.reportProblem = false; >+ } >+ >+ act = stack[stateStackTop]; >+ >+ // >+ // If the recovery was successful on a nonterminal candidate, >+ // parse through that candidate and "read" the next token. >+ // >+ if (candidate.symbol == 0) { >+ break; >+ } else if (candidate.symbol > NT_OFFSET) { >+ int lhs_symbol = candidate.symbol - NT_OFFSET; >+ if(DEBUG) { >+ System.out.println(Parser.name[Parser.non_terminal_index[lhs_symbol]]); >+ } >+ act = Parser.ntAction(act, lhs_symbol); >+ while(act <= NUM_RULES) { >+ stateStackTop -= (Parser.rhs[act]-1); >+ act = Parser.ntAction(stack[stateStackTop], Parser.lhs[act]); >+ } >+ stack[++stateStackTop] = act; >+ currentToken = lexStream.getToken(); >+ tok = lexStream.kind(currentToken); >+ locationStack[stateStackTop] = currentToken; >+ locationStartStack[stateStackTop] = lexStream.start(currentToken); >+ } else { >+ tok = candidate.symbol; >+ locationStack[stateStackTop] = candidate.location; >+ locationStartStack[stateStackTop] = lexStream.start(candidate.location); > } >- stack[++stateStackTop] = act; >- currentToken = lexStream.getToken(); >- tok = lexStream.kind(currentToken); >- locationStack[stateStackTop] = currentToken; >- locationStartStack[stateStackTop] = lexStream.start(currentToken); >- } else { >- tok = candidate.symbol; >- locationStack[stateStackTop] = candidate.location; >- locationStartStack[stateStackTop] = lexStream.start(candidate.location); > } >+ } while (act != ACCEPT_ACTION); >+ } finally { >+ if(this.recoveryScanner != null) { >+ this.recoveryScanner.record = oldRecord; > } >- } while (act != ACCEPT_ACTION); >- >+ } > return; > } > >@@ -2084,9 +2102,25 @@ > String errorTokenName = Parser.name[Parser.terminal_index[lexStream.kind(token)]]; > char[] errorTokenSource = lexStream.name(token); > >+ int addedToken = -1; >+ if(recoveryScanner != null) { >+ if (nameIndex >= 0) { >+ addedToken = Parser.reverse_index[nameIndex]; >+ } >+ } > switch(msgCode) { > case BEFORE_CODE: >- problemReporter().parseErrorInsertBeforeToken( >+ if(recoveryScanner != null) { >+ if(addedToken > -1) { >+ recoveryScanner.insertToken(addedToken, -1, errorStart); >+ } else { >+ int[] template = getNTermTemplate(-addedToken); >+ if(template != null) { >+ recoveryScanner.insertTokens(template, -1, errorStart); >+ } >+ } >+ } >+ if(this.reportProblem) problemReporter().parseErrorInsertBeforeToken( > errorStart, > errorEnd, > currentKind, >@@ -2095,7 +2129,17 @@ > name); > break; > case INSERTION_CODE: >- problemReporter().parseErrorInsertAfterToken( >+ if(recoveryScanner != null) { >+ if(addedToken > -1) { >+ recoveryScanner.insertToken(addedToken, -1, errorEnd); >+ } else { >+ int[] template = getNTermTemplate(-addedToken); >+ if(template != null) { >+ recoveryScanner.insertTokens(template, -1, errorEnd); >+ } >+ } >+ } >+ if(this.reportProblem) problemReporter().parseErrorInsertAfterToken( > errorStart, > errorEnd, > currentKind, >@@ -2104,7 +2148,10 @@ > name); > break; > case DELETION_CODE: >- problemReporter().parseErrorDeleteToken( >+ if(recoveryScanner != null) { >+ recoveryScanner.removeTokens(errorStart, errorEnd); >+ } >+ if(this.reportProblem) problemReporter().parseErrorDeleteToken( > errorStart, > errorEnd, > currentKind, >@@ -2113,7 +2160,10 @@ > break; > case INVALID_CODE: > if (name.length() == 0) { >- problemReporter().parseErrorReplaceToken( >+ if(recoveryScanner != null) { >+ recoveryScanner.removeTokens(errorStart, errorEnd); >+ } >+ if(this.reportProblem) problemReporter().parseErrorReplaceToken( > errorStart, > errorEnd, > currentKind, >@@ -2121,7 +2171,17 @@ > errorTokenName, > name); > } else { >- problemReporter().parseErrorInvalidToken( >+ if(recoveryScanner != null) { >+ if(addedToken > -1) { >+ recoveryScanner.replaceTokens(addedToken, errorStart, errorEnd); >+ } else { >+ int[] template = getNTermTemplate(-addedToken); >+ if(template != null) { >+ recoveryScanner.replaceTokens(template, errorStart, errorEnd); >+ } >+ } >+ } >+ if(this.reportProblem) problemReporter().parseErrorInvalidToken( > errorStart, > errorEnd, > currentKind, >@@ -2131,7 +2191,17 @@ > } > break; > case SUBSTITUTION_CODE: >- problemReporter().parseErrorReplaceToken( >+ if(recoveryScanner != null) { >+ if(addedToken > -1) { >+ recoveryScanner.replaceTokens(addedToken, errorStart, errorEnd); >+ } else { >+ int[] template = getNTermTemplate(-addedToken); >+ if(template != null) { >+ recoveryScanner.replaceTokens(template, errorStart, errorEnd); >+ } >+ } >+ } >+ if(this.reportProblem) problemReporter().parseErrorReplaceToken( > errorStart, > errorEnd, > currentKind, >@@ -2141,21 +2211,62 @@ > break; > case SCOPE_CODE: > StringBuffer buf = new StringBuffer(); >+ >+ int[] addedTokens = null; >+ int addedTokenCount = 0; >+ if(this.recoveryScanner != null) { >+ addedTokens = new int[Parser.scope_rhs.length - Parser.scope_suffix[- nameIndex]]; >+ } >+ > for (int i = Parser.scope_suffix[- nameIndex]; Parser.scope_rhs[i] != 0; i++) { > buf.append(Parser.readableName[Parser.scope_rhs[i]]); > if (Parser.scope_rhs[i + 1] != 0) // any more symbols to print? > buf.append(' '); >- >+ >+ if(addedTokens != null) { >+ int tmpAddedToken = Parser.reverse_index[Parser.scope_rhs[i]]; >+ if (tmpAddedToken > -1) { >+ int length = addedTokens.length; >+ if(addedTokenCount == length) { >+ System.arraycopy(addedTokens, 0, addedTokens = new int[length * 2], 0, length); >+ } >+ addedTokens[addedTokenCount++] = tmpAddedToken; >+ } else { >+ int[] template = getNTermTemplate(-tmpAddedToken); >+ if(template != null) { >+ for (int j = 0; j < template.length; j++) { >+ int length = addedTokens.length; >+ if(addedTokenCount == length) { >+ System.arraycopy(addedTokens, 0, addedTokens = new int[length * 2], 0, length); >+ } >+ addedTokens[addedTokenCount++] = template[j]; >+ } >+ } else { >+ addedTokenCount = 0; >+ addedTokens = null; >+ } >+ } >+ } > } > >+ if(addedTokenCount > 0) { >+ System.arraycopy(addedTokens, 0, addedTokens = new int[addedTokenCount], 0, addedTokenCount); >+ >+ int completedToken = -1; >+ if(scopeNameIndex != 0) { >+ completedToken = -Parser.reverse_index[scopeNameIndex]; >+ } >+ this.recoveryScanner.insertTokens(addedTokens, completedToken, errorEnd); >+ } >+ > if (scopeNameIndex != 0) { >- problemReporter().parseErrorInsertToComplete( >+ if(this.reportProblem) problemReporter().parseErrorInsertToComplete( > errorStart, > errorEnd, > buf.toString(), > Parser.readableName[scopeNameIndex]); > } else { >- problemReporter().parseErrorInsertToCompleteScope( >+ if(this.reportProblem) problemReporter().parseErrorInsertToCompleteScope( > errorStart, > errorEnd, > buf.toString()); >@@ -2163,31 +2274,57 @@ > > break; > case EOF_CODE: >- problemReporter().parseErrorUnexpectedEnd( >+ if(this.reportProblem) problemReporter().parseErrorUnexpectedEnd( > errorStart, > errorEnd); > break; > case MERGE_CODE: >- problemReporter().parseErrorMergeTokens( >+ if(recoveryScanner != null) { >+ if(addedToken > -1) { >+ recoveryScanner.replaceTokens(addedToken, errorStart, errorEnd); >+ } else { >+ int[] template = getNTermTemplate(-addedToken); >+ if(template != null) { >+ recoveryScanner.replaceTokens(template, errorStart, errorEnd); >+ } >+ } >+ } >+ if(this.reportProblem) problemReporter().parseErrorMergeTokens( > errorStart, > errorEnd, > name); > break; > case MISPLACED_CODE: >- problemReporter().parseErrorMisplacedConstruct( >+ if(recoveryScanner != null) { >+ recoveryScanner.removeTokens(errorStart, errorEnd); >+ } >+ if(this.reportProblem) problemReporter().parseErrorMisplacedConstruct( > errorStart, > errorEnd); > break; > default: > if (name.length() == 0) { >- problemReporter().parseErrorNoSuggestion( >+ if(recoveryScanner != null) { >+ recoveryScanner.removeTokens(errorStart, errorEnd); >+ } >+ if(this.reportProblem) problemReporter().parseErrorNoSuggestion( > errorStart, > errorEnd, > currentKind, > errorTokenSource, > errorTokenName); > } else { >- problemReporter().parseErrorReplaceToken( >+ if(recoveryScanner != null) { >+ if(addedToken > -1) { >+ recoveryScanner.replaceTokens(addedToken, errorStart, errorEnd); >+ } else { >+ int[] template = getNTermTemplate(-addedToken); >+ if(template != null) { >+ recoveryScanner.replaceTokens(template, errorStart, errorEnd); >+ } >+ } >+ } >+ if(this.reportProblem) problemReporter().parseErrorReplaceToken( > errorStart, > errorEnd, > currentKind, >@@ -2230,9 +2367,19 @@ > } > int errorEnd = lexStream.end(rightToken); > >+ int addedToken = -1; >+ if(recoveryScanner != null) { >+ if (nameIndex >= 0) { >+ addedToken = Parser.reverse_index[nameIndex]; >+ } >+ } >+ > switch(msgCode) { > case MISPLACED_CODE: >- problemReporter().parseErrorMisplacedConstruct( >+ if(recoveryScanner != null) { >+ recoveryScanner.removeTokens(errorStart, errorEnd); >+ } >+ if(this.reportProblem) problemReporter().parseErrorMisplacedConstruct( > errorStart, > errorEnd); > break; >@@ -2241,42 +2388,109 @@ > errorStart = lexStream.start(rightToken); > > StringBuffer buf = new StringBuffer(); >+ >+ int[] addedTokens = null; >+ int addedTokenCount = 0; >+ if(this.recoveryScanner != null) { >+ addedTokens = new int[Parser.scope_rhs.length - Parser.scope_suffix[- nameIndex]]; >+ } >+ > for (int i = Parser.scope_suffix[- nameIndex]; Parser.scope_rhs[i] != 0; i++) { >+ > buf.append(Parser.readableName[Parser.scope_rhs[i]]); > if (Parser.scope_rhs[i+1] != 0) > buf.append(' '); >+ >+ if(addedTokens != null) { >+ int tmpAddedToken = Parser.reverse_index[Parser.scope_rhs[i]]; >+ if (tmpAddedToken > -1) { >+ int length = addedTokens.length; >+ if(addedTokenCount == length) { >+ System.arraycopy(addedTokens, 0, addedTokens = new int[length * 2], 0, length); >+ } >+ addedTokens[addedTokenCount++] = tmpAddedToken; >+ } else { >+ int[] template = getNTermTemplate(-tmpAddedToken); >+ if(template != null) { >+ for (int j = 0; j < template.length; j++) { >+ int length = addedTokens.length; >+ if(addedTokenCount == length) { >+ System.arraycopy(addedTokens, 0, addedTokens = new int[length * 2], 0, length); >+ } >+ addedTokens[addedTokenCount++] = template[j]; >+ } >+ } else { >+ addedTokenCount = 0; >+ addedTokens = null; >+ } >+ } >+ } >+ } >+ if(addedTokenCount > 0) { >+ System.arraycopy(addedTokens, 0, addedTokens = new int[addedTokenCount], 0, addedTokenCount); >+ int completedToken = -1; >+ if(scopeNameIndex != 0) { >+ completedToken = -Parser.reverse_index[scopeNameIndex]; >+ } >+ this.recoveryScanner.insertTokens(addedTokens, completedToken, errorEnd); > } > if (scopeNameIndex != 0) { >- problemReporter().parseErrorInsertToComplete( >+ if(this.reportProblem) problemReporter().parseErrorInsertToComplete( > errorStart, > errorEnd, > buf.toString(), > Parser.readableName[scopeNameIndex]); > } else { >- problemReporter().parseErrorInsertToCompletePhrase( >+ if(this.reportProblem) problemReporter().parseErrorInsertToCompletePhrase( > errorStart, > errorEnd, > buf.toString()); > } > break; > case MERGE_CODE: >- problemReporter().parseErrorMergeTokens( >+ if(recoveryScanner != null) { >+ if(addedToken > -1) { >+ recoveryScanner.replaceTokens(addedToken, errorStart, errorEnd); >+ } else { >+ int[] template = getNTermTemplate(-addedToken); >+ if(template != null) { >+ recoveryScanner.replaceTokens(template, errorStart, errorEnd); >+ } >+ } >+ } >+ if(this.reportProblem) problemReporter().parseErrorMergeTokens( > errorStart, > errorEnd, > name); > break; > case DELETION_CODE: >- problemReporter().parseErrorDeleteTokens( >+ if(recoveryScanner != null) { >+ recoveryScanner.removeTokens(errorStart, errorEnd); >+ } >+ if(this.reportProblem) problemReporter().parseErrorDeleteTokens( > errorStart, > errorEnd); > break; > default: > if (name.length() == 0) { >- problemReporter().parseErrorNoSuggestionForTokens( >+ if(recoveryScanner != null) { >+ recoveryScanner.removeTokens(errorStart, errorEnd); >+ } >+ if(this.reportProblem) problemReporter().parseErrorNoSuggestionForTokens( > errorStart, > errorEnd); > } else { >- problemReporter().parseErrorReplaceTokens( >+ if(recoveryScanner != null) { >+ if(addedToken > -1) { >+ recoveryScanner.replaceTokens(addedToken, errorStart, errorEnd); >+ } else { >+ int[] template = getNTermTemplate(-addedToken); >+ if(template != null) { >+ recoveryScanner.replaceTokens(template, errorStart, errorEnd); >+ } >+ } >+ } >+ if(this.reportProblem) problemReporter().parseErrorReplaceTokens( > errorStart, > errorEnd, > name); >@@ -2285,6 +2499,21 @@ > return; > } > >+ private int[] getNTermTemplate(int sym) { >+ int templateIndex = Parser.recovery_templates_index[sym]; >+ if(templateIndex > 0) { >+ int[] result = new int[Parser.recovery_templates.length]; >+ int count = 0; >+ for(int j = templateIndex; Parser.recovery_templates[j] != 0; j++) { >+ result[count++] = Parser.recovery_templates[j]; >+ } >+ System.arraycopy(result, 0, result = new int[count], 0, count); >+ return result; >+ } else { >+ return null; >+ } >+ } >+ > public String toString() { > StringBuffer res = new StringBuffer(); > >Index: compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java >=================================================================== >RCS file: /home/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java,v >retrieving revision 1.153 >diff -u -r1.153 CompilerOptions.java >--- compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java 12 Jan 2006 15:55:44 -0000 1.153 >+++ compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java 17 Jan 2006 17:44:21 -0000 >@@ -113,6 +113,9 @@ > /* should surface ??? */ > public static final String OPTION_PrivateConstructorAccess = "org.eclipse.jdt.core.compiler.codegen.constructorAccessEmulation"; //$NON-NLS-1$ > >+ //TODO temporary option >+ public static final String OPTION_StatementsRecovery = "org.eclipse.jdt.core.compiler.statementsRecovery"; //$NON-NLS-1$ >+ > /** > * Possible values for configurable options > */ >@@ -187,7 +190,7 @@ > public static final long RawTypeReference = ASTNode.Bit46L; > public static final long UnusedLabel = ASTNode.Bit47L; > public static final long ParameterAssignment = ASTNode.Bit48L; >- >+ > // Default severity level for handlers > public long errorThreshold = 0; > >@@ -296,9 +299,12 @@ > // treat optional error as fatal or just like warning? > public boolean treatOptionalErrorAsFatal = true; > >+ // parser perform statements recovery >+ public boolean performStatementsRecovery = true; >+ > // store annotations > public boolean storeAnnotations = false; >- >+ > /** > * Initializing the compiler options with defaults > */ >@@ -726,6 +732,13 @@ > this.reportMissingJavadocCommentsOverriding = false; > } > } >+ if ((optionValue = optionsMap.get(OPTION_StatementsRecovery)) != null) { >+ if (ENABLED.equals(optionValue)) { >+ this.performStatementsRecovery = true; >+ } else if (DISABLED.equals(optionValue)) { >+ this.performStatementsRecovery = false; >+ } >+ } > } > > public String toString() { >Index: model/org/eclipse/jdt/internal/core/JavaCorePreferenceInitializer.java >=================================================================== >RCS file: /home/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaCorePreferenceInitializer.java,v >retrieving revision 1.26 >diff -u -r1.26 JavaCorePreferenceInitializer.java >--- model/org/eclipse/jdt/internal/core/JavaCorePreferenceInitializer.java 13 Jan 2006 09:36:49 -0000 1.26 >+++ model/org/eclipse/jdt/internal/core/JavaCorePreferenceInitializer.java 17 Jan 2006 17:44:48 -0000 >@@ -43,7 +43,8 @@ > defaultOptionsMap.put(JavaCore.COMPILER_TASK_CASE_SENSITIVE, JavaCore.ENABLED); > defaultOptionsMap.put(JavaCore.COMPILER_DOC_COMMENT_SUPPORT, JavaCore.ENABLED); > defaultOptionsMap.put(JavaCore.COMPILER_PB_FORBIDDEN_REFERENCE, JavaCore.ERROR); >- >+ defaultOptionsMap.put(JavaCore.COMPILER_STATEMENTS_RECOVERY, JavaCore.DISABLED); //TODO It is a temporary option >+ > // Builder settings > defaultOptionsMap.put(JavaCore.CORE_JAVA_BUILD_RESOURCE_COPY_FILTER, ""); //$NON-NLS-1$ > defaultOptionsMap.put(JavaCore.CORE_JAVA_BUILD_INVALID_CLASSPATH, JavaCore.ABORT); >Index: compiler/org/eclipse/jdt/internal/compiler/CompilationResult.java >=================================================================== >RCS file: /home/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/CompilationResult.java,v >retrieving revision 1.48 >diff -u -r1.48 CompilationResult.java >--- compiler/org/eclipse/jdt/internal/compiler/CompilationResult.java 10 Jan 2006 21:01:06 -0000 1.48 >+++ compiler/org/eclipse/jdt/internal/compiler/CompilationResult.java 17 Jan 2006 17:44:19 -0000 >@@ -42,6 +42,7 @@ > import org.eclipse.jdt.internal.compiler.env.ICompilationUnit; > import org.eclipse.jdt.internal.compiler.impl.ReferenceContext; > import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding; >+import org.eclipse.jdt.internal.compiler.parser.RecoveryScannerData; > import org.eclipse.jdt.internal.compiler.problem.ProblemReporter; > > public class CompilationResult { >@@ -60,6 +61,7 @@ > public boolean hasAnnotations = false; > > public int lineSeparatorPositions[]; >+ public RecoveryScannerData recoveryScannerData; > public Map compiledTypes = new Hashtable(11); > public int unitIndex, totalUnitsKnown; > public boolean hasBeenAccepted = false; >Index: compiler/org/eclipse/jdt/internal/compiler/parser/RecoveryScannerData.java >=================================================================== >RCS file: compiler/org/eclipse/jdt/internal/compiler/parser/RecoveryScannerData.java >diff -N compiler/org/eclipse/jdt/internal/compiler/parser/RecoveryScannerData.java >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ compiler/org/eclipse/jdt/internal/compiler/parser/RecoveryScannerData.java 1 Jan 1970 00:00:00 -0000 >@@ -0,0 +1,65 @@ >+/** >+ * >+ */ >+package org.eclipse.jdt.internal.compiler.parser; >+ >+public class RecoveryScannerData { >+ public int insertedTokensPtr = -1; >+ public int[][] insertedTokens; >+ public int[] insertedTokensPosition; >+ public boolean[] insertedTokenUsed; >+ >+ public int replacedTokensPtr = -1; >+ public int[][] replacedTokens; >+ public int[] replacedTokensStart; >+ public int[] replacedTokensEnd; >+ public boolean[] replacedTokenUsed; >+ >+ public int removedTokensPtr = -1; >+ public int[] removedTokensStart; >+ public int[] removedTokensEnd; >+ public boolean[] removedTokenUsed; >+ >+ public RecoveryScannerData removeUnused() { >+ if(this.insertedTokens != null) { >+ int newInsertedTokensPtr = -1; >+ for (int i = 0; i <= this.insertedTokensPtr; i++) { >+ if(this.insertedTokenUsed[i]) { >+ newInsertedTokensPtr++; >+ this.insertedTokens[newInsertedTokensPtr] = this.insertedTokens[i]; >+ this.insertedTokensPosition[newInsertedTokensPtr] = this.insertedTokensPosition[i]; >+ this.insertedTokenUsed[newInsertedTokensPtr] = this.insertedTokenUsed[i]; >+ } >+ } >+ this.insertedTokensPtr = newInsertedTokensPtr; >+ } >+ >+ if(this.replacedTokens != null) { >+ int newReplacedTokensPtr = -1; >+ for (int i = 0; i <= this.replacedTokensPtr; i++) { >+ if(this.replacedTokenUsed[i]) { >+ newReplacedTokensPtr++; >+ this.replacedTokens[newReplacedTokensPtr] = this.replacedTokens[i]; >+ this.replacedTokensStart[newReplacedTokensPtr] = this.replacedTokensStart[i]; >+ this.replacedTokensEnd[newReplacedTokensPtr] = this.replacedTokensEnd[i]; >+ this.replacedTokenUsed[newReplacedTokensPtr] = this.replacedTokenUsed[i]; >+ } >+ } >+ this.replacedTokensPtr = newReplacedTokensPtr; >+ } >+ if(this.removedTokensStart != null) { >+ int newRemovedTokensPtr = -1; >+ for (int i = 0; i <= this.removedTokensPtr; i++) { >+ if(this.removedTokenUsed[i]) { >+ newRemovedTokensPtr++; >+ this.removedTokensStart[newRemovedTokensPtr] = this.removedTokensStart[i]; >+ this.removedTokensEnd[newRemovedTokensPtr] = this.removedTokensEnd[i]; >+ this.removedTokenUsed[newRemovedTokensPtr] = this.removedTokenUsed[i]; >+ } >+ } >+ this.removedTokensPtr = newRemovedTokensPtr; >+ } >+ >+ return this; >+ } >+} >Index: compiler/org/eclipse/jdt/internal/compiler/parser/RecoveryScanner.java >=================================================================== >RCS file: compiler/org/eclipse/jdt/internal/compiler/parser/RecoveryScanner.java >diff -N compiler/org/eclipse/jdt/internal/compiler/parser/RecoveryScanner.java >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ compiler/org/eclipse/jdt/internal/compiler/parser/RecoveryScanner.java 1 Jan 1970 00:00:00 -0000 >@@ -0,0 +1,186 @@ >+package org.eclipse.jdt.internal.compiler.parser; >+ >+import org.eclipse.jdt.core.compiler.CharOperation; >+import org.eclipse.jdt.core.compiler.InvalidInputException; >+ >+public class RecoveryScanner extends Scanner { >+ private RecoveryScannerData data; >+ >+ private int[] pendingTokens; >+ private int pendingTokensPtr = -1; >+ private char[] fakeTokenSource = null; >+ private int skipNextInsertedTokens = -1; >+ >+ public boolean record = true; >+ >+ public RecoveryScanner(Scanner scanner, RecoveryScannerData data) { >+ super(false, >+ scanner.tokenizeWhiteSpace, >+ scanner.checkNonExternalizedStringLiterals, >+ scanner.sourceLevel, >+ scanner.complianceLevel, >+ scanner.taskTags, >+ scanner.taskPriorities, >+ scanner.isTaskCaseSensitive); >+ this.setData(data); >+ } >+ >+ public void insertToken(int token, int completedToken, int position) { >+ insertTokens(new int []{token}, completedToken, position); >+ } >+ >+ private int[] reverse(int[] tokens) { >+ int length = tokens.length; >+ for(int i = 0, max = length / 2; i < max; i++) { >+ int tmp = tokens[i]; >+ tokens[i] = tokens[length - i - 1]; >+ tokens[length - i - 1] = tmp; >+ } >+ return tokens; >+ } >+ public void insertTokens(int[] tokens, int completedToken, int position) { >+ if(!this.record) return; >+ >+ if(completedToken > -1 && Parser.statements_recovery_filter[completedToken] != 0) return; >+ >+ this.data.insertedTokensPtr++; >+ if(this.data.insertedTokens == null) { >+ this.data.insertedTokens = new int[10][]; >+ this.data.insertedTokensPosition = new int[10]; >+ this.data.insertedTokenUsed = new boolean[10]; >+ } else if(this.data.insertedTokens.length == this.data.insertedTokensPtr) { >+ int length = this.data.insertedTokens.length; >+ System.arraycopy(this.data.insertedTokens, 0, this.data.insertedTokens = new int[length * 2][], 0, length); >+ System.arraycopy(this.data.insertedTokensPosition, 0, this.data.insertedTokensPosition = new int[length * 2], 0, length); >+ System.arraycopy(this.data.insertedTokenUsed, 0, this.data.insertedTokenUsed = new boolean[length * 2], 0, length); >+ } >+ this.data.insertedTokens[this.data.insertedTokensPtr] = reverse(tokens); >+ this.data.insertedTokensPosition[this.data.insertedTokensPtr] = position; >+ this.data.insertedTokenUsed[this.data.insertedTokensPtr] = false; >+ } >+ >+ public void replaceTokens(int token, int start, int end) { >+ replaceTokens(new int []{token}, start, end); >+ } >+ >+ public void replaceTokens(int[] tokens, int start, int end) { >+ if(!this.record) return; >+ this.data.replacedTokensPtr++; >+ if(this.data.replacedTokensStart == null) { >+ this.data.replacedTokens = new int[10][]; >+ this.data.replacedTokensStart = new int[10]; >+ this.data.replacedTokensEnd = new int[10]; >+ this.data.replacedTokenUsed= new boolean[10]; >+ } else if(this.data.replacedTokensStart.length == this.data.replacedTokensPtr) { >+ int length = this.data.replacedTokensStart.length; >+ System.arraycopy(this.data.replacedTokens, 0, this.data.replacedTokens = new int[length * 2][], 0, length); >+ System.arraycopy(this.data.replacedTokensStart, 0, this.data.replacedTokensStart = new int[length * 2], 0, length); >+ System.arraycopy(this.data.replacedTokensEnd, 0, this.data.replacedTokensEnd = new int[length * 2], 0, length); >+ System.arraycopy(this.data.replacedTokenUsed, 0, this.data.replacedTokenUsed = new boolean[length * 2], 0, length); >+ } >+ this.data.replacedTokens[this.data.replacedTokensPtr] = reverse(tokens); >+ this.data.replacedTokensStart[this.data.replacedTokensPtr] = start; >+ this.data.replacedTokensEnd[this.data.replacedTokensPtr] = end; >+ this.data.replacedTokenUsed[this.data.replacedTokensPtr] = false; >+ } >+ >+ public void removeTokens(int start, int end) { >+ if(!this.record) return; >+ this.data.removedTokensPtr++; >+ if(this.data.removedTokensStart == null) { >+ this.data.removedTokensStart = new int[10]; >+ this.data.removedTokensEnd = new int[10]; >+ this.data.removedTokenUsed = new boolean[10]; >+ } else if(this.data.removedTokensStart.length == this.data.removedTokensPtr) { >+ int length = this.data.removedTokensStart.length; >+ System.arraycopy(this.data.removedTokensStart, 0, this.data.removedTokensStart = new int[length * 2], 0, length); >+ System.arraycopy(this.data.removedTokensEnd, 0, this.data.removedTokensEnd = new int[length * 2], 0, length); >+ System.arraycopy(this.data.removedTokenUsed, 0, this.data.removedTokenUsed = new boolean[length * 2], 0, length); >+ } >+ this.data.removedTokensStart[this.data.removedTokensPtr] = start; >+ this.data.removedTokensEnd[this.data.removedTokensPtr] = end; >+ this.data.removedTokenUsed[this.data.removedTokensPtr] = false; >+ } >+ >+ public int getNextToken() throws InvalidInputException { >+ if(this.pendingTokensPtr > -1) { >+ return this.pendingTokens[this.pendingTokensPtr--]; >+ } >+ >+ this.fakeTokenSource = null; >+ >+ if(this.data.insertedTokens != null) { >+// if(!skipNextInsertedTokens) { >+ for (int i = 0; i <= this.data.insertedTokensPtr; i++) { >+ if(this.data.insertedTokensPosition[i] == this.currentPosition - 1 && i > skipNextInsertedTokens) { >+ this.data.insertedTokenUsed[i] = true; >+ this.pendingTokens = this.data.insertedTokens[i]; >+ this.pendingTokensPtr = this.data.insertedTokens[i].length - 1; >+ this.fakeTokenSource = CharOperation.NO_CHAR; >+ this.startPosition = this.currentPosition - 1; >+ this.skipNextInsertedTokens = i; >+ return this.pendingTokens[this.pendingTokensPtr--]; >+ } >+ } >+// } >+ this.skipNextInsertedTokens = -1; >+ } >+ >+ int previousLocation = this.currentPosition; >+ int currentToken = super.getNextToken(); >+ >+ if(this.data.replacedTokens != null) { >+ for (int i = 0; i <= this.data.replacedTokensPtr; i++) { >+ if(this.data.replacedTokensStart[i] >= previousLocation && >+ this.data.replacedTokensStart[i] <= this.startPosition && >+ this.data.replacedTokensEnd[i] >= this.currentPosition - 1) { >+ this.data.replacedTokenUsed[i] = true; >+ this.pendingTokens = this.data.replacedTokens[i]; >+ this.pendingTokensPtr = this.data.replacedTokens[i].length - 1; >+ this.fakeTokenSource = CharOperation.NO_CHAR; >+ this.currentPosition = this.data.replacedTokensEnd[i] + 1; >+ return this.pendingTokens[this.pendingTokensPtr--]; >+ } >+ } >+ } >+ if(this.data.removedTokensStart != null) { >+ for (int i = 0; i <= this.data.removedTokensPtr; i++) { >+ if(this.data.removedTokensStart[i] >= previousLocation && >+ this.data.removedTokensStart[i] <= this.startPosition && >+ this.data.removedTokensEnd[i] >= this.currentPosition - 1) { >+ this.data.removedTokenUsed[i] = true; >+ this.currentPosition = this.data.removedTokensEnd[i] + 1; >+ return getNextToken(); >+ } >+ } >+ } >+ return currentToken; >+ } >+ >+ public char[] getCurrentIdentifierSource() { >+ if(this.fakeTokenSource != null) return this.fakeTokenSource; >+ return super.getCurrentIdentifierSource(); >+ } >+ >+ public char[] getCurrentTokenSourceString() { >+ if(this.fakeTokenSource != null) return this.fakeTokenSource; >+ return super.getCurrentTokenSourceString(); >+ } >+ >+ public char[] getCurrentTokenSource() { >+ if(this.fakeTokenSource != null) return this.fakeTokenSource; >+ return super.getCurrentTokenSource(); >+ } >+ >+ public RecoveryScannerData getData() { >+ return this.data; >+ } >+ >+ public void setData(RecoveryScannerData data) { >+ if(data == null) { >+ this.data = new RecoveryScannerData(); >+ } else { >+ this.data = data; >+ } >+ } >+} >Index: dom/org/eclipse/jdt/core/dom/ASTRecoveryPropagator.java >=================================================================== >RCS file: dom/org/eclipse/jdt/core/dom/ASTRecoveryPropagator.java >diff -N dom/org/eclipse/jdt/core/dom/ASTRecoveryPropagator.java >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ dom/org/eclipse/jdt/core/dom/ASTRecoveryPropagator.java 1 Jan 1970 00:00:00 -0000 >@@ -0,0 +1,81 @@ >+/******************************************************************************* >+ * Copyright (c) 2006 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.jdt.core.dom; >+ >+import org.eclipse.jdt.core.compiler.IProblem; >+ >+/** >+ * Internal AST visitor for propagating syntax errors. >+ */ >+class ASTRecoveryPropagator extends DefaultASTVisitor { >+ private IProblem[] problems; >+ >+ ASTRecoveryPropagator(IProblem[] problems) { >+ // visit Javadoc.tags() as well >+ this.problems = problems; >+ } >+ >+ protected boolean visitNode(ASTNode node) { >+ return checkAndTagAsMalformed(node); >+ } >+ >+ private boolean checkAndTagAsMalformed(ASTNode node) { >+ boolean tagWithErrors = false; >+ search: for (int i = 0, max = this.problems.length; i < max; i++) { >+ IProblem problem = this.problems[i]; >+ switch(problem.getID()) { >+ case IProblem.ParsingErrorOnKeywordNoSuggestion : >+ case IProblem.ParsingErrorOnKeyword : >+ case IProblem.ParsingError : >+ case IProblem.ParsingErrorNoSuggestion : >+ case IProblem.ParsingErrorInsertTokenBefore : >+ case IProblem.ParsingErrorInsertTokenAfter : >+ case IProblem.ParsingErrorDeleteToken : >+ case IProblem.ParsingErrorDeleteTokens : >+ case IProblem.ParsingErrorMergeTokens : >+ case IProblem.ParsingErrorInvalidToken : >+ case IProblem.ParsingErrorMisplacedConstruct : >+ case IProblem.ParsingErrorReplaceTokens : >+ case IProblem.ParsingErrorNoSuggestionForTokens : >+ case IProblem.ParsingErrorUnexpectedEOF : >+ case IProblem.ParsingErrorInsertToComplete : >+ case IProblem.ParsingErrorInsertToCompleteScope : >+ case IProblem.ParsingErrorInsertToCompletePhrase : >+ case IProblem.EndOfSource : >+ case IProblem.InvalidHexa : >+ case IProblem.InvalidOctal : >+ case IProblem.InvalidCharacterConstant : >+ case IProblem.InvalidEscape : >+ case IProblem.InvalidInput : >+ case IProblem.InvalidUnicodeEscape : >+ case IProblem.InvalidFloat : >+ case IProblem.NullSourceString : >+ case IProblem.UnterminatedString : >+ case IProblem.UnterminatedComment : >+ case IProblem.InvalidDigit : >+ break; >+ default: >+ continue search; >+ } >+ int problemStart = problem.getSourceStart(); >+ int problemEnd = problem.getSourceEnd(); >+ int start = node.getStartPosition(); >+ int end = start + node.getLength(); >+ if ((start <= problemStart) && (problemStart <= end) || >+ (start <= problemEnd) && (problemEnd <= end)) { >+ node.setFlags(node.getFlags() | ASTNode.RECOVERED); >+ tagWithErrors = true; >+ } >+ } >+ return tagWithErrors; >+ } >+}
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 42253
:
31884
| 33154 |
34338