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

Collapse All | Expand All

(-)src/org/eclipse/jdt/core/tests/model/JavaSearchBugsTests.java (+29 lines)
Lines 10187-10190 Link Here
10187
		deleteProject("P");
10187
		deleteProject("P");
10188
	}
10188
	}
10189
}
10189
}
10190
10191
/**
10192
 * @bug 266582: [search] NPE finding references 
10193
 * @test Ensure that no NPE occurs when searching for type references
10194
 * 	in a project which has the same jar twice on its classpath
10195
 * @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=266582"
10196
 */
10197
public void testBug266582() throws Exception {
10198
	addLibraryEntry(JAVA_PROJECT, "/JavaSearchBugs/lib/b266582a.jar", false);
10199
	addLibraryEntry(JAVA_PROJECT, "/JavaSearchBugs/lib/b266582b.jar", false);
10200
	try {
10201
		createFile("/JavaSearchBugs/src/A.java",
10202
			"import foo.JohnsonException;\n" + 
10203
			"class A {\n" + 
10204
			"	void foo() throws JohnsonException {}\n" + 
10205
			"}"
10206
		);
10207
		IType type = getClassFile("JavaSearchBugs", "/JavaSearchBugs/lib/b266582a.jar", "foo", "JohnsonException.class").getType();
10208
		search(type, REFERENCES);
10209
		assertSearchResults(
10210
			"src/A.java [foo.JohnsonException] EXACT_MATCH\n" + 
10211
			"src/A.java void A.foo() [JohnsonException] EXACT_MATCH"
10212
		);
10213
	}
10214
	finally {
10215
		removeClasspathEntry(JAVA_PROJECT, new Path("/JavaSearchBugs/lib/b266582a.jar"));
10216
		removeClasspathEntry(JAVA_PROJECT, new Path("/JavaSearchBugs/lib/b266582b.jar"));
10217
	}
10218
}
10190
}
10219
}
(-)compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java (-76 / +125 lines)
Lines 243-333 Link Here
243
	return availableMethods;
243
	return availableMethods;
