reenabled folding preference for inner types
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / compiler / lookup / LookupEnvironment.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 import net.sourceforge.phpdt.core.compiler.CharOperation;
14 import net.sourceforge.phpdt.internal.compiler.ast.CompilationUnitDeclaration;
15 import net.sourceforge.phpdt.internal.compiler.env.IBinaryType;
16 import net.sourceforge.phpdt.internal.compiler.env.INameEnvironment;
17 import net.sourceforge.phpdt.internal.compiler.env.NameEnvironmentAnswer;
18 import net.sourceforge.phpdt.internal.compiler.impl.ITypeRequestor;
19 import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter;
20 import net.sourceforge.phpdt.internal.compiler.util.HashtableOfPackage;
21 import net.sourceforge.phpdt.internal.compiler.util.Util;
22
23 public class LookupEnvironment implements BaseTypes, ProblemReasons, TypeConstants {
24 //      public CompilerOptions options;
25         public ProblemReporter problemReporter;
26         public ITypeRequestor typeRequestor;
27
28         PackageBinding defaultPackage;
29         ImportBinding[] defaultImports;
30         HashtableOfPackage knownPackages;
31         static final ProblemPackageBinding TheNotFoundPackage = new ProblemPackageBinding(CharOperation.NO_CHAR, NotFound);
32         static final ProblemReferenceBinding TheNotFoundType = new ProblemReferenceBinding(CharOperation.NO_CHAR, NotFound);
33
34         private INameEnvironment nameEnvironment;
35         private MethodVerifier verifier;
36         private ArrayBinding[][] uniqueArrayBindings;
37
38         private CompilationUnitDeclaration[] units = new CompilationUnitDeclaration[4];
39         private int lastUnitIndex = -1;
40         private int lastCompletedUnitIndex = -1;
41
42         // indicate in which step on the compilation we are.
43         // step 1 : build the reference binding
44         // step 2 : conect the hierarchy (connect bindings)
45         // step 3 : build fields and method bindings.
46         private int stepCompleted;
47         final static int BUILD_TYPE_HIERARCHY = 1;
48         final static int CHECK_AND_SET_IMPORTS = 2;
49         final static int CONNECT_TYPE_HIERARCHY = 3;
50         final static int BUILD_FIELDS_AND_METHODS = 4;
51 public LookupEnvironment(ITypeRequestor typeRequestor,ProblemReporter problemReporter, INameEnvironment nameEnvironment) {
52 // CompilerOptions options, ProblemReporter problemReporter, INameEnvironment nameEnvironment) {
53         this.typeRequestor = typeRequestor;
54 //      this.options = options;
55         this.problemReporter = problemReporter;
56         this.defaultPackage = new PackageBinding(this); // assume the default package always exists
57         this.defaultImports = null;
58         this.nameEnvironment = nameEnvironment;
59         this.knownPackages = new HashtableOfPackage();
60         this.uniqueArrayBindings = new ArrayBinding[5][];
61         this.uniqueArrayBindings[0] = new ArrayBinding[50]; // start off the most common 1 dimension array @ 50
62 }
63 /* Ask the oracle for a type which corresponds to the compoundName.
64 * Answer null if the name cannot be found.
65 */
66
67 public ReferenceBinding askForType(char[][] compoundName) {
68         NameEnvironmentAnswer answer = nameEnvironment.findType(compoundName);
69         if (answer == null)
70                 return null;
71
72         if (answer.isBinaryType())
73                 // the type was found as a .class file
74                 typeRequestor.accept(answer.getBinaryType(), computePackageFrom(compoundName));
75         else if (answer.isCompilationUnit())
76                 // the type was found as a .java file, try to build it then search the cache
77                 typeRequestor.accept(answer.getCompilationUnit());
78         else if (answer.isSourceType())
79                 // the type was found as a source model
80                 typeRequestor.accept(answer.getSourceTypes(), computePackageFrom(compoundName));
81
82         return getCachedType(compoundName);
83 }
84 /* Ask the oracle for a type named name in the packageBinding.
85 * Answer null if the name cannot be found.
86 */
87
88 ReferenceBinding askForType(PackageBinding packageBinding, char[] name) {
89         if (packageBinding == null) {
90                 if (defaultPackage == null)
91                         return null;
92                 packageBinding = defaultPackage;
93         }
94         NameEnvironmentAnswer answer = nameEnvironment.findType(name, packageBinding.compoundName);
95         if (answer == null)
96                 return null;
97
98         if (answer.isBinaryType())
99                 // the type was found as a .class file
100                 typeRequestor.accept(answer.getBinaryType(), packageBinding);
101         else if (answer.isCompilationUnit())
102                 // the type was found as a .java file, try to build it then search the cache
103                 typeRequestor.accept(answer.getCompilationUnit());
104         else if (answer.isSourceType())
105                 // the type was found as a source model
106                 typeRequestor.accept(answer.getSourceTypes(), packageBinding);
107
108         return packageBinding.getType0(name);
109 }
110 /* Create the initial type bindings for the compilation unit.
111 *
112 * See completeTypeBindings() for a description of the remaining steps
113 *
114 * NOTE: This method can be called multiple times as additional source files are needed
115 */
116
117 public void buildTypeBindings(CompilationUnitDeclaration unit) {
118         CompilationUnitScope scope = new CompilationUnitScope(unit, this);
119         scope.buildTypeBindings();
120
121         int unitsLength = units.length;
122         if (++lastUnitIndex >= unitsLength)
123                 System.arraycopy(units, 0, units = new CompilationUnitDeclaration[2 * unitsLength], 0, unitsLength);
124         units[lastUnitIndex] = unit;
125 }
126 /* Cache the binary type since we know it is needed during this compile.
127 *
128 * Answer the created BinaryTypeBinding or null if the type is already in the cache.
129 */
130
131 public BinaryTypeBinding cacheBinaryType(IBinaryType binaryType) {
132         return cacheBinaryType(binaryType, true);
133 }
134 /* Cache the binary type since we know it is needed during this compile.
135 *
136 * Answer the created BinaryTypeBinding or null if the type is already in the cache.
137 */
138
139 public BinaryTypeBinding cacheBinaryType(IBinaryType binaryType, boolean needFieldsAndMethods) {
140         char[][] compoundName = CharOperation.splitOn('/', binaryType.getName());
141         ReferenceBinding existingType = getCachedType(compoundName);
142
143         if (existingType == null || existingType instanceof UnresolvedReferenceBinding)
144                 // only add the binary type if its not already in the cache
145                 return createBinaryTypeFrom(binaryType, computePackageFrom(compoundName), needFieldsAndMethods);
146         return null; // the type already exists & can be retrieved from the cache
147 }
148 /*
149 * 1. Connect the type hierarchy for the type bindings created for parsedUnits.
150 * 2. Create the field bindings
151 * 3. Create the method bindings
152 */
153
154 /* We know each known compilationUnit is free of errors at this point...
155 *
156 * Each step will create additional bindings unless a problem is detected, in which
157 * case either the faulty import/superinterface/field/method will be skipped or a
158 * suitable replacement will be substituted (such as Object for a missing superclass)
159 */
160
161 public void completeTypeBindings() {
162         stepCompleted = BUILD_TYPE_HIERARCHY;
163         
164 //      for (int i = lastCompletedUnitIndex + 1; i <= lastUnitIndex; i++) {
165 //              units[i].scope.checkAndSetImports();
166 //      }
167         stepCompleted = CHECK_AND_SET_IMPORTS;
168
169 //      for (int i = lastCompletedUnitIndex + 1; i <= lastUnitIndex; i++) {
170 //              units[i].scope.connectTypeHierarchy();
171 //      }
172         stepCompleted = CONNECT_TYPE_HIERARCHY;
173
174         for (int i = lastCompletedUnitIndex + 1; i <= lastUnitIndex; i++) {
175 //              units[i].scope.buildFieldsAndMethods();
176                 units[i] = null; // release unnecessary reference to the parsed unit
177         }
178         stepCompleted = BUILD_FIELDS_AND_METHODS;
179         lastCompletedUnitIndex = lastUnitIndex;
180 }
181 /*
182 * 1. Connect the type hierarchy for the type bindings created for parsedUnits.
183 * 2. Create the field bindings
184 * 3. Create the method bindings
185 */
186
187 /*
188 * Each step will create additional bindings unless a problem is detected, in which
189 * case either the faulty import/superinterface/field/method will be skipped or a
190 * suitable replacement will be substituted (such as Object for a missing superclass)
191 */
192
193 public void completeTypeBindings(CompilationUnitDeclaration parsedUnit) {
194         if (stepCompleted == BUILD_FIELDS_AND_METHODS) {
195                 // This can only happen because the original set of units are completely built and
196                 // are now being processed, so we want to treat all the additional units as a group
197                 // until they too are completely processed.
198                 completeTypeBindings();
199         } else {
200                 if (parsedUnit.scope == null) return; // parsing errors were too severe
201
202 //              if (stepCompleted >= CHECK_AND_SET_IMPORTS)
203 //                      parsedUnit.scope.checkAndSetImports();
204
205                 if (stepCompleted >= CONNECT_TYPE_HIERARCHY)
206                         parsedUnit.scope.connectTypeHierarchy();
207         }
208 }
209 /*
210 * Used by other compiler tools which do not start by calling completeTypeBindings().
211 *
212 * 1. Connect the type hierarchy for the type bindings created for parsedUnits.
213 * 2. Create the field bindings
214 * 3. Create the method bindings
215 */
216
217 public void completeTypeBindings(CompilationUnitDeclaration parsedUnit, boolean buildFieldsAndMethods) {
218         if (parsedUnit.scope == null) return; // parsing errors were too severe
219
220         parsedUnit.scope.checkAndSetImports();
221         parsedUnit.scope.connectTypeHierarchy();
222
223         if (buildFieldsAndMethods)
224                 parsedUnit.scope.buildFieldsAndMethods();
225 }
226
227 private PackageBinding computePackageFrom(char[][] constantPoolName) {
228         if (constantPoolName.length == 1)
229                 return defaultPackage;
230
231         PackageBinding packageBinding = getPackage0(constantPoolName[0]);
232         if (packageBinding == null || packageBinding == TheNotFoundPackage) {
233                 packageBinding = new PackageBinding(constantPoolName[0], this);
234                 knownPackages.put(constantPoolName[0], packageBinding);
235         }
236
237         for (int i = 1, length = constantPoolName.length - 1; i < length; i++) {
238                 PackageBinding parent = packageBinding;
239                 if ((packageBinding = parent.getPackage0(constantPoolName[i])) == null || packageBinding == TheNotFoundPackage) {
240                         packageBinding = new PackageBinding(CharOperation.subarray(constantPoolName, 0, i + 1), parent, this);
241                         parent.addPackage(packageBinding);
242                 }
243         }
244         return packageBinding;
245 }
246 /* Used to guarantee array type identity.
247 */
248
249 ArrayBinding createArrayType(TypeBinding type, int dimensionCount) {
250         if (type instanceof LocalTypeBinding) // cache local type arrays with the local type itself
251                 return ((LocalTypeBinding) type).createArrayType(dimensionCount);
252
253         // find the array binding cache for this dimension
254         int dimIndex = dimensionCount - 1;
255         int length = uniqueArrayBindings.length;
256         ArrayBinding[] arrayBindings;
257         if (dimIndex < length) {
258                 if ((arrayBindings = uniqueArrayBindings[dimIndex]) == null)
259                         uniqueArrayBindings[dimIndex] = arrayBindings = new ArrayBinding[10];
260         } else {
261                 System.arraycopy(
262                         uniqueArrayBindings, 0, 
263                         uniqueArrayBindings = new ArrayBinding[dimensionCount][], 0, 
264                         length); 
265                 uniqueArrayBindings[dimIndex] = arrayBindings = new ArrayBinding[10];
266         }
267
268         // find the cached array binding for this leaf component type (if any)
269         int index = -1;
270         length = arrayBindings.length;
271         while (++index < length) {
272                 ArrayBinding currentBinding = arrayBindings[index];
273                 if (currentBinding == null) // no matching array, but space left
274                         return arrayBindings[index] = new ArrayBinding(type, dimensionCount);
275                 if (currentBinding.leafComponentType == type)
276                         return currentBinding;
277         }
278
279         // no matching array, no space left
280         System.arraycopy(
281                 arrayBindings, 0,
282                 (arrayBindings = new ArrayBinding[length * 2]), 0,
283                 length); 
284         uniqueArrayBindings[dimIndex] = arrayBindings;
285         return arrayBindings[length] = new ArrayBinding(type, dimensionCount);
286 }
287 public BinaryTypeBinding createBinaryTypeFrom(IBinaryType binaryType, PackageBinding packageBinding) {
288         return createBinaryTypeFrom(binaryType, packageBinding, true);
289 }
290 public BinaryTypeBinding createBinaryTypeFrom(IBinaryType binaryType, PackageBinding packageBinding, boolean needFieldsAndMethods) {
291         BinaryTypeBinding binaryBinding = new BinaryTypeBinding(packageBinding, binaryType, this);
292
293         // resolve any array bindings which reference the unresolvedType
294         ReferenceBinding cachedType = packageBinding.getType0(binaryBinding.compoundName[binaryBinding.compoundName.length - 1]);
295         if (cachedType != null) {
296                 if (cachedType.isBinaryBinding()) // sanity check before the cast... at this point the cache should ONLY contain unresolved types
297                         return (BinaryTypeBinding) cachedType;
298
299                 UnresolvedReferenceBinding unresolvedType = (UnresolvedReferenceBinding) cachedType;
300                 unresolvedType.resolvedType = binaryBinding;
301                 updateArrayCache(unresolvedType, binaryBinding);
302         }
303
304         packageBinding.addType(binaryBinding);
305         binaryBinding.cachePartsFrom(binaryType, needFieldsAndMethods);
306         return binaryBinding;
307 }
308 /* Used to create packages from the package statement.
309 */
310
311 PackageBinding createPackage(char[][] compoundName) {
312     return null;
313 //      PackageBinding packageBinding = getPackage0(compoundName[0]);
314 //      if (packageBinding == null || packageBinding == TheNotFoundPackage) {
315 //              packageBinding = new PackageBinding(compoundName[0], this);
316 //              knownPackages.put(compoundName[0], packageBinding);
317 //      }
318 //
319 //      for (int i = 1, length = compoundName.length; i < length; i++) {
320 //              // check to see if it collides with a known type...
321 //              // this case can only happen if the package does not exist as a directory in the file system
322 //              // otherwise when the source type was defined, the correct error would have been reported
323 //              // unless its an unresolved type which is referenced from an inconsistent class file
324 //              ReferenceBinding type = packageBinding.getType0(compoundName[i]);
325 //              if (type != null && type != TheNotFoundType && !(type instanceof UnresolvedReferenceBinding))
326 //                      return null;
327 //
328 //              PackageBinding parent = packageBinding;
329 //              if ((packageBinding = parent.getPackage0(compoundName[i])) == null || packageBinding == TheNotFoundPackage) {
330 //                      // if the package is unknown, check to see if a type exists which would collide with the new package
331 //                      // catches the case of a package statement of: package java.lang.Object;
332 //                      // since the package can be added after a set of source files have already been compiled, we need
333 //                      // whenever a package statement is encountered
334 //                      if (nameEnvironment.findType(compoundName[i], parent.compoundName) != null)
335 //                              return null;
336 //
337 //                      packageBinding = new PackageBinding(CharOperation.subarray(compoundName, 0, i + 1), parent, this);
338 //                      parent.addPackage(packageBinding);
339 //              }
340 //      }
341 //      return packageBinding;
342 }
343 /* Answer the type for the compoundName if it exists in the cache.
344 * Answer theNotFoundType if it could not be resolved the first time
345 * it was looked up, otherwise answer null.
346 *
347 * NOTE: Do not use for nested types... the answer is NOT the same for a.b.C or a.b.C.D.E
348 * assuming C is a type in both cases. In the a.b.C.D.E case, null is the answer.
349 */
350
351 public ReferenceBinding getCachedType(char[][] compoundName) {
352         if (compoundName.length == 1) {
353                 if (defaultPackage == null)
354                         return null;
355                 return defaultPackage.getType0(compoundName[0]);
356         }
357
358         PackageBinding packageBinding = getPackage0(compoundName[0]);
359         if (packageBinding == null || packageBinding == TheNotFoundPackage)
360                 return null;
361
362         for (int i = 1, packageLength = compoundName.length - 1; i < packageLength; i++)
363                 if ((packageBinding = packageBinding.getPackage0(compoundName[i])) == null || packageBinding == TheNotFoundPackage)
364                         return null;
365         return packageBinding.getType0(compoundName[compoundName.length - 1]);
366 }
367 /* Answer the top level package named name if it exists in the cache.
368 * Answer theNotFoundPackage if it could not be resolved the first time
369 * it was looked up, otherwise answer null.
370 *
371 * NOTE: Senders must convert theNotFoundPackage into a real problem
372 * package if its to returned.
373 */
374
375 PackageBinding getPackage0(char[] name) {
376         return knownPackages.get(name);
377 }
378 /* Answer the top level package named name.
379 * Ask the oracle for the package if its not in the cache.
380 * Answer null if the package cannot be found.
381 */
382
383 PackageBinding getTopLevelPackage(char[] name) {
384         PackageBinding packageBinding = getPackage0(name);
385         if (packageBinding != null) {
386                 if (packageBinding == TheNotFoundPackage)
387                         return null;
388                 else
389                         return packageBinding;
390         }
391
392         if (nameEnvironment.isPackage(null, name)) {
393                 knownPackages.put(name, packageBinding = new PackageBinding(name, this));
394                 return packageBinding;
395         }
396
397         knownPackages.put(name, TheNotFoundPackage); // saves asking the oracle next time
398         return null;
399 }
400 /* Answer the type corresponding to the compoundName.
401 * Ask the oracle for the type if its not in the cache.
402 * Answer null if the type cannot be found... likely a fatal error.
403 */
404
405 public ReferenceBinding getType(char[][] compoundName) {
406         ReferenceBinding referenceBinding;
407
408         if (compoundName.length == 1) {
409                 if (defaultPackage == null)
410                         return null;
411
412                 if ((referenceBinding = defaultPackage.getType0(compoundName[0])) == null) {
413                         PackageBinding packageBinding = getPackage0(compoundName[0]);
414                         if (packageBinding != null && packageBinding != TheNotFoundPackage)
415                                 return null; // collides with a known package... should not call this method in such a case
416                         referenceBinding = askForType(defaultPackage, compoundName[0]);
417                 }
418         } else {
419                 PackageBinding packageBinding = getPackage0(compoundName[0]);
420                 if (packageBinding == TheNotFoundPackage)
421                         return null;
422
423                 if (packageBinding != null) {
424                         for (int i = 1, packageLength = compoundName.length - 1; i < packageLength; i++) {
425                                 if ((packageBinding = packageBinding.getPackage0(compoundName[i])) == null)
426                                         break;
427                                 if (packageBinding == TheNotFoundPackage)
428                                         return null;
429                         }
430                 }
431
432                 if (packageBinding == null)
433                         referenceBinding = askForType(compoundName);
434                 else if ((referenceBinding = packageBinding.getType0(compoundName[compoundName.length - 1])) == null)
435                         referenceBinding = askForType(packageBinding, compoundName[compoundName.length - 1]);
436         }
437
438         if (referenceBinding == null || referenceBinding == TheNotFoundType)
439                 return null;
440         if (referenceBinding instanceof UnresolvedReferenceBinding)
441                 referenceBinding = ((UnresolvedReferenceBinding) referenceBinding).resolve(this);
442
443         // compoundName refers to a nested type incorrectly (for example, package1.A$B)
444         if (referenceBinding.isNestedType())
445                 return new ProblemReferenceBinding(compoundName, InternalNameProvided);
446         else
447                 return referenceBinding;
448 }
449 /* Answer the type corresponding to the name from the binary file.
450 * Does not ask the oracle for the type if its not found in the cache... instead an
451 * unresolved type is returned which must be resolved before used.
452 *
453 * NOTE: Does NOT answer base types nor array types!
454 *
455 * NOTE: Aborts compilation if the class file cannot be found.
456 */
457
458 ReferenceBinding getTypeFromConstantPoolName(char[] signature, int start, int end) {
459         if (end == -1)
460                 end = signature.length;
461
462         char[][] compoundName = CharOperation.splitOn('/', signature, start, end);
463         ReferenceBinding binding = getCachedType(compoundName);
464         if (binding == null) {
465                 PackageBinding packageBinding = computePackageFrom(compoundName);
466                 binding = new UnresolvedReferenceBinding(compoundName, packageBinding);
467                 packageBinding.addType(binding);
468         } else if (binding == TheNotFoundType) {
469                 problemReporter.isClassPathCorrect(compoundName, null);
470                 return null; // will not get here since the above error aborts the compilation
471         }
472         return binding;
473 }
474 /* Answer the type corresponding to the signature from the binary file.
475 * Does not ask the oracle for the type if its not found in the cache... instead an
476 * unresolved type is returned which must be resolved before used.
477 *
478 * NOTE: Does answer base types & array types.
479 *
480 * NOTE: Aborts compilation if the class file cannot be found.
481 */
482
483 TypeBinding getTypeFromSignature(char[] signature, int start, int end) {
484         int dimension = 0;
485         while (signature[start] == '[') {
486                 start++;
487                 dimension++;
488         }
489         if (end == -1)
490                 end = signature.length - 1;
491
492         // Just switch on signature[start] - the L case is the else
493         TypeBinding binding = null;
494         if (start == end) {
495                 switch (signature[start]) {
496                         case 'I' :
497                                 binding = IntBinding;
498                                 break;
499                         case 'Z' :
500                                 binding = BooleanBinding;
501                                 break;
502                         case 'V' :
503                                 binding = VoidBinding;
504                                 break;
505                         case 'C' :
506                                 binding = CharBinding;
507                                 break;
508                         case 'D' :
509                                 binding = DoubleBinding;
510                                 break;
511                         case 'B' :
512                                 binding = ByteBinding;
513                                 break;
514                         case 'F' :
515                                 binding = FloatBinding;
516                                 break;
517                         case 'J' :
518                                 binding = LongBinding;
519                                 break;
520                         case 'S' :
521                                 binding = ShortBinding;
522                                 break;
523                         default :
524                                 throw new Error(Util.bind("error.undefinedBaseType",String.valueOf(signature[start]))); //$NON-NLS-1$
525                 }
526         } else {
527                 binding = getTypeFromConstantPoolName(signature, start + 1, end);
528         }
529
530         if (dimension == 0)
531                 return binding;
532         else
533                 return createArrayType(binding, dimension);
534 }
535 /* Ask the oracle if a package exists named name in the package named compoundName.
536 */
537
538 boolean isPackage(char[][] compoundName, char[] name) {
539         if (compoundName == null || compoundName.length == 0)
540                 return nameEnvironment.isPackage(null, name);
541         else
542                 return nameEnvironment.isPackage(compoundName, name);
543 }
544 // The method verifier is lazily initialized to guarantee the receiver, the compiler & the oracle are ready.
545
546 public MethodVerifier methodVerifier() {
547         if (verifier == null)
548                 verifier = new MethodVerifier(this);
549         return verifier;
550 }
551 public void reset() {
552         this.defaultPackage = new PackageBinding(this); // assume the default package always exists
553         this.defaultImports = null;
554         this.knownPackages = new HashtableOfPackage();
555
556         this.verifier = null;
557         for (int i = this.uniqueArrayBindings.length; --i >= 0;)
558                 this.uniqueArrayBindings[i] = null;
559         this.uniqueArrayBindings[0] = new ArrayBinding[50]; // start off the most common 1 dimension array @ 50
560
561         for (int i = this.units.length; --i >= 0;)
562                 this.units[i] = null;
563         this.lastUnitIndex = -1;
564         this.lastCompletedUnitIndex = -1;
565         
566         // name environment has a longer life cycle, and must be reset in
567         // the code which created it.
568 }
569 void updateArrayCache(UnresolvedReferenceBinding unresolvedType, ReferenceBinding resolvedType) {
570         nextDimension : for (int i = 0, length = uniqueArrayBindings.length; i < length; i++) {
571                 ArrayBinding[] arrayBindings = uniqueArrayBindings[i];
572                 if (arrayBindings != null) {
573                         for (int j = 0, max = arrayBindings.length; j < max; j++) {
574                                 ArrayBinding currentBinding = arrayBindings[j];
575                                 if (currentBinding == null)
576                                         continue nextDimension;
577                                 if (currentBinding.leafComponentType == unresolvedType) {
578                                         currentBinding.leafComponentType = resolvedType;
579                                         continue nextDimension;
580                                 }
581                         }
582                 }
583         }
584 }
585 }