View | Details | Raw Unified | Return to bug 361327 | Differences between
and this patch

Collapse All | Expand All

(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java (-75 / +183 lines)
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
			if(checkAndRecordImportBinding(importBinding, typesBySimpleNames, importReference, compoundName) == -1)
383
			if (importBinding instanceof MethodBinding) {
386
				continue nextImport;
384
				conflictingType = (ReferenceBinding) getType(compoundName, compoundName.length);
387
			if (importReference.isStatic()) {
385
				if (!conflictingType.isValidBinding() || (importReference.isStatic() && !conflictingType.isStatic()))
388
				// look for more bindings being imported
386
					conflictingType = null;
389
				// static imports are checked for fields first, followed by method and then type
387
			}
390
				// So if a type is found, no fields and methods are available anyway
388
			// collisions between an imported static field & a type should be checked according to spec... but currently not by javac
391
				// similarly when method is found, type may be available but no field available for sure
389
			if (importBinding instanceof ReferenceBinding || conflictingType != null) {
392
				if (importBinding.kind() == Binding.FIELD) {
390
				ReferenceBinding referenceBinding = conflictingType == null ? (ReferenceBinding) importBinding : conflictingType;
393
					if (checkMoreStaticBindings(compoundName, typesBySimpleNames, Binding.TYPE | Binding.METHOD, importReference) == -1)
391
				ReferenceBinding typeToCheck = referenceBinding.problemId() == ProblemReasons.Ambiguous
392
					? ((ProblemReferenceBinding) referenceBinding).closestMatch
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;
394
						continue nextImport;
422
					}
395
				} else if (importBinding.kind() == Binding.METHOD) {
423
					// either the type collides with a top level type or another imported type
396
					if (checkMoreStaticBindings(compoundName, typesBySimpleNames, Binding.TYPE, importReference) == -1)
424
					for (int j = 0, length = this.topLevelTypes.length; j < length; j++) {
397
						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
				}
398
				}
433
				typesBySimpleNames.put(compoundName[compoundName.length - 1], referenceBinding);
399
//				Binding importBinding = findSingleStaticImport(compoundName, Binding.TYPE);
434
			} else if (importBinding instanceof FieldBinding) {
400
//				if (importBinding.isValidBinding()) {
435
				for (int j = 0; j < index; j++) {
401
//					temp = checkAndAddImportBinding(importBinding, typesBySimpleNames, importReference, compoundName);
436
					ImportBinding resolved = resolvedImports[j];
402
//					if (temp == -1) continue nextImport;
437
					// find other static fields with the same name
403
//				}
438
					if (resolved.isStatic() && resolved.resolvedImport instanceof FieldBinding && importBinding != resolved.resolvedImport) {
404
//				importBinding = findSingleStaticImport(compoundName, Binding.FIELD);
439
						if (CharOperation.equals(compoundName[compoundName.length - 1], resolved.compoundName[resolved.compoundName.length - 1])) {
405
//				if (importBinding.isValidBinding()) {
440
							problemReporter().duplicateImport(importReference);
406
//					temp = checkAndAddImportBinding(importBinding, typesBySimpleNames, importReference, compoundName);
441
							continue nextImport;
407
//					if (temp == -1) continue nextImport;
442
						}
408
//				}
443
					}
409
//				importBinding = findSingleStaticImport(compoundName, Binding.METHOD);
444
				}
410
//				if (importBinding.isValidBinding()) {
411
//					temp = checkAndAddImportBinding(importBinding, typesBySimpleNames, importReference, compoundName);
412
//					if (temp == -1) continue nextImport; 
413
//				}
445
			}
414
			}
446
			resolvedImports[index++] = conflictingType == null
447
				? new ImportBinding(compoundName, false, importBinding, importReference)
448
				: new ImportConflictBinding(compoundName, importBinding, conflictingType, importReference);
449
		}
415
		}
450
	}
416
	}
451
417
452
	// shrink resolvedImports... only happens if an error was reported
418
	// shrink resolvedImports... only happens if an error was reported
453
	if (resolvedImports.length > index)
419
	if (this.tempImports.length > this.importPtr)
