KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > eval > CodeSnippetParser


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 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.eval;
12
13 import org.eclipse.jdt.core.compiler.CharOperation;
14 import org.eclipse.jdt.core.compiler.IProblem;
15 import org.eclipse.jdt.internal.compiler.CompilationResult;
16 import org.eclipse.jdt.internal.compiler.ast.*;
17 import org.eclipse.jdt.internal.compiler.lookup.Binding;
18 import org.eclipse.jdt.internal.compiler.parser.Parser;
19 import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
20
21 /**
22  * A parser for code snippets.
23  */

24 public class CodeSnippetParser extends Parser implements EvaluationConstants {
25     int codeSnippetStart, codeSnippetEnd;
26     EvaluationContext evaluationContext;
27     boolean hasRecoveredOnExpression;
28     int lastStatement = -1; // end of last top level statement
29
int lineSeparatorLength;
30
31     int problemCountBeforeRecovery = 0;
32 /**
33  * Creates a new code snippet parser.
34  */

35 public CodeSnippetParser(ProblemReporter problemReporter, EvaluationContext evaluationContext, boolean optimizeStringLiterals, int codeSnippetStart, int codeSnippetEnd) {
36     super(problemReporter, optimizeStringLiterals);
37     this.codeSnippetStart = codeSnippetStart;
38     this.codeSnippetEnd = codeSnippetEnd;
39     this.evaluationContext = evaluationContext;
40     this.reportOnlyOneSyntaxError = true;
41     this.javadocParser.checkDocComment = false;
42 }
43 protected void classInstanceCreation(boolean alwaysQualified) {
44     // ClassInstanceCreationExpression ::= 'new' ClassType '(' ArgumentListopt ')' ClassBodyopt
45

46     // ClassBodyopt produces a null item on the astStak if it produces NO class body
47
// An empty class body produces a 0 on the length stack.....
48

49     AllocationExpression alloc;
50     int length;
51     if (((length = this.astLengthStack[this.astLengthPtr--]) == 1)
52         && (this.astStack[this.astPtr] == null)) {
53         //NO ClassBody
54
this.astPtr--;
55         if (alwaysQualified) {
56             alloc = new QualifiedAllocationExpression();
57         } else {
58             alloc = new CodeSnippetAllocationExpression(this.evaluationContext);
59         }
60         alloc.sourceEnd = this.endPosition; //the position has been stored explicitly
61

62         if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
63             this.expressionPtr -= length;
64             System.arraycopy(
65                 this.expressionStack,
66                 this.expressionPtr + 1,
67                 alloc.arguments = new Expression[length],
68                 0,
69                 length);
70         }
71         alloc.type = getTypeReference(0);
72         //the default constructor with the correct number of argument
73
//will be created and added by the TC (see createsInternalConstructorWithBinding)
74
alloc.sourceStart = this.intStack[this.intPtr--];
75         pushOnExpressionStack(alloc);
76     } else {
77         dispatchDeclarationInto(length);
78         TypeDeclaration anonymousTypeDeclaration = (TypeDeclaration) this.astStack[this.astPtr];
79         anonymousTypeDeclaration.declarationSourceEnd = this.endStatementPosition;
80         if (anonymousTypeDeclaration.allocation != null) {
81             anonymousTypeDeclaration.allocation.sourceEnd = this.endStatementPosition;
82         }
83         this.astPtr--;
84         this.astLengthPtr--;
85
86         // mark initializers with local type mark if needed
87
markInitializersWithLocalType(anonymousTypeDeclaration);
88     }
89 }
90 protected void consumeClassDeclaration() {
91     super.consumeClassDeclaration();
92     /* recovery */
93     recordLastStatementIfNeeded();
94 }
95 protected void consumeClassHeaderName1() {
96     // ClassHeaderName ::= Modifiersopt 'class' 'Identifier'
97
TypeDeclaration typeDecl;
98     if (this.nestedMethod[this.nestedType] == 0) {
99         if (this.nestedType != 0) {
100             typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult);
101             typeDecl.bits |= ASTNode.IsMemberType;
102         } else {
103             typeDecl = new CodeSnippetTypeDeclaration(this.compilationUnit.compilationResult);
104         }
105     } else {
106         // Record that the block has a declaration for local types
107
typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult);
108         typeDecl.bits |= ASTNode.IsLocalType;
109         markEnclosingMemberWithLocalType();
110         blockReal();
111     }
112
113     //highlight the name of the type
114
long pos = this.identifierPositionStack[this.identifierPtr];
115     typeDecl.sourceEnd = (int) pos;
116     typeDecl.sourceStart = (int) (pos >>> 32);
117     typeDecl.name = this.identifierStack[this.identifierPtr--];
118     this.identifierLengthPtr--;
119
120     //compute the declaration source too
121
typeDecl.declarationSourceStart = this.intStack[this.intPtr--];
122     this.intPtr--;
123     // 'class' and 'interface' push an int position
124
typeDecl.modifiersSourceStart = this.intStack[this.intPtr--];
125     typeDecl.modifiers = this.intStack[this.intPtr--];
126     if (typeDecl.modifiersSourceStart >= 0) {
127         typeDecl.declarationSourceStart = typeDecl.modifiersSourceStart;
128     }
129     typeDecl.bodyStart = typeDecl.sourceEnd + 1;
130     pushOnAstStack(typeDecl);
131
132     this.listLength = 0; // will be updated when reading super-interfaces
133
// recovery
134
if (this.currentElement != null){
135         this.lastCheckPoint = typeDecl.bodyStart;
136         this.currentElement = this.currentElement.add(typeDecl, 0);
137         this.lastIgnoredToken = -1;
138     }
139     // javadoc
140
typeDecl.javadoc = this.javadoc;
141     this.javadoc = null;
142 }
143 protected void consumeEmptyStatement() {
144     super.consumeEmptyStatement();
145     /* recovery */
146     recordLastStatementIfNeeded();
147 }
148 protected void consumeEnhancedForStatement() {
149     super.consumeEnhancedForStatement();
150     /* recovery */
151     recordLastStatementIfNeeded();
152 }
153 protected void consumeExpressionStatement() {
154     super.consumeExpressionStatement();
155     /* recovery */
156     recordLastStatementIfNeeded();
157 }
158 protected void consumeFieldAccess(boolean isSuperAccess) {
159     // FieldAccess ::= Primary '.' 'Identifier'
160
// FieldAccess ::= 'super' '.' 'Identifier'
161

162     FieldReference fr =
163         new CodeSnippetFieldReference(
164             this.identifierStack[this.identifierPtr],
165             this.identifierPositionStack[this.identifierPtr--],
166             this.evaluationContext);
167     this.identifierLengthPtr--;
168     if (isSuperAccess) {
169         //considerates the fieldReference beginning at the 'super' ....
170
fr.sourceStart = this.intStack[this.intPtr--];
171         problemReporter().codeSnippetMissingClass(null,0, 0);
172         fr.receiver = new CodeSnippetSuperReference(fr.sourceStart, this.endPosition);
173         pushOnExpressionStack(fr);
174     } else {
175         //optimize push/pop
176
if ((fr.receiver = this.expressionStack[this.expressionPtr]).isThis()) {
177             //fieldreference begins at the this
178
fr.sourceStart = fr.receiver.sourceStart;
179         }
180         this.expressionStack[this.expressionPtr] = fr;
181     }
182 }
183 protected void consumeInterfaceHeaderName1() {
184     // InterfaceHeaderName ::= Modifiersopt 'interface' 'Identifier'
185
TypeDeclaration typeDecl;
186     if (this.nestedMethod[this.nestedType] == 0) {
187         if (this.nestedType != 0) {
188             typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult);
189             typeDecl.bits |= ASTNode.IsMemberType;
190         } else {
191             typeDecl = new CodeSnippetTypeDeclaration(this.compilationUnit.compilationResult);
192         }
193     } else {
194         // Record that the block has a declaration for local types
195
typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult);
196         typeDecl.bits |= ASTNode.IsLocalType;
197         markEnclosingMemberWithLocalType();
198         blockReal();
199     }
200
201     //highlight the name of the type
202
long pos = this.identifierPositionStack[this.identifierPtr];
203     typeDecl.sourceEnd = (int) pos;
204     typeDecl.sourceStart = (int) (pos >>> 32);
205     typeDecl.name = this.identifierStack[this.identifierPtr--];
206     this.identifierLengthPtr--;
207
208     //compute the declaration source too
209
typeDecl.declarationSourceStart = this.intStack[this.intPtr--];
210     this.intPtr--;
211     // 'class' and 'interface' push an int position
212
typeDecl.modifiersSourceStart = this.intStack[this.intPtr--];
213     typeDecl.modifiers = this.intStack[this.intPtr--];
214     if (typeDecl.modifiersSourceStart >= 0) {
215         typeDecl.declarationSourceStart = typeDecl.modifiersSourceStart;
216     }
217     typeDecl.bodyStart = typeDecl.sourceEnd + 1;
218     pushOnAstStack(typeDecl);
219     this.listLength = 0; // will be updated when reading super-interfaces
220
// recovery
221
if (this.currentElement != null){ // is recovering
222
this.lastCheckPoint = typeDecl.bodyStart;
223         this.currentElement = this.currentElement.add(typeDecl, 0);
224         this.lastIgnoredToken = -1;
225     }
226     // javadoc
227
typeDecl.javadoc = this.javadoc;
228     this.javadoc = null;
229 }
230 protected void consumeInternalCompilationUnit() {
231     // InternalCompilationUnit ::= PackageDeclaration
232
// InternalCompilationUnit ::= PackageDeclaration ImportDeclarations ReduceImports
233
// InternalCompilationUnit ::= ImportDeclarations ReduceImports
234
}
235 protected void consumeInternalCompilationUnitWithTypes() {
236     // InternalCompilationUnit ::= PackageDeclaration ImportDeclarations ReduceImports TypeDeclarations
237
// InternalCompilationUnit ::= PackageDeclaration TypeDeclarations
238
// InternalCompilationUnit ::= TypeDeclarations
239
// InternalCompilationUnit ::= ImportDeclarations ReduceImports TypeDeclarations
240
// consume type declarations
241
int length;
242     if ((length = this.astLengthStack[this.astLengthPtr--]) != 0) {
243         this.compilationUnit.types = new TypeDeclaration[length];
244         this.astPtr -= length;
245         System.arraycopy(this.astStack, this.astPtr + 1, this.compilationUnit.types, 0, length);
246     }
247 }
248 protected void consumeLocalVariableDeclarationStatement() {
249     super.consumeLocalVariableDeclarationStatement();
250     /* recovery */
251     recordLastStatementIfNeeded();
252 }
253
254 /**
255  * In case emulating local variables, wrap the (recovered) statements inside a
256  * try statement so as to achieve local state commiting (copy local vars back to fields).
257  * The CSToCuMapper could not be used, since it could have interfered with
258  * the syntax recovery specific to code snippets.
259  */

