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

(-)buildnotes_jdt-core.html (-1 / +3 lines)
Lines 53-59 Link Here
53
</ul>
53
</ul>
54
54
55
<h3>Problem Reports Fixed</h3>
55
<h3>Problem Reports Fixed</h3>
56
<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=73671">73671</a>
56
<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=73277">73277</a>
57
[1.5][Search] Fields search does not work with generics
58
<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=73671">73671</a>
57
[1.5] Signature.getTypeArguments should also tolerate normal types
59
[1.5] Signature.getTypeArguments should also tolerate normal types
58
<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=73078">73078</a>
60
<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=73078">73078</a>
59
ISourceManipulation.delete() tries to run in WorkspaceRoot scheduling rule
61
ISourceManipulation.delete() tries to run in WorkspaceRoot scheduling rule
(-)model/org/eclipse/jdt/core/Signature.java (-7 / +35 lines)
Lines 1443-1449 Link Here
1443
 * @since 3.1
1443
 * @since 3.1
1444
 */
1444
 */
1445
public static char[][] getTypeArguments(char[] parameterizedTypeSignature) throws IllegalArgumentException {
1445
public static char[][] getTypeArguments(char[] parameterizedTypeSignature) throws IllegalArgumentException {
1446
	int start = CharOperation.indexOf(C_GENERIC_START, parameterizedTypeSignature);
1446
	int lastDot = CharOperation.lastIndexOf(C_DOT, parameterizedTypeSignature);
1447
	int start = lastDot == -1
1448
		? CharOperation.indexOf(C_GENERIC_START, parameterizedTypeSignature)
1449
		: CharOperation.indexOf(C_GENERIC_START, parameterizedTypeSignature, lastDot+1);
1447
	if (start == -1) 
1450
	if (start == -1) 
1448
		return CharOperation.NO_CHAR_CHAR;
1451
		return CharOperation.NO_CHAR_CHAR;
1449
	ArrayList args = new ArrayList();
1452
	ArrayList args = new ArrayList();
Lines 1492-1503 Link Here
1492
 * @since 3.1
1495
 * @since 3.1
1493
 */
1496
 */
1494
public static char[] getTypeErasure(char[] parameterizedTypeSignature) throws IllegalArgumentException {
1497
public static char[] getTypeErasure(char[] parameterizedTypeSignature) throws IllegalArgumentException {
1495
	int genericStart = CharOperation.indexOf(C_GENERIC_START, parameterizedTypeSignature);
1498
	int end = CharOperation.indexOf(C_GENERIC_START, parameterizedTypeSignature);
1496
	if (genericStart == -1) return parameterizedTypeSignature;
1499
	if (end == -1) return parameterizedTypeSignature;
1497
	char[] result = new char[genericStart+1];
1500
	int length = parameterizedTypeSignature.length;
1498
	System.arraycopy(parameterizedTypeSignature, 0, result, 0, genericStart);
1501
	char[] result = new char[length];
1499
	result[genericStart] = C_SEMICOLON;
1502
	int pos = 0;
1500
	return result;
1503
	int start = 0;
1504
	int deep= 0;
1505
	for (int idx=end; idx<length; idx++) {
1506
		switch (parameterizedTypeSignature[idx]) {
1507
			case C_GENERIC_START:
1508
				if (deep == 0) {
1509
					int size = idx-start;
1510
					System.arraycopy(parameterizedTypeSignature, start, result, pos, size);
1511
					end = idx;
1512
					pos += size;
1513
				}
1514
				deep++;
1515
				break;
1516
			case C_GENERIC_END:
1517
				deep--;
1518
				if (deep < 0) throw new IllegalArgumentException();
1519
				if (deep == 0) start = idx+1;
1520
				break;
1521
		}
1522
	}
1523
	if (deep > 0) throw new IllegalArgumentException();
1524
	int size = pos+length-start;
1525
	char[] resized = new char[size];
1526
	System.arraycopy(result, 0, resized, 0, pos);
1527
	System.arraycopy(parameterizedTypeSignature, start, resized, pos, length-start);
1528
	return resized;
1501
}
1529
}
1502
1530
1503
/**
1531
/**
(-)model/org/eclipse/jdt/internal/core/BinaryType.java (-1 / +2 lines)
Lines 466-472 Link Here
466
	return typeParameters;
466
	return typeParameters;
467
}
467
}
468
468
469
// SEARCH_15 Get type parameter names
469
// Get type parameter names
470
// TODO (frederic) see if this method needs to be added to API
470
public char[][] getTypeParameterNames() throws JavaModelException {
471
public char[][] getTypeParameterNames() throws JavaModelException {
471
	String[] typeParameterSignatures = getTypeParameterSignatures();
472
	String[] typeParameterSignatures = getTypeParameterSignatures();
472
	int length = typeParameterSignatures.length;
473
	int length = typeParameterSignatures.length;
(-)model/org/eclipse/jdt/internal/core/JavaProject.java (-1 / +1 lines)
Lines 127-133 Link Here
127
	/**
127
	/**
128
	 * Name of file containing custom project preferences
128
	 * Name of file containing custom project preferences
129
	 * @deprecated WARNING Visibility will be reduce to private before M9
129
	 * @deprecated WARNING Visibility will be reduce to private before M9
130
	 * 	If you use this variable, change your implementation to avoid future comilation error...
130
	 * 	If you use this variable, change your implementation to avoid future compilation error...
131
	 * @see <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=59258">bug 59258</a>
131
	 * @see <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=59258">bug 59258</a>
132
	 * TODO (frederic) set visibility from public to private
132
	 * TODO (frederic) set visibility from public to private
133
	 */
133
	 */
(-)model/org/eclipse/jdt/internal/core/SourceType.java (-1 / +2 lines)
Lines 407-413 Link Here
407
	return info.typeParameters;
407
	return info.typeParameters;
408
}
408
}
409
409
410
// SEARCH_15 Get type parameter names
410
// Get type parameter names
411
// TODO (frederic) see if this method needs to be added to API
411
public char[][] getTypeParameterNames() throws JavaModelException {
412
public char[][] getTypeParameterNames() throws JavaModelException {
412
	SourceTypeElementInfo info = (SourceTypeElementInfo) getElementInfo();
413
	SourceTypeElementInfo info = (SourceTypeElementInfo) getElementInfo();
413
	return info.getTypeParameterNames();
414
	return info.getTypeParameterNames();
(-)search/org/eclipse/jdt/core/search/SearchPattern.java (-36 / +54 lines)
Lines 752-760 Link Here
752
	 */
752
	 */
753
	/* (non-Javadoc) 
753
	/* (non-Javadoc) 
754
	 * SEARCH_15
754
	 * SEARCH_15
755
	 * 	Modified to handle generics.
755
	 * 	Modified to handle generics:
756
	 * 	Note that no change are done for declaration patterns as the search works well for generics
757
	 * 	without any additional information.
758
	 * 		1) Field defined on parameterized types
756
	 * 		1) Field defined on parameterized types
759
	 * 			In this case, we need to split the erasure name and type argument names.
757
	 * 			In this case, we need to split the erasure name and type argument names.
760
	 * 			Erasure name is used as type simple name and type argument names
758
	 * 			Erasure name is used as type simple name and type argument names
Lines 762-767 Link Here
762
	 * 		2) Generic types declaration
760
	 * 		2) Generic types declaration
763
	 * 			In this case, type arguments names are got from IType and stored
761
	 * 			In this case, type arguments names are got from IType and stored
764
	 * 			in instanciated type reference pattern.
762
	 * 			in instanciated type reference pattern.
763
	 * 	Note that no change was done for declaration patterns as the search works well for generics
764
	 * 	without any additional information.
765
	 */
765
	 */
766
	public static SearchPattern createPattern(IJavaElement element, int limitTo) {
766
	public static SearchPattern createPattern(IJavaElement element, int limitTo) {
767
		SearchPattern searchPattern = null;
767
		SearchPattern searchPattern = null;
Lines 779-806 Link Here
779
				char[] typeSimpleName;
779
				char[] typeSimpleName;
780
				char[] typeQualification;
780
				char[] typeQualification;
781
				char[][] typeNames = null;
781
				char[][] typeNames = null;
782
				int[] wildcards = null;
782
				try {
783
				try {
783
					char[] typeSignature = field.getTypeSignature().toCharArray();
784
					char[] typeSignature = field.getTypeSignature().toCharArray();
784
					// SEARCH_15 (start)
785
					char[] typeErasure = null;
785
					char[] typeErasure = null;
786
					if (CharOperation.indexOf(Signature.C_GENERIC_START, typeSignature) == -1) {
786
					if (CharOperation.indexOf(Signature.C_GENERIC_START, typeSignature) == -1) {
787
						typeErasure = Signature.toCharArray(typeSignature);
787
						typeErasure = Signature.toCharArray(typeSignature);
788
					} else {
788
					} else {
789
						typeErasure = Signature.toCharArray(Signature.getTypeErasure(typeSignature));
789
						typeErasure = Signature.toCharArray(Signature.getTypeErasure(typeSignature));
790
						CharOperation.replace(typeErasure, '$', '.');
790
						CharOperation.replace(typeErasure, '$', '.');
791
						if ((typeNames = Signature.getTypeArguments(typeSignature)) != null) {
791
						try {
792
							typeNames = Signature.getTypeArguments(typeSignature);
793
						}
794
						catch (IllegalArgumentException iae) {
795
							// do nothing
796
						}
797
						if (typeNames != null) {
792
							int length = typeNames.length;
798
							int length = typeNames.length;
799
							wildcards = new int[length];
793
							for (int i=0; i<length; i++) {
800
							for (int i=0; i<length; i++) {
794
								typeNames[i] = Signature.toCharArray(typeNames[i]);
801
								char[] typeName = typeNames[i];
802
								switch (typeName[0]) {
803
									case Signature.C_STAR:
804
										wildcards[i] = Wildcard.UNBOUND;
805
										break;
806
									case Signature.C_EXTENDS:
807
										wildcards[i] = Wildcard.EXTENDS;
808
										typeNames[i] = Signature.toCharArray(CharOperation.subarray(typeName, 1, typeName.length));
809
										break;
810
									case Signature.C_SUPER:
811
										wildcards[i] = Wildcard.SUPER;
812
										typeNames[i] = Signature.toCharArray(CharOperation.subarray(typeName, 1, typeName.length));
813
										break;
814
									default:
815
										wildcards[i] = -1;
816
										typeNames[i] = Signature.toCharArray(typeName);
817
										break;
818
								}
795
							}
819
							}
796
						}
820
						}
797
					}
821
					}
798
					// end
799
					if ((lastDot = CharOperation.lastIndexOf('.', typeErasure)) == -1) {
822
					if ((lastDot = CharOperation.lastIndexOf('.', typeErasure)) == -1) {
800
						typeSimpleName = typeErasure;
823
						typeSimpleName = typeErasure;
801
						typeQualification = null;
824
						typeQualification = null;
802
					} else {
825
					} else {
803
						typeSimpleName = CharOperation.subarray(typeErasure, 0, lastDot + 1);
826
						typeSimpleName = CharOperation.subarray(typeErasure, lastDot + 1, typeErasure.length);
804
						typeQualification = CharOperation.subarray(typeErasure, 0, lastDot);
827
						typeQualification = CharOperation.subarray(typeErasure, 0, lastDot);
805
						if (!field.isBinary()) {
828
						if (!field.isBinary()) {
806
							// prefix with a '*' as the full qualification could be bigger (because of an import)
829
							// prefix with a '*' as the full qualification could be bigger (because of an import)
Lines 823-828 Link Here
823
								typeQualification, 
846
								typeQualification, 
824
								typeSimpleName,
847
								typeSimpleName,
825
								typeNames,
848
								typeNames,
849
								wildcards,
826
								R_EXACT_MATCH | R_CASE_SENSITIVE);
850
								R_EXACT_MATCH | R_CASE_SENSITIVE);
827
						break;
851
						break;
828
					case IJavaSearchConstants.REFERENCES :
852
					case IJavaSearchConstants.REFERENCES :
Lines 837-842 Link Here
837
								typeQualification, 
861
								typeQualification, 
838
								typeSimpleName,
862
								typeSimpleName,
839
								typeNames,
863
								typeNames,
864
								wildcards,
840
								R_EXACT_MATCH | R_CASE_SENSITIVE);
865
								R_EXACT_MATCH | R_CASE_SENSITIVE);
841
						break;
866
						break;
842
					case IJavaSearchConstants.READ_ACCESSES :
867
					case IJavaSearchConstants.READ_ACCESSES :
Lines 851-856 Link Here
851
								typeQualification, 
876
								typeQualification, 
852
								typeSimpleName,
877
								typeSimpleName,
853
								typeNames,
878
								typeNames,
879
								wildcards,
854
								R_EXACT_MATCH | R_CASE_SENSITIVE);
880
								R_EXACT_MATCH | R_CASE_SENSITIVE);
855
						break;
881
						break;
856
					case IJavaSearchConstants.WRITE_ACCESSES :
882
					case IJavaSearchConstants.WRITE_ACCESSES :
Lines 865-870 Link Here
865
								typeQualification, 
891
								typeQualification, 
866
								typeSimpleName,
892
								typeSimpleName,
867
								typeNames,
893
								typeNames,
894
								wildcards,
868
								R_EXACT_MATCH | R_CASE_SENSITIVE);
895
								R_EXACT_MATCH | R_CASE_SENSITIVE);
869
						break;
896
						break;
870
					case IJavaSearchConstants.ALL_OCCURRENCES :
897
					case IJavaSearchConstants.ALL_OCCURRENCES :
Lines 879-884 Link Here
879
								typeQualification, 
906
								typeQualification, 
880
								typeSimpleName,
907
								typeSimpleName,
881
								typeNames,
908
								typeNames,
909
								wildcards,
882
								R_EXACT_MATCH | R_CASE_SENSITIVE);
910
								R_EXACT_MATCH | R_CASE_SENSITIVE);
