Exemplo n.º 1
0
    private MethodBinding checkAndResolveMethodRef(
        SourceInfo errorInfo,
        ReferenceBinding clazz,
        JsniRef jsniRef,
        boolean hasQualifier,
        boolean isLvalue) {
      assert jsniRef.isMethod();
      List<MethodBinding> targets = getMatchingMethods(clazz, jsniRef);
      if (targets.size() > 1) {
        emitError(
            ERR_AMBIGUOUS_WILDCARD_MATCH,
            errorInfo,
            jsniRef,
            JdtUtil.formatBinding(targets.get(0)),
            JdtUtil.formatBinding(targets.get(1)));
        return null;
      } else if (targets.isEmpty()) {
        emitError(ERR_UNABLE_TO_RESOLVE_METHOD, errorInfo, jsniRef);
        return null;
      }
      MethodBinding target = targets.get(0);
      resolveJsniRef(jsniRef, target);
      if (target.isDeprecated()
          && !isEnclosingClass(method.binding.declaringClass, target.declaringClass)) {
        emitWarning("deprecation", WARN_DEPRECATED_METHOD, errorInfo, jsniRef);
      }
      if (isLvalue) {
        emitError(ERR_ILLEGAL_ASSIGNMENT_TO_METHOD, errorInfo, jsniRef);
      }
      boolean needsQualifer = !target.isStatic() && !target.isConstructor();
      if (!needsQualifer && hasQualifier) {
        emitError(ERR_UNNECESSARY_QUALIFIER_STATIC_METHOD, errorInfo, jsniRef);
      } else if (needsQualifer && !hasQualifier) {
        emitError(ERR_MISSING_QUALIFIER_INSTANCE_METHOD, errorInfo, jsniRef);
      }

      if (hasUnsafeLongsAnnotation) {
        return target;
      }
      if (containsLong(target.returnType)) {
        emitError(ERR_ILLEGAL_RETURN_TYPE, errorInfo, jsniRef, typeString(target.returnType));
      }

      if (target.parameters != null) {
        int i = 0;
        for (TypeBinding paramType : target.parameters) {
          ++i;
          if (containsLong(paramType)) {
            // It would be nice to print the parameter name, but how to find it?
            emitError(ERR_ILLEGAL_PARAMETER, errorInfo, jsniRef, i, typeString(paramType));
          }
        }
      }
      return target;
    }
Exemplo n.º 2
0
  /**
   * This method is used by {@link
   * org.eclipse.objectteams.otdt.internal.core.compiler.bytecode.CallinMethodMappingsAttribute
   * CallinMethodMappingsAttribute} for decoding a mapping from its bytecode attribute.
   *
   * @param method
   * @return the bytecode level signature of the given method (yet retrenched)
   */
  public static char[] signature(MethodBinding method, WeavingScheme weavingScheme) {

    StringBuffer buffer = new StringBuffer();
    buffer.append('(');
    // synthetic args for static role method?
    MethodBinding orig =
        method.copyInheritanceSrc != null
            ? method.copyInheritanceSrc
            : method; // normalize to copyInhSrc so reading a callin-attr. from bytes can more
    // easily find the method
    if (weavingScheme == WeavingScheme.OTDRE && orig.declaringClass.isRole() && orig.isStatic()) {
      buffer.append('I');
      buffer.append(String.valueOf(orig.declaringClass.enclosingType().signature()));
    }
    // manual retrenching?
    boolean shouldRetrench = weavingScheme == WeavingScheme.OTRE && method.isCallin();
    int offset = shouldRetrench ? MethodSignatureEnhancer.getEnhancingArgLen(weavingScheme) : 0;
    int paramLen = method.parameters.length;
    for (int i = offset; i < paramLen; i++) {
      // 'weaken' to that erasure that was used in the tsuper version:
      TypeBinding targetParameter = method.getCodeGenType(i);
      buffer.append(targetParameter.signature());
    }
    buffer.append(')');
    TypeBinding sourceReturnType =
        shouldRetrench ? MethodModel.getReturnType(method) : method.returnType;
    // 'weaken' to that erasure that was used in the tsuper version:
    MethodBinding tsuperOriginal =
        (method.tagBits & TagBits.IsCopyOfParameterized) != 0
            ? method.copyInheritanceSrc.original()
            : null;
    TypeBinding returnType =
        (tsuperOriginal != null
                && tsuperOriginal.returnType.isTypeVariable()
                && !sourceReturnType.isTypeVariable())
            ? tsuperOriginal.returnType
            : sourceReturnType;
    if (returnType.isTypeVariable() && method instanceof ParameterizedGenericMethodBinding)
      returnType =
          ((ParameterizedGenericMethodBinding) method)
              .reverseSubstitute((TypeVariableBinding) returnType);
    buffer.append(returnType.erasure().signature());
    int nameLength = buffer.length();
    char[] signature = new char[nameLength];
    buffer.getChars(0, nameLength, signature, 0);

    return signature;
  }
  private void searchVisibleLocalMethods(
      MethodBinding[] methods,
      ReferenceBinding receiverType,
      Scope scope,
      InvocationSite invocationSite,
      Scope invocationScope,
      boolean onlyStaticMethods,
      ObjectVector methodsFound) {
    ObjectVector newMethodsFound = new ObjectVector();
    // Inherited methods which are hidden by subclasses are filtered out
    // No visibility checks can be performed without the scope & invocationSite

    next:
    for (int f = methods.length; --f >= 0; ) {
      MethodBinding method = methods[f];

      if (method.isSynthetic()) continue next;

      if (method.isDefaultAbstract()) continue next;

      if (method.isConstructor()) continue next;

      if (onlyStaticMethods && !method.isStatic()) continue next;

      if (!method.canBeSeenBy(receiverType, invocationSite, scope)) continue next;

      for (int i = methodsFound.size; --i >= 0; ) {
        MethodBinding otherMethod = (MethodBinding) methodsFound.elementAt(i);
        if (method == otherMethod) continue next;

        if (CharOperation.equals(method.selector, otherMethod.selector, true)) {
          if (this.lookupEnvironment.methodVerifier().isMethodSubsignature(otherMethod, method)) {
            continue next;
          }
        }
      }

      newMethodsFound.add(method);
    }

    methodsFound.addAll(newMethodsFound);
  }
  public int resolveLevel(Binding binding) {
    if (binding == null) return INACCURATE_MATCH;
    if (!(binding instanceof MethodBinding)) return IMPOSSIBLE_MATCH;

    MethodBinding method = (MethodBinding) binding;
    boolean skipVerif = this.pattern.findDeclarations && this.mayBeGeneric;
    int methodLevel = matchMethod(method, skipVerif);
    if (methodLevel == IMPOSSIBLE_MATCH) {
      if (method != method.original()) methodLevel = matchMethod(method.original(), skipVerif);
      if (methodLevel == IMPOSSIBLE_MATCH) {
        return IMPOSSIBLE_MATCH;
      } else {
        method = method.original();
      }
    }

    // declaring type
    char[] qualifiedPattern =
        qualifiedPattern(this.pattern.declaringSimpleName, this.pattern.declaringQualification);
    if (qualifiedPattern == null) return methodLevel; // since any declaring class will do

    boolean subType = !method.isStatic() && !method.isPrivate();
    if (subType
        && this.pattern.declaringQualification != null
        && method.declaringClass != null
        && method.declaringClass.fPackage != null) {
      subType =
          CharOperation.compareWith(
                  this.pattern.declaringQualification,
                  method.declaringClass.fPackage.shortReadableName())
              == 0;
    }
    int declaringLevel =
        subType
            ? resolveLevelAsSubtype(qualifiedPattern, method.declaringClass, null)
            : resolveLevelForType(qualifiedPattern, method.declaringClass);
    return methodLevel > declaringLevel ? declaringLevel : methodLevel; // return the weaker match
  }
Exemplo n.º 5
0
  private static List<MethodBinding> getApplicableExtensionMethodsDefinedInProvider(
      EclipseNode typeNode,
      ReferenceBinding extensionMethodProviderBinding,
      TypeBinding receiverType) {

    List<MethodBinding> extensionMethods = new ArrayList<MethodBinding>();
    CompilationUnitScope cuScope = ((CompilationUnitDeclaration) typeNode.top().get()).scope;
    for (MethodBinding method : extensionMethodProviderBinding.methods()) {
      if (!method.isStatic()) continue;
      if (!method.isPublic()) continue;
      if (method.parameters == null || method.parameters.length == 0) continue;
      TypeBinding firstArgType = method.parameters[0];
      if (receiverType.isProvablyDistinct(firstArgType)
          && !receiverType.isCompatibleWith(firstArgType.erasure())) continue;
      TypeBinding[] argumentTypes =
          Arrays.copyOfRange(method.parameters, 1, method.parameters.length);
      if ((receiverType instanceof ReferenceBinding)
          && ((ReferenceBinding) receiverType)
                  .getExactMethod(method.selector, argumentTypes, cuScope)
              != null) continue;
      extensionMethods.add(method);
    }
    return extensionMethods;
  }
 /** Returns whether the code gen will use an invoke virtual for this message send or not. */
 protected boolean isVirtualInvoke(MethodBinding method, MessageSend messageSend) {
   return !method.isStatic() && !method.isPrivate() && !messageSend.isSuperAccess();
 }
Exemplo n.º 7
0
  public static boolean checkInvocationArguments(
      BlockScope scope,
      Expression receiver,
      TypeBinding receiverType,
      MethodBinding method,
      Expression[] arguments,
      TypeBinding[] argumentTypes,
      boolean argsContainCast,
      InvocationSite invocationSite) {
    TypeBinding[] params = method.parameters;
    int paramLength = params.length;
    boolean isRawMemberInvocation =
        !method.isStatic()
            && !receiverType.isUnboundWildcard()
            && method.declaringClass.isRawType()
            && method.hasSubstitutedParameters();

    boolean uncheckedBoundCheck =
        (method.tagBits & TagBits.HasUncheckedTypeArgumentForBoundCheck) != 0;
    MethodBinding rawOriginalGenericMethod = null;
    if (!isRawMemberInvocation) {
      if (method instanceof ParameterizedGenericMethodBinding) {
        ParameterizedGenericMethodBinding paramMethod = (ParameterizedGenericMethodBinding) method;
        if (paramMethod.isRaw && method.hasSubstitutedParameters()) {
          rawOriginalGenericMethod = method.original();
        }
      }
    }
    int invocationStatus = INVOCATION_ARGUMENT_OK;
    if (arguments == null) {
      if (method.isVarargs()) {
        TypeBinding parameterType =
            ((ArrayBinding) params[paramLength - 1])
                .elementsType(); // no element was supplied for vararg parameter
        if (!parameterType.isReifiable()) {
          scope
              .problemReporter()
              .unsafeGenericArrayForVarargs(parameterType, (ASTNode) invocationSite);
        }
      }
    } else {
      if (method.isVarargs()) {
        // 4 possibilities exist for a call to the vararg method foo(int i, long ... value) :
        // foo(1), foo(1, 2), foo(1, 2, 3, 4) & foo(1, new long[] {1, 2})
        int lastIndex = paramLength - 1;
        for (int i = 0; i < lastIndex; i++) {
          TypeBinding originalRawParam =
              rawOriginalGenericMethod == null ? null : rawOriginalGenericMethod.parameters[i];
          invocationStatus |=
              checkInvocationArgument(
                  scope, arguments[i], params[i], argumentTypes[i], originalRawParam);
        }
        int argLength = arguments.length;
        if (lastIndex < argLength) { // vararg argument was provided
          TypeBinding parameterType = params[lastIndex];
          TypeBinding originalRawParam = null;

          if (paramLength != argLength
              || parameterType.dimensions() != argumentTypes[lastIndex].dimensions()) {
            parameterType =
                ((ArrayBinding) parameterType)
                    .elementsType(); // single element was provided for vararg parameter
            if (!parameterType.isReifiable()) {
              scope
                  .problemReporter()
                  .unsafeGenericArrayForVarargs(parameterType, (ASTNode) invocationSite);
            }
            originalRawParam =
                rawOriginalGenericMethod == null
                    ? null
                    : ((ArrayBinding) rawOriginalGenericMethod.parameters[lastIndex])
                        .elementsType();
          }
          for (int i = lastIndex; i < argLength; i++) {
            invocationStatus |=
                checkInvocationArgument(
                    scope, arguments[i], parameterType, argumentTypes[i], originalRawParam);
          }
        }
        if (paramLength == argLength) { // 70056
          int varargsIndex = paramLength - 1;
          ArrayBinding varargsType = (ArrayBinding) params[varargsIndex];
          TypeBinding lastArgType = argumentTypes[varargsIndex];
          int dimensions;
          if (lastArgType == TypeBinding.NULL) {
            if (!(varargsType.leafComponentType().isBaseType() && varargsType.dimensions() == 1))
              scope.problemReporter().varargsArgumentNeedCast(method, lastArgType, invocationSite);
          } else if (varargsType.dimensions <= (dimensions = lastArgType.dimensions())) {
            if (lastArgType.leafComponentType().isBaseType()) {
              dimensions--;
            }
            if (varargsType.dimensions < dimensions) {
              scope.problemReporter().varargsArgumentNeedCast(method, lastArgType, invocationSite);
            } else if (varargsType.dimensions == dimensions
                && lastArgType != varargsType
                && lastArgType.leafComponentType().erasure()
                    != varargsType.leafComponentType.erasure()
                && lastArgType.isCompatibleWith(varargsType.elementsType())
                && lastArgType.isCompatibleWith(varargsType)) {
              scope.problemReporter().varargsArgumentNeedCast(method, lastArgType, invocationSite);
            }
          }
        }
      } else {
        for (int i = 0; i < paramLength; i++) {
          TypeBinding originalRawParam =
              rawOriginalGenericMethod == null ? null : rawOriginalGenericMethod.parameters[i];
          invocationStatus |=
              checkInvocationArgument(
                  scope, arguments[i], params[i], argumentTypes[i], originalRawParam);
        }
      }
      if (argsContainCast) {
        CastExpression.checkNeedForArgumentCasts(
            scope, receiver, receiverType, method, arguments, argumentTypes, invocationSite);
      }
    }
    if ((invocationStatus & INVOCATION_ARGUMENT_WILDCARD) != 0) {
      scope
          .problemReporter()
          .wildcardInvocation((ASTNode) invocationSite, receiverType, method, argumentTypes);
    } else if (!method.isStatic()
        && !receiverType.isUnboundWildcard()
        && method.declaringClass.isRawType()
        && method.hasSubstitutedParameters()) {
      scope.problemReporter().unsafeRawInvocation((ASTNode) invocationSite, method);
    } else if (rawOriginalGenericMethod != null
        || uncheckedBoundCheck
        || ((invocationStatus & INVOCATION_ARGUMENT_UNCHECKED) != 0
            && method instanceof ParameterizedGenericMethodBinding
        /*&& method.returnType != scope.environment().convertToRawType(method.returnType.erasure(), true)*/ )) {
      scope
          .problemReporter()
          .unsafeRawGenericMethodInvocation((ASTNode) invocationSite, method, argumentTypes);
      return true;
    }
    return false;
  }
Exemplo n.º 8
0
  /**
   * MessageSend code generation
   *
   * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
   * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
   * @param valueRequired boolean
   */
  public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
    int pc = codeStream.position;
    MethodBinding codegenBinding = this.binding.original();
    if (codegenBinding.canBeSeenBy(this.actualReceiverType, this, currentScope)) {
      // generate receiver/enclosing instance access
      boolean isStatic = codegenBinding.isStatic();
      // outer access ?
      if (!isStatic && ((this.bits & DepthMASK) != 0)) {
        // outer method can be reached through emulation
        ReferenceBinding targetType =
            currentScope
                .enclosingSourceType()
                .enclosingTypeAt((this.bits & DepthMASK) >> DepthSHIFT);
        Object[] path =
            currentScope.getEmulationPath(
                targetType, true /*only exact match*/, false /*consider enclosing arg*/);
        if (path == null) {
          // emulation was not possible (should not happen per construction)
          currentScope.problemReporter().needImplementation(this);
        } else {
          codeStream.generateOuterAccess(path, this, targetType, currentScope);
        }
      } else {
        this.receiver.generateCode(currentScope, codeStream, !isStatic);
        if ((this.bits & NeedReceiverGenericCast) != 0) {
          codeStream.checkcast(this.actualReceiverType);
        }
        codeStream.recordPositionsFrom(pc, this.sourceStart);
      }
      // generate arguments
      generateArguments(this.binding, this.arguments, currentScope, codeStream);
      // actual message invocation
      TypeBinding constantPoolDeclaringClass =
          CodeStream.getConstantPoolDeclaringClass(
              currentScope,
              codegenBinding,
              this.actualReceiverType,
              this.receiver.isImplicitThis());
      if (isStatic) {
        codeStream.invoke(Opcodes.OPC_invokestatic, codegenBinding, constantPoolDeclaringClass);
      } else if ((this.receiver.isSuper()) || codegenBinding.isPrivate()) {
        codeStream.invoke(Opcodes.OPC_invokespecial, codegenBinding, constantPoolDeclaringClass);
      } else {
        if (constantPoolDeclaringClass.isInterface()) { // interface or annotation type
          codeStream.invoke(
              Opcodes.OPC_invokeinterface, codegenBinding, constantPoolDeclaringClass);
        } else {
          codeStream.invoke(Opcodes.OPC_invokevirtual, codegenBinding, constantPoolDeclaringClass);
        }
      }
    } else {
      codeStream.generateEmulationForMethod(currentScope, codegenBinding);
      // generate receiver/enclosing instance access
      boolean isStatic = codegenBinding.isStatic();
      // outer access ?
      if (!isStatic && ((this.bits & DepthMASK) != 0)) {
        // not supported yet
        currentScope.problemReporter().needImplementation(this);
      } else {
        this.receiver.generateCode(currentScope, codeStream, !isStatic);
        if ((this.bits & NeedReceiverGenericCast) != 0) {
          codeStream.checkcast(this.actualReceiverType);
        }
        codeStream.recordPositionsFrom(pc, this.sourceStart);
      }
      if (isStatic) {
        // we need an object on the stack which is ignored for the method invocation
        codeStream.aconst_null();
      }
      // generate arguments
      if (this.arguments != null) {
        int argsLength = this.arguments.length;
        codeStream.generateInlinedValue(argsLength);
        codeStream.newArray(
            currentScope.createArrayType(
                currentScope.getType(TypeConstants.JAVA_LANG_OBJECT, 3), 1));
        codeStream.dup();
        for (int i = 0; i < argsLength; i++) {
          codeStream.generateInlinedValue(i);
          this.arguments[i].generateCode(currentScope, codeStream, true);
          TypeBinding parameterBinding = codegenBinding.parameters[i];
          if (parameterBinding.isBaseType() && parameterBinding != TypeBinding.NULL) {
            codeStream.generateBoxingConversion(codegenBinding.parameters[i].id);
          }
          codeStream.aastore();
          if (i < argsLength - 1) {
            codeStream.dup();
          }
        }
      } else {
        codeStream.generateInlinedValue(0);
        codeStream.newArray(
            currentScope.createArrayType(
                currentScope.getType(TypeConstants.JAVA_LANG_OBJECT, 3), 1));
      }
      codeStream.invokeJavaLangReflectMethodInvoke();

      // convert the return value to the appropriate type for primitive types
      if (codegenBinding.returnType.isBaseType()) {
        int typeID = codegenBinding.returnType.id;
        if (typeID == T_void) {
          // remove the null from the stack
          codeStream.pop();
        }
        codeStream.checkcast(typeID);
        codeStream.getBaseTypeValue(typeID);
      } else {
        codeStream.checkcast(codegenBinding.returnType);
      }
    }
    // required cast must occur even if no value is required
    if (this.valueCast != null) codeStream.checkcast(this.valueCast);
    if (valueRequired) {
      // implicit conversion if necessary
      codeStream.generateImplicitConversion(this.implicitConversion);
    } else {
      boolean isUnboxing = (this.implicitConversion & TypeIds.UNBOXING) != 0;
      // conversion only generated if unboxing
      if (isUnboxing) codeStream.generateImplicitConversion(this.implicitConversion);
      switch (isUnboxing ? postConversionType(currentScope).id : codegenBinding.returnType.id) {
        case T_long:
        case T_double:
          codeStream.pop2();
          break;
        case T_void:
          break;
        default:
          codeStream.pop();
      }
    }
    codeStream.recordPositionsFrom(
        pc, (int) (this.nameSourcePosition >>> 32)); // highlight selector
  }
Exemplo n.º 9
0
 /**
  * MessageSend code generation
  *
  * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
  * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
  * @param valueRequired boolean
  */
 public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
   int pc = codeStream.position;
   // generate receiver/enclosing instance access
   MethodBinding codegenBinding =
       this.binding instanceof PolymorphicMethodBinding ? this.binding : this.binding.original();
   boolean isStatic = codegenBinding.isStatic();
   if (isStatic) {
     this.receiver.generateCode(currentScope, codeStream, false);
   } else if ((this.bits & ASTNode.DepthMASK) != 0
       && this.receiver.isImplicitThis()) { // outer access ?
     // outer method can be reached through emulation if implicit access
     ReferenceBinding targetType =
         currentScope
             .enclosingSourceType()
             .enclosingTypeAt((this.bits & ASTNode.DepthMASK) >> ASTNode.DepthSHIFT);
     Object[] path =
         currentScope.getEmulationPath(
             targetType, true /*only exact match*/, false /*consider enclosing arg*/);
     codeStream.generateOuterAccess(path, this, targetType, currentScope);
   } else {
     this.receiver.generateCode(currentScope, codeStream, true);
     if ((this.bits & NeedReceiverGenericCast) != 0) {
       codeStream.checkcast(this.actualReceiverType);
     }
   }
   codeStream.recordPositionsFrom(pc, this.sourceStart);
   // generate arguments
   generateArguments(this.binding, this.arguments, currentScope, codeStream);
   pc = codeStream.position;
   // actual message invocation
   if (this.syntheticAccessor == null) {
     TypeBinding constantPoolDeclaringClass =
         CodeStream.getConstantPoolDeclaringClass(
             currentScope,
             codegenBinding,
             this.actualReceiverType,
             this.receiver.isImplicitThis());
     if (isStatic) {
       codeStream.invoke(Opcodes.OPC_invokestatic, codegenBinding, constantPoolDeclaringClass);
     } else if ((this.receiver.isSuper()) || codegenBinding.isPrivate()) {
       codeStream.invoke(Opcodes.OPC_invokespecial, codegenBinding, constantPoolDeclaringClass);
     } else if (constantPoolDeclaringClass.isInterface()) { // interface or annotation type
       codeStream.invoke(Opcodes.OPC_invokeinterface, codegenBinding, constantPoolDeclaringClass);
     } else {
       codeStream.invoke(Opcodes.OPC_invokevirtual, codegenBinding, constantPoolDeclaringClass);
     }
   } else {
     codeStream.invoke(
         Opcodes.OPC_invokestatic, this.syntheticAccessor, null /* default declaringClass */);
   }
   // required cast must occur even if no value is required
   if (this.valueCast != null) codeStream.checkcast(this.valueCast);
   if (valueRequired) {
     // implicit conversion if necessary
     codeStream.generateImplicitConversion(this.implicitConversion);
   } else {
     boolean isUnboxing = (this.implicitConversion & TypeIds.UNBOXING) != 0;
     // conversion only generated if unboxing
     if (isUnboxing) codeStream.generateImplicitConversion(this.implicitConversion);
     switch (isUnboxing ? postConversionType(currentScope).id : codegenBinding.returnType.id) {
       case T_long:
       case T_double:
         codeStream.pop2();
         break;
       case T_void:
         break;
       default:
         codeStream.pop();
     }
   }
   codeStream.recordPositionsFrom(
       pc, (int) (this.nameSourcePosition >>> 32)); // highlight selector
 }