a94618b9ec95260ddb87457e633d33655b006af5
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / compiler / DocumentElementParser.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
3  * All rights reserved. This program and the accompanying materials 
4  * are made available under the terms of the Common Public License v0.5 
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v05.html
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  ******************************************************************************/
11 package net.sourceforge.phpdt.internal.compiler;
12
13 /*
14  * A document element parser extracts structural information
15  * from a piece of source, providing detailed source positions info.
16  *
17  * also see @IDocumentElementRequestor
18  *
19  * The structural investigation includes:
20  * - the package statement
21  * - import statements
22  * - top-level types: package member, member types (member types of member types...)
23  * - fields
24  * - methods
25  *
26  * Any (parsing) problem encountered is also provided.
27  */
28 import net.sourceforge.phpdt.internal.compiler.env.*;
29
30 import net.sourceforge.phpdt.internal.compiler.impl.*;
31 import net.sourceforge.phpdt.core.compiler.*;
32 import net.sourceforge.phpdt.internal.compiler.ast.*;
33 import net.sourceforge.phpdt.internal.compiler.parser.*;
34 import net.sourceforge.phpdt.internal.compiler.problem.*;
35 import net.sourceforge.phpdt.internal.compiler.util.*;
36
37 public class DocumentElementParser extends Parser {
38         IDocumentElementRequestor requestor;
39         private int localIntPtr;
40         private int lastFieldEndPosition;
41         private int lastFieldBodyEndPosition;   
42         private int typeStartPosition;
43         private long selectorSourcePositions;
44         private int typeDims;
45         private int extendsDim;
46         private int declarationSourceStart;
47
48         /* int[] stack for storing javadoc positions */
49         int[][] intArrayStack;
50         int intArrayPtr;
51         
52         CompilerOptions options;
53         
54 public DocumentElementParser(
55         final IDocumentElementRequestor requestor, 
56         IProblemFactory problemFactory,
57         CompilerOptions options) {
58         super(new ProblemReporter(
59                 DefaultErrorHandlingPolicies.exitAfterAllProblems(), 
60                 options, 
61                 problemFactory) {
62                 public void record(IProblem problem, CompilationResult unitResult) {
63                         requestor.acceptProblem(problem);
64                 }
65         },
66         false,
67         options.assertMode);
68         this.requestor = requestor;
69         intArrayStack = new int[30][];
70         this.options = options;
71 }
72
73 /**
74  *
75  * INTERNAL USE-ONLY
76  */
77 protected void adjustInterfaceModifiers() {
78         intStack[intPtr - 2] |= AccInterface;
79 }
80 /*
81  * Will clear the comment stack when looking
82  * for a potential JavaDoc which might contain @deprecated.
83  *
84  * Additionally, before investigating for @deprecated, retrieve the positions
85  * of the JavaDoc comments so as to notify requestor with them.
86  */
87 public void checkAnnotation() {
88
89         /* persisting javadoc positions */
90         pushOnIntArrayStack(this.getJavaDocPositions());
91         boolean deprecated = false;
92         int lastAnnotationIndex = -1;
93
94         //since jdk1.2 look only in the last java doc comment...
95         found : {
96                 if ((lastAnnotationIndex = scanner.commentPtr) >= 0) { //look for @deprecated
97                         scanner.commentPtr = -1;
98                         // reset the comment stack, since not necessary after having checked
99                         int commentSourceStart = scanner.commentStarts[lastAnnotationIndex];
100                         // javadoc only (non javadoc comment have negative end positions.)
101                         int commentSourceEnd = scanner.commentStops[lastAnnotationIndex] - 1;
102                         //stop is one over
103                         char[] comment = scanner.source;
104
105                         for (int i = commentSourceStart + 3; i < commentSourceEnd - 10; i++) {
106                                 if ((comment[i] == '@')
107                                         && (comment[i + 1] == 'd')
108                                         && (comment[i + 2] == 'e')
109                                         && (comment[i + 3] == 'p')
110                                         && (comment[i + 4] == 'r')
111                                         && (comment[i + 5] == 'e')
112                                         && (comment[i + 6] == 'c')
113                                         && (comment[i + 7] == 'a')
114                                         && (comment[i + 8] == 't')
115                                         && (comment[i + 9] == 'e')
116                                         && (comment[i + 10] == 'd')) {
117                                         // ensure the tag is properly ended: either followed by a space, line end or asterisk.
118                                         int nextPos = i + 11;
119                                         deprecated = 
120                                                 (comment[nextPos] == ' ')
121                                                         || (comment[nextPos] == '\n')
122                                                         || (comment[nextPos] == '\r')
123                                                         || (comment[nextPos] == '*'); 
124                                         break found;
125                                 }
126                         }
127                 }
128         }
129         if (deprecated) {
130                 checkAndSetModifiers(AccDeprecated);
131         }
132         // modify the modifier source start to point at the first comment
133         if (lastAnnotationIndex >= 0) {
134                 declarationSourceStart = scanner.commentStarts[0];
135         }
136 }
137 /**
138  *
139  * INTERNAL USE-ONLY
140  */
141 protected void consumeClassBodyDeclaration() {
142         // ClassBodyDeclaration ::= Diet Block
143         //push an Initializer
144         //optimize the push/pop
145
146         super.consumeClassBodyDeclaration();
147         Initializer initializer = (Initializer) astStack[astPtr];
148         requestor.acceptInitializer(
149                 initializer.declarationSourceStart,
150                 initializer.declarationSourceEnd,
151                 intArrayStack[intArrayPtr--], 
152                 0,
153                 modifiersSourceStart, 
154                 initializer.block.sourceStart,
155                 initializer.block.sourceEnd);
156 }
157 /**
158  *
159  * INTERNAL USE-ONLY
160  */
161 protected void consumeClassDeclaration() {
162         super.consumeClassDeclaration();
163         // we know that we have a TypeDeclaration on the top of the astStack
164         if (isLocalDeclaration()) {
165                 // we ignore the local variable declarations
166                 return;
167         }
168         requestor.exitClass(endStatementPosition, // '}' is the end of the body 
169          ((TypeDeclaration) astStack[astPtr]).declarationSourceEnd);
170 }
171 /**
172  *
173  * INTERNAL USE-ONLY
174  */
175 protected void consumeClassHeader() {
176         //ClassHeader ::= $empty
177         super.consumeClassHeader();
178         if (isLocalDeclaration()) {
179                 // we ignore the local variable declarations
180                 intArrayPtr--;
181                 return;
182         }
183         TypeDeclaration typeDecl = (TypeDeclaration) astStack[astPtr];
184         TypeReference[] superInterfaces = typeDecl.superInterfaces;
185         char[][] interfaceNames = null;
186         int[] interfaceNameStarts = null;
187         int[] interfaceNameEnds = null;
188         if (superInterfaces != null) {
189                 int superInterfacesLength = superInterfaces.length;
190                 interfaceNames = new char[superInterfacesLength][];
191                 interfaceNameStarts = new int[superInterfacesLength];
192                 interfaceNameEnds = new int[superInterfacesLength];
193                 for (int i = 0; i < superInterfacesLength; i++) {
194                         TypeReference superInterface = superInterfaces[i];
195                         interfaceNames[i] = CharOperation.concatWith(superInterface.getTypeName(), '.'); 
196                         interfaceNameStarts[i] = superInterface.sourceStart;
197                         interfaceNameEnds[i] = superInterface.sourceEnd;
198                 }
199         }
200         // flush the comments related to the class header
201         scanner.commentPtr = -1;
202         TypeReference superclass = typeDecl.superclass;
203         if (superclass == null) {
204                 requestor.enterClass(
205                         typeDecl.declarationSourceStart, 
206                         intArrayStack[intArrayPtr--], 
207                         typeDecl.modifiers, 
208                         typeDecl.modifiersSourceStart, 
209                         typeStartPosition, 
210                         typeDecl.name, 
211                         typeDecl.sourceStart, 
212                         typeDecl.sourceEnd, 
213                         null, 
214                         -1, 
215                         -1, 
216                         interfaceNames, 
217                         interfaceNameStarts, 
218                         interfaceNameEnds, 
219                         scanner.currentPosition - 1); 
220         } else {
221                 requestor.enterClass(
222                         typeDecl.declarationSourceStart, 
223                         intArrayStack[intArrayPtr--], 
224                         typeDecl.modifiers, 
225                         typeDecl.modifiersSourceStart, 
226                         typeStartPosition, 
227                         typeDecl.name, 
228                         typeDecl.sourceStart, 
229                         typeDecl.sourceEnd, 
230                         CharOperation.concatWith(superclass.getTypeName(), '.'), 
231                         superclass.sourceStart, 
232                         superclass.sourceEnd, 
233                         interfaceNames, 
234                         interfaceNameStarts, 
235                         interfaceNameEnds, 
236                         scanner.currentPosition - 1); 
237
238         }
239 }
240 protected void consumeClassHeaderName() {
241         // ClassHeaderName ::= Modifiersopt 'class' 'Identifier'
242         TypeDeclaration typeDecl;
243         if (nestedMethod[nestedType] == 0) {
244                 if (nestedType != 0) {
245                         typeDecl = new MemberTypeDeclaration(this.compilationUnit.compilationResult);
246                 } else {
247                         typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult);
248                 }
249         } else {
250                 // Record that the block has a declaration for local types
251                 typeDecl = new LocalTypeDeclaration(this.compilationUnit.compilationResult);
252                 markCurrentMethodWithLocalType();
253                 blockReal();
254         }
255
256         //highlight the name of the type
257         long pos = identifierPositionStack[identifierPtr];
258         typeDecl.sourceEnd = (int) pos;
259         typeDecl.sourceStart = (int) (pos >>> 32);
260         typeDecl.name = identifierStack[identifierPtr--];
261         identifierLengthPtr--;
262
263         //compute the declaration source too
264         // 'class' and 'interface' push an int position
265         typeStartPosition = typeDecl.declarationSourceStart = intStack[intPtr--];
266         intPtr--;
267         int declarationSourceStart = intStack[intPtr--];
268         typeDecl.modifiersSourceStart = intStack[intPtr--];
269         typeDecl.modifiers = intStack[intPtr--];
270         if (typeDecl.declarationSourceStart > declarationSourceStart) {
271                 typeDecl.declarationSourceStart = declarationSourceStart;
272         }
273         typeDecl.bodyStart = typeDecl.sourceEnd + 1;
274         pushOnAstStack(typeDecl);
275 }
276 /**
277  *
278  * INTERNAL USE-ONLY
279  */
280 protected void consumeCompilationUnit() {
281         // CompilationUnit ::= EnterCompilationUnit PackageDeclarationopt ImportDeclarationsopt
282         requestor.exitCompilationUnit(scanner.source.length - 1);
283 }
284 /**
285  *
286  * INTERNAL USE-ONLY
287  */
288 protected void consumeConstructorDeclaration() {
289         // ConstructorDeclaration ::= ConstructorHeader ConstructorBody
290         super.consumeConstructorDeclaration();
291         if (isLocalDeclaration()) {
292                 // we ignore the local variable declarations
293                 return;
294         }
295         ConstructorDeclaration cd = (ConstructorDeclaration) astStack[astPtr];
296         requestor.exitConstructor(endStatementPosition, cd.declarationSourceEnd);
297 }
298 /**
299  *
300  * INTERNAL USE-ONLY
301  */
302 protected void consumeConstructorHeader() {
303         // ConstructorHeader ::= ConstructorHeaderName MethodHeaderParameters MethodHeaderThrowsClauseopt
304         super.consumeConstructorHeader();
305         if (isLocalDeclaration()) {
306                 // we ignore the local variable declarations
307                 intArrayPtr--;
308                 return;
309         }
310         ConstructorDeclaration cd = (ConstructorDeclaration) astStack[astPtr];
311         Argument[] arguments = cd.arguments;
312         char[][] argumentTypes = null;
313         char[][] argumentNames = null;
314         int[] argumentTypeStarts = null;
315         int[] argumentTypeEnds = null;
316         int[] argumentNameStarts = null;
317         int[] argumentNameEnds = null;
318         if (arguments != null) {
319                 int argumentLength = arguments.length;
320                 argumentTypes = new char[argumentLength][];
321                 argumentNames = new char[argumentLength][];
322                 argumentNameStarts = new int[argumentLength];
323                 argumentNameEnds = new int[argumentLength];
324                 argumentTypeStarts = new int[argumentLength];
325                 argumentTypeEnds = new int[argumentLength];
326                 for (int i = 0; i < argumentLength; i++) {
327                         Argument argument = arguments[i];
328                         TypeReference argumentType = argument.type;
329                         argumentTypes[i] = returnTypeName(argumentType);
330                         argumentNames[i] = argument.name;
331                         argumentNameStarts[i] = argument.sourceStart;
332                         argumentNameEnds[i] = argument.sourceEnd;
333                         argumentTypeStarts[i] = argumentType.sourceStart;
334                         argumentTypeEnds[i] = argumentType.sourceEnd;
335                 }
336         }
337         TypeReference[] thrownExceptions = cd.thrownExceptions;
338         char[][] exceptionTypes = null;
339         int[] exceptionTypeStarts = null;
340         int[] exceptionTypeEnds = null;
341         if (thrownExceptions != null) {
342                 int thrownExceptionLength = thrownExceptions.length;
343                 exceptionTypes = new char[thrownExceptionLength][];
344                 exceptionTypeStarts = new int[thrownExceptionLength];
345                 exceptionTypeEnds = new int[thrownExceptionLength];
346                 for (int i = 0; i < thrownExceptionLength; i++) {
347                         TypeReference exception = thrownExceptions[i];
348                         exceptionTypes[i] = CharOperation.concatWith(exception.getTypeName(), '.');
349                         exceptionTypeStarts[i] = exception.sourceStart;
350                         exceptionTypeEnds[i] = exception.sourceEnd;
351                 }
352         }
353         requestor
354                 .enterConstructor(
355                         cd.declarationSourceStart, 
356                         intArrayStack[intArrayPtr--], 
357                         cd.modifiers,
358                         cd.modifiersSourceStart, 
359                         cd.selector, 
360                         cd.sourceStart, 
361                         (int) (selectorSourcePositions & 0xFFFFFFFFL), 
362                         // retrieve the source end of the name
363                         argumentTypes, 
364                         argumentTypeStarts, 
365                         argumentTypeEnds, 
366                         argumentNames, 
367                         argumentNameStarts, 
368                         argumentNameEnds, 
369                         rParenPos, 
370                         // right parenthesis
371                         exceptionTypes, 
372                         exceptionTypeStarts, 
373                         exceptionTypeEnds, 
374                         scanner.currentPosition - 1); 
375 }
376 protected void consumeConstructorHeaderName() {
377         // ConstructorHeaderName ::=  Modifiersopt 'Identifier' '('
378         ConstructorDeclaration cd = new ConstructorDeclaration(this.compilationUnit.compilationResult);
379
380         //name -- this is not really revelant but we do .....
381         cd.selector = identifierStack[identifierPtr];
382         selectorSourcePositions = identifierPositionStack[identifierPtr--];
383         identifierLengthPtr--;
384
385         //modifiers
386         cd.declarationSourceStart = intStack[intPtr--];
387         cd.modifiersSourceStart = intStack[intPtr--];
388         cd.modifiers = intStack[intPtr--];
389
390         //highlight starts at the selector starts
391         cd.sourceStart = (int) (selectorSourcePositions >>> 32);
392         pushOnAstStack(cd);
393
394         cd.sourceEnd = lParenPos;
395         cd.bodyStart = lParenPos + 1;
396 }
397 protected void consumeDefaultModifiers() {
398         checkAnnotation(); // might update modifiers with AccDeprecated
399         pushOnIntStack(modifiers); // modifiers
400         pushOnIntStack(-1);
401         pushOnIntStack(
402                 declarationSourceStart >= 0 ? declarationSourceStart : scanner.startPosition); 
403         resetModifiers();
404 }
405 protected void consumeDiet() {
406         // Diet ::= $empty
407         super.consumeDiet();
408         /* persisting javadoc positions
409          * Will be consume in consumeClassBodyDeclaration
410          */
411         pushOnIntArrayStack(this.getJavaDocPositions());        
412 }
413 /**
414  *
415  * INTERNAL USE-ONLY
416  */
417 protected void consumeEnterCompilationUnit() {
418         // EnterCompilationUnit ::= $empty
419         requestor.enterCompilationUnit();
420 }
421 /**
422  *
423  * INTERNAL USE-ONLY
424  */
425 protected void consumeEnterVariable() {
426         // EnterVariable ::= $empty
427         boolean isLocalDeclaration = isLocalDeclaration();
428         if (!isLocalDeclaration && (variablesCounter[nestedType] != 0)) {
429                 requestor.exitField(lastFieldBodyEndPosition, lastFieldEndPosition);
430         }
431         char[] name = identifierStack[identifierPtr];
432         long namePosition = identifierPositionStack[identifierPtr--];
433         int extendedTypeDimension = intStack[intPtr--];
434
435         AbstractVariableDeclaration declaration;
436         if (nestedMethod[nestedType] != 0) {
437                 // create the local variable declarations
438                 declaration = 
439                         new LocalDeclaration(null, name, (int) (namePosition >>> 32), (int) namePosition); 
440         } else {
441                 // create the field declaration
442                 declaration = 
443                         new FieldDeclaration(null, name, (int) (namePosition >>> 32), (int) namePosition); 
444         }
445         identifierLengthPtr--;
446         TypeReference type;
447         int variableIndex = variablesCounter[nestedType];
448         int typeDim = 0;
449         if (variableIndex == 0) {
450                 // first variable of the declaration (FieldDeclaration or LocalDeclaration)
451                 if (nestedMethod[nestedType] != 0) {
452                         // local declaration
453                         declaration.declarationSourceStart = intStack[intPtr--];
454                         declaration.modifiersSourceStart = intStack[intPtr--];
455                         declaration.modifiers = intStack[intPtr--];
456                         type = getTypeReference(typeDim = intStack[intPtr--]); // type dimension
457                         pushOnAstStack(type);
458                 } else {
459                         // field declaration
460                         type = getTypeReference(typeDim = intStack[intPtr--]); // type dimension
461                         pushOnAstStack(type);
462                         declaration.declarationSourceStart = intStack[intPtr--];
463                         declaration.modifiersSourceStart = intStack[intPtr--];
464                         declaration.modifiers = intStack[intPtr--];
465                 }
466         } else {
467                 type = (TypeReference) astStack[astPtr - variableIndex];
468                 typeDim = type.dimensions();
469                 AbstractVariableDeclaration previousVariable = 
470                         (AbstractVariableDeclaration) astStack[astPtr]; 
471                 declaration.declarationSourceStart = previousVariable.declarationSourceStart;
472                 declaration.modifiers = previousVariable.modifiers;
473                 declaration.modifiersSourceStart = previousVariable.modifiersSourceStart;
474         }
475
476         localIntPtr = intPtr;
477
478         if (extendedTypeDimension == 0) {
479                 declaration.type = type;
480         } else {
481                 int dimension = typeDim + extendedTypeDimension;
482                 //on the identifierLengthStack there is the information about the type....
483                 int baseType;
484                 if ((baseType = identifierLengthStack[identifierLengthPtr + 1]) < 0) {
485                         //it was a baseType
486                         declaration.type = TypeReference.baseTypeReference(-baseType, dimension);
487                         declaration.type.sourceStart = type.sourceStart;
488                         declaration.type.sourceEnd = type.sourceEnd;
489                 } else {
490                         declaration.type = this.copyDims(type, dimension);
491                 }
492         }
493         variablesCounter[nestedType]++;
494         nestedMethod[nestedType]++;
495         pushOnAstStack(declaration);
496
497         int[] javadocPositions = intArrayStack[intArrayPtr];
498         if (!isLocalDeclaration) {
499                 requestor
500                         .enterField(
501                                 declaration.declarationSourceStart, 
502                                 javadocPositions, 
503                                 declaration.modifiers, 
504                                 declaration.modifiersSourceStart, 
505                                 returnTypeName(declaration.type), 
506                                 type.sourceStart, 
507                                 type.sourceEnd, 
508                                 typeDims, 
509                                 name, 
510                                 (int) (namePosition >>> 32), 
511                                 (int) namePosition, 
512                                 extendedTypeDimension, 
513                                 extendedTypeDimension == 0 ? -1 : endPosition); 
514         }
515 }
516 /**
517  *
518  * INTERNAL USE-ONLY
519  */
520 protected void consumeExitVariableWithInitialization() {
521         // ExitVariableWithInitialization ::= $empty
522         // the scanner is located after the comma or the semi-colon.
523         // we want to include the comma or the semi-colon
524         super.consumeExitVariableWithInitialization();
525         nestedMethod[nestedType]--;     
526         lastFieldEndPosition = scanner.currentPosition - 1;
527         lastFieldBodyEndPosition =      ((AbstractVariableDeclaration) astStack[astPtr]).initialization.sourceEnd;
528 }
529 protected void consumeExitVariableWithoutInitialization() {
530         // ExitVariableWithoutInitialization ::= $empty
531         // do nothing by default
532         super.consumeExitVariableWithoutInitialization();
533         nestedMethod[nestedType]--;     
534         lastFieldEndPosition = scanner.currentPosition - 1;
535         lastFieldBodyEndPosition = scanner.startPosition - 1;
536 }
537 /**
538  *
539  * INTERNAL USE-ONLY
540  */
541 protected void consumeFieldDeclaration() {
542         // See consumeLocalVariableDeclarationDefaultModifier() in case of change: duplicated code
543         // FieldDeclaration ::= Modifiersopt Type VariableDeclarators ';'
544         // the super.consumeFieldDeclaration will reinitialize the variableCounter[nestedType]  
545         int variableIndex = variablesCounter[nestedType];
546         super.consumeFieldDeclaration();
547         intArrayPtr--;
548         if (isLocalDeclaration())
549                 return;
550         if (variableIndex != 0) {
551                 requestor.exitField(lastFieldBodyEndPosition, lastFieldEndPosition);
552         }
553 }
554 protected void consumeFormalParameter() {
555         // FormalParameter ::= Type VariableDeclaratorId ==> false
556         // FormalParameter ::= Modifiers Type VariableDeclaratorId ==> true
557         /*
558         astStack : 
559         identifierStack : type identifier
560         intStack : dim dim
561          ==>
562         astStack : Argument
563         identifierStack :  
564         intStack :  
565         */
566
567         identifierLengthPtr--;
568         char[] name = identifierStack[identifierPtr];
569         long namePositions = identifierPositionStack[identifierPtr--];
570         TypeReference type = getTypeReference(intStack[intPtr--] + intStack[intPtr--]);
571         intPtr -= 3;
572         Argument arg = 
573                 new Argument(
574                         name, 
575                         namePositions, 
576                         type, 
577                         intStack[intPtr + 1]); // modifiers
578         pushOnAstStack(arg);
579         intArrayPtr--;
580 }
581 /**
582  *
583  * INTERNAL USE-ONLY
584  */
585 protected void consumeInterfaceDeclaration() {
586         super.consumeInterfaceDeclaration();
587         // we know that we have a TypeDeclaration on the top of the astStack
588         if (isLocalDeclaration()) {
589                 // we ignore the local variable declarations
590                 return;
591         }
592         requestor.exitInterface(endStatementPosition, // the '}' is the end of the body
593          ((TypeDeclaration) astStack[astPtr]).declarationSourceEnd);
594 }
595 /**
596  *
597  * INTERNAL USE-ONLY
598  */
599 protected void consumeInterfaceHeader() {
600         //InterfaceHeader ::= $empty
601         super.consumeInterfaceHeader();
602         if (isLocalDeclaration()) {
603                 // we ignore the local variable declarations
604                 intArrayPtr--;
605                 return;
606         }
607         TypeDeclaration typeDecl = (TypeDeclaration) astStack[astPtr];
608         TypeReference[] superInterfaces = typeDecl.superInterfaces;
609         char[][] interfaceNames = null;
610         int[] interfaceNameStarts = null;
611         int[] interfacenameEnds = null;
612         int superInterfacesLength = 0;
613         if (superInterfaces != null) {
614                 superInterfacesLength = superInterfaces.length;
615                 interfaceNames = new char[superInterfacesLength][];
616                 interfaceNameStarts = new int[superInterfacesLength];
617                 interfacenameEnds = new int[superInterfacesLength];
618         }
619         if (superInterfaces != null) {
620                 for (int i = 0; i < superInterfacesLength; i++) {
621                         TypeReference superInterface = superInterfaces[i];
622                         interfaceNames[i] = CharOperation.concatWith(superInterface.getTypeName(), '.'); 
623                         interfaceNameStarts[i] = superInterface.sourceStart;
624                         interfacenameEnds[i] = superInterface.sourceEnd;
625                 }
626         }
627         // flush the comments related to the interface header
628         scanner.commentPtr = -1;
629         requestor.enterInterface(
630                 typeDecl.declarationSourceStart, 
631                 intArrayStack[intArrayPtr--], 
632                 typeDecl.modifiers, 
633                 typeDecl.modifiersSourceStart, 
634                 typeStartPosition, 
635                 typeDecl.name, 
636                 typeDecl.sourceStart, 
637                 typeDecl.sourceEnd, 
638                 interfaceNames, 
639                 interfaceNameStarts, 
640                 interfacenameEnds, 
641                 scanner.currentPosition - 1); 
642 }
643 protected void consumeInterfaceHeaderName() {
644         // InterfaceHeaderName ::= Modifiersopt 'interface' 'Identifier'
645         TypeDeclaration typeDecl;
646         if (nestedMethod[nestedType] == 0) {
647                 if (nestedType != 0) {
648                         typeDecl = new MemberTypeDeclaration(this.compilationUnit.compilationResult);
649                 } else {
650                         typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult);
651                 }
652         } else {
653                 // Record that the block has a declaration for local types
654                 typeDecl = new LocalTypeDeclaration(this.compilationUnit.compilationResult);
655                 markCurrentMethodWithLocalType();
656                 blockReal();
657         }
658
659         //highlight the name of the type
660         long pos = identifierPositionStack[identifierPtr];
661         typeDecl.sourceEnd = (int) pos;
662         typeDecl.sourceStart = (int) (pos >>> 32);
663         typeDecl.name = identifierStack[identifierPtr--];
664         identifierLengthPtr--;
665
666         //compute the declaration source too
667         // 'class' and 'interface' push an int position
668         typeStartPosition = typeDecl.declarationSourceStart = intStack[intPtr--];
669         intPtr--;
670         int declarationSourceStart = intStack[intPtr--];
671         typeDecl.modifiersSourceStart = intStack[intPtr--];
672         typeDecl.modifiers = intStack[intPtr--];
673         if (typeDecl.declarationSourceStart > declarationSourceStart) {
674                 typeDecl.declarationSourceStart = declarationSourceStart;
675         }
676         typeDecl.bodyStart = typeDecl.sourceEnd + 1;
677         pushOnAstStack(typeDecl);
678 }
679 /**
680  *
681  * INTERNAL USE-ONLY
682  */
683 protected void consumeLocalVariableDeclaration() {
684         // See consumeLocalVariableDeclarationDefaultModifier() in case of change: duplicated code
685         // FieldDeclaration ::= Modifiersopt Type VariableDeclarators ';'
686
687         super.consumeLocalVariableDeclaration();
688         intArrayPtr--;
689 }
690 /**
691  *
692  * INTERNAL USE-ONLY
693  */
694 protected void consumeMethodDeclaration(boolean isNotAbstract) {
695         // MethodDeclaration ::= MethodHeader MethodBody
696         // AbstractMethodDeclaration ::= MethodHeader ';'
697         super.consumeMethodDeclaration(isNotAbstract);
698         if (isLocalDeclaration()) {
699                 // we ignore the local variable declarations
700                 return;
701         }
702         MethodDeclaration md = (MethodDeclaration) astStack[astPtr];
703         requestor.exitMethod(endStatementPosition, md.declarationSourceEnd);
704 }
705 /**
706  *
707  * INTERNAL USE-ONLY
708  */
709 protected void consumeMethodHeader() {
710         // MethodHeader ::= MethodHeaderName MethodHeaderParameters MethodHeaderExtendedDims ThrowsClauseopt
711         super.consumeMethodHeader();
712         if (isLocalDeclaration()) {
713                 // we ignore the local variable declarations
714                 intArrayPtr--;
715                 return;
716         }
717         MethodDeclaration md = (MethodDeclaration) astStack[astPtr];
718
719         TypeReference returnType = md.returnType;
720         char[] returnTypeName = returnTypeName(returnType);
721         Argument[] arguments = md.arguments;
722         char[][] argumentTypes = null;
723         char[][] argumentNames = null;
724         int[] argumentTypeStarts = null;
725         int[] argumentTypeEnds = null;
726         int[] argumentNameStarts = null;
727         int[] argumentNameEnds = null;
728         if (arguments != null) {
729                 int argumentLength = arguments.length;
730                 argumentTypes = new char[argumentLength][];
731                 argumentNames = new char[argumentLength][];
732                 argumentNameStarts = new int[argumentLength];
733                 argumentNameEnds = new int[argumentLength];
734                 argumentTypeStarts = new int[argumentLength];
735                 argumentTypeEnds = new int[argumentLength];
736                 for (int i = 0; i < argumentLength; i++) {
737                         Argument argument = arguments[i];
738                         TypeReference argumentType = argument.type;
739                         argumentTypes[i] = returnTypeName(argumentType);
740                         argumentNames[i] = argument.name;
741                         argumentNameStarts[i] = argument.sourceStart;
742                         argumentNameEnds[i] = argument.sourceEnd;
743                         argumentTypeStarts[i] = argumentType.sourceStart;
744                         argumentTypeEnds[i] = argumentType.sourceEnd;
745                 }
746         }
747         TypeReference[] thrownExceptions = md.thrownExceptions;
748         char[][] exceptionTypes = null;
749         int[] exceptionTypeStarts = null;
750         int[] exceptionTypeEnds = null;
751         if (thrownExceptions != null) {
752                 int thrownExceptionLength = thrownExceptions.length;
753                 exceptionTypeStarts = new int[thrownExceptionLength];
754                 exceptionTypeEnds = new int[thrownExceptionLength];
755                 exceptionTypes = new char[thrownExceptionLength][];
756                 for (int i = 0; i < thrownExceptionLength; i++) {
757                         TypeReference exception = thrownExceptions[i];
758                         exceptionTypes[i] = CharOperation.concatWith(exception.getTypeName(), '.');
759                         exceptionTypeStarts[i] = exception.sourceStart;
760                         exceptionTypeEnds[i] = exception.sourceEnd;
761                 }
762         }
763         requestor
764                 .enterMethod(
765                         md.declarationSourceStart, 
766                         intArrayStack[intArrayPtr--], 
767                         md.modifiers, 
768                         md.modifiersSourceStart, 
769                         returnTypeName, 
770                         returnType.sourceStart, 
771                         returnType.sourceEnd, 
772                         typeDims, 
773                         md.selector, 
774                         md.sourceStart, 
775                         (int) (selectorSourcePositions & 0xFFFFFFFFL), 
776                         argumentTypes, 
777                         argumentTypeStarts, 
778                         argumentTypeEnds, 
779                         argumentNames, 
780                         argumentNameStarts, 
781                         argumentNameEnds, 
782                         rParenPos, 
783                         extendsDim, 
784                         extendsDim == 0 ? -1 : endPosition, 
785                         exceptionTypes, 
786                         exceptionTypeStarts, 
787                         exceptionTypeEnds, 
788                         scanner.currentPosition - 1); 
789 }
790 protected void consumeMethodHeaderExtendedDims() {
791         // MethodHeaderExtendedDims ::= Dimsopt
792         // now we update the returnType of the method
793         MethodDeclaration md = (MethodDeclaration) astStack[astPtr];
794         int extendedDims = intStack[intPtr--];
795         extendsDim = extendedDims;
796         if (extendedDims != 0) {
797                 TypeReference returnType = md.returnType;
798                 md.sourceEnd = endPosition;
799                 int dims = returnType.dimensions() + extendedDims;
800                 int baseType;
801                 if ((baseType = identifierLengthStack[identifierLengthPtr + 1]) < 0) {
802                         //it was a baseType
803                         int sourceStart = returnType.sourceStart;
804                         int sourceEnd = returnType.sourceEnd;
805                         returnType = TypeReference.baseTypeReference(-baseType, dims);
806                         returnType.sourceStart = sourceStart;
807                         returnType.sourceEnd = sourceEnd;
808                         md.returnType = returnType;
809                 } else {
810                         md.returnType = this.copyDims(md.returnType, dims);
811                 }
812                 if (currentToken == TokenNameLBRACE) {
813                         md.bodyStart = endPosition + 1;
814                 }
815         }
816 }
817 protected void consumeMethodHeaderName() {
818         // MethodHeaderName ::= Modifiersopt Type 'Identifier' '('
819         MethodDeclaration md = new MethodDeclaration(this.compilationUnit.compilationResult);
820
821         //name
822         md.selector = identifierStack[identifierPtr];
823         selectorSourcePositions = identifierPositionStack[identifierPtr--];
824         identifierLengthPtr--;
825         //type
826         md.returnType = getTypeReference(typeDims = intStack[intPtr--]);
827         //modifiers
828         md.declarationSourceStart = intStack[intPtr--];
829         md.modifiersSourceStart = intStack[intPtr--];
830         md.modifiers = intStack[intPtr--];
831
832         //highlight starts at selector start
833         md.sourceStart = (int) (selectorSourcePositions >>> 32);
834         pushOnAstStack(md);
835         md.bodyStart = scanner.currentPosition-1;
836 }
837 protected void consumeModifiers() {
838         checkAnnotation(); // might update modifiers with AccDeprecated
839         pushOnIntStack(modifiers); // modifiers
840         pushOnIntStack(modifiersSourceStart);
841         pushOnIntStack(
842                 declarationSourceStart >= 0 ? declarationSourceStart : modifiersSourceStart); 
843         resetModifiers();
844 }
845 /**
846  *
847  * INTERNAL USE-ONLY
848  */
849 protected void consumePackageDeclarationName() {
850         /* persisting javadoc positions */
851         pushOnIntArrayStack(this.getJavaDocPositions());
852
853         super.consumePackageDeclarationName();
854         ImportReference importReference = compilationUnit.currentPackage;
855
856         requestor.acceptPackage(
857                 importReference.declarationSourceStart, 
858                 importReference.declarationSourceEnd, 
859                 intArrayStack[intArrayPtr--], 
860                 CharOperation.concatWith(importReference.getImportName(), '.'),
861                 importReference.sourceStart);
862 }
863 protected void consumePushModifiers() {
864         checkAnnotation(); // might update modifiers with AccDeprecated
865         pushOnIntStack(modifiers); // modifiers
866         if (modifiersSourceStart < 0) {
867                 pushOnIntStack(-1);
868                 pushOnIntStack(
869                         declarationSourceStart >= 0 ? declarationSourceStart : scanner.startPosition); 
870         } else {
871                 pushOnIntStack(modifiersSourceStart);
872                 pushOnIntStack(
873                         declarationSourceStart >= 0 ? declarationSourceStart : modifiersSourceStart); 
874         }
875         resetModifiers();
876 }
877 /**
878  *
879  * INTERNAL USE-ONLY
880  */
881 protected void consumeSingleTypeImportDeclarationName() {
882         // SingleTypeImportDeclarationName ::= 'import' Name
883
884         /* persisting javadoc positions */
885         pushOnIntArrayStack(this.getJavaDocPositions());
886
887         super.consumeSingleTypeImportDeclarationName();
888         ImportReference importReference = (ImportReference) astStack[astPtr];
889         requestor.acceptImport(
890                 importReference.declarationSourceStart, 
891                 importReference.declarationSourceEnd,
892                 intArrayStack[intArrayPtr--],
893                 CharOperation.concatWith(importReference.getImportName(), '.'),
894                 importReference.sourceStart,
895                 false);
896 }
897 /**
898  *
899  * INTERNAL USE-ONLY
900  */
901 protected void consumeStaticInitializer() {
902         // StaticInitializer ::=  StaticOnly Block
903         //push an Initializer
904         //optimize the push/pop
905         super.consumeStaticInitializer();
906         Initializer initializer = (Initializer) astStack[astPtr];
907         requestor.acceptInitializer(
908                 initializer.declarationSourceStart,
909                 initializer.declarationSourceEnd,
910                 intArrayStack[intArrayPtr--],
911                 AccStatic, 
912                 intStack[intPtr--], 
913                 initializer.block.sourceStart,
914                 initializer.declarationSourceEnd);
915 }
916 protected void consumeStaticOnly() {
917         // StaticOnly ::= 'static'
918         checkAnnotation(); // might update declaration source start
919         pushOnIntStack(modifiersSourceStart);
920         pushOnIntStack(
921                 declarationSourceStart >= 0 ? declarationSourceStart : modifiersSourceStart); 
922         jumpOverMethodBody();
923         nestedMethod[nestedType]++;
924         resetModifiers();
925 }
926 /**
927  *
928  * INTERNAL USE-ONLY
929  */
930 protected void consumeTypeImportOnDemandDeclarationName() {
931         // TypeImportOnDemandDeclarationName ::= 'import' Name '.' '*'
932
933         /* persisting javadoc positions */
934         pushOnIntArrayStack(this.getJavaDocPositions());
935
936         super.consumeTypeImportOnDemandDeclarationName();
937         ImportReference importReference = (ImportReference) astStack[astPtr];
938         requestor.acceptImport(
939                 importReference.declarationSourceStart, 
940                 importReference.declarationSourceEnd,
941                 intArrayStack[intArrayPtr--],
942                 CharOperation.concatWith(importReference.getImportName(), '.'), 
943                 importReference.sourceStart,
944                 true);
945 }
946 public CompilationUnitDeclaration endParse(int act) {
947         if (scanner.recordLineSeparator) {
948                 requestor.acceptLineSeparatorPositions(scanner.getLineEnds());
949         }
950         return super.endParse(act);
951 }
952 /*
953  * Flush annotations defined prior to a given positions.
954  *
955  * Note: annotations are stacked in syntactical order
956  *
957  * Either answer given <position>, or the end position of a comment line 
958  * immediately following the <position> (same line)
959  *
960  * e.g.
961  * void foo(){
962  * } // end of method foo
963  */
964  
965 public int flushAnnotationsDefinedPriorTo(int position) {
966
967         return lastFieldEndPosition = super.flushAnnotationsDefinedPriorTo(position);
968 }
969 protected TypeReference getTypeReference(int dim) { /* build a Reference on a variable that may be qualified or not
970 This variable is a type reference and dim will be its dimensions*/
971
972         int length;
973         TypeReference ref;
974         if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
975                 // single variable reference
976                 if (dim == 0) {
977                         ref = 
978                                 new SingleTypeReference(
979                                         identifierStack[identifierPtr], 
980                                         identifierPositionStack[identifierPtr--]); 
981                 } else {
982                         ref = 
983                                 new ArrayTypeReference(
984                                         identifierStack[identifierPtr], 
985                                         dim, 
986                                         identifierPositionStack[identifierPtr--]); 
987                         ref.sourceEnd = endPosition;
988                 }
989         } else {
990                 if (length < 0) { //flag for precompiled type reference on base types
991                         ref = TypeReference.baseTypeReference(-length, dim);
992                         ref.sourceStart = intStack[intPtr--];
993                         if (dim == 0) {
994                                 ref.sourceEnd = intStack[intPtr--];
995                         } else {
996                                 intPtr--;
997                                 ref.sourceEnd = endPosition;
998                         }
999                 } else { //Qualified variable reference
1000                         char[][] tokens = new char[length][];
1001                         identifierPtr -= length;
1002                         long[] positions = new long[length];
1003                         System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
1004                         System.arraycopy(
1005                                 identifierPositionStack, 
1006                                 identifierPtr + 1, 
1007                                 positions, 
1008                                 0, 
1009                                 length); 
1010                         if (dim == 0) {
1011                                 ref = new QualifiedTypeReference(tokens, positions);
1012                         } else {
1013                                 ref = new ArrayQualifiedTypeReference(tokens, dim, positions);
1014                                 ref.sourceEnd = endPosition;
1015                         }
1016                 }
1017         };
1018         return ref;
1019 }
1020 public void initialize() {
1021         //positionning the parser for a new compilation unit
1022         //avoiding stack reallocation and all that....
1023         super.initialize();
1024         intArrayPtr = -1;
1025 }
1026 /**
1027  *
1028  * INTERNAL USE-ONLY
1029  */
1030 private boolean isLocalDeclaration() {
1031         int nestedDepth = nestedType;
1032         while (nestedDepth >= 0) {
1033                 if (nestedMethod[nestedDepth] != 0) {
1034                         return true;
1035                 }
1036                 nestedDepth--;
1037         }
1038         return false;
1039 }
1040 /*
1041  * Investigate one entire unit.
1042  */
1043 public void parseCompilationUnit(ICompilationUnit unit) {
1044         char[] regionSource = unit.getContents();
1045         try {
1046                 initialize();
1047                 goForCompilationUnit();
1048                 referenceContext =
1049                         compilationUnit = 
1050                                 compilationUnit = 
1051                                         new CompilationUnitDeclaration(
1052                                                 problemReporter(), 
1053                                                 new CompilationResult(unit, 0, 0, this.options.maxProblemsPerUnit), 
1054                                                 regionSource.length); 
1055                 scanner.resetTo(0, regionSource.length);
1056                 scanner.setSource(regionSource);
1057                 parse();
1058         } catch (AbortCompilation ex) {
1059         }
1060 }
1061 /*
1062  * Investigate one constructor declaration.
1063  */
1064 public void parseConstructor(char[] regionSource) {
1065         try {
1066                 initialize();
1067                 goForClassBodyDeclarations();
1068                 referenceContext = 
1069                         compilationUnit = 
1070                                 compilationUnit = 
1071                                         new CompilationUnitDeclaration(
1072                                                 problemReporter(), 
1073                                                 new CompilationResult(regionSource, 0, 0, this.options.maxProblemsPerUnit), 
1074                                                 regionSource.length); 
1075                 scanner.resetTo(0, regionSource.length);
1076                 scanner.setSource(regionSource);
1077                 parse();
1078         } catch (AbortCompilation ex) {
1079         }
1080 }
1081 /*
1082  * Investigate one field declaration statement (might have multiple declarations in it).
1083  */
1084 public void parseField(char[] regionSource) {
1085         try {
1086                 initialize();
1087                 goForFieldDeclaration();
1088                 referenceContext = 
1089                         compilationUnit = 
1090                                 compilationUnit = 
1091                                         new CompilationUnitDeclaration(
1092                                                 problemReporter(), 
1093                                                 new CompilationResult(regionSource, 0, 0, this.options.maxProblemsPerUnit), 
1094                                                 regionSource.length); 
1095                 scanner.resetTo(0, regionSource.length);
1096                 scanner.setSource(regionSource);
1097                 parse();
1098         } catch (AbortCompilation ex) {
1099         }
1100
1101 }
1102 /*
1103  * Investigate one import statement declaration.
1104  */
1105 public void parseImport(char[] regionSource) {
1106         try {
1107                 initialize();
1108                 goForImportDeclaration();
1109                 referenceContext = 
1110                         compilationUnit = 
1111                                 compilationUnit = 
1112                                         new CompilationUnitDeclaration(
1113                                                 problemReporter(), 
1114                                                 new CompilationResult(regionSource, 0, 0, this.options.maxProblemsPerUnit), 
1115                                                 regionSource.length); 
1116                 scanner.resetTo(0, regionSource.length);
1117                 scanner.setSource(regionSource);
1118                 parse();
1119         } catch (AbortCompilation ex) {
1120         }
1121
1122 }
1123 /*
1124  * Investigate one initializer declaration.
1125  * regionSource need to content exactly an initializer declaration.
1126  * e.g: static { i = 4; }
1127  * { name = "test"; }
1128  */
1129 public void parseInitializer(char[] regionSource) {
1130         try {
1131                 initialize();
1132                 goForInitializer();
1133                 referenceContext = 
1134                         compilationUnit = 
1135                                 compilationUnit = 
1136                                         new CompilationUnitDeclaration(
1137                                                 problemReporter(), 
1138                                                 new CompilationResult(regionSource, 0, 0, this.options.maxProblemsPerUnit), 
1139                                                 regionSource.length); 
1140                 scanner.resetTo(0, regionSource.length);
1141                 scanner.setSource(regionSource);
1142                 parse();
1143         } catch (AbortCompilation ex) {
1144         }
1145
1146 }
1147 /*
1148  * Investigate one method declaration.
1149  */
1150 public void parseMethod(char[] regionSource) {
1151         try {
1152                 initialize();
1153                 goForGenericMethodDeclaration();
1154                 referenceContext = 
1155                         compilationUnit = 
1156                                 compilationUnit = 
1157                                         new CompilationUnitDeclaration(
1158                                                 problemReporter(), 
1159                                                 new CompilationResult(regionSource, 0, 0, this.options.maxProblemsPerUnit), 
1160                                                 regionSource.length); 
1161                 scanner.resetTo(0, regionSource.length);
1162                 scanner.setSource(regionSource);
1163                 parse();
1164         } catch (AbortCompilation ex) {
1165         }
1166
1167 }
1168 /*
1169  * Investigate one package statement declaration.
1170  */
1171 public void parsePackage(char[] regionSource) {
1172         try {
1173                 initialize();
1174                 goForPackageDeclaration();
1175                 referenceContext = 
1176                         compilationUnit = 
1177                                 compilationUnit = 
1178                                         new CompilationUnitDeclaration(
1179                                                 problemReporter(), 
1180                                                 new CompilationResult(regionSource, 0, 0, this.options.maxProblemsPerUnit), 
1181                                                 regionSource.length); 
1182                 scanner.resetTo(0, regionSource.length);
1183                 scanner.setSource(regionSource);
1184                 parse();
1185         } catch (AbortCompilation ex) {
1186         }
1187
1188 }
1189 /*
1190  * Investigate one type declaration, its fields, methods and member types.
1191  */
1192 public void parseType(char[] regionSource) {
1193         try {
1194                 initialize();
1195                 goForTypeDeclaration();
1196                 referenceContext = 
1197                         compilationUnit = 
1198                                 compilationUnit = 
1199                                         new CompilationUnitDeclaration(
1200                                                 problemReporter(), 
1201                                                 new CompilationResult(regionSource, 0, 0, this.options.maxProblemsPerUnit), 
1202                                                 regionSource.length); 
1203                 scanner.resetTo(0, regionSource.length);
1204                 scanner.setSource(regionSource);
1205                 parse();
1206         } catch (AbortCompilation ex) {
1207         }
1208
1209 }
1210 /**
1211  * Returns this parser's problem reporter initialized with its reference context.
1212  * Also it is assumed that a problem is going to be reported, so initializes
1213  * the compilation result's line positions.
1214  */
1215 public ProblemReporter problemReporter() {
1216         problemReporter.referenceContext = referenceContext;
1217         return problemReporter;
1218 }
1219 protected void pushOnIntArrayStack(int[] positions) {
1220
1221         try {
1222                 intArrayStack[++intArrayPtr] = positions;
1223         } catch (IndexOutOfBoundsException e) {
1224                 //intPtr is correct 
1225                 int oldStackLength = intArrayStack.length;
1226                 int oldStack[][] = intArrayStack;
1227                 intArrayStack = new int[oldStackLength + StackIncrement][];
1228                 System.arraycopy(oldStack, 0, intArrayStack, 0, oldStackLength);
1229                 intArrayStack[intArrayPtr] = positions;
1230         }
1231 }
1232 protected void resetModifiers() {
1233         super.resetModifiers();
1234         declarationSourceStart = -1;
1235 }
1236 /*
1237  * Syntax error was detected. Will attempt to perform some recovery action in order
1238  * to resume to the regular parse loop.
1239  */
1240 protected boolean resumeOnSyntaxError() {
1241         return false;
1242 }
1243 /*
1244  * Answer a char array representation of the type name formatted like:
1245  * - type name + dimensions
1246  * Example:
1247  * "A[][]".toCharArray()
1248  * "java.lang.String".toCharArray()
1249  */
1250 private char[] returnTypeName(TypeReference type) {
1251         int dimension = type.dimensions();
1252         if (dimension != 0) {
1253                 char[] dimensionsArray = new char[dimension * 2];
1254                 for (int i = 0; i < dimension; i++) {
1255                         dimensionsArray[i*2] = '[';
1256                         dimensionsArray[(i*2) + 1] = ']';
1257                 }
1258                 return CharOperation.concat(
1259                         CharOperation.concatWith(type.getTypeName(), '.'), 
1260                         dimensionsArray); 
1261         }
1262         return CharOperation.concatWith(type.getTypeName(), '.');
1263 }
1264 public String toString() {
1265         StringBuffer buffer = new StringBuffer();
1266         buffer.append("intArrayPtr = " + intArrayPtr + "\n"); //$NON-NLS-1$ //$NON-NLS-2$
1267         buffer.append(super.toString());
1268         return buffer.toString();
1269 }
1270 /**
1271  * INTERNAL USE ONLY
1272  */
1273 protected TypeReference typeReference(
1274         int dim,
1275         int localIdentifierPtr, 
1276         int localIdentifierLengthPtr) {
1277         /* build a Reference on a variable that may be qualified or not
1278          * This variable is a type reference and dim will be its dimensions.
1279          * We don't have any side effect on the stacks' pointers.
1280          */
1281
1282         int length;
1283         TypeReference ref;
1284         if ((length = identifierLengthStack[localIdentifierLengthPtr]) == 1) {
1285                 // single variable reference
1286                 if (dim == 0) {
1287                         ref = 
1288                                 new SingleTypeReference(
1289                                         identifierStack[localIdentifierPtr], 
1290                                         identifierPositionStack[localIdentifierPtr--]); 
1291                 } else {
1292                         ref = 
1293                                 new ArrayTypeReference(
1294                                         identifierStack[localIdentifierPtr], 
1295                                         dim, 
1296                                         identifierPositionStack[localIdentifierPtr--]); 
1297                         ref.sourceEnd = endPosition;                            
1298                 }
1299         } else {
1300                 if (length < 0) { //flag for precompiled type reference on base types
1301                         ref = TypeReference.baseTypeReference(-length, dim);
1302                         ref.sourceStart = intStack[localIntPtr--];
1303                         if (dim == 0) {
1304                                 ref.sourceEnd = intStack[localIntPtr--];
1305                         } else {
1306                                 localIntPtr--;
1307                                 ref.sourceEnd = endPosition;
1308                         }
1309                 } else { //Qualified variable reference
1310                         char[][] tokens = new char[length][];
1311                         localIdentifierPtr -= length;
1312                         long[] positions = new long[length];
1313                         System.arraycopy(identifierStack, localIdentifierPtr + 1, tokens, 0, length);
1314                         System.arraycopy(
1315                                 identifierPositionStack, 
1316                                 localIdentifierPtr + 1, 
1317                                 positions, 
1318                                 0, 
1319                                 length); 
1320                         if (dim == 0)
1321                                 ref = new QualifiedTypeReference(tokens, positions);
1322                         else
1323                                 ref = new ArrayQualifiedTypeReference(tokens, dim, positions);
1324                 }
1325         };
1326         return ref;
1327 }
1328 }