All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.aspectj.weaver.BoundedReferenceType Maven / Gradle / Ivy

Go to download

AspectJ tools most notably contains the AspectJ compiler (AJC). AJC applies aspects to Java classes during compilation, fully replacing Javac for plain Java classes and also compiling native AspectJ or annotation-based @AspectJ syntax. Furthermore, AJC can weave aspects into existing class files in a post-compile binary weaving step. This library is a superset of AspectJ weaver and hence also of AspectJ runtime.

There is a newer version: 1.9.22.1
Show newest version
/* *******************************************************************
 * Copyright (c) 2010 Contributors.
 * All rights reserved.
 * This program and the accompanying materials are made available
 * under the terms of the Eclipse Public License v 2.0
 * which accompanies this distribution and is available at
 * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
 * ******************************************************************/
package org.aspectj.weaver;

import java.util.Map;

/**
 * A BoundedReferenceType is the result of a generics wildcard expression ? extends String, ? super Foo etc..
 *
 * The "signature" for a bounded reference type follows the generic signature specification in section 4.4 of JVM spec: *,+,- plus
 * signature strings.
 *
 * The bound may be a type variable (e.g. ? super T)
 *
 * @author Adrian Colyer
 * @author Andy Clement
 */
public class BoundedReferenceType extends ReferenceType {

	// possible kinds of BoundedReferenceType
	public static final int UNBOUND = 0;
	public static final int EXTENDS = 1;
	public static final int SUPER = 2;

	public int kind;

	private ResolvedType lowerBound;

	private ResolvedType upperBound;

	protected ReferenceType[] additionalInterfaceBounds = ReferenceType.EMPTY_ARRAY;

	public BoundedReferenceType(ReferenceType aBound, boolean isExtends, World world) {
		super((isExtends ? "+" : "-") + aBound.signature, aBound.signatureErasure, world);
		if (isExtends) {
			this.kind = EXTENDS;
		} else {
			this.kind = SUPER;
		}
		if (isExtends) {
			upperBound = aBound;
		} else {
			lowerBound = aBound;
			upperBound = world.resolve(UnresolvedType.OBJECT);
		}
		setDelegate(new BoundedReferenceTypeDelegate((ReferenceType) getUpperBound()));
	}

	public BoundedReferenceType(ReferenceType aBound, boolean isExtends, World world, ReferenceType[] additionalInterfaces) {
		this(aBound, isExtends, world);
		this.additionalInterfaceBounds = additionalInterfaces;
	}

	/**
	 * only for use when resolving GenericsWildcardTypeX or a TypeVariableReferenceType
	 */
	protected BoundedReferenceType(String signature, String erasedSignature, World world) {
		super(signature, erasedSignature, world);
		if (signature.equals("*")) {
			// pure wildcard
			this.kind = UNBOUND;
			upperBound = world.resolve(UnresolvedType.OBJECT);
		} else {
			upperBound = world.resolve(forSignature(erasedSignature));
		}
		setDelegate(new BoundedReferenceTypeDelegate((ReferenceType) upperBound));
	}

	/**
	 * Constructs the BoundedReferenceType representing an unbounded wildcard '?'. In this situation the signature is '*' and the
	 * erased signature is Ljava/lang/Object;
	 */
	public BoundedReferenceType(World world) {
		super("*", "Ljava/lang/Object;", world);
		this.kind = UNBOUND;
		upperBound = world.resolve(UnresolvedType.OBJECT);
		setDelegate(new BoundedReferenceTypeDelegate((ReferenceType) upperBound));
	}

	public UnresolvedType getUpperBound() {
		return upperBound;
	}

	public UnresolvedType getLowerBound() {
		return lowerBound;
	}

	public ReferenceType[] getAdditionalBounds() {
		return additionalInterfaceBounds;
	}

