org.aspectj.org.eclipse.jdt.internal.core.util.BindingKeyResolver Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of aspectjtools Show documentation
Show all versions of aspectjtools Show documentation
Tools from the AspectJ project
/*******************************************************************************
* Copyright (c) 2005, 2017 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
* Stephan Herrmann - Contribution for
* Bug 425183 - [1.8][inference] make CaptureBinding18 safe
* Bug 466308 - [hovering] Javadoc header for parameter is wrong with annotation-based null analysis
*******************************************************************************/
package org.aspectj.org.eclipse.jdt.internal.core.util;
import java.util.ArrayList;
import org.aspectj.org.eclipse.jdt.core.Signature;
import org.aspectj.org.eclipse.jdt.core.compiler.CharOperation;
import org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor;
import org.aspectj.org.eclipse.jdt.internal.compiler.Compiler;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ArrayReference;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Assignment;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.CastExpression;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ConditionalExpression;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.FieldReference;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.MessageSend;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Wildcard;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.Binding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.CaptureBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.CaptureBinding18;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.LocalTypeBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.PolymorphicMethodBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.RawTypeBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TagBits;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.VariableBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.WildcardBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
@SuppressWarnings({"rawtypes", "unchecked"})
public class BindingKeyResolver extends BindingKeyParser {
/** Synthetic bindings for local variables (method arguments) restored from a binding key. */
private final class SyntheticLocalVariableBinding extends LocalVariableBinding {
private final MethodBinding enclosingMethod;
private int paramPosition;
private char[] key;
SyntheticLocalVariableBinding(char[] name, TypeBinding type, MethodBinding enclosingMethod, int paramPosition) {
super(name, type, 0, true);
this.enclosingMethod = enclosingMethod;
this.paramPosition = paramPosition;
}
@Override
public char[] computeUniqueKey() {
if (this.key == null) {
// have no scope to find the enclosing method, so use the captured method:
StringBuilder buf = new StringBuilder().append(this.enclosingMethod.computeUniqueKey());
buf.append('#');
buf.append(this.name);
buf.append("#0#"); //$NON-NLS-1$
buf.append(this.paramPosition);
int length = buf.length();
this.key = new char[length];
buf.getChars(0, length, this.key, 0);
}
return this.key;
}
@Override
public MethodBinding getEnclosingMethod() {
return this.enclosingMethod;
}
@Override
public int hashCode() {
return CharOperation.hashCode(computeUniqueKey());
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof SyntheticLocalVariableBinding))
return false;
return CharOperation.equals(computeUniqueKey(), ((SyntheticLocalVariableBinding) obj).computeUniqueKey());
}
}
Compiler compiler;
Binding compilerBinding;
char[][] compoundName;
char[] moduleName;
int dimension;
LookupEnvironment environment;
ReferenceBinding genericType;
MethodBinding methodBinding;
AnnotationBinding annotationBinding;
char[] secondarySimpleName;
CompilationUnitDeclaration parsedUnit;
BlockScope scope;
TypeBinding typeBinding;
TypeDeclaration typeDeclaration;
ArrayList types = new ArrayList();
int wildcardRank;
CompilationUnitDeclaration outerMostParsedUnit;
/*
* A hash set of the file names of already resolved units
*/
HashtableOfObject resolvedUnits;
private BindingKeyResolver(BindingKeyParser parser, Compiler compiler, LookupEnvironment environment, CompilationUnitDeclaration outerMostParsedUnit, HashtableOfObject parsedUnits) {
super(parser);
this.compiler = compiler;
this.environment = environment;
this.outerMostParsedUnit = outerMostParsedUnit;
this.resolvedUnits = parsedUnits;
}
public BindingKeyResolver(String key, Compiler compiler, LookupEnvironment environment) {
super(key);
this.compiler = compiler;
this.environment = environment;
this.resolvedUnits = new HashtableOfObject();
}
/*
* If not already cached, computes and cache the compound name (pkg name + top level name) of this key.
* Returns the package name if key is a pkg key.
* Returns an empty array if malformed.
* This key's scanner should be positioned on the package or type token.
*/
public char[][] compoundName() {
return this.compoundName;
}
public char[] moduleName() {
return this.moduleName;
}
@Override
public void consumeAnnotation() {
int size = this.types.size();
if (size == 0) return;
Binding annotationType = ((BindingKeyResolver) this.types.get(size-1)).compilerBinding;
AnnotationBinding[] annotationBindings;
if (this.compilerBinding == null && this.typeBinding instanceof ReferenceBinding) {
annotationBindings = ((ReferenceBinding) this.typeBinding).getAnnotations();
} else if (this.compilerBinding instanceof MethodBinding) {
annotationBindings = ((MethodBinding) this.compilerBinding).getAnnotations();
} else if (this.compilerBinding instanceof VariableBinding) {
annotationBindings = ((VariableBinding) this.compilerBinding).getAnnotations();
} else {
return;
}
for (int i = 0, length = annotationBindings.length; i < length; i++) {
AnnotationBinding binding = annotationBindings[i];
if (binding.getAnnotationType() == annotationType) {
this.annotationBinding = binding;
break;
}
}
}
@Override
public void consumeArrayDimension(char[] brakets) {
this.dimension = brakets.length;
}
@Override
public void consumeBaseType(char[] baseTypeSig) {
this.compoundName = new char[][] {getKey().toCharArray()};
TypeBinding baseTypeBinding = getBaseTypeBinding(baseTypeSig);
if (baseTypeBinding != null) {
this.typeBinding = baseTypeBinding;
}
}
@Override
public void consumeCapture18ID(int id, int position) {
consumeAnyCapture(id, position);
}
@Override
public void consumeCapture(final int position) {
consumeAnyCapture(-1, position);
}
public void consumeAnyCapture(final int capture18id, final int position) {
CompilationUnitDeclaration outerParsedUnit = this.outerMostParsedUnit == null ? this.parsedUnit : this.outerMostParsedUnit;
if (outerParsedUnit == null) return;
final Binding wildcardBinding = this.types.size() > 0 // 0 may happen for CaptureBinding18
? ((BindingKeyResolver) this.types.get(0)).compilerBinding : null;
class CaptureFinder extends ASTVisitor {
CaptureBinding capture;
boolean checkType(TypeBinding binding) {
if (binding == null)
return false;
switch (binding.kind()) {
case Binding.PARAMETERIZED_TYPE:
TypeBinding[] arguments = ((ParameterizedTypeBinding) binding).arguments;
if (arguments == null) return false;
for (int i = 0, length = arguments.length; i < length; i++) {
if (checkType(arguments[i]))
return true;
}
break;
case Binding.WILDCARD_TYPE:
return checkType(((WildcardBinding) binding).bound);
case Binding.INTERSECTION_TYPE:
if (checkType(((WildcardBinding) binding).bound))
return true;
TypeBinding[] otherBounds = ((WildcardBinding) binding).otherBounds;
// per construction, otherBounds is never null
for (int i = 0, length = otherBounds.length; i < length; i++) {
if (checkType(otherBounds[i]))
return true;
}
break;
case Binding.ARRAY_TYPE:
return checkType(((ArrayBinding) binding).leafComponentType);
case Binding.TYPE_PARAMETER:
if (binding.isCapture()) {
CaptureBinding captureBinding = (CaptureBinding) binding;
if (captureBinding.end == position && captureBinding.wildcard == wildcardBinding) {
if (captureBinding instanceof CaptureBinding18) {
if (((CaptureBinding18)captureBinding).captureID != capture18id)
return false;
}
this.capture = captureBinding;
return true;
}
}
break;
}
return false;
}
@Override
public boolean visit(SingleNameReference singleNameReference, BlockScope blockScope) {
if (checkType(singleNameReference.resolvedType))
return false;
return super.visit(singleNameReference, blockScope);
}
@Override
public boolean visit(QualifiedNameReference qualifiedNameReference, BlockScope blockScope) {
if (checkType(qualifiedNameReference.resolvedType))
return false;
return super.visit(qualifiedNameReference, blockScope);
}
@Override
public boolean visit(MessageSend messageSend, BlockScope blockScope) {
if (checkType(messageSend.resolvedType))
return false;
return super.visit(messageSend, blockScope);
}
@Override
public boolean visit(FieldReference fieldReference, BlockScope blockScope) {
if (checkType(fieldReference.resolvedType))
return false;
return super.visit(fieldReference, blockScope);
}
@Override
public boolean visit(ConditionalExpression conditionalExpression, BlockScope blockScope) {
if (checkType(conditionalExpression.resolvedType))
return false;
return super.visit(conditionalExpression, blockScope);
}
@Override
public boolean visit(CastExpression castExpression, BlockScope blockScope) {
if (checkType(castExpression.resolvedType))
return false;
return super.visit(castExpression, blockScope);
}
@Override
public boolean visit(Assignment assignment, BlockScope blockScope) {
if (checkType(assignment.resolvedType))
return false;
return super.visit(assignment, blockScope);
}
@Override
public boolean visit(ArrayReference arrayReference, BlockScope blockScope) {
if (checkType(arrayReference.resolvedType))
return false;
return super.visit(arrayReference, blockScope);
}
}
CaptureFinder captureFinder = new CaptureFinder();
outerParsedUnit.traverse(captureFinder, outerParsedUnit.scope);
this.typeBinding = captureFinder.capture;
}
@Override
public void consumeException() {
this.types = new ArrayList();
}
@Override
public void consumeField(char[] fieldName) {
if (this.typeBinding == null)
return;
FieldBinding[] fields = ((ReferenceBinding) this.typeBinding).availableFields(); // resilience
for (int i = 0, length = fields.length; i < length; i++) {
FieldBinding field = fields[i];
if (CharOperation.equals(fieldName, field.name)) {
this.typeBinding = null;
this.compilerBinding = field;
return;
}
}
}
@Override
public void consumeParameterizedGenericMethod() {
if (this.methodBinding == null)
return;
TypeBinding[] arguments = getTypeBindingArguments();
if (arguments == null) {
this.methodBinding = null;
this.compilerBinding = null;
return;
}
if (arguments.length != this.methodBinding.typeVariables().length)
this.methodBinding = this.environment.createParameterizedGenericMethod(this.methodBinding, (RawTypeBinding) null);
else
this.methodBinding = this.environment.createParameterizedGenericMethod(this.methodBinding, arguments);
this.compilerBinding = this.methodBinding;
}
@Override
public void consumeLocalType(char[] uniqueKey) {
if (this.parsedUnit == null) {
this.typeBinding = null;
return;
}
LocalTypeBinding[] localTypeBindings = this.parsedUnit.localTypes;
for (int i = 0; i < this.parsedUnit.localTypeCount; i++)
if (CharOperation.equals(uniqueKey, localTypeBindings[i].computeUniqueKey(false/*not a leaf*/))) {
this.typeBinding = localTypeBindings[i];
return;
}
}
@Override
public void consumeLocalVar(char[] varName, int occurrenceCount, int argumentPosition) {
if (this.scope == null) {
if (this.methodBinding == null)
return;
AbstractMethodDeclaration sourceMethod = this.methodBinding.sourceMethod();
if (sourceMethod != null) {
this.scope = sourceMethod.scope;
} else {
char[][] parameterNames = this.methodBinding.parameterNames;
int paramPosition = -1;
if (parameterNames.length == 0) {
paramPosition = argumentPosition;
} else {
for (int i = 0; i < parameterNames.length; i++) {
if (CharOperation.equals(parameterNames[i], varName)) {
paramPosition = i;
break;
}
}
}
if (paramPosition != -1) {
// we don't have a compiler binding for this argument, but we can craft one:
this.compilerBinding = new SyntheticLocalVariableBinding(varName, this.methodBinding.parameters[paramPosition], this.methodBinding, paramPosition);
this.methodBinding = null;
return;
}
}
}
if (this.scope != null) {
for (int i = 0; i < this.scope.localIndex; i++) {
LocalVariableBinding local = this.scope.locals[i];
if (CharOperation.equals(local.name, varName)
&& occurrenceCount-- == 0) {
this.methodBinding = null;
this.compilerBinding = local;
return;
}
}
}
}
@Override
public void consumeMethod(char[] selector, char[] signature) {
if (this.typeBinding == null)
return;
MethodBinding[] methods = ((ReferenceBinding) this.typeBinding).availableMethods(); // resilience
for (int i = 0, methodLength = methods.length; i < methodLength; i++) {
MethodBinding method = methods[i];
if (CharOperation.equals(selector, method.selector) || (selector.length == 0 && method.isConstructor())) {
char[] methodSignature = method.genericSignature();
if (methodSignature == null)
methodSignature = method.signature();
if (CharOperation.equals(signature, methodSignature)) {
this.typeBinding = null;
this.methodBinding = method;
this.compilerBinding = this.methodBinding;
return;
} else if ((method.tagBits & TagBits.AnnotationPolymorphicSignature) != 0) {
this.typeBinding = null;
char[][] typeParameters = Signature.getParameterTypes(signature);
int length = typeParameters.length;
TypeBinding[] parameterTypes = new TypeBinding[length];
for (int j = 0; j < length; j++) {
parameterTypes[j] = getType(typeParameters[j]);
}
PolymorphicMethodBinding polymorphicMethod = this.environment.createPolymorphicMethod(method, parameterTypes, this.scope);
this.methodBinding = polymorphicMethod;
this.methodBinding = this.environment.updatePolymorphicMethodReturnType(
polymorphicMethod,
getType(Signature.getReturnType(signature)));
this.compilerBinding = this.methodBinding;
return;
}
}
}
}
private TypeBinding getType(char[] type) {
TypeBinding binding = null;
int length = type.length;
switch(length) {
case 1 :
switch (type[0]) {
case 'I' :
binding = TypeBinding.INT;
break;
case 'Z' :
binding = TypeBinding.BOOLEAN;
break;
case 'V' :
binding = TypeBinding.VOID;
break;
case 'C' :
binding = TypeBinding.CHAR;
break;
case 'D' :
binding = TypeBinding.DOUBLE;
break;
case 'B' :
binding = TypeBinding.BYTE;
break;
case 'F' :
binding = TypeBinding.FLOAT;
break;
case 'J' :
binding = TypeBinding.LONG;
break;
case 'S' :
binding = TypeBinding.SHORT;
break;
}
break;
default:
int dimensions = 0;
int start = 0;
while (type[start] == '[') {
start++;
dimensions++;
}
binding = this.environment.getType(CharOperation.splitOn('/', type, start + 1, length - 1));
if (dimensions != 0) {
binding = this.environment.createArrayType(binding, dimensions);
}
}
return binding;
}
@Override
public void consumeMemberType(char[] simpleTypeName) {
this.typeBinding = getTypeBinding(simpleTypeName);
}
@Override
public void consumePackage(char[] pkgName) {
this.compoundName = CharOperation.splitOn('/', pkgName);
this.compilerBinding = new PackageBinding(this.compoundName, null, this.environment, this.environment.module); //TODO(SHMOD) enclosingModule
}
@Override
public void consumeParameterizedType(char[] simpleTypeName, boolean isRaw) {
if (this.typeBinding == null)
return;
TypeBinding[] arguments = getTypeBindingArguments();
if (arguments == null) {
this.typeBinding = null;
this.genericType = null;
return;
}
if (simpleTypeName != null) {
if (this.genericType == null) {
// parameterized member type with raw enclosing type
this.genericType = ((ReferenceBinding) this.typeBinding).getMemberType(simpleTypeName);
} else {
// parameterized member type with parameterized enclosing type
this.genericType = this.genericType.getMemberType(simpleTypeName);
}
if (!isRaw)
this.typeBinding = this.environment.createParameterizedType(this.genericType, arguments, (ReferenceBinding) this.typeBinding);
else
// raw type
this.typeBinding = this.environment.createRawType(this.genericType, (ReferenceBinding) this.typeBinding);
} else {
// parameterized top level type or parameterized member type with raw enclosing type
this.genericType = (ReferenceBinding) this.typeBinding;
ReferenceBinding enclosing = this.genericType.enclosingType();
if (enclosing != null) enclosing = (ReferenceBinding) this.environment.convertToRawType(enclosing, false /*do not force conversion of enclosing types*/);
this.typeBinding = this.environment.createParameterizedType(this.genericType, arguments, enclosing);
}
}
@Override
public void consumeParser(BindingKeyParser parser) {
this.types.add(parser);
}
@Override
public void consumeScope(int scopeNumber) {
if (this.scope == null) {
if (this.methodBinding == null)
return;
this.scope = this.methodBinding.sourceMethod().scope;
}
if (scopeNumber >= this.scope.subscopeCount)
return; // malformed key
this.scope = (BlockScope) this.scope.subscopes[scopeNumber];
}
@Override
public void consumeRawType() {
if (this.typeBinding == null) return;
this.typeBinding = this.environment.convertToRawType(this.typeBinding, false /*do not force conversion of enclosing types*/);
}
@Override
public void consumeSecondaryType(char[] simpleTypeName) {
this.secondarySimpleName = simpleTypeName;
}
@Override
public void consumeFullyQualifiedName(char[] fullyQualifiedName) {
this.compoundName = CharOperation.splitOn('/', fullyQualifiedName);
}
@Override
public void consumeTopLevelType() {
char[] fileName;
this.parsedUnit = getCompilationUnitDeclaration();
if (this.parsedUnit != null && this.compiler != null && !this.resolvedUnits.containsKey(fileName = this.parsedUnit.getFileName())) {
this.compiler.process(this.parsedUnit, this.compiler.totalUnits+1); // unit is resolved only once thanks to the resolvedUnits protection
this.resolvedUnits.put(fileName, fileName);
}
if (this.parsedUnit == null) {
this.typeBinding = getBinaryBinding();
} else {
char[] typeName = this.secondarySimpleName == null ? this.compoundName[this.compoundName.length-1] : this.secondarySimpleName;
this.typeBinding = getTypeBinding(typeName);
}
}
@Override
public void consumeKey() {
if (this.typeBinding != null) {
this.typeBinding = getArrayBinding(this.dimension, this.typeBinding);
this.compilerBinding = this.typeBinding;
}
}
@Override
public void consumeTypeVariable(char[] position, char[] typeVariableName) {
if (position.length > 0) {
if (this.typeBinding == null)
return;
int pos = Integer.parseInt(new String(position));
MethodBinding[] methods = ((ReferenceBinding) this.typeBinding).availableMethods(); // resilience
if (methods != null && pos < methods.length) {
this.methodBinding = methods[pos];
}
}
TypeVariableBinding[] typeVariableBindings;
if (this.methodBinding != null) {
typeVariableBindings = this.methodBinding.typeVariables();
} else if (this.typeBinding != null) {
typeVariableBindings = this.typeBinding.typeVariables();
} else {
return;
}
for (int i = 0, length = typeVariableBindings.length; i < length; i++) {
TypeVariableBinding typeVariableBinding = typeVariableBindings[i];
if (CharOperation.equals(typeVariableName, typeVariableBinding.sourceName())) {
this.typeBinding = typeVariableBinding;
return;
}
}
}
@Override
public void consumeTypeWithCapture() {
BindingKeyResolver resolver = (BindingKeyResolver) this.types.get(0);
this.typeBinding =(TypeBinding) resolver.compilerBinding;
}
@Override
public void consumeWildcardRank(int aRank) {
this.wildcardRank = aRank;
}
@Override
public void consumeWildCard(int kind) {
switch (kind) {
case Wildcard.EXTENDS:
case Wildcard.SUPER:
BindingKeyResolver boundResolver = (BindingKeyResolver) this.types.get(0);
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=157847, do not allow creation of
// internally inconsistent wildcards of the form '? super ' or '? extends '
final Binding boundBinding = boundResolver.compilerBinding;
if (boundBinding instanceof TypeBinding) {
this.typeBinding = this.environment.createWildcard((ReferenceBinding) this.typeBinding, this.wildcardRank, (TypeBinding) boundBinding, null /*no extra bound*/, kind);
} else {
this.typeBinding = null;
}
break;
case Wildcard.UNBOUND:
this.typeBinding = this.environment.createWildcard((ReferenceBinding) this.typeBinding, this.wildcardRank, null/*no bound*/, null /*no extra bound*/, kind);
break;
}
}
@Override
public void consumeModule(char[] aModuleName) {
this.moduleName = aModuleName;
this.compilerBinding = this.environment.getModule(aModuleName);
}
public AnnotationBinding getAnnotationBinding() {
return this.annotationBinding;
}
/*
* If the given dimension is greater than 0 returns an array binding for the given type binding.
* Otherwise return the given type binding.
* Returns null if the given type binding is null.
*/
private TypeBinding getArrayBinding(int dim, TypeBinding binding) {
if (binding == null) return null;
if (dim == 0) return binding;
return this.environment.createArrayType(binding, dim);
}
private TypeBinding getBaseTypeBinding(char[] signature) {
switch (signature[0]) {
case 'I' :
return TypeBinding.INT;
case 'Z' :
return TypeBinding.BOOLEAN;
case 'V' :
return TypeBinding.VOID;
case 'C' :
return TypeBinding.CHAR;
case 'D' :
return TypeBinding.DOUBLE;
case 'B' :
return TypeBinding.BYTE;
case 'F' :
return TypeBinding.FLOAT;
case 'J' :
return TypeBinding.LONG;
case 'S' :
return TypeBinding.SHORT;
case 'N':
return TypeBinding.NULL;
default :
return null;
}
}
/*
* Returns a binary binding corresonding to this key's compound name.
* Returns null if not found.
*/
private TypeBinding getBinaryBinding() {
if (this.compoundName.length == 0) return null;
return this.environment.getType(this.compoundName);
}
/*
* Finds the compilation unit declaration corresponding to the key in the given lookup environment.
* Returns null if no compilation unit declaration could be found.
* This key's scanner should be positioned on the package token.
*/
public CompilationUnitDeclaration getCompilationUnitDeclaration() {
char[][] name = this.compoundName;
if (name.length == 0) return null;
if (this.environment == null) return null;
ReferenceBinding binding = this.environment.getType(name);
if (!(binding instanceof SourceTypeBinding)) {
if (this.secondarySimpleName == null)
return null;
// case of a secondary type with no primary type (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=177115)
int length = name.length;
System.arraycopy(name, 0, name = new char[length][], 0, length-1);
name[length-1] = this.secondarySimpleName;
binding = this.environment.getType(name);
if (!(binding instanceof SourceTypeBinding))
return null;
}
SourceTypeBinding sourceTypeBinding = (SourceTypeBinding) binding;
if (sourceTypeBinding.scope == null)
return null;
return sourceTypeBinding.scope.compilationUnitScope().referenceContext;
}
/*
* Returns the compiler binding corresponding to this key.
* Returns null is malformed.
* This key's scanner should be positioned on the package token.
*/
public Binding getCompilerBinding() {
try {
parse();
return this.compilerBinding;
} catch (RuntimeException e) {
Util.log(e, "Could not create binding from binding key: " + getKey()); //$NON-NLS-1$
return null;
}
}
private TypeBinding getTypeBinding(char[] simpleTypeName) {
if (this.typeBinding instanceof ReferenceBinding) {
return ((ReferenceBinding) this.typeBinding).getMemberType(simpleTypeName);
}
TypeDeclaration[] typeDeclarations =
this.typeDeclaration == null ?
(this.parsedUnit == null ? null : this.parsedUnit.types) :
this.typeDeclaration.memberTypes;
if (typeDeclarations == null) return null;
for (int i = 0, length = typeDeclarations.length; i < length; i++) {
TypeDeclaration declaration = typeDeclarations[i];
if (CharOperation.equals(simpleTypeName, declaration.name)) {
this.typeDeclaration = declaration;
return declaration.binding;
}
}
return null;
}
private TypeBinding[] getTypeBindingArguments() {
int size = this.types.size();
TypeBinding[] arguments = new TypeBinding[size];
for (int i = 0; i < size; i++) {
BindingKeyResolver resolver = (BindingKeyResolver) this.types.get(i);
TypeBinding compilerBinding2 = (TypeBinding) resolver.compilerBinding;
if (compilerBinding2 == null) {
this.types = new ArrayList();
return null;
}
arguments[i] = compilerBinding2;
}
this.types = new ArrayList();
return arguments;
}
@Override
public void malformedKey() {
this.compoundName = CharOperation.NO_CHAR_CHAR;
}
@Override
public BindingKeyParser newParser() {
return new BindingKeyResolver(this, this.compiler, this.environment, this.outerMostParsedUnit == null ? this.parsedUnit : this.outerMostParsedUnit, this.resolvedUnits);
}
@Override
public String toString() {
return getKey();
}
}