예제 #1
0
  public LambdaInfo(
      @NotNull KtExpression expression,
      @NotNull KotlinTypeMapper typeMapper,
      boolean isCrossInline,
      boolean isBoundCallableReference) {
    this.isCrossInline = isCrossInline;
    this.expression =
        expression instanceof KtLambdaExpression
            ? ((KtLambdaExpression) expression).getFunctionLiteral()
            : expression;

    this.typeMapper = typeMapper;
    this.isBoundCallableReference = isBoundCallableReference;
    BindingContext bindingContext = typeMapper.getBindingContext();
    FunctionDescriptor function = bindingContext.get(BindingContext.FUNCTION, this.expression);
    if (function == null && expression instanceof KtCallableReferenceExpression) {
      VariableDescriptor variableDescriptor =
          bindingContext.get(BindingContext.VARIABLE, this.expression);
      assert variableDescriptor instanceof VariableDescriptorWithAccessors
          : "Reference expression not resolved to variable descriptor with accessors: "
              + expression.getText();
      classDescriptor =
          CodegenBinding.anonymousClassForCallable(bindingContext, variableDescriptor);
      closureClassType = typeMapper.mapClass(classDescriptor);
      SimpleFunctionDescriptor getFunction =
          PropertyReferenceCodegen.findGetFunction(variableDescriptor);
      functionDescriptor =
          PropertyReferenceCodegen.createFakeOpenDescriptor(getFunction, classDescriptor);
      ResolvedCall<?> resolvedCall =
          CallUtilKt.getResolvedCallWithAssert(
              ((KtCallableReferenceExpression) expression).getCallableReference(), bindingContext);
      propertyReferenceInfo =
          new PropertyReferenceInfo(
              (VariableDescriptor) resolvedCall.getResultingDescriptor(), getFunction);
    } else {
      propertyReferenceInfo = null;
      functionDescriptor = function;
      assert functionDescriptor != null
          : "Function is not resolved to descriptor: " + expression.getText();
      classDescriptor = anonymousClassForCallable(bindingContext, functionDescriptor);
      closureClassType = asmTypeForAnonymousClass(bindingContext, functionDescriptor);
    }

    closure = bindingContext.get(CLOSURE, classDescriptor);
    assert closure != null : "Closure for lambda should be not null " + expression.getText();

    labels = InlineCodegen.getDeclarationLabels(expression, functionDescriptor);
  }
예제 #2
0
  @NotNull
  public List<CapturedParamDesc> getCapturedVars() {
    // lazy initialization cause it would be calculated after object creation
    if (capturedVars == null) {
      capturedVars = new ArrayList<CapturedParamDesc>();

      if (closure.getCaptureThis() != null) {
        Type type = typeMapper.mapType(closure.getCaptureThis());
        EnclosedValueDescriptor descriptor =
            new EnclosedValueDescriptor(
                AsmUtil.CAPTURED_THIS_FIELD,
                /* descriptor = */ null,
                StackValue.field(
                    type, closureClassType, AsmUtil.CAPTURED_THIS_FIELD, false, StackValue.LOCAL_0),
                type);
        capturedVars.add(getCapturedParamInfo(descriptor));
      }

      if (closure.getCaptureReceiverType() != null) {
        Type type = typeMapper.mapType(closure.getCaptureReceiverType());
        EnclosedValueDescriptor descriptor =
            new EnclosedValueDescriptor(
                AsmUtil.CAPTURED_RECEIVER_FIELD,
                /* descriptor = */ null,
                StackValue.field(
                    type,
                    closureClassType,
                    AsmUtil.CAPTURED_RECEIVER_FIELD,
                    false,
                    StackValue.LOCAL_0),
                type);
        capturedVars.add(getCapturedParamInfo(descriptor));
      }

      for (EnclosedValueDescriptor descriptor : closure.getCaptureVariables().values()) {
        capturedVars.add(getCapturedParamInfo(descriptor));
      }
    }
    return capturedVars;
  }
예제 #3
0
  @NotNull
  public Parameters addAllParameters(@NotNull FieldRemapper remapper) {
    Method asmMethod = typeMapper.mapAsmMethod(getFunctionDescriptor());
    ParametersBuilder builder =
        ParametersBuilder.initializeBuilderFrom(
            AsmTypes.OBJECT_TYPE, asmMethod.getDescriptor(), this);

    for (CapturedParamDesc info : getCapturedVars()) {
      CapturedParamInfo field =
          remapper.findField(
              new FieldInsnNode(0, info.getContainingLambdaName(), info.getFieldName(), ""));
      assert field != null
          : "Captured field not found: "
              + info.getContainingLambdaName()
              + "."
              + info.getFieldName();
      builder.addCapturedParam(field, info.getFieldName());
    }

    return builder.buildParameters();
  }
예제 #4
0
 @NotNull
 public List<Type> getInvokeParamsWithoutCaptured() {
   return Arrays.asList(typeMapper.mapAsmMethod(functionDescriptor).getArgumentTypes());
 }