KickJava   Java API By Example, From Geeks To Geeks.

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


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.resources.IResource;
14 import org.eclipse.core.runtime.CoreException;
15 import org.eclipse.jdt.core.*;
16 import org.eclipse.jdt.core.compiler.CharOperation;
17 import org.eclipse.jdt.core.search.*;
18 import org.eclipse.jdt.internal.compiler.ast.*;
19 import org.eclipse.jdt.internal.compiler.env.IBinaryType;
20 import org.eclipse.jdt.internal.compiler.lookup.*;
21 import org.eclipse.jdt.internal.compiler.util.SimpleSet;
22 import org.eclipse.jdt.internal.core.JavaElement;
23
24 public class FieldLocator extends VariableLocator {
25
26 protected boolean isDeclarationOfAccessedFieldsPattern;
27
28 public FieldLocator(FieldPattern pattern) {
29     super(pattern);
30
31     this.isDeclarationOfAccessedFieldsPattern = this.pattern instanceof DeclarationOfAccessedFieldsPattern;
32 }
33 public int match(ASTNode node, MatchingNodeSet nodeSet) {
34     int declarationsLevel = IMPOSSIBLE_MATCH;
35     if (this.pattern.findReferences) {
36         if (node instanceof ImportReference) {
37             // With static import, we can have static field reference in import reference
38
ImportReference importRef = (ImportReference) node;
39             int length = importRef.tokens.length-1;
40             if (importRef.isStatic() && ((importRef.bits & ASTNode.OnDemand) == 0) && matchesName(this.pattern.name, importRef.tokens[length])) {
41                 char[][] compoundName = new char[length][];
42                 System.arraycopy(importRef.tokens, 0, compoundName, 0, length);
43                 FieldPattern fieldPattern = (FieldPattern) this.pattern;
44                 char[] declaringType = CharOperation.concat(fieldPattern.declaringQualification, fieldPattern.declaringSimpleName, '.');
45                 if (matchesName(declaringType, CharOperation.concatWith(compoundName, '.'))) {
46                     declarationsLevel = ((InternalSearchPattern)this.pattern).mustResolve ? POSSIBLE_MATCH : ACCURATE_MATCH;
47                 }
48             }
49         }
50     }
51     return nodeSet.addMatch(node, declarationsLevel);
52 }
53 //public int match(ConstructorDeclaration node, MatchingNodeSet nodeSet) - SKIP IT
54
public int match(FieldDeclaration node, MatchingNodeSet nodeSet) {
55     int referencesLevel = IMPOSSIBLE_MATCH;
56     if (this.pattern.findReferences)
57         // must be a write only access with an initializer
58
if (this.pattern.writeAccess && !this.pattern.readAccess && node.initialization != null)
59             if (matchesName(this.pattern.name, node.name))
60                 referencesLevel = ((InternalSearchPattern)this.pattern).mustResolve ? POSSIBLE_MATCH : ACCURATE_MATCH;
61
62     int declarationsLevel = IMPOSSIBLE_MATCH;
63     if (this.pattern.findDeclarations) {
64         switch (node.getKind()) {
65             case AbstractVariableDeclaration.FIELD :
66             case AbstractVariableDeclaration.ENUM_CONSTANT :
67                 if (matchesName(this.pattern.name, node.name))
68                     if (matchesTypeReference(((FieldPattern)this.pattern).typeSimpleName, node.type))
69                         declarationsLevel = ((InternalSearchPattern)this.pattern).mustResolve ? POSSIBLE_MATCH : ACCURATE_MATCH;
70                 break;
71         }
72     }
73     return nodeSet.addMatch(node, referencesLevel >= declarationsLevel ? referencesLevel : declarationsLevel); // use the stronger match
74
}
75 //public int match(MethodDeclaration node, MatchingNodeSet nodeSet) - SKIP IT
76
//public int match(MessageSend node, MatchingNodeSet nodeSet) - SKIP IT
77
//public int match(TypeDeclaration node, MatchingNodeSet nodeSet) - SKIP IT
78
//public int match(TypeReference node, MatchingNodeSet nodeSet) - SKIP IT
79

80 protected int matchContainer() {
81     if (this.pattern.findReferences) {
82         // need to look everywhere to find in javadocs and static import
83
return ALL_CONTAINER;
84     }
85     return CLASS_CONTAINER;
86 }
87 protected int matchField(FieldBinding field, boolean matchName) {
88     if (field == null) return INACCURATE_MATCH;
89
90     if (matchName && !matchesName(this.pattern.name, field.readableName())) return IMPOSSIBLE_MATCH;
91
92     FieldPattern fieldPattern = (FieldPattern)this.pattern;
93     ReferenceBinding receiverBinding = field.declaringClass;
94     if (receiverBinding == null) {
95         if (field == ArrayBinding.ArrayLength)
96             // optimized case for length field of an array
97
return fieldPattern.declaringQualification == null && fieldPattern.declaringSimpleName == null
98                 ? ACCURATE_MATCH
99                 : IMPOSSIBLE_MATCH;
100         return INACCURATE_MATCH;
101     }
102
103     // Note there is no dynamic lookup for field access
104
int declaringLevel = resolveLevelForType(fieldPattern.declaringSimpleName, fieldPattern.declaringQualification, receiverBinding);
105     if (declaringLevel == IMPOSSIBLE_MATCH) return IMPOSSIBLE_MATCH;
106
107     // look at field type only if declaring type is not specified
108
if (fieldPattern.declaringSimpleName == null) return declaringLevel;
109
110     // get real field binding
111
FieldBinding fieldBinding = field;
112     if (field instanceof ParameterizedFieldBinding) {
113         fieldBinding = ((ParameterizedFieldBinding) field).originalField;
114     }
115
116     int typeLevel = resolveLevelForType(fieldBinding.type);
117     return declaringLevel > typeLevel ? typeLevel : declaringLevel; // return the weaker match
118
}
119 /* (non-Javadoc)
120  * @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)
121  * Accept to report match of static field on static import
122  */

123 protected void matchLevelAndReportImportRef(ImportReference importRef, Binding binding, MatchLocator locator) throws CoreException {
124     if (importRef.isStatic() && binding instanceof FieldBinding) {
125         super.matchLevelAndReportImportRef(importRef, binding, locator);
126     }
127 }
128 protected int matchReference(Reference node, MatchingNodeSet nodeSet, boolean writeOnlyAccess) {
129     if (node instanceof FieldReference) {
130         if (matchesName(this.pattern.name, ((FieldReference) node).token))
131             return nodeSet.addMatch(node, ((InternalSearchPattern)this.pattern).mustResolve ? POSSIBLE_MATCH : ACCURATE_MATCH);
132         return IMPOSSIBLE_MATCH;
133     }
134     return super.matchReference(node, nodeSet, writeOnlyAccess);
135 }
136 protected void matchReportReference(ASTNode reference, IJavaElement element, Binding elementBinding, int accuracy, MatchLocator locator) throws CoreException {
137     if (this.isDeclarationOfAccessedFieldsPattern) {
138         // need exact match to be able to open on type ref
139
if (accuracy != SearchMatch.A_ACCURATE) return;
140
141         // element that references the field must be included in the enclosing element
142
DeclarationOfAccessedFieldsPattern declPattern = (DeclarationOfAccessedFieldsPattern) this.pattern;
143         while (element != null && !declPattern.enclosingElement.equals(element))
144             element = element.getParent();
145         if (element != null) {
146             if (reference instanceof FieldReference) {
147                 reportDeclaration(((FieldReference) reference).binding, locator, declPattern.knownFields);
148             } else if (reference instanceof QualifiedNameReference) {
149                 QualifiedNameReference qNameRef = (QualifiedNameReference) reference;
150                 Binding nameBinding = qNameRef.binding;
151                 if (nameBinding instanceof FieldBinding)
152                     reportDeclaration((FieldBinding)nameBinding, locator, declPattern.knownFields);
153                 int otherMax = qNameRef.otherBindings == null ? 0 : qNameRef.otherBindings.length;
154                 for (int i = 0; i < otherMax; i++)
155                     reportDeclaration(qNameRef.otherBindings[i], locator, declPattern.knownFields);
156             } else if (reference instanceof SingleNameReference) {
157                 reportDeclaration((FieldBinding)((SingleNameReference) reference).binding, locator, declPattern.knownFields);
158             }
159         }
160     } else if (reference instanceof ImportReference) {
161         ImportReference importRef = (ImportReference) reference;
162         long[] positions = importRef.sourcePositions;
163         int lastIndex = importRef.tokens.length - 1;
164         int start = (int) ((positions[lastIndex]) >>> 32);
165         int end = (int) positions[lastIndex];
166         match = locator.newFieldReferenceMatch(element, elementBinding, accuracy, start, end-start+1, importRef);
167         locator.report(match);
168     } else if (reference instanceof FieldReference) {
169         FieldReference fieldReference = (FieldReference) reference;
170         long position = fieldReference.nameSourcePosition;
171         int start = (int) (position >>> 32);
172         int end = (int) position;
173         match = locator.newFieldReferenceMatch(element, elementBinding, accuracy, start, end-start+1, fieldReference);
174         locator.report(match);
175     } else if (reference instanceof SingleNameReference) {
176         int offset = reference.sourceStart;
177         match = locator.newFieldReferenceMatch(element, elementBinding, accuracy, offset, reference.sourceEnd-offset+1, reference);
178         locator.report(match);
179     } else if (reference instanceof QualifiedNameReference) {
180         QualifiedNameReference qNameRef = (QualifiedNameReference) reference;
181         int length = qNameRef.tokens.length;
182         SearchMatch[] matches = new SearchMatch[length];
183         Binding nameBinding = qNameRef.binding;
184         int indexOfFirstFieldBinding = qNameRef.indexOfFirstFieldBinding > 0 ? qNameRef.indexOfFirstFieldBinding-1 : 0;
185
186         // first token
187
if (matchesName(this.pattern.name, qNameRef.tokens[indexOfFirstFieldBinding]) && !(nameBinding instanceof LocalVariableBinding)) {
188             FieldBinding fieldBinding = nameBinding instanceof FieldBinding ? (FieldBinding) nameBinding : null;
189             if (fieldBinding == null) {
190                 matches[indexOfFirstFieldBinding] = locator.newFieldReferenceMatch(element, elementBinding, accuracy, -1, -1, reference);
191             } else {
192                 switch (matchField(fieldBinding, false)) {
193                     case ACCURATE_MATCH:
194                         matches[indexOfFirstFieldBinding] = locator.newFieldReferenceMatch(element, elementBinding, SearchMatch.A_ACCURATE, -1, -1, reference);
195                         break;
196                     case INACCURATE_MATCH:
197                         match = locator.newFieldReferenceMatch(element, elementBinding, SearchMatch.A_INACCURATE, -1, -1, reference);
198                         if (fieldBinding.type != null && fieldBinding.type.isParameterizedType() && this.pattern.hasTypeArguments()) {
199                             updateMatch((ParameterizedTypeBinding) fieldBinding.type, this.pattern.getTypeArguments(), locator);
200                         }
201                         matches[indexOfFirstFieldBinding] = match;
202                         break;
203                 }
204             }
205         }
206
207         // other tokens
208
for (int i = indexOfFirstFieldBinding+1; i < length; i++) {
209             char[] token = qNameRef.tokens[i];
210             if (matchesName(this.pattern.name, token)) {
211                 FieldBinding otherBinding = qNameRef.otherBindings == null ? null : qNameRef.otherBindings[i-(indexOfFirstFieldBinding+1)];
212                 if (otherBinding == null) {
213                     matches[i] = locator.newFieldReferenceMatch(element, elementBinding, accuracy, -1, -1, reference);
214                 } else {
215                     switch (matchField(otherBinding, false)) {
216                         case ACCURATE_MATCH:
217                             matches[i] = locator.newFieldReferenceMatch(element, elementBinding, SearchMatch.A_ACCURATE, -1, -1, reference);
218                             break;
219                         case INACCURATE_MATCH:
220                             match = locator.newFieldReferenceMatch(element, elementBinding, SearchMatch.A_INACCURATE, -1, -1, reference);
221                             if (otherBinding.type != null && otherBinding.type.isParameterizedType() && this.pattern.hasTypeArguments()) {
222                                 updateMatch((ParameterizedTypeBinding) otherBinding.type, this.pattern.getTypeArguments(), locator);
223                             }
224                             matches[i] = match;
225                             break;
226                     }
227                 }
228             }
229         }
230         locator.reportAccurateFieldReference(matches, qNameRef);
231     }
232 }
233 /* (non-Javadoc)
234  * Overridden to reject unexact matches.
235  * @see org.eclipse.jdt.internal.core.search.matching.PatternLocator#updateMatch(org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding, char[][][], org.eclipse.jdt.internal.core.search.matching.MatchLocator)
236  *
237  */

238 protected void updateMatch(ParameterizedTypeBinding parameterizedBinding, char[][][] patternTypeArguments, MatchLocator locator) {
239     // We can only refine if locator has an unit scope.
240
if (locator.unitScope == null) return;
241     updateMatch(parameterizedBinding, patternTypeArguments, false, 0, locator);
242     if (!match.isExact()) {
243         // cannot accept neither erasure nor compatible match
244
match.setRule(0);
245     }
246 }
247 protected void reportDeclaration(FieldBinding fieldBinding, MatchLocator locator, SimpleSet knownFields) throws CoreException {
248     // ignore length field
249
if (fieldBinding == ArrayBinding.ArrayLength) return;
250     
251     ReferenceBinding declaringClass = fieldBinding.declaringClass;
252     IType type = locator.lookupType(declaringClass);
253     if (type == null) return; // case of a secondary type
254

255     char[] bindingName = fieldBinding.name;
256     IField field = type.getField(new String JavaDoc(bindingName));
257     if (knownFields.addIfNotIncluded(field) == null) return;
258
259     IResource resource = type.getResource();
260     boolean isBinary = type.isBinary();
261     IBinaryType info = null;
262     if (isBinary) {
263         if (resource == null)
264             resource = type.getJavaProject().getProject();
265         info = locator.getBinaryInfo((org.eclipse.jdt.internal.core.ClassFile) type.getClassFile(), resource);
266         locator.reportBinaryMemberDeclaration(resource, field, fieldBinding, info, SearchMatch.A_ACCURATE);
267     } else {
268         if (declaringClass instanceof ParameterizedTypeBinding)
269             declaringClass = ((ParameterizedTypeBinding) declaringClass).genericType();
270         ClassScope scope = ((SourceTypeBinding) declaringClass).scope;
271         if (scope != null) {
272             TypeDeclaration typeDecl = scope.referenceContext;
273             FieldDeclaration fieldDecl = null;
274             FieldDeclaration[] fieldDecls = typeDecl.fields;
275             for (int i = 0, length = fieldDecls.length; i < length; i++) {
276                 if (CharOperation.equals(bindingName, fieldDecls[i].name)) {
277                     fieldDecl = fieldDecls[i];
278                     break;
279                 }
280             }
281             if (fieldDecl != null) {
282                 int offset = fieldDecl.sourceStart;
283                 match = new FieldDeclarationMatch(((JavaElement) field).resolved(fieldBinding), SearchMatch.A_ACCURATE, offset, fieldDecl.sourceEnd-offset+1, locator.getParticipant(), resource);
284                 locator.report(match);
285             }
286         }
287     }
288 }
289 protected int referenceType() {
290     return IJavaElement.FIELD;
291 }
292 public int resolveLevel(ASTNode possiblelMatchingNode) {
293     if (this.pattern.findReferences) {
294         if (possiblelMatchingNode instanceof FieldReference)
295             return matchField(((FieldReference) possiblelMatchingNode).binding, true);
296         else if (possiblelMatchingNode instanceof NameReference)
297             return resolveLevel((NameReference) possiblelMatchingNode);
298     }
299     if (possiblelMatchingNode instanceof FieldDeclaration)
300         return matchField(((FieldDeclaration) possiblelMatchingNode).binding, true);
301     return IMPOSSIBLE_MATCH;
302 }
303 public int resolveLevel(Binding binding) {
304     if (binding == null) return INACCURATE_MATCH;
305     if (!(binding instanceof FieldBinding)) return IMPOSSIBLE_MATCH;
306
307     return matchField((FieldBinding) binding, true);
308 }
309 protected int resolveLevel(NameReference nameRef) {
310     if (nameRef instanceof SingleNameReference)
311         return resolveLevel(nameRef.binding);
312
313     Binding binding = nameRef.binding;
314     QualifiedNameReference qNameRef = (QualifiedNameReference) nameRef;
315     FieldBinding fieldBinding = null;
316     if (binding instanceof FieldBinding) {
317         fieldBinding = (FieldBinding) binding;
318         char[] bindingName = fieldBinding.name;
319         int lastDot = CharOperation.lastIndexOf('.', bindingName);
320         if (lastDot > -1)
321             bindingName = CharOperation.subarray(bindingName, lastDot+1, bindingName.length);
322         if (matchesName(this.pattern.name, bindingName)) {
323             int level = matchField(fieldBinding, false);
324             if (level != IMPOSSIBLE_MATCH) return level;
325         }
326     }
327     int otherMax = qNameRef.otherBindings == null ? 0 : qNameRef.otherBindings.length;
328     for (int i = 0; i < otherMax; i++) {
329         char[] token = qNameRef.tokens[i + qNameRef.indexOfFirstFieldBinding];
330         if (matchesName(this.pattern.name, token)) {
331             FieldBinding otherBinding = qNameRef.otherBindings[i];
332             int level = matchField(otherBinding, false);
333             if (level != IMPOSSIBLE_MATCH) return level;
334         }
335     }
336     return IMPOSSIBLE_MATCH;
337 }
338 /* (non-Javadoc)
339  * Resolve level for type with a given binding.
340  */

341 protected int resolveLevelForType(TypeBinding typeBinding) {
342     FieldPattern fieldPattern = (FieldPattern) this.pattern;
343     TypeBinding fieldTypeBinding = typeBinding;
344     if (fieldTypeBinding != null && fieldTypeBinding.isParameterizedType()) {
345         fieldTypeBinding = typeBinding.erasure();
346     }
347     return resolveLevelForType(
348             fieldPattern.typeSimpleName,
349             fieldPattern.typeQualification,
350             fieldPattern.getTypeArguments(),
351             0,
352             fieldTypeBinding);
353 }
354 }
355
Popular Tags