Lines 25-30
Link Here
|
25 |
public char[][] currentPackageName; |
25 |
public char[][] currentPackageName; |
26 |
public PackageBinding fPackage; |
26 |
public PackageBinding fPackage; |
27 |
public ImportBinding[] imports; |
27 |
public ImportBinding[] imports; |
|
|
28 |
public int importPtr; |
28 |
public HashtableOfObject typeOrPackageCache; // used in Scope.getTypeOrPackage() |
29 |
public HashtableOfObject typeOrPackageCache; // used in Scope.getTypeOrPackage() |
29 |
|
30 |
|
30 |
public SourceTypeBinding[] topLevelTypes; |
31 |
public SourceTypeBinding[] topLevelTypes; |
Lines 37-42
Link Here
|
37 |
|
38 |
|
38 |
HashtableOfType constantPoolNameUsage; |
39 |
HashtableOfType constantPoolNameUsage; |
39 |
private int captureID = 1; |
40 |
private int captureID = 1; |
|
|
41 |
|
42 |
private ImportBinding[] tempImports; // to keep a record of resolved imports while traversing all in faultInImports() |
40 |
|
43 |
|
41 |
public CompilationUnitScope(CompilationUnitDeclaration unit, LookupEnvironment environment) { |
44 |
public CompilationUnitScope(CompilationUnitDeclaration unit, LookupEnvironment environment) { |
42 |
super(COMPILATION_UNIT_SCOPE, null); |
45 |
super(COMPILATION_UNIT_SCOPE, null); |
Lines 328-337
Link Here
|
328 |
break; |
331 |
break; |
329 |
} |
332 |
} |
330 |
} |
333 |
} |
331 |
ImportBinding[] resolvedImports = new ImportBinding[numberOfImports]; |
334 |
this.tempImports = new ImportBinding[numberOfImports]; |
332 |
resolvedImports[0] = getDefaultImports()[0]; |
335 |
this.tempImports[0] = getDefaultImports()[0]; |
333 |
int index = 1; |
336 |
this.importPtr = 1; |
334 |
|
337 |
|
335 |
// keep static imports with normal imports until there is a reason to split them up |
338 |
// keep static imports with normal imports until there is a reason to split them up |
336 |
// on demand imports continue to be packages & types. need to check on demand type imports for fields/methods |
339 |
// on demand imports continue to be packages & types. need to check on demand type imports for fields/methods |
337 |
// single imports change from being just types to types or fields |
340 |
// single imports change from being just types to types or fields |
Lines 340-347
Link Here
|
340 |
char[][] compoundName = importReference.tokens; |
343 |
char[][] compoundName = importReference.tokens; |
341 |
|
344 |
|
342 |
// skip duplicates or imports of the current package |
345 |
// skip duplicates or imports of the current package |
343 |
for (int j = 0; j < index; j++) { |
346 |
for (int j = 0; j < this.importPtr; j++) { |
344 |
ImportBinding resolved = resolvedImports[j]; |
347 |
ImportBinding resolved = this.tempImports[j]; |
345 |
if (resolved.onDemand == ((importReference.bits & ASTNode.OnDemand) != 0) && resolved.isStatic() == importReference.isStatic()) { |
348 |
if (resolved.onDemand == ((importReference.bits & ASTNode.OnDemand) != 0) && resolved.isStatic() == importReference.isStatic()) { |
346 |
if (CharOperation.equals(compoundName, resolved.compoundName)) { |
349 |
if (CharOperation.equals(compoundName, resolved.compoundName)) { |
347 |
problemReporter().unusedImport(importReference); // since skipped, must be reported now |
350 |
problemReporter().unusedImport(importReference); // since skipped, must be reported now |
Lines 364-370
Link Here
|
364 |
problemReporter().cannotImportPackage(importReference); |
367 |
problemReporter().cannotImportPackage(importReference); |
365 |
continue nextImport; |
368 |
continue nextImport; |
366 |
} |
369 |
} |
367 |
resolvedImports[index++] = new ImportBinding(compoundName, true, importBinding, importReference); |
370 |
recordImportBinding(new ImportBinding(compoundName, true, importBinding, importReference)); |
368 |
} else { |
371 |
} else { |
369 |
Binding importBinding = findSingleImport(compoundName, Binding.TYPE | Binding.FIELD | Binding.METHOD, importReference.isStatic()); |
372 |
Binding importBinding = findSingleImport(compoundName, Binding.TYPE | Binding.FIELD | Binding.METHOD, importReference.isStatic()); |
370 |
if (!importBinding.isValidBinding()) { |
373 |
if (!importBinding.isValidBinding()) { |
Lines 379-459
Link Here
|
379 |
problemReporter().cannotImportPackage(importReference); |
382 |
problemReporter().cannotImportPackage(importReference); |
380 |
continue nextImport; |
383 |
continue nextImport; |
381 |
} |
384 |
} |
382 |
ReferenceBinding conflictingType = null; |
385 |
// all the code here which checks for valid bindings have been moved to the method |
383 |
if (importBinding instanceof MethodBinding) { |
386 |
// checkAndRecordImportBinding() since bug 361327 |
384 |
conflictingType = (ReferenceBinding) getType(compoundName, compoundName.length); |
387 |
if(checkAndRecordImportBinding(importBinding, typesBySimpleNames, importReference, compoundName) == -1) |
385 |
if (!conflictingType.isValidBinding() || (importReference.isStatic() && !conflictingType.isStatic())) |
388 |
continue nextImport; |
386 |
conflictingType = null; |
389 |
if (importReference.isStatic()) { |
387 |
} |
390 |
// look for more static bindings being imported by single static import(bug 361327). |
388 |
// collisions between an imported static field & a type should be checked according to spec... but currently not by javac |
391 |
// findSingleImport() finds fields first, followed by method and then type |
389 |
if (importBinding instanceof ReferenceBinding || conflictingType != null) { |
392 |
// So if a type is found, no fields and methods are available anyway |
390 |
ReferenceBinding referenceBinding = conflictingType == null ? (ReferenceBinding) importBinding : conflictingType; |
393 |
// similarly when method is found, type may be available but no field available for sure |
391 |
ReferenceBinding typeToCheck = referenceBinding.problemId() == ProblemReasons.Ambiguous |
394 |
if (importBinding.kind() == Binding.FIELD) { |
392 |
? ((ProblemReferenceBinding) referenceBinding).closestMatch |
395 |
if (checkMoreStaticBindings(compoundName, typesBySimpleNames, Binding.TYPE | Binding.METHOD, importReference) == -1) |
393 |
: referenceBinding; |
|
|
394 |
if (importReference.isTypeUseDeprecated(typeToCheck, this)) |
395 |
problemReporter().deprecatedType(typeToCheck, importReference); |
396 |
|
397 |
ReferenceBinding existingType = typesBySimpleNames.get(compoundName[compoundName.length - 1]); |
398 |
if (existingType != null) { |
399 |
// duplicate test above should have caught this case, but make sure |
400 |
if (existingType == referenceBinding) { |
401 |
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=302865 |
402 |
// Check all resolved imports to see if this import qualifies as a duplicate |
403 |
for (int j = 0; j < index; j++) { |
404 |
ImportBinding resolved = resolvedImports[j]; |
405 |
if (resolved instanceof ImportConflictBinding) { |
406 |
ImportConflictBinding importConflictBinding = (ImportConflictBinding) resolved; |
407 |
if (importConflictBinding.conflictingTypeBinding == referenceBinding) { |
408 |
if (!importReference.isStatic()) { |
409 |
// resolved is implicitly static |
410 |
problemReporter().duplicateImport(importReference); |
411 |
resolvedImports[index++] = new ImportBinding(compoundName, false, importBinding, importReference); |
412 |
} |
413 |
} |
414 |
} else if (resolved.resolvedImport == referenceBinding) { |
415 |
if (importReference.isStatic() != resolved.isStatic()) { |
416 |
problemReporter().duplicateImport(importReference); |
417 |
resolvedImports[index++] = new ImportBinding(compoundName, false, importBinding, importReference); |
418 |
} |
419 |
} |
420 |
} |
421 |
continue nextImport; |
396 |
continue nextImport; |
422 |
} |
397 |
} else if (importBinding.kind() == Binding.METHOD) { |
423 |
// either the type collides with a top level type or another imported type |
398 |
if (checkMoreStaticBindings(compoundName, typesBySimpleNames, Binding.TYPE, importReference) == -1) |
424 |
for (int j = 0, length = this.topLevelTypes.length; j < length; j++) { |
399 |
continue nextImport; |
425 |
if (CharOperation.equals(this.topLevelTypes[j].sourceName, existingType.sourceName)) { |
|
|
426 |
problemReporter().conflictingImport(importReference); |
427 |
continue nextImport; |
428 |
} |
429 |
} |
430 |
problemReporter().duplicateImport(importReference); |
431 |
continue nextImport; |
432 |
} |
433 |
typesBySimpleNames.put(compoundName[compoundName.length - 1], referenceBinding); |
434 |
} else if (importBinding instanceof FieldBinding) { |
435 |
for (int j = 0; j < index; j++) { |
436 |
ImportBinding resolved = resolvedImports[j]; |
437 |
// find other static fields with the same name |
438 |
if (resolved.isStatic() && resolved.resolvedImport instanceof FieldBinding && importBinding != resolved.resolvedImport) { |
439 |
if (CharOperation.equals(compoundName[compoundName.length - 1], resolved.compoundName[resolved.compoundName.length - 1])) { |
440 |
problemReporter().duplicateImport(importReference); |
441 |
continue nextImport; |
442 |
} |
443 |
} |
444 |
} |
400 |
} |
445 |
} |
401 |
} |
446 |
resolvedImports[index++] = conflictingType == null |
|
|
447 |
? new ImportBinding(compoundName, false, importBinding, importReference) |
448 |
: new ImportConflictBinding(compoundName, importBinding, conflictingType, importReference); |
449 |
} |
402 |
} |
450 |
} |
403 |
} |
451 |
|
404 |
|
452 |
// shrink resolvedImports... only happens if an error was reported |
405 |
// shrink resolvedImports... only happens if an error was reported |
453 |
if (resolvedImports.length > index) |
406 |
if (this.tempImports.length > this.importPtr) |
454 |
System.arraycopy(resolvedImports, 0, resolvedImports = new ImportBinding[index], 0, index); |
407 |
System.arraycopy(this.tempImports, 0, this.tempImports = new ImportBinding[this.importPtr], 0, this.importPtr); |
455 |
this.imports = resolvedImports; |
408 |
this.imports = this.tempImports; |
456 |
|
|
|
457 |
int length = this.imports.length; |
409 |
int length = this.imports.length; |
458 |
this.typeOrPackageCache = new HashtableOfObject(length); |
410 |
this.typeOrPackageCache = new HashtableOfObject(length); |
459 |
for (int i = 0; i < length; i++) { |
411 |
for (int i = 0; i < length; i++) { |
Lines 840-843
Link Here
|
840 |
for (int i = 0, length = this.topLevelTypes.length; i < length; i++) |
792 |
for (int i = 0, length = this.topLevelTypes.length; i < length; i++) |
841 |
this.topLevelTypes[i].verifyMethods(verifier); |
793 |
this.topLevelTypes[i].verifyMethods(verifier); |
842 |
} |
794 |
} |
|
|
795 |
private void recordImportBinding(ImportBinding bindingToAdd) { |
796 |
if (this.tempImports.length == this.importPtr) { |
797 |
System.arraycopy(this.tempImports, 0, (this.tempImports = new ImportBinding[this.importPtr + 1]), 0, this.importPtr); |
798 |
} |
799 |
this.tempImports[this.importPtr++] = bindingToAdd; |
800 |
} |
801 |
/** |
802 |
* Checks additional bindings (methods or types) imported from a single static import. |
803 |
* Method is tried first, followed by type. If found, records them. |
804 |
* If in the process, import is flagged as duplicate, -1 is returned. |
805 |
* @param compoundName |
806 |
* @param typesBySimpleNames |
807 |
* @param mask |
808 |
* @param importReference |
809 |
* @return -1 when this import is flagged as duplicate, 0 otherwise. |
810 |
*/ |
811 |
private int checkMoreStaticBindings( |
812 |
char[][] compoundName, |
813 |
HashtableOfType typesBySimpleNames, |
814 |
int mask, |
815 |
ImportReference importReference) { |
816 |
Binding importBinding = findSingleStaticImport(compoundName, mask); |
817 |
|
818 |
int temp; |
819 |
if (!importBinding.isValidBinding()) { |
820 |
// only continue if the same kind's ambiguous binding is returned |
821 |
// may have found an ambiguous type when looking for field or method. Don't continue in that case |
822 |
if (importBinding.problemId() == ProblemReasons.Ambiguous) { |
823 |
// keep it unless a duplicate can be found below |
824 |
temp = checkAndRecordImportBinding(importBinding, typesBySimpleNames, importReference, compoundName); |
825 |
if (temp == -1) return -1; |
826 |
} |
827 |
} else { |
828 |
temp = checkAndRecordImportBinding(importBinding, typesBySimpleNames, importReference, compoundName); |
829 |
if (temp == -1) return -1; |
830 |
} |
831 |
if (importBinding.kind() == Binding.METHOD) { |
832 |
// found method |
833 |
// type is left to be looked for |
834 |
// reset METHOD bit to enable lookup for only type |
835 |
mask &= ~Binding.METHOD; |
836 |
// now search for a type binding |
837 |
importBinding = findSingleStaticImport(compoundName, mask); |
838 |
if (!importBinding.isValidBinding()) { |
839 |
// only continue if the same kind's ambiguous binding is returned |
840 |
// may have found,say, an ambiguous type when looking for field or method. Don't continue in that case |
841 |
if (importBinding.problemId() == ProblemReasons.Ambiguous) { |
842 |
// keep it unless a duplicate can be found below |
843 |
temp = checkAndRecordImportBinding(importBinding, typesBySimpleNames, importReference, compoundName); |
844 |
if (temp == -1) return -1; |
845 |
} |
846 |
} else { |
847 |
temp = checkAndRecordImportBinding(importBinding, typesBySimpleNames, importReference, compoundName); |
848 |
if (temp == -1) return -1; |
849 |
} |
850 |
} |
851 |
return 0; |
852 |
} |
853 |
/** |
854 |
* Checks for duplicates. If all ok, records the importBinding |
855 |
* returns -1 when this import is flagged as duplicate. |
856 |
* @param importBinding |
857 |
* @param typesBySimpleNames |
858 |
* @param importReference |
859 |
* @param compoundName |
860 |
* @return -1 when this import is flagged as duplicate, importPtr otherwise. |
861 |
*/ |
862 |
private int checkAndRecordImportBinding( |
863 |
Binding importBinding, |
864 |
HashtableOfType typesBySimpleNames, |
865 |
ImportReference importReference, |
866 |
char[][] compoundName) { |
867 |
ReferenceBinding conflictingType = null; |
868 |
if (importBinding instanceof MethodBinding) { |
869 |
conflictingType = (ReferenceBinding) getType(compoundName, compoundName.length); |
870 |
if (!conflictingType.isValidBinding() || (importReference.isStatic() && !conflictingType.isStatic())) |
871 |
conflictingType = null; |
872 |
} |
873 |
// collisions between an imported static field & a type should be checked according to spec... but currently not by javac |
874 |
if (importBinding instanceof ReferenceBinding || conflictingType != null) { |
875 |
ReferenceBinding referenceBinding = conflictingType == null ? (ReferenceBinding) importBinding : conflictingType; |
876 |
ReferenceBinding typeToCheck = referenceBinding.problemId() == ProblemReasons.Ambiguous |
877 |
? ((ProblemReferenceBinding) referenceBinding).closestMatch |
878 |
: referenceBinding; |
879 |
if (importReference.isTypeUseDeprecated(typeToCheck, this)) |
880 |
problemReporter().deprecatedType(typeToCheck, importReference); |
881 |
|
882 |
ReferenceBinding existingType = typesBySimpleNames.get(compoundName[compoundName.length - 1]); |
883 |
if (existingType != null) { |
884 |
// duplicate test above should have caught this case, but make sure |
885 |
if (existingType == referenceBinding) { |
886 |
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=302865 |
887 |
// Check all resolved imports to see if this import qualifies as a duplicate |
888 |
for (int j = 0; j < this.importPtr; j++) { |
889 |
ImportBinding resolved = this.tempImports[j]; |
890 |
if (resolved instanceof ImportConflictBinding) { |
891 |
ImportConflictBinding importConflictBinding = (ImportConflictBinding) resolved; |
892 |
if (importConflictBinding.conflictingTypeBinding == referenceBinding) { |
893 |
if (!importReference.isStatic()) { |
894 |
// resolved is implicitly static |
895 |
problemReporter().duplicateImport(importReference); |
896 |
recordImportBinding(new ImportBinding(compoundName, false, importBinding, importReference)); |
897 |
} |
898 |
} |
899 |
} else if (resolved.resolvedImport == referenceBinding) { |
900 |
if (importReference.isStatic() != resolved.isStatic()) { |
901 |
problemReporter().duplicateImport(importReference); |
902 |
recordImportBinding(new ImportBinding(compoundName, false, importBinding, importReference)); |
903 |
} |
904 |
} |
905 |
} |
906 |
return -1; |
907 |
} |
908 |
// either the type collides with a top level type or another imported type |
909 |
for (int j = 0, length = this.topLevelTypes.length; j < length; j++) { |
910 |
if (CharOperation.equals(this.topLevelTypes[j].sourceName, existingType.sourceName)) { |
911 |
problemReporter().conflictingImport(importReference); |
912 |
return -1; |
913 |
} |
914 |
} |
915 |
problemReporter().duplicateImport(importReference); |
916 |
return -1; |
917 |
} |
918 |
typesBySimpleNames.put(compoundName[compoundName.length - 1], referenceBinding); |
919 |
} else if (importBinding instanceof FieldBinding) { |
920 |
for (int j = 0; j < this.importPtr; j++) { |
921 |
ImportBinding resolved = this.tempImports[j]; |
922 |
// find other static fields with the same name |
923 |
if (resolved.isStatic() && resolved.resolvedImport instanceof FieldBinding && importBinding != resolved.resolvedImport) { |
924 |
if (CharOperation.equals(compoundName[compoundName.length - 1], resolved.compoundName[resolved.compoundName.length - 1])) { |
925 |
problemReporter().duplicateImport(importReference); |
926 |
return -1; |
927 |
} |
928 |
} |
929 |
} |
930 |
} |
931 |
if (conflictingType == null) { |
932 |
recordImportBinding(new ImportBinding(compoundName, false, importBinding, importReference)); |
933 |
} else { |
934 |
recordImportBinding(new ImportConflictBinding(compoundName, importBinding, conflictingType, importReference)); |
935 |
} |
936 |
return this.importPtr; |
937 |
} |
843 |
} |
938 |
} |