View | Details | Raw Unified | Return to bug 42253 | Differences between
and this patch

Collapse All | Expand All

(-)dom/org/eclipse/jdt/core/dom/ASTParser.java (-9 / +9 lines)
Lines 970-976 Link Here
970
							}
970
							}
971
						}
971
						}
972
					}
972
					}
973
					rootNodeToCompilationUnit(ast, compilationUnit, block, recordedParsingInformation);
973
					rootNodeToCompilationUnit(ast, compilationUnit, block, recordedParsingInformation, data);
974
					ast.setDefaultNodeFlag(0);
974
					ast.setDefaultNodeFlag(0);
975
					ast.setOriginalModificationCount(ast.modificationCount());
975
					ast.setOriginalModificationCount(ast.modificationCount());
976
					return block;
976
					return block;
Lines 993-999 Link Here
993
				compilationUnit.setLineEndTable(recordedParsingInformation.lineEnds);
993
				compilationUnit.setLineEndTable(recordedParsingInformation.lineEnds);
994
				if (expression != null) {
994
				if (expression != null) {
995
					Expression expression2 = converter.convert(expression);
995
					Expression expression2 = converter.convert(expression);
996
					rootNodeToCompilationUnit(expression2.getAST(), compilationUnit, expression2, codeSnippetParsingUtil.recordedParsingInformation);
996
					rootNodeToCompilationUnit(expression2.getAST(), compilationUnit, expression2, codeSnippetParsingUtil.recordedParsingInformation, null);
997
					ast.setDefaultNodeFlag(0);
997
					ast.setDefaultNodeFlag(0);
998
					ast.setOriginalModificationCount(ast.modificationCount());
998
					ast.setOriginalModificationCount(ast.modificationCount());
999
					return expression2;
999
					return expression2;
Lines 1016-1022 Link Here
1016
				compilationUnit.setLineEndTable(recordedParsingInformation.lineEnds);
1016
				compilationUnit.setLineEndTable(recordedParsingInformation.lineEnds);
1017
				if (nodes != null) {
1017
				if (nodes != null) {
1018
					TypeDeclaration typeDeclaration = converter.convert(nodes);
1018
					TypeDeclaration typeDeclaration = converter.convert(nodes);
1019
					rootNodeToCompilationUnit(typeDeclaration.getAST(), compilationUnit, typeDeclaration, codeSnippetParsingUtil.recordedParsingInformation);
1019
					rootNodeToCompilationUnit(typeDeclaration.getAST(), compilationUnit, typeDeclaration, codeSnippetParsingUtil.recordedParsingInformation, null);
1020
					ast.setDefaultNodeFlag(0);
1020
					ast.setDefaultNodeFlag(0);
1021
					ast.setOriginalModificationCount(ast.modificationCount());
1021
					ast.setOriginalModificationCount(ast.modificationCount());
1022
					return typeDeclaration;
1022
					return typeDeclaration;
Lines 1033-1046 Link Here
1033
		throw new IllegalStateException();
1033
		throw new IllegalStateException();
1034
	}
1034
	}
1035
1035
1036
	private void propagateErrors(ASTNode astNode, IProblem[] problems) {
1036
	private void propagateErrors(ASTNode astNode, IProblem[] problems, RecoveryScannerData data) {
1037
		ASTSyntaxErrorPropagator syntaxErrorPropagator = new ASTSyntaxErrorPropagator(problems);
1037
		ASTSyntaxErrorPropagator syntaxErrorPropagator = new ASTSyntaxErrorPropagator(problems);
1038
		astNode.accept(syntaxErrorPropagator);
1038
		astNode.accept(syntaxErrorPropagator);
1039
		ASTRecoveryPropagator recoveryPropagator = new ASTRecoveryPropagator(problems);
1039
		ASTRecoveryPropagator recoveryPropagator = new ASTRecoveryPropagator(problems, data);
1040
		astNode.accept(recoveryPropagator);
1040
		astNode.accept(recoveryPropagator);
1041
	}
1041
	}
1042
	
1042
	
1043
	private void rootNodeToCompilationUnit(AST ast, CompilationUnit compilationUnit, ASTNode node, RecordedParsingInformation recordedParsingInformation) {
1043
	private void rootNodeToCompilationUnit(AST ast, CompilationUnit compilationUnit, ASTNode node, RecordedParsingInformation recordedParsingInformation, RecoveryScannerData data) {
1044
		final int problemsCount = recordedParsingInformation.problemsCount;
1044
		final int problemsCount = recordedParsingInformation.problemsCount;
1045
		switch(node.getNodeType()) {
1045
		switch(node.getNodeType()) {
1046
			case ASTNode.BLOCK :
1046
			case ASTNode.BLOCK :
Lines 1050-1056 Link Here
1050
						// propagate and record problems
1050
						// propagate and record problems
1051
						final IProblem[] problems = recordedParsingInformation.problems;
1051
						final IProblem[] problems = recordedParsingInformation.problems;
1052
						for (int i = 0, max = block.statements().size(); i < max; i++) {
1052
						for (int i = 0, max = block.statements().size(); i < max; i++) {
1053
							propagateErrors((ASTNode) block.statements().get(i), problems);
1053
							propagateErrors((ASTNode) block.statements().get(i), problems, data);
1054
						}
1054
						}
1055
						compilationUnit.setProblems(problems);
1055
						compilationUnit.setProblems(problems);
1056
					}
1056
					}
Lines 1068-1074 Link Here
1068
						// propagate and record problems
1068
						// propagate and record problems
1069
						final IProblem[] problems = recordedParsingInformation.problems;
1069
						final IProblem[] problems = recordedParsingInformation.problems;
1070
						for (int i = 0, max = typeDeclaration.bodyDeclarations().size(); i < max; i++) {
1070
						for (int i = 0, max = typeDeclaration.bodyDeclarations().size(); i < max; i++) {
1071
							propagateErrors((ASTNode) typeDeclaration.bodyDeclarations().get(i), problems);
1071
							propagateErrors((ASTNode) typeDeclaration.bodyDeclarations().get(i), problems, data);
1072
						}
1072
						}
1073
						compilationUnit.setProblems(problems);
1073
						compilationUnit.setProblems(problems);
1074
					}
1074
					}
Lines 1081-1087 Link Here
1081
					if (problemsCount != 0) {
1081
					if (problemsCount != 0) {
1082
						// propagate and record problems
1082
						// propagate and record problems
1083
						final IProblem[] problems = recordedParsingInformation.problems;
1083
						final IProblem[] problems = recordedParsingInformation.problems;
1084
						propagateErrors(expression, problems);
1084
						propagateErrors(expression, problems, data);
1085
						compilationUnit.setProblems(problems);
1085
						compilationUnit.setProblems(problems);
1086
					}
1086
					}
1087
					ExpressionStatement expressionStatement = ast.newExpressionStatement(expression);
1087
					ExpressionStatement expressionStatement = ast.newExpressionStatement(expression);
(-)dom/org/eclipse/jdt/core/dom/ASTRecoveryPropagator.java (-11 / +267 lines)
Lines 11-37 Link Here
11
11
12
package org.eclipse.jdt.core.dom;
12
package org.eclipse.jdt.core.dom;
13
13
14
import java.util.Vector;
15
14
import org.eclipse.jdt.core.compiler.IProblem;
16
import org.eclipse.jdt.core.compiler.IProblem;
17
import org.eclipse.jdt.internal.compiler.parser.RecoveryScannerData;
18
import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
19
import org.eclipse.jdt.internal.compiler.util.HashtableOfObjectToIntArray;
15
20
16
/**
21
/**
17
 * Internal AST visitor for propagating syntax errors.
22
 * Internal AST visitor for propagating syntax errors.
18
 */
23
 */
19
class ASTRecoveryPropagator extends DefaultASTVisitor {
24
class ASTRecoveryPropagator extends DefaultASTVisitor {
25
	private static final int NOTHING = -1;
26
	HashtableOfObjectToIntArray endingTokens = new HashtableOfObjectToIntArray();
27
	{
28
		this.endingTokens.put(AnonymousClassDeclaration.class, new int[]{TerminalTokens.TokenNameRBRACE});
29
		this.endingTokens.put(ArrayAccess.class, new int[]{TerminalTokens.TokenNameRBRACKET});
30
		this.endingTokens.put(ArrayCreation.class, new int[]{NOTHING, TerminalTokens.TokenNameRBRACKET});
31
		this.endingTokens.put(ArrayInitializer.class, new int[]{TerminalTokens.TokenNameRBRACE});
32
		this.endingTokens.put(ArrayType.class, new int[]{TerminalTokens.TokenNameRBRACKET});
33
		this.endingTokens.put(AssertStatement.class, new int[]{TerminalTokens.TokenNameSEMICOLON});
34
		this.endingTokens.put(Block.class, new int[]{TerminalTokens.TokenNameRBRACE});
35
		this.endingTokens.put(BooleanLiteral.class, new int[]{TerminalTokens.TokenNamefalse, TerminalTokens.TokenNametrue});
36
		this.endingTokens.put(BreakStatement.class, new int[]{TerminalTokens.TokenNameSEMICOLON});
37
		this.endingTokens.put(CharacterLiteral.class, new int[]{TerminalTokens.TokenNameCharacterLiteral});
38
		this.endingTokens.put(ClassInstanceCreation.class, new int[]{TerminalTokens.TokenNameRBRACE, TerminalTokens.TokenNameRPAREN});
39
		this.endingTokens.put(ConstructorInvocation.class, new int[]{TerminalTokens.TokenNameSEMICOLON});
40
		this.endingTokens.put(ContinueStatement.class, new int[]{TerminalTokens.TokenNameSEMICOLON});
41
		this.endingTokens.put(DoStatement.class, new int[]{TerminalTokens.TokenNameRPAREN});
42
		this.endingTokens.put(EmptyStatement.class, new int[]{TerminalTokens.TokenNameSEMICOLON});
43
		this.endingTokens.put(ExpressionStatement.class, new int[]{TerminalTokens.TokenNameSEMICOLON});
44
		this.endingTokens.put(FieldDeclaration.class, new int[]{TerminalTokens.TokenNameSEMICOLON});
45
		this.endingTokens.put(ImportDeclaration.class, new int[]{TerminalTokens.TokenNameSEMICOLON});
46
		this.endingTokens.put(Initializer.class, new int[]{TerminalTokens.TokenNameRBRACE});
47
		this.endingTokens.put(MethodDeclaration.class, new int[]{NOTHING, TerminalTokens.TokenNameSEMICOLON});
48
		this.endingTokens.put(MethodInvocation.class, new int[]{TerminalTokens.TokenNameRPAREN});
49
		this.endingTokens.put(NullLiteral.class, new int[]{TerminalTokens.TokenNamenull});
50
		this.endingTokens.put(NumberLiteral.class, new int[]{TerminalTokens.TokenNameIntegerLiteral, TerminalTokens.TokenNameLongLiteral, TerminalTokens.TokenNameFloatingPointLiteral, TerminalTokens.TokenNameDoubleLiteral});
51
		this.endingTokens.put(PackageDeclaration.class, new int[]{TerminalTokens.TokenNameSEMICOLON});
52
		this.endingTokens.put(ParenthesizedExpression.class, new int[]{TerminalTokens.TokenNameRPAREN});
53
		this.endingTokens.put(PostfixExpression.class, new int[]{TerminalTokens.TokenNamePLUS_PLUS, TerminalTokens.TokenNameMINUS_MINUS});
54
		this.endingTokens.put(PrimitiveType.class, new int[]{TerminalTokens.TokenNamebyte, TerminalTokens.TokenNameshort, TerminalTokens.TokenNamechar, TerminalTokens.TokenNameint, TerminalTokens.TokenNamelong, TerminalTokens.TokenNamefloat, TerminalTokens.TokenNameboolean, TerminalTokens.TokenNamedouble, TerminalTokens.TokenNamevoid});
55
		this.endingTokens.put(ReturnStatement.class, new int[]{TerminalTokens.TokenNameSEMICOLON});
56
		this.endingTokens.put(SimpleName.class, new int[]{TerminalTokens.TokenNameIdentifier});
57
		this.endingTokens.put(SingleVariableDeclaration.class, new int[]{TerminalTokens.TokenNameSEMICOLON});
58
		this.endingTokens.put(StringLiteral.class, new int[]{TerminalTokens.TokenNameStringLiteral});
59
		this.endingTokens.put(SuperConstructorInvocation.class, new int[]{TerminalTokens.TokenNameSEMICOLON});
60
		this.endingTokens.put(SuperMethodInvocation.class, new int[]{TerminalTokens.TokenNameRPAREN});
61
		this.endingTokens.put(SwitchCase.class, new int[]{TerminalTokens.TokenNameCOLON});
62
		this.endingTokens.put(SwitchStatement.class, new int[]{TerminalTokens.TokenNameRBRACE});
63
		this.endingTokens.put(SynchronizedStatement.class, new int[]{TerminalTokens.TokenNameRBRACE});
64
		this.endingTokens.put(ThisExpression.class, new int[]{TerminalTokens.TokenNamethis});
65
		this.endingTokens.put(ThrowStatement.class, new int[]{TerminalTokens.TokenNameSEMICOLON});
66
		this.endingTokens.put(TypeDeclaration.class, new int[]{TerminalTokens.TokenNameRBRACE});
67
		this.endingTokens.put(TypeLiteral.class, new int[]{TerminalTokens.TokenNameclass});
68
		this.endingTokens.put(VariableDeclarationStatement.class, new int[]{TerminalTokens.TokenNameSEMICOLON});
69
	}
70
20
	private IProblem[] problems;
71
	private IProblem[] problems;
72
	private boolean[] usedOrIrrelevantProblems;
73
	
74
	private RecoveryScannerData data;
75
	private int blockDepth = 0;
76
	private int lastEnd;
77
	
78
	private int[] insertedTokensKind;
79
	private int[] insertedTokensPosition;
80
	private boolean[] insertedTokensFlagged;
81
	
82
	private boolean[] removedTokensFlagged;
83
	private boolean[] replacedTokensFlagged;
84
	
85
	private Vector stack = new Vector();
21
	
86
	
22
	ASTRecoveryPropagator(IProblem[] problems) {
87
	ASTRecoveryPropagator(IProblem[] problems, RecoveryScannerData data) {
23
		// visit Javadoc.tags() as well
88
		// visit Javadoc.tags() as well
24
		this.problems = problems;
89
		this.problems = problems;
90
		this.usedOrIrrelevantProblems = new boolean[problems.length];
91
		
92
		this.data = data;
93
		
94
		if(this.data != null) {
95
			
96
			int length = 0;
97
			for (int i = 0; i < data.insertedTokensPtr + 1; i++) {
98
				length += data.insertedTokens[i].length;
99
			}
100
			this.insertedTokensKind = new int[length];
101
			this.insertedTokensPosition = new int[length];
102
			this.insertedTokensFlagged = new boolean[length];
103
			int tokenCount = 0;
104
			for (int i = 0; i < data.insertedTokensPtr + 1; i++) {
105
				for (int j = 0; j < data.insertedTokens[i].length; j++) {
106
					this.insertedTokensKind[tokenCount] = data.insertedTokens[i][j];
107
					this.insertedTokensPosition[tokenCount] = data.insertedTokensPosition[i];
108
					tokenCount++;
109
				}
110
			}
111
			
112
			if(data.removedTokensPtr != -1) {
113
				this.removedTokensFlagged = new boolean[data.removedTokensPtr + 1];
114
			}
115
			if(data.replacedTokensPtr != -1) {
116
				this.replacedTokensFlagged = new boolean[data.replacedTokensPtr + 1];
117
			}
118
		}
119
	}
120
121
	public void endVisit(Block node) {
122
		this.blockDepth--;
123
		if(this.blockDepth <= 0) {
124
			flagNodeWithInsertedTokens();
125
		}
126
		super.endVisit(node);
127
	}
128
129
	
130
131
	public boolean visit(Block node) {
132
		boolean visitChildren = super.visit(node);
133
		this.blockDepth++;
134
		return visitChildren;
25
	}
135
	}
26
	
136
	
27
	protected boolean visitNode(ASTNode node) {
137
	protected boolean visitNode(ASTNode node) {
28
		return checkAndTagAsMalformed(node);
138
		if(this.blockDepth > 0) {
139
			int start = node.getStartPosition();
140
			int end = start + node.getLength() - 1;
141
			
142
			// continue to visit the node only if it contains tokens modifications
143
			
144
			if(this.insertedTokensFlagged != null) {
145
				for (int i = 0; i < this.insertedTokensFlagged.length; i++) {
146
					if(this.insertedTokensPosition[i] >= start &&
147
							this.insertedTokensPosition[i] <= end) {
148
						return true;
149
					}
150
				}
151
			}
152
			
153
			if(this.removedTokensFlagged != null) {
154
				for (int i = 0; i <= this.data.removedTokensPtr; i++) {
155
					if(this.data.removedTokensStart[i] >= start &&
156
							this.data.removedTokensEnd[i] <= end) {
157
						return true;
158
					}
159
				}
160
			}
161
			
162
			if(this.replacedTokensFlagged != null) {
163
				for (int i = 0; i <= this.data.removedTokensPtr; i++) {
164
					if(this.data.replacedTokensStart[i] >= start &&
165
							this.data.replacedTokensEnd[i] <= end) {
166
						return true;
167
					}
168
				}
169
			}
170
			
171
			return false;
172
		}
173
		return true;
174
	}
175
176
	protected void endVisitNode(ASTNode node) {
177
		int start = node.getStartPosition();
178
		int end = start + node.getLength() - 1;
179
		
180
		// is inside diet part of the ast
181
		if(this.blockDepth < 1) {
182
			if(this.markIncludedProblems(start, end)) {
183
				node.setFlags(node.getFlags() | ASTNode.RECOVERED);
184
			}
185
		} else {			
186
			this.markIncludedProblems(start, end);
187
			
188
			if(this.insertedTokensFlagged != null) {
189
				if(this.lastEnd != end) {
190
					flagNodeWithInsertedTokens();
191
				}
192
				this.stack.add(node);
193
			}
194
195
			if(this.removedTokensFlagged != null) {
196
				for (int i = 0; i <= this.data.removedTokensPtr; i++) {
197
					if(!this.removedTokensFlagged[i] &&
198
							this.data.removedTokensStart[i] >= start &&
199
							this.data.removedTokensEnd[i] <= end) {
200
						node.setFlags(node.getFlags() | ASTNode.RECOVERED);
201
						this.removedTokensFlagged[i] = true;
202
					}
203
				}
204
			}
205
			
206
			if(this.replacedTokensFlagged != null) {
207
				for (int i = 0; i <= this.data.replacedTokensPtr; i++) {
208
					if(!this.replacedTokensFlagged[i] &&
209
							this.data.replacedTokensStart[i] >= start &&
210
							this.data.replacedTokensEnd[i] <= end) {
211
						node.setFlags(node.getFlags() | ASTNode.RECOVERED);
212
						this.replacedTokensFlagged[i] = true;
213
					}
214
				}
215
			}
216
		}
217
		this.lastEnd = end;
29
	}
218
	}
30
	
219
	
31
	private boolean checkAndTagAsMalformed(ASTNode node) {
220
	private void flagNodeWithInsertedTokens() {
32
		boolean tagWithErrors = false;
221
		if(this.insertedTokensKind != null && this.insertedTokensKind.length > 0) {
33
		search: for (int i = 0, max = this.problems.length; i < max; i++) {
222
			int s = this.stack.size();
223
			for (int i = s - 1; i > -1; i--) {
224
				flagNodesWithInsertedTokensAtEnd((ASTNode)this.stack.get(i));
225
			}
226
			for (int i = 0; i < s; i++) {
227
				flagNodesWithInsertedTokensInside((ASTNode)this.stack.get(i));
228
			}
229
			this.stack = new Vector();
230
		}
231
	}
232
	
233
	private boolean flagNodesWithInsertedTokensAtEnd(ASTNode node) {
234
		int[] expectedEndingToken = this.endingTokens.get(node.getClass());
235
		if (expectedEndingToken != null) {
236
			int start = node.getStartPosition();
237
			int end = start + node.getLength() - 1;
238
			
239
			boolean flagParent = false;
240
			done : for (int i = this.insertedTokensKind.length - 1; i > -1 ; i--) {
241
				if(!this.insertedTokensFlagged[i] &&
242
						this.insertedTokensPosition[i] == end){
243
					this.insertedTokensFlagged[i] = true;
244
					for (int j = 0; j < expectedEndingToken.length; j++) {
245
						if(expectedEndingToken[j] == this.insertedTokensKind[i]) {
246
							node.setFlags(node.getFlags() | ASTNode.RECOVERED);
247
							break done;
248
						}
249
					}
250
					flagParent = true;
251
				}
252
			}
253
			
254
			if(flagParent) {
255
				ASTNode parent = node.getParent();
256
				while (parent != null) {
257
					parent.setFlags(node.getFlags() | ASTNode.RECOVERED);
258
					if((parent.getStartPosition() + parent.getLength() - 1) != end) {
259
						parent = null;
260
					} else {
261
						parent = parent.getParent();
262
					}
263
				}
264
			}
265
		}
266
		return true;
267
	}
268
	
269
	private boolean flagNodesWithInsertedTokensInside(ASTNode node) {
270
		int start = node.getStartPosition();
271
		int end = start + node.getLength() - 1;
272
		for (int i = 0; i < this.insertedTokensKind.length; i++) {
273
			if(!this.insertedTokensFlagged[i] &&
274
					start <= this.insertedTokensPosition[i] &&
275
					this.insertedTokensPosition[i] < end){
276
				node.setFlags(node.getFlags() | ASTNode.RECOVERED);
277
				this.insertedTokensFlagged[i] = true;
278
			}
279
		}
280
		return true;
281
	}
282
	
283
	private boolean markIncludedProblems(int start, int end) {
284
		boolean foundProblems = false;
285
		next: for (int i = 0, max = this.problems.length; i < max; i++) {
34
			IProblem problem = this.problems[i];
286
			IProblem problem = this.problems[i];
287
			
288
			if(this.usedOrIrrelevantProblems[i]) continue next;
289
			
35
			switch(problem.getID()) {
290
			switch(problem.getID()) {
36
				case IProblem.ParsingErrorOnKeywordNoSuggestion :
291
				case IProblem.ParsingErrorOnKeywordNoSuggestion :
37
				case IProblem.ParsingErrorOnKeyword :
292
				case IProblem.ParsingErrorOnKeyword :
Lines 64-81 Link Here
64
				case IProblem.InvalidDigit :
319
				case IProblem.InvalidDigit :
65
					break;
320
					break;
66
				default:
321
				default:
67
					continue search;
322
					this.usedOrIrrelevantProblems[i] = true;
323
					continue next;
324
					
68
			}
325
			}
326
			
69
			int problemStart = problem.getSourceStart();
327
			int problemStart = problem.getSourceStart();
70
			int problemEnd = problem.getSourceEnd();
328
			int problemEnd = problem.getSourceEnd();
71
			int start = node.getStartPosition();
72
			int end = start + node.getLength();
73
			if ((start <= problemStart) && (problemStart <= end) ||
329
			if ((start <= problemStart) && (problemStart <= end) ||
74
					(start <= problemEnd) && (problemEnd <= end)) {
330
					(start <= problemEnd) && (problemEnd <= end)) {
75
				node.setFlags(node.getFlags() | ASTNode.RECOVERED);
331
				this.usedOrIrrelevantProblems[i] = true;
76
				tagWithErrors = true;
332
				foundProblems = true;
77
			}
333
			}
78
		}
334
		}
79
		return tagWithErrors;
335
		return foundProblems;
80
	}
336
	}
81
}
337
}
(-)dom/org/eclipse/jdt/core/dom/ASTConverter.java (-5 / +7 lines)
Lines 114-120 Link Here
114
						}
114
						}
