View | Details | Raw Unified | Return to bug 96761
Collapse All | Expand All

(-)search/org/eclipse/jdt/internal/core/search/matching/MatchLocator.java (-71 / +111 lines)
Lines 39-44 Link Here
39
import org.eclipse.jdt.internal.compiler.CompilationResult;
39
import org.eclipse.jdt.internal.compiler.CompilationResult;
40
import org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies;
40
import org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies;
41
import org.eclipse.jdt.internal.compiler.ast.*;
41
import org.eclipse.jdt.internal.compiler.ast.*;
42
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
42
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
43
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
43
import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException;
44
import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException;
44
import org.eclipse.jdt.internal.compiler.env.*;
45
import org.eclipse.jdt.internal.compiler.env.*;
Lines 401-436 Link Here
401
	}
402
	}
402
	return this.basicParser;
403
	return this.basicParser;
403
}
404
}
404
/**
405
 * Add the possibleMatch to the loop
406
 *  ->  build compilation unit declarations, their bindings and record their results.
407
 */
408
protected void parseAndBuildBindings(PossibleMatch possibleMatch, boolean mustResolve) {
409
	if (this.progressMonitor != null && this.progressMonitor.isCanceled())
410
		throw new OperationCanceledException();
411
412
	try {
413
		if (BasicSearchEngine.VERBOSE)
414
			System.out.println("Parsing " + possibleMatch.openable.toStringWithAncestors()); //$NON-NLS-1$
415
416
		this.parser.nodeSet = possibleMatch.nodeSet;
417
		CompilationResult unitResult = new CompilationResult(possibleMatch, 1, 1, this.options.maxProblemsPerUnit);
418
		CompilationUnitDeclaration parsedUnit = this.parser.dietParse(possibleMatch, unitResult);
419
		if (parsedUnit != null) {
420
			if (mustResolve && !parsedUnit.isEmpty())
421
				this.lookupEnvironment.buildTypeBindings(parsedUnit, null /*no access restriction*/);
422
423
			// add the possibleMatch with its parsedUnit to matchesToProcess
424
			possibleMatch.parsedUnit = parsedUnit;
425
			int size = this.matchesToProcess.length;
426
			if (this.numberOfMatches == size)
427
				System.arraycopy(this.matchesToProcess, 0, this.matchesToProcess = new PossibleMatch[size == 0 ? 1 : size * 2], 0, this.numberOfMatches);
428
			this.matchesToProcess[this.numberOfMatches++] = possibleMatch;
429
		}
430
	} finally {
431
		this.parser.nodeSet = null;
432
	}
433
}
434
/*
405
/*
435
 * Caches the given binary type in the lookup environment and returns it.
406
 * Caches the given binary type in the lookup environment and returns it.
436
 * Returns the existing one if already cached.
407
 * Returns the existing one if already cached.
Lines 732-738 Link Here
732
protected IType getFocusType() {
703
protected IType getFocusType() {
733
	return this.scope instanceof HierarchyScope ? ((HierarchyScope) this.scope).focusType : null;
704
	return this.scope instanceof HierarchyScope ? ((HierarchyScope) this.scope).focusType : null;
734
}
705
}
735
protected void getMethodBodies(CompilationUnitDeclaration unit) {
706
protected void getMethodBodies(CompilationUnitDeclaration unit, MatchingNodeSet nodeSet) {
736
	if (unit.ignoreMethodBodies) {
707
	if (unit.ignoreMethodBodies) {
737
		unit.ignoreFurtherInvestigation = true;
708
		unit.ignoreFurtherInvestigation = true;
738
		return; // if initial diet parse did not work, no need to dig into method bodies.
709
		return; // if initial diet parse did not work, no need to dig into method bodies.
Lines 751-757 Link Here
751
			char[] contents = compilationResult.compilationUnit.getContents();
722
			char[] contents = compilationResult.compilationUnit.getContents();
752
			this.parser.javadocParser.scanner.setSource(contents);
723
			this.parser.javadocParser.scanner.setSource(contents);
753
		}
724
		}
754
		this.parser.nodeSet = this.currentPossibleMatch.nodeSet;
725
		this.parser.nodeSet = nodeSet;
755
		this.parser.parseBodies(unit);
726
		this.parser.parseBodies(unit);
756
	} finally {
727
	} finally {
757
		this.parser.nodeSet = null;
728
		this.parser.nodeSet = null;
Lines 776-806 Link Here
776
	this.bindings.put(typeKey, typeBinding);
747
	this.bindings.put(typeKey, typeBinding);
777
	return typeBinding.isValidBinding() ? typeBinding : null;
748
	return typeBinding.isValidBinding() ? typeBinding : null;
778
}
749
}
779
public MethodBinding getMethodBinding(IMethod method) {
750
public MethodBinding getMethodBinding(MethodPattern methodPattern) {
780
	if (this.unitScope == null) return null;
751
	if (this.unitScope == null) return null;
781
	// Try to get binding from cache
752
	// Try to get binding from cache
782
	Binding binding = (Binding) this.bindings.get(method);
753
	Binding binding = (Binding) this.bindings.get(methodPattern);
783
	if (binding != null) {
754
	if (binding != null) {
784
		if (binding instanceof MethodBinding && binding.isValidBinding())
755
		if (binding instanceof MethodBinding && binding.isValidBinding())
785
			return (MethodBinding) binding;
756
			return (MethodBinding) binding;
786
		return null;
757
		return null;
787
	}
758
	}
788
	//	Get binding from unit scope
759
	//	Get binding from unit scope
789
	String typeName = method.getDeclaringType().getElementName();
760
	char[] typeName = PatternLocator.qualifiedPattern(methodPattern.declaringSimpleName, methodPattern.declaringQualification);
790
	TypeBinding declaringTypeBinding = getType(typeName, typeName.toCharArray());
761
	if (typeName == null) {
762
		if (methodPattern.declaringType == null) return null;
763
		typeName = methodPattern.declaringType.getFullyQualifiedName().toCharArray();
764
	}
765
	TypeBinding declaringTypeBinding = getType(typeName, typeName);
791
	if (declaringTypeBinding != null) {
766
	if (declaringTypeBinding != null) {
792
		if (declaringTypeBinding.isArrayType()) {
767
		if (declaringTypeBinding.isArrayType()) {
793
			declaringTypeBinding = declaringTypeBinding.leafComponentType();
768
			declaringTypeBinding = declaringTypeBinding.leafComponentType();
794
		}
769
		}
795
		if (!declaringTypeBinding.isBaseType()) {
770
		if (!declaringTypeBinding.isBaseType()) {
796
			String[] parameterTypes = method.getParameterTypes();
771
			char[][] parameterTypes = methodPattern.parameterSimpleNames;
772
			if (parameterTypes == null) return null;
797
			int paramTypeslength = parameterTypes.length;
773
			int paramTypeslength = parameterTypes.length;
798
			char[][] paramTypesChars = new char[paramTypeslength][];
799
			for (int i=0;  i<paramTypeslength; i++) {
800
				paramTypesChars[i] = Signature.toCharArray(parameterTypes[i].toCharArray());
801
			}
802
			ReferenceBinding referenceBinding = (ReferenceBinding) declaringTypeBinding;
774
			ReferenceBinding referenceBinding = (ReferenceBinding) declaringTypeBinding;
803
			MethodBinding[] methods = referenceBinding.getMethods(method.getElementName().toCharArray());
775
			MethodBinding[] methods = referenceBinding.getMethods(methodPattern.selector);
804
			int methodsLength = methods.length;
776
			int methodsLength = methods.length;
805
			TypeVariableBinding[] refTypeVariables = referenceBinding.typeVariables();
777
			TypeVariableBinding[] refTypeVariables = referenceBinding.typeVariables();
806
			int typeVarLength = refTypeVariables==null ? 0 : refTypeVariables.length;
778
			int typeVarLength = refTypeVariables==null ? 0 : refTypeVariables.length;
Lines 809-850 Link Here
809
				int paramLength = methodParameters==null ? 0 : methodParameters.length;
781
				int paramLength = methodParameters==null ? 0 : methodParameters.length;
810
				TypeVariableBinding[] methodTypeVariables = methods[i].typeVariables;
782
				TypeVariableBinding[] methodTypeVariables = methods[i].typeVariables;
811
				int methTypeVarLength = methodTypeVariables==null ? 0 : methodTypeVariables.length;
783
				int methTypeVarLength = methodTypeVariables==null ? 0 : methodTypeVariables.length;
812
				boolean found = paramLength == paramTypeslength;
784
				boolean found = false;
813
				if (found) {
785
				if (paramLength == paramTypeslength) {
814
					for (int p=0; found && p<paramLength; p++) {
786
					for (int p=0; p<paramLength; p++) {
815
						if (CharOperation.equals(methodParameters[p].erasure().shortReadableName(), paramTypesChars[p])) {
787
						if (CharOperation.equals(methodParameters[p].erasure().shortReadableName(), parameterTypes[p])) {
816
							// param erasure match
788
							// param erasure match
789
							found = true;
817
						} else {
790
						} else {
818
							// type variable
791
							// type variable
819
							boolean foundVar = true;
792
							found = false;
820
							for (int v=0; foundVar && v<typeVarLength; v++) {
793
							for (int v=0; v<typeVarLength; v++) {
821
								if (!CharOperation.equals(refTypeVariables[v].sourceName, paramTypesChars[p])) {
794
								if (!CharOperation.equals(refTypeVariables[v].sourceName, parameterTypes[p])) {
822
									foundVar = false;
795
									found = false;
796
									break;
823
								}
797
								}
798
								found = true;
824
							}
799
							}
825
							if (!foundVar) {
800
							if (!found) {
826
								foundVar = true;
801
								for (int v=0; v<methTypeVarLength; v++) {
827
								for (int v=0; foundVar && v<methTypeVarLength; v++) {
802
									if (!CharOperation.equals(methodTypeVariables[v].sourceName, parameterTypes[p])) {
828
									if (!CharOperation.equals(methodTypeVariables[v].sourceName, paramTypesChars[p])) {
803
										found = false;
829
										foundVar = false;
804
										break;
830
									}
805
									}
806
									found = true;
831
								}
807
								}
832
								if (!foundVar) found = false;
833
							}
808
							}
809
							if (!found) break;
834
						}
810
						}
835
					}
811
					}
836
				}
812
				}
837
				if (found) {
813
				if (found) {
838
					this.bindings.put(method, methods[i]);
814
					this.bindings.put(methodPattern, methods[i]);
839
					return methods[i];
815
					return methods[i];
840
				}
816
				}
841
			}
817
			}
842
//			methodBinding = referenceBinding.getExactMethod(method.getElementName().toCharArray(), parameters);
843
//			this.bindings.put(method, methodBinding);
844
//			return methodBinding;
845
		}
818
		}
846
	}
819
	}
847
	this.bindings.put(method, new ProblemMethodBinding(method.getElementName().toCharArray(), null, ProblemReasons.NotFound));
820
	this.bindings.put(methodPattern, new ProblemMethodBinding(methodPattern.selector, null, ProblemReasons.NotFound));
848
	return null;
821
	return null;
849
}
822
}
850
protected boolean hasAlreadyDefinedType(CompilationUnitDeclaration parsedUnit) {
823
protected boolean hasAlreadyDefinedType(CompilationUnitDeclaration parsedUnit) {
Lines 897-918 Link Here
897
	initialize(javaProject, length);
870
	initialize(javaProject, length);
898
871
899
	// create and resolve binding (equivalent to beginCompilation() in Compiler)
872
	// create and resolve binding (equivalent to beginCompilation() in Compiler)
900
	boolean mustResolve = ((InternalSearchPattern)this.pattern).mustResolve;
873
	boolean mustResolvePattern = ((InternalSearchPattern)this.pattern).mustResolve;
874
	boolean mustResolve = mustResolvePattern;
875
	this.patternLocator.mayBeGeneric = this.options.sourceLevel >= ClassFileConstants.JDK1_5;
901
	boolean bindingsWereCreated = mustResolve;
876
	boolean bindingsWereCreated = mustResolve;
902
	try {
877
	try {
903
		for (int i = start, maxUnits = start + length; i < maxUnits; i++) {
878
		for (int i = start, maxUnits = start + length; i < maxUnits; i++) {
904
			PossibleMatch possibleMatch = possibleMatches[i];
879
			PossibleMatch possibleMatch = possibleMatches[i];
905
			try {
880
			try {
906
				parseAndBuildBindings(possibleMatch, mustResolve);
881
				if (!parseAndBuildBindings(possibleMatch, mustResolvePattern)) continue;
907
				if (!mustResolve) {
882
				// Currently we only need to resolve over pattern flag if there's potential parameterized types
883
				if (this.patternLocator.mayBeGeneric) {
884
					// If pattern does not resolve then rely on possible match node set resolution
885
					// which may have been modified while locator was adding possible matches to it
886
					if (!mustResolvePattern && !mustResolve) {
887
						mustResolve = possibleMatch.nodeSet.mustResolve;
888
						bindingsWereCreated = mustResolve;
889
					}
890
				} else {
891
					// Reset matching node resolution with pattern one if there's no potential parameterized type
892
					// to minimize side effect on previous search behavior
893
					possibleMatch.nodeSet.mustResolve = mustResolvePattern;
894
				}
895
				// possible match node resolution has been merged with pattern one, so rely on it to know
896
				// whether we need to process compilation unit now or later
897
				if (!possibleMatch.nodeSet.mustResolve) {
908
					if (this.progressMonitor != null) {
898
					if (this.progressMonitor != null) {
909
						this.progressWorked++;
899
						this.progressWorked++;
910
						if ((this.progressWorked%this.progressStep)==0) this.progressMonitor.worked(this.progressStep);
900
						if ((this.progressWorked%this.progressStep)==0) this.progressMonitor.worked(this.progressStep);
911
					}
901
					}
912
					process(possibleMatch, bindingsWereCreated);
902
					process(possibleMatch, bindingsWereCreated);
903
					if (this.numberOfMatches>0 && this.matchesToProcess[this.numberOfMatches-1] == possibleMatch) {
904
						// forget last possible match as it was processed
905
						this.numberOfMatches--;
906
					}
913
				}
907
				}
914
			} finally {
908
			} finally {
915
				if (!mustResolve)
909
				if (!possibleMatch.nodeSet.mustResolve)
916
					possibleMatch.cleanUp();
910
					possibleMatch.cleanUp();
917
			}
911
			}
918
		}
912
		}
Lines 1094-1100 Link Here
1094
				}
1088
				}
1095
				previousJavaProject = javaProject;
1089
				previousJavaProject = javaProject;
1096
			}
1090
			}
1097
			matchSet.add(new PossibleMatch(this, resource, openable, searchDocument));
1091
			matchSet.add(new PossibleMatch(this, resource, openable, searchDocument, ((InternalSearchPattern) this.pattern).mustResolve));
1098
		}
1092
		}
1099
1093
1100
		// last project
1094
		// last project
Lines 1133-1139 Link Here
1133
		IJavaElement focus = ((InternalSearchPattern) searchPattern).focus;
1127
		IJavaElement focus = ((InternalSearchPattern) searchPattern).focus;
1134
		if (focus != null) {
1128
		if (focus != null) {
1135
			SearchDocument document = participant.getDocument(focus.getPath().toString());
1129
			SearchDocument document = participant.getDocument(focus.getPath().toString());
1136
			this.currentPossibleMatch = new PossibleMatch(this, focus.getResource(), null, document);
1130
			this.currentPossibleMatch = new PossibleMatch(this, focus.getResource(), null, document, ((InternalSearchPattern) searchPattern).mustResolve);
1137
			if (encloses(focus)) {
1131
			if (encloses(focus)) {
1138
				SearchMatch match = newDeclarationMatch(focus.getAncestor(IJavaElement.PACKAGE_FRAGMENT), null/*no binding*/, SearchMatch.A_ACCURATE, -1, -1);
1132
				SearchMatch match = newDeclarationMatch(focus.getAncestor(IJavaElement.PACKAGE_FRAGMENT), null/*no binding*/, SearchMatch.A_ACCURATE, -1, -1);
1139
				report(match);
1133
				report(match);
Lines 1174-1180 Link Here
1174
						if (resource == null) // case of a file in an external jar
1168
						if (resource == null) // case of a file in an external jar
1175
							resource = javaProject.getProject();
1169
							resource = javaProject.getProject();
1176
						SearchDocument document = participant.getDocument(resource.getFullPath().toString());
1170
						SearchDocument document = participant.getDocument(resource.getFullPath().toString());
1177
						this.currentPossibleMatch = new PossibleMatch(this, resource, null, document);
1171
						this.currentPossibleMatch = new PossibleMatch(this, resource, null, document, ((InternalSearchPattern) searchPattern).mustResolve);
1178
						try {
1172
						try {
1179
							if (encloses(pkg)) {
1173
							if (encloses(pkg)) {
1180
								SearchMatch match = newDeclarationMatch(pkg, null/*no binding*/, SearchMatch.A_ACCURATE, -1, -1);
1174
								SearchMatch match = newDeclarationMatch(pkg, null/*no binding*/, SearchMatch.A_ACCURATE, -1, -1);
Lines 1373-1378 Link Here
1373
	return newTypeReferenceMatch(enclosingElement, enclosingBinding, accuracy, reference.sourceStart, reference.sourceEnd-reference.sourceStart+1, reference);
1367
	return newTypeReferenceMatch(enclosingElement, enclosingBinding, accuracy, reference.sourceStart, reference.sourceEnd-reference.sourceStart+1, reference);
1374
}
1368
}
1375
1369
1370
/**
1371
 * Add the possibleMatch to the loop
1372
 *  ->  build compilation unit declarations, their bindings and record their results.
1373
 */
1374
protected boolean parseAndBuildBindings(PossibleMatch possibleMatch, boolean mustResolve) throws CoreException {
1375
	if (this.progressMonitor != null && this.progressMonitor.isCanceled())
1376
		throw new OperationCanceledException();
1377
1378
	try {
1379
		if (BasicSearchEngine.VERBOSE)
1380
			System.out.println("Parsing " + possibleMatch.openable.toStringWithAncestors()); //$NON-NLS-1$
1381
1382
		this.parser.nodeSet = possibleMatch.nodeSet;
1383
		CompilationResult unitResult = new CompilationResult(possibleMatch, 1, 1, this.options.maxProblemsPerUnit);
1384
		CompilationUnitDeclaration parsedUnit = this.parser.dietParse(possibleMatch, unitResult);
1385
		if (parsedUnit != null) {
1386
			if (!parsedUnit.isEmpty()) {
1387
				if (mustResolve) {
1388
					this.lookupEnvironment.buildTypeBindings(parsedUnit, null /*no access restriction*/);
1389
				}
1390
				if (hasAlreadyDefinedType(parsedUnit)) return false; // skip type has it is hidden so not visible
1391
				getMethodBodies(parsedUnit, possibleMatch.nodeSet);
1392
				if (this.patternLocator.mayBeGeneric && !mustResolve && possibleMatch.nodeSet.mustResolve) {
1393
					// special case: possible match node set force resolution although pattern does not
1394
					// => we need to build types for this compilation unit
1395
					this.lookupEnvironment.buildTypeBindings(parsedUnit, null /*no access restriction*/);
1396
				}
1397
			}
1398
	
1399
			// add the possibleMatch with its parsedUnit to matchesToProcess
1400
			possibleMatch.parsedUnit = parsedUnit;
1401
			int size = this.matchesToProcess.length;
1402
			if (this.numberOfMatches == size)
1403
				System.arraycopy(this.matchesToProcess, 0, this.matchesToProcess = new PossibleMatch[size == 0 ? 1 : size * 2], 0, this.numberOfMatches);
1404
			this.matchesToProcess[this.numberOfMatches++] = possibleMatch;
1405
		}
1406
	} finally {
1407
		this.parser.nodeSet = null;
1408
	}
1409
	return true;
1410
}
1376
/*
1411
/*
1377
 * Process a compilation unit already parsed and build.
1412
 * Process a compilation unit already parsed and build.
1378
 */
1413
 */
Lines 1391-1399 Link Here
1391
		}
1426
		}
1392
		if (hasAlreadyDefinedType(unit)) return; // skip type has it is hidden so not visible
1427
		if (hasAlreadyDefinedType(unit)) return; // skip type has it is hidden so not visible
1393
1428
1394
		getMethodBodies(unit);
1429
		// Move getMethodBodies to #parseAndBuildings(...) method to allow possible match resolution management
1430
		//getMethodBodies(unit);
1395
1431
1396
		boolean mustResolve = ((InternalSearchPattern)this.pattern).mustResolve;
1432
		boolean mustResolve = ((InternalSearchPattern)this.pattern).mustResolve || possibleMatch.nodeSet.mustResolve;
1397
		if (bindingsWereCreated &&  mustResolve) {
1433
		if (bindingsWereCreated &&  mustResolve) {
1398
			if (unit.types != null) {
1434
			if (unit.types != null) {
1399
				if (BasicSearchEngine.VERBOSE)
1435
				if (BasicSearchEngine.VERBOSE)
Lines 1773-1779 Link Here
1773
			if (encloses(enclosingElement)) {
1809
			if (encloses(enclosingElement)) {
1774
				int length = scanner.currentPosition - nameSourceStart;
1810
				int length = scanner.currentPosition - nameSourceStart;
1775
				SearchMatch match = this.patternLocator.newDeclarationMatch(method, enclosingElement, method.binding, accuracy, length, this);
1811
				SearchMatch match = this.patternLocator.newDeclarationMatch(method, enclosingElement, method.binding, accuracy, length, this);
1776
				report(match);
1812
				if (match != null) report(match);
1777
			}
1813
			}
1778
		}
1814
		}
1779
	}
1815
	}
Lines 1868-1873 Link Here
1868
 */
1904
 */
1869
protected void reportMatching(CompilationUnitDeclaration unit, boolean mustResolve) throws CoreException {
1905
protected void reportMatching(CompilationUnitDeclaration unit, boolean mustResolve) throws CoreException {
1870
	MatchingNodeSet nodeSet = this.currentPossibleMatch.nodeSet;
1906
	MatchingNodeSet nodeSet = this.currentPossibleMatch.nodeSet;
1907
	boolean locatorMustResolve = this.patternLocator.mustResolve;
1908
	if (nodeSet.mustResolve) this.patternLocator.mustResolve = true;
1871
	if (mustResolve) {
1909
	if (mustResolve) {
1872
		this.unitScope= unit.scope.compilationUnitScope();
1910
		this.unitScope= unit.scope.compilationUnitScope();
1873
		// move the possible matching nodes that exactly match the search pattern to the matching nodes set
1911
		// move the possible matching nodes that exactly match the search pattern to the matching nodes set
Lines 1950-1955 Link Here
1950
	
1988
	
1951
	// Clear handle cache
1989
	// Clear handle cache
1952
	this.methodHandles = null;
1990
	this.methodHandles = null;
1991
	this.bindings.removeKey(this.pattern);
1992
	this.patternLocator.mustResolve = locatorMustResolve;
1953
}
1993
}
1954
/**
1994
/**
1955
 * Visit the given field declaration and report the nodes that match exactly the
1995
 * Visit the given field declaration and report the nodes that match exactly the
(-)search/org/eclipse/jdt/internal/core/search/matching/MatchingNodeSet.java (+11 lines)
Lines 36-47 Link Here
36
static Integer ERASURE_MATCH = new Integer(SearchPattern.R_ERASURE_MATCH);
36
static Integer ERASURE_MATCH = new Integer(SearchPattern.R_ERASURE_MATCH);
37
37
38
/**
38
/**
39
 * Tell whether locators need to resolve or not for current matching node set.
40
 */
41
public boolean mustResolve;
42
43
/**
39
 * Set of possible matching ast nodes. They need to be resolved
44
 * Set of possible matching ast nodes. They need to be resolved
40
 * to determine if they really match the search pattern.
45
 * to determine if they really match the search pattern.
41
 */
46
 */
42
SimpleSet possibleMatchingNodesSet = new SimpleSet(7);
47
SimpleSet possibleMatchingNodesSet = new SimpleSet(7);
43
private HashtableOfLong possibleMatchingNodesKeys = new HashtableOfLong(7);
48
private HashtableOfLong possibleMatchingNodesKeys = new HashtableOfLong(7);
44
49
50
51
public MatchingNodeSet(boolean mustResolvePattern) {
52
	super();
53
	mustResolve = mustResolvePattern;
54
}
55
45
public int addMatch(ASTNode node, int matchLevel) {
56
public int addMatch(ASTNode node, int matchLevel) {
46
	switch (matchLevel) {
57
	switch (matchLevel) {
47
		case PatternLocator.INACCURATE_MATCH:
58
		case PatternLocator.INACCURATE_MATCH:
(-)search/org/eclipse/jdt/internal/core/search/matching/MethodLocator.java (-67 / +114 lines)
Lines 49-54 Link Here
49
		// inaccurate matches will be found
49
		// inaccurate matches will be found
50
	}
50
	}
51
}
51
}
52
/*
53
 * Return whether a method may override a method in super classes erasures or not.
54
 */
55
private boolean isErasureMethodOverride(ReferenceBinding type, MethodBinding method) {
56
	if (type == null) return false;
57
58
	// matches superclass
59
	if (!type.isInterface() && !CharOperation.equals(type.compoundName, TypeConstants.JAVA_LANG_OBJECT)) {
60
		ReferenceBinding superClass = type.superclass();
61
		if (superClass.isParameterizedType()) {
62
			TypeBinding erasure = ((ParameterizedTypeBinding)superClass).erasure();
63
			if (erasure instanceof ReferenceBinding) {
64
				MethodBinding[] methods = superClass.getMethods(this.pattern.selector);
65
				int length = methods.length;
66
				for (int i = 0; i<length; i++) {
67
					if (methods[i].areParametersEqual(method)) return true;
68
				}
69
			}
70
		}
71
		if (isErasureMethodOverride(superClass, method)) {
72
			return true;
73
		}
74
	}
75
76
	// matches interfaces
77
	ReferenceBinding[] interfaces = type.superInterfaces();
78
	if (interfaces == null) return false;
79
	int iLength = interfaces.length;
80
	for (int i = 0; i<iLength; i++) {
81
		if (interfaces[i].isParameterizedType()) {
82
			TypeBinding erasure = ((ParameterizedTypeBinding)interfaces[i]).erasure();
83
			if (erasure instanceof ReferenceBinding) {
84
				MethodBinding[] methods = ((ReferenceBinding)erasure).getMethods(this.pattern.selector);
85
				int length = methods.length;
86
				for (int j = 0; j<length; j++) {
87
					if (methods[i].areParametersEqual(method)) return true;
88
				}
89
			}
90
		}
91
		if (isErasureMethodOverride(interfaces[i], method)) {
92
			return true;
93
		}
94
	}
95
	return false;
96
}
97
/*
98
 * Return whether a type name is in pattern all super declaring types names.
99
 */
100
private boolean isTypeInSuperDeclaringTypeNames(char[][] typeName) {
101
	if (allSuperDeclaringTypeNames == null) return false;
102
	int length = allSuperDeclaringTypeNames.length;
103
	for (int i= 0; i<length; i++) {
104
		if (CharOperation.equals(allSuperDeclaringTypeNames[i], typeName)) {
105
			return true;
106
		}
107
	}
108
	return false;
109
}
52
/**
110
/**
53
 * Returns whether the code gen will use an invoke virtual for 
111
 * Returns whether the code gen will use an invoke virtual for 
54
 * this message send or not.
112
 * this message send or not.
Lines 85-100 Link Here
85
	if (!matchesName(this.pattern.selector, node.selector)) return IMPOSSIBLE_MATCH;
143
	if (!matchesName(this.pattern.selector, node.selector)) return IMPOSSIBLE_MATCH;
86
	
144
	
87
	// Verify parameters types
145
	// Verify parameters types
146
	boolean resolve = ((InternalSearchPattern)this.pattern).mustResolve;
88
	if (this.pattern.parameterSimpleNames != null) {
147
	if (this.pattern.parameterSimpleNames != null) {
89
		int length = this.pattern.parameterSimpleNames.length;
148
		int length = this.pattern.parameterSimpleNames.length;
90
		ASTNode[] args = node.arguments;
149
		ASTNode[] args = node.arguments;
91
		int argsLength = args == null ? 0 : args.length;
150
		int argsLength = args == null ? 0 : args.length;
92
		if (length != argsLength) return IMPOSSIBLE_MATCH;
151
		if (length != argsLength) return IMPOSSIBLE_MATCH;
93
		// Disable filter on argument syntax to allow generic type search.
152
		for (int i = 0; i < argsLength; i++) {
94
		// (see  bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=79990)
153
			if (!matchesTypeReference(this.pattern.parameterSimpleNames[i], ((Argument) args[i]).type)) {
95
		if (!this.pattern.mustResolveGeneric) {
154
				if (!((InternalSearchPattern)this.pattern).mustResolve) {
96
			for (int i = 0; i < argsLength; i++) {
155
					// Set resolution flag on node set in case of types was inferred in parameterized types from generic ones...
97
				if (!matchesTypeReference(this.pattern.parameterSimpleNames[i], ((Argument) args[i]).type)) return IMPOSSIBLE_MATCH;
156
				 	// (see  bugs https://bugs.eclipse.org/bugs/show_bug.cgi?id=79990, 96761, 96763)
157
					nodeSet.mustResolve = true;
158
					resolve = true;
159
				}
98
			}
160
			}
99
		}
161
		}
100
	}
162
	}
Lines 105-111 Link Here
105
	}
167
	}
106
168
107
	// Method declaration may match pattern
169
	// Method declaration may match pattern
108
	return nodeSet.addMatch(node, ((InternalSearchPattern)this.pattern).mustResolve ? POSSIBLE_MATCH : ACCURATE_MATCH);
170
	return nodeSet.addMatch(node, resolve ? POSSIBLE_MATCH : ACCURATE_MATCH);
109
}
171
}
110
public int match(MemberValuePair node, MatchingNodeSet nodeSet) {
172
public int match(MemberValuePair node, MatchingNodeSet nodeSet) {
111
	if (!this.pattern.findReferences) return IMPOSSIBLE_MATCH;
173
	if (!this.pattern.findReferences) return IMPOSSIBLE_MATCH;
Lines 163-169 Link Here
163
		super.matchLevelAndReportImportRef(importRef, binding, locator);
225
		super.matchLevelAndReportImportRef(importRef, binding, locator);
164
	}
226
	}
165
}
227
}
166
protected int matchMethod(MethodBinding method) {
228
protected int matchMethod(MethodBinding method, boolean skipImpossibleArg) {
167
	if (!matchesName(this.pattern.selector, method.selector)) return IMPOSSIBLE_MATCH;
229
	if (!matchesName(this.pattern.selector, method.selector)) return IMPOSSIBLE_MATCH;
168
230
169
	int level = ACCURATE_MATCH;
231
	int level = ACCURATE_MATCH;
Lines 205-214 Link Here
205
			}
267
			}
206
			if (level > newLevel) {
268
			if (level > newLevel) {
207
				if (newLevel == IMPOSSIBLE_MATCH) {
269
				if (newLevel == IMPOSSIBLE_MATCH) {
208
//					if (isErasureMatch) {
270
					if (skipImpossibleArg) {
209
//						return ERASURE_MATCH;
271
						// Do not consider match as impossible while finding declarations and source level >= 1.5
210
//					}
272
					 	// (see  bugs https://bugs.eclipse.org/bugs/show_bug.cgi?id=79990, 96761, 96763)
211
					return IMPOSSIBLE_MATCH;
273
						newLevel = level;
274
					} else {
275
						return IMPOSSIBLE_MATCH;
276
					}
212
				}
277
				}
213
				level = newLevel; // can only be downgraded
278
				level = newLevel; // can only be downgraded
214
			}
279
			}
Lines 218-271 Link Here
218
	return level;
283
	return level;
219
}
284
}
220
/**
285
/**
221
 * Return if pattern method may override a method in super classes
222
 * or or implement one in super interfaces of given type.
223
 * @param type
224
 * @return level
225
 */
226
int matchOverriddenMethod(ReferenceBinding type) {
227
	if (type == null) return INACCURATE_MATCH;
228
	int level = IMPOSSIBLE_MATCH;
229
230
	// matches superclass
231
	if (!type.isInterface() && !CharOperation.equals(type.compoundName, TypeConstants.JAVA_LANG_OBJECT)) {
232
		if (type.superclass().isParameterizedType()) {
233
			TypeBinding erasure = ((ParameterizedTypeBinding)type.superclass()).erasure();
234
			if (erasure instanceof ReferenceBinding) {
235
				MethodBinding[] methods = ((ReferenceBinding)erasure).getMethods(this.pattern.selector);
236
				int length = methods.length;
237
				for (int i = 0; i<length && level == IMPOSSIBLE_MATCH; i++) {
238
					level = matchMethod(methods[i]);
239
				}
240
				if (level != IMPOSSIBLE_MATCH) return level;
241
			}
242
		}
243
		level = matchOverriddenMethod(type.superclass());
244
		if (level != IMPOSSIBLE_MATCH) return level;
245
	}
246
247
	// matches interfaces
248
	ReferenceBinding[] interfaces = type.superInterfaces();
249
	if (interfaces == null) return INACCURATE_MATCH;
250
	int iLength = interfaces.length;
251
	for (int i = 0; i<iLength; i++) {
252
		if (interfaces[i].isParameterizedType()) {
253
			TypeBinding erasure = ((ParameterizedTypeBinding)interfaces[i]).erasure();
254
			if (erasure instanceof ReferenceBinding) {
255
				MethodBinding[] methods = ((ReferenceBinding)erasure).getMethods(this.pattern.selector);
256
				int mLength = methods.length;
257
				for (int j = 0; j<mLength && level == IMPOSSIBLE_MATCH; j++) {
258
					level = matchMethod(methods[j]);
259
				}
260
				if (level != IMPOSSIBLE_MATCH) return level;
261
			}
262
		}
263
		level = matchOverriddenMethod(interfaces[i]);
264
		if (level != IMPOSSIBLE_MATCH) return level;
265
	}
266
	return IMPOSSIBLE_MATCH;
267
}
268
/**
269
 * @see org.eclipse.jdt.internal.core.search.matching.PatternLocator#matchReportReference(org.eclipse.jdt.internal.compiler.ast.ASTNode, org.eclipse.jdt.core.IJavaElement, Binding, int, org.eclipse.jdt.internal.core.search.matching.MatchLocator)
286
 * @see org.eclipse.jdt.internal.core.search.matching.PatternLocator#matchReportReference(org.eclipse.jdt.internal.compiler.ast.ASTNode, org.eclipse.jdt.core.IJavaElement, Binding, int, org.eclipse.jdt.internal.core.search.matching.MatchLocator)
270
 */
287
 */
271
protected void matchReportReference(ASTNode reference, IJavaElement element, Binding elementBinding, int accuracy, MatchLocator locator) throws CoreException {
288
protected void matchReportReference(ASTNode reference, IJavaElement element, Binding elementBinding, int accuracy, MatchLocator locator) throws CoreException {
Lines 387-392 Link Here
387
protected int referenceType() {
404
protected int referenceType() {
388
	return IJavaElement.METHOD;
405
	return IJavaElement.METHOD;
389
}
406
}
407
public SearchMatch newDeclarationMatch(ASTNode reference, IJavaElement element, Binding elementBinding, int accuracy, int length, MatchLocator locator) {
408
	if (elementBinding != null) {
409
		MethodBinding methodBinding = (MethodBinding) elementBinding;
410
		// Redo arguments verif as in this case previous filter may accept different ones
411
		boolean equals = true;
412
		if (this.pattern.parameterSimpleNames != null) {
413
			int paramLength = this.pattern.parameterSimpleNames.length;
414
			for (int i=0; equals && i<paramLength; i++) {
415
				int level = resolveLevelForType(this.pattern.parameterSimpleNames[i], this.pattern.parameterQualifications[i], methodBinding.parameters[i]);
416
				if (level == IMPOSSIBLE_MATCH) equals = false;
417
			}
418
		}
419
		// If arguments are not equals then try to see if method arguments can match erasures in hierarchy
420
		if (!equals && this.pattern.findDeclarations && this.mayBeGeneric) {
421
			if (isErasureMethodOverride(methodBinding.declaringClass, methodBinding)) {
422
				return super.newDeclarationMatch(reference, element, elementBinding, accuracy, length, locator);
423
			}
424
			if (isTypeInSuperDeclaringTypeNames(methodBinding.declaringClass.compoundName)) {
425
				MethodBinding patternBinding = locator.getMethodBinding(this.pattern);
426
				if (patternBinding != null) {
427
					patternBinding = patternBinding.original();
428
					if (!isErasureMethodOverride(patternBinding.declaringClass, patternBinding)) {
429
						return null;
430
					}
431
				}
432
				return super.newDeclarationMatch(reference, element, elementBinding, accuracy, length, locator);
433
			}
434
			return null;
435
		}
436
	}
437
	return super.newDeclarationMatch(reference, element, elementBinding, accuracy, length, locator);
438
}
390
protected void reportDeclaration(MethodBinding methodBinding, MatchLocator locator, SimpleSet knownMethods) throws CoreException {
439
protected void reportDeclaration(MethodBinding methodBinding, MatchLocator locator, SimpleSet knownMethods) throws CoreException {
391
	ReferenceBinding declaringClass = methodBinding.declaringClass;
440
	ReferenceBinding declaringClass = methodBinding.declaringClass;
392
	IType type = locator.lookupType(declaringClass);
441
	IType type = locator.lookupType(declaringClass);
Lines 463-476 Link Here
463
	if (!(binding instanceof MethodBinding)) return IMPOSSIBLE_MATCH;
512
	if (!(binding instanceof MethodBinding)) return IMPOSSIBLE_MATCH;
464
513
465
	MethodBinding method = (MethodBinding) binding;
514
	MethodBinding method = (MethodBinding) binding;
466
	int methodLevel = matchMethod(method);
515
	boolean skipVerif = this.pattern.findDeclarations && this.mayBeGeneric;
516
	int methodLevel = matchMethod(method, skipVerif);
467
	if (methodLevel == IMPOSSIBLE_MATCH) {
517
	if (methodLevel == IMPOSSIBLE_MATCH) {
468
		if (method != method.original()) methodLevel = matchMethod(method.original());
518
		if (method != method.original()) methodLevel = matchMethod(method.original(), skipVerif);
469
		if (methodLevel == IMPOSSIBLE_MATCH) {
519
		if (methodLevel == IMPOSSIBLE_MATCH) {
470
			if (this.pattern.findDeclarations && this.pattern.mustResolveGeneric) {
520
			return IMPOSSIBLE_MATCH;
471
				methodLevel = matchOverriddenMethod(method.declaringClass);
472
			}
473
			if (methodLevel == IMPOSSIBLE_MATCH) return IMPOSSIBLE_MATCH;
474
		} else {
521
		} else {
475
			method = method.original();
522
			method = method.original();
476
		}
523
		}
Lines 503-511 Link Here
503
		return IMPOSSIBLE_MATCH;
550
		return IMPOSSIBLE_MATCH;
504
	}
551
	}
505
	
552
	
506
	int methodLevel = matchMethod(method);
553
	int methodLevel = matchMethod(method, false);
507
	if (methodLevel == IMPOSSIBLE_MATCH) {
554
	if (methodLevel == IMPOSSIBLE_MATCH) {
508
		if (method != method.original()) methodLevel = matchMethod(method.original());
555
		if (method != method.original()) methodLevel = matchMethod(method.original(), false);
509
		if (methodLevel == IMPOSSIBLE_MATCH) return IMPOSSIBLE_MATCH;
556
		if (methodLevel == IMPOSSIBLE_MATCH) return IMPOSSIBLE_MATCH;
510
		method = method.original();
557
		method = method.original();
511
	}
558
	}
(-)search/org/eclipse/jdt/internal/core/search/matching/MethodPattern.java (-23 lines)
Lines 36-42 Link Here
36
public char[][] parameterSimpleNames;
36
public char[][] parameterSimpleNames;
37
public int parameterCount;
37
public int parameterCount;
38
public int flags = 0;
38
public int flags = 0;
39
public boolean mustResolveGeneric = false;
40
39
41
// extra reference info
40
// extra reference info
42
protected IType declaringType;
41
protected IType declaringType;
Lines 181-208 Link Here
181
	// Store type signatures and arguments for method
180
	// Store type signatures and arguments for method
182
	methodArguments = extractMethodArguments(method);
181
	methodArguments = extractMethodArguments(method);
183
	if (hasMethodArguments())  ((InternalSearchPattern)this).mustResolve = true;
182
	if (hasMethodArguments())  ((InternalSearchPattern)this).mustResolve = true;
184
	
185
	// See if we must resolve specifically for generics
186
	if (parameterSimpleNames != null && parameterSimpleNames.length > 0) {
187
		int psLength = parameterSimpleNames.length;
188
		try {
189
			// Currently, we need to resolve for generic if one of method type argument
190
			// equals to one of declaring type type parameter
191
			ITypeParameter[] typeParameters = this.declaringType.getTypeParameters();
192
			if (typeParameters != null && typeParameters.length > 0) {
193
				int tpLength = typeParameters.length;
194
				for (int i=0; i<psLength && !this.mustResolveGeneric; i++) {
195
					for (int j=0; j<tpLength && !this.mustResolveGeneric; j++) {
196
						if (CharOperation.equals(parameterSimpleNames[i], typeParameters[j].getElementName().toCharArray())) {
197
							this.mustResolveGeneric = true;
198
						}
199
					}
200
				}
201
			}
202
		} catch (JavaModelException e) {
203
			// ignore
204
		}
205
	}
206
}
183
}
207
/*
184
/*
208
 * Instanciate a method pattern with signatures for generics search
185
 * Instanciate a method pattern with signatures for generics search
(-)search/org/eclipse/jdt/internal/core/search/matching/PatternLocator.java (+1 lines)
Lines 26-31 Link Here
26
protected boolean isEquivalentMatch;
26
protected boolean isEquivalentMatch;
27
protected boolean isErasureMatch;
27
protected boolean isErasureMatch;
28
protected boolean mustResolve;
28
protected boolean mustResolve;
29
protected boolean mayBeGeneric;
29
30
30
// match to report
31
// match to report
31
SearchMatch match = null;
32
SearchMatch match = null;
(-)search/org/eclipse/jdt/internal/core/search/matching/PossibleMatch.java (-2 / +2 lines)
Lines 33-43 Link Here
33
private String sourceFileName;
33
private String sourceFileName;
34
private char[] source;
34
private char[] source;
35
35
36
public PossibleMatch(MatchLocator locator, IResource resource, Openable openable, SearchDocument document) {
36
public PossibleMatch(MatchLocator locator, IResource resource, Openable openable, SearchDocument document, boolean mustResolve) {
37
	this.resource = resource;
37
	this.resource = resource;
38
	this.openable = openable;
38
	this.openable = openable;
39
	this.document = document;
39
	this.document = document;
40
	this.nodeSet = new MatchingNodeSet();
40
	this.nodeSet = new MatchingNodeSet(mustResolve);
41
	char[] qualifiedName = getQualifiedName();
41
	char[] qualifiedName = getQualifiedName();
42
	if (qualifiedName != null)
42
	if (qualifiedName != null)
43
		this.compoundName = CharOperation.splitOn('.', qualifiedName);
43
		this.compoundName = CharOperation.splitOn('.', qualifiedName);

Return to bug 96761