選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

Proceed.java 8.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. /* *******************************************************************
  2. * Copyright (c) 2002-2014 Palo Alto Research Center, Incorporated (PARC)
  3. * and Contributors
  4. * All rights reserved.
  5. * This program and the accompanying materials are made available
  6. * under the terms of the Eclipse Public License v1.0
  7. * which accompanies this distribution and is available at
  8. * http://www.eclipse.org/legal/epl-v10.html
  9. *
  10. * Contributors:
  11. * PARC initial implementation
  12. * IBM ongoing maintenance
  13. * ******************************************************************/
  14. package org.aspectj.ajdt.internal.compiler.ast;
  15. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.CastExpression;
  16. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Expression;
  17. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.MessageSend;
  18. import org.aspectj.org.eclipse.jdt.internal.compiler.impl.Constant;
  19. import org.aspectj.org.eclipse.jdt.internal.compiler.impl.ReferenceContext;
  20. import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope;
  21. import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ClassScope;
  22. import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MethodScope;
  23. import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.Scope;
  24. import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
  25. import org.aspectj.weaver.AdviceKind;
  26. /**
  27. * Used to represent any method call to a method named <code>proceed</code>. During
  28. * <code>resolvedType</code> it will be determined if this is actually in the body
  29. * of an <code>around</code> advice and has no receiver (must be a bare proceed call,
  30. * see pr 53981), and if not this will be treated like any other
  31. * MessageSend.
  32. *
  33. * @author Jim Hugunin
  34. */
  35. public class Proceed extends MessageSend {
  36. public boolean inInner = false;
  37. public Proceed(MessageSend parent) {
  38. super();
  39. this.receiver = parent.receiver;
  40. this.selector = parent.selector;
  41. this.arguments = parent.arguments;
  42. this.binding = parent.binding;
  43. //this.codegenBinding = parent.codegenBinding;
  44. this.syntheticAccessor = parent.syntheticAccessor;
  45. this.expectedType = parent.expectedType;
  46. this.nameSourcePosition = parent.nameSourcePosition;
  47. this.actualReceiverType = parent.actualReceiverType;
  48. //this.qualifyingType = parent.qualifyingType;
  49. this.valueCast = parent.valueCast;
  50. this.typeArguments = parent.typeArguments;
  51. this.genericTypeArguments = parent.genericTypeArguments;
  52. this.sourceStart = parent.sourceStart;
  53. this.sourceEnd = parent.sourceEnd;
  54. }
  55. public TypeBinding resolveType(BlockScope scope) {
  56. // find out if I'm really in an around body or not
  57. //??? this could in theory be done by the parser, but that appears to be hard
  58. AdviceDeclaration aroundDecl = findEnclosingAround(scope);
  59. if (aroundDecl == null) {
  60. return super.resolveType(scope);
  61. }
  62. constant = Constant.NotAConstant;
  63. binding =/* codegenBinding = */aroundDecl.proceedMethodBinding;
  64. this.actualReceiverType = binding.declaringClass;
  65. int baseArgCount = 0;
  66. if (arguments != null) {
  67. baseArgCount = arguments.length;
  68. Expression[] newArguments = new Expression[baseArgCount + 1];
  69. System.arraycopy(arguments, 0, newArguments, 0, baseArgCount);
  70. arguments = newArguments;
  71. } else {
  72. arguments = new Expression[1];
  73. }
  74. arguments[baseArgCount] = AstUtil.makeLocalVariableReference(aroundDecl.extraArgument.binding);
  75. int declaredParameterCount = aroundDecl.getDeclaredParameterCount();
  76. if (baseArgCount < declaredParameterCount) {
  77. scope.problemReporter().signalError(this.sourceStart, this.sourceEnd,
  78. "too few arguments to proceed, expected " + declaredParameterCount);
  79. aroundDecl.ignoreFurtherInvestigation = true;
  80. return null; //binding.returnType;
  81. }
  82. if (baseArgCount > declaredParameterCount) {
  83. scope.problemReporter().signalError(this.sourceStart, this.sourceEnd,
  84. "too many arguments to proceed, expected " + declaredParameterCount);
  85. aroundDecl.ignoreFurtherInvestigation = true;
  86. return null; //binding.returnType;
  87. }
  88. boolean argsContainCast = false;
  89. for (int i=0; i<arguments.length;i++) {
  90. if (arguments[i] instanceof CastExpression) argsContainCast = true;
  91. // if (arguments[i].constant==null) arguments[i].constant=Constant.NotAConstant;
  92. }
  93. // TypeBinding[] argumentTypes = Binding.NO_PARAMETERS;
  94. // if (this.arguments != null) {
  95. // boolean argHasError = false; // typeChecks all arguments
  96. // int length = this.arguments.length;
  97. // argumentTypes = new TypeBinding[length];
  98. // for (int i = 0; i < length; i++){
  99. // Expression argument = this.arguments[i];
  100. // if (argument instanceof CastExpression) {
  101. // argument.bits |= ASTNode.DisableUnnecessaryCastCheck; // will check later on
  102. // argsContainCast = true;
  103. // }
  104. // if ((argumentTypes[i] = argument.resolveType(scope)) == null){
  105. // argHasError = true;
  106. // }
  107. // }
  108. // if (argHasError) {
  109. // if (this.actualReceiverType instanceof ReferenceBinding) {
  110. // // record a best guess, for clients who need hint about possible method match
  111. // TypeBinding[] pseudoArgs = new TypeBinding[length];
  112. // for (int i = length; --i >= 0;)
  113. // pseudoArgs[i] = argumentTypes[i] == null ? TypeBinding.NULL : argumentTypes[i]; // replace args with errors with null type
  114. // this.binding =
  115. // this.receiver.isImplicitThis()
  116. // ? scope.getImplicitMethod(this.selector, pseudoArgs, this)
  117. // : scope.findMethod((ReferenceBinding) this.actualReceiverType, this.selector, pseudoArgs, this);
  118. // if (this.binding != null && !this.binding.isValidBinding()) {
  119. // MethodBinding closestMatch = ((ProblemMethodBinding)this.binding).closestMatch;
  120. // // record the closest match, for clients who may still need hint about possible method match
  121. // if (closestMatch != null) {
  122. // if (closestMatch.original().typeVariables != Binding.NO_TYPE_VARIABLES) { // generic method
  123. // // shouldn't return generic method outside its context, rather convert it to raw method (175409)
  124. // closestMatch = scope.environment().createParameterizedGenericMethod(closestMatch.original(), (RawTypeBinding)null);
  125. // }
  126. // this.binding = closestMatch;
  127. // MethodBinding closestMatchOriginal = closestMatch.original();
  128. // if ((closestMatchOriginal.isPrivate() || closestMatchOriginal.declaringClass.isLocalType()) && !scope.isDefinedInMethod(closestMatchOriginal)) {
  129. // // ignore cases where method is used from within inside itself (e.g. direct recursions)
  130. // closestMatchOriginal.modifiers |= ExtraCompilerModifiers.AccLocallyUsed;
  131. // }
  132. // }
  133. // }
  134. // }
  135. // return null;
  136. // }
  137. // }
  138. //
  139. // checkInvocationArguments(scope, this.receiver, this.actualReceiverType, this.binding, this.arguments, argumentTypes, argsContainCast, this);
  140. int len = arguments.length;
  141. this.argumentTypes = (len == 0? TypeBinding.NO_TYPES:new TypeBinding[len]);
  142. for (int i=0; i < len; i++) {
  143. Expression arg = arguments[i];
  144. argumentTypes[i] = arg.resolveType(scope);
  145. if (argumentTypes[i] != null) {
  146. TypeBinding paramType = binding.parameters[i];
  147. if (!argumentTypes[i].isCompatibleWith(paramType)) {
  148. scope.problemReporter().typeMismatchError(argumentTypes[i], paramType, arg, null);
  149. }
  150. }
  151. }
  152. checkInvocationArguments(scope,null,this.actualReceiverType,binding,
  153. this.arguments,binding.parameters,argsContainCast,this);
  154. this.resolvedType = binding.returnType;
  155. return binding.returnType;
  156. }
  157. private AdviceDeclaration findEnclosingAround(Scope scope) {
  158. if (scope == null) return null;
  159. if (scope instanceof MethodScope) {
  160. MethodScope methodScope = (MethodScope)scope;
  161. ReferenceContext context = methodScope.referenceContext;
  162. if (context instanceof AdviceDeclaration) {
  163. AdviceDeclaration adviceDecl = (AdviceDeclaration)context;
  164. if (adviceDecl.kind == AdviceKind.Around) {
  165. // pr 53981 only match "bare" calls to proceed
  166. if((receiver != null) && (!receiver.isThis())) { return null; }
  167. adviceDecl.proceedCalls.add(this);
  168. return adviceDecl;
  169. } else {
  170. return null;
  171. }
  172. }
  173. } else if (scope instanceof ClassScope) {
  174. inInner = true;
  175. }
  176. return findEnclosingAround(scope.parent);
  177. }
  178. }