KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > core > util > BindingKeyResolver


1 /*******************************************************************************
2  * Copyright (c) 2005, 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.util;
12
13 import java.util.ArrayList JavaDoc;
14
15 import org.eclipse.jdt.core.compiler.CharOperation;
16 import org.eclipse.jdt.internal.compiler.ASTVisitor;
17 import org.eclipse.jdt.internal.compiler.Compiler;
18 import org.eclipse.jdt.internal.compiler.ast.ArrayReference;
19 import org.eclipse.jdt.internal.compiler.ast.Assignment;
20 import org.eclipse.jdt.internal.compiler.ast.CastExpression;
21 import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
22 import org.eclipse.jdt.internal.compiler.ast.ConditionalExpression;
23 import org.eclipse.jdt.internal.compiler.ast.FieldReference;
24 import org.eclipse.jdt.internal.compiler.ast.MessageSend;
25 import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference;
26 import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
27 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
28 import org.eclipse.jdt.internal.compiler.ast.Wildcard;
29 import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
30 import org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding;
31 import org.eclipse.jdt.internal.compiler.lookup.Binding;
32 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
33 import org.eclipse.jdt.internal.compiler.lookup.CaptureBinding;
34 import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
35 import org.eclipse.jdt.internal.compiler.lookup.LocalTypeBinding;
36 import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
37 import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
38 import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
39 import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
40 import org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding;
41 import org.eclipse.jdt.internal.compiler.lookup.RawTypeBinding;
42 import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
43 import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
44 import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
45 import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding;
46 import org.eclipse.jdt.internal.compiler.lookup.WildcardBinding;
47
48 public class BindingKeyResolver extends BindingKeyParser {
49     Compiler JavaDoc compiler;
50     Binding compilerBinding;
51     
52     char[][] compoundName;
53     int dimension;
54     LookupEnvironment environment;
55     ReferenceBinding genericType;
56     MethodBinding methodBinding;
57     
58     char[] secondarySimpleName;
59     CompilationUnitDeclaration parsedUnit;
60     BlockScope scope;
61     TypeBinding typeBinding;
62     TypeDeclaration typeDeclaration;
63     ArrayList JavaDoc types = new ArrayList JavaDoc();
64     int rank = 0;
65     
66     int wildcardRank;
67     
68     CompilationUnitDeclaration outerMostParsedUnit;
69     
70     private BindingKeyResolver(BindingKeyParser parser, Compiler JavaDoc compiler, LookupEnvironment environment, int wildcardRank, CompilationUnitDeclaration outerMostParsedUnit) {
71         super(parser);
72         this.compiler = compiler;
73         this.environment = environment;
74         this.wildcardRank = wildcardRank;
75         this.outerMostParsedUnit = outerMostParsedUnit;
76     }
77     
78     public BindingKeyResolver(String JavaDoc key) {
79         this(key, null, null);
80     }
81
82     public BindingKeyResolver(String JavaDoc key, Compiler JavaDoc compiler, LookupEnvironment environment) {
83         super(key);
84         this.compiler = compiler;
85         this.environment = environment;
86     }
87     
88     /*
89      * If not already cached, computes and cache the compound name (pkg name + top level name) of this key.
90      * Returns the package name if key is a pkg key.
91      * Returns an empty array if malformed.
92      * This key's scanner should be positioned on the package or type token.
93      */

