new version with WorkingCopy Management
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / compiler / lookup / NestedTypeBinding.java
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
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11 package net.sourceforge.phpdt.internal.compiler.lookup;
12
13 public class NestedTypeBinding extends SourceTypeBinding {
14
15         public SourceTypeBinding enclosingType;
16
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
21         
22         public NestedTypeBinding(char[][] typeName, ClassScope scope, SourceTypeBinding enclosingType) {
23                 super(typeName, enclosingType.fPackage, scope);
24                 this.tagBits |= IsNestedType;
25                 this.enclosingType = enclosingType;
26         }
27         
28         /* Add a new synthetic argument for <actualOuterLocalVariable>.
29         * Answer the new argument or the existing argument if one already existed.
30         */
31         public SyntheticArgumentBinding addSyntheticArgument(LocalVariableBinding actualOuterLocalVariable) {
32                 SyntheticArgumentBinding synthLocal = null;
33         
34                 if (outerLocalVariables == null) {
35                         synthLocal = new SyntheticArgumentBinding(actualOuterLocalVariable);
36                         outerLocalVariables = new SyntheticArgumentBinding[] {synthLocal};
37                 } else {
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)
44                                         newArgIndex = i;
45                         }
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;
51                 }
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();
55                 return synthLocal;
56         }
57
58         /* Add a new synthetic argument for <enclosingType>.
59         * Answer the new argument or the existing argument if one already existed.
60         */
61         public SyntheticArgumentBinding addSyntheticArgument(ReferenceBinding enclosingType) {
62                 SyntheticArgumentBinding synthLocal = null;
63                 if (enclosingInstances == null) {
64                         synthLocal = new SyntheticArgumentBinding(enclosingType);
65                         enclosingInstances = new SyntheticArgumentBinding[] {synthLocal};
66                 } else {
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)
73                                         newArgIndex = 0;
74                         }
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;
79                 }
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();
83                 return synthLocal;
84         }
85
86         /* Add a new synthetic argument and field for <actualOuterLocalVariable>.
87         * Answer the new argument or the existing argument if one already existed.
88         */
89         public SyntheticArgumentBinding addSyntheticArgumentAndField(LocalVariableBinding actualOuterLocalVariable) {
90                 SyntheticArgumentBinding synthLocal = addSyntheticArgument(actualOuterLocalVariable);
91                 if (synthLocal == null) return null;
92         
93                 if (synthLocal.matchingField == null)
94                         synthLocal.matchingField = addSyntheticField(actualOuterLocalVariable);
95                 return synthLocal;
96         }
97
98         /* Add a new synthetic argument and field for <enclosingType>.
99         * Answer the new argument or the existing argument if one already existed.
100         */
101         public SyntheticArgumentBinding addSyntheticArgumentAndField(ReferenceBinding enclosingType) {
102                 SyntheticArgumentBinding synthLocal = addSyntheticArgument(enclosingType);
103                 if (synthLocal == null) return null;
104         
105                 if (synthLocal.matchingField == null)
106                         synthLocal.matchingField = addSyntheticField(enclosingType);
107                 return synthLocal;
108         }
109
110         /**
111          * Compute the resolved positions for all the synthetic arguments
112          */
113         final public void computeSyntheticArgumentSlotSizes() {
114         
115                 int slotSize = 0; 
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()); 
125                         }
126                         if ((argument.type == LongBinding) || (argument.type == DoubleBinding)){
127                                 slotSize += 2;
128                         } else {
129                                 slotSize ++;
130                         }
131                 }
132                 this.enclosingInstancesSlotSize = slotSize; 
133                 
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)){
141                                 slotSize += 2;
142                         } else {
143                                 slotSize ++;
144                         }
145                 }
146                 this.outerLocalVariablesSlotSize = slotSize;
147         }
148         
149         /* Answer the receiver's enclosing type... null if the receiver is a top level type.
150         */
151         public ReferenceBinding enclosingType() {
152
153                 return enclosingType;
154         }
155
156         /* Answer the synthetic argument for <actualOuterLocalVariable> or null if one does not exist.
157         */
158         public SyntheticArgumentBinding getSyntheticArgument(LocalVariableBinding actualOuterLocalVariable) {
159
160                 if (outerLocalVariables == null) return null;           // is null if no outer local variables are known
161         
162                 for (int i = outerLocalVariables.length; --i >= 0;)
163                         if (outerLocalVariables[i].actualOuterLocalVariable == actualOuterLocalVariable)
164                                 return outerLocalVariables[i];
165                 return null;
166         }
167
168         public SyntheticArgumentBinding[] syntheticEnclosingInstances() {
169                 return enclosingInstances;              // is null if no enclosing instances are required
170         }
171
172         public ReferenceBinding[] syntheticEnclosingInstanceTypes() {
173                 if (enclosingInstances == null)
174                         return null;
175         
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;
180                 return types;
181         }
182
183         public SyntheticArgumentBinding[] syntheticOuterLocalVariables() {
184
185                 return outerLocalVariables;             // is null if no outer locals are required
186         }
187
188         /*
189          * Trigger the dependency mechanism forcing the innerclass emulation
190          * to be propagated to all dependent source types.
191          */
192         public void updateInnerEmulationDependents() {
193                 // nothing to do in general, only local types are doing anything
194         }
195         
196         /* Answer the synthetic argument for <targetEnclosingType> or null if one does not exist.
197         */
198         public SyntheticArgumentBinding getSyntheticArgument(ReferenceBinding targetEnclosingType, boolean onlyExactMatch) {
199
200                 if (enclosingInstances == null) return null;            // is null if no enclosing instances are known
201         
202                 // exact match
203                 for (int i = enclosingInstances.length; --i >= 0;)
204                         if (enclosingInstances[i].type == targetEnclosingType)
205                                 if (enclosingInstances[i].actualOuterLocalVariable == null)
206                                         return enclosingInstances[i];
207         
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];
216                 }
217                 return null;
218         }
219 }