454
		System.arraycopy(resolvedImports, 0, resolvedImports = new ImportBinding[index], 0, index);
420
		System.arraycopy(this.tempImports, 0, this.tempImports = new ImportBinding[this.importPtr], 0, this.importPtr);
455
	this.imports = resolvedImports;
421
	this.imports = this.tempImports;
456
457
	int length = this.imports.length;
422
	int length = this.imports.length;
458
	this.typeOrPackageCache = new HashtableOfObject(length);
423
	this.typeOrPackageCache = new HashtableOfObject(length);
459
	for (int i = 0; i < length; i++) {
424
	for (int i = 0; i < length; i++) {
Lines 840-843 Link Here
840
	for (int i = 0, length = this.topLevelTypes.length; i < length; i++)
805
	for (int i = 0, length = this.topLevelTypes.length; i < length; i++)
841
		this.topLevelTypes[i].verifyMethods(verifier);
806
		this.topLevelTypes[i].verifyMethods(verifier);
842
}
807
}
808
private void recordImportBinding(ImportBinding bindingToAdd) {
809
	if (this.tempImports.length == this.importPtr) {
810
		System.arraycopy(this.tempImports, 0, (this.tempImports = new ImportBinding[this.importPtr + 1]), 0, this.importPtr);
811
	}
812
	this.tempImports[this.importPtr++] = bindingToAdd;
813
}
814
/**
815
 * Checks additional bindings (methods or types) imported from a single static import. 
816
 * Method is tried first, followed by type. If found, records them.
817
 * If in the process, import is flagged as duplicate, -1 is returned.
818
 * @param compoundName
819
 * @param typesBySimpleNames
820
 * @param mask
821
 * @param importReference
822
 * @return -1 when this import is flagged as duplicate, 0 otherwise.
823
 */
824
private int checkMoreStaticBindings(
825
		char[][] compoundName, 
826
		HashtableOfType typesBySimpleNames, 
827
		int mask,
828
		ImportReference importReference) {
829
	Binding importBinding = findSingleStaticImport(compoundName, mask);
830
	
831
	int temp;
832
	if (!importBinding.isValidBinding()) {
833
		// only continue of the same kind's ambiguous binding is returned
834
		// may have found an ambiguous type when looking for field or method. Don't continue in that case
835
		if (importBinding.problemId() == ProblemReasons.Ambiguous) {
836
			// keep it unless a duplicate can be found below
837
			temp = checkAndRecordImportBinding(importBinding, typesBySimpleNames, importReference, compoundName);
838
			if (temp == -1) return -1;
839
		}
840
	} else {
841
		temp = checkAndRecordImportBinding(importBinding, typesBySimpleNames, importReference, compoundName);
842
		if (temp == -1) return -1;
843
	}
844
	if (importBinding.kind() == Binding.METHOD) {
845
		// found method
846
		// type is left to be looked for
847
		// reset METHOD bit to enable lookup for only type
848
		mask &= ~Binding.METHOD;
849
		// now search for a type binding
850
		importBinding = findSingleStaticImport(compoundName, mask);
851
		if (!importBinding.isValidBinding()) {
852
			// only continue of the same kind's ambiguous binding is returned
853
			// may have found,say, an ambiguous type when looking for field or method. Don't continue in that case
854
			if (importBinding.problemId() == ProblemReasons.Ambiguous) {
855
				// keep it unless a duplicate can be found below
856
				temp = checkAndRecordImportBinding(importBinding, typesBySimpleNames, importReference, compoundName);
857
				if (temp == -1) return -1;
858
			}
859
		} else {
860
			temp = checkAndRecordImportBinding(importBinding, typesBySimpleNames, importReference, compoundName);
861
			if (temp == -1) return -1;
862
		}
863
	}
864
	return 0;
865
}
866
/**
867
 * Checks for duplicates. If all ok, records the importBinding
868
 * returns -1 when this import is flagged as duplicate.
869
 * @param importBinding
870
 * @param typesBySimpleNames
871
 * @param importReference
872
 * @param compoundName
873
 * @return -1 when this import is flagged as duplicate, importPtr otherwise.
874
 */