94     public char[][] compoundName() {
95         return this.compoundName;
96     }
97      
98     public void consumeArrayDimension(char[] brakets) {
99         this.dimension = brakets.length;
100     }
101     
102     public void consumeBaseType(char[] baseTypeSig) {
103         this.compoundName = new char[][] {getKey().toCharArray()};
104         TypeBinding baseTypeBinding = getBaseTypeBinding(baseTypeSig);
105         if (baseTypeBinding != null) {
106             this.typeBinding = baseTypeBinding;
107         }
108     }
109     
110     public void consumeCapture(final int position) {
111         CompilationUnitDeclaration outerParsedUnit = this.outerMostParsedUnit == null ? this.parsedUnit : this.outerMostParsedUnit;
112         if (outerParsedUnit == null) return;
113         final Binding wildcardBinding = ((BindingKeyResolver) this.types.get(0)).compilerBinding;
114         class CaptureFinder extends ASTVisitor {
115             CaptureBinding capture;
116             boolean checkType(TypeBinding binding) {
117                 if (binding == null)
118                     return false;
119                 switch (binding.kind()) {
120                     case Binding.PARAMETERIZED_TYPE:
121                         TypeBinding[] arguments = ((ParameterizedTypeBinding) binding).arguments;
122                         if (arguments == null) return false;
123                         for (int i = 0, length = arguments.length; i < length; i++) {
124                             if (checkType(arguments[i]))
125                                 return true;
126                         }
127                         break;
128                     case Binding.WILDCARD_TYPE:
129                         return checkType(((WildcardBinding) binding).bound);
130                     case Binding.ARRAY_TYPE:
131                         return checkType(((ArrayBinding) binding).leafComponentType);
132                     case Binding.TYPE_PARAMETER:
133                         if (binding.isCapture()) {
134                             CaptureBinding captureBinding = (CaptureBinding) binding;
135                             if (captureBinding.position == position && captureBinding.wildcard == wildcardBinding) {
136                                 this.capture = captureBinding;
137                                 return true;
138                             }
139                         }
140                         break;
141                 }
142                 return false;
143             }
144             public boolean visit(SingleNameReference singleNameReference, BlockScope blockScope) {
145                 if (checkType(singleNameReference.resolvedType))
146                     return false;
147                 return super.visit(singleNameReference, blockScope);
148             }
149             public boolean visit(QualifiedNameReference qualifiedNameReference, BlockScope blockScope) {
150                 if (checkType(qualifiedNameReference.resolvedType))
151                     return false;
152                 return super.visit(qualifiedNameReference, blockScope);
153             }
154             public boolean visit(MessageSend messageSend, BlockScope blockScope) {
155                 if (checkType(messageSend.resolvedType))
156                     return false;
157                 return super.visit(messageSend, blockScope);
158             }
159             public boolean visit(FieldReference fieldReference, BlockScope blockScope) {
160                 if (checkType(fieldReference.resolvedType))
161                     return false;
162                 return super.visit(fieldReference, blockScope);
163             }
164             public boolean visit(ConditionalExpression conditionalExpression, BlockScope blockScope) {
165                 if (checkType(conditionalExpression.resolvedType))
166                     return false;
167                 return super.visit(conditionalExpression, blockScope);
168             }
169             public boolean visit(CastExpression castExpression, BlockScope blockScope) {
170                 if (checkType(castExpression.resolvedType))
171                     return false;
172                 return super.visit(castExpression, blockScope);
173             }
174             public boolean visit(Assignment assignment, BlockScope blockScope) {
175                 if (checkType(assignment.resolvedType))
176                     return false;
177                 return super.visit(assignment, blockScope);
178             }
179             public boolean visit(ArrayReference arrayReference, BlockScope blockScope) {
180                 if (checkType(arrayReference.resolvedType))
181                     return false;
182                 return super.visit(arrayReference, blockScope);
183             }
184         }
185         CaptureFinder captureFinder = new CaptureFinder();
186         outerParsedUnit.traverse(captureFinder, outerParsedUnit.scope);
187         this.typeBinding = captureFinder.capture;
188     }
189     
190     public void consumeException() {
191         this.types = new ArrayList JavaDoc();
192     }
193
194     public void consumeField(char[] fieldName) {
195         FieldBinding[] fields = ((ReferenceBinding) this.typeBinding).availableFields(); // resilience
196
for (int i = 0, length = fields.length; i < length; i++) {
197             FieldBinding field = fields[i];
198             if (CharOperation.equals(fieldName, field.name)) {
199                 this.typeBinding = null;
200                 this.compilerBinding = field;
201                 return;
202             }
203         }
204     }
205
206     public void consumeParameterizedGenericMethod() {
207         if (this.methodBinding == null)
208             return;
209         TypeBinding[] arguments = getTypeBindingArguments();
210         if (arguments.length != this.methodBinding.typeVariables().length)
211             this.methodBinding = this.environment.createParameterizedGenericMethod(this.methodBinding, (RawTypeBinding) null);
212         else
213             this.methodBinding = this.environment.createParameterizedGenericMethod(this.methodBinding, arguments);
214         this.compilerBinding = this.methodBinding;
215     }
216     
217     public void consumeLocalType(char[] uniqueKey) {
218         LocalTypeBinding[] localTypeBindings = this.parsedUnit.localTypes;
219         for (int i = 0; i < this.parsedUnit.localTypeCount; i++)
220             if (CharOperation.equals(uniqueKey, localTypeBindings[i].computeUniqueKey(false/*not a leaf*/))) {
221                 this.typeBinding = localTypeBindings[i];
222                 return;
223             }
224     }
225
226     public void consumeLocalVar(char[] varName) {
227         if (this.scope == null) {
228             this.scope = this.methodBinding.sourceMethod().scope;
229         }
230         for (int i = 0; i < this.scope.localIndex; i++) {
231             LocalVariableBinding local = this.scope.locals[i];
232             if (CharOperation.equals(varName, local.name)) {
233                 this.methodBinding = null;
234                 this.compilerBinding = local;
235                 return;
236             }
237         }
238     }
239
240     public void consumeMethod(char[] selector, char[] signature) {
241         MethodBinding[] methods = ((ReferenceBinding) this.typeBinding).availableMethods(); // resilience
242
for (int i = 0, methodLength = methods.length; i < methodLength; i++) {
243             MethodBinding method = methods[i];
244             if (CharOperation.equals(selector, method.selector) || (selector.length == 0 && method.isConstructor())) {
245                 char[] methodSignature = method.genericSignature();
246                 if (methodSignature == null)
247                     methodSignature = method.signature();
248                 if (CharOperation.equals(signature, methodSignature)) {
249                     this.typeBinding = null;
250                     this.methodBinding = method;
251                     this.compilerBinding = this.methodBinding;
252                     return;
253                 }
254             }
255         }
256     }
257     
258     public void consumeMemberType(char[] simpleTypeName) {
259         this.typeBinding = getTypeBinding(simpleTypeName);
260     }
261
262     public void consumePackage(char[] pkgName) {
263         this.compoundName = CharOperation.splitOn('/', pkgName);
264         this.compilerBinding = new PackageBinding(this.compoundName, null, this.environment);
265     }
266     
267     public void consumeParameterizedType(char[] simpleTypeName, boolean isRaw) {
268         TypeBinding[] arguments = getTypeBindingArguments();
269         if (simpleTypeName != null) {
270             if (this.genericType == null) {
271                 // parameterized member type with raw enclosing type
272
this.genericType = ((ReferenceBinding) this.typeBinding).getMemberType(simpleTypeName);
273             } else {
274                 // parameterized member type with parameterized enclosing type
275
this.genericType = this.genericType.getMemberType(simpleTypeName);
276             }
277             if (!isRaw)
278                 this.typeBinding = this.environment.createParameterizedType(this.genericType, arguments, (ReferenceBinding) this.typeBinding);
279             else
280                 // raw type
281
this.typeBinding = this.environment.createRawType(this.genericType, (ReferenceBinding) this.typeBinding);
282         } else {
283             // parameterized top level type or parameterized member type with raw enclosing type
284
this.genericType = (ReferenceBinding) this.typeBinding;
285             ReferenceBinding enclosing = this.genericType.enclosingType();
286             if (enclosing != null) enclosing = (ReferenceBinding) this.environment.convertToRawType(enclosing);
287             this.typeBinding = this.environment.createParameterizedType(this.genericType, arguments, enclosing);
288         }
289     }
290     
291
292     public void consumeParser(BindingKeyParser parser) {
293         this.types.add(parser);
294         if (((BindingKeyResolver) parser).compilerBinding instanceof WildcardBinding)
295             this.rank++;
296     }
297     
298     public void consumeScope(int scopeNumber) {
299         if (this.scope == null) {
300             this.scope = this.methodBinding.sourceMethod().scope;
301         }
302         if (scopeNumber >= this.scope.subscopeCount)
303             return; // malformed key
304
this.scope = (BlockScope) this.scope.subscopes[scopeNumber];
305     }
306     
307     public void consumeRawType() {
308         if (this.typeBinding == null) return;
309         this.typeBinding = this.environment.convertToRawType(this.typeBinding);
310     }
311     public void consumeSecondaryType(char[] simpleTypeName) {
312         this.secondarySimpleName = simpleTypeName;
313     }
314     
315     public void consumeFullyQualifiedName(char[] fullyQualifiedName) {
316         this.compoundName = CharOperation.splitOn('/', fullyQualifiedName);
317     }
318     
319     public void consumeTopLevelType() {
320         this.parsedUnit = getCompilationUnitDeclaration();
321         if (this.parsedUnit != null && this.compiler != null) {
322             this.compiler.process(this.parsedUnit, this.compiler.totalUnits+1); // noop if unit has already been resolved
323
}
324         if (this.parsedUnit == null) {
325             this.typeBinding = getBinaryBinding();
326         } else {
327             char[] typeName = this.secondarySimpleName == null ? this.compoundName[this.compoundName.length-1] : this.secondarySimpleName;
328             this.typeBinding = getTypeBinding(typeName);
329         }
330     }
331     
332     public void consumeKey() {
333         if (this.typeBinding != null) {
334             this.typeBinding = getArrayBinding(this.dimension, this.typeBinding);
335             this.compilerBinding = this.typeBinding;
336         }
337     }
338     
339     public void consumeTypeVariable(char[] position, char[] typeVariableName) {
340         if (position.length > 0) {
341             int pos = Integer.parseInt(new String JavaDoc(position));
342             MethodBinding[] methods = ((ReferenceBinding) this.typeBinding).availableMethods(); // resilience
343
if (methods != null && pos < methods.length) {
344                 this.methodBinding = methods[pos];
345             }
346         }
347         TypeVariableBinding[] typeVariableBindings = this.methodBinding != null ? this.methodBinding.typeVariables() : this.typeBinding.typeVariables();
348         for (int i = 0, length = typeVariableBindings.length; i < length; i++) {
349             TypeVariableBinding typeVariableBinding = typeVariableBindings[i];
350             if (CharOperation.equals(typeVariableName, typeVariableBinding.sourceName())) {
351                 this.typeBinding = typeVariableBinding;
352                 return;
353             }
354         }
355     }
356     
357     public void consumeTypeWithCapture() {
358         BindingKeyResolver resolver = (BindingKeyResolver) this.types.get(0);
359         this.typeBinding =(TypeBinding) resolver.compilerBinding;
360     }
361     
362     public void consumeWildCard(int kind) {
363         switch (kind) {
364             case Wildcard.EXTENDS:
365             case Wildcard.SUPER:
366                 BindingKeyResolver boundResolver = (BindingKeyResolver) this.types.get(0);
367                 this.typeBinding = this.environment.createWildcard((ReferenceBinding) this.typeBinding, this.wildcardRank, (TypeBinding) boundResolver.compilerBinding, null /*no extra bound*/, kind);
368                 break;
369             case Wildcard.UNBOUND:
370                 this.typeBinding = this.environment.createWildcard((ReferenceBinding) this.typeBinding, rank++, null/*no bound*/, null /*no extra bound*/, kind);
371                 break;
372         }
373     }
374     
375     /*
376      * If the given dimension is greater than 0 returns an array binding for the given type binding.
377      * Otherwise return the given type binding.
378      * Returns null if the given type binding is null.
379      */

