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
9 * IBM Corporation - initial API and implementation
10 ******************************************************************************/
11 package net.sourceforge.phpdt.internal.compiler.lookup;
13 public class NestedTypeBinding extends SourceTypeBinding {
14 public SourceTypeBinding enclosingType;
16 public SyntheticArgumentBinding[] enclosingInstances;
17 public SyntheticArgumentBinding[] outerLocalVariables;
18 public int syntheticArgumentsOffset; // amount of slots used by synthetic constructor arguments
19 public NestedTypeBinding(char[][] typeName, ClassScope scope, SourceTypeBinding enclosingType) {
20 super(typeName, enclosingType.fPackage, scope);
21 this.tagBits |= IsNestedType;
22 this.enclosingType = enclosingType;
24 /* Add a new synthetic argument for <actualOuterLocalVariable>.
25 * Answer the new argument or the existing argument if one already existed.
28 public SyntheticArgumentBinding addSyntheticArgument(LocalVariableBinding actualOuterLocalVariable) {
29 SyntheticArgumentBinding synthLocal = null;
31 if (outerLocalVariables == null) {
32 synthLocal = new SyntheticArgumentBinding(actualOuterLocalVariable);
33 outerLocalVariables = new SyntheticArgumentBinding[] {synthLocal};
35 int size = outerLocalVariables.length;
36 int newArgIndex = size;
37 for (int i = size; --i >= 0;) { // must search backwards
38 if (outerLocalVariables[i].actualOuterLocalVariable == actualOuterLocalVariable)
39 return outerLocalVariables[i]; // already exists
40 if (outerLocalVariables[i].id > actualOuterLocalVariable.id)
43 SyntheticArgumentBinding[] synthLocals = new SyntheticArgumentBinding[size + 1];
44 System.arraycopy(outerLocalVariables, 0, synthLocals, 0, newArgIndex);
45 synthLocals[newArgIndex] = synthLocal = new SyntheticArgumentBinding(actualOuterLocalVariable);
46 System.arraycopy(outerLocalVariables, newArgIndex, synthLocals, newArgIndex + 1, size - newArgIndex);
47 outerLocalVariables = synthLocals;
49 //System.out.println("Adding synth arg for local var: " + new String(actualOuterLocalVariable.name) + " to: " + new String(this.readableName()));
50 if (scope.referenceCompilationUnit().isPropagatingInnerClassEmulation)
51 this.updateInnerEmulationDependents();
54 /* Add a new synthetic argument for <enclosingType>.
55 * Answer the new argument or the existing argument if one already existed.
58 public SyntheticArgumentBinding addSyntheticArgument(ReferenceBinding enclosingType) {
59 SyntheticArgumentBinding synthLocal = null;
60 if (enclosingInstances == null) {
61 synthLocal = new SyntheticArgumentBinding(enclosingType);
62 enclosingInstances = new SyntheticArgumentBinding[] {synthLocal};
64 int size = enclosingInstances.length;
65 int newArgIndex = size;
66 for (int i = size; --i >= 0;) {
67 if (enclosingInstances[i].type == enclosingType)
68 return enclosingInstances[i]; // already exists
69 if (this.enclosingType() == enclosingType)
72 SyntheticArgumentBinding[] newInstances = new SyntheticArgumentBinding[size + 1];
73 System.arraycopy(enclosingInstances, 0, newInstances, newArgIndex == 0 ? 1 : 0, size);
74 newInstances[newArgIndex] = synthLocal = new SyntheticArgumentBinding(enclosingType);
75 enclosingInstances = newInstances;
77 //System.out.println("Adding synth arg for enclosing type: " + new String(enclosingType.readableName()) + " to: " + new String(this.readableName()));
78 if (scope.referenceCompilationUnit().isPropagatingInnerClassEmulation)
79 this.updateInnerEmulationDependents();
82 /* Add a new synthetic argument and field for <actualOuterLocalVariable>.
83 * Answer the new argument or the existing argument if one already existed.
86 public SyntheticArgumentBinding addSyntheticArgumentAndField(LocalVariableBinding actualOuterLocalVariable) {
87 SyntheticArgumentBinding synthLocal = addSyntheticArgument(actualOuterLocalVariable);
88 if (synthLocal == null) return null;
90 if (synthLocal.matchingField == null)
91 synthLocal.matchingField = addSyntheticField(actualOuterLocalVariable);
94 /* Add a new synthetic argument and field for <enclosingType>.
95 * Answer the new argument or the existing argument if one already existed.
98 public SyntheticArgumentBinding addSyntheticArgumentAndField(ReferenceBinding enclosingType) {
99 SyntheticArgumentBinding synthLocal = addSyntheticArgument(enclosingType);
100 if (synthLocal == null) return null;
102 if (synthLocal.matchingField == null)
103 synthLocal.matchingField = addSyntheticField(enclosingType);
107 * Compute the resolved positions for all the synthetic arguments
109 final public void computeSyntheticArgumentsOffset() {
111 int position = 1; // inside constructor, reserve room for receiver
113 // insert enclosing instances first, followed by the outerLocals
114 SyntheticArgumentBinding[] enclosingInstances = this.syntheticEnclosingInstances();
115 int enclosingInstancesCount = enclosingInstances == null ? 0 : enclosingInstances.length;
116 for (int i = 0; i < enclosingInstancesCount; i++){
117 SyntheticArgumentBinding syntheticArg = enclosingInstances[i];
118 syntheticArg.resolvedPosition = position;
119 if ((syntheticArg.type == LongBinding) || (syntheticArg.type == DoubleBinding)){
125 SyntheticArgumentBinding[] outerLocals = this.syntheticOuterLocalVariables();
126 int outerLocalsCount = outerLocals == null ? 0 : outerLocals.length;
127 for (int i = 0; i < outerLocalsCount; i++){
128 SyntheticArgumentBinding syntheticArg = outerLocals[i];
129 syntheticArg.resolvedPosition = position;
130 if ((syntheticArg.type == LongBinding) || (syntheticArg.type == DoubleBinding)){
136 this.syntheticArgumentsOffset = position;
138 /* Answer the receiver's enclosing type... null if the receiver is a top level type.
141 public ReferenceBinding enclosingType() {
142 return enclosingType;
144 /* Answer the synthetic argument for <actualOuterLocalVariable> or null if one does not exist.
147 public SyntheticArgumentBinding getSyntheticArgument(LocalVariableBinding actualOuterLocalVariable) {
148 if (outerLocalVariables == null) return null; // is null if no outer local variables are known
150 for (int i = outerLocalVariables.length; --i >= 0;)
151 if (outerLocalVariables[i].actualOuterLocalVariable == actualOuterLocalVariable)
152 return outerLocalVariables[i];
155 public SyntheticArgumentBinding[] syntheticEnclosingInstances() {
156 return enclosingInstances; // is null if no enclosing instances are required
158 public ReferenceBinding[] syntheticEnclosingInstanceTypes() {
159 if (enclosingInstances == null)
162 int length = enclosingInstances.length;
163 ReferenceBinding types[] = new ReferenceBinding[length];
164 for (int i = 0; i < length; i++)
165 types[i] = (ReferenceBinding) enclosingInstances[i].type;
168 public SyntheticArgumentBinding[] syntheticOuterLocalVariables() {
169 return outerLocalVariables; // is null if no enclosing instances are required
172 * Trigger the dependency mechanism forcing the innerclass emulation
173 * to be propagated to all dependent source types.
175 public void updateInnerEmulationDependents() {
176 // nothing to do in general, only local types are doing anything
179 /* Answer the synthetic argument for <targetEnclosingType> or null if one does not exist.
182 public SyntheticArgumentBinding getSyntheticArgument(ReferenceBinding targetEnclosingType, BlockScope scope, boolean onlyExactMatch) {
183 if (enclosingInstances == null) return null; // is null if no enclosing instances are known
186 for (int i = enclosingInstances.length; --i >= 0;)
187 if (enclosingInstances[i].type == targetEnclosingType)
188 if (enclosingInstances[i].actualOuterLocalVariable == null)
189 return enclosingInstances[i];
191 // type compatibility : to handle cases such as
192 // class T { class M{}}
193 // class S extends T { class N extends M {}} --> need to use S as a default enclosing instance for the super constructor call in N().
194 if (!onlyExactMatch){
195 for (int i = enclosingInstances.length; --i >= 0;)
196 if (enclosingInstances[i].actualOuterLocalVariable == null)
197 if (targetEnclosingType.isSuperclassOf((ReferenceBinding) enclosingInstances[i].type))
198 return enclosingInstances[i];