KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > compiler > parser > RecoveredType


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.compiler.parser;
12
13 import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
14 import org.eclipse.jdt.internal.compiler.ast.ASTNode;
15 import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration;
16 import org.eclipse.jdt.internal.compiler.ast.Block;
17 import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
18 import org.eclipse.jdt.internal.compiler.ast.Initializer;
19 import org.eclipse.jdt.internal.compiler.ast.QualifiedAllocationExpression;
20 import org.eclipse.jdt.internal.compiler.ast.Statement;
21 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
22 import org.eclipse.jdt.internal.compiler.ast.TypeParameter;
23 import org.eclipse.jdt.internal.compiler.ast.TypeReference;
24 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
25
26 /**
27  * Internal type structure for parsing recovery
28  */

29
30 public class RecoveredType extends RecoveredStatement implements TerminalTokens {
31     public TypeDeclaration typeDeclaration;
32
33     public RecoveredType[] memberTypes;
34     public int memberTypeCount;
35     public RecoveredField[] fields;
36     public int fieldCount;
37     public RecoveredMethod[] methods;
38     public int methodCount;
39
40     public boolean preserveContent = false; // only used for anonymous types
41
public int bodyEnd;
42     
43     public boolean insideEnumConstantPart = false;
44     
45     public TypeParameter[] pendingTypeParameters;
46     public int pendingTypeParametersStart;
47     
48 public RecoveredType(TypeDeclaration typeDeclaration, RecoveredElement parent, int bracketBalance){
49     super(typeDeclaration, parent, bracketBalance);
50     this.typeDeclaration = typeDeclaration;
51     if(typeDeclaration.allocation != null && typeDeclaration.allocation.type == null) {
52         // an enum constant body can not exist if there is no opening brace
53
this.foundOpeningBrace = true;
54     } else {
55         this.foundOpeningBrace = !bodyStartsAtHeaderEnd();
56     }
57     this.insideEnumConstantPart = TypeDeclaration.kind(typeDeclaration.modifiers) == TypeDeclaration.ENUM_DECL;
58     if(this.foundOpeningBrace) {
59         this.bracketBalance++;
60     }
61     
62     this.preserveContent = this.parser().methodRecoveryActivated || this.parser().statementRecoveryActivated;
63 }
64 public RecoveredElement add(AbstractMethodDeclaration methodDeclaration, int bracketBalanceValue) {
65
66     /* do not consider a method starting passed the type end (if set)
67         it must be belonging to an enclosing type */

68     if (typeDeclaration.declarationSourceEnd != 0
69         && methodDeclaration.declarationSourceStart > typeDeclaration.declarationSourceEnd){
70         this.pendingTypeParameters = null;
71         return this.parent.add(methodDeclaration, bracketBalanceValue);
72     }
73
74     if (methods == null) {
75         methods = new RecoveredMethod[5];
76         methodCount = 0;
77     } else {
78         if (methodCount == methods.length) {
79             System.arraycopy(
80                 methods,
81                 0,
82                 (methods = new RecoveredMethod[2 * methodCount]),
83                 0,
84                 methodCount);
85         }
86     }
87     RecoveredMethod element = new RecoveredMethod(methodDeclaration, this, bracketBalanceValue, this.recoveringParser);
88     methods[methodCount++] = element;
89     
90     if(this.pendingTypeParameters != null) {
91         element.attach(this.pendingTypeParameters, this.pendingTypeParametersStart);
92         this.pendingTypeParameters = null;
93     }
94     
95     this.insideEnumConstantPart = false;
96
97     /* consider that if the opening brace was not found, it is there */
98     if (!foundOpeningBrace){
99         foundOpeningBrace = true;
100         this.bracketBalance++;
101     }
102     /* if method not finished, then method becomes current */
103     if (methodDeclaration.declarationSourceEnd == 0) return element;
104     return this;
105 }
106 public RecoveredElement add(Block nestedBlockDeclaration,int bracketBalanceValue) {
107     this.pendingTypeParameters = null;
108     
109     int modifiers = ClassFileConstants.AccDefault;
110     if(this.parser().recoveredStaticInitializerStart != 0) {
111         modifiers = ClassFileConstants.AccStatic;
112     }
113     return this.add(new Initializer(nestedBlockDeclaration, modifiers), bracketBalanceValue);
114 }
115 public RecoveredElement add(FieldDeclaration fieldDeclaration, int bracketBalanceValue) {
116     this.pendingTypeParameters = null;
117     
118     /* do not consider a field starting passed the type end (if set)
119     it must be belonging to an enclosing type */

120     if (typeDeclaration.declarationSourceEnd != 0
121         && fieldDeclaration.declarationSourceStart > typeDeclaration.declarationSourceEnd) {
122         return this.parent.add(fieldDeclaration, bracketBalanceValue);
123     }
124     if (fields == null) {
125         fields = new RecoveredField[5];
126         fieldCount = 0;
127     } else {
128         if (fieldCount == fields.length) {
129             System.arraycopy(
130                 fields,
131                 0,
132                 (fields = new RecoveredField[2 * fieldCount]),
133                 0,
134                 fieldCount);
135         }
136     }
137     RecoveredField element;
138     switch (fieldDeclaration.getKind()) {
139         case AbstractVariableDeclaration.FIELD:
140         case AbstractVariableDeclaration.ENUM_CONSTANT:
141             element = new RecoveredField(fieldDeclaration, this, bracketBalanceValue);
142             break;
143         case AbstractVariableDeclaration.INITIALIZER:
144             element = new RecoveredInitializer(fieldDeclaration, this, bracketBalanceValue);
145             break;
146         default:
147             // never happens, as field is always identified
148
return this;
149     }
150     fields[fieldCount++] = element;
151
152     /* consider that if the opening brace was not found, it is there */
153     if (!foundOpeningBrace){
154         foundOpeningBrace = true;
155         this.bracketBalance++;
156     }
157     /* if field not finished, then field becomes current */
158     if (fieldDeclaration.declarationSourceEnd == 0) return element;
159     return this;
160 }
161 public RecoveredElement add(TypeDeclaration memberTypeDeclaration, int bracketBalanceValue) {
162     this.pendingTypeParameters = null;
163     
164     /* do not consider a type starting passed the type end (if set)
165         it must be belonging to an enclosing type */

166     if (typeDeclaration.declarationSourceEnd != 0
167         && memberTypeDeclaration.declarationSourceStart > typeDeclaration.declarationSourceEnd){
168         return this.parent.add(memberTypeDeclaration, bracketBalanceValue);
169     }
170     
171     this.insideEnumConstantPart = false;
172     
173     if ((memberTypeDeclaration.bits & ASTNode.IsAnonymousType) != 0){
174         if (this.methodCount > 0) {
175             // add it to the last method body
176
RecoveredMethod lastMethod = this.methods[this.methodCount-1];
177             lastMethod.methodDeclaration.bodyEnd = 0; // reopen method
178
lastMethod.methodDeclaration.declarationSourceEnd = 0; // reopen method
179
lastMethod.bracketBalance++; // expect one closing brace
180
return lastMethod.add(memberTypeDeclaration, bracketBalanceValue);
181         } else {
182             // ignore
183
return this;
184         }
185     }
186         
187     if (memberTypes == null) {
188         memberTypes = new RecoveredType[5];
189         memberTypeCount = 0;
190     } else {
191         if (memberTypeCount == memberTypes.length) {
192             System.arraycopy(
193                 memberTypes,
194                 0,
195                 (memberTypes = new RecoveredType[2 * memberTypeCount]),
196                 0,
197                 memberTypeCount);
198         }
199     }
200     RecoveredType element = new RecoveredType(memberTypeDeclaration, this, bracketBalanceValue);
201     memberTypes[memberTypeCount++] = element;
202
203     /* consider that if the opening brace was not found, it is there */
204     if (!foundOpeningBrace){
205         foundOpeningBrace = true;
206         this.bracketBalance++;
207     }
208     /* if member type not finished, then member type becomes current */
209     if (memberTypeDeclaration.declarationSourceEnd == 0) return element;
210     return this;
211 }
212 public void add(TypeParameter[] parameters, int startPos) {
213     this.pendingTypeParameters = parameters;
214     this.pendingTypeParametersStart = startPos;
215 }
216 /*
217  * Answer the body end of the corresponding parse node
218  */

219 public int bodyEnd(){
220     if (bodyEnd == 0) return typeDeclaration.declarationSourceEnd;
221     return bodyEnd;
222 }
223 public boolean bodyStartsAtHeaderEnd(){
224     if (typeDeclaration.superInterfaces == null){
225         if (typeDeclaration.superclass == null){
226             if(typeDeclaration.typeParameters == null) {
227                 return typeDeclaration.bodyStart == typeDeclaration.sourceEnd+1;
228             } else {
229                 return typeDeclaration.bodyStart == typeDeclaration.typeParameters[typeDeclaration.typeParameters.length-1].sourceEnd+1;
230             }
231         } else {
232             return typeDeclaration.bodyStart == typeDeclaration.superclass.sourceEnd+1;
233         }
234     } else {
235         return typeDeclaration.bodyStart
236                 == typeDeclaration.superInterfaces[typeDeclaration.superInterfaces.length-1].sourceEnd+1;
237     }
238 }
239 /*
240  * Answer the enclosing type node, or null if none
241  */

242 public RecoveredType enclosingType(){
243     RecoveredElement current = parent;
244     while (current != null){
245         if (current instanceof RecoveredType){
246             return (RecoveredType) current;
247         }
248         current = current.parent;
249     }
250     return null;
251 }
252 public char[] name(){
253     return typeDeclaration.name;
254 }
255 /*
256  * Answer the associated parsed structure
257  */

258 public ASTNode parseTree(){
259     return typeDeclaration;
260 }
261 /*
262  * Answer the very source end of the corresponding parse node
263  */

264 public int sourceEnd(){
265     return this.typeDeclaration.declarationSourceEnd;
266 }
267 public String JavaDoc toString(int tab) {
268     StringBuffer JavaDoc result = new StringBuffer JavaDoc(tabString(tab));
269     result.append("Recovered type:\n"); //$NON-NLS-1$
270
if ((typeDeclaration.bits & ASTNode.IsAnonymousType) != 0) {
271         result.append(tabString(tab));
272         result.append(" "); //$NON-NLS-1$
273
}
274     typeDeclaration.print(tab + 1, result);
275     if (this.memberTypes != null) {
276         for (int i = 0; i < this.memberTypeCount; i++) {
277             result.append("\n"); //$NON-NLS-1$
278
result.append(this.memberTypes[i].toString(tab + 1));
279         }
280     }
281     if (this.fields != null) {
282         for (int i = 0; i < this.fieldCount; i++) {
283             result.append("\n"); //$NON-NLS-1$
284
result.append(this.fields[i].toString(tab + 1));
285         }
286     }
287     if (this.methods != null) {
288         for (int i = 0; i < this.methodCount; i++) {
289             result.append("\n"); //$NON-NLS-1$
290
result.append(this.methods[i].toString(tab + 1));
291         }
292     }
293     return result.toString();
294 }
295 /*
296  * Update the bodyStart of the corresponding parse node
297  */

298 public void updateBodyStart(int bodyStart){
299     this.foundOpeningBrace = true;
300     this.typeDeclaration.bodyStart = bodyStart;
301 }
302 public Statement updatedStatement(){
303
304     // ignore closed anonymous type
305
if ((typeDeclaration.bits & ASTNode.IsAnonymousType) != 0 && !this.preserveContent){
306         return null;
307     }
308         
309     TypeDeclaration updatedType = this.updatedTypeDeclaration();
310     if ((updatedType.bits & ASTNode.IsAnonymousType) != 0){
311         /* in presence of an anonymous type, we want the full allocation expression */
312         QualifiedAllocationExpression allocation = updatedType.allocation;
313         
314         if (allocation.statementEnd == -1) {
315             allocation.statementEnd = updatedType.declarationSourceEnd;
316         }
317         return allocation;
318     }
319     return updatedType;
320 }
321 public TypeDeclaration updatedTypeDeclaration(){
322     int lastEnd = typeDeclaration.bodyStart;
323     /* update member types */
324     if (memberTypeCount > 0){
325         int existingCount = typeDeclaration.memberTypes == null ? 0 : typeDeclaration.memberTypes.length;
326         TypeDeclaration[] memberTypeDeclarations = new TypeDeclaration[existingCount + memberTypeCount];
327         if (existingCount > 0){
328             System.arraycopy(typeDeclaration.memberTypes, 0, memberTypeDeclarations, 0, existingCount);
329         }
330         // may need to update the declarationSourceEnd of the last type
331
if (memberTypes[memberTypeCount - 1].typeDeclaration.declarationSourceEnd == 0){
332             int bodyEndValue = bodyEnd();
333             memberTypes[memberTypeCount - 1].typeDeclaration.declarationSourceEnd = bodyEndValue;
334             memberTypes[memberTypeCount - 1].typeDeclaration.bodyEnd = bodyEndValue;
335         }
336         for (int i = 0; i < memberTypeCount; i++){
337             memberTypeDeclarations[existingCount + i] = memberTypes[i].updatedTypeDeclaration();
338         }
339         typeDeclaration.memberTypes = memberTypeDeclarations;
340         if(memberTypeDeclarations[memberTypeDeclarations.length - 1].declarationSourceEnd > lastEnd) {
341             lastEnd = memberTypeDeclarations[memberTypeDeclarations.length - 1].declarationSourceEnd;
342         }
343     }
344     /* update fields */
345     if (fieldCount > 0){
346         int existingCount = typeDeclaration.fields == null ? 0 : typeDeclaration.fields.length;
347         FieldDeclaration[] fieldDeclarations = new FieldDeclaration[existingCount + fieldCount];
348         if (existingCount > 0){
349             System.arraycopy(typeDeclaration.fields, 0, fieldDeclarations, 0, existingCount);
350         }
351         // may need to update the declarationSourceEnd of the last field
352
if (fields[fieldCount - 1].fieldDeclaration.declarationSourceEnd == 0){
353             int temp = bodyEnd();
354             fields[fieldCount - 1].fieldDeclaration.declarationSourceEnd = temp;
355             fields[fieldCount - 1].fieldDeclaration.declarationEnd = temp;
356         }
357         for (int i = 0; i < fieldCount; i++){
358             fieldDeclarations[existingCount + i] = fields[i].updatedFieldDeclaration();
359         }
360         typeDeclaration.fields = fieldDeclarations;
361         if(fieldDeclarations[fieldDeclarations.length - 1].declarationSourceEnd > lastEnd) {
362             lastEnd = fieldDeclarations[fieldDeclarations.length - 1].declarationSourceEnd;
363         }
364     }
365     /* update methods */
366     int existingCount = typeDeclaration.methods == null ? 0 : typeDeclaration.methods.length;
367     boolean hasConstructor = false, hasRecoveredConstructor = false;
368     boolean hasAbstractMethods = false;
369     int defaultConstructorIndex = -1;
370     if (methodCount > 0){
371         AbstractMethodDeclaration[] methodDeclarations = new AbstractMethodDeclaration[existingCount + methodCount];
372         for (int i = 0; i < existingCount; i++){
373             AbstractMethodDeclaration m = typeDeclaration.methods[i];
374             if (m.isDefaultConstructor()) defaultConstructorIndex = i;
375             if (m.isAbstract()) hasAbstractMethods = true;
376             methodDeclarations[i] = m;
377         }
378         // may need to update the declarationSourceEnd of the last method
379
if (methods[methodCount - 1].methodDeclaration.declarationSourceEnd == 0){
380             int bodyEndValue = bodyEnd();
381             methods[methodCount - 1].methodDeclaration.declarationSourceEnd = bodyEndValue;
382             methods[methodCount - 1].methodDeclaration.bodyEnd = bodyEndValue;
383         }
384         for (int i = 0; i < methodCount; i++){
385             AbstractMethodDeclaration updatedMethod = methods[i].updatedMethodDeclaration();
386             if (updatedMethod.isConstructor()) hasRecoveredConstructor = true;
387             if (updatedMethod.isAbstract()) hasAbstractMethods = true;
388             methodDeclarations[existingCount + i] = updatedMethod;
389         }
390         typeDeclaration.methods = methodDeclarations;
391         if(methodDeclarations[methodDeclarations.length - 1].declarationSourceEnd > lastEnd) {
392             lastEnd = methodDeclarations[methodDeclarations.length - 1].declarationSourceEnd;
393         }
394         if (hasAbstractMethods) typeDeclaration.bits |= ASTNode.HasAbstractMethods;
395         hasConstructor = typeDeclaration.checkConstructors(this.parser());
396     } else {
397         for (int i = 0; i < existingCount; i++){
398             if (typeDeclaration.methods[i].isConstructor()) hasConstructor = true;
399         }
400     }
401     /* add clinit ? */
402     if (typeDeclaration.needClassInitMethod()){
403         boolean alreadyHasClinit = false;
404         for (int i = 0; i < existingCount; i++){
405             if (typeDeclaration.methods[i].isClinit()){
406                 alreadyHasClinit = true;
407                 break;
408             }
409         }
410         if (!alreadyHasClinit) typeDeclaration.addClinit();
411     }
412     /* add default constructor ? */
413     if (defaultConstructorIndex >= 0 && hasRecoveredConstructor){
414         /* should discard previous default construtor */
415         AbstractMethodDeclaration[] methodDeclarations = new AbstractMethodDeclaration[typeDeclaration.methods.length - 1];
416         if (defaultConstructorIndex != 0){
417             System.arraycopy(typeDeclaration.methods, 0, methodDeclarations, 0, defaultConstructorIndex);
418         }
419         if (defaultConstructorIndex != typeDeclaration.methods.length-1){
420             System.arraycopy(
421                 typeDeclaration.methods,
422                 defaultConstructorIndex+1,
423                 methodDeclarations,
424                 defaultConstructorIndex,
425                 typeDeclaration.methods.length - defaultConstructorIndex - 1);
426         }
427         typeDeclaration.methods = methodDeclarations;
428     } else {
429         int kind = TypeDeclaration.kind(typeDeclaration.modifiers);
430         if (!hasConstructor &&
431                 kind != TypeDeclaration.INTERFACE_DECL &&
432                 kind != TypeDeclaration.ANNOTATION_TYPE_DECL &&
433                 typeDeclaration.allocation == null) {// if was already reduced, then constructor
434
boolean insideFieldInitializer = false;
435             RecoveredElement parentElement = this.parent;
436             while (parentElement != null){
437                 if (parentElement instanceof RecoveredField){
438                         insideFieldInitializer = true;
439                         break;
440                 }
441                 parentElement = parentElement.parent;
442             }
443             typeDeclaration.createDefaultConstructor(!parser().diet || insideFieldInitializer, true);
444         }
445     }
446     if (parent instanceof RecoveredType){
447         typeDeclaration.bits |= ASTNode.IsMemberType;
448     } else if (parent instanceof RecoveredMethod){
449         typeDeclaration.bits |= ASTNode.IsLocalType;
450     }
451     if(typeDeclaration.declarationSourceEnd == 0) {
452         typeDeclaration.declarationSourceEnd = lastEnd;
453         typeDeclaration.bodyEnd = lastEnd;
454     }
455     return typeDeclaration;
456 }
457 /*
458  * Update the corresponding parse node from parser state which
459  * is about to disappear because of restarting recovery
460  */

461 public void updateFromParserState(){
462
463     // anymous type and enum constant doesn't need to be updated
464
if(this.bodyStartsAtHeaderEnd() && typeDeclaration.allocation == null){
465         Parser parser = this.parser();
466         /* might want to recover implemented interfaces */
467         // protection for bugs 15142
468
if (parser.listLength > 0 && parser.astLengthPtr > 0){ // awaiting interface type references
469
int length = parser.astLengthStack[parser.astLengthPtr];
470             int astPtr = parser.astPtr - length;
471             boolean canConsume = astPtr >= 0;
472             if(canConsume) {
473                 if((!(parser.astStack[astPtr] instanceof TypeDeclaration))) {
474                     canConsume = false;
475                 }
476                 for (int i = 1, max = length + 1; i < max; i++) {
477                     if(!(parser.astStack[astPtr + i ] instanceof TypeReference)) {
478                         canConsume = false;
479                     }
480                 }
481             }
482             if(canConsume) {
483                 parser.consumeClassHeaderImplements();
484                 // will reset typeListLength to zero
485
// thus this check will only be performed on first errorCheck after class X implements Y,Z,
486
}
487         } else if (parser.listTypeParameterLength > 0) {
488             int length = parser.listTypeParameterLength;
489             int genericsPtr = parser.genericsPtr;
490             boolean canConsume = genericsPtr + 1 >= length && parser.astPtr > -1;
491             if(canConsume) {
492                 if (!(parser.astStack[parser.astPtr] instanceof TypeDeclaration)) {
493                     canConsume = false;
494                 }
495                 while(genericsPtr + 1 > length && !(parser.genericsStack[genericsPtr] instanceof TypeParameter)) {
496                     genericsPtr--;
497                 }
498                 for (int i = 0; i < length; i++) {
499                     if(!(parser.genericsStack[genericsPtr - i] instanceof TypeParameter)) {
500                         canConsume = false;
501                     }
502                 }
503             }
504             if(canConsume) {
505                 TypeDeclaration typeDecl = (TypeDeclaration)parser.astStack[parser.astPtr];
506                 System.arraycopy(parser.genericsStack, genericsPtr - length + 1, typeDecl.typeParameters = new TypeParameter[length], 0, length);
507                 typeDecl.bodyStart = typeDecl.typeParameters[length-1].declarationSourceEnd + 1;
508                 parser.listTypeParameterLength = 0;
509                 parser.lastCheckPoint = typeDecl.bodyStart;
510             }
511         }
512     }
513 }
514 /*
515  * A closing brace got consumed, might have closed the current element,
516  * in which case both the currentElement is exited
517  */

518 public RecoveredElement updateOnClosingBrace(int braceStart, int braceEnd){
519     if ((--bracketBalance <= 0) && (parent != null)){
520         this.updateSourceEndIfNecessary(braceStart, braceEnd);
521         this.bodyEnd = braceStart - 1;
522         return parent;
523     }
524     return this;
525 }
526 /*
527  * An opening brace got consumed, might be the expected opening one of the current element,
528  * in which case the bodyStart is updated.
529  */

530 public RecoveredElement updateOnOpeningBrace(int braceStart, int braceEnd){
531     /* in case the opening brace is not close enough to the signature, ignore it */
532     if (bracketBalance == 0){
533         /*
534             if (parser.scanner.searchLineNumber(typeDeclaration.sourceEnd)
535                 != parser.scanner.searchLineNumber(braceEnd)){
536          */

537         Parser parser = this.parser();
538         switch(parser.lastIgnoredToken){
539             case -1 :
540             case TokenNameextends :
541             case TokenNameimplements :
542             case TokenNameGREATER :
543             case TokenNameRIGHT_SHIFT :
544             case TokenNameUNSIGNED_RIGHT_SHIFT :
545                 if (parser.recoveredStaticInitializerStart == 0) break;
546             default:
547                 this.foundOpeningBrace = true;
548                 bracketBalance = 1; // pretend the brace was already there
549
}
550     }
551     // might be an initializer
552
if (this.bracketBalance == 1){
553         Block block = new Block(0);
554         Parser parser = this.parser();
555         block.sourceStart = parser.scanner.startPosition;
556         Initializer init;
557         if (parser.recoveredStaticInitializerStart == 0){
558             init = new Initializer(block, ClassFileConstants.AccDefault);
559         } else {
560             init = new Initializer(block, ClassFileConstants.AccStatic);
561             init.declarationSourceStart = parser.recoveredStaticInitializerStart;
562         }
563         init.bodyStart = parser.scanner.currentPosition;
564         return this.add(init, 1);
565     }
566     return super.updateOnOpeningBrace(braceStart, braceEnd);
567 }
568 public void updateParseTree(){
569     this.updatedTypeDeclaration();
570 }
571 /*
572  * Update the declarationSourceEnd of the corresponding parse node
573  */

574 public void updateSourceEndIfNecessary(int start, int end){
575     if (this.typeDeclaration.declarationSourceEnd == 0){
576         this.bodyEnd = 0;
577         this.typeDeclaration.declarationSourceEnd = end;
578         this.typeDeclaration.bodyEnd = end;
579     }
580 }
581 }
582
Popular Tags