1 /*******************************************************************************
2 * Copyright (c) 2000, 2003 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v10.html
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package net.sourceforge.phpdt.internal.compiler.lookup;
13 public class NestedTypeBinding extends SourceTypeBinding {
15 public SourceTypeBinding enclosingType;
17 public SyntheticArgumentBinding[] enclosingInstances;
19 public SyntheticArgumentBinding[] outerLocalVariables;
21 public int enclosingInstancesSlotSize; // amount of slots used by synthetic
22 // enclosing instances
24 public int outerLocalVariablesSlotSize; // amount of slots used by synthetic
25 // outer local variables
27 public NestedTypeBinding(char[][] typeName, ClassScope scope,
28 SourceTypeBinding enclosingType) {
29 super(typeName, enclosingType.fPackage, scope);
30 this.tagBits |= IsNestedType;
31 this.enclosingType = enclosingType;
35 * Add a new synthetic argument for <actualOuterLocalVariable>. Answer the
36 * new argument or the existing argument if one already existed.
38 public SyntheticArgumentBinding addSyntheticArgument(
39 LocalVariableBinding actualOuterLocalVariable) {
40 SyntheticArgumentBinding synthLocal = null;
42 if (outerLocalVariables == null) {
43 synthLocal = new SyntheticArgumentBinding(actualOuterLocalVariable);
44 outerLocalVariables = new SyntheticArgumentBinding[] { synthLocal };
46 int size = outerLocalVariables.length;
47 int newArgIndex = size;
48 for (int i = size; --i >= 0;) { // must search backwards
49 if (outerLocalVariables[i].actualOuterLocalVariable == actualOuterLocalVariable)
50 return outerLocalVariables[i]; // already exists
51 if (outerLocalVariables[i].id > actualOuterLocalVariable.id)
54 SyntheticArgumentBinding[] synthLocals = new SyntheticArgumentBinding[size + 1];
55 System.arraycopy(outerLocalVariables, 0, synthLocals, 0,
57 synthLocals[newArgIndex] = synthLocal = new SyntheticArgumentBinding(
58 actualOuterLocalVariable);
59 System.arraycopy(outerLocalVariables, newArgIndex, synthLocals,
60 newArgIndex + 1, size - newArgIndex);
61 outerLocalVariables = synthLocals;
63 // System.out.println("Adding synth arg for local var: " + new
64 // String(actualOuterLocalVariable.name) + " to: " + new
65 // String(this.readableName()));
66 if (scope.referenceCompilationUnit().isPropagatingInnerClassEmulation)
67 this.updateInnerEmulationDependents();
72 * Add a new synthetic argument for <enclosingType>. Answer the new argument
73 * or the existing argument if one already existed.
75 public SyntheticArgumentBinding addSyntheticArgument(
76 ReferenceBinding enclosingType) {
77 SyntheticArgumentBinding synthLocal = null;
78 if (enclosingInstances == null) {
79 synthLocal = new SyntheticArgumentBinding(enclosingType);
80 enclosingInstances = new SyntheticArgumentBinding[] { synthLocal };
82 int size = enclosingInstances.length;
83 int newArgIndex = size;
84 for (int i = size; --i >= 0;) {
85 if (enclosingInstances[i].type == enclosingType)
86 return enclosingInstances[i]; // already exists
87 if (this.enclosingType() == enclosingType)
90 SyntheticArgumentBinding[] newInstances = new SyntheticArgumentBinding[size + 1];
91 System.arraycopy(enclosingInstances, 0, newInstances,
92 newArgIndex == 0 ? 1 : 0, size);
93 newInstances[newArgIndex] = synthLocal = new SyntheticArgumentBinding(
95 enclosingInstances = newInstances;
97 // System.out.println("Adding synth arg for enclosing type: " + new
98 // String(enclosingType.readableName()) + " to: " + new
99 // String(this.readableName()));
100 if (scope.referenceCompilationUnit().isPropagatingInnerClassEmulation)
101 this.updateInnerEmulationDependents();
106 * Add a new synthetic argument and field for <actualOuterLocalVariable>.
107 * Answer the new argument or the existing argument if one already existed.
109 public SyntheticArgumentBinding addSyntheticArgumentAndField(
110 LocalVariableBinding actualOuterLocalVariable) {
111 SyntheticArgumentBinding synthLocal = addSyntheticArgument(actualOuterLocalVariable);
112 if (synthLocal == null)
115 if (synthLocal.matchingField == null)
116 synthLocal.matchingField = addSyntheticField(actualOuterLocalVariable);
121 * Add a new synthetic argument and field for <enclosingType>. Answer the
122 * new argument or the existing argument if one already existed.
124 public SyntheticArgumentBinding addSyntheticArgumentAndField(
125 ReferenceBinding enclosingType) {
126 SyntheticArgumentBinding synthLocal = addSyntheticArgument(enclosingType);
127 if (synthLocal == null)
130 if (synthLocal.matchingField == null)
131 synthLocal.matchingField = addSyntheticField(enclosingType);
136 * Compute the resolved positions for all the synthetic arguments
138 final public void computeSyntheticArgumentSlotSizes() {
141 // insert enclosing instances first, followed by the outerLocals
142 SyntheticArgumentBinding[] enclosingInstances = this
143 .syntheticEnclosingInstances();
144 int enclosingInstancesCount = enclosingInstances == null ? 0
145 : enclosingInstances.length;
146 for (int i = 0; i < enclosingInstancesCount; i++) {
147 SyntheticArgumentBinding argument = enclosingInstances[i];
148 // position the enclosing instance synthetic arg
149 argument.resolvedPosition = slotSize + 1; // shift by 1 to leave
150 // room for aload0==this
151 if (slotSize + 1 > 0xFF) { // no more than 255 words of arguments
152 this.scope.problemReporter().noMoreAvailableSpaceForArgument(
153 argument, this.scope.referenceType());
155 if ((argument.type == LongBinding)
156 || (argument.type == DoubleBinding)) {
162 this.enclosingInstancesSlotSize = slotSize;
164 slotSize = 0; // reset, outer local are not positionned yet, since
165 // will be appended to user arguments
166 SyntheticArgumentBinding[] outerLocals = this
167 .syntheticOuterLocalVariables();
168 int outerLocalsCount = outerLocals == null ? 0 : outerLocals.length;
169 for (int i = 0; i < outerLocalsCount; i++) {
170 SyntheticArgumentBinding argument = outerLocals[i];
171 // do NOT position the outerlocal synthetic arg yet, since will be
172 // appended to user arguments
173 if ((argument.type == LongBinding)
174 || (argument.type == DoubleBinding)) {
180 this.outerLocalVariablesSlotSize = slotSize;
184 * Answer the receiver's enclosing type... null if the receiver is a top
187 public ReferenceBinding enclosingType() {
189 return enclosingType;
193 * Answer the synthetic argument for <actualOuterLocalVariable> or null if
194 * one does not exist.
196 public SyntheticArgumentBinding getSyntheticArgument(
197 LocalVariableBinding actualOuterLocalVariable) {
199 if (outerLocalVariables == null)
200 return null; // is null if no outer local variables are known
202 for (int i = outerLocalVariables.length; --i >= 0;)
203 if (outerLocalVariables[i].actualOuterLocalVariable == actualOuterLocalVariable)
204 return outerLocalVariables[i];
208 public SyntheticArgumentBinding[] syntheticEnclosingInstances() {
209 return enclosingInstances; // is null if no enclosing instances are
213 public ReferenceBinding[] syntheticEnclosingInstanceTypes() {
214 if (enclosingInstances == null)
217 int length = enclosingInstances.length;
218 ReferenceBinding types[] = new ReferenceBinding[length];
219 for (int i = 0; i < length; i++)
220 types[i] = (ReferenceBinding) enclosingInstances[i].type;
224 public SyntheticArgumentBinding[] syntheticOuterLocalVariables() {
226 return outerLocalVariables; // is null if no outer locals are required
230 * Trigger the dependency mechanism forcing the innerclass emulation to be
231 * propagated to all dependent source types.
233 public void updateInnerEmulationDependents() {
234 // nothing to do in general, only local types are doing anything
238 * Answer the synthetic argument for <targetEnclosingType> or null if one
241 public SyntheticArgumentBinding getSyntheticArgument(
242 ReferenceBinding targetEnclosingType, boolean onlyExactMatch) {
244 if (enclosingInstances == null)
245 return null; // is null if no enclosing instances are known
248 for (int i = enclosingInstances.length; --i >= 0;)
249 if (enclosingInstances[i].type == targetEnclosingType)
250 if (enclosingInstances[i].actualOuterLocalVariable == null)
251 return enclosingInstances[i];
253 // type compatibility : to handle cases such as
254 // class T { class M{}}
255 // class S extends T { class N extends M {}} --> need to use S as a
256 // default enclosing instance for the super constructor call in N().
257 if (!onlyExactMatch) {
258 for (int i = enclosingInstances.length; --i >= 0;)
259 if (enclosingInstances[i].actualOuterLocalVariable == null)
260 if (targetEnclosingType
261 .isSuperclassOf((ReferenceBinding) enclosingInstances[i].type))
262 return enclosingInstances[i];