875
private int checkAndRecordImportBinding(
876
		Binding importBinding, 
877
		HashtableOfType typesBySimpleNames, 
878
		ImportReference importReference,
879
		char[][] compoundName) {
880
	ReferenceBinding conflictingType = null;
881
	if (importBinding instanceof MethodBinding) {
882
		conflictingType = (ReferenceBinding) getType(compoundName, compoundName.length);
883
		if (!conflictingType.isValidBinding() || (importReference.isStatic() && !conflictingType.isStatic()))
884
			conflictingType = null;
885
	}
886
	// collisions between an imported static field & a type should be checked according to spec... but currently not by javac
887
	if (importBinding instanceof ReferenceBinding || conflictingType != null) {
888
		ReferenceBinding referenceBinding = conflictingType == null ? (ReferenceBinding) importBinding : conflictingType;
889
		ReferenceBinding typeToCheck = referenceBinding.problemId() == ProblemReasons.Ambiguous
890
			? ((ProblemReferenceBinding) referenceBinding).closestMatch
891
			: referenceBinding;
892
		if (importReference.isTypeUseDeprecated(typeToCheck, this))
893
			problemReporter().deprecatedType(typeToCheck, importReference);
894
895
		ReferenceBinding existingType = typesBySimpleNames.get(compoundName[compoundName.length - 1]);
896
		if (existingType != null) {
897
			// duplicate test above should have caught this case, but make sure
898
			if (existingType == referenceBinding) {
899
				// https://bugs.eclipse.org/bugs/show_bug.cgi?id=302865
900
				// Check all resolved imports to see if this import qualifies as a duplicate
901
				for (int j = 0; j < this.importPtr; j++) {
902
					ImportBinding resolved = this.tempImports[j];
903
					if (resolved instanceof ImportConflictBinding) {
904
						ImportConflictBinding importConflictBinding = (ImportConflictBinding) resolved;
905
						if (importConflictBinding.conflictingTypeBinding == referenceBinding) {
906
							if (!importReference.isStatic()) {
907
								// resolved is implicitly static
908
								problemReporter().duplicateImport(importReference);
909
								recordImportBinding(new ImportBinding(compoundName, false, importBinding, importReference));
910
							}
911
						}
912
					} else if (resolved.resolvedImport == referenceBinding) {
913
						if (importReference.isStatic() != resolved.isStatic()) {
914
							problemReporter().duplicateImport(importReference);
915
							recordImportBinding(new ImportBinding(compoundName, false, importBinding, importReference));
916
						}
917
					}
918
				}
919
				return -1;
920
			}
921
			// either the type collides with a top level type or another imported type
922
			for (int j = 0, length = this.topLevelTypes.length; j < length; j++) {
923
				if (CharOperation.equals(this.topLevelTypes[j].sourceName, existingType.sourceName)) {
924
					problemReporter().conflictingImport(importReference);
925
					return -1;
926
				}
927
			}
928
			problemReporter().duplicateImport(importReference);
929
			return -1;
930
		}
931
		typesBySimpleNames.put(compoundName[compoundName.length - 1], referenceBinding);
932
	} else if (importBinding instanceof FieldBinding) {
933
		for (int j = 0; j < this.importPtr; j++) {
934
			ImportBinding resolved = this.tempImports[j];
935
			// find other static fields with the same name
936
			if (resolved.isStatic() && resolved.resolvedImport instanceof FieldBinding && importBinding != resolved.resolvedImport) {
937
				if (CharOperation.equals(compoundName[compoundName.length - 1], resolved.compoundName[resolved.compoundName.length - 1])) {
938
					problemReporter().duplicateImport(importReference);
939
					return -1;
940
				}
941
			}
942
		}
943
	}
944
	if (conflictingType == null) {
945
		recordImportBinding(new ImportBinding(compoundName, false, importBinding, importReference));
946
	} else {
947
		recordImportBinding(new ImportConflictBinding(compoundName, importBinding, conflictingType, importReference));
948
	}
949
	return this.importPtr;
950
}
843
}
951
}

Return to bug 361327