115
				}
115
				}
116
			}
116
			}
117
			if(this.scanner instanceof RecoveryScanner && ((RecoveryScanner)this.scanner).isFakeTokenInserted()) {
117
			if(this.scanner instanceof RecoveryScanner && ((RecoveryScanner)this.scanner).isInsertedToken()) {
118
				expression.sourceEnd =  this.scanner.startPosition;
118
				expression.sourceEnd =  this.scanner.startPosition;
119
			} else {
119
			} else {
120
				expression.sourceEnd = this.scanner.startPosition - 1;
120
				expression.sourceEnd = this.scanner.startPosition - 1;
Lines 1196-1202 Link Here
1196
	
1196
	
1197
	public CompilationUnit convert(org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration unit, char[] source) {
1197
	public CompilationUnit convert(org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration unit, char[] source) {
1198
		if(unit.compilationResult.recoveryScannerData != null) {
1198
		if(unit.compilationResult.recoveryScannerData != null) {
1199
			this.scanner = new RecoveryScanner(this.scanner, unit.compilationResult.recoveryScannerData.removeUnused());
1199
			RecoveryScanner recoveryScanner = new RecoveryScanner(this.scanner, unit.compilationResult.recoveryScannerData.removeUnused());
1200
			this.scanner = recoveryScanner;
1200
			this.docParser.scanner = this.scanner;
1201
			this.docParser.scanner = this.scanner;
1201
		}
1202
		}
1202
		this.compilationUnitSource = source;
1203
		this.compilationUnitSource = source;
Lines 1257-1263 Link Here
1257
			}
1258
			}
1258
			ASTSyntaxErrorPropagator syntaxErrorPropagator = new ASTSyntaxErrorPropagator(resizedProblems);
1259
			ASTSyntaxErrorPropagator syntaxErrorPropagator = new ASTSyntaxErrorPropagator(resizedProblems);
1259
			compilationUnit.accept(syntaxErrorPropagator);
1260
			compilationUnit.accept(syntaxErrorPropagator);
1260
			ASTRecoveryPropagator recoveryPropagator = new ASTRecoveryPropagator(resizedProblems);
1261
			ASTRecoveryPropagator recoveryPropagator =
1262
				new ASTRecoveryPropagator(resizedProblems, unit.compilationResult.recoveryScannerData);
1261
			compilationUnit.accept(recoveryPropagator);
1263
			compilationUnit.accept(recoveryPropagator);
1262
			compilationUnit.setProblems(resizedProblems);
1264
			compilationUnit.setProblems(resizedProblems);
1263
		}
1265
		}
