123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206 |
- /* *******************************************************************
- * 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$<adviceSequenceNumber>[$<ifnumberinPcd>]$<hashcodeOfIfExpressionInHex>
- 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[$<ifnumberinpcd>]$<hashcodeofpointcuttextandexpressiontext>
- 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;
- }
-
- }
|