244
}
244
}
245
void cachePartsFrom(IBinaryType binaryType, boolean needFieldsAndMethods) {
245
void cachePartsFrom(IBinaryType binaryType, boolean needFieldsAndMethods) {
246
	// default initialization for super-interfaces early, in case some aborting compilation error occurs,
246
	try {
247
	// and still want to use binaries passed that point (e.g. type hierarchy resolver, see bug 63748).
247
		// default initialization for super-interfaces early, in case some aborting compilation error occurs,
248
	this.typeVariables = Binding.NO_TYPE_VARIABLES;
248
		// and still want to use binaries passed that point (e.g. type hierarchy resolver, see bug 63748).
249
	this.superInterfaces = Binding.NO_SUPERINTERFACES;
249
		this.typeVariables = Binding.NO_TYPE_VARIABLES;
250
251
	// must retrieve member types in case superclass/interfaces need them
252
	this.memberTypes = Binding.NO_MEMBER_TYPES;
253
	IBinaryNestedType[] memberTypeStructures = binaryType.getMemberTypes();
254
	if (memberTypeStructures != null) {
255
		int size = memberTypeStructures.length;
256
		if (size > 0) {
257
			this.memberTypes = new ReferenceBinding[size];
258
			for (int i = 0; i < size; i++)
259
				// attempt to find each member type if it exists in the cache (otherwise - resolve it when requested)
260
				this.memberTypes[i] = environment.getTypeFromConstantPoolName(memberTypeStructures[i].getName(), 0, -1, false, null /* could not be missing */);
261
			this.tagBits |= 	TagBits.HasUnresolvedMemberTypes;
262
		}
263
	}
264
265
	
266
	long sourceLevel = environment.globalOptions.sourceLevel;
267
	char[] typeSignature = null;
268
	if (sourceLevel >= ClassFileConstants.JDK1_5) {
269
		typeSignature = binaryType.getGenericSignature();
270
		this.tagBits |= binaryType.getTagBits();
271
	}
272
	char[][][] missingTypeNames = binaryType.getMissingTypeNames();	
273
	if (typeSignature == null) {
274
		char[] superclassName = binaryType.getSuperclassName();
275
		if (superclassName != null) {
276
			// attempt to find the superclass if it exists in the cache (otherwise - resolve it when requested)
277
			this.superclass = environment.getTypeFromConstantPoolName(superclassName, 0, -1, false, missingTypeNames);
278
			this.tagBits |= TagBits.HasUnresolvedSuperclass;
279
		}
280
281
		this.superInterfaces = Binding.NO_SUPERINTERFACES;
250
		this.superInterfaces = Binding.NO_SUPERINTERFACES;
282
		char[][] interfaceNames = binaryType.getInterfaceNames();
251
283
		if (interfaceNames != null) {
252
		// must retrieve member types in case superclass/interfaces need them
284
			int size = interfaceNames.length;
253
		this.memberTypes = Binding.NO_MEMBER_TYPES;
254
		IBinaryNestedType[] memberTypeStructures = binaryType.getMemberTypes();
255
		if (memberTypeStructures != null) {
256
			int size = memberTypeStructures.length;
285
			if (size > 0) {
257
			if (size > 0) {
286
				this.superInterfaces = new ReferenceBinding[size];
258
				this.memberTypes = new ReferenceBinding[size];
287
				for (int i = 0; i < size; i++)
259
				for (int i = 0; i < size; i++)
288
					// attempt to find each superinterface if it exists in the cache (otherwise - resolve it when requested)
260
					// attempt to find each member type if it exists in the cache (otherwise - resolve it when requested)
289
					this.superInterfaces[i] = environment.getTypeFromConstantPoolName(interfaceNames[i], 0, -1, false, missingTypeNames);
261
					this.memberTypes[i] = environment.getTypeFromConstantPoolName(memberTypeStructures[i].getName(), 0, -1, false, null /* could not be missing */);
290
				this.tagBits |= TagBits.HasUnresolvedSuperinterfaces;
262
				this.tagBits |= 	TagBits.HasUnresolvedMemberTypes;
291
			}
263
			}
292
		}
264
		}
293
	} else {
294
		// ClassSignature = ParameterPart(optional) super_TypeSignature interface_signature
295
		SignatureWrapper wrapper = new SignatureWrapper(typeSignature);
296
		if (wrapper.signature[wrapper.start] == '<') {
297
			// ParameterPart = '<' ParameterSignature(s) '>'
298
			wrapper.start++; // skip '<'
299
			this.typeVariables = createTypeVariables(wrapper, true, missingTypeNames);
300
			wrapper.start++; // skip '>'
301
			this.tagBits |=  TagBits.HasUnresolvedTypeVariables;
302
			this.modifiers |= ExtraCompilerModifiers.AccGenericSignature;
303
		}
304
265
305
		// attempt to find the superclass if it exists in the cache (otherwise - resolve it when requested)
266
		long sourceLevel = environment.globalOptions.sourceLevel;
306
		this.superclass = (ReferenceBinding) environment.getTypeFromTypeSignature(wrapper, Binding.NO_TYPE_VARIABLES, this, missingTypeNames);
267
		char[] typeSignature = null;
307
		this.tagBits |= TagBits.HasUnresolvedSuperclass;
268
		if (sourceLevel >= ClassFileConstants.JDK1_5) {
269
			typeSignature = binaryType.getGenericSignature();
270
			this.tagBits |= binaryType.getTagBits();
271
		}
272
		char[][][] missingTypeNames = binaryType.getMissingTypeNames();	
273
		if (typeSignature == null) {
274
			char[] superclassName = binaryType.getSuperclassName();
275
			if (superclassName != null) {
276
				// attempt to find the superclass if it exists in the cache (otherwise - resolve it when requested)
277
				this.superclass = environment.getTypeFromConstantPoolName(superclassName, 0, -1, false, missingTypeNames);
278
				this.tagBits |= TagBits.HasUnresolvedSuperclass;
279
			}
280
281
			this.superInterfaces = Binding.NO_SUPERINTERFACES;
282
			char[][] interfaceNames = binaryType.getInterfaceNames();
283
			if (interfaceNames != null) {
284
				int size = interfaceNames.length;
285
				if (size > 0) {
286
					this.superInterfaces = new ReferenceBinding[size];
287
					for (int i = 0; i < size; i++)
288
						// attempt to find each superinterface if it exists in the cache (otherwise - resolve it when requested)
289
						this.superInterfaces[i] = environment.getTypeFromConstantPoolName(interfaceNames[i], 0, -1, false, missingTypeNames);
290
					this.tagBits |= TagBits.HasUnresolvedSuperinterfaces;
291
				}
292
			}
293
		} else {
294
			// ClassSignature = ParameterPart(optional) super_TypeSignature interface_signature
295
			SignatureWrapper wrapper = new SignatureWrapper(typeSignature);
296
			if (wrapper.signature[wrapper.start] == '<') {
297
				// ParameterPart = '<' ParameterSignature(s) '>'
298
				wrapper.start++; // skip '<'
299
				this.typeVariables = createTypeVariables(wrapper, true, missingTypeNames);
300
				wrapper.start++; // skip '>'
301
				this.tagBits |=  TagBits.HasUnresolvedTypeVariables;
302
				this.modifiers |= ExtraCompilerModifiers.AccGenericSignature;
303
			}
304
			TypeVariableBinding[] typeVars = Binding.NO_TYPE_VARIABLES;
305
			char[] methodDescriptor = binaryType.getEnclosingMethod();
306
			if (methodDescriptor != null) {
307
				MethodBinding enclosingMethod = findMethod(methodDescriptor, missingTypeNames);
308
				typeVars = enclosingMethod.typeVariables;
309
			}
308
310
309
		this.superInterfaces = Binding.NO_SUPERINTERFACES;
311
			// attempt to find the superclass if it exists in the cache (otherwise - resolve it when requested)
310
		if (!wrapper.atEnd()) {
312
			this.superclass = (ReferenceBinding) environment.getTypeFromTypeSignature(wrapper, typeVars, this, missingTypeNames);
311
			// attempt to find each superinterface if it exists in the cache (otherwise - resolve it when requested)
313
			this.tagBits |= TagBits.HasUnresolvedSuperclass;
312
			java.util.ArrayList types = new java.util.ArrayList(2);
314
313
			do {
315
			this.superInterfaces = Binding.NO_SUPERINTERFACES;
314
				types.add(environment.getTypeFromTypeSignature(wrapper, Binding.NO_TYPE_VARIABLES, this, missingTypeNames));
316
			if (!wrapper.atEnd()) {
315
			} while (!wrapper.atEnd());
317
				// attempt to find each superinterface if it exists in the cache (otherwise - resolve it when requested)
316
			this.superInterfaces = new ReferenceBinding[types.size()];
318
				java.util.ArrayList types = new java.util.ArrayList(2);
317
			types.toArray(this.superInterfaces);
319
				do {
318
			this.tagBits |= TagBits.HasUnresolvedSuperinterfaces;
320
					types.add(environment.getTypeFromTypeSignature(wrapper, typeVars, this, missingTypeNames));
321
				} while (!wrapper.atEnd());
322
				this.superInterfaces = new ReferenceBinding[types.size()];
323
				types.toArray(this.superInterfaces);
324
				this.tagBits |= TagBits.HasUnresolvedSuperinterfaces;
325
			}
319
		}
326
		}
320
	}
321
327
322
	if (needFieldsAndMethods) {
328
		if (needFieldsAndMethods) {
323
		createFields(binaryType.getFields(), sourceLevel, missingTypeNames);
329
			createFields(binaryType.getFields(), sourceLevel, missingTypeNames);
324
		createMethods(binaryType.getMethods(), sourceLevel, missingTypeNames);
330
			createMethods(binaryType.getMethods(), sourceLevel, missingTypeNames);
325
	} else { // protect against incorrect use of the needFieldsAndMethods flag, see 48459
331
		}
326
		this.fields = Binding.NO_FIELDS;
332
		if (this.environment.globalOptions.storeAnnotations)
327
		this.methods = Binding.NO_METHODS;
333
			setAnnotations(createAnnotations(binaryType.getAnnotations(), this.environment, missingTypeNames));	
328
	}
334
	} finally {
329
	if (this.environment.globalOptions.storeAnnotations)
335
		// protect against incorrect use of the needFieldsAndMethods flag, see 48459
330
		setAnnotations(createAnnotations(binaryType.getAnnotations(), this.environment, missingTypeNames));	
336
		if (this.fields == null)
337
			this.fields = Binding.NO_FIELDS;
338
		if (this.methods == null)
339
			this.methods = Binding.NO_METHODS;
340
 	}
331
}
341
}
332
private void createFields(IBinaryField[] iFields, long sourceLevel, char[][][] missingTypeNames) {
342
private void createFields(IBinaryField[] iFields, long sourceLevel, char[][][] missingTypeNames) {
333
	this.fields = Binding.NO_FIELDS;
343
	this.fields = Binding.NO_FIELDS;
Lines 647-652 Link Here
647
	this.tagBits |= TagBits.AreFieldsComplete;
657
	this.tagBits |= TagBits.AreFieldsComplete;
648
	return fields;
658
	return fields;
649
}
659
}
660
private MethodBinding findMethod(char[] methodDescriptor, char[][][] missingTypeNames) {
661
	int index = -1;
662
	while (methodDescriptor[++index] != '(') {
663
		// empty
664
	}
665
	char[] selector = new char[index];
666
	System.arraycopy(methodDescriptor, 0, selector, 0, index);
667
	TypeBinding[] parameters = Binding.NO_PARAMETERS;
668
	int numOfParams = 0;
669
	char nextChar;
670
	while ((nextChar = methodDescriptor[++index]) != ')') {
671
		if (nextChar != '[') {
672
			numOfParams++;
673
			if (nextChar == 'L')
674
				while ((nextChar = methodDescriptor[++index]) != ';'){/*empty*/}
675
		}
676
	}
677
678
	int startIndex = 0;
679
	if (numOfParams > 0) {
680
		parameters = new TypeBinding[numOfParams];
681
		index = 1;
682
		int end = 0;   // first character is always '(' so skip it
683
		for (int i = 0; i < numOfParams; i++) {
684
			while ((nextChar = methodDescriptor[++end]) == '['){/*empty*/}
685
			if (nextChar == 'L')
686
				while ((nextChar = methodDescriptor[++end]) != ';'){/*empty*/}
687
688
			if (i >= startIndex) {   // skip the synthetic arg if necessary
689
				parameters[i - startIndex] = this.environment.getTypeFromSignature(methodDescriptor, index, end, false, this, missingTypeNames);
690
			}
691
			index = end + 1;
692
		}
693
	}
694
695
	return CharOperation.equals(selector, TypeConstants.INIT)
696
		? this.enclosingType.getExactConstructor(parameters)
697
		: this.enclosingType.getExactMethod(selector, parameters, null);
698
}
650
/**
699
/**
651
 * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#genericTypeSignature()
700
 * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#genericTypeSignature()
652
 */
