コード例 #1
0
 @Override
 public KotlinTypeInfo visitContinueExpression(
     @NotNull KtContinueExpression expression, ExpressionTypingContext context) {
   LabelResolver.INSTANCE.resolveControlLabel(expression, context);
   return components
       .dataFlowAnalyzer
       .createCheckedTypeInfo(components.builtIns.getNothingType(), context, expression)
       .replaceJumpOutPossible(true);
 }
コード例 #2
0
  @Override
  public KotlinTypeInfo visitReturnExpression(
      @NotNull KtReturnExpression expression, ExpressionTypingContext context) {
    KtElement labelTargetElement = LabelResolver.INSTANCE.resolveControlLabel(expression, context);

    KtExpression returnedExpression = expression.getReturnedExpression();

    KotlinType expectedType = NO_EXPECTED_TYPE;
    KotlinType resultType = components.builtIns.getNothingType();
    KtDeclaration parentDeclaration = PsiTreeUtil.getParentOfType(expression, KtDeclaration.class);

    if (parentDeclaration instanceof KtParameter) {
      // In a default value for parameter
      context.trace.report(RETURN_NOT_ALLOWED.on(expression));
    }

    if (expression.getTargetLabel() == null) {
      while (parentDeclaration instanceof KtMultiDeclaration) {
        // TODO: It's hacking fix for KT-5100: Strange "Return is not allowed here" for
        // multi-declaration initializer with elvis expression
        parentDeclaration = PsiTreeUtil.getParentOfType(parentDeclaration, KtDeclaration.class);
      }

      assert parentDeclaration != null
          : "Can't find parent declaration for " + expression.getText();
      DeclarationDescriptor declarationDescriptor =
          context.trace.get(DECLARATION_TO_DESCRIPTOR, parentDeclaration);
      Pair<FunctionDescriptor, PsiElement> containingFunInfo =
          BindingContextUtils.getContainingFunctionSkipFunctionLiterals(
              declarationDescriptor, false);
      FunctionDescriptor containingFunctionDescriptor = containingFunInfo.getFirst();

      if (containingFunctionDescriptor != null) {
        if (!InlineUtil.checkNonLocalReturnUsage(
                containingFunctionDescriptor, expression, context.trace)
            || isClassInitializer(containingFunInfo)) {
          // Unqualified, in a function literal
          context.trace.report(RETURN_NOT_ALLOWED.on(expression));
          resultType = ErrorUtils.createErrorType(RETURN_NOT_ALLOWED_MESSAGE);
        }

        expectedType =
            getFunctionExpectedReturnType(
                containingFunctionDescriptor, (KtElement) containingFunInfo.getSecond(), context);
      } else {
        // Outside a function
        context.trace.report(RETURN_NOT_ALLOWED.on(expression));
        resultType = ErrorUtils.createErrorType(RETURN_NOT_ALLOWED_MESSAGE);
      }
    } else if (labelTargetElement != null) {
      SimpleFunctionDescriptor functionDescriptor = context.trace.get(FUNCTION, labelTargetElement);
      if (functionDescriptor != null) {
        expectedType =
            getFunctionExpectedReturnType(functionDescriptor, labelTargetElement, context);
        if (!InlineUtil.checkNonLocalReturnUsage(functionDescriptor, expression, context.trace)) {
          // Qualified, non-local
          context.trace.report(RETURN_NOT_ALLOWED.on(expression));
          resultType = ErrorUtils.createErrorType(RETURN_NOT_ALLOWED_MESSAGE);
        }
      } else {
        context.trace.report(NOT_A_RETURN_LABEL.on(expression, expression.getLabelName()));
      }
    }
    if (returnedExpression != null) {
      facade.getTypeInfo(
          returnedExpression,
          context
              .replaceExpectedType(expectedType)
              .replaceScope(context.scope)
              .replaceContextDependency(INDEPENDENT));
    } else {
      if (expectedType != null
          && !noExpectedType(expectedType)
          && !KotlinBuiltIns.isUnit(expectedType)
          && !isDontCarePlaceholder(expectedType)) // for lambda with implicit return type Unit
      {
        context.trace.report(RETURN_TYPE_MISMATCH.on(expression, expectedType));
      }
    }
    return components.dataFlowAnalyzer.createCheckedTypeInfo(resultType, context, expression);
  }