883
						break;
911
						break;
884
				}
912
				}
Lines 896-905 Link Here
896
							elementName.substring(lastDot+1).toCharArray(),
924
							elementName.substring(lastDot+1).toCharArray(),
897
							elementName.substring(0, lastDot).toCharArray(),
925
							elementName.substring(0, lastDot).toCharArray(),
898
							null,
926
							null,
899
							// SEARCH_15 (start)
900
							null,
927
							null,
901
							false,
928
							false,
902
							// end
903
							limitTo);
929
							limitTo);
904
				}
930
				}
905
				break;
931
				break;
Lines 1092-1101 Link Here
1092
							type.getElementName().toCharArray(), 
1118
							type.getElementName().toCharArray(), 
1093
							type.getPackageFragment().getElementName().toCharArray(),
1119
							type.getPackageFragment().getElementName().toCharArray(),
1094
							enclosingTypeNames(type),
1120
							enclosingTypeNames(type),
1095
							// SEARCH_15 (start)
1096
							typeParameterNames(type),
1121
							typeParameterNames(type),
1097
							true, /* generic type */
1122
							true, /* generic type */
1098
							// end
1099
							limitTo);
1123
							limitTo);
1100
				break;
1124
				break;
1101
			case IJavaElement.PACKAGE_DECLARATION :
1125
			case IJavaElement.PACKAGE_DECLARATION :
Lines 1120-1130 Link Here
1120
				return new TypeReferencePattern(
1144
				return new TypeReferencePattern(
1121
					CharOperation.concatWith(packageName, enclosingTypeNames, '.'), 
1145
					CharOperation.concatWith(packageName, enclosingTypeNames, '.'), 
1122
					simpleName,
1146
					simpleName,
1123
					// SEARCH_15 (start)
1124
					typeNames,
1147
					typeNames,
1125
					generic,
1148
					generic,
1126
					null,
1149
					null,
1127
					// end
1128
					R_EXACT_MATCH | R_CASE_SENSITIVE);
1150
					R_EXACT_MATCH | R_CASE_SENSITIVE);
1129
			case IJavaSearchConstants.IMPLEMENTORS : 
1151
			case IJavaSearchConstants.IMPLEMENTORS : 
1130
				return new SuperTypeReferencePattern(
1152
				return new SuperTypeReferencePattern(
Lines 1143-1174 Link Here
1143
					new TypeReferencePattern(
1165
					new TypeReferencePattern(
1144
						CharOperation.concatWith(packageName, enclosingTypeNames, '.'), 
1166
						CharOperation.concatWith(packageName, enclosingTypeNames, '.'), 
1145
						simpleName,
1167
						simpleName,
1146
						// SEARCH_15 (start)
1147
						typeNames,
1168
						typeNames,
1148
						generic,
1169
						generic,
1149
						null,
1170
						null,
1150
						// end
1151
						R_EXACT_MATCH | R_CASE_SENSITIVE));
1171
						R_EXACT_MATCH | R_CASE_SENSITIVE));
1152
		}
1172
		}
1153
		return null;
1173
		return null;
1154
	}
1174
	}
1155
	/**
1175
	/**
1156
	 * Type pattern are formed by [qualification.]type
1176
	 * Type pattern are formed by [qualification.]type.
1157
	 * e.g. java.lang.Object
1177
	 * e.g. java.lang.Object
1158
	 *		Runnable
1178
	 *		Runnable
1159
	 */
1179
	 *
1160
	/* (non-Javadoc)
1180
	 * @since 3.1
1161
	 * SEARCH_15
1181
	 *		Type arguments can be specified to search references to parameterized types.
1162
	 * 	Modified to be able to identify type arguments in pattern
1182
	 * 	Then patterns will look as follow:
1163
	 * 	Note that:
1164
	 * 		1) '?' is understood as a wildcard when it is inside <>
1165
	 * 		2) '*' is not treated yet inside <>
1166
	 * 		3) that nested <> are not treated yet
1167
	 * 		4) that only one type arguments definition is allowed
1168
	 * 			(ie. Gen<Exception>.Member<Object> will be treated same as
1169
	 * 			 Gen<Exception>.Member pattern)
1170
	 * 	Using regexp syntax, we can described allowed patterns as:
1171
	 * 		[qualification.] type [ '<' [ [ '?' {'extends'|'super'} ] type ( ',' [ '?' {'extends'|'super'} ] type )* ] '>' ]
1183
	 * 		[qualification.] type [ '<' [ [ '?' {'extends'|'super'} ] type ( ',' [ '?' {'extends'|'super'} ] type )* ] '>' ]
1184
	 * 	Please note that:
1185
	 * 		- '*' is not valid inside type arguments definition <>
1186
	 * 		- '?' is treated as a wildcard when it is inside <> (ie. it must be put on first position of the type argument)
1187
	 * 		- nested <> are not allowed; List<List<Object>> will be treated as pattern List<List>
1188
	 * 		- only one type arguments definition is allowed; Gen<Exception>.Member<Object>
1189
	 *				will be treated as pattern Gen<Exception>.Member
1172
	 */
1190
	 */
1173
	private static SearchPattern createTypePattern(String patternString, int limitTo, int matchRule) {
1191
	private static SearchPattern createTypePattern(String patternString, int limitTo, int matchRule) {
1174
		
1192
		
Lines 1185-1198 Link Here
1185
		int parameterized = 0;
1203
		int parameterized = 0;
1186
		int paramPtr = -1;
1204
		int paramPtr = -1;
1187
		char[][] paramNames = null;
1205
		char[][] paramNames = null;
1188
		int[] wildcards = new int[10];
1206
		int[] wildcards = null;
1189
		while (token != TerminalTokens.TokenNameEOF) {
1207
		while (token != TerminalTokens.TokenNameEOF) {
1190
			if (token != TerminalTokens.TokenNameWHITESPACE) {
1208
			if (token != TerminalTokens.TokenNameWHITESPACE) {
1191
				if (storeParam) {
1209
				if (storeParam) {
1192
					switch (token) {
1210
					switch (token) {
1193
						case TerminalTokens.TokenNameMULTIPLY:
1211
						case TerminalTokens.TokenNameMULTIPLY:
1194
							if (parameterized > 0) {
1212
							if (parameterized > 0) {
1195
								// SEARCH_15 (frederic) Not treated yet...
1213
								// TODO (frederic) Should warn user that syntax is not valid
1196
							}
1214
							}
1197
							break;
1215
							break;
1198
						case TerminalTokens.TokenNameQUESTION:
1216
						case TerminalTokens.TokenNameQUESTION:
Lines 1200-1206 Link Here
1200
								if (wildcards[paramPtr] == -1) {
1218
								if (wildcards[paramPtr] == -1) {
1201
									wildcards[paramPtr] = Wildcard.UNBOUND;
1219
									wildcards[paramPtr] = Wildcard.UNBOUND;
1202
								} else {
1220
								} else {
1203
									// SEARCH_15 (frederic) Invalid syntax
1221
									// TODO (frederic) Should warn user that syntax is not valid
1204
								}
1222
								}
1205
							}
1223
							}
1206
							break;
1224
							break;
Lines 1209-1215 Link Here
1209
								if (wildcards[paramPtr] == Wildcard.UNBOUND) {
1227
								if (wildcards[paramPtr] == Wildcard.UNBOUND) {
1210
									wildcards[paramPtr] = Wildcard.EXTENDS;
1228
									wildcards[paramPtr] = Wildcard.EXTENDS;
1211
								} else {
1229
								} else {
1212
									// SEARCH_15 (frederic) Invalid syntax
1230
									// TODO (frederic) Should warn user that syntax is not valid
1213
								}
1231
								}
1214
							}
1232
							}
1215
							break;
1233
							break;
Lines 1218-1224 Link Here
1218
								if (wildcards[paramPtr] == Wildcard.UNBOUND) {
1236
								if (wildcards[paramPtr] == Wildcard.UNBOUND) {
1219
									wildcards[paramPtr] = Wildcard.SUPER;
1237
									wildcards[paramPtr] = Wildcard.SUPER;
1220
								} else {
1238
								} else {
1221
									// SEARCH_15 (frederic) Invalid syntax
1239
									// TODO (frederic) Should warn user that syntax is not valid
1222
								}
1240
								}
1223
							}
1241
							}
1224
							break;
1242
							break;
Lines 1236-1241 Link Here
1236
							if (parameterized == 0) {
1254
							if (parameterized == 0) {
1237
								paramNames = new char[10][]; // 10 parameters max
1255
								paramNames = new char[10][]; // 10 parameters max
1238
								paramPtr++;
1256
								paramPtr++;
1257
								wildcards = new int[10]; // 10 parameters max
1239
								wildcards[paramPtr] = -1;
1258
								wildcards[paramPtr] = -1;
1240
								storeType = false;
1259
								storeType = false;
1241
							}
1260
							}
Lines 1340-1347 Link Here
1340
		}
1359
		}
1341
	}
1360
	}
1342
	/**
1361
	/**
1343
	 * Returns the enclosing type names of the given type.
1362
	 * Returns the type parameter names of the given type.
1344
	 * TODO (frederic) Add-on for generic search
1345
	 */
1363
	 */
1346
	private static char[][] typeParameterNames(IType type) {
1364
	private static char[][] typeParameterNames(IType type) {
1347
		char[][] paramNames = null;
1365
		char[][] paramNames = null;
(-)search/org/eclipse/jdt/internal/core/search/matching/FieldLocator.java (-40 / +47 lines)
Lines 30-35 Link Here
30
30
31
	this.isDeclarationOfAccessedFieldsPattern = this.pattern instanceof DeclarationOfAccessedFieldsPattern;
31
	this.isDeclarationOfAccessedFieldsPattern = this.pattern instanceof DeclarationOfAccessedFieldsPattern;
32
}
32
}
33
/*
34
 * Get binding of type argument from an index position.
35
 * Delegate this search to the pattern which can cache results.
36
 */
37
protected TypeBinding getTypeNameBinding(int index) {
38
	return ((FieldPattern) this.pattern).getTypeNameBinding(this.unitScope, index);
39
}
33
//public int match(ASTNode node, MatchingNodeSet nodeSet) - SKIP IT
40
//public int match(ASTNode node, MatchingNodeSet nodeSet) - SKIP IT
34
//public int match(ConstructorDeclaration node, MatchingNodeSet nodeSet) - SKIP IT
41
//public int match(ConstructorDeclaration node, MatchingNodeSet nodeSet) - SKIP IT
35
public int match(FieldDeclaration node, MatchingNodeSet nodeSet) {
42
public int match(FieldDeclaration node, MatchingNodeSet nodeSet) {
Lines 84-130 Link Here
84
	// look at field type only if declaring type is not specified
91
	// look at field type only if declaring type is not specified
85
	if (fieldPattern.declaringSimpleName == null) return declaringLevel;
92
	if (fieldPattern.declaringSimpleName == null) return declaringLevel;
86
93
87
	int typeLevel = resolveLevelForType(fieldPattern.typeSimpleName, fieldPattern.typeQualification, field.type);
94
	// get real field binding
88
	
95
	FieldBinding fieldBinding = field;
89
		// SEARCH_15 (frederic) Specific field pattern verification for generics (not fully tested yet...)
96
	if (field instanceof ParameterizedFieldBinding) {
90
		if (typeLevel == IMPOSSIBLE_MATCH) {
97
		fieldBinding = ((ParameterizedFieldBinding) field).originalField;
91
			return IMPOSSIBLE_MATCH;
98
	}
92
		}
93
		TypeBinding typeBinding = field.type;
94
		if (typeBinding != null) {
95
			boolean isParameterized = typeBinding.isParameterizedType();
96
			boolean isRawType = typeBinding.isRawType();
97
			if (fieldPattern.typeNames== null) {
98
				if (isParameterized && !isRawType) return IMPOSSIBLE_MATCH;
99
			} else {
100
				if (!isParameterized) return IMPOSSIBLE_MATCH;
101
				ParameterizedTypeBinding paramTypeBinding = (ParameterizedTypeBinding) typeBinding;
102
				if (paramTypeBinding.arguments == null) {
103
					return IMPOSSIBLE_MATCH;
104
				}
105
				int length = fieldPattern.typeNames.length;
106
				if (paramTypeBinding.arguments.length != length) return IMPOSSIBLE_MATCH;
107
				for (int i= 0; i<length; i++) {
108
					char[] argType = fieldPattern.typeNames[i];
109
					TypeBinding argTypeBinding = paramTypeBinding.arguments[i];
110
					if (!CharOperation.equals(argType, argTypeBinding.shortReadableName(), fieldPattern.isCaseSensitive) &&
111
						!CharOperation.equals(argType, argTypeBinding.readableName(), fieldPattern.isCaseSensitive)) {
112
						return IMPOSSIBLE_MATCH;
113
					}
114
				}
115
			}
116
		}
117
		/* Try to pull-up generics verification in PatternLocator?
118
		int typeLevel = resolveLevelForType(
119
				fieldPattern.typeSimpleName,
120
				fieldPattern.typeQualification,
121
				fieldPattern.typeNames,
122
				fieldPattern.mustResolve(),
123
				true // parameterized,
124
				field.type);
125
		*/
126
		// end
127
99
100
	int typeLevel = resolveLevelForType(fieldBinding.type);
128
	return declaringLevel > typeLevel ? typeLevel : declaringLevel; // return the weaker match
101
	return declaringLevel > typeLevel ? typeLevel : declaringLevel; // return the weaker match
129
}
102
}
130
protected int matchReference(Reference node, MatchingNodeSet nodeSet, boolean writeOnlyAccess) {
103
protected int matchReference(Reference node, MatchingNodeSet nodeSet, boolean writeOnlyAccess) {
Lines 315-319 Link Here
315
		}
288
		}
316
	}
289
	}
317
	return IMPOSSIBLE_MATCH;
290
	return IMPOSSIBLE_MATCH;
291
}
292
/* (non-Javadoc)
293
 * Resolve level for type with a given binding.
294
 */
295
protected int resolveLevelForType(TypeBinding typeBinding) {
296
	FieldPattern fieldPattern = (FieldPattern) this.pattern;
297
	return resolveLevelForType(
298
			fieldPattern.typeSimpleName,
299
			fieldPattern.typeQualification,
300
			fieldPattern.typeNames,
301
			fieldPattern.wildcards,
302
			((InternalSearchPattern)this.pattern).mustResolve,
303
			fieldPattern.declaration,
304
			typeBinding);
305
}
306
/* (non-Javadoc)
307
 * Overrides PatternLocator method behavior in order to accept member pattern as X.Member
308
 * @see org.eclipse.jdt.internal.core.search.matching.PatternLocator#resolveLevelForType(char[], char[], org.eclipse.jdt.internal.compiler.lookup.TypeBinding)
309
 */
310
protected int resolveLevelForType (char[] simpleNamePattern, char[] qualificationPattern, TypeBinding type) {
311
	char[] qualifiedPattern = getQualifiedPattern(simpleNamePattern, qualificationPattern);
312
	int level = resolveLevelForType(qualifiedPattern, type);
313
	if (level == ACCURATE_MATCH || type == null) return level;
314
	boolean match = false;
315
	if (type.isMemberType() || type.isLocalType()) {
316
		if (qualificationPattern != null) {
317
			match = CharOperation.equals(qualifiedPattern, getQualifiedSourceName(type), this.isCaseSensitive);
318
		} else {
319
			match = CharOperation.equals(qualifiedPattern, type.sourceName(), this.isCaseSensitive);
320
		}
321
	} else if (qualificationPattern == null) {
322
		match = CharOperation.equals(qualifiedPattern, getQualifiedSourceName(type), this.isCaseSensitive);
323
	}
324
	return match ? ACCURATE_MATCH : IMPOSSIBLE_MATCH;
318
}
325
}
319
}
326
}
(-)search/org/eclipse/jdt/internal/core/search/matching/FieldPattern.java (-3 / +31 lines)
Lines 12-17 Link Here
12
12
13
import org.eclipse.jdt.core.compiler.CharOperation;
13
import org.eclipse.jdt.core.compiler.CharOperation;
14
import org.eclipse.jdt.core.search.SearchPattern;
14
import org.eclipse.jdt.core.search.SearchPattern;
15
import org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope;
16
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
15
import org.eclipse.jdt.internal.core.search.indexing.IIndexConstants;
17
import org.eclipse.jdt.internal.core.search.indexing.IIndexConstants;
16
18
17
public class FieldPattern extends VariablePattern implements IIndexConstants {
19
public class FieldPattern extends VariablePattern implements IIndexConstants {
Lines 24-31 Link Here
24
protected char[] typeQualification;
26
protected char[] typeQualification;
25
protected char[] typeSimpleName;
27
protected char[] typeSimpleName;
26
	
28
	
27
// SEARCH_15 Store type names
29
// Additional information for generics search
28
protected char[][] typeNames;
30
protected boolean declaration;	// show whether the search is based on a declaration or an instance
31
protected char[][] typeNames;	// type arguments names storage
32
protected TypeBinding[] typeBindings;	// cache for type arguments bindings
33
protected int[] wildcards;	// show wildcard kind for each type arguments
29
34
30
protected static char[][] REF_CATEGORIES = { REF };
35
protected static char[][] REF_CATEGORIES = { REF };
31
protected static char[][] REF_AND_DECL_CATEGORIES = { REF, FIELD_DECL };
36
protected static char[][] REF_AND_DECL_CATEGORIES = { REF, FIELD_DECL };
Lines 55-61 Link Here
55
60
56
	((InternalSearchPattern)this).mustResolve = mustResolve();
61
	((InternalSearchPattern)this).mustResolve = mustResolve();
57
}
62
}
58
// SEARCH_15 Create field pattern with generics additional information
63
/*
64
 * Instanciate a field pattern with additional information for generics search
65
 */
59
public FieldPattern(
66
public FieldPattern(
60
	boolean findDeclarations,
67
	boolean findDeclarations,
61
	boolean readAccess,
68
	boolean readAccess,
Lines 66-71 Link Here
66
	char[] typeQualification, 
73
	char[] typeQualification, 
67
	char[] typeSimpleName,
74
	char[] typeSimpleName,
68
	char[][] typeNames,
75
	char[][] typeNames,
76
	int[] wildcards,
69
	int matchRule) {
77
	int matchRule) {
70
78
71
	this(findDeclarations, readAccess, writeAccess, name, declaringQualification, declaringSimpleName, typeQualification, typeSimpleName, matchRule);
79
	this(findDeclarations, readAccess, writeAccess, name, declaringQualification, declaringSimpleName, typeQualification, typeSimpleName, matchRule);
Lines 73-78 Link Here
73
	if (typeNames != null) {
81
	if (typeNames != null) {
74
		this.typeNames= typeNames;
82
		this.typeNames= typeNames;
75
	}
83
	}
84
	this.wildcards = wildcards;
76
}
85
}
77
public void decodeIndexKey(char[] key) {
86
public void decodeIndexKey(char[] key) {
78
	this.name = key;
87
	this.name = key;
Lines 89-94 Link Here
89
	if (this.findDeclarations)
98
	if (this.findDeclarations)
90
		return DECL_CATEGORIES;
99
		return DECL_CATEGORIES;
91
	return CharOperation.NO_CHAR_CHAR;
100
	return CharOperation.NO_CHAR_CHAR;
101
}
102
/*
103
 * Get binding of type argument from a class unit scope and its index position.
104
 * Cache is lazy initialized and if no binding is found, then store a problem binding
105
 * to avoid making research twice...
106
 */
107
protected TypeBinding getTypeNameBinding(CompilationUnitScope unitScope, int index) {
108
	int length = this.typeNames.length;
109
	if (this.typeBindings == null) this.typeBindings = new TypeBinding[length];
110
	if (index <0 || index > length) return null;
111
	TypeBinding typeBinding = this.typeBindings[index];
112
	if (typeBinding == null) {
113
		typeBinding = unitScope.getType(this.typeNames[index]);
114
		this.typeBindings[index] = typeBinding;
115
	} 
116
	if (!typeBinding.isValidBinding()) {
117
		typeBinding = null;
118
	}
119
	return typeBinding;
92
}
120
}
93
public boolean matchesDecodedKey(SearchPattern decodedPattern) {
121
public boolean matchesDecodedKey(SearchPattern decodedPattern) {
94
	return true; // index key is not encoded so query results all match
122
	return true; // index key is not encoded so query results all match
(-)search/org/eclipse/jdt/internal/core/search/matching/MatchLocator.java (-13 / +14 lines)
Lines 58-65 Link Here
58
public SearchRequestor requestor;
58
public SearchRequestor requestor;
59
public IJavaSearchScope scope;
59
public IJavaSearchScope scope;
60
public IProgressMonitor progressMonitor;
60
public IProgressMonitor progressMonitor;
61
// SEARCH_15
62
public CompilationUnitScope unitScope;
63
61
64
public org.eclipse.jdt.core.ICompilationUnit[] workingCopies;
62
public org.eclipse.jdt.core.ICompilationUnit[] workingCopies;
65
public HandleFactory handleFactory;
63
public HandleFactory handleFactory;
Lines 1286-1292 Link Here
1286
}
1284
}
1287
1285
1288
/**
1286
/**
1289
 * SEARCH_15
1287
 * @since 3.1
1290
 * Finds the accurate positions of the sequence of tokens given by qualifiedName
1288
 * Finds the accurate positions of the sequence of tokens given by qualifiedName
1291
 * in the source and reports a reference to this this qualified name
1289
 * in the source and reports a reference to this this qualified name
1292
 * to the search requestor.
1290
 * to the search requestor.
Lines 1316-1326 Link Here
1316
		if (token == TerminalTokens.TokenNameIdentifier && this.pattern.matchesName(name, scanner.getCurrentTokenSource())) {
1314
		if (token == TerminalTokens.TokenNameIdentifier && this.pattern.matchesName(name, scanner.getCurrentTokenSource())) {
1317
			// extends selection end for parameterized types if necessary
1315
			// extends selection end for parameterized types if necessary
1318
			try {
1316
			try {
1319
				while (token != TerminalTokens.TokenNameGREATER) {
1317
				int count = 0;
1318
				while (token != TerminalTokens.TokenNameGREATER || count > 0) {
1320
					token = scanner.getNextToken();
1319
					token = scanner.getNextToken();
1321
					if (token == TerminalTokens.TokenNameEOF) {
1320
					switch (token) {
1322
						// TODO (search-frederic) Abnormal end of file, perhaps trace something in DEBUG
1321
						case TerminalTokens.TokenNameLESS:
1323
						return;
1322
							count++;
1323
							break;
1324
						case TerminalTokens.TokenNameGREATER:
1325
							count--;
1326
							break;
1327
						case TerminalTokens.TokenNameEOF:
1328
							return;
1324
					}
1329
					}
1325
				}
1330
				}
1326
			} catch (InvalidInputException e1) {
1331
			} catch (InvalidInputException e1) {
Lines 1487-1501 Link Here
1487
}
1492
}
1488
/**
1493
/**
1489
 * Visit the given resolved parse tree and report the nodes that match the search pattern.
1494
 * Visit the given resolved parse tree and report the nodes that match the search pattern.
1490
 * SEARCH_15
1491
 * 	Add unit scope storage in pattern locator. This will allow some additional verification
1492
 * 	while resolving levels of type arguments.
1493
 */