Lines 4125-4137 Link Here
4125
						balance --;
4127
						balance --;
4126
						break;
4128
						break;
4127
					case TerminalTokens.TokenNameCOMMA :
4129
					case TerminalTokens.TokenNameCOMMA :
4128
						if(this.scanner instanceof RecoveryScanner && ((RecoveryScanner)this.scanner).isFakeTokenInserted()) {
4130
						if(this.scanner instanceof RecoveryScanner && ((RecoveryScanner)this.scanner).isInsertedToken()) {
4129
							return this.scanner.startPosition;
4131
							return this.scanner.startPosition;
4130
						}
4132
						}
4131
						if (balance == 0) return this.scanner.startPosition - 1;
4133
						if (balance == 0) return this.scanner.startPosition - 1;
4132
						break;
4134
						break;
4133
					case TerminalTokens.TokenNameSEMICOLON :
4135
					case TerminalTokens.TokenNameSEMICOLON :
4134
						if(this.scanner instanceof RecoveryScanner && ((RecoveryScanner)this.scanner).isFakeTokenInserted()) {
4136
						if(this.scanner instanceof RecoveryScanner && ((RecoveryScanner)this.scanner).isInsertedToken()) {
4135
							return this.scanner.startPosition;
4137
							return this.scanner.startPosition;
4136
						}
4138
						}