380     private TypeBinding getArrayBinding(int dim, TypeBinding binding) {
381         if (binding == null) return null;
382         if (dim == 0) return binding;
383         return this.environment.createArrayType(binding, dim);
384     }
385     
386     private TypeBinding getBaseTypeBinding(char[] signature) {
387         switch (signature[0]) {
388             case 'I' :
389                 return TypeBinding.INT;
390             case 'Z' :
391                 return TypeBinding.BOOLEAN;
392             case 'V' :
393                 return TypeBinding.VOID;
394             case 'C' :
395                 return TypeBinding.CHAR;
396             case 'D' :
397                 return TypeBinding.DOUBLE;
398             case 'B' :
399                 return TypeBinding.BYTE;
400             case 'F' :
401                 return TypeBinding.FLOAT;
402             case 'J' :
403                 return TypeBinding.LONG;
404             case 'S' :
405                 return TypeBinding.SHORT;
406             case 'N':
407                 return TypeBinding.NULL;
408             default :
409                 return null;
410         }
411     }
412      
413     /*
414      * Returns a binary binding corresonding to this key's compound name.
415      * Returns null if not found.
416      */

417     private TypeBinding getBinaryBinding() {
418         if (this.compoundName.length == 0) return null;
419         return this.environment.getType(this.compoundName);
420     }
421      
422     /*
423      * Finds the compilation unit declaration corresponding to the key in the given lookup environment.
424      * Returns null if no compilation unit declaration could be found.
425      * This key's scanner should be positioned on the package token.
426      */

