@Nullable
  private static JetType computeUnsafeReturnType(
      @NotNull JetFunctionLiteralExpression expression,
      @NotNull ExpressionTypingContext context,
      @NotNull SimpleFunctionDescriptorImpl functionDescriptor,
      @Nullable JetType expectedReturnType) {
    JetFunctionLiteral functionLiteral = expression.getFunctionLiteral();
    JetBlockExpression bodyExpression = functionLiteral.getBodyExpression();
    assert bodyExpression != null;

    JetScope functionInnerScope =
        FunctionDescriptorUtil.getFunctionInnerScope(
            context.scope, functionDescriptor, context.trace);
    JetTypeReference returnTypeRef = functionLiteral.getReturnTypeRef();
    JetType declaredReturnType = null;
    if (returnTypeRef != null) {
      declaredReturnType =
          context
              .expressionTypingServices
              .getTypeResolver()
              .resolveType(context.scope, returnTypeRef, context.trace, true);
      // This is needed for ControlStructureTypingVisitor#visitReturnExpression() to properly
      // type-check returned expressions
      functionDescriptor.setReturnType(declaredReturnType);
      if (expectedReturnType != null) {
        if (!JetTypeChecker.INSTANCE.isSubtypeOf(declaredReturnType, expectedReturnType)) {
          context.trace.report(EXPECTED_RETURN_TYPE_MISMATCH.on(returnTypeRef, expectedReturnType));
        }
      }
    }

    // Type-check the body
    ExpressionTypingContext newContext =
        context
            .replaceScope(functionInnerScope)
            .replaceExpectedType(
                declaredReturnType != null
                    ? declaredReturnType
                    : (expectedReturnType != null ? expectedReturnType : NO_EXPECTED_TYPE));

    JetType typeOfBodyExpression =
        context
            .expressionTypingServices
            .getBlockReturnedType(bodyExpression, COERCION_TO_UNIT, newContext)
            .getType();

    List<JetType> returnedExpressionTypes =
        Lists.newArrayList(
            getTypesOfLocallyReturnedExpressions(
                functionLiteral, context.trace, collectReturns(bodyExpression)));
    ContainerUtil.addIfNotNull(returnedExpressionTypes, typeOfBodyExpression);

    if (declaredReturnType != null) return declaredReturnType;
    if (returnedExpressionTypes.isEmpty()) return null;
    return CommonSupertypes.commonSupertype(returnedExpressionTypes);
  }
  private List<ValueParameterDescriptor> createValueParameterDescriptors(
      ExpressionTypingContext context,
      JetFunctionLiteral functionLiteral,
      FunctionDescriptorImpl functionDescriptor,
      boolean functionTypeExpected) {
    List<ValueParameterDescriptor> valueParameterDescriptors = Lists.newArrayList();
    List<JetParameter> declaredValueParameters = functionLiteral.getValueParameters();

    List<ValueParameterDescriptor> expectedValueParameters =
        (functionTypeExpected)
            ? JetStandardClasses.getValueParameters(functionDescriptor, context.expectedType)
            : null;

    boolean hasDeclaredValueParameters = functionLiteral.getValueParameterList() != null;
    if (functionTypeExpected
        && !hasDeclaredValueParameters
        && expectedValueParameters.size() == 1) {
      ValueParameterDescriptor valueParameterDescriptor = expectedValueParameters.get(0);
      ValueParameterDescriptor it =
          new ValueParameterDescriptorImpl(
              functionDescriptor,
              0,
              Collections.<AnnotationDescriptor>emptyList(),
              "it",
              false,
              valueParameterDescriptor.getOutType(),
              valueParameterDescriptor.hasDefaultValue(),
              valueParameterDescriptor.getVarargElementType());
      valueParameterDescriptors.add(it);
      context.trace.record(AUTO_CREATED_IT, it);
    } else {
      for (int i = 0; i < declaredValueParameters.size(); i++) {
        JetParameter declaredParameter = declaredValueParameters.get(i);
        JetTypeReference typeReference = declaredParameter.getTypeReference();

        JetType type;
        if (typeReference != null) {
          type = context.getTypeResolver().resolveType(context.scope, typeReference);
        } else {
          if (expectedValueParameters != null && i < expectedValueParameters.size()) {
            type = expectedValueParameters.get(i).getOutType();
          } else {
            context.trace.report(CANNOT_INFER_PARAMETER_TYPE.on(declaredParameter));
            type = ErrorUtils.createErrorType("Cannot be inferred");
          }
        }
        ValueParameterDescriptor valueParameterDescriptor =
            context
                .getDescriptorResolver()
                .resolveValueParameterDescriptor(functionDescriptor, declaredParameter, i, type);
        valueParameterDescriptors.add(valueParameterDescriptor);
      }
    }
    return valueParameterDescriptors;
  }
  @NotNull
  private static List<ValueParameterDescriptor> createValueParameterDescriptors(
      @NotNull ExpressionTypingContext context,
      @NotNull JetFunctionLiteral functionLiteral,
      @NotNull FunctionDescriptorImpl functionDescriptor,
      boolean functionTypeExpected) {
    List<ValueParameterDescriptor> valueParameterDescriptors = Lists.newArrayList();
    List<JetParameter> declaredValueParameters = functionLiteral.getValueParameters();

    List<ValueParameterDescriptor> expectedValueParameters =
        (functionTypeExpected)
            ? KotlinBuiltIns.getInstance()
                .getValueParameters(functionDescriptor, context.expectedType)
            : null;

    JetParameterList valueParameterList = functionLiteral.getValueParameterList();
    boolean hasDeclaredValueParameters = valueParameterList != null;
    if (functionTypeExpected
        && !hasDeclaredValueParameters
        && expectedValueParameters.size() == 1) {
      ValueParameterDescriptor valueParameterDescriptor = expectedValueParameters.get(0);
      ValueParameterDescriptor it =
          new ValueParameterDescriptorImpl(
              functionDescriptor,
              0,
              Collections.<AnnotationDescriptor>emptyList(),
              Name.identifier("it"),
              valueParameterDescriptor.getType(),
              valueParameterDescriptor.hasDefaultValue(),
              valueParameterDescriptor.getVarargElementType());
      valueParameterDescriptors.add(it);
      context.trace.record(AUTO_CREATED_IT, it);
    } else {
      if (expectedValueParameters != null
          && declaredValueParameters.size() != expectedValueParameters.size()) {
        List<JetType> expectedParameterTypes =
            DescriptorUtils.getValueParametersTypes(expectedValueParameters);
        context.trace.report(
            EXPECTED_PARAMETERS_NUMBER_MISMATCH.on(
                functionLiteral, expectedParameterTypes.size(), expectedParameterTypes));
      }
      for (int i = 0; i < declaredValueParameters.size(); i++) {
        ValueParameterDescriptor valueParameterDescriptor =
            createValueParameterDescriptor(
                context, functionDescriptor, declaredValueParameters, expectedValueParameters, i);
        valueParameterDescriptors.add(valueParameterDescriptor);
      }
    }
    return valueParameterDescriptors;
  }
  private static boolean checkIfHasExpectedType(
      @NotNull FunctionDescriptor functionDescriptor, boolean isInherited) {
    if (!(functionDescriptor instanceof AnonymousFunctionDescriptor && isInherited)) return false;

    JetFunctionLiteral functionLiteral =
        (JetFunctionLiteral) DescriptorToSourceUtils.descriptorToDeclaration(functionDescriptor);
    assert functionLiteral != null : "No declaration found for " + functionDescriptor;

    PsiElement parent = functionLiteral.getParent();
    if (!(parent instanceof JetFunctionLiteralExpression)) return false;

    JetFunctionLiteralExpression expression = (JetFunctionLiteralExpression) parent;
    return ResolvePackage.analyze(expression, BodyResolveMode.PARTIAL)
            .get(BindingContext.EXPECTED_EXPRESSION_TYPE, expression)
        != null;
  }
  @NotNull
  private static AnonymousFunctionDescriptor createFunctionDescriptor(
      @NotNull JetFunctionLiteralExpression expression,
      @NotNull ExpressionTypingContext context,
      boolean functionTypeExpected) {
    JetFunctionLiteral functionLiteral = expression.getFunctionLiteral();
    JetTypeReference receiverTypeRef = functionLiteral.getReceiverTypeRef();
    AnonymousFunctionDescriptor functionDescriptor =
        new AnonymousFunctionDescriptor(
            context.scope.getContainingDeclaration(),
            Collections.<AnnotationDescriptor>emptyList(),
            CallableMemberDescriptor.Kind.DECLARATION);

    List<ValueParameterDescriptor> valueParameterDescriptors =
        createValueParameterDescriptors(
            context, functionLiteral,
            functionDescriptor, functionTypeExpected);

    JetType effectiveReceiverType;
    if (receiverTypeRef == null) {
      if (functionTypeExpected) {
        effectiveReceiverType = KotlinBuiltIns.getInstance().getReceiverType(context.expectedType);
      } else {
        effectiveReceiverType = null;
      }
    } else {
      effectiveReceiverType =
          context
              .expressionTypingServices
              .getTypeResolver()
              .resolveType(context.scope, receiverTypeRef, context.trace, true);
    }
    functionDescriptor.initialize(
        effectiveReceiverType,
        ReceiverParameterDescriptor.NO_RECEIVER_PARAMETER,
        Collections.<TypeParameterDescriptorImpl>emptyList(),
        valueParameterDescriptors,
        /*unsubstitutedReturnType = */ null,
        Modality.FINAL,
        Visibilities.LOCAL);
    BindingContextUtils.recordFunctionDeclarationToDescriptor(
        context.trace, functionLiteral, functionDescriptor);
    return functionDescriptor;
  }
  private NamedFunctionDescriptorImpl createFunctionDescriptor(
      JetFunctionLiteralExpression expression,
      ExpressionTypingContext context,
      boolean functionTypeExpected) {
    JetFunctionLiteral functionLiteral = expression.getFunctionLiteral();
    JetTypeReference receiverTypeRef = functionLiteral.getReceiverTypeRef();
    NamedFunctionDescriptorImpl functionDescriptor =
        new NamedFunctionDescriptorImpl(
            context.scope.getContainingDeclaration(),
            Collections.<AnnotationDescriptor>emptyList(),
            "<anonymous>",
            CallableMemberDescriptor.Kind.DECLARATION);

    List<ValueParameterDescriptor> valueParameterDescriptors =
        createValueParameterDescriptors(
            context, functionLiteral, functionDescriptor, functionTypeExpected);

    JetType effectiveReceiverType;
    if (receiverTypeRef == null) {
      if (functionTypeExpected) {
        effectiveReceiverType = JetStandardClasses.getReceiverType(context.expectedType);
      } else {
        effectiveReceiverType = null;
      }
    } else {
      effectiveReceiverType = context.getTypeResolver().resolveType(context.scope, receiverTypeRef);
    }
    functionDescriptor.initialize(
        effectiveReceiverType,
        NO_RECEIVER,
        Collections.<TypeParameterDescriptor>emptyList(),
        valueParameterDescriptors,
        null,
        Modality.FINAL,
        Visibility.LOCAL);
    context.trace.record(BindingContext.FUNCTION, expression, functionDescriptor);
    return functionDescriptor;
  }
Example #7
0
 @Nullable
 public static <T extends PsiElement> T getDirectParentOfTypeForBlock(
     @NotNull JetBlockExpression block, @NotNull Class<T> aClass) {
   T parent = PsiTreeUtil.getParentOfType(block, aClass);
   if (parent instanceof JetIfExpression) {
     JetIfExpression ifExpression = (JetIfExpression) parent;
     if (ifExpression.getElse() == block || ifExpression.getThen() == block) {
       return parent;
     }
   }
   if (parent instanceof JetWhenExpression) {
     JetWhenExpression whenExpression = (JetWhenExpression) parent;
     for (JetWhenEntry whenEntry : whenExpression.getEntries()) {
       if (whenEntry.getExpression() == block) {
         return parent;
       }
     }
   }
   if (parent instanceof JetFunctionLiteral) {
     JetFunctionLiteral functionLiteral = (JetFunctionLiteral) parent;
     if (functionLiteral.getBodyExpression() == block) {
       return parent;
     }
   }
   if (parent instanceof JetTryExpression) {
     JetTryExpression tryExpression = (JetTryExpression) parent;
     if (tryExpression.getTryBlock() == block) {
       return parent;
     }
     for (JetCatchClause clause : tryExpression.getCatchClauses()) {
       if (clause.getCatchBody() == block) {
         return parent;
       }
     }
   }
   return null;
 }
  @Override
  public JetType visitFunctionLiteralExpression(
      JetFunctionLiteralExpression expression, ExpressionTypingContext context) {
    JetFunctionLiteral functionLiteral = expression.getFunctionLiteral();
    JetBlockExpression bodyExpression = functionLiteral.getBodyExpression();
    if (bodyExpression == null) return null;

    JetType expectedType = context.expectedType;
    boolean functionTypeExpected =
        expectedType != TypeUtils.NO_EXPECTED_TYPE
            && JetStandardClasses.isFunctionType(expectedType);

    NamedFunctionDescriptorImpl functionDescriptor =
        createFunctionDescriptor(expression, context, functionTypeExpected);

    List<JetType> parameterTypes = Lists.newArrayList();
    List<ValueParameterDescriptor> valueParameters = functionDescriptor.getValueParameters();
    for (ValueParameterDescriptor valueParameter : valueParameters) {
      parameterTypes.add(valueParameter.getOutType());
    }
    ReceiverDescriptor receiverParameter = functionDescriptor.getReceiverParameter();
    JetType receiver = receiverParameter != NO_RECEIVER ? receiverParameter.getType() : null;

    JetType returnType = TypeUtils.NO_EXPECTED_TYPE;
    JetScope functionInnerScope =
        FunctionDescriptorUtil.getFunctionInnerScope(
            context.scope, functionDescriptor, context.trace);
    JetTypeReference returnTypeRef = functionLiteral.getReturnTypeRef();
    if (returnTypeRef != null) {
      returnType = context.getTypeResolver().resolveType(context.scope, returnTypeRef);
      context
          .getServices()
          .checkFunctionReturnType(
              expression,
              context
                  .replaceScope(functionInnerScope)
                  .replaceExpectedType(returnType)
                  .replaceExpectedReturnType(returnType)
                  .replaceDataFlowInfo(context.dataFlowInfo));
    } else {
      if (functionTypeExpected) {
        returnType = JetStandardClasses.getReturnTypeFromFunctionType(expectedType);
      }
      returnType =
          context
              .getServices()
              .getBlockReturnedType(
                  functionInnerScope,
                  bodyExpression,
                  CoercionStrategy.COERCION_TO_UNIT,
                  context.replaceExpectedType(returnType).replaceExpectedReturnType(returnType));
    }
    JetType safeReturnType =
        returnType == null ? ErrorUtils.createErrorType("<return type>") : returnType;
    functionDescriptor.setReturnType(safeReturnType);

    boolean hasDeclaredValueParameters = functionLiteral.getValueParameterList() != null;
    if (!hasDeclaredValueParameters && functionTypeExpected) {
      JetType expectedReturnType = JetStandardClasses.getReturnTypeFromFunctionType(expectedType);
      if (JetStandardClasses.isUnit(expectedReturnType)) {
        functionDescriptor.setReturnType(JetStandardClasses.getUnitType());
        return DataFlowUtils.checkType(
            JetStandardClasses.getFunctionType(
                Collections.<AnnotationDescriptor>emptyList(),
                receiver,
                parameterTypes,
                JetStandardClasses.getUnitType()),
            expression,
            context);
      }
    }
    return DataFlowUtils.checkType(
        JetStandardClasses.getFunctionType(
            Collections.<AnnotationDescriptor>emptyList(),
            receiver,
            parameterTypes,
            safeReturnType),
        expression,
        context);
  }
  private void processParameterListWithStructuralChanges(
      JetChangeInfo changeInfo,
      PsiElement element,
      JetParameterList parameterList,
      JetPsiFactory psiFactory) {
    int parametersCount = changeInfo.getNonReceiverParametersCount();
    boolean isLambda = element instanceof JetFunctionLiteral;
    boolean canReplaceEntireList = false;

    JetParameterList newParameterList = null;
    if (isLambda) {
      if (parametersCount == 0 && ((JetFunctionLiteral) element).getTypeReference() == null) {
        if (parameterList != null) {
          parameterList.delete();
          ASTNode arrowNode = ((JetFunctionLiteral) element).getArrowNode();
          if (arrowNode != null) {
            arrowNode.getPsi().delete();
          }
          parameterList = null;
        }
      } else {
        newParameterList =
            psiFactory.createFunctionLiteralParameterList(
                changeInfo.getNewParametersSignature(
                    (JetFunctionDefinitionUsage<PsiElement>) this));
        canReplaceEntireList = true;
      }
    } else {
      newParameterList =
          psiFactory.createParameterList(
              changeInfo.getNewParametersSignature((JetFunctionDefinitionUsage<PsiElement>) this));
    }

    if (newParameterList == null) return;

    if (parameterList != null) {
      if (canReplaceEntireList) {
        newParameterList = (JetParameterList) parameterList.replace(newParameterList);
      } else {
        newParameterList = replaceParameterListAndKeepDelimiters(parameterList, newParameterList);
      }
    } else {
      if (element instanceof JetClass) {
        PsiElement anchor = ((JetClass) element).getTypeParameterList();

        if (anchor == null) {
          anchor = ((JetClass) element).getNameIdentifier();
        }
        if (anchor != null) {
          JetPrimaryConstructor constructor =
              (JetPrimaryConstructor)
                  element.addAfter(psiFactory.createPrimaryConstructor(), anchor);
          JetParameterList oldParameterList = constructor.getValueParameterList();
          assert oldParameterList != null : "primary constructor from factory has parameter list";
          newParameterList = (JetParameterList) oldParameterList.replace(newParameterList);
        }
      } else if (isLambda) {
        //noinspection ConstantConditions
        JetFunctionLiteral functionLiteral = (JetFunctionLiteral) element;
        PsiElement anchor = functionLiteral.getLBrace();
        newParameterList = (JetParameterList) element.addAfter(newParameterList, anchor);
        if (functionLiteral.getArrowNode() == null) {
          Pair<PsiElement, PsiElement> whitespaceAndArrow = psiFactory.createWhitespaceAndArrow();
          element.addRangeAfter(
              whitespaceAndArrow.getFirst(), whitespaceAndArrow.getSecond(), newParameterList);
        }
      }
    }

    if (newParameterList != null) {
      ShortenPackage.addToShorteningWaitSet(newParameterList, Options.DEFAULT);
    }
  }