KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > compiler > lookup > LocalTypeBinding


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.lookup;
12
13 import org.eclipse.jdt.core.compiler.CharOperation;
14 import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
15 import org.eclipse.jdt.internal.compiler.ast.CaseStatement;
16
17 public final class LocalTypeBinding extends NestedTypeBinding {
18     final static char[] LocalTypePrefix = { '$', 'L', 'o', 'c', 'a', 'l', '$' };
19
20     private InnerEmulationDependency[] dependents;
21     public ArrayBinding[] localArrayBindings; // used to cache array bindings of various dimensions for this local type
22
public CaseStatement enclosingCase; // from 1.4 on, local types should not be accessed across switch case blocks (52221)
23
public int sourceStart; // used by computeUniqueKey to uniquely identify this binding
24
public MethodBinding enclosingMethod;
25     
26 public LocalTypeBinding(ClassScope scope, SourceTypeBinding enclosingType, CaseStatement switchCase) {
27     super(
28         new char[][] {CharOperation.concat(LocalTypePrefix, scope.referenceContext.name)},
29         scope,
30         enclosingType);
31     
32     if (this.sourceName == CharOperation.NO_CHAR)
33         this.tagBits |= TagBits.AnonymousTypeMask;
34     else
35         this.tagBits |= TagBits.LocalTypeMask;
36     this.enclosingCase = switchCase;
37     this.sourceStart = scope.referenceContext.sourceStart;
38     MethodScope methodScope = scope.enclosingMethodScope();
39     AbstractMethodDeclaration declaration = methodScope.referenceMethod();
40     if (declaration != null) {
41         this.enclosingMethod = declaration.binding;
42     }
43 }
44 /* Record a dependency onto a source target type which may be altered
45 * by the end of the innerclass emulation. Later on, we will revisit
46 * all its dependents so as to update them (see updateInnerEmulationDependents()).
47 */

48
49 public void addInnerEmulationDependent(BlockScope dependentScope, boolean wasEnclosingInstanceSupplied) {
50     int index;
51     if (dependents == null) {
52         index = 0;
53         dependents = new InnerEmulationDependency[1];
54     } else {
55         index = dependents.length;
56         for (int i = 0; i < index; i++)
57             if (dependents[i].scope == dependentScope)
58                 return; // already stored
59
System.arraycopy(dependents, 0, (dependents = new InnerEmulationDependency[index + 1]), 0, index);
60     }
61     dependents[index] = new InnerEmulationDependency(dependentScope, wasEnclosingInstanceSupplied);
62     // System.out.println("Adding dependency: "+ new String(scope.enclosingType().readableName()) + " --> " + new String(this.readableName()));
63
}
64 public char[] computeUniqueKey(boolean isLeaf) {
65     char[] outerKey = outermostEnclosingType().computeUniqueKey(isLeaf);
66     int semicolon = CharOperation.lastIndexOf(';', outerKey);
67
68     StringBuffer JavaDoc sig = new StringBuffer JavaDoc();
69     sig.append(outerKey, 0, semicolon);
70
71     // insert $sourceStart
72
sig.append('$');
73     sig.append(String.valueOf(this.sourceStart));
74     
75     // insert $LocalName if local
76
if (!isAnonymousType()) {
77         sig.append('$');
78         sig.append(this.sourceName);
79     }
80     
81     // insert remaining from outer key
82
sig.append(outerKey, semicolon, outerKey.length-semicolon);
83     
84     int sigLength = sig.length();
85     char[] uniqueKey = new char[sigLength];
86     sig.getChars(0, sigLength, uniqueKey, 0);
87     return uniqueKey;
88 }
89
90 public char[] constantPoolName() /* java/lang/Object */ {
91     return constantPoolName;
92 }
93
94 ArrayBinding createArrayType(int dimensionCount, LookupEnvironment lookupEnvironment) {
95     if (localArrayBindings == null) {
96         localArrayBindings = new ArrayBinding[] {new ArrayBinding(this, dimensionCount, lookupEnvironment)};
97         return localArrayBindings[0];
98     }
99
100     // find the cached array binding for this dimensionCount (if any)
101
int length = localArrayBindings.length;
102     for (int i = 0; i < length; i++)
103         if (localArrayBindings[i].dimensions == dimensionCount)
104             return localArrayBindings[i];
105
106     // no matching array
107
System.arraycopy(localArrayBindings, 0, localArrayBindings = new ArrayBinding[length + 1], 0, length);
108     return localArrayBindings[length] = new ArrayBinding(this, dimensionCount, lookupEnvironment);
109 }
110
111 /*
112  * Overriden for code assist. In this case, the constantPoolName() has not been computed yet.
113  * Slam the source name so that the signature is syntactically correct.
114  * (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=99686)
115  */

116 public char[] genericTypeSignature() {
117     if (this.genericReferenceTypeSignature == null && constantPoolName() == null) {
118         if (isAnonymousType())
119             setConstantPoolName(superclass().sourceName());
120         else
121             setConstantPoolName(sourceName());
122     }
123     return super.genericTypeSignature();
124 }
125
126 public char[] readableName() /*java.lang.Object, p.X<T> */ {
127     char[] readableName;
128     if (isAnonymousType()) {
129         if (superInterfaces == Binding.NO_SUPERINTERFACES)
130             readableName = CharOperation.concat(TypeConstants.ANONYM_PREFIX, superclass.readableName(), TypeConstants.ANONYM_SUFFIX);
131         else
132             readableName = CharOperation.concat(TypeConstants.ANONYM_PREFIX, superInterfaces[0].readableName(), TypeConstants.ANONYM_SUFFIX);
133     } else if (isMemberType()) {
134         readableName = CharOperation.concat(enclosingType().readableName(), this.sourceName, '.');
135     } else {
136         readableName = this.sourceName;
137     }
138     TypeVariableBinding[] typeVars;
139     if ((typeVars = this.typeVariables()) != Binding.NO_TYPE_VARIABLES) {
140         StringBuffer JavaDoc nameBuffer = new StringBuffer JavaDoc(10);
141         nameBuffer.append(readableName).append('<');
142         for (int i = 0, length = typeVars.length; i < length; i++) {
143             if (i > 0) nameBuffer.append(',');
144             nameBuffer.append(typeVars[i].readableName());
145         }
146         nameBuffer.append('>');
147         int nameLength = nameBuffer.length();
148         readableName = new char[nameLength];
149         nameBuffer.getChars(0, nameLength, readableName, 0);
150     }
151     return readableName;
152 }
153
154 public char[] shortReadableName() /*Object*/ {
155     char[] shortReadableName;
156     if (isAnonymousType()) {
157         if (superInterfaces == Binding.NO_SUPERINTERFACES)
158             shortReadableName = CharOperation.concat(TypeConstants.ANONYM_PREFIX, superclass.shortReadableName(), TypeConstants.ANONYM_SUFFIX);
159         else
160             shortReadableName = CharOperation.concat(TypeConstants.ANONYM_PREFIX, superInterfaces[0].shortReadableName(), TypeConstants.ANONYM_SUFFIX);
161     } else if (isMemberType()) {
162         shortReadableName = CharOperation.concat(enclosingType().shortReadableName(), sourceName, '.');
163     } else {
164         shortReadableName = sourceName;
165     }
166     TypeVariableBinding[] typeVars;
167     if ((typeVars = this.typeVariables()) != Binding.NO_TYPE_VARIABLES) {
168         StringBuffer JavaDoc nameBuffer = new StringBuffer JavaDoc(10);
169         nameBuffer.append(shortReadableName).append('<');
170         for (int i = 0, length = typeVars.length; i < length; i++) {
171             if (i > 0) nameBuffer.append(',');
172             nameBuffer.append(typeVars[i].shortReadableName());
173         }
174         nameBuffer.append('>');
175         int nameLength = nameBuffer.length();
176         shortReadableName = new char[nameLength];
177         nameBuffer.getChars(0, nameLength, shortReadableName, 0);
178     }
179     return shortReadableName;
180 }
181
182 // Record that the type is a local member type
183
public void setAsMemberType() {
184     this.tagBits |= TagBits.MemberTypeMask;
185 }
186
187 public void setConstantPoolName(char[] computedConstantPoolName) /* java/lang/Object */ {
188     this.constantPoolName = computedConstantPoolName;
189 }
190 /*
191  * Overriden for code assist. In this case, the constantPoolName() has not been computed yet.
192  * Slam the source name so that the signature is syntactically correct.
193  * (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=102284)
194  */

195 public char[] signature() {
196     if (this.signature == null && constantPoolName() == null) {
197         if (isAnonymousType())
198             setConstantPoolName(superclass().sourceName());
199         else
200             setConstantPoolName(sourceName());
201     }
202     return super.signature();
203 }
204 public char[] sourceName() {
205     if (isAnonymousType()) {
206         if (superInterfaces == Binding.NO_SUPERINTERFACES)
207             return CharOperation.concat(TypeConstants.ANONYM_PREFIX, superclass.sourceName(), TypeConstants.ANONYM_SUFFIX);
208         else
209             return CharOperation.concat(TypeConstants.ANONYM_PREFIX, superInterfaces[0].sourceName(), TypeConstants.ANONYM_SUFFIX);
210             
211     } else
212         return sourceName;
213 }
214 public String JavaDoc toString() {
215     if (isAnonymousType())
216         return "Anonymous type : " + super.toString(); //$NON-NLS-1$
217
if (isMemberType())
218         return "Local member type : " + new String JavaDoc(sourceName()) + " " + super.toString(); //$NON-NLS-2$ //$NON-NLS-1$
219
return "Local type : " + new String JavaDoc(sourceName()) + " " + super.toString(); //$NON-NLS-2$ //$NON-NLS-1$
220
}
221 /* Trigger the dependency mechanism forcing the innerclass emulation
222 * to be propagated to all dependent source types.
223 */

224
225 public void updateInnerEmulationDependents() {
226     if (dependents != null) {
227         for (int i = 0; i < dependents.length; i++) {
228             InnerEmulationDependency dependency = dependents[i];
229             // System.out.println("Updating " + new String(this.readableName()) + " --> " + new String(dependency.scope.enclosingType().readableName()));
230
dependency.scope.propagateInnerEmulation(this, dependency.wasEnclosingInstanceSupplied);
231         }
232     }
233 }
234 }
235
Popular Tags