701
 */
(-)model/org/eclipse/jdt/internal/core/hierarchy/HierarchyBinaryType.java (+3 lines)
Lines 51-56 Link Here
51
public IBinaryAnnotation[] getAnnotations() {
51
public IBinaryAnnotation[] getAnnotations() {
52
	return null;
52
	return null;
53
}
53
}
54
public char[] getEnclosingMethod() {
55
	return null;
56
}
54
/**
57
/**
55
 * Answer the resolved name of the enclosing type in the
58
 * Answer the resolved name of the enclosing type in the
56
 * class file format as specified in section 4.2 of the Java 2 VM spec
59
 * class file format as specified in section 4.2 of the Java 2 VM spec
(-)eval/org/eclipse/jdt/internal/eval/CodeSnippetSkeleton.java (+3 lines)
Lines 108-113 Link Here
108
public IBinaryAnnotation[] getAnnotations() {
108
public IBinaryAnnotation[] getAnnotations() {
109
	return null;
109
	return null;
110
}
110
}
111
public char[] getEnclosingMethod() {
112
	return null;
113
}
111
public char[] getEnclosingTypeName() {
114
public char[] getEnclosingTypeName() {
112
	return null;
115
	return null;
113
}
116
}
(-)compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java (-1 / +20 lines)
Lines 50-55 Link Here
50
	private long version;
50
	private long version;
51
	private char[] enclosingTypeName;
51
	private char[] enclosingTypeName;
52
	private char[][][] missingTypeNames;
52
	private char[][][] missingTypeNames;
53
	private int enclosingNameAndTypeIndex;
53
	
54
	
54
private static String printTypeModifiers(int modifiers) {
55
private static String printTypeModifiers(int modifiers) {
55
	java.io.ByteArrayOutputStream out = new java.io.ByteArrayOutputStream();
56
	java.io.ByteArrayOutputStream out = new java.io.ByteArrayOutputStream();
Lines 276-283 Link Here
276
				case 'E' :
277
				case 'E' :
277
					if (CharOperation.equals(attributeName, AttributeNamesConstants.EnclosingMethodName)) {
278
					if (CharOperation.equals(attributeName, AttributeNamesConstants.EnclosingMethodName)) {
278
						utf8Offset = 
279
						utf8Offset = 
279
							constantPoolOffsets[u2At(constantPoolOffsets[u2At(readOffset + 6)] - structOffset + 1)] - structOffset; 
280
							this.constantPoolOffsets[u2At(this.constantPoolOffsets[u2At(readOffset + 6)] + 1)];
280
						this.enclosingTypeName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
281
						this.enclosingTypeName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
282
						this.enclosingNameAndTypeIndex = u2At(readOffset + 8);
281
					}
283
					}
282
					break;
284
					break;
283
				case 'D' :
285
				case 'D' :
Lines 445-450 Link Here
445
	return this.constantPoolOffsets;
447
	return this.constantPoolOffsets;
446
}
448
}
447
449
450
public char[] getEnclosingMethod() {
451
	if (this.enclosingNameAndTypeIndex <= 0) {
452
		return null;
453
	}
454
	// read the name
455
	StringBuffer buffer = new StringBuffer();
456
	
457
	int nameAndTypeOffset = this.constantPoolOffsets[this.enclosingNameAndTypeIndex];
458
	int utf8Offset = this.constantPoolOffsets[u2At(nameAndTypeOffset + 1)];
459
	buffer.append(utf8At(utf8Offset + 3, u2At(utf8Offset + 1)));
460
461
	utf8Offset = this.constantPoolOffsets[u2At(nameAndTypeOffset + 3)];
462
	buffer.append(utf8At(utf8Offset + 3, u2At(utf8Offset + 1)));
463
464
	return String.valueOf(buffer).toCharArray();
465
}
466
448
/*
467
/*
449
 * Answer the resolved compoundName of the enclosing type
468
 * Answer the resolved compoundName of the enclosing type
450
 * or null if the receiver is a top level type.
469
 * or null if the receiver is a top level type.
(-)compiler/org/eclipse/jdt/internal/compiler/env/IBinaryType.java (+8 lines)
Lines 24-29 Link Here
24
24
25
IBinaryAnnotation[] getAnnotations();
25
IBinaryAnnotation[] getAnnotations();
26
/**
26
/**
27
 * Answer the enclosing method (including method selector and method descriptor), or
28
 * null if none.
29
 *
30
 * For example, "foo()Ljava/lang/Object;V"
31
 */
32
33
char[] getEnclosingMethod();
34
/**
27
 * Answer the resolved name of the enclosing type in the
35
 * Answer the resolved name of the enclosing type in the
28
 * class file format as specified in section 4.2 of the Java 2 VM spec
36
 * class file format as specified in section 4.2 of the Java 2 VM spec
29
 * or null if the receiver is a top level type.
37
 * or null if the receiver is a top level type.

Return to bug 266582