427     public CompilationUnitDeclaration getCompilationUnitDeclaration() {
428         char[][] name = this.compoundName;
429         if (name.length == 0) return null;
430         if (this.environment == null) return null;
431         ReferenceBinding binding = this.environment.getType(name);
432         if (!(binding instanceof SourceTypeBinding)) {
433             if (this.secondarySimpleName == null)
434                 return null;
435             // case of a secondary type with no primary type (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=177115)
436
int length = name.length;
437             System.arraycopy(name, 0, name = new char[length][], 0, length-1);
438             name[length-1] = this.secondarySimpleName;
439             binding = this.environment.getType(name);
440             if (!(binding instanceof SourceTypeBinding))
441                 return null;
442         }
443         SourceTypeBinding sourceTypeBinding = (SourceTypeBinding) binding;
444         if (sourceTypeBinding.scope == null)
445             return null;
446         return sourceTypeBinding.scope.compilationUnitScope().referenceContext;
447     }
448      
449     /*
450      * Returns the compiler binding corresponding to this key.
451      * Returns null is malformed.
452      * This key's scanner should be positioned on the package token.
453      */

454     public Binding getCompilerBinding() {
455         try {
456             parse();
457             return this.compilerBinding;
458         } catch (RuntimeException JavaDoc e) {
459             Util.log(e, "Could not create binding from binding key: " + getKey()); //$NON-NLS-1$
460
return null;
461         }
462     }
463     
464     private TypeBinding getTypeBinding(char[] simpleTypeName) {
465         if (this.typeBinding instanceof BinaryTypeBinding) {
466             return ((BinaryTypeBinding) this.typeBinding).getMemberType(simpleTypeName);
467         } else {
468             TypeDeclaration[] typeDeclarations =
469                 this.typeDeclaration == null ?
470                     (this.parsedUnit == null ? null : this.parsedUnit.types) :
471                     this.typeDeclaration.memberTypes;
472             if (typeDeclarations == null) return null;
473             for (int i = 0, length = typeDeclarations.length; i < length; i++) {
474                 TypeDeclaration declaration = typeDeclarations[i];
475                 if (CharOperation.equals(simpleTypeName, declaration.name)) {
476                     this.typeDeclaration = declaration;
477                     return declaration.binding;
478                 }
479             }
480         }
481         return null;
482     }
483     
484     private TypeBinding[] getTypeBindingArguments() {
485         int size = this.types.size();
486         TypeBinding[] arguments = new TypeBinding[size];
487         for (int i = 0; i < size; i++) {
488             BindingKeyResolver resolver = (BindingKeyResolver) this.types.get(i);
489             TypeBinding compilerBinding2 = (TypeBinding) resolver.compilerBinding;
490             if (compilerBinding2 == null) {
491                 throw new IllegalArgumentException JavaDoc();
492             }
493             arguments[i] = compilerBinding2;
494         }
495         this.types = new ArrayList JavaDoc();
496         return arguments;
497     }
498      
499     public void malformedKey() {
500         this.compoundName = CharOperation.NO_CHAR_CHAR;
501     }
502     
503     public BindingKeyParser newParser() {
504         return new BindingKeyResolver(this, this.compiler, this.environment, this.rank, this.outerMostParsedUnit == null ? this.parsedUnit : this.outerMostParsedUnit);
505     }
506      
507     public String JavaDoc toString() {
508         return getKey();
509     }
510
511 }
512
Popular Tags