	@Override
	public UnresolvedType parameterize(Map typeBindings) {
		if (this.kind == UNBOUND) {
			return this;
		}
		ReferenceType[] parameterizedAdditionalInterfaces = new ReferenceType[additionalInterfaceBounds == null ? 0
				: additionalInterfaceBounds.length];
		for (int i = 0; i < parameterizedAdditionalInterfaces.length; i++) {
			parameterizedAdditionalInterfaces[i] = (ReferenceType) additionalInterfaceBounds[i].parameterize(typeBindings);
		}
		if (this.kind == EXTENDS) {
			UnresolvedType parameterizedUpperBound = getUpperBound().parameterize(typeBindings);
			if (!(parameterizedUpperBound instanceof ReferenceType)) {
				throw new IllegalStateException("DEBUG551732: Unexpected problem processing bounds. Parameterizing "+getUpperBound()+" produced "+parameterizedUpperBound+
						" (Type: "+parameterizedUpperBound==null?"null":parameterizedUpperBound.getClass().getName()+") (typeBindings="+typeBindings+")");
			}
			return new BoundedReferenceType((ReferenceType) parameterizedUpperBound, true, world,
					parameterizedAdditionalInterfaces);
		} else {
			// (this.kind == SUPER)
			UnresolvedType parameterizedLowerBound = getLowerBound().parameterize(typeBindings);
			if (!(parameterizedLowerBound instanceof ReferenceType)) {
				throw new IllegalStateException("PR543023: Unexpectedly found a non reference type: "+
						parameterizedLowerBound.getClass().getName()+" with signature "+parameterizedLowerBound.getSignature());
			}
			return new BoundedReferenceType((ReferenceType)parameterizedLowerBound , false, world,
					parameterizedAdditionalInterfaces);
		}
	}

	@Override
	public String getSignatureForAttribute() {
		StringBuilder ret = new StringBuilder();
		if (kind==SUPER){
			ret.append("-");
			ret.append(lowerBound.getSignatureForAttribute());
			for (ReferenceType additionalInterfaceBound : additionalInterfaceBounds) {
				ret.append(additionalInterfaceBound.getSignatureForAttribute());
			}
		} else if (kind==EXTENDS) {
			ret.append("+");
			ret.append(upperBound.getSignatureForAttribute());
			for (ReferenceType additionalInterfaceBound : additionalInterfaceBounds) {
				ret.append(additionalInterfaceBound.getSignatureForAttribute());
			}
		} else if (kind==UNBOUND) {
			ret.append("*");
		}
		return ret.toString();
	}


	public boolean hasLowerBound() {
		return lowerBound != null;
	}

	public boolean isExtends() {
		return this.kind == EXTENDS;
	}

	public boolean isSuper() {
		return this.kind == SUPER;
	}

	public boolean isUnbound() {
		return this.kind == UNBOUND;
	}

	public boolean alwaysMatches(ResolvedType aCandidateType) {
		if (isExtends()) {
			// aCandidateType must be a subtype of upperBound
			return ((ReferenceType) getUpperBound()).isAssignableFrom(aCandidateType);
		} else if (isSuper()) {
			// aCandidateType must be a supertype of lowerBound
			return aCandidateType.isAssignableFrom((ReferenceType) getLowerBound());
		} else {
			return true; // straight '?'
		}
	}

	// this "maybe matches" that
	public boolean canBeCoercedTo(ResolvedType aCandidateType) {
		if (alwaysMatches(aCandidateType)) {
			return true;
		}
		if (aCandidateType.isGenericWildcard()) {
			BoundedReferenceType boundedRT = (BoundedReferenceType) aCandidateType;
			ResolvedType myUpperBound = (ResolvedType) getUpperBound();
			ResolvedType myLowerBound = (ResolvedType) getLowerBound();
			if (isExtends()) {
				if (boundedRT.isExtends()) {
					return myUpperBound.isAssignableFrom((ResolvedType) boundedRT.getUpperBound());
				} else if (boundedRT.isSuper()) {
					return myUpperBound == boundedRT.getLowerBound();
				} else {
					return true; // it's '?'
				}
			} else if (isSuper()) {
				if (boundedRT.isSuper()) {
					return ((ResolvedType) boundedRT.getLowerBound()).isAssignableFrom(myLowerBound);
				} else if (boundedRT.isExtends()) {
					return myLowerBound == boundedRT.getUpperBound();
				} else {
					return true;
				}
			} else {
				return true;
			}
		} else {
			return false;
		}
	}

	@Override
	public String getSimpleName() {
		if (!isExtends() && !isSuper()) {
			return "?";
		}
		if (isExtends()) {
			return ("? extends " + getUpperBound().getSimpleName());
		} else {
			return ("? super " + getLowerBound().getSimpleName());
		}
	}

	// override to include additional interface bounds...
	@Override
	public ResolvedType[] getDeclaredInterfaces() {
		ResolvedType[] interfaces = super.getDeclaredInterfaces();
		if (additionalInterfaceBounds.length > 0) {
			ResolvedType[] allInterfaces = new ResolvedType[interfaces.length + additionalInterfaceBounds.length];
			System.arraycopy(interfaces, 0, allInterfaces, 0, interfaces.length);
			System.arraycopy(additionalInterfaceBounds, 0, allInterfaces, interfaces.length, additionalInterfaceBounds.length);
			return allInterfaces;
		} else {
			return interfaces;
		}
	}

	@Override
	public boolean isGenericWildcard() {
		return true;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy