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

org.aspectj.ajdt.internal.compiler.ast.IfPseudoToken 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) 2002 Palo Alto Research Center, Incorporated (PARC).
 * 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
 *
 * Contributors:
 *     PARC     initial implementation
 * ******************************************************************/

package org.aspectj.ajdt.internal.compiler.ast;

import java.lang.reflect.Modifier;

import org.aspectj.org.eclipse.jdt.core.compiler.CharOperation;
import org.aspectj.org.eclipse.jdt.internal.compiler.CompilationResult;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Annotation;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Argument;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Expression;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.FalseLiteral;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.MemberValuePair;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.NormalAnnotation;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ReturnStatement;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.SingleTypeReference;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Statement;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.StringLiteral;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TrueLiteral;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.aspectj.org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.parser.Parser;
import org.aspectj.weaver.Member;
import org.aspectj.weaver.ResolvedMemberImpl;
import org.aspectj.weaver.UnresolvedType;
import org.aspectj.weaver.patterns.IfPointcut;
import org.aspectj.weaver.patterns.Pointcut;

/**
 * (formals*): ... if(expr) ...
 *
 * generates the following: public static final boolean ajc$if_N(formals*,
 * [thisJoinPoints as needed]) { return expr; }
 *
 * Here's the complicated bit, it deals with cflow: (a): ... this(a) && cflow(if
 * (a == foo)) is an error. The way we capture this is: We generate the ajc$if
 * method with an (a) parameter, we let eclipse do the proper name binding. We
 * then, as a post pass (that we need to do anyway) look for the used
 * parameters. If a is used, we signal an error because a was not one of the
 * cflow variables. XXX we'll do this part after we do cflow
 *
 * The IfPointcut pcd then generates itself always as a dynamic test, it has to
 * get the right parameters through any named pointcut references...
 */
public class IfPseudoToken extends PseudoToken {
	public Expression expr;
	public MethodDeclaration testMethod;
	private IfPointcut pointcut;

	public IfPseudoToken(Parser parser, Expression expr) {
		super(parser, "if", false);
		this.expr = expr;
	}

	public Pointcut maybeGetParsedPointcut() {
		if (expr instanceof FalseLiteral) {
			return IfPointcut.makeIfFalsePointcut(Pointcut.SYMBOLIC);
		} else if (expr instanceof TrueLiteral) {
			return IfPointcut.makeIfTruePointcut(Pointcut.SYMBOLIC);
		} else {
			pointcut = new IfPointcut(new ResolvedMemberImpl(Member.METHOD,
					UnresolvedType.OBJECT, 0, "if_", "()V"), 0);
		}
		return pointcut;

	}

	/**
	 * enclosingDec is either AdviceDeclaration or PointcutDeclaration
	 */
	public int postParse(TypeDeclaration typeDec,
			MethodDeclaration enclosingDec, int counter) {
		// typeDec.scope.problemReporter().signalError(sourceStart, sourceEnd,
		// "if pcd is not implemented in 1.1alpha1");
		// XXX need to implement correctly
		if (pointcut == null)
			return 0;

		testMethod = makeIfMethod(enclosingDec.compilationResult, enclosingDec, typeDec, counter);
		AstUtil.addMethodDeclaration(typeDec, testMethod);
		return 1;
	}

	private final static char[] CodeGenerationHint = "CodeGenerationHint".toCharArray();
	private final static char[] FullyQualifiedCodeGenerationHint = "org.aspectj.lang.annotation.control.CodeGenerationHint".toCharArray();
	private final static char[] IfNameSuffix = "ifNameSuffix".toCharArray();

