|
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 |
checkMoreStaticBindings(compoundName, typesBySimpleNames, Binding.TYPE | Binding.METHOD, importReference); |
| 393 |
: referenceBinding; |
396 |
} else if (importBinding.kind() == Binding.METHOD) { |
| 394 |
if (importReference.isTypeUseDeprecated(typeToCheck, this)) |
397 |
checkMoreStaticBindings(compoundName, typesBySimpleNames, Binding.TYPE, importReference); |
| 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; |
| 422 |
} |
| 423 |
// either the type collides with a top level type or another imported type |
| 424 |
for (int j = 0, length = this.topLevelTypes.length; j < length; j++) { |
| 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 |
} |
398 |
} |
| 445 |
} |
399 |
} |
| 446 |
resolvedImports[index++] = conflictingType == null |
|
|
| 447 |
? new ImportBinding(compoundName, false, importBinding, importReference) |
| 448 |
: new ImportConflictBinding(compoundName, importBinding, conflictingType, importReference); |
| 449 |
} |
400 |
} |
| 450 |
} |
401 |
} |
| 451 |
|
402 |
|
| 452 |
// shrink resolvedImports... only happens if an error was reported |
403 |
// shrink resolvedImports... only happens if an error was reported |
| 453 |
if (resolvedImports.length > index) |
404 |
if (this.tempImports.length > this.importPtr) |
| 454 |
System.arraycopy(resolvedImports, 0, resolvedImports = new ImportBinding[index], 0, index); |
405 |
System.arraycopy(this.tempImports, 0, this.tempImports = new ImportBinding[this.importPtr], 0, this.importPtr); |
| 455 |
this.imports = resolvedImports; |
406 |
this.imports = this.tempImports; |
| 456 |
|
|
|
| 457 |
int length = this.imports.length; |
407 |
int length = this.imports.length; |
| 458 |
this.typeOrPackageCache = new HashtableOfObject(length); |
408 |
this.typeOrPackageCache = new HashtableOfObject(length); |
| 459 |
for (int i = 0; i < length; i++) { |
409 |
for (int i = 0; i < length; i++) { |
|
Lines 840-843
Link Here
|
| 840 |
for (int i = 0, length = this.topLevelTypes.length; i < length; i++) |
790 |
for (int i = 0, length = this.topLevelTypes.length; i < length; i++) |
| 841 |
this.topLevelTypes[i].verifyMethods(verifier); |
791 |
this.topLevelTypes[i].verifyMethods(verifier); |
| 842 |
} |
792 |
} |
|
|
793 |
private void recordImportBinding(ImportBinding bindingToAdd) { |
| 794 |
if (this.tempImports.length == this.importPtr) { |
| 795 |
System.arraycopy(this.tempImports, 0, (this.tempImports = new ImportBinding[this.importPtr + 1]), 0, this.importPtr); |
| 796 |
} |
| 797 |
this.tempImports[this.importPtr++] = bindingToAdd; |
| 798 |
} |
| 799 |
/** |
| 800 |
* Checks additional bindings (methods or types) imported from a single static import. |
| 801 |
* Method is tried first, followed by type. If found, records them. |
| 802 |
* If in the process, import is flagged as duplicate, -1 is returned. |
| 803 |
* @param compoundName |
| 804 |
* @param typesBySimpleNames |
| 805 |
* @param mask |
| 806 |
* @param importReference |
| 807 |
*/ |
| 808 |
private void checkMoreStaticBindings( |
| 809 |
char[][] compoundName, |
| 810 |
HashtableOfType typesBySimpleNames, |
| 811 |
int mask, |
| 812 |
ImportReference importReference) { |
| 813 |
Binding importBinding = findSingleStaticImport(compoundName, mask); |
| 814 |
if (!importBinding.isValidBinding()) { |
| 815 |
// only continue if the same kind's ambiguous binding is returned |
| 816 |
// may have found an ambiguous type when looking for field or method. Don't continue in that case |
| 817 |
if (importBinding.problemId() == ProblemReasons.Ambiguous) { |
| 818 |
// keep it unless a duplicate can be found below |
| 819 |
checkAndRecordImportBinding(importBinding, typesBySimpleNames, importReference, compoundName); |
| 820 |
} |
| 821 |
} else { |
| 822 |
checkAndRecordImportBinding(importBinding, typesBySimpleNames, importReference, compoundName); |
| 823 |
} |
| 824 |
if (((mask & Binding.METHOD) != 0) && (importBinding.kind() == Binding.METHOD)) { |
| 825 |
// found method |
| 826 |
// type is left to be looked for |
| 827 |
// reset METHOD bit to enable lookup for only type |
| 828 |
mask &= ~Binding.METHOD; |
| 829 |
// now search for a type binding |
| 830 |
checkMoreStaticBindings(compoundName, typesBySimpleNames, mask, importReference); |
| 831 |
} |
| 832 |
} |
| 833 |
/** |
| 834 |
* Checks for duplicates. If all ok, records the importBinding |
| 835 |
* returns -1 when this import is flagged as duplicate. |
| 836 |
* @param importBinding |
| 837 |
* @param typesBySimpleNames |
| 838 |
* @param importReference |
| 839 |
* @param compoundName |
| 840 |
* @return -1 when this import is flagged as duplicate, importPtr otherwise. |
| 841 |
*/ |
| 842 |
private int checkAndRecordImportBinding( |
| 843 |
Binding importBinding, |
| 844 |
HashtableOfType typesBySimpleNames, |
| 845 |
ImportReference importReference, |
| 846 |
char[][] compoundName) { |
| 847 |
ReferenceBinding conflictingType = null; |
| 848 |
if (importBinding instanceof MethodBinding) { |
| 849 |
conflictingType = (ReferenceBinding) getType(compoundName, compoundName.length); |
| 850 |
if (!conflictingType.isValidBinding() || (importReference.isStatic() && !conflictingType.isStatic())) |
| 851 |
conflictingType = null; |
| 852 |
} |
| 853 |
// collisions between an imported static field & a type should be checked according to spec... but currently not by javac |
| 854 |
if (importBinding instanceof ReferenceBinding || conflictingType != null) { |
| 855 |
ReferenceBinding referenceBinding = conflictingType == null ? (ReferenceBinding) importBinding : conflictingType; |
| 856 |
ReferenceBinding typeToCheck = referenceBinding.problemId() == ProblemReasons.Ambiguous |
| 857 |
? ((ProblemReferenceBinding) referenceBinding).closestMatch |
| 858 |
: referenceBinding; |
| 859 |
if (importReference.isTypeUseDeprecated(typeToCheck, this)) |
| 860 |
problemReporter().deprecatedType(typeToCheck, importReference); |
| 861 |
|
| 862 |
ReferenceBinding existingType = typesBySimpleNames.get(compoundName[compoundName.length - 1]); |
| 863 |
if (existingType != null) { |
| 864 |
// duplicate test above should have caught this case, but make sure |
| 865 |
if (existingType == referenceBinding) { |
| 866 |
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=302865 |
| 867 |
// Check all resolved imports to see if this import qualifies as a duplicate |
| 868 |
for (int j = 0; j < this.importPtr; j++) { |
| 869 |
ImportBinding resolved = this.tempImports[j]; |
| 870 |
if (resolved instanceof ImportConflictBinding) { |
| 871 |
ImportConflictBinding importConflictBinding = (ImportConflictBinding) resolved; |
| 872 |
if (importConflictBinding.conflictingTypeBinding == referenceBinding) { |
| 873 |
if (!importReference.isStatic()) { |
| 874 |
// resolved is implicitly static |
| 875 |
problemReporter().duplicateImport(importReference); |
| 876 |
recordImportBinding(new ImportBinding(compoundName, false, importBinding, importReference)); |
| 877 |
} |
| 878 |
} |
| 879 |
} else if (resolved.resolvedImport == referenceBinding) { |
| 880 |
if (importReference.isStatic() != resolved.isStatic()) { |
| 881 |
problemReporter().duplicateImport(importReference); |
| 882 |
recordImportBinding(new ImportBinding(compoundName, false, importBinding, importReference)); |
| 883 |
} |
| 884 |
} |
| 885 |
} |
| 886 |
return -1; |
| 887 |
} |
| 888 |
// either the type collides with a top level type or another imported type |
| 889 |
for (int j = 0, length = this.topLevelTypes.length; j < length; j++) { |
| 890 |
if (CharOperation.equals(this.topLevelTypes[j].sourceName, existingType.sourceName)) { |
| 891 |
problemReporter().conflictingImport(importReference); |
| 892 |
return -1; |
| 893 |
} |
| 894 |
} |
| 895 |
problemReporter().duplicateImport(importReference); |
| 896 |
return -1; |
| 897 |
} |
| 898 |
typesBySimpleNames.put(compoundName[compoundName.length - 1], referenceBinding); |
| 899 |
} else if (importBinding instanceof FieldBinding) { |
| 900 |
for (int j = 0; j < this.importPtr; j++) { |
| 901 |
ImportBinding resolved = this.tempImports[j]; |
| 902 |
// find other static fields with the same name |
| 903 |
if (resolved.isStatic() && resolved.resolvedImport instanceof FieldBinding && importBinding != resolved.resolvedImport) { |
| 904 |
if (CharOperation.equals(compoundName[compoundName.length - 1], resolved.compoundName[resolved.compoundName.length - 1])) { |
| 905 |
problemReporter().duplicateImport(importReference); |
| 906 |
return -1; |
| 907 |
} |
| 908 |
} |
| 909 |
} |
| 910 |
} |
| 911 |
if (conflictingType == null) { |
| 912 |
recordImportBinding(new ImportBinding(compoundName, false, importBinding, importReference)); |
| 913 |
} else { |
| 914 |
recordImportBinding(new ImportConflictBinding(compoundName, importBinding, conflictingType, importReference)); |
| 915 |
} |
| 916 |
return this.importPtr; |
| 917 |
} |
| 843 |
} |
918 |
} |