1495
 */
1494
protected void reportMatching(CompilationUnitDeclaration unit, boolean mustResolve) throws CoreException {
1496
protected void reportMatching(CompilationUnitDeclaration unit, boolean mustResolve) throws CoreException {
1495
	MatchingNodeSet nodeSet = this.currentPossibleMatch.nodeSet;
1497
	MatchingNodeSet nodeSet = this.currentPossibleMatch.nodeSet;
1496
	if (mustResolve) {
1498
	if (mustResolve) {
1497
		this.unitScope = unit.scope.compilationUnitScope();
1499
		CompilationUnitScope unitScope= unit.scope.compilationUnitScope();
1498
		this.patternLocator.unitScope = this.unitScope;
1500
		this.patternLocator.unitScope = unitScope;
1499
		// move the possible matching nodes that exactly match the search pattern to the matching nodes set
1501
		// move the possible matching nodes that exactly match the search pattern to the matching nodes set
1500
		Object[] nodes = nodeSet.possibleMatchingNodesSet.values;
1502
		Object[] nodes = nodeSet.possibleMatchingNodesSet.values;
1501
		for (int i = 0, l = nodes.length; i < l; i++) {
1503
		for (int i = 0, l = nodes.length; i < l; i++) {
Lines 1516-1522 Link Here
1516
		}
1518
		}
1517
		nodeSet.possibleMatchingNodesSet = new SimpleSet(3);
1519
		nodeSet.possibleMatchingNodesSet = new SimpleSet(3);
1518
	} else {
1520
	} else {
1519
		this.unitScope = null;
1520
		this.patternLocator.unitScope = null;
1521
		this.patternLocator.unitScope = null;
1521
	}
1522
	}
1522
1523
(-)search/org/eclipse/jdt/internal/core/search/matching/PatternLocator.java (-1 / +206 lines)
Lines 22-28 Link Here
22
22
23
protected int matchMode;
23
protected int matchMode;
24
protected boolean isCaseSensitive;
24
protected boolean isCaseSensitive;
25
// SEARCH_15
26
protected CompilationUnitScope unitScope;
25
protected CompilationUnitScope unitScope;
27
26
28
/* match levels */
27
/* match levels */
Lines 92-97 Link Here
92
	this.isCaseSensitive = (matchRule & SearchPattern.R_CASE_SENSITIVE) != 0;
91
	this.isCaseSensitive = (matchRule & SearchPattern.R_CASE_SENSITIVE) != 0;
93
	this.matchMode = matchRule - (this.isCaseSensitive ? SearchPattern.R_CASE_SENSITIVE : 0);
92
	this.matchMode = matchRule - (this.isCaseSensitive ? SearchPattern.R_CASE_SENSITIVE : 0);
94
}
93
}
94
/* (non-Javadoc)
95
 * Modify PatternLocator.qualifiedPattern behavior:
96
 * do not add star before simple name pattern when qualification pattern is null.
97
 * This avoid to match p.X when pattern is only X...
98
 */
99
protected char[] getQualifiedPattern(char[] simpleNamePattern, char[] qualificationPattern) {
100
	// NOTE: if case insensitive search then simpleNamePattern & qualificationPattern are assumed to be lowercase
101
	if (simpleNamePattern == null) {
102
		if (qualificationPattern == null) return null;
103
		return CharOperation.concat(qualificationPattern, ONE_STAR, '.');
104
	} else if (qualificationPattern == null) {
105
		return simpleNamePattern;
106
	} else {
107
		return CharOperation.concat(qualificationPattern, simpleNamePattern, '.');
108
	}
109
}
110
/* (non-Javadoc)
111
 * Modify PatternLocator.qualifiedSourceName behavior:
112
 * also concatene enclosing type name when type is a only a member type.
113
 */
114
protected char[] getQualifiedSourceName(TypeBinding binding) {
115
	if (binding instanceof ReferenceBinding) {
116
		ReferenceBinding type = (ReferenceBinding) binding;
117
		if (type.isLocalType()) {
118
			return CharOperation.concat(qualifiedSourceName(type.enclosingType()), new char[] {'.', '1', '.'}, type.sourceName());
119
		} else if (type.isMemberType()) {
120
			return CharOperation.concat(qualifiedSourceName(type.enclosingType()), type.sourceName(), '.');
121
		}
122
	}
123
	return binding != null ? binding.qualifiedSourceName() : null;
124
}
125
/*
126
 * Get binding of type argument from a class unit scope and its index position.
127
 * Cache is lazy initialized and if no binding is found, then store a problem binding
128
 * to avoid making research twice...
129
 */
130
protected TypeBinding getTypeNameBinding(int index) {
131
	return null;
132
}
95
/**
133
/**
96
 * Initializes this search pattern so that polymorphic search can be performed.
134
 * Initializes this search pattern so that polymorphic search can be performed.
97
 */ 
135
 */ 
Lines 316-321 Link Here
316
	return CharOperation.match(qualifiedPattern, fullyQualifiedTypeName, this.isCaseSensitive)
354
	return CharOperation.match(qualifiedPattern, fullyQualifiedTypeName, this.isCaseSensitive)
317
		? ACCURATE_MATCH
355
		? ACCURATE_MATCH
318
		: IMPOSSIBLE_MATCH;
356
		: IMPOSSIBLE_MATCH;
357
}
358
/* (non-Javadoc)
359
 * Resolve level for type with a given binding with all pattern information.
360
 */
361
protected int resolveLevelForType (char[] simpleNamePattern,
362
									char[] qualificationPattern,
363
									char[][] typeNames,
364
									int[] wildcards,
365
									boolean mustResolve,
366
									boolean declaration,
367
									TypeBinding type) {
368
	// standard search with no generic additional information must succeed
369
	int level = resolveLevelForType(simpleNamePattern, qualificationPattern, type);
370
	if (level == IMPOSSIBLE_MATCH) return IMPOSSIBLE_MATCH;
371
	if (type == null) return level;
372
373
	// pattern has no type parameter, return standard result
374
	if (typeNames == null || typeNames.length == 0) {
375
		return level;
376
	}
377
	
378
	// pattern has type parameter(s) or type argument(s)
379
	boolean isRawType = type.isRawType();
380
	if (type.isGenericType()) {
381
		// Binding is generic, get its type variable(s)
382
		TypeVariableBinding[] typeVariables = null;
383
		if (type instanceof SourceTypeBinding) {
384
			SourceTypeBinding sourceTypeBinding = (SourceTypeBinding) type;
385
			typeVariables = sourceTypeBinding.typeVariables;
386
		} else if (type instanceof BinaryTypeBinding) {
387
			BinaryTypeBinding binaryTypeBinding = (BinaryTypeBinding) type;
388
			if (mustResolve)
389
				typeVariables = binaryTypeBinding.typeVariables(); // TODO (frederic) verify performance
390
		}
391
		// type variables length must match at least specified type names length
392
		if (typeVariables == null || typeVariables.length == 0) {
393
			return IMPOSSIBLE_MATCH;
394
		}
395
		int length = typeNames.length;
396
		if (typeVariables.length != length) return IMPOSSIBLE_MATCH;
397
		// TODO (frederic) do we need to verify each parameter?
398
		return level; // we can't do better
399
	} else if (!type.isParameterizedType() && !isRawType) {
400
		// Standard types (ie. neither generic nor parameterized nor raw types)
401
		// cannot match pattern with type parameters or arguments
402
		return IMPOSSIBLE_MATCH;
403
	} else {
404
		// Binding is parameterized type
405
		ParameterizedTypeBinding paramTypeBinding = (ParameterizedTypeBinding) type;
406
		if (paramTypeBinding.arguments == null) {
407
			// binding has no type parameters => ok for raw types
408
			if (isRawType) return level;
409
			// need to verify hierarchy for member types (raw type of generic member
410
			// are stored as parameterized types...)
411
			if (type.isMemberType() && qualificationPattern != null) {
412
				int lastDot = CharOperation.lastIndexOf('.', qualificationPattern);
413
				char[] enclosingQualificationPattern = lastDot==-1 ? null : CharOperation.subarray(qualificationPattern, 0, lastDot);
414
				char[] enclosingSimpleNamePattern = lastDot==-1 ? qualificationPattern : CharOperation.subarray(qualificationPattern, lastDot+1, qualificationPattern.length);
415
				if (resolveLevelForType(enclosingSimpleNamePattern, enclosingQualificationPattern, typeNames, wildcards, mustResolve, declaration, paramTypeBinding.enclosingType()) == IMPOSSIBLE_MATCH) {
416
					return IMPOSSIBLE_MATCH;
417
				}
418
				return level;
419
			}
420
			return IMPOSSIBLE_MATCH;
421
		}
422
423
		// type parameters length must match at least specified type names length
424
		int length = typeNames.length;
425
		if (paramTypeBinding.arguments.length != length) return IMPOSSIBLE_MATCH;
426
427
		// for generic type declaration, verification is different than for parameterized type
428
		if (declaration) {
429
			// TODO (frederic) more verification to do here with type parameter bounds?
430
			return level;
431
		}
432
433
		// verify each pattern type parameter
434
		nextTypeArgument: for (int i= 0; i<length; i++) {
435
			char[] argType = typeNames[i];
436
			TypeBinding argTypeBinding = paramTypeBinding.arguments[i];
437
			// get corresponding pattern wildcard
438
			int patternWildcard = wildcards == null ? -1 : wildcards[i];
439
			if (patternWildcard == Wildcard.UNBOUND) continue; // unbound parameter always match
440
441
			// try to resolve pattern
442
			TypeBinding patternBinding = getTypeNameBinding(i);
443
			if (patternBinding != null) {
444
				// We can bind pattern type name => verify that types are compatible
445
				if (argTypeBinding == patternBinding) continue;
446
				if (argTypeBinding.isWildcard()) {
447
					TypeBinding bound = ((WildcardBinding) argTypeBinding).bound;
448
					switch (patternWildcard) {
449
						case Wildcard.SUPER:
450
							if (bound == null || patternBinding.isCompatibleWith(bound))
451
								// argument type is in bound hierarchy => match
452
								continue;
453
							break;
454
						case Wildcard.EXTENDS:
455
							if (bound == null || bound.isCompatibleWith(patternBinding))
456
								// argument type is a subclass of bound => match
457
								continue;
458
							break;
459
						default: //UNBOUND
460
							// there's no bound name => match
461
							continue;
462
					}
463
				}
464
				return IMPOSSIBLE_MATCH;
465
			}
466
			
467
			// pattern hasn't be solved, try to see if names match in hierarchy
468
			// First if type argument is a wildcard
469
			if (argTypeBinding.isWildcard()) {
470
				WildcardBinding wildcardBinding = (WildcardBinding) argTypeBinding;
471
				switch (wildcardBinding.kind) {
472
					case Wildcard.EXTENDS:
473
						// We cannot know in this case...
474
						level = INACCURATE_MATCH;
475
					case Wildcard.UNBOUND:
476
						// there's no bound name to match => valid
477
						continue;
478
				}
479
				// try to match name in hierarchy
480
				ReferenceBinding boundBinding = (ReferenceBinding) wildcardBinding.bound;
481
				while (boundBinding != null) {
482
					if (CharOperation.equals(argType, boundBinding.shortReadableName(), this.isCaseSensitive) ||
483
						CharOperation.equals(argType, boundBinding.readableName(), this.isCaseSensitive)) {
484
						// found name in hierarchy => match
485
						continue nextTypeArgument;
486
					}
487
					boundBinding = boundBinding.superclass();
488
				}
489
				return IMPOSSIBLE_MATCH;
490
			}
491
			
492
			// try to match names when there's no wildcard
493
			// first get real binding
494
			ReferenceBinding refBinding = null;
495
			if (argTypeBinding.isArrayType()) {
496
				TypeBinding leafBinding = ((ArrayBinding) argTypeBinding).leafComponentType;
497
				if (!leafBinding.isBaseType()) {
498
					refBinding = (ReferenceBinding) leafBinding;
499
				}
500
			} else if (!argTypeBinding.isBaseType()) {
501
				refBinding = (ReferenceBinding) argTypeBinding;
502
			}
503
			// Compare name
504
			if (refBinding == null) {
505
				// Based type
506
				if (!CharOperation.equals(argType, argTypeBinding.shortReadableName(), this.isCaseSensitive) &&
507
					!CharOperation.equals(argType, argTypeBinding.readableName(), this.isCaseSensitive)) {
508
					return IMPOSSIBLE_MATCH;
509
				}
510
			} else {
511
				while (refBinding != null) {
512
					if (CharOperation.equals(argType, refBinding.shortReadableName(), this.isCaseSensitive) ||
513
						CharOperation.equals(argType, refBinding.readableName(), this.isCaseSensitive)) {
514
						// found name in hierarchy => match
515
						continue nextTypeArgument;
516
					}
517
					refBinding = refBinding.superclass();
518
				}
519
				return IMPOSSIBLE_MATCH;
520
			}
521
		}
522
		return level;
523
	}
319
}
524
}
320
public String toString(){
525
public String toString(){
321
	return "SearchPattern"; //$NON-NLS-1$
526
	return "SearchPattern"; //$NON-NLS-1$
(-)search/org/eclipse/jdt/internal/core/search/matching/TypeReferenceLocator.java (-198 / +14 lines)
Lines 31-67 Link Here
31
	this.pattern = pattern;
31
	this.pattern = pattern;
32
	this.isDeclarationOfReferencedTypesPattern = this.pattern instanceof DeclarationOfReferencedTypesPattern;
32
	this.isDeclarationOfReferencedTypesPattern = this.pattern instanceof DeclarationOfReferencedTypesPattern;
33
}
33
}
34
/* SEARCH_15 
35
 * Modify PatternLocator.qualifiedPattern behavior:
36
 * do not add star before simple name pattern when qualification pattern is null.
37
 * This avoid to match p.X when pattern is X...
38
 */
39
public static char[] qualifiedPattern(char[] simpleNamePattern, char[] qualificationPattern) {
40
	// NOTE: if case insensitive search then simpleNamePattern & qualificationPattern are assumed to be lowercase
41
	if (simpleNamePattern == null) {
42
		if (qualificationPattern == null) return null;
43
		return CharOperation.concat(qualificationPattern, ONE_STAR, '.');
44
	} else if (qualificationPattern == null) {
45
		return simpleNamePattern;
46
	} else {
47
		return CharOperation.concat(qualificationPattern, simpleNamePattern, '.');
48
	}
49
}
50
/* SEARCH_15 
51
 * Modify PatternLocator.qualifiedSourceName behavior:
52
 * concat enclosing type when type is a only a member type.
53
 */
54
public static char[] qualifiedSourceName(TypeBinding binding) {
55
	if (binding instanceof ReferenceBinding) {
56
		ReferenceBinding type = (ReferenceBinding) binding;
57
		if (type.isLocalType()) {
58
			return CharOperation.concat(qualifiedSourceName(type.enclosingType()), new char[] {'.', '1', '.'}, type.sourceName());
59
		} else if (type.isMemberType()) {
60
			return CharOperation.concat(qualifiedSourceName(type.enclosingType()), type.sourceName(), '.');
61
		}
62
	}
63
	return binding != null ? binding.qualifiedSourceName() : null;
64
}
65
protected IJavaElement findElement(IJavaElement element, int accuracy) {
34
protected IJavaElement findElement(IJavaElement element, int accuracy) {
66
	// need exact match to be able to open on type ref
35
	// need exact match to be able to open on type ref
67
	if (accuracy != SearchMatch.A_ACCURATE) return null;
36
	if (accuracy != SearchMatch.A_ACCURATE) return null;
Lines 72-77 Link Here
72
		element = element.getParent();
41
		element = element.getParent();
73
	return element;
42
	return element;
74
}
43
}
44
/*
45
 * Get binding of type argument from an index position.
46
 * Delegate this search to the pattern which can cache results.
47
 */
48
protected TypeBinding getTypeNameBinding(int index) {
49
	return this.pattern.getTypeNameBinding(this.unitScope, index);
50
}
75
public int match(ASTNode node, MatchingNodeSet nodeSet) { // interested in ImportReference
51
public int match(ASTNode node, MatchingNodeSet nodeSet) { // interested in ImportReference
76
	if (!(node instanceof ImportReference)) return IMPOSSIBLE_MATCH;
52
	if (!(node instanceof ImportReference)) return IMPOSSIBLE_MATCH;
77
53
Lines 144-150 Link Here
144
}
120
}
145
protected void matchReportImportRef(ImportReference importRef, Binding binding, IJavaElement element, int accuracy, MatchLocator locator) throws CoreException {
121
protected void matchReportImportRef(ImportReference importRef, Binding binding, IJavaElement element, int accuracy, MatchLocator locator) throws CoreException {
146
	if (this.pattern.shouldExtendSelection()) {
122
	if (this.pattern.shouldExtendSelection()) {
147
		// SEARCH_15 do not report import ref for generic patterns...
123
		// do not report import ref for generic patterns...
148
		return;
124
		return;
149
	}
125
	}
150
	if (this.isDeclarationOfReferencedTypesPattern) {
126
	if (this.isDeclarationOfReferencedTypesPattern) {
Lines 193-199 Link Here
193
			locator.report(match);
169
			locator.report(match);
194
		}
170
		}
195
	} else if (this.pattern.shouldExtendSelection() && arrayRef.resolvedType.isParameterizedType() && ((ParameterizedTypeBinding)arrayRef.resolvedType).arguments != null) {
171
	} else if (this.pattern.shouldExtendSelection() && arrayRef.resolvedType.isParameterizedType() && ((ParameterizedTypeBinding)arrayRef.resolvedType).arguments != null) {
196
		// SEARCH_15 specific report accurate match for parameterized types
172
		// specific report accurate match for parameterized types
197
		locator.reportAccurateParameterizedTypeReference(arrayRef, this.pattern.simpleName, element, accuracy);
173
		locator.reportAccurateParameterizedTypeReference(arrayRef, this.pattern.simpleName, element, accuracy);
198
	} else 
174
	} else 
199
		locator.reportAccurateTypeReference(arrayRef, this.pattern.simpleName, element, accuracy);
175
		locator.reportAccurateTypeReference(arrayRef, this.pattern.simpleName, element, accuracy);
Lines 287-293 Link Here
287
					int start = (int) ((positions[this.pattern.qualification == null ? lastIndex : 0]) >>> 32);
263
					int start = (int) ((positions[this.pattern.qualification == null ? lastIndex : 0]) >>> 32);
288
					int end = (int) positions[lastIndex];
264
					int end = (int) positions[lastIndex];
289
					if (this.pattern.shouldExtendSelection() && refBinding.isParameterizedType() && ((ParameterizedTypeBinding)refBinding).arguments != null) {
265
					if (this.pattern.shouldExtendSelection() && refBinding.isParameterizedType() && ((ParameterizedTypeBinding)refBinding).arguments != null) {
290
						// SEARCH_15 specific report accurate match for parameterized types
266
						// specific report accurate match for parameterized types
291
						locator.reportAccurateParameterizedTypeReference(qTypeRef, this.pattern.simpleName, element, accuracy);
267
						locator.reportAccurateParameterizedTypeReference(qTypeRef, this.pattern.simpleName, element, accuracy);
292
					} else {
268
					} else {
293
						SearchMatch match = locator.newTypeReferenceMatch(element, accuracy, start, end-start+1, qTypeRef);
269
						SearchMatch match = locator.newTypeReferenceMatch(element, accuracy, start, end-start+1, qTypeRef);
Lines 480-486 Link Here
480
		return resolveLevelForTypeOrEnclosingTypes(this.pattern.simpleName, this.pattern.qualification, typeBinding);
456
		return resolveLevelForTypeOrEnclosingTypes(this.pattern.simpleName, this.pattern.qualification, typeBinding);
481
}
457
}
482
/* (non-Javadoc)
458
/* (non-Javadoc)
483
 * SEARCH_15
484
 * Resolve level for type with a given binding.
459
 * Resolve level for type with a given binding.
485
 * This is just an helper to avoid call of method with all parameters...
460
 * This is just an helper to avoid call of method with all parameters...
486
 */
461
 */
Lines 489-677 Link Here
489
			this.pattern.simpleName,
464
			this.pattern.simpleName,
490
			this.pattern.qualification,
465
			this.pattern.qualification,
491
			this.pattern.typeNames,
466
			this.pattern.typeNames,
467
			this.pattern.wildcards,
492
			((InternalSearchPattern)this.pattern).mustResolve,
468
			((InternalSearchPattern)this.pattern).mustResolve,
493
			this.pattern.declaration,
469
			this.pattern.declaration,
494
			typeBinding);
470
			typeBinding);
495
}
471
}
496
/* (non-Javadoc)
472
/* (non-Javadoc)
497
 * SEARCH_15
498
 * Overrides PatternLocator method behavior in order to accept member pattern as X.Member
473
 * Overrides PatternLocator method behavior in order to accept member pattern as X.Member
499
 * @see org.eclipse.jdt.internal.core.search.matching.PatternLocator#resolveLevelForType(char[], char[], org.eclipse.jdt.internal.compiler.lookup.TypeBinding)
474
 * @see org.eclipse.jdt.internal.core.search.matching.PatternLocator#resolveLevelForType(char[], char[], org.eclipse.jdt.internal.compiler.lookup.TypeBinding)
500
 */
475
 */
501
protected int resolveLevelForType (char[] simpleNamePattern, char[] qualificationPattern, TypeBinding type) {
476
protected int resolveLevelForType (char[] simpleNamePattern, char[] qualificationPattern, TypeBinding type) {
502
	char[] qualifiedPattern = qualifiedPattern(simpleNamePattern, qualificationPattern);
477
	char[] qualifiedPattern = getQualifiedPattern(simpleNamePattern, qualificationPattern);
503
	int level = resolveLevelForType(qualifiedPattern, type);
478
	int level = resolveLevelForType(qualifiedPattern, type);
504
	if (level == ACCURATE_MATCH || type == null) return level;
479
	if (level == ACCURATE_MATCH || type == null) return level;
505
	boolean match = false;
480
	boolean match = false;
506
	if (type.isMemberType() || type.isLocalType()) {
481
	if (type.isMemberType() || type.isLocalType()) {
507
		if (qualificationPattern != null) {
482
		if (qualificationPattern != null) {
508
			match = CharOperation.equals(qualifiedPattern, qualifiedSourceName(type), this.isCaseSensitive);
483
			match = CharOperation.equals(qualifiedPattern, getQualifiedSourceName(type), this.isCaseSensitive);
509
		} else {
484
		} else {
510
			match = CharOperation.equals(qualifiedPattern, type.sourceName(), this.isCaseSensitive);
485
			match = CharOperation.equals(qualifiedPattern, type.sourceName(), this.isCaseSensitive);
511
		}
486
		}
512
	} else if (qualificationPattern == null) {
487
	} else if (qualificationPattern == null) {
513
		match = CharOperation.equals(qualifiedPattern, qualifiedSourceName(type), this.isCaseSensitive);
488
		match = CharOperation.equals(qualifiedPattern, getQualifiedSourceName(type), this.isCaseSensitive);
514
	}
489
	}
515
	return match ? ACCURATE_MATCH : IMPOSSIBLE_MATCH;
490
	return match ? ACCURATE_MATCH : IMPOSSIBLE_MATCH;
516
}
517
/* (non-Javadoc)
518
 * SEARCH_15
519
 * Resolve level for type with a given binding with all pattern information.
520
 */
521
protected int resolveLevelForType (char[] simpleNamePattern,
522
									char[] qualificationPattern,
523
									char[][] typeNames,
524
									boolean mustResolve,
525
									boolean declaration,
526
									TypeBinding type) {
527
	int level = resolveLevelForType(simpleNamePattern, qualificationPattern, type);
528
	if (level == IMPOSSIBLE_MATCH) return IMPOSSIBLE_MATCH;
529
	if (type == null) return level;
530
531
	// pattern has no type parameter
532
	if (typeNames == null || typeNames.length == 0) {
533
		return level;
534
	}
535
	
536
	// pattern has type parameter(s) or type argument(s)
537
	boolean isRawType = type.isRawType();
538
	if (type.isGenericType()) {
539
		// Binding is generic, get its type variable(s)
540
		TypeVariableBinding[] typeVariables = null;
541
		if (type instanceof SourceTypeBinding) {
542
			SourceTypeBinding sourceTypeBinding = (SourceTypeBinding) type;
543
			typeVariables = sourceTypeBinding.typeVariables;
544
		} else if (type instanceof BinaryTypeBinding) {
545
			BinaryTypeBinding binaryTypeBinding = (BinaryTypeBinding) type;
546
			if (mustResolve)
547
				typeVariables = binaryTypeBinding.typeVariables(); // TODO (frederic) do we really want to resolve?
548
		}
549
		// type variables length must match at least specified type names length
550
		if (typeVariables == null || typeVariables.length == 0) {
551
			return IMPOSSIBLE_MATCH;
552
		}
553
		int length = typeNames.length;
554
		if (typeVariables.length != length) return IMPOSSIBLE_MATCH;
555
		// verify each parameters
556
		return level; // we can't do better
557
		// TODO (frederic) need to do more verifications here?
558
	} else if (!type.isParameterizedType() && !isRawType) {
559
		// Standard types (ie. neither generic nor parameterized nor raw types)
560
		// cannot match pattern when it has type parameters or arguments
561
		return IMPOSSIBLE_MATCH;
562
	} else {
563
		// Binding is parameterized type
564
		ParameterizedTypeBinding paramTypeBinding = (ParameterizedTypeBinding) type;
565
		if (paramTypeBinding.arguments == null) {
566
			// binding has no type parameters => ok for raw types
567
			if (isRawType) return level;
568
			// need to verify hierarchy for member types
569
			if (type.isMemberType() && qualificationPattern != null) {
570
				int lastDot = CharOperation.lastIndexOf('.', qualificationPattern);
571
				char[] enclosingQualificationPattern = lastDot==-1 ? null : CharOperation.subarray(qualificationPattern, 0, lastDot);
572
				char[] enclosingSimpleNamePattern = lastDot==-1 ? qualificationPattern : CharOperation.subarray(qualificationPattern, lastDot+1, qualificationPattern.length);
573
				if (resolveLevelForType(enclosingSimpleNamePattern, enclosingQualificationPattern, typeNames, mustResolve, declaration, paramTypeBinding.enclosingType()) == IMPOSSIBLE_MATCH) {
574
					return IMPOSSIBLE_MATCH;
575
				}
576
				return level;
577
			}
578
			return IMPOSSIBLE_MATCH;
579
		}
580
		// type parameters length must match at least specified type names length
581
		int length = typeNames.length;
582
		if (paramTypeBinding.arguments.length != length) return IMPOSSIBLE_MATCH;
583
		// verify each type parameter
584
		if (declaration) {
585
			// TODO (frederic) more verification to do here with type parameter bounds?
586
			return level;
587
		}
588
		nextTypeArgument: for (int i= 0; i<length; i++) {
589
			char[] argType = typeNames[i];
590
			TypeBinding argTypeBinding = paramTypeBinding.arguments[i];
591
			// get pattern wildcard
592
			int patternWildcard = this.pattern.wildcards[i];
593
			if (patternWildcard == Wildcard.UNBOUND) continue;
594
			// try to resolve pattern
595
			TypeBinding patternBinding = this.pattern.getTypeNameBinding(this.unitScope, i);
596
			if (patternBinding != null) {
597
				// We can bind pattern type name => verify that types are compatible
598
				if (argTypeBinding == patternBinding) continue;
599
				if (argTypeBinding.isWildcard()) {
600
					TypeBinding bound = ((WildcardBinding) argTypeBinding).bound;
601
					if (this.pattern.wildcards != null) {
602
						switch (this.pattern.wildcards[i]) {
603
							case Wildcard.SUPER:
604
								if (bound == null || patternBinding.isCompatibleWith(bound))
605
									// argument type is in bound hierarchy => valid
606
									continue;
607
								break;
608
							case Wildcard.EXTENDS:
609
								if (bound == null || bound.isCompatibleWith(patternBinding))
610
									// argument type is a subclass of bound => valid
611
									continue;
612
								break;
613
							default: //UNBOUND
614
								// there's no bound name to match => valid
615
								continue;
616
						}
617
					}
618
				}
619
				return IMPOSSIBLE_MATCH;
620
			}
621
			
622
			// pattern hasn't be solved, try to see if names match in hierarchy
623
			// First if type argument is a wildcard
624
			if (argTypeBinding.isWildcard()) {
625
				WildcardBinding wildcardBinding = (WildcardBinding) argTypeBinding;
626
				switch (wildcardBinding.kind) {
627
					case Wildcard.EXTENDS:
628
						// We cannot know in this case...
629
						level = INACCURATE_MATCH;
630
					case Wildcard.UNBOUND:
631
						// there's no bound name to match => valid
632
						continue;
633
				}
634
				// try to match name in hierarchy
635
				ReferenceBinding boundBinding = (ReferenceBinding) wildcardBinding.bound;
636
				while (boundBinding != null) {
637
					if (CharOperation.equals(argType, boundBinding.shortReadableName(), this.isCaseSensitive) ||
638
						CharOperation.equals(argType, boundBinding.readableName(), this.isCaseSensitive)) {
639
						continue nextTypeArgument;
640
					}
641
					boundBinding = boundBinding.superclass();
642
				}
643
				return IMPOSSIBLE_MATCH;
644
			}
645
			
646
			// try to match names when there's no wildcard
647
			ReferenceBinding refBinding = null;
648
			if (argTypeBinding.isArrayType()) {
649
				TypeBinding leafBinding = ((ArrayBinding) argTypeBinding).leafComponentType;
650
				if (!leafBinding.isBaseType()) {
651
					refBinding = (ReferenceBinding) leafBinding;
652
				}
653
			} else if (!argTypeBinding.isBaseType()) {
654
				refBinding = (ReferenceBinding) argTypeBinding;
655
			}
656
			if (refBinding == null) {
657
				// Based type
658
				if (!CharOperation.equals(argType, argTypeBinding.shortReadableName(), this.isCaseSensitive) &&
659
					!CharOperation.equals(argType, argTypeBinding.readableName(), this.isCaseSensitive)) {
660
					return IMPOSSIBLE_MATCH;
661
				}
662
			} else {
663
				while (refBinding != null) {
664
					if (CharOperation.equals(argType, refBinding.shortReadableName(), this.isCaseSensitive) ||
665
						CharOperation.equals(argType, refBinding.readableName(), this.isCaseSensitive)) {
666
						continue nextTypeArgument;
667
					}
668
					refBinding = refBinding.superclass();
669
				}
670
				return IMPOSSIBLE_MATCH;
671
			}
672
		}
673
		return level;
674
	}
675
}
491
}
676
/**
492
/**
677
 * Returns whether the given type binding or one of its enclosing types
493
 * Returns whether the given type binding or one of its enclosing types
(-)search/org/eclipse/jdt/internal/core/search/matching/TypeReferencePattern.java (-10 / +7 lines)
Lines 13-20 Link Here
13
import org.eclipse.jdt.core.compiler.CharOperation;
13
import org.eclipse.jdt.core.compiler.CharOperation;
14
import org.eclipse.jdt.core.search.SearchPattern;
14
import org.eclipse.jdt.core.search.SearchPattern;
15
import org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope;
15
import org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope;
16
import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons;
17
import org.eclipse.jdt.internal.compiler.lookup.ProblemReferenceBinding;
18
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
16
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
19
import org.eclipse.jdt.internal.core.search.indexing.IIndexConstants;
17
import org.eclipse.jdt.internal.core.search.indexing.IIndexConstants;
20
18
Lines 23-29 Link Here
23
protected char[] qualification;
21
protected char[] qualification;
24
protected char[] simpleName;
22
protected char[] simpleName;
25
	
23
	
26
// SEARCH_15 Additional information for generics search
24
// Additional information for generics search
27
protected boolean declaration;	// show whether the search is based on a declaration or an instance
25
protected boolean declaration;	// show whether the search is based on a declaration or an instance
28
protected char[][] typeNames;	// type arguments names storage
26
protected char[][] typeNames;	// type arguments names storage
29
protected TypeBinding[] typeBindings;	// cache for type arguments bindings
27
protected TypeBinding[] typeBindings;	// cache for type arguments bindings
Lines 50-56 Link Here
50
48
51
	((InternalSearchPattern)this).mustResolve = true; // always resolve (in case of a simple name reference being a potential match)
49
	((InternalSearchPattern)this).mustResolve = true; // always resolve (in case of a simple name reference being a potential match)
52
}
50
}
53
// SEARCH_15 Instanciate a type reference pattern with additional information for generics search
51
/*
52
 * Instanciate a type reference pattern with additional information for generics search
53
 */
54
public TypeReferencePattern(char[] qualification, char[] simpleName, char[][] typeNames, boolean fromJavaElement, int[] wildcards, int matchRule) {
54
public TypeReferencePattern(char[] qualification, char[] simpleName, char[][] typeNames, boolean fromJavaElement, int[] wildcards, int matchRule) {
55
	this(qualification, simpleName,matchRule);
55
	this(qualification, simpleName,matchRule);
56
56
Lines 94-105 Link Here
94
	TypeBinding typeBinding = this.typeBindings[index];
94
	TypeBinding typeBinding = this.typeBindings[index];
95
	if (typeBinding == null) {
95
	if (typeBinding == null) {
96
		typeBinding = unitScope.getType(this.typeNames[index]);
96
		typeBinding = unitScope.getType(this.typeNames[index]);
97
		if (typeBinding == null) {
97
		this.typeBindings[index] = typeBinding;
98
			this.typeBindings[index] = new ProblemReferenceBinding(this.typeNames[index], ProblemReasons.NotFound);
98
	}
99
		} else {
99
	if (!typeBinding.isValidBinding()) {
100
			this.typeBindings[index] = typeBinding;
101
		}
102
	} else if (!typeBinding.isValidBinding()) {
103
		typeBinding = null;
100
		typeBinding = null;
104
	}
101
	}
105
	return typeBinding;
102
	return typeBinding;

Return to bug 73277