	// XXX todo: make sure that errors in Arguments only get displayed once
	private MethodDeclaration makeIfMethod(CompilationResult result, MethodDeclaration enclosingDec, TypeDeclaration containingTypeDec, int counter) {
		MethodDeclaration ret = new IfMethodDeclaration(result, pointcut);
		ret.modifiers = ClassFileConstants.AccStatic | ClassFileConstants.AccFinal | ClassFileConstants.AccPublic;
		ret.returnType = AstUtil.makeTypeReference(TypeBinding.BOOLEAN);

		String nameSuffix = null;

		if (enclosingDec!=null && enclosingDec.annotations!=null) {
			NormalAnnotation interestingAnnotation = null;
			Annotation[] as = enclosingDec.annotations;
			if (as!=null) {
				for (int a = 0; a < as.length && interestingAnnotation == null; a++) {
					if (as[a] instanceof NormalAnnotation) {
						TypeReference tr = as[a].type;
						if (tr instanceof SingleTypeReference) {
							if (CharOperation.equals(CodeGenerationHint,((SingleTypeReference)tr).token)) {
								interestingAnnotation = (NormalAnnotation)as[a];
							}
						} else if (tr instanceof QualifiedTypeReference) {
							char[] qualifiedName = CharOperation.concatWith(((QualifiedTypeReference)tr).tokens,'.');
							if (CharOperation.equals(FullyQualifiedCodeGenerationHint,qualifiedName)) {
								interestingAnnotation = (NormalAnnotation)as[a];
							}
						}
					}
				}
			}
			if (interestingAnnotation!=null) {
				MemberValuePair[] memberValuePairs = interestingAnnotation.memberValuePairs;
				for (MemberValuePair memberValuePair: memberValuePairs) {
					if (CharOperation.equals(IfNameSuffix,memberValuePair.name) && (memberValuePair.value instanceof StringLiteral)) {
						nameSuffix = new String(((StringLiteral)memberValuePair.value).source());
					}
				}
			}
		}


		// create a more stable name 277508
		StringBuilder ifSelector = new StringBuilder();
		ifSelector.append("ajc$if$");
		if (nameSuffix == null || nameSuffix.length()==0) {
			boolean computedName = false;
			try {
				// possibly even better logic for more reliable name:
				if (enclosingDec instanceof AdviceDeclaration) {
					// name is ajc$if$[$]$
					ifSelector.append(((AdviceDeclaration)enclosingDec).adviceSequenceNumberInType).append("$");
					if (counter!=0) {
						ifSelector.append(counter);
						ifSelector.append("$");
					}
					ifSelector.append(Integer.toHexString(expr.toString().hashCode()));
					computedName = true;
				} else if (enclosingDec instanceof PointcutDeclaration) {
					if (counter!=0) {
						ifSelector.append(counter);
						ifSelector.append("$");
					}
					StringBuilder toHash = new StringBuilder(((PointcutDeclaration) enclosingDec).getPointcutText());
					toHash.append(expr.toString());
					// name is pointcut selector then $if[$]$
					ifSelector.append(Integer.toHexString(toHash.toString().hashCode()));
					computedName = true;
				}
			} catch (Throwable t) {
				throw new IllegalStateException(t);
				// let it build a name the 'old way'
			}
			if (!computedName) {
				ifSelector.append(Integer.toHexString(expr.sourceStart));
			}
		} else {
			ifSelector.append(nameSuffix);
		}


		ret.selector = ifSelector.toString().toCharArray();
		ret.arguments = makeArguments(enclosingDec, containingTypeDec);
		ret.statements = new Statement[] { new ReturnStatement(expr,
				expr.sourceStart, expr.sourceEnd) };
		return ret;
	}

	private Argument[] makeArguments(MethodDeclaration enclosingDec,
			TypeDeclaration containingTypeDec) {
		Argument[] baseArguments = enclosingDec.arguments;
		int len = baseArguments.length;
		if (enclosingDec instanceof AdviceDeclaration) {
			len = ((AdviceDeclaration) enclosingDec).baseArgumentCount;
		}

		Argument[] ret = new Argument[len];
		for (int i = 0; i < len; i++) {
			Argument a = baseArguments[i];
			ret[i] = new Argument(a.name, AstUtil.makeLongPos(a.sourceStart,
					a.sourceEnd), a.type, Modifier.FINAL);
		}
		ret = AdviceDeclaration.addTjpArguments(ret, containingTypeDec);

		return ret;
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy