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;
18 public SyntheticArgumentBinding[] outerLocalVariables;
19 public int enclosingInstancesSlotSize; // amount of slots used by synthetic enclosing instances
20 public int outerLocalVariablesSlotSize; // amount of slots used by synthetic outer local variables
22 public NestedTypeBinding(char[][] typeName, ClassScope scope, SourceTypeBinding enclosingType) {
23 super(typeName, enclosingType.fPackage, scope);
24 this.tagBits |= IsNestedType;
25 this.enclosingType = enclosingType;
28 /* Add a new synthetic argument for <actualOuterLocalVariable>.
29 * Answer the new argument or the existing argument if one already existed.
31 public SyntheticArgumentBinding addSyntheticArgument(LocalVariableBinding actualOuterLocalVariable) {
32 SyntheticArgumentBinding synthLocal = null;
34 if (outerLocalVariables == null) {
35 synthLocal = new SyntheticArgumentBinding(actualOuterLocalVariable);
36 outerLocalVariables = new SyntheticArgumentBinding[] {synthLocal};
38 int size = outerLocalVariables.length;
39 int newArgIndex = size;
40 for (int i = size; --i >= 0;) { // must search backwards
41 if (outerLocalVariables[i].actualOuterLocalVariable == actualOuterLocalVariable)
42 return outerLocalVariables[i]; // already exists
43 if (outerLocalVariables[i].id > actualOuterLocalVariable.id)
46 SyntheticArgumentBinding[] synthLocals = new SyntheticArgumentBinding[size + 1];
47 System.arraycopy(outerLocalVariables, 0, synthLocals, 0, newArgIndex);
48 synthLocals[newArgIndex] = synthLocal = new SyntheticArgumentBinding(actualOuterLocalVariable);
49 System.arraycopy(outerLocalVariables, newArgIndex, synthLocals, newArgIndex + 1, size - newArgIndex);
50 outerLocalVariables = synthLocals;
52 //System.out.println("Adding synth arg for local var: " + new String(actualOuterLocalVariable.name) + " to: " + new String(this.readableName()));
53 if (scope.referenceCompilationUnit().isPropagatingInnerClassEmulation)
54 this.updateInnerEmulationDependents();
58 /* Add a new synthetic argument for <enclosingType>.
59 * Answer the new argument or the existing argument if one already existed.
61 public SyntheticArgumentBinding addSyntheticArgument(ReferenceBinding enclosingType) {
62 SyntheticArgumentBinding synthLocal = null;
63 if (enclosingInstances == null) {
64 synthLocal = new SyntheticArgumentBinding(enclosingType);
65 enclosingInstances = new SyntheticArgumentBinding[] {synthLocal};
67 int size = enclosingInstances.length;
68 int newArgIndex = size;
69 for (int i = size; --i >= 0;) {
70 if (enclosingInstances[i].type == enclosingType)
71 return enclosingInstances[i]; // already exists
72 if (this.enclosingType() == enclosingType)
75 SyntheticArgumentBinding[] newInstances = new SyntheticArgumentBinding[size + 1];
76 System.arraycopy(enclosingInstances, 0, newInstances, newArgIndex == 0 ? 1 : 0, size);
77 newInstances[newArgIndex] = synthLocal = new SyntheticArgumentBinding(enclosingType);
78 enclosingInstances = newInstances;
80 //System.out.println("Adding synth arg for enclosing type: " + new String(enclosingType.readableName()) + " to: " + new String(this.readableName()));
81 if (scope.referenceCompilationUnit().isPropagatingInnerClassEmulation)
82 this.updateInnerEmulationDependents();
86 /* Add a new synthetic argument and field for <actualOuterLocalVariable>.
87 * Answer the new argument or the existing argument if one already existed.
89 public SyntheticArgumentBinding addSyntheticArgumentAndField(LocalVariableBinding actualOuterLocalVariable) {
90 SyntheticArgumentBinding synthLocal = addSyntheticArgument(actualOuterLocalVariable);
91 if (synthLocal == null) return null;
93 if (synthLocal.matchingField == null)
94 synthLocal.matchingField = addSyntheticField(actualOuterLocalVariable);
98 /* Add a new synthetic argument and field for <enclosingType>.
99 * Answer the new argument or the existing argument if one already existed.
101 public SyntheticArgumentBinding addSyntheticArgumentAndField(ReferenceBinding enclosingType) {
102 SyntheticArgumentBinding synthLocal = addSyntheticArgument(enclosingType);
103 if (synthLocal == null) return null;
105 if (synthLocal.matchingField == null)
106 synthLocal.matchingField = addSyntheticField(enclosingType);
111 * Compute the resolved positions for all the synthetic arguments
113 final public void computeSyntheticArgumentSlotSizes() {
116 // insert enclosing instances first, followed by the outerLocals
117 SyntheticArgumentBinding[] enclosingInstances = this.syntheticEnclosingInstances();
118 int enclosingInstancesCount = enclosingInstances == null ? 0 : enclosingInstances.length;
119 for (int i = 0; i < enclosingInstancesCount; i++){
120 SyntheticArgumentBinding argument = enclosingInstances[i];
121 // position the enclosing instance synthetic arg
122 argument.resolvedPosition = slotSize + 1; // shift by 1 to leave room for aload0==this
123 if (slotSize + 1 > 0xFF) { // no more than 255 words of arguments
124 this.scope.problemReporter().noMoreAvailableSpaceForArgument(argument, this.scope.referenceType());
126 if ((argument.type == LongBinding) || (argument.type == DoubleBinding)){
132 this.enclosingInstancesSlotSize = slotSize;
134 slotSize = 0; // reset, outer local are not positionned yet, since will be appended to user arguments
135 SyntheticArgumentBinding[] outerLocals = this.syntheticOuterLocalVariables();
136 int outerLocalsCount = outerLocals == null ? 0 : outerLocals.length;
137 for (int i = 0; i < outerLocalsCount; i++){
138 SyntheticArgumentBinding argument = outerLocals[i];
139 // do NOT position the outerlocal synthetic arg yet, since will be appended to user arguments
140 if ((argument.type == LongBinding) || (argument.type == DoubleBinding)){
146 this.outerLocalVariablesSlotSize = slotSize;
149 /* Answer the receiver's enclosing type... null if the receiver is a top level type.
151 public ReferenceBinding enclosingType() {
153 return enclosingType;
156 /* Answer the synthetic argument for <actualOuterLocalVariable> or null if one does not exist.
158 public SyntheticArgumentBinding getSyntheticArgument(LocalVariableBinding actualOuterLocalVariable) {
160 if (outerLocalVariables == null) return null; // is null if no outer local variables are known
162 for (int i = outerLocalVariables.length; --i >= 0;)
163 if (outerLocalVariables[i].actualOuterLocalVariable == actualOuterLocalVariable)
164 return outerLocalVariables[i];
168 public SyntheticArgumentBinding[] syntheticEnclosingInstances() {
169 return enclosingInstances; // is null if no enclosing instances are required
172 public ReferenceBinding[] syntheticEnclosingInstanceTypes() {
173 if (enclosingInstances == null)
176 int length = enclosingInstances.length;
177 ReferenceBinding types[] = new ReferenceBinding[length];
178 for (int i = 0; i < length; i++)
179 types[i] = (ReferenceBinding) enclosingInstances[i].type;
183 public SyntheticArgumentBinding[] syntheticOuterLocalVariables() {
185 return outerLocalVariables; // is null if no outer locals are required
189 * Trigger the dependency mechanism forcing the innerclass emulation
190 * to be propagated to all dependent source types.
192 public void updateInnerEmulationDependents() {
193 // nothing to do in general, only local types are doing anything
196 /* Answer the synthetic argument for <targetEnclosingType> or null if one does not exist.
198 public SyntheticArgumentBinding getSyntheticArgument(ReferenceBinding targetEnclosingType, boolean onlyExactMatch) {
200 if (enclosingInstances == null) return null; // is null if no enclosing instances are known
203 for (int i = enclosingInstances.length; --i >= 0;)
204 if (enclosingInstances[i].type == targetEnclosingType)
205 if (enclosingInstances[i].actualOuterLocalVariable == null)
206 return enclosingInstances[i];
208 // type compatibility : to handle cases such as
209 // class T { class M{}}
210 // class S extends T { class N extends M {}} --> need to use S as a default enclosing instance for the super constructor call in N().
211 if (!onlyExactMatch){
212 for (int i = enclosingInstances.length; --i >= 0;)
213 if (enclosingInstances[i].actualOuterLocalVariable == null)
214 if (targetEnclosingType.isSuperclassOf((ReferenceBinding) enclosingInstances[i].type))
215 return enclosingInstances[i];