KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > core > search > matching > ClassFileMatchLocator


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.core.search.matching;
12
13 import org.eclipse.core.runtime.CoreException;
14 import org.eclipse.jdt.core.*;
15 import org.eclipse.jdt.core.compiler.CharOperation;
16 import org.eclipse.jdt.core.search.*;
17 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
18 import org.eclipse.jdt.internal.compiler.env.*;
19 import org.eclipse.jdt.internal.compiler.lookup.*;
20 import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
21 import org.eclipse.jdt.internal.core.*;
22 import org.eclipse.jdt.internal.core.search.indexing.IIndexConstants;
23
24 public class ClassFileMatchLocator implements IIndexConstants {
25
26 public static char[] convertClassFileFormat(char[] name) {
27     return CharOperation.replaceOnCopy(name, '/', '.');
28 }
29
30 private boolean checkDeclaringType(IBinaryType enclosingBinaryType, char[] simpleName, char[] qualification, boolean isCaseSensitive, boolean isCamelCase) {
31     if (simpleName == null && qualification == null) return true;
32     if (enclosingBinaryType == null) return true;
33
34     char[] declaringTypeName = convertClassFileFormat(enclosingBinaryType.getName());
35     return checkTypeName(simpleName, qualification, declaringTypeName, isCaseSensitive, isCamelCase);
36 }
37 private boolean checkParameters(char[] methodDescriptor, char[][] parameterSimpleNames, char[][] parameterQualifications, boolean isCaseSensitive, boolean isCamelCase) {
38     char[][] arguments = Signature.getParameterTypes(methodDescriptor);
39     int parameterCount = parameterSimpleNames.length;
40     if (parameterCount != arguments.length) return false;
41     for (int i = 0; i < parameterCount; i++)
42         if (!checkTypeName(parameterSimpleNames[i], parameterQualifications[i], Signature.toCharArray(arguments[i]), isCaseSensitive, isCamelCase))
43             return false;
44     return true;
45 }
46 private boolean checkTypeName(char[] simpleName, char[] qualification, char[] fullyQualifiedTypeName, boolean isCaseSensitive, boolean isCamelCase) {
47     // NOTE: if case insensitive then simpleName & qualification are assumed to be lowercase
48
char[] wildcardPattern = PatternLocator.qualifiedPattern(simpleName, qualification);
49     if (wildcardPattern == null) return true;
50     return CharOperation.match(wildcardPattern, fullyQualifiedTypeName, isCaseSensitive);
51 }
52 /**
53  * Locate declaration in the current class file. This class file is always in a jar.
54  */

55 public void locateMatches(MatchLocator locator, ClassFile classFile, IBinaryType info) throws CoreException {
56     // check class definition
57
SearchPattern pattern = locator.pattern;
58     BinaryType binaryType = (BinaryType) classFile.getType();
59     if (matchBinary(pattern, info, null)) {
60         binaryType = new ResolvedBinaryType((JavaElement) binaryType.getParent(), binaryType.getElementName(), binaryType.getKey());
61         locator.reportBinaryMemberDeclaration(null, binaryType, null, info, SearchMatch.A_ACCURATE);
62     }
63
64     int accuracy = SearchMatch.A_ACCURATE;
65     if (((InternalSearchPattern)pattern).mustResolve) {
66         try {
67             BinaryTypeBinding binding = locator.cacheBinaryType(binaryType, info);
68             if (binding != null) {
69                 // filter out element not in hierarchy scope
70
if (!locator.typeInHierarchy(binding)) return;
71
72                 MethodBinding[] methods = binding.methods();
73                 for (int i = 0, l = methods.length; i < l; i++) {
74                     MethodBinding method = methods[i];
75                     if (locator.patternLocator.resolveLevel(method) == PatternLocator.ACCURATE_MATCH) {
76                         char[] methodSignature = method.genericSignature();
77                         if (methodSignature == null) methodSignature = method.signature();
78                         IMethod methodHandle = binaryType.getMethod(
79                             new String JavaDoc(method.isConstructor() ? binding.compoundName[binding.compoundName.length-1] : method.selector),
80                             CharOperation.toStrings(Signature.getParameterTypes(convertClassFileFormat(methodSignature))));
81                         locator.reportBinaryMemberDeclaration(null, methodHandle, method, info, SearchMatch.A_ACCURATE);
82                     }
83                 }
84
85                 FieldBinding[] fields = binding.fields();
86                 for (int i = 0, l = fields.length; i < l; i++) {
87                     FieldBinding field = fields[i];
88                     if (locator.patternLocator.resolveLevel(field) == PatternLocator.ACCURATE_MATCH) {
89                         IField fieldHandle = binaryType.getField(new String JavaDoc(field.name));
90                         locator.reportBinaryMemberDeclaration(null, fieldHandle, field, info, SearchMatch.A_ACCURATE);
91                     }
92                 }
93
94                 // no need to check binary info since resolve was successful
95
return;
96             }
97         } catch (AbortCompilation e) { // if compilation was aborted it is a problem with the class path
98
}
99         // report as a potential match if binary info matches the pattern
100
accuracy = SearchMatch.A_INACCURATE;
101     }
102
103     IBinaryMethod[] methods = info.getMethods();
104     if (methods != null) {
105         for (int i = 0, l = methods.length; i < l; i++) {
106             IBinaryMethod method = methods[i];
107             if (matchBinary(pattern, method, info)) {
108                 char[] name;
109                 if (method.isConstructor()) {
110                     name = info.getName();
111                     int lastSlash = CharOperation.lastIndexOf('/', name);
112                     if (lastSlash != -1) {
113                         name = CharOperation.subarray(name, lastSlash+1, name.length);
114                     }
115                 } else {
116                     name = method.getSelector();
117                 }
118                 String JavaDoc selector = new String JavaDoc(name);
119                 String JavaDoc[] parameterTypes = CharOperation.toStrings(Signature.getParameterTypes(convertClassFileFormat(method.getMethodDescriptor())));
120                 IMethod methodHandle = binaryType.getMethod(selector, parameterTypes);
121                 methodHandle = new ResolvedBinaryMethod(binaryType, selector, parameterTypes, methodHandle.getKey());
122                 locator.reportBinaryMemberDeclaration(null, methodHandle, null, info, accuracy);
123             }
124         }
125     }
126
127     IBinaryField[] fields = info.getFields();
128     if (fields != null) {
129         for (int i = 0, l = fields.length; i < l; i++) {
130             IBinaryField field = fields[i];
131             if (matchBinary(pattern, field, info)) {
132                 String JavaDoc fieldName = new String JavaDoc(field.getName());
133                 IField fieldHandle = binaryType.getField(fieldName);
134                 fieldHandle = new ResolvedBinaryField(binaryType, fieldName, fieldHandle.getKey());
135                 locator.reportBinaryMemberDeclaration(null, fieldHandle, null, info, accuracy);
136             }
137         }
138     }
139 }
140 /**
141  * Finds out whether the given binary info matches the search pattern.
142  * Default is to return false.
143  */

144 boolean matchBinary(SearchPattern pattern, Object JavaDoc binaryInfo, IBinaryType enclosingBinaryType) {
145     switch (((InternalSearchPattern)pattern).kind) {
146         case CONSTRUCTOR_PATTERN :
147             return matchConstructor((ConstructorPattern) pattern, binaryInfo, enclosingBinaryType);
148         case FIELD_PATTERN :
149             return matchField((FieldPattern) pattern, binaryInfo, enclosingBinaryType);
150         case METHOD_PATTERN :
151             return matchMethod((MethodPattern) pattern, binaryInfo, enclosingBinaryType);
152         case SUPER_REF_PATTERN :
153             return matchSuperTypeReference((SuperTypeReferencePattern) pattern, binaryInfo, enclosingBinaryType);
154         case TYPE_DECL_PATTERN :
155             return matchTypeDeclaration((TypeDeclarationPattern) pattern, binaryInfo, enclosingBinaryType);
156         case OR_PATTERN :
157             SearchPattern[] patterns = ((OrPattern) pattern).patterns;
158             for (int i = 0, length = patterns.length; i < length; i++)
159                 if (matchBinary(patterns[i], binaryInfo, enclosingBinaryType)) return true;
160     }
161     return false;
162 }
163 boolean matchConstructor(ConstructorPattern pattern, Object JavaDoc binaryInfo, IBinaryType enclosingBinaryType) {
164     if (!pattern.findDeclarations) return false; // only relevant when finding declarations
165
if (!(binaryInfo instanceof IBinaryMethod)) return false;
166
167     IBinaryMethod method = (IBinaryMethod) binaryInfo;
168     if (!method.isConstructor()) return false;
169     if (!checkDeclaringType(enclosingBinaryType, pattern.declaringSimpleName, pattern.declaringQualification, pattern.isCaseSensitive(), pattern.isCamelCase()))
170         return false;
171     if (pattern.parameterSimpleNames != null) {
172         char[] methodDescriptor = convertClassFileFormat(method.getMethodDescriptor());
173         if (!checkParameters(methodDescriptor, pattern.parameterSimpleNames, pattern.parameterQualifications, pattern.isCaseSensitive(), pattern.isCamelCase()))
174             return false;
175     }
176     return true;
177 }
178 boolean matchField(FieldPattern pattern, Object JavaDoc binaryInfo, IBinaryType enclosingBinaryType) {
179     if (!pattern.findDeclarations) return false; // only relevant when finding declarations
180
if (!(binaryInfo instanceof IBinaryField)) return false;
181
182     IBinaryField field = (IBinaryField) binaryInfo;
183     if (!pattern.matchesName(pattern.name, field.getName())) return false;
184     if (!checkDeclaringType(enclosingBinaryType, pattern.declaringSimpleName, pattern.declaringQualification, pattern.isCaseSensitive(), pattern.isCamelCase()))
185         return false;
186
187     char[] fieldTypeSignature = Signature.toCharArray(convertClassFileFormat(field.getTypeName()));
188     return checkTypeName(pattern.typeSimpleName, pattern.typeQualification, fieldTypeSignature, pattern.isCaseSensitive(), pattern.isCamelCase());
189 }
190 boolean matchMethod(MethodPattern pattern, Object JavaDoc binaryInfo, IBinaryType enclosingBinaryType) {
191     if (!pattern.findDeclarations) return false; // only relevant when finding declarations
192
if (!(binaryInfo instanceof IBinaryMethod)) return false;
193
194     IBinaryMethod method = (IBinaryMethod) binaryInfo;
195     if (!pattern.matchesName(pattern.selector, method.getSelector())) return false;
196     if (!checkDeclaringType(enclosingBinaryType, pattern.declaringSimpleName, pattern.declaringQualification, pattern.isCaseSensitive(), pattern.isCamelCase()))
197         return false;
198
199     // look at return type only if declaring type is not specified
200
boolean checkReturnType = pattern.declaringSimpleName == null && (pattern.returnSimpleName != null || pattern.returnQualification != null);
201     boolean checkParameters = pattern.parameterSimpleNames != null;
202     if (checkReturnType || checkParameters) {
203         char[] methodDescriptor = convertClassFileFormat(method.getMethodDescriptor());
204         if (checkReturnType) {
205             char[] returnTypeSignature = Signature.toCharArray(Signature.getReturnType(methodDescriptor));
206             if (!checkTypeName(pattern.returnSimpleName, pattern.returnQualification, returnTypeSignature, pattern.isCaseSensitive(), pattern.isCamelCase()))
207                 return false;
208         }
209         if (checkParameters && !checkParameters(methodDescriptor, pattern.parameterSimpleNames, pattern.parameterQualifications, pattern.isCaseSensitive(), pattern.isCamelCase()))
210             return false;
211     }
212     return true;
213 }
214 boolean matchSuperTypeReference(SuperTypeReferencePattern pattern, Object JavaDoc binaryInfo, IBinaryType enclosingBinaryType) {
215     if (!(binaryInfo instanceof IBinaryType)) return false;
216
217     IBinaryType type = (IBinaryType) binaryInfo;
218     if (pattern.superRefKind != SuperTypeReferencePattern.ONLY_SUPER_INTERFACES) {
219         char[] vmName = type.getSuperclassName();
220         if (vmName != null) {
221             char[] superclassName = convertClassFileFormat(vmName);
222             if (checkTypeName(pattern.superSimpleName, pattern.superQualification, superclassName, pattern.isCaseSensitive(), pattern.isCamelCase()))
223                 return true;
224         }
225     }
226
227     if (pattern.superRefKind != SuperTypeReferencePattern.ONLY_SUPER_CLASSES) {
228         char[][] superInterfaces = type.getInterfaceNames();
229         if (superInterfaces != null) {
230             for (int i = 0, max = superInterfaces.length; i < max; i++) {
231                 char[] superInterfaceName = convertClassFileFormat(superInterfaces[i]);
232                 if (checkTypeName(pattern.superSimpleName, pattern.superQualification, superInterfaceName, pattern.isCaseSensitive(), pattern.isCamelCase()))
233                     return true;
234             }
235         }
236     }
237     return false;
238 }
239 boolean matchTypeDeclaration(TypeDeclarationPattern pattern, Object JavaDoc binaryInfo, IBinaryType enclosingBinaryType) {
240     if (!(binaryInfo instanceof IBinaryType)) return false;
241
242     IBinaryType type = (IBinaryType) binaryInfo;
243     char[] fullyQualifiedTypeName = convertClassFileFormat(type.getName());
244     boolean qualifiedPattern = pattern instanceof QualifiedTypeDeclarationPattern;
245     if (pattern.enclosingTypeNames == null || qualifiedPattern) {
246         char[] simpleName = (pattern.getMatchMode() == SearchPattern.R_PREFIX_MATCH)
247             ? CharOperation.concat(pattern.simpleName, IIndexConstants.ONE_STAR)
248             : pattern.simpleName;
249         char[] pkg = qualifiedPattern ? ((QualifiedTypeDeclarationPattern)pattern).qualification : pattern.pkg;
250         if (!checkTypeName(simpleName, pkg, fullyQualifiedTypeName, pattern.isCaseSensitive(), pattern.isCamelCase())) return false;
251     } else {
252         char[] enclosingTypeName = CharOperation.concatWith(pattern.enclosingTypeNames, '.');
253         char[] patternString = pattern.pkg == null
254             ? enclosingTypeName
255             : CharOperation.concat(pattern.pkg, enclosingTypeName, '.');
256         if (!checkTypeName(pattern.simpleName, patternString, fullyQualifiedTypeName, pattern.isCaseSensitive(), pattern.isCamelCase())) return false;
257     }
258
259     int kind = TypeDeclaration.kind(type.getModifiers());
260     switch (pattern.typeSuffix) {
261         case CLASS_SUFFIX:
262             return kind == TypeDeclaration.CLASS_DECL;
263         case INTERFACE_SUFFIX:
264             return kind == TypeDeclaration.INTERFACE_DECL;
265         case ENUM_SUFFIX:
266             return kind == TypeDeclaration.ENUM_DECL;
267         case ANNOTATION_TYPE_SUFFIX:
268             return kind == TypeDeclaration.ANNOTATION_TYPE_DECL;
269         case CLASS_AND_INTERFACE_SUFFIX:
270             return kind == TypeDeclaration.CLASS_DECL || kind == TypeDeclaration.INTERFACE_DECL;
271         case CLASS_AND_ENUM_SUFFIX:
272             return kind == TypeDeclaration.CLASS_DECL || kind == TypeDeclaration.ENUM_DECL;
273         case INTERFACE_AND_ANNOTATION_SUFFIX:
274             return kind == TypeDeclaration.INTERFACE_DECL || kind == TypeDeclaration.ANNOTATION_TYPE_DECL;
275         case TYPE_SUFFIX: // nothing
276
}
277     return true;
278 }
279 }
280
Popular Tags