Package org.aspectj.ajdt.internal.compiler.ast

Source Code of org.aspectj.ajdt.internal.compiler.ast.Proceed

/* *******************************************************************
* Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
*               2004 contributors
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Eclipse Public License v1.0
* which accompanies this distribution and is available at
* http://www.eclipse.org/legal/epl-v10.html
* Contributors:
*     PARC     initial implementation
*     IBM      ongoing maintenance
* ******************************************************************/


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

import org.aspectj.org.eclipse.jdt.internal.compiler.ast.CastExpression;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Expression;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.MessageSend;
import org.aspectj.org.eclipse.jdt.internal.compiler.impl.Constant;
import org.aspectj.org.eclipse.jdt.internal.compiler.impl.ReferenceContext;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ClassScope;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MethodScope;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.Scope;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.aspectj.weaver.AdviceKind;

/**
* Used to represent any method call to a method named <code>proceed</code>.  During
* <code>resolvedType</code> it will be determined if this is actually in the body
* of an <code>around</code> advice and has no receiver (must be a bare proceed call,
* see pr 53981), and if not this will be treated like any other
* MessageSend.
*
* @author Jim Hugunin
*/
public class Proceed extends MessageSend {
  public boolean inInner = false;
 
  public Proceed(MessageSend parent) {
    super();
   
    this.receiver = parent.receiver;
    this.selector  = parent.selector;
    this.arguments  = parent.arguments;
    this.binding  = parent.binding;
    this.codegenBinding = parent.codegenBinding;
    this.syntheticAccessor = parent.syntheticAccessor;
    this.expectedType = parent.expectedType;

    this.nameSourcePosition = parent.nameSourcePosition;
    this.actualReceiverType = parent.actualReceiverType;
    //this.qualifyingType = parent.qualifyingType;
   
    this.valueCast = parent.valueCast;
    this.typeArguments = parent.typeArguments;
    this.genericTypeArguments = parent.genericTypeArguments;
   
    this.sourceStart = parent.sourceStart;
    this.sourceEnd = parent.sourceEnd;
  }

  public TypeBinding resolveType(BlockScope scope) {
    // find out if I'm really in an around body or not
    //??? this could in theory be done by the parser, but that appears to be hard
    AdviceDeclaration aroundDecl = findEnclosingAround(scope);
   
    if (aroundDecl == null) {
      return super.resolveType(scope);
    }
   
    constant = Constant.NotAConstant;
    binding = codegenBinding = aroundDecl.proceedMethodBinding;
   
    this.actualReceiverType = binding.declaringClass;
   
    int baseArgCount = 0;
    if (arguments != null) {
      baseArgCount = arguments.length;
      Expression[] newArguments = new Expression[baseArgCount + 1];
      System.arraycopy(arguments, 0, newArguments, 0, baseArgCount);
      arguments = newArguments;
    } else {
      arguments = new Expression[1];
    }
   
    arguments[baseArgCount] = AstUtil.makeLocalVariableReference(aroundDecl.extraArgument.binding);
   
    int declaredParameterCount = aroundDecl.getDeclaredParameterCount();
    if (baseArgCount < declaredParameterCount) {
      scope.problemReporter().signalError(this.sourceStart, this.sourceEnd,
                "too few arguments to proceed, expected " + declaredParameterCount);
      aroundDecl.ignoreFurtherInvestigation = true;
      return null; //binding.returnType;
    }
   
    if (baseArgCount > declaredParameterCount) {
      scope.problemReporter().signalError(this.sourceStart, this.sourceEnd,
                "too many arguments to proceed, expected " + declaredParameterCount);
      aroundDecl.ignoreFurtherInvestigation = true;
      return null; //binding.returnType;
    }

    boolean argsContainCast = false;
    for (int i=0; i<arguments.length;i++) {
      if (arguments[i] instanceof CastExpression) argsContainCast = true;
    //  if (arguments[i].constant==null) arguments[i].constant=Constant.NotAConstant;
    }
//    TypeBinding[] argumentTypes = Binding.NO_PARAMETERS;
//    if (this.arguments != null) {
//      boolean argHasError = false; // typeChecks all arguments
//      int length = this.arguments.length;
//      argumentTypes = new TypeBinding[length];
//      for (int i = 0; i < length; i++){
//        Expression argument = this.arguments[i];
//        if (argument instanceof CastExpression) {
//          argument.bits |= ASTNode.DisableUnnecessaryCastCheck; // will check later on
//          argsContainCast = true;
//        }
//        if ((argumentTypes[i] = argument.resolveType(scope)) == null){
//          argHasError = true;
//        }
//      }
//      if (argHasError) {
//        if (this.actualReceiverType instanceof ReferenceBinding) {
//          //  record a best guess, for clients who need hint about possible method match
//          TypeBinding[] pseudoArgs = new TypeBinding[length];
//          for (int i = length; --i >= 0;)
//            pseudoArgs[i] = argumentTypes[i] == null ? TypeBinding.NULL : argumentTypes[i]; // replace args with errors with null type
//          this.binding =
//            this.receiver.isImplicitThis()
//              ? scope.getImplicitMethod(this.selector, pseudoArgs, this)
//              : scope.findMethod((ReferenceBinding) this.actualReceiverType, this.selector, pseudoArgs, this);
//          if (this.binding != null && !this.binding.isValidBinding()) {
//            MethodBinding closestMatch = ((ProblemMethodBinding)this.binding).closestMatch;
//            // record the closest match, for clients who may still need hint about possible method match
//            if (closestMatch != null) {
//              if (closestMatch.original().typeVariables != Binding.NO_TYPE_VARIABLES) { // generic method
//                // shouldn't return generic method outside its context, rather convert it to raw method (175409)
//                closestMatch = scope.environment().createParameterizedGenericMethod(closestMatch.original(), (RawTypeBinding)null);
//              }
//              this.binding = closestMatch;
//              MethodBinding closestMatchOriginal = closestMatch.original();
//              if ((closestMatchOriginal.isPrivate() || closestMatchOriginal.declaringClass.isLocalType()) && !scope.isDefinedInMethod(closestMatchOriginal)) {
//                // ignore cases where method is used from within inside itself (e.g. direct recursions)
//                closestMatchOriginal.modifiers |= ExtraCompilerModifiers.AccLocallyUsed;
//              }
//            }
//          }
//        }
//        return null;
//      }
//    }
//


  //  checkInvocationArguments(scope, this.receiver, this.actualReceiverType, this.binding, this.arguments, argumentTypes, argsContainCast, this);
    for (int i=0, len=arguments.length; i < len; i++) {
      Expression arg = arguments[i];
      TypeBinding argType = arg.resolveType(scope);
      if (argType != null) {
        TypeBinding paramType = binding.parameters[i];
        if (!argType.isCompatibleWith(paramType)) {
          scope.problemReporter().typeMismatchError(argType, paramType, arg);
        }
      }
    }
    checkInvocationArguments(scope,null,this.actualReceiverType,binding,
        this.arguments,binding.parameters,argsContainCast,this);
   
    return binding.returnType;
  }

  private AdviceDeclaration findEnclosingAround(Scope scope) {
    if (scope == null) return null;
       
    if (scope instanceof MethodScope) {
      MethodScope methodScope = (MethodScope)scope;
      ReferenceContext context = methodScope.referenceContext;
      if (context instanceof AdviceDeclaration) {
        AdviceDeclaration adviceDecl = (AdviceDeclaration)context;
        if (adviceDecl.kind == AdviceKind.Around) {
          // pr 53981 only match "bare" calls to proceed
          if((receiver != null) && (!receiver.isThis())) { return null; }
          adviceDecl.proceedCalls.add(this);
          return adviceDecl;
        } else {
          return null;
        }
      }
    } else if (scope instanceof ClassScope) {
      inInner = true;
    }
   
    return findEnclosingAround(scope.parent);
  }
}
TOP

Related Classes of org.aspectj.ajdt.internal.compiler.ast.Proceed

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.