4137
						return this.scanner.startPosition - 1;
4139
						return this.scanner.startPosition - 1;
(-)model/org/eclipse/jdt/core/ICompilationUnit.java (+5 lines)
Lines 512-517 Link Here
512
 * creation of the DOM AST was not requested, or if the requested level of AST
512
 * creation of the DOM AST was not requested, or if the requested level of AST
513
 * API is not supported, or if the working copy was already consistent.
513
 * API is not supported, or if the working copy was already consistent.
514
 * </p>
514
 * </p>
515
 * 
516
 * <p>
517
 * The statement recovery is disable if this method is use. To recover statements with syntax
518
 * errors {@link #reconcile(int, boolean, boolean, WorkingCopyOwner, IProgressMonitor)} must be use.
519
 * </p>
515
 *
520
 *
516
 * @param astLevel either {@link #NO_AST} if no AST is wanted,
521
 * @param astLevel either {@link #NO_AST} if no AST is wanted,
517
 * or the {@linkplain AST#newAST(int) AST API level} of the AST if one is wanted
522
 * or the {@linkplain AST#newAST(int) AST API level} of the AST if one is wanted
(-)compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java (-3 / +24 lines)
Lines 2654-2664 Link Here
2654
}
2654
}
2655
protected void consumeEmptyStatement() {
2655
protected void consumeEmptyStatement() {
2656
	// EmptyStatement ::= ';'
2656
	// EmptyStatement ::= ';'
2657
	if (this.scanner.source[this.endStatementPosition] == ';') {
2657
	char[] source = this.scanner.source;
2658
	if (source[this.endStatementPosition] == ';') {
2658
		pushOnAstStack(new EmptyStatement(this.endStatementPosition, this.endStatementPosition));
2659
		pushOnAstStack(new EmptyStatement(this.endStatementPosition, this.endStatementPosition));
2659
	} else {
2660
	} else {
2660
		// we have a Unicode for the ';' (/u003B)
2661
		if(source.length > 5) {
2661
		pushOnAstStack(new EmptyStatement(this.endStatementPosition - 5, this.endStatementPosition));
2662
			int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
2663
			int pos = this.endStatementPosition - 4;
2664
			while (source[pos] == 'u') {
2665
				pos--;
2666
			}
2667
			if (source[pos] == '\\' &&
2668
					!((c1 = Character.getNumericValue(source[this.endStatementPosition - 3])) > 15
2669
						|| c1 < 0
2670
						|| (c2 = Character.getNumericValue(source[this.endStatementPosition - 2])) > 15
2671
						|| c2 < 0
2672
						|| (c3 = Character.getNumericValue(source[this.endStatementPosition - 1])) > 15
2673
						|| c3 < 0
2674
						|| (c4 = Character.getNumericValue(source[this.endStatementPosition])) > 15
2675
						|| c4 < 0) &&
2676
					((char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4)) == ';'){
2677
				// we have a Unicode for the ';' (/u003B)
2678
				pushOnAstStack(new EmptyStatement(pos, this.endStatementPosition));
2679
				return;
2680
			}
2681
		}
2682
		pushOnAstStack(new EmptyStatement(this.endStatementPosition, this.endStatementPosition));
2662
	}
2683
	}
2663
}
2684
}
2664
protected void consumeEmptySwitchBlock() {
2685
protected void consumeEmptySwitchBlock() {
(-)compiler/org/eclipse/jdt/internal/compiler/parser/RecoveryScanner.java (-2 / +11 lines)
Lines 21-26 Link Here
21
	private int pendingTokensPtr = -1;
21
	private int pendingTokensPtr = -1;
22
	private char[] fakeTokenSource = null;
22
	private char[] fakeTokenSource = null;
23
	private boolean isInserted = true;
23
	private boolean isInserted = true;
24
	private boolean precededByRemoved = false;
24
	private int skipNextInsertedTokens = -1;
25
	private int skipNextInsertedTokens = -1;
25
26
26
	public boolean record = true;
27
	public boolean record = true;
Lines 120-125 Link Here
120
		}
121
		}
121
		
122
		
122
		this.fakeTokenSource = null;
123
		this.fakeTokenSource = null;
124
		this.precededByRemoved = false;
123
		
125
		
124
		if(this.data.insertedTokens != null) {
126
		if(this.data.insertedTokens != null) {
125
			for (int i = 0; i <= this.data.insertedTokensPtr; i++) {
127
			for (int i = 0; i <= this.data.insertedTokensPtr; i++) {
Lines 128-133 Link Here
128
					this.pendingTokens = this.data.insertedTokens[i];
130
					this.pendingTokens = this.data.insertedTokens[i];
129
					this.pendingTokensPtr = this.data.insertedTokens[i].length - 1;
131
					this.pendingTokensPtr = this.data.insertedTokens[i].length - 1;
130
					this.fakeTokenSource = CharOperation.NO_CHAR;
132
					this.fakeTokenSource = CharOperation.NO_CHAR;
133
					this.isInserted = true;
131
					this.startPosition = this.currentPosition - 1;
134
					this.startPosition = this.currentPosition - 1;
132
					this.skipNextInsertedTokens = i;
135
					this.skipNextInsertedTokens = i;
133
					return this.pendingTokens[this.pendingTokensPtr--];
136
					return this.pendingTokens[this.pendingTokensPtr--];
Lines 148-153 Link Here
148
					this.pendingTokens = this.data.replacedTokens[i];
151
					this.pendingTokens = this.data.replacedTokens[i];
149
					this.pendingTokensPtr = this.data.replacedTokens[i].length - 1;
152
					this.pendingTokensPtr = this.data.replacedTokens[i].length - 1;
150
					this.fakeTokenSource = CharOperation.NO_CHAR;
153
					this.fakeTokenSource = CharOperation.NO_CHAR;
154
					this.isInserted = false;
151
					this.currentPosition = this.data.replacedTokensEnd[i] + 1;
155
					this.currentPosition = this.data.replacedTokensEnd[i] + 1;
152
					return this.pendingTokens[this.pendingTokensPtr--];
156
					return this.pendingTokens[this.pendingTokensPtr--];
153
				}
157
				}
Lines 160-165 Link Here
160
						this.data.removedTokensEnd[i] >= this.currentPosition - 1) {
164
						this.data.removedTokensEnd[i] >= this.currentPosition - 1) {
161
					this.data.removedTokenUsed[i] = true;
165
					this.data.removedTokenUsed[i] = true;
162
					this.currentPosition = this.data.removedTokensEnd[i] + 1;
166
					this.currentPosition = this.data.removedTokensEnd[i] + 1;
167
					this.precededByRemoved = false;
163
					return getNextToken();
168
					return getNextToken();
164
				}
169
				}
165
			}
170
			}
Lines 190-203 Link Here
190
		return this.fakeTokenSource != null;
195
		return this.fakeTokenSource != null;
191
	}
196
	}
192
	
197
	
193
	public boolean isFakeTokenInserted() {
198
	public boolean isInsertedToken() {
194
		return this.fakeTokenSource != null && this.isInserted;
199
		return this.fakeTokenSource != null && this.isInserted;
195
	}
200
	}
196
	
201
	
197
	public boolean isFakeTokenReplaced() {
202
	public boolean isReplacedToken() {
198
		return this.fakeTokenSource != null && !this.isInserted;
203
		return this.fakeTokenSource != null && !this.isInserted;
199
	}
204
	}
200
	
205
	
206
	public boolean isPrecededByRemovedToken() {
207
		return this.precededByRemoved;
208
	}
209
	
201
	public void setData(RecoveryScannerData data) {
210
	public void setData(RecoveryScannerData data) {
202
		if(data == null) {
211
		if(data == null) {
203
			this.data = new RecoveryScannerData();
212
			this.data = new RecoveryScannerData();
(-)compiler/org/eclipse/jdt/internal/compiler/util/HashtableOfObjectToIntArray.java (+147 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2005 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.jdt.internal.compiler.util;
12
13
/**
14
 * Hashtable of {Object --> int[] }
15
 */
16
public final class HashtableOfObjectToIntArray implements Cloneable {
17
	
18
	// to avoid using Enumerations, walk the individual tables skipping nulls
19
	public Object[] keyTable;
20
	public int[][] valueTable;
21
22
	public int elementSize; // number of elements in the table
23
	int threshold;
24
25
	public HashtableOfObjectToIntArray() {
26
		this(13);
27
	}
28
29
	public HashtableOfObjectToIntArray(int size) {
30
31
		this.elementSize = 0;
32
		this.threshold = size; // size represents the expected number of elements
33
		int extraRoom = (int) (size * 1.75f);
34
		if (this.threshold == extraRoom)
35
			extraRoom++;
36
		this.keyTable = new Object[extraRoom];
37
		this.valueTable = new int[extraRoom][];
38
	}
39
40
	public Object clone() throws CloneNotSupportedException {
41
		HashtableOfObjectToIntArray result = (HashtableOfObjectToIntArray) super.clone();
42
		result.elementSize = this.elementSize;
43
		result.threshold = this.threshold;
44
45
		int length = this.keyTable.length;
46
		result.keyTable = new Object[length];
47
		System.arraycopy(this.keyTable, 0, result.keyTable, 0, length);
48
49
		length = this.valueTable.length;
50
		result.valueTable = new int[length][];
51
		System.arraycopy(this.valueTable, 0, result.valueTable, 0, length);
52
		return result;
53
	}
54
55
	public boolean containsKey(Object key) {
56
57
		int index = (key.hashCode()& 0x7FFFFFFF) % this.valueTable.length;
58
		Object currentKey;
59
		while ((currentKey = this.keyTable[index]) != null) {
60
			if (currentKey.equals(key))
61
				return true;
62
			index = (index + 1) % this.keyTable.length;
63
		}
64
		return false;
65
	}
66
67
	public int[] get(Object key) {
68
69
		int index = (key.hashCode()& 0x7FFFFFFF) % this.valueTable.length;
70
		Object currentKey;
71
		while ((currentKey = this.keyTable[index]) != null) {
72
			if (currentKey.equals(key))
73
				return this.valueTable[index];
74
			index = (index + 1) % this.keyTable.length;
75
		}
76
		return null;
77
	}
78
79
	public void keysToArray(Object[] array) {
80
		int index = 0;
81
		for (int i=0, length=this.keyTable.length; i<length; i++) {
82
			if (this.keyTable[i] != null)
83
				array[index++] = this.keyTable[i];
84
		}
85
	}
86
87
	public int[] put(Object key, int[] value) {
88
89
		int index = (key.hashCode()& 0x7FFFFFFF) % this.valueTable.length;
90
		Object currentKey;
91
		while ((currentKey = this.keyTable[index]) != null) {
92
			if (currentKey.equals(key))
93
				return this.valueTable[index] = value;
94
			index = (index + 1) % this.keyTable.length;
95
		}
96
		this.keyTable[index] = key;
97
		this.valueTable[index] = value;
98
99
		// assumes the threshold is never equal to the size of the table
100
		if (++elementSize > threshold)
101
			rehash();
102
		return value;
103
	}
104
105
	public int[] removeKey(Object key) {
106
107
		int index = (key.hashCode()& 0x7FFFFFFF) % this.valueTable.length;
108
		Object currentKey;
109
		while ((currentKey = this.keyTable[index]) != null) {
110
			if (currentKey.equals(key)) {
111
				int[] value = this.valueTable[index];
112
				elementSize--;
113
				this.keyTable[index] = null;
114
				rehash();
115
				return value;
116
			}
117
			index = (index + 1) % this.keyTable.length;
118
		}
119
		return null;
120
	}
121
122
	private void rehash() {
123
124
		HashtableOfObjectToIntArray newHashtable = new HashtableOfObjectToIntArray(elementSize * 2);		// double the number of expected elements
125
		Object currentKey;
126
		for (int i = this.keyTable.length; --i >= 0;)
127
			if ((currentKey = this.keyTable[i]) != null)
128
				newHashtable.put(currentKey, this.valueTable[i]);
129
130
		this.keyTable = newHashtable.keyTable;
131
		this.valueTable = newHashtable.valueTable;
132
		this.threshold = newHashtable.threshold;
133
	}
134
135
	public int size() {
136
		return elementSize;
137
	}
138
	
139
	public String toString() {
140
		String s = ""; //$NON-NLS-1$
141
		Object key;
142
		for (int i = 0, length = this.keyTable.length; i < length; i++)
143
			if ((key = this.keyTable[i]) != null)
144
				s += key + " -> " + this.valueTable[i] + "\n"; 	//$NON-NLS-2$ //$NON-NLS-1$
145
		return s;
146
	}
147
}
(-)src/org/eclipse/jdt/core/tests/dom/ASTConverterRecoveryTest.java (+368 lines)
Lines 21-28 Link Here
21
import org.eclipse.jdt.core.dom.ArrayInitializer;
21
import org.eclipse.jdt.core.dom.ArrayInitializer;
22
import org.eclipse.jdt.core.dom.Block;
22
import org.eclipse.jdt.core.dom.Block;
23
import org.eclipse.jdt.core.dom.CompilationUnit;
23
import org.eclipse.jdt.core.dom.CompilationUnit;
24
import org.eclipse.jdt.core.dom.EmptyStatement;
24
import org.eclipse.jdt.core.dom.Expression;
25
import org.eclipse.jdt.core.dom.Expression;
25
import org.eclipse.jdt.core.dom.ExpressionStatement;
26
import org.eclipse.jdt.core.dom.ExpressionStatement;
27
import org.eclipse.jdt.core.dom.ForStatement;
26
import org.eclipse.jdt.core.dom.ITypeBinding;
28
import org.eclipse.jdt.core.dom.ITypeBinding;
27
import org.eclipse.jdt.core.dom.MethodDeclaration;
29
import org.eclipse.jdt.core.dom.MethodDeclaration;
28
import org.eclipse.jdt.core.dom.MethodInvocation;
30
import org.eclipse.jdt.core.dom.MethodInvocation;
Lines 32-37 Link Here
32
import org.eclipse.jdt.core.dom.StringLiteral;
34
import org.eclipse.jdt.core.dom.StringLiteral;
33
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
35
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
34
import org.eclipse.jdt.core.dom.VariableDeclarationStatement;
36
import org.eclipse.jdt.core.dom.VariableDeclarationStatement;
37
import org.eclipse.jdt.core.dom.VariableDeclarationExpression;
35
38
36
public class ASTConverterRecoveryTest extends ConverterTestSetup {
39
public class ASTConverterRecoveryTest extends ConverterTestSetup {
37
	public ASTConverterRecoveryTest(String name) {
40
	public ASTConverterRecoveryTest(String name) {
Lines 352-355 Link Here
352
		checkSourceRange(simpleName, ",", source); //$NON-NLS-1$
355
		checkSourceRange(simpleName, ",", source); //$NON-NLS-1$
353
		
356
		
354
	}
357
	}
358
		
359
	// check RECOVERED flag (insert tokens)
360
	public void test0006() throws JavaModelException {
361
		this.workingCopies = new ICompilationUnit[1];
362
		this.workingCopies[0] = getWorkingCopy(
363
			"/Converter/src/test/X.java",
364
			"package test;\n"+
365
			"\n"+
366
			"public class X {\n"+
367
			"	void foo() {\n"+
368
			"	    bar()\n"+
369
			"	}\n"+
370
			"}\n");
371
		
372
		char[] source = this.workingCopies[0].getSource().toCharArray();
373
		ASTNode result = runConversion(AST.JLS3, this.workingCopies[0], true, true);
374
		
375
		assertASTNodeEquals(
376
			"package test;\n" + 
377
			"public class X {\n" + 
378
			"  void foo(){\n" + 
379
			"    bar();\n" + 
380
			"  }\n" + 
381
			"}\n",
382
			result);
383
		
384
		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
385
		assertNotNull(node);
386
		assertTrue("Not a method declaration", node.getNodeType() == ASTNode.METHOD_DECLARATION); //$NON-NLS-1$
387
		MethodDeclaration methodDeclaration = (MethodDeclaration) node;
388
		assertTrue("Flag as RECOVERED", (methodDeclaration.getFlags() & ASTNode.RECOVERED) == 0);
389
		Block block = methodDeclaration.getBody();
390
		assertTrue("Flag as RECOVERED", (block.getFlags() & ASTNode.RECOVERED) == 0);
391
		List statements = block.statements();
392
		assertEquals("wrong size", 1, statements.size()); //$NON-NLS-1$
393
		Statement statement = (Statement) statements.get(0);
394
		assertTrue("Not an expression statement", statement.getNodeType() == ASTNode.EXPRESSION_STATEMENT); //$NON-NLS-1$
395
		ExpressionStatement expressionStatement = (ExpressionStatement) statement;
396
		checkSourceRange(expressionStatement, "bar()", source); //$NON-NLS-1$
397
		assertTrue("Not flag as RECOVERED", (expressionStatement.getFlags() & ASTNode.RECOVERED) != 0);
398
		Expression expression = expressionStatement.getExpression();
399
		assertTrue("Not a method invocation", expression.getNodeType() == ASTNode.METHOD_INVOCATION); //$NON-NLS-1$
400
		MethodInvocation methodInvocation = (MethodInvocation)expression;
401
		checkSourceRange(methodInvocation, "bar()", source); //$NON-NLS-1$
402
		assertTrue("Flag as RECOVERED", (methodInvocation.getFlags() & ASTNode.RECOVERED) == 0);
403
	}
404
	
405
	// check RECOVERED flag (insert tokens)
406
	public void test0007() throws JavaModelException {
407
		this.workingCopies = new ICompilationUnit[1];
408
		this.workingCopies[0] = getWorkingCopy(
409
			"/Converter/src/test/X.java",
410
			"package test;\n"+
411
			"\n"+
412
			"public class X {\n"+
413
			"	void foo() {\n"+
414
			"	    bar(baz()\n"+
415
			"	}\n"+
416
			"}\n");
417
		
418
		char[] source = this.workingCopies[0].getSource().toCharArray();
419
		ASTNode result = runConversion(AST.JLS3, this.workingCopies[0], true, true);
420
		
421
		assertASTNodeEquals(
422
			"package test;\n" + 
423
			"public class X {\n" + 
424
			"  void foo(){\n" + 
425
			"    bar(baz());\n" + 
426
			"  }\n" + 
427
			"}\n",
428
			result);
429
		
430
		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
431
		assertNotNull(node);
432
		assertTrue("Not a method declaration", node.getNodeType() == ASTNode.METHOD_DECLARATION); //$NON-NLS-1$
433
		MethodDeclaration methodDeclaration = (MethodDeclaration) node;
434
		assertTrue("Flag as RECOVERED", (methodDeclaration.getFlags() & ASTNode.RECOVERED) == 0);
435
		Block block = methodDeclaration.getBody();
436
		assertTrue("Flag as RECOVERED", (block.getFlags() & ASTNode.RECOVERED) == 0);
437
		List statements = block.statements();
438
		assertEquals("wrong size", 1, statements.size()); //$NON-NLS-1$
439
		Statement statement = (Statement) statements.get(0);
440
		assertTrue("Not an expression statement", statement.getNodeType() == ASTNode.EXPRESSION_STATEMENT); //$NON-NLS-1$
441
		ExpressionStatement expressionStatement = (ExpressionStatement) statement;
442
		checkSourceRange(expressionStatement, "bar(baz()", source); //$NON-NLS-1$
443
		assertTrue("Not flag as RECOVERED", (expressionStatement.getFlags() & ASTNode.RECOVERED) != 0);
444
		Expression expression = expressionStatement.getExpression();
445
		assertTrue("Not a method invocation", expression.getNodeType() == ASTNode.METHOD_INVOCATION); //$NON-NLS-1$
446
		MethodInvocation methodInvocation = (MethodInvocation)expression;
447
		checkSourceRange(methodInvocation, "bar(baz()", source); //$NON-NLS-1$
448
		assertTrue("Not flag as RECOVERED", (methodInvocation.getFlags() & ASTNode.RECOVERED) != 0);
449
		List arguments = methodInvocation.arguments();
450
		assertEquals("wrong size", 1, arguments.size()); //$NON-NLS-1$
451
		Expression argument = (Expression) arguments.get(0);
452
		assertTrue("Not a method invocation", argument.getNodeType() == ASTNode.METHOD_INVOCATION); //$NON-NLS-1$
453
		MethodInvocation methodInvocation2 = (MethodInvocation) argument;
454
		checkSourceRange(methodInvocation2, "baz()", source); //$NON-NLS-1$
455
		assertTrue("Flag as RECOVERED", (methodInvocation2.getFlags() & ASTNode.RECOVERED) == 0);
456
	}
457
	
458
	// check RECOVERED flag (insert tokens)
459
	public void test0008() throws JavaModelException {
460
		this.workingCopies = new ICompilationUnit[1];
461
		this.workingCopies[0] = getWorkingCopy(
462
			"/Converter/src/test/X.java",
463
			"package test;\n"+
464
			"\n"+
465
			"public class X {\n"+
466
			"	void foo() {\n"+
467
			"	    for(int i\n"+
468
			"	}\n"+
469
			"}\n");
470
		
471
		char[] source = this.workingCopies[0].getSource().toCharArray();
472
		ASTNode result = runConversion(AST.JLS3, this.workingCopies[0], true, true);
473
		
474
		assertASTNodeEquals(
475
			"package test;\n" + 
476
			"public class X {\n" + 
477
			"  void foo(){\n" + 
478
			"    for (int i; ; )     ;\n" + 
479
			"  }\n" + 
480
			"}\n",
481
			result);
482
		
483
		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
484
		assertNotNull(node);
485
		assertTrue("Not a method declaration", node.getNodeType() == ASTNode.METHOD_DECLARATION); //$NON-NLS-1$
486
		MethodDeclaration methodDeclaration = (MethodDeclaration) node;
487
		assertTrue("Flag as RECOVERED", (methodDeclaration.getFlags() & ASTNode.RECOVERED) == 0);
488
		Block block = methodDeclaration.getBody();
489
		assertTrue("Not flag as RECOVERED", (block.getFlags() & ASTNode.RECOVERED) != 0);
490
		List statements = block.statements();
491
		assertEquals("wrong size", 1, statements.size()); //$NON-NLS-1$
492
		Statement statement = (Statement) statements.get(0);
493
		assertTrue("Not a for statement", statement.getNodeType() == ASTNode.FOR_STATEMENT); //$NON-NLS-1$
494
		ForStatement forStatement = (ForStatement) statement;
495
		checkSourceRange(forStatement, "for(int i", source); //$NON-NLS-1$
496
		assertTrue("Not flag as RECOVERED", (forStatement.getFlags() & ASTNode.RECOVERED) != 0);
497
		List initializers = forStatement.initializers();
498
		assertEquals("wrong size", 1, statements.size()); //$NON-NLS-1$
499
		Expression expression = (Expression)initializers.get(0);
500
		assertTrue("Not a method invocation", expression.getNodeType() == ASTNode.VARIABLE_DECLARATION_EXPRESSION); //$NON-NLS-1$
501
		VariableDeclarationExpression variableDeclarationExpression = (VariableDeclarationExpression)expression;
502
		checkSourceRange(variableDeclarationExpression, "int i", source); //$NON-NLS-1$
503
		assertTrue("Not flag as RECOVERED", (variableDeclarationExpression.getFlags() & ASTNode.RECOVERED) != 0);
504
		List fragments = variableDeclarationExpression.fragments();
505
		assertEquals("wrong size", 1, fragments.size()); //$NON-NLS-1$
506
		VariableDeclarationFragment fragment = (VariableDeclarationFragment)fragments.get(0);
507
		checkSourceRange(fragment, "i", source); //$NON-NLS-1$
508
		assertTrue("Not flag as RECOVERED", (fragment.getFlags() & ASTNode.RECOVERED) != 0);
509
		SimpleName name = fragment.getName();
510
		checkSourceRange(name, "i", source); //$NON-NLS-1$
511
		assertTrue("Flag as RECOVERED", (name.getFlags() & ASTNode.RECOVERED) == 0);
512
		Statement statement2 = forStatement.getBody();
513
		assertTrue("Not an empty statement", statement2.getNodeType() == ASTNode.EMPTY_STATEMENT); //$NON-NLS-1$
514
		EmptyStatement emptyStatement = (EmptyStatement)statement2;
515
		checkSourceRange(emptyStatement, "i", source); //$NON-NLS-1$
516
		assertTrue("Not flag as RECOVERED", (emptyStatement.getFlags() & ASTNode.RECOVERED) != 0);
517
	}
518
	
519
	// check RECOVERED flag (remove tokens)
520
	public void test0009() throws JavaModelException {
521
		this.workingCopies = new ICompilationUnit[1];
522
		this.workingCopies[0] = getWorkingCopy(
523
			"/Converter/src/test/X.java",
524
			"package test;\n"+
525
			"\n"+
526
			"public class X {\n"+
527
			"	void foo() {\n"+
528
			"	    bar(baz());#\n"+
529
			"	}\n"+
530
			"}\n");
531
		
532
		char[] source = this.workingCopies[0].getSource().toCharArray();
533
		ASTNode result = runConversion(AST.JLS3, this.workingCopies[0], true, true);
534
		
535
		assertASTNodeEquals(
536
			"package test;\n" + 
537
			"public class X {\n" + 
538
			"  void foo(){\n" + 
539
			"    bar(baz());\n" + 
540
			"  }\n" + 
541
			"}\n",
542
			result);
543
		
544
		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
545
		assertNotNull(node);
546
		assertTrue("Not a method declaration", node.getNodeType() == ASTNode.METHOD_DECLARATION); //$NON-NLS-1$
547
		MethodDeclaration methodDeclaration = (MethodDeclaration) node;
548
		assertTrue("Flag as RECOVERED", (methodDeclaration.getFlags() & ASTNode.RECOVERED) == 0);
549
		Block block = methodDeclaration.getBody();
550
		assertTrue("Not flag as RECOVERED", (block.getFlags() & ASTNode.RECOVERED) != 0);
551
		List statements = block.statements();
552
		assertEquals("wrong size", 1, statements.size()); //$NON-NLS-1$
553
		Statement statement = (Statement) statements.get(0);
554
		assertTrue("Not an expression statement", statement.getNodeType() == ASTNode.EXPRESSION_STATEMENT); //$NON-NLS-1$
555
		ExpressionStatement expressionStatement = (ExpressionStatement) statement;
556
		checkSourceRange(expressionStatement, "bar(baz());", source); //$NON-NLS-1$
557
		assertTrue("Flag as RECOVERED", (expressionStatement.getFlags() & ASTNode.RECOVERED) == 0);
558
		Expression expression = expressionStatement.getExpression();
559
		assertTrue("Not a method invocation", expression.getNodeType() == ASTNode.METHOD_INVOCATION); //$NON-NLS-1$
560
		MethodInvocation methodInvocation = (MethodInvocation)expression;
561
		checkSourceRange(methodInvocation, "bar(baz())", source); //$NON-NLS-1$
562
		assertTrue("Flag as RECOVERED", (methodInvocation.getFlags() & ASTNode.RECOVERED) == 0);
563
		List arguments = methodInvocation.arguments();
564
		assertEquals("wrong size", 1, arguments.size()); //$NON-NLS-1$
565
		Expression argument = (Expression) arguments.get(0);
566
		assertTrue("Not a method invocation", argument.getNodeType() == ASTNode.METHOD_INVOCATION); //$NON-NLS-1$
567
		MethodInvocation methodInvocation2 = (MethodInvocation) argument;
568
		checkSourceRange(methodInvocation2, "baz()", source); //$NON-NLS-1$
569
		assertTrue("Flag as RECOVERED", (methodInvocation2.getFlags() & ASTNode.RECOVERED) == 0);
570
	}
571
	
572
	// check RECOVERED flag (remove tokens)
573
	public void test0010() throws JavaModelException {
574
		this.workingCopies = new ICompilationUnit[1];
575
		this.workingCopies[0] = getWorkingCopy(
576
			"/Converter/src/test/X.java",
577
			"package test;\n"+
578
			"\n"+
579
			"public class X {\n"+
580
			"	void foo() {\n"+
581
			"	    bar(baz())#;\n"+
582
			"	}\n"+
583
			"}\n");
584
		
585
		char[] source = this.workingCopies[0].getSource().toCharArray();
586
		ASTNode result = runConversion(AST.JLS3, this.workingCopies[0], true, true);
587
		
588
		assertASTNodeEquals(
589
			"package test;\n" + 
590
			"public class X {\n" + 
591
			"  void foo(){\n" + 
592
			"    bar(baz());\n" + 
593
			"  }\n" + 
594
			"}\n",
595
			result);
596
		
597
		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
598
		assertNotNull(node);
599
		assertTrue("Not a method declaration", node.getNodeType() == ASTNode.METHOD_DECLARATION); //$NON-NLS-1$
600
		MethodDeclaration methodDeclaration = (MethodDeclaration) node;
601
		assertTrue("Flag as RECOVERED", (methodDeclaration.getFlags() & ASTNode.RECOVERED) == 0);
602
		Block block = methodDeclaration.getBody();
603
		assertTrue("Flag as RECOVERED", (block.getFlags() & ASTNode.RECOVERED) == 0);
604
		List statements = block.statements();
605
		assertEquals("wrong size", 1, statements.size()); //$NON-NLS-1$
606
		Statement statement = (Statement) statements.get(0);
607
		assertTrue("Not an expression statement", statement.getNodeType() == ASTNode.EXPRESSION_STATEMENT); //$NON-NLS-1$
608
		ExpressionStatement expressionStatement = (ExpressionStatement) statement;
609
		checkSourceRange(expressionStatement, "bar(baz())#;", source); //$NON-NLS-1$
610
		assertTrue("Not flag as RECOVERED", (expressionStatement.getFlags() & ASTNode.RECOVERED) != 0);
611
		Expression expression = expressionStatement.getExpression();
612
		assertTrue("Not a method invocation", expression.getNodeType() == ASTNode.METHOD_INVOCATION); //$NON-NLS-1$
613
		MethodInvocation methodInvocation = (MethodInvocation)expression;
614
		checkSourceRange(methodInvocation, "bar(baz())", source); //$NON-NLS-1$
615
		assertTrue("Flag as RECOVERED", (methodInvocation.getFlags() & ASTNode.RECOVERED) == 0);
616
		List arguments = methodInvocation.arguments();
617
		assertEquals("wrong size", 1, arguments.size()); //$NON-NLS-1$
618
		Expression argument = (Expression) arguments.get(0);
619
		assertTrue("Not a method invocation", argument.getNodeType() == ASTNode.METHOD_INVOCATION); //$NON-NLS-1$
620
		MethodInvocation methodInvocation2 = (MethodInvocation) argument;
621
		checkSourceRange(methodInvocation2, "baz()", source); //$NON-NLS-1$
622
		assertTrue("Flag as RECOVERED", (methodInvocation2.getFlags() & ASTNode.RECOVERED) == 0);
623
	}
624
	
625
	// check RECOVERED flag (remove tokens)
626
	public void test0011() throws JavaModelException {
627
		this.workingCopies = new ICompilationUnit[1];
628
		this.workingCopies[0] = getWorkingCopy(
629
			"/Converter/src/test/X.java",
630
			"package test;\n"+
631
			"\n"+
632
			"public class X {\n"+
633
			"	void foo() {\n"+
634
			"	    bar(baz()#);\n"+
635
			"	}\n"+
636
			"}\n");
637
		
638
		char[] source = this.workingCopies[0].getSource().toCharArray();
639
		ASTNode result = runConversion(AST.JLS3, this.workingCopies[0], true, true);
640
		
641
		assertASTNodeEquals(
642
			"package test;\n" + 
643
			"public class X {\n" + 
644
			"  void foo(){\n" + 
645
			"    bar(baz());\n" + 
646
			"  }\n" + 
647
			"}\n",
648
			result);
649
		
650
		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
651
		assertNotNull(node);
652
		assertTrue("Not a method declaration", node.getNodeType() == ASTNode.METHOD_DECLARATION); //$NON-NLS-1$
653
		MethodDeclaration methodDeclaration = (MethodDeclaration) node;
654
		assertTrue("Flag as RECOVERED", (methodDeclaration.getFlags() & ASTNode.RECOVERED) == 0);
655
		Block block = methodDeclaration.getBody();
656
		assertTrue("Flag as RECOVERED", (block.getFlags() & ASTNode.RECOVERED) == 0);
657
		List statements = block.statements();
658
		assertEquals("wrong size", 1, statements.size()); //$NON-NLS-1$
659
		Statement statement = (Statement) statements.get(0);
660
		assertTrue("Not an expression statement", statement.getNodeType() == ASTNode.EXPRESSION_STATEMENT); //$NON-NLS-1$
661
		ExpressionStatement expressionStatement = (ExpressionStatement) statement;
662
		checkSourceRange(expressionStatement, "bar(baz()#);", source); //$NON-NLS-1$
663
		assertTrue("Flag as RECOVERED", (expressionStatement.getFlags() & ASTNode.RECOVERED) == 0);
664
		Expression expression = expressionStatement.getExpression();
665
		assertTrue("Not a method invocation", expression.getNodeType() == ASTNode.METHOD_INVOCATION); //$NON-NLS-1$
666
		MethodInvocation methodInvocation = (MethodInvocation)expression;
667
		checkSourceRange(methodInvocation, "bar(baz()#)", source); //$NON-NLS-1$
668
		assertTrue("Not flag as RECOVERED", (methodInvocation.getFlags() & ASTNode.RECOVERED) != 0);
669
		List arguments = methodInvocation.arguments();
670
		assertEquals("wrong size", 1, arguments.size()); //$NON-NLS-1$
671
		Expression argument = (Expression) arguments.get(0);
672
		assertTrue("Not a method invocation", argument.getNodeType() == ASTNode.METHOD_INVOCATION); //$NON-NLS-1$
673
		MethodInvocation methodInvocation2 = (MethodInvocation) argument;
674
		checkSourceRange(methodInvocation2, "baz()", source); //$NON-NLS-1$
675
		assertTrue("Flag as RECOVERED", (methodInvocation2.getFlags() & ASTNode.RECOVERED) == 0);
676
	}
677
	
678
	// check RECOVERED flag (insert tokens)
679
	public void test0012() throws JavaModelException {
680
		this.workingCopies = new ICompilationUnit[1];
681
		this.workingCopies[0] = getWorkingCopy(
682
			"/Converter/src/test/X.java",
683
			"package test;\n"+
684
			"\n"+
685
			"public class X {\n"+
686
			"	void foo() {\n"+
687
			"	    bar()#\n"+
688
			"	}\n"+
689
			"}\n");
690
		
691
		char[] source = this.workingCopies[0].getSource().toCharArray();
692
		ASTNode result = runConversion(AST.JLS3, this.workingCopies[0], true, true);
693
		
694
		assertASTNodeEquals(
695
			"package test;\n" + 
696
			"public class X {\n" + 
697
			"  void foo(){\n" + 
698
			"    bar();\n" + 
699
			"  }\n" + 
700
			"}\n",
701
			result);
702
		
703
		ASTNode node = getASTNode((CompilationUnit) result, 0, 0);
704
		assertNotNull(node);
705
		assertTrue("Not a method declaration", node.getNodeType() == ASTNode.METHOD_DECLARATION); //$NON-NLS-1$
706
		MethodDeclaration methodDeclaration = (MethodDeclaration) node;
707
		assertTrue("Flag as RECOVERED", (methodDeclaration.getFlags() & ASTNode.RECOVERED) == 0);
708
		Block block = methodDeclaration.getBody();
709
		assertTrue("Flag as RECOVERED", (block.getFlags() & ASTNode.RECOVERED) == 0);
710
		List statements = block.statements();
711
		assertEquals("wrong size", 1, statements.size()); //$NON-NLS-1$
712
		Statement statement = (Statement) statements.get(0);
713
		assertTrue("Not an expression statement", statement.getNodeType() == ASTNode.EXPRESSION_STATEMENT); //$NON-NLS-1$
714
		ExpressionStatement expressionStatement = (ExpressionStatement) statement;
715
		checkSourceRange(expressionStatement, "bar()#", source); //$NON-NLS-1$
716
		assertTrue("Not flag as RECOVERED", (expressionStatement.getFlags() & ASTNode.RECOVERED) != 0);
717
		Expression expression = expressionStatement.getExpression();
718
		assertTrue("Not a method invocation", expression.getNodeType() == ASTNode.METHOD_INVOCATION); //$NON-NLS-1$
719
		MethodInvocation methodInvocation = (MethodInvocation)expression;
720
		checkSourceRange(methodInvocation, "bar()", source); //$NON-NLS-1$
721
		assertTrue("Flag as RECOVERED", (methodInvocation.getFlags() & ASTNode.RECOVERED) == 0);
722
	}
355
}
723
}

Return to bug 42253