KickJava   Java API By Example, From Geeks To Geeks.

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


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
15 import org.eclipse.jdt.core.IJavaElement;
16 import org.eclipse.jdt.core.IPackageFragment;
17 import org.eclipse.jdt.core.IPackageFragmentRoot;
18 import org.eclipse.jdt.core.JavaModelException;
19 import org.eclipse.jdt.core.search.SearchPattern;
20 import org.eclipse.jdt.core.compiler.CharOperation;
21 import org.eclipse.jdt.internal.compiler.ast.*;
22 import org.eclipse.jdt.internal.compiler.lookup.*;
23 import org.eclipse.jdt.internal.compiler.util.Util;
24
25 public class PackageReferenceLocator extends PatternLocator {
26
27 protected PackageReferencePattern pattern;
28
29 // check that referenced type is actually defined in this package fragment
30
public static boolean isDeclaringPackageFragment(IPackageFragment packageFragment, ReferenceBinding typeBinding) {
31     char[] fileName = typeBinding.getFileName();
32     if (fileName != null) {
33         // retrieve the actual file name from the full path (sources are generally only containing it already)
34
fileName = CharOperation.replaceOnCopy(fileName, '/', '\\'); // ensure to not do any side effect on file name (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=136016)
35
fileName = CharOperation.lastSegment(fileName, '\\');
36         
37         try {
38             switch (packageFragment.getKind()) {
39                 case IPackageFragmentRoot.K_SOURCE :
40                     if (!org.eclipse.jdt.internal.core.util.Util.isJavaLikeFileName(fileName) || !packageFragment.getCompilationUnit(new String JavaDoc(fileName)).exists()) {
41                         return false; // unit doesn't live in selected package
42
}
43                     break;
44                 case IPackageFragmentRoot.K_BINARY :
45 // if (Util.isJavaFileName(fileName)) { // binary with attached source
46
// int length = fileName.length;
47
// System.arraycopy(fileName, 0, fileName = new char[length], 0, length - 4); // copy all but extension
48
// System.arraycopy(SuffixConstants.SUFFIX_class, 0, fileName, length - 4, 4);
49
// }
50
if (!Util.isClassFileName(fileName) || !packageFragment.getClassFile(new String JavaDoc(fileName)).exists()) {
51                         return false; // classfile doesn't live in selected package
52
}
53                     break;
54             }
55         } catch(JavaModelException e) {
56             // unable to determine kind; tolerate this match
57
}
58     }
59     return true; // by default, do not eliminate
60
}
61
62 public PackageReferenceLocator(PackageReferencePattern pattern) {
63     super(pattern);
64
65     this.pattern = pattern;
66 }
67 public int match(ASTNode node, MatchingNodeSet nodeSet) { // interested in ImportReference
68
if (!(node instanceof ImportReference)) return IMPOSSIBLE_MATCH;
69
70     return nodeSet.addMatch(node, matchLevel((ImportReference) node));
71 }
72 //public int match(ConstructorDeclaration node, MatchingNodeSet nodeSet) - SKIP IT
73
//public int match(Expression node, MatchingNodeSet nodeSet) - SKIP IT
74
//public int match(FieldDeclaration node, MatchingNodeSet nodeSet) - SKIP IT
75
//public int match(MethodDeclaration node, MatchingNodeSet nodeSet) - SKIP IT
76
//public int match(MessageSend node, MatchingNodeSet nodeSet) - SKIP IT
77
public int match(Reference node, MatchingNodeSet nodeSet) { // interested in QualifiedNameReference
78
if (!(node instanceof QualifiedNameReference)) return IMPOSSIBLE_MATCH;
79
80     return nodeSet.addMatch(node, matchLevelForTokens(((QualifiedNameReference) node).tokens));
81 }
82 //public int match(TypeDeclaration node, MatchingNodeSet nodeSet) - SKIP IT
83
public int match(TypeReference node, MatchingNodeSet nodeSet) { // interested in QualifiedTypeReference only
84
if (node instanceof JavadocSingleTypeReference) {
85         char[][] tokens = new char[][] { ((JavadocSingleTypeReference) node).token };
86         return nodeSet.addMatch(node, matchLevelForTokens(tokens));
87     }
88     if (!(node instanceof QualifiedTypeReference)) return IMPOSSIBLE_MATCH;
89     return nodeSet.addMatch(node, matchLevelForTokens(((QualifiedTypeReference) node).tokens));
90 }
91
92 protected int matchLevel(ImportReference importRef) {
93     return matchLevelForTokens(importRef.tokens);
94 }
95 protected int matchLevelForTokens(char[][] tokens) {
96     if (this.pattern.pkgName == null) return ACCURATE_MATCH;
97
98     char[] packageName = null;
99     if (this.isCamelCase) {
100         packageName = CharOperation.concatWith(tokens, '.');
101         if (CharOperation.camelCaseMatch(this.pattern.pkgName, packageName)) {
102             return POSSIBLE_MATCH;
103         }
104     }
105     switch (this.matchMode) {
106         case SearchPattern.R_EXACT_MATCH:
107         case SearchPattern.R_PREFIX_MATCH:
108             if (packageName==null) packageName = CharOperation.concatWith(tokens, '.');
109             if (CharOperation.prefixEquals(this.pattern.pkgName, packageName, this.isCaseSensitive)) {
110                 return POSSIBLE_MATCH;
111             }
112             break;
113         case SearchPattern.R_PATTERN_MATCH:
114             char[] patternName = this.pattern.pkgName[this.pattern.pkgName.length - 1] == '*'
115                 ? this.pattern.pkgName
116                 : CharOperation.concat(this.pattern.pkgName, ".*".toCharArray()); //$NON-NLS-1$
117
if (packageName==null) packageName = CharOperation.concatWith(tokens, '.');
118             if (CharOperation.match(patternName, packageName, this.isCaseSensitive)) {
119                 return POSSIBLE_MATCH;
120             }
121             break;
122         case SearchPattern.R_REGEXP_MATCH :
123             // TODO (frederic) implement regular expression match
124
break;
125     }
126     return IMPOSSIBLE_MATCH;
127 }
128 /* (non-Javadoc)
129  * @see org.eclipse.jdt.internal.core.search.matching.PatternLocator#matchLevelAndReportImportRef(org.eclipse.jdt.internal.compiler.ast.ImportReference, org.eclipse.jdt.internal.compiler.lookup.Binding, org.eclipse.jdt.internal.core.search.matching.MatchLocator)
130  */

131 protected void matchLevelAndReportImportRef(ImportReference importRef, Binding binding, MatchLocator locator) throws CoreException {
132     Binding refBinding = binding;
133     if (importRef.isStatic()) {
134         // for static import, binding can be a field binding or a member type binding
135
// verify that in this case binding is static and use declaring class for fields
136
if (binding instanceof FieldBinding) {
137             FieldBinding fieldBinding = (FieldBinding) binding;
138             if (!fieldBinding.isStatic()) return;
139             refBinding = fieldBinding.declaringClass;
140         } else if (binding instanceof MethodBinding) {
141             MethodBinding methodBinding = (MethodBinding) binding;
142             if (!methodBinding.isStatic()) return;
143             refBinding = methodBinding.declaringClass;
144         } else if (binding instanceof MemberTypeBinding) {
145             MemberTypeBinding memberBinding = (MemberTypeBinding) binding;
146             if (!memberBinding.isStatic()) return;
147         }
148     }
149     super.matchLevelAndReportImportRef(importRef, refBinding, locator);
150 }
151 protected void matchReportImportRef(ImportReference importRef, Binding binding, IJavaElement element, int accuracy, MatchLocator locator) throws CoreException {
152     if (binding == null) {
153         this.matchReportReference(importRef, element, null/*no binding*/, accuracy, locator);
154     } else {
155         if (locator.encloses(element)) {
156             long[] positions = importRef.sourcePositions;
157             int last = positions.length - 1;
158             if (binding instanceof ProblemReferenceBinding)
159                 binding = ((ProblemReferenceBinding) binding).closestMatch();
160             if (binding instanceof ReferenceBinding) {
161                 PackageBinding pkgBinding = ((ReferenceBinding) binding).fPackage;
162                 if (pkgBinding != null)
163                     last = pkgBinding.compoundName.length;
164             }
165             if (binding instanceof PackageBinding)
166                 last = ((PackageBinding) binding).compoundName.length;
167             int start = (int) (positions[0] >>> 32);
168             int end = (int) positions[last - 1];
169             match = locator.newPackageReferenceMatch(element, accuracy, start, end-start+1, importRef);
170             locator.report(match);
171         }
172     }
173 }
174 protected void matchReportReference(ASTNode reference, IJavaElement element, Binding elementBinding, int accuracy, MatchLocator locator) throws CoreException {
175     long[] positions = null;
176     int last = -1;
177     if (reference instanceof ImportReference) {
178         ImportReference importRef = (ImportReference) reference;
179         positions = importRef.sourcePositions;
180         last = (importRef.bits & ASTNode.OnDemand) != 0 ? positions.length : positions.length - 1;
181     } else {
182         TypeBinding typeBinding = null;
183         if (reference instanceof QualifiedNameReference) {
184             QualifiedNameReference qNameRef = (QualifiedNameReference) reference;
185             positions = qNameRef.sourcePositions;
186             switch (qNameRef.bits & ASTNode.RestrictiveFlagMASK) {
187                 case Binding.FIELD : // reading a field
188
typeBinding = qNameRef.actualReceiverType;
189                     break;
190                 case Binding.TYPE : //=============only type ==============
191
if (qNameRef.binding instanceof TypeBinding)
192                         typeBinding = (TypeBinding) qNameRef.binding;
193                     break;
194                 case Binding.VARIABLE : //============unbound cases===========
195
case Binding.TYPE | Binding.VARIABLE :
196                     Binding binding = qNameRef.binding;
197                     if (binding instanceof TypeBinding) {
198                         typeBinding = (TypeBinding) binding;
199                     } else if (binding instanceof ProblemFieldBinding) {
200                         typeBinding = qNameRef.actualReceiverType;
201                         last = qNameRef.tokens.length - (qNameRef.otherBindings == null ? 2 : qNameRef.otherBindings.length + 2);
202                     } else if (binding instanceof ProblemBinding) {
203                         ProblemBinding pbBinding = (ProblemBinding) binding;
204                         typeBinding = pbBinding.searchType;
205                         last = CharOperation.occurencesOf('.', pbBinding.name);
206                     }
207                     break;
208             }
209         } else if (reference instanceof QualifiedTypeReference) {
210             QualifiedTypeReference qTypeRef = (QualifiedTypeReference) reference;
211             positions = qTypeRef.sourcePositions;
212             typeBinding = qTypeRef.resolvedType;
213         } else if (reference instanceof JavadocSingleTypeReference) {
214             JavadocSingleTypeReference jsTypeRef = (JavadocSingleTypeReference) reference;
215             positions = new long[1];
216             positions[0] = (((long)jsTypeRef.sourceStart) << 32) + jsTypeRef.sourceEnd;
217             typeBinding = jsTypeRef.resolvedType;
218         }
219         if (positions == null) return;
220         if (typeBinding instanceof ArrayBinding)
221             typeBinding = ((ArrayBinding) typeBinding).leafComponentType;
222         if (typeBinding instanceof ProblemReferenceBinding)
223             typeBinding = ((ProblemReferenceBinding) typeBinding).closestMatch();
224         if (typeBinding instanceof ReferenceBinding) {
225             PackageBinding pkgBinding = ((ReferenceBinding) typeBinding).fPackage;
226             if (pkgBinding != null)
227                 last = pkgBinding.compoundName.length;
228         }
229         // Do not report qualified references which are only enclosing type
230
// (see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=91078)
231
ReferenceBinding enclosingType = typeBinding == null ? null: typeBinding.enclosingType();
232         if (enclosingType != null) {
233             int length = positions.length;
234             while (enclosingType != null && length > 0) {
235                 length--;
236                 enclosingType = enclosingType.enclosingType();
237             }
238             if (length <= 1) return;
239         }
240     }
241     if (last == -1) {
242         last = this.pattern.segments.length;
243     }
244     if (last == 0) return;
245     if (last > positions.length) last = positions.length;
246     int sourceStart = (int) (positions[0] >>> 32);
247     int sourceEnd = ((int) positions[last - 1]);
248     match = locator.newPackageReferenceMatch(element, accuracy, sourceStart, sourceEnd-sourceStart+1, reference);
249     locator.report(match);
250 }
251 protected int referenceType() {
252     return IJavaElement.PACKAGE_FRAGMENT;
253 }
254 public int resolveLevel(ASTNode node) {
255     if (node instanceof JavadocQualifiedTypeReference) {
256         JavadocQualifiedTypeReference qualifRef = (JavadocQualifiedTypeReference) node;
257         if (qualifRef.packageBinding != null)
258             return resolveLevel(qualifRef.packageBinding);
259         return resolveLevel(qualifRef.resolvedType);
260     }
261     if (node instanceof JavadocSingleTypeReference) {
262         JavadocSingleTypeReference singleRef = (JavadocSingleTypeReference) node;
263         if (singleRef.packageBinding != null)
264             return resolveLevel(singleRef.packageBinding);
265         return IMPOSSIBLE_MATCH;
266     }
267     if (node instanceof QualifiedTypeReference)
268         return resolveLevel(((QualifiedTypeReference) node).resolvedType);
269     if (node instanceof QualifiedNameReference)
270         return this.resolveLevel((QualifiedNameReference) node);
271 // if (node instanceof ImportReference) - Not called when resolve is true, see MatchingNodeSet.reportMatching(unit)
272
return IMPOSSIBLE_MATCH;
273 }
274 public int resolveLevel(Binding binding) {
275     if (binding == null) return INACCURATE_MATCH;
276
277     char[][] compoundName = null;
278     if (binding instanceof ImportBinding) {
279         compoundName = ((ImportBinding) binding).compoundName;
280     } else if (binding instanceof PackageBinding) {
281         compoundName = ((PackageBinding) binding).compoundName;
282     } else {
283         if (binding instanceof ArrayBinding)
284             binding = ((ArrayBinding) binding).leafComponentType;
285         if (binding instanceof ProblemReferenceBinding)
286             binding = ((ProblemReferenceBinding) binding).closestMatch();
287         if (binding == null) return INACCURATE_MATCH;
288
289         if (binding instanceof ReferenceBinding) {
290             PackageBinding pkgBinding = ((ReferenceBinding) binding).fPackage;
291             if (pkgBinding == null) return INACCURATE_MATCH;
292             compoundName = pkgBinding.compoundName;
293         }
294     }
295     if (compoundName != null && matchesName(this.pattern.pkgName, CharOperation.concatWith(compoundName, '.'))) {
296         if (((InternalSearchPattern) this.pattern).focus instanceof IPackageFragment && binding instanceof ReferenceBinding) {
297             // check that type is located inside this instance of a package fragment
298
if (!isDeclaringPackageFragment((IPackageFragment)((InternalSearchPattern) this.pattern).focus, (ReferenceBinding)binding))
299                 return IMPOSSIBLE_MATCH;
300         }
301         return ACCURATE_MATCH;
302     } else {
303         return IMPOSSIBLE_MATCH;
304     }
305 }
306 protected int resolveLevel(QualifiedNameReference qNameRef) {
307     TypeBinding typeBinding = null;
308     switch (qNameRef.bits & ASTNode.RestrictiveFlagMASK) {
309         case Binding.FIELD : // reading a field
310
if (qNameRef.tokens.length < (qNameRef.otherBindings == null ? 3 : qNameRef.otherBindings.length + 3))
311                 return IMPOSSIBLE_MATCH; // must be at least p1.A.x
312
typeBinding = qNameRef.actualReceiverType;
313             break;
314         case Binding.LOCAL : // reading a local variable
315
return IMPOSSIBLE_MATCH; // no package match in it
316
case Binding.TYPE : //=============only type ==============
317
if (qNameRef.binding instanceof TypeBinding)
318                 typeBinding = (TypeBinding) qNameRef.binding;
319             break;
320         /*
321          * Handling of unbound qualified name references. The match may reside in the resolved fragment,
322          * which is recorded inside the problem binding, along with the portion of the name until it became a problem.
323          */

324         case Binding.VARIABLE : //============unbound cases===========
325
case Binding.TYPE | Binding.VARIABLE :
326             Binding binding = qNameRef.binding;
327             if (binding instanceof ProblemReferenceBinding) {
328                 typeBinding = (TypeBinding) binding;
329             } else if (binding instanceof ProblemFieldBinding) {
330                 if (qNameRef.tokens.length < (qNameRef.otherBindings == null ? 3 : qNameRef.otherBindings.length + 3))
331                     return IMPOSSIBLE_MATCH; // must be at least p1.A.x
332
typeBinding = qNameRef.actualReceiverType;
333             } else if (binding instanceof ProblemBinding) {
334                 ProblemBinding pbBinding = (ProblemBinding) binding;
335                 if (CharOperation.occurencesOf('.', pbBinding.name) <= 0) // index of last bound token is one before the pb token
336
return INACCURATE_MATCH;
337                 typeBinding = pbBinding.searchType;
338             }
339             break;
340     }
341     return resolveLevel(typeBinding);
342 }
343 public String JavaDoc toString() {
344     return "Locator for " + this.pattern.toString(); //$NON-NLS-1$
345
}
346 }
347
Popular Tags