예제 #1
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;
  }
예제 #2
0
  /**
   * Resolve the method or field (see FieldAccessSpec).
   *
   * @param receiverType receiver of the method call.
   * @param scope
   * @param callinExpected whether this method spec is the LHS of a replace callin.
   * @param isBaseSide whether this method spec is the RHS (any binding kind)
   * @param allowEnclosing whether a method may be found in an enclosing type of receiverType
   * @return the resolved method (may be problem method) or null
   */
  public MethodBinding resolveFeature(
      ReferenceBinding receiverType,
      BlockScope scope,
      boolean callinExpected,
      boolean isBaseSide,
      boolean allowEnclosing) {
    // getRealClass() is used, because decapsulation needs to find private methods,
    // which for roles are found only in the class part.
    ReferenceBinding receiverClass = receiverType.getRealClass();
    boolean isConstructorSpec = CharOperation.equals(this.selector, receiverClass.sourceName());
    char[] realSelector = isConstructorSpec ? TypeConstants.INIT : this.selector;
    if (this.hasSignature) {
      TypeBinding[] enhancedParameters = this.parameters;
      // first chance: try enhanced:
      enhancedParameters = MethodSignatureEnhancer.enhanceParameters(scope, this.parameters);
      CompilationResult compilationResult = scope.referenceContext().compilationResult();
      CheckPoint cp = compilationResult.getCheckPoint(scope.referenceContext());

      this.resolvedMethod =
          TypeAnalyzer.findMethod(
              scope,
              receiverClass,
              realSelector,
              enhancedParameters,
              isBaseSide,
              isBaseSide ? this : null);
      if (!this.resolvedMethod.isValidBinding()
          && this.resolvedMethod.problemId() == ProblemReasons.NotFound) {
        // second+ chance: try plain:
        while (receiverClass != null) {
          compilationResult.rollBack(cp);
          MethodBinding plainMethod =
              TypeAnalyzer.findMethod(
                  scope,
                  receiverClass,
                  realSelector,
                  this.parameters,
                  isBaseSide,
                  isBaseSide ? this : null);
          if (!callinExpected) {
            this.resolvedMethod = plainMethod;
          } else {
            if (plainMethod != null && plainMethod.isValidBinding())
              scope.problemReporter().replaceMappingToNonCallin(this, plainMethod);
            // mark the ProblemMethodBinding consistently to what we have been looking for last:
            this.resolvedMethod.modifiers |=
                ExtraCompilerModifiers.AccCallin | ClassFileConstants.AccStatic;
          }
          if (plainMethod != null && plainMethod.isValidBinding()) break;
          if (allowEnclosing) receiverClass = receiverClass.enclosingType();
          else receiverClass = null;
        }
      }
    } else {
      CompilationResult compilationResult = scope.referenceContext().compilationResult();
      CheckPoint cp = compilationResult.getCheckPoint(scope.referenceContext());
      while (receiverClass != null) {
        this.resolvedMethod = receiverClass.getMethod(scope, realSelector);
        if (this.resolvedMethod != null && this.resolvedMethod.isValidBinding()) break; // good
        if (!allowEnclosing) break; // bad
        compilationResult.rollBack(cp);
        receiverClass = receiverClass.enclosingType();
      }
    }
    if (this.resolvedMethod != null) {
      if (this.resolvedMethod.isValidBinding()) {
        // check visibility of role-side in callin:
        if (!isBaseSide
            && scope.referenceContext() instanceof CallinMappingDeclaration
            && !this.resolvedMethod.canBeSeenBy(this, scope)) {
          scope.problemReporter().invisibleMethod(this, this.resolvedMethod);
          this.resolvedMethod =
              new ProblemMethodBinding(
                  this.resolvedMethod, this.selector, this.parameters, ProblemReasons.NotVisible);
        }
      }
      if (!this.resolvedMethod.isValidBinding() && this.resolvedMethod.declaringClass == null)
        this.resolvedMethod.declaringClass = receiverClass; // needed for computeUniqueKey (via
      // CallinCalloutBinding.computeUniqueKey)
    }
    return this.resolvedMethod;
  }