first scanner /parser copied from the jdt java version
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / compiler / lookup / NestedTypeBinding.java
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
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         public SourceTypeBinding enclosingType;
15
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;
23 }
24 /* Add a new synthetic argument for <actualOuterLocalVariable>.
25 * Answer the new argument or the existing argument if one already existed.
26 */
27
28 public SyntheticArgumentBinding addSyntheticArgument(LocalVariableBinding actualOuterLocalVariable) {
29         SyntheticArgumentBinding synthLocal = null;
30
31         if (outerLocalVariables == null) {
32                 synthLocal = new SyntheticArgumentBinding(actualOuterLocalVariable);
33                 outerLocalVariables = new SyntheticArgumentBinding[] {synthLocal};
34         } else {
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)
41                                 newArgIndex = i;
42                 }
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;
48         }
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();
52         return synthLocal;
53 }
54 /* Add a new synthetic argument for <enclosingType>.
55 * Answer the new argument or the existing argument if one already existed.
56 */
57
58 public SyntheticArgumentBinding addSyntheticArgument(ReferenceBinding enclosingType) {
59         SyntheticArgumentBinding synthLocal = null;
60         if (enclosingInstances == null) {
61                 synthLocal = new SyntheticArgumentBinding(enclosingType);
62                 enclosingInstances = new SyntheticArgumentBinding[] {synthLocal};
63         } else {
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)
70                                 newArgIndex = 0;
71                 }
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;
76         }
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();
80         return synthLocal;
81 }
82 /* Add a new synthetic argument and field for <actualOuterLocalVariable>.
83 * Answer the new argument or the existing argument if one already existed.
84 */
85
86 public SyntheticArgumentBinding addSyntheticArgumentAndField(LocalVariableBinding actualOuterLocalVariable) {
87         SyntheticArgumentBinding synthLocal = addSyntheticArgument(actualOuterLocalVariable);
88         if (synthLocal == null) return null;
89
90         if (synthLocal.matchingField == null)
91                 synthLocal.matchingField = addSyntheticField(actualOuterLocalVariable);
92         return synthLocal;
93 }
94 /* Add a new synthetic argument and field for <enclosingType>.
95 * Answer the new argument or the existing argument if one already existed.
96 */
97
98 public SyntheticArgumentBinding addSyntheticArgumentAndField(ReferenceBinding enclosingType) {
99         SyntheticArgumentBinding synthLocal = addSyntheticArgument(enclosingType);
100         if (synthLocal == null) return null;
101
102         if (synthLocal.matchingField == null)
103                 synthLocal.matchingField = addSyntheticField(enclosingType);
104         return synthLocal;
105 }
106 /**
107  * Compute the resolved positions for all the synthetic arguments
108  */
109 final public void computeSyntheticArgumentsOffset() {
110
111         int position = 1; // inside constructor, reserve room for receiver
112         
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)){
120                         position += 2;
121                 } else {
122                         position ++;
123                 }
124         }
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)){
131                         position += 2;
132                 } else {
133                         position ++;
134                 }
135         }
136         this.syntheticArgumentsOffset = position;
137 }
138 /* Answer the receiver's enclosing type... null if the receiver is a top level type.
139 */
140
141 public ReferenceBinding enclosingType() {
142         return enclosingType;
143 }
144 /* Answer the synthetic argument for <actualOuterLocalVariable> or null if one does not exist.
145 */
146
147 public SyntheticArgumentBinding getSyntheticArgument(LocalVariableBinding actualOuterLocalVariable) {
148         if (outerLocalVariables == null) return null;           // is null if no outer local variables are known
149
150         for (int i = outerLocalVariables.length; --i >= 0;)
151                 if (outerLocalVariables[i].actualOuterLocalVariable == actualOuterLocalVariable)
152                         return outerLocalVariables[i];
153         return null;
154 }
155 public SyntheticArgumentBinding[] syntheticEnclosingInstances() {
156         return enclosingInstances;              // is null if no enclosing instances are required
157 }
158 public ReferenceBinding[] syntheticEnclosingInstanceTypes() {
159         if (enclosingInstances == null)
160                 return null;
161
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;
166         return types;
167 }
168 public SyntheticArgumentBinding[] syntheticOuterLocalVariables() {
169         return outerLocalVariables;             // is null if no enclosing instances are required
170 }
171 /*
172  * Trigger the dependency mechanism forcing the innerclass emulation
173  * to be propagated to all dependent source types.
174  */
175 public void updateInnerEmulationDependents() {
176         // nothing to do in general, only local types are doing anything
177 }
178
179 /* Answer the synthetic argument for <targetEnclosingType> or null if one does not exist.
180 */
181
182 public SyntheticArgumentBinding getSyntheticArgument(ReferenceBinding targetEnclosingType, BlockScope scope, boolean onlyExactMatch) {
183         if (enclosingInstances == null) return null;            // is null if no enclosing instances are known
184
185         // exact match
186         for (int i = enclosingInstances.length; --i >= 0;)
187                 if (enclosingInstances[i].type == targetEnclosingType)
188                         if (enclosingInstances[i].actualOuterLocalVariable == null)
189                                 return enclosingInstances[i];
190
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];
199         }
200         return null;
201 }
202 }