260 protected void consumeMethodDeclaration(boolean isNotAbstract) {
261     // MethodDeclaration ::= MethodHeader MethodBody
262
// AbstractMethodDeclaration ::= MethodHeader ';'
263

264     super.consumeMethodDeclaration(isNotAbstract);
265     
266     // now we know that we have a method declaration at the top of the ast stack
267
MethodDeclaration methodDecl = (MethodDeclaration) this.astStack[this.astPtr];
268
269     // automatically wrap the last statement inside a return statement, if it is an expression
270
// support have to be defined at toplevel only
271
if (this.isTopLevelType()) {
272         int last = methodDecl.statements == null ? -1 : methodDecl.statements.length - 1;
273         if (last >= 0 && methodDecl.statements[last] instanceof Expression){
274             Expression lastExpression = (Expression) methodDecl.statements[last];
275             methodDecl.statements[last] = new CodeSnippetReturnStatement(
276                                             lastExpression,
277                                             lastExpression.sourceStart,
278                                             lastExpression.sourceEnd);
279         }
280     }
281     
282     int start = methodDecl.bodyStart-1, end = start;
283     long position = ((long)start << 32) + end;
284     long[] positions = new long[]{position};
285     if (this.evaluationContext.localVariableNames != null) {
286
287         int varCount = this.evaluationContext.localVariableNames.length; // n local decls+ try statement
288

289         // generate n local variable declarations: [type] [name] = val$[name];
290
Statement[] newStatements = new Statement[varCount+1];
291         for (int i = 0; i < varCount; i++){
292             char[] trimmedTypeName = this.evaluationContext.localVariableTypeNames[i];
293             int nameEnd = CharOperation.indexOf('[', trimmedTypeName);
294             if (nameEnd >= 0) {
295                 trimmedTypeName = CharOperation.subarray(trimmedTypeName, 0, nameEnd);
296             }
297             nameEnd = CharOperation.indexOf(' ', trimmedTypeName);
298             if (nameEnd >= 0) {
299                 trimmedTypeName = CharOperation.subarray(trimmedTypeName, 0, nameEnd);
300             }
301             TypeReference typeReference = new QualifiedTypeReference(
302                 CharOperation.splitOn('.', trimmedTypeName),
303                 positions);
304             int dimCount = CharOperation.occurencesOf('[', this.evaluationContext.localVariableTypeNames[i]);
305             if (dimCount > 0) {
306                 typeReference = this.copyDims(typeReference, dimCount);
307             }
308             NameReference init = new SingleNameReference(
309                                     CharOperation.concat(LOCAL_VAR_PREFIX, this.evaluationContext.localVariableNames[i]), position);
310             LocalDeclaration declaration = new LocalDeclaration(this.evaluationContext.localVariableNames[i], start, end);
311             declaration.initialization = init;
312             declaration.type = typeReference;
313             declaration.modifiers = this.evaluationContext.localVariableModifiers[i];
314             newStatements[i] = declaration;
315         }
316
317         // generate try { [snippet] } finally { [save locals to fields] }
318
// try block
319
TryStatement tryStatement = new TryStatement();
320         Block tryBlock = new Block(methodDecl.explicitDeclarations);
321         tryBlock.sourceStart = start;
322         tryBlock.sourceEnd = end;
323         tryBlock.statements = methodDecl.statements; // snippet statements
324
tryStatement.tryBlock = tryBlock;
325         // finally block
326
Block finallyBlock = new Block(0);
327         finallyBlock.sourceStart = start;
328         finallyBlock.sourceEnd = end;
329         finallyBlock.statements = new Statement[varCount];
330         for (int i = 0; i < varCount; i++){
331             finallyBlock.statements[i] = new Assignment(
332                 new SingleNameReference(CharOperation.concat(LOCAL_VAR_PREFIX, this.evaluationContext.localVariableNames[i]), position),
333                 new SingleNameReference(this.evaluationContext.localVariableNames[i], position),
334                 (int) position);
335         }
336         tryStatement.finallyBlock = finallyBlock;
337
338         newStatements[varCount] = tryStatement;
339         methodDecl.statements = newStatements;
340     }
341 }
342
343 protected void consumeMethodInvocationName() {
344     // MethodInvocation ::= Name '(' ArgumentListopt ')'
345

346     if (this.scanner.startPosition >= this.codeSnippetStart
347         && this.scanner.startPosition <= this.codeSnippetEnd + 1 + this.lineSeparatorLength // 14838
348
&& isTopLevelType()) {
349             
350         // when the name is only an identifier...we have a message send to "this" (implicit)
351

352         MessageSend m = newMessageSend();
353         m.sourceEnd = this.rParenPos;
354         m.sourceStart =
355             (int) ((m.nameSourcePosition = this.identifierPositionStack[this.identifierPtr]) >>> 32);
356         m.selector = this.identifierStack[this.identifierPtr--];
357         if (this.identifierLengthStack[this.identifierLengthPtr] == 1) {
358             m.receiver = new CodeSnippetThisReference(0,0,this.evaluationContext, true);
359             this.identifierLengthPtr--;
360         } else {
361             this.identifierLengthStack[this.identifierLengthPtr]--;
362             m.receiver = getUnspecifiedReference();
363             m.sourceStart = m.receiver.sourceStart;
364         }
365         pushOnExpressionStack(m);
366     } else {
367         super.consumeMethodInvocationName();
368     }
369 }
370
371 protected void consumeMethodInvocationSuper() {
372     // MethodInvocation ::= 'super' '.' 'Identifier' '(' ArgumentListopt ')'
373

374     MessageSend m = newMessageSend();
375     m.sourceStart = this.intStack[this.intPtr--];
376     m.sourceEnd = this.rParenPos;
377     m.nameSourcePosition = this.identifierPositionStack[this.identifierPtr];
378     m.selector = this.identifierStack[this.identifierPtr--];
379     this.identifierLengthPtr--;
380     m.receiver = new CodeSnippetSuperReference(m.sourceStart, this.endPosition);
381     pushOnExpressionStack(m);
382 }
383 protected void consumePrimaryNoNewArrayThis() {
384     // PrimaryNoNewArray ::= 'this'
385

386     if (this.scanner.startPosition >= this.codeSnippetStart
387         && this.scanner.startPosition <= this.codeSnippetEnd + 1 + this.lineSeparatorLength // 14838
388
&& isTopLevelType()) {
389         pushOnExpressionStack(
390             new CodeSnippetThisReference(this.intStack[this.intPtr--], this.endPosition, this.evaluationContext, false));
391     } else {
392         super.consumePrimaryNoNewArrayThis();
393     }
394 }
395 protected void consumeStatementBreak() {
396     super.consumeStatementBreak();
397     /* recovery */
398     recordLastStatementIfNeeded();
399 }
400 protected void consumeStatementBreakWithLabel() {
401     super.consumeStatementBreakWithLabel();
402     /* recovery */
403     recordLastStatementIfNeeded();
404 }
405 protected void consumeStatementCatch() {
406     super.consumeStatementCatch();
407     /* recovery */
408     recordLastStatementIfNeeded();
409 }
410 protected void consumeStatementContinue() {
411     super.consumeStatementContinue();
412     /* recovery */
413     recordLastStatementIfNeeded();
414 }
415 protected void consumeStatementContinueWithLabel() {
416     super.consumeStatementContinueWithLabel();
417     /* recovery */
418     recordLastStatementIfNeeded();
419 }
420 protected void consumeStatementDo() {
421     super.consumeStatementDo();
422     /* recovery */
423     recordLastStatementIfNeeded();
424 }
425 protected void consumeStatementFor() {
426     super.consumeStatementFor();
427     /* recovery */
428     recordLastStatementIfNeeded();
429 }
430 protected void consumeStatementIfNoElse() {
431     super.consumeStatementIfNoElse();
432     /* recovery */
433     recordLastStatementIfNeeded();
434 }
435 protected void consumeStatementIfWithElse() {
436     super.consumeStatementIfWithElse();
437     /* recovery */
438     recordLastStatementIfNeeded();
439 }
440 protected void consumeStatementLabel() {
441     super.consumeStatementLabel();
442     /* recovery */
443     recordLastStatementIfNeeded();
444 }
445 protected void consumeStatementReturn() {
446     // ReturnStatement ::= 'return' Expressionopt ';'
447

448     // returned value intercepted by code snippet
449
// support have to be defined at toplevel only
450
if ((this.hasRecoveredOnExpression
451             || (this.scanner.startPosition >= this.codeSnippetStart && this.scanner.startPosition <= this.codeSnippetEnd+1+this.lineSeparatorLength /* 14838*/))
452         && this.expressionLengthStack[this.expressionLengthPtr] != 0
453         && isTopLevelType()) {
454         this.expressionLengthPtr--;
455         Expression expression = this.expressionStack[this.expressionPtr--];
456         pushOnAstStack(
457             new CodeSnippetReturnStatement(
458                 expression,
459                 expression.sourceStart,
460                 expression.sourceEnd));
461     } else {
462         super.consumeStatementReturn();
463     }
464     /* recovery */
465     recordLastStatementIfNeeded();
466 }
467 protected void consumeStatementSwitch() {
468     super.consumeStatementSwitch();
469     /* recovery */
470     recordLastStatementIfNeeded();
471 }
472 protected void consumeStatementSynchronized() {
473     super.consumeStatementSynchronized();
474     /* recovery */
475     recordLastStatementIfNeeded();
476 }
477 protected void consumeStatementThrow() {
478     super.consumeStatementThrow();
479     /* recovery */
480     recordLastStatementIfNeeded();
481 }
482 protected void consumeStatementTry(boolean arg_0) {
483     super.consumeStatementTry(arg_0);
484     /* recovery */
485     recordLastStatementIfNeeded();
486 }
487 protected void consumeStatementWhile() {
488     super.consumeStatementWhile();
489     /* recovery */
490     recordLastStatementIfNeeded();
491 }
492 protected CompilationUnitDeclaration endParse(int act) {
493     if (this.hasRecoveredOnExpression) {
494         CompilationResult unitResult = this.compilationUnit.compilationResult;
495         if (act != ERROR_ACTION) { // expression recovery worked
496
// flush previously recorded problems
497
for (int i = 0; i < unitResult.problemCount; i++) {
498                 unitResult.problems[i] = null; // discard problem
499
}
500             unitResult.problemCount = 0;
501             if (this.referenceContext instanceof AbstractMethodDeclaration) {
502                 ((AbstractMethodDeclaration)this.referenceContext).ignoreFurtherInvestigation = false;
503             }
504             if (this.referenceContext instanceof CompilationUnitDeclaration) {
505                 ((CompilationUnitDeclaration)this.referenceContext).ignoreFurtherInvestigation = false;
506             }
507
508             // consume expresion as a return statement
509
consumeStatementReturn();
510             int fieldsCount =
511                 (this.evaluationContext.localVariableNames == null ? 0 : this.evaluationContext.localVariableNames.length)
512                 + (this.evaluationContext.declaringTypeName == null ? 0 : 1);
513             if (this.astPtr > (this.diet ? 0 : 2 + fieldsCount)) {
514                     // in diet mode, the ast stack was empty when we went for method body
515
// otherwise it contained the type, the generated fields for local variables,
516
// the generated field for 'this' and the method
517
consumeBlockStatements();
518             }
519             consumeMethodBody();
520             if (!this.diet) {
521                 consumeMethodDeclaration(true);
522                 if (fieldsCount > 0) {
523                     consumeClassBodyDeclarations();
524                 }
525                 consumeClassBodyDeclarationsopt();
526                 consumeClassDeclaration();
527                 consumeInternalCompilationUnitWithTypes();
528                 consumeCompilationUnit();
529             }
530             this.lastAct = ACCEPT_ACTION;
531         } else {
532             // might have more than one error recorded:
533
// 1. during regular parse
534
// 2. during expression recovery
535
// -> must filter out one of them, the earliest one is less accurate
536
int maxRegularPos = 0, problemCount = unitResult.problemCount;
537             for (int i = 0; i < this.problemCountBeforeRecovery; i++) {
538                 // skip unmatched bracket problems
539
if (unitResult.problems[i].getID() == IProblem.UnmatchedBracket) continue;
540                 
541                 int start = unitResult.problems[i].getSourceStart();
542                 if (start > maxRegularPos && start <= this.codeSnippetEnd) {
543                     maxRegularPos = start;
544                 }
545             }
546             int maxRecoveryPos = 0;
547             for (int i = this.problemCountBeforeRecovery; i < problemCount; i++) {
548                 // skip unmatched bracket problems
549
if (unitResult.problems[i].getID() == IProblem.UnmatchedBracket) continue;
550                 
551                 int start = unitResult.problems[i].getSourceStart();
552                 if (start > maxRecoveryPos && start <= this.codeSnippetEnd) {
553                     maxRecoveryPos = start;
554                 }
555             }
556             if (maxRecoveryPos > maxRegularPos) {
557                 System.arraycopy(unitResult.problems, this.problemCountBeforeRecovery, unitResult.problems, 0, problemCount - this.problemCountBeforeRecovery);
558                 unitResult.problemCount -= this.problemCountBeforeRecovery;
559             } else {
560                 unitResult.problemCount -= (problemCount - this.problemCountBeforeRecovery);
561             }
562             for (int i = unitResult.problemCount; i < problemCount; i++) {
563                 unitResult.problems[i] = null; // discard problem
564
}
565
566         }
567     }
568     return super.endParse(act);
569 }
570 protected NameReference getUnspecifiedReference() {
571     /* build a (unspecified) NameReference which may be qualified*/
572
573     if (this.scanner.startPosition >= this.codeSnippetStart
574         && this.scanner.startPosition <= this.codeSnippetEnd+1+this.lineSeparatorLength /*14838*/){
575         int length;
576         NameReference ref;
577         if ((length = this.identifierLengthStack[this.identifierLengthPtr--]) == 1) {
578             // single variable reference
579
ref =
580                 new CodeSnippetSingleNameReference(
581                     this.identifierStack[this.identifierPtr],
582                     this.identifierPositionStack[this.identifierPtr--],
583                     this.evaluationContext);
584         } else {
585             //Qualified variable reference
586
char[][] tokens = new char[length][];
587             this.identifierPtr -= length;
588             System.arraycopy(this.identifierStack, this.identifierPtr + 1, tokens, 0, length);
589             long[] positions = new long[length];
590             System.arraycopy(this.identifierPositionStack, this.identifierPtr + 1, positions, 0, length);
591             ref =
592                 new CodeSnippetQualifiedNameReference(tokens,
593                     positions,
594                     (int) (this.identifierPositionStack[this.identifierPtr + 1] >> 32), // sourceStart
595
(int) this.identifierPositionStack[this.identifierPtr + length],
596                     this.evaluationContext); // sourceEnd
597
}
598         return ref;
599     } else {
600         return super.getUnspecifiedReference();
601     }
602 }
603 protected NameReference getUnspecifiedReferenceOptimized() {
604     /* build a (unspecified) NameReference which may be qualified
605     The optimization occurs for qualified reference while we are
606     certain in this case the last item of the qualified name is
607     a field access. This optimization is IMPORTANT while it results
608     that when a NameReference is build, the type checker should always
609     look for that it is not a type reference */

610
611     if (this.scanner.startPosition >= this.codeSnippetStart
612         && this.scanner.startPosition <= this.codeSnippetEnd+1+this.lineSeparatorLength /*14838*/){
613         int length;
614         NameReference ref;
615         if ((length = this.identifierLengthStack[this.identifierLengthPtr--]) == 1) {
616             // single variable reference
617
ref =
618                 new CodeSnippetSingleNameReference(
619                     this.identifierStack[this.identifierPtr],
620                     this.identifierPositionStack[this.identifierPtr--],
621                     this.evaluationContext);
622             ref.bits &= ~ASTNode.RestrictiveFlagMASK;
623             ref.bits |= Binding.LOCAL | Binding.FIELD;
624             return ref;
625         }
626
627         //Qualified-variable-reference
628
//In fact it is variable-reference DOT field-ref , but it would result in a type
629
//conflict tha can be only reduce by making a superclass (or inetrface ) between
630
//nameReference and FiledReference or putting FieldReference under NameReference
631
//or else..........This optimisation is not really relevant so just leave as it is
632

633         char[][] tokens = new char[length][];
634         this.identifierPtr -= length;
635         System.arraycopy(this.identifierStack, this.identifierPtr + 1, tokens, 0, length);
636         long[] positions = new long[length];
637         System.arraycopy(this.identifierPositionStack, this.identifierPtr + 1, positions, 0, length);
638         ref = new CodeSnippetQualifiedNameReference(
639                 tokens,
640                 positions,
641                 (int) (this.identifierPositionStack[this.identifierPtr + 1] >> 32), // sourceStart
642
(int) this.identifierPositionStack[this.identifierPtr + length],
643                 this.evaluationContext); // sourceEnd
644
ref.bits &= ~ASTNode.RestrictiveFlagMASK;
645         ref.bits |= Binding.LOCAL | Binding.FIELD;
646         return ref;
647     } else {
648         return super.getUnspecifiedReferenceOptimized();
649     }
650 }
651 protected void ignoreExpressionAssignment() {
652     super.ignoreExpressionAssignment();
653     /* recovery */
654     recordLastStatementIfNeeded();
655 }
656 /**
657  * Returns whether we are parsing a top level type or not.
658  */

659 private boolean isTopLevelType() {
660     return this.nestedType == (this.diet ? 0 : 1);
661 }
662 protected MessageSend newMessageSend() {
663     // '(' ArgumentListopt ')'
664
// the arguments are on the expression stack
665

666     CodeSnippetMessageSend m = new CodeSnippetMessageSend(this.evaluationContext);
667     int length;
668     if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
669         this.expressionPtr -= length;
670         System.arraycopy(
671             this.expressionStack,
672             this.expressionPtr + 1,
673             m.arguments = new Expression[length],
674             0,
675             length);
676     }
677     return m;
678 }
679 /**
680  * Records the scanner position if we're parsing a top level type.
681  */

682 private void recordLastStatementIfNeeded() {
683     if ((isTopLevelType()) && (this.scanner.startPosition <= this.codeSnippetEnd+this.lineSeparatorLength /*14838*/)) {
684         this.lastStatement = this.scanner.startPosition;
685     }
686 }
687
688 protected void reportSyntaxErrors(boolean isDietParse, int oldFirstToken) {
689     if (!isDietParse) {
690         this.scanner.initialPosition = this.lastStatement;
691         this.scanner.eofPosition = this.codeSnippetEnd + 1; // stop after expression
692
oldFirstToken = TokenNameTWIDDLE;//TokenNameREMAINDER; // first token of th expression parse
693
}
694     super.reportSyntaxErrors(isDietParse, oldFirstToken);
695 }
696 /*
697  * A syntax error was detected. If a method is being parsed, records the number of errors and
698  * attempts to restart from the last statement by going for an expression.
699  */

700 protected boolean resumeOnSyntaxError() {
701     if (this.diet || this.hasRecoveredOnExpression) { // no reentering inside expression recovery
702
return false;
703     }
704     
705     // record previous error, in case more accurate than potential one in expression recovery
706
// e.g. "return foo(a a); 1+3"
707
this.problemCountBeforeRecovery = this.compilationUnit.compilationResult.problemCount;
708
709     // reposition for expression parsing
710
if (this.lastStatement < 0) {
711         this.lastStatement = this.codeSnippetStart; // no statement reduced prior to error point
712
}
713     this.scanner.initialPosition = this.lastStatement;
714     this.scanner.startPosition = this.lastStatement;
715     this.scanner.currentPosition = this.lastStatement;
716     this.scanner.eofPosition = this.codeSnippetEnd < Integer.MAX_VALUE ? this.codeSnippetEnd + 1 : this.codeSnippetEnd; // stop after expression
717
this.scanner.commentPtr = -1;
718
719     // reset stacks in consistent state
720
this.expressionPtr = -1;
721     this.identifierPtr = -1;
722     this.identifierLengthPtr = -1;
723
724     // go for the expression
725
goForExpression();
726     this.hasRecoveredOnExpression = true;
727     this.hasReportedError = false;
728     this.hasError = false;
729     return true;
730 }
731 }
732
Popular Tags