@Override
 public StackValue visitLabeledExpression(
     @NotNull KtLabeledExpression expression, StackValue receiver) {
   KtExpression baseExpression = expression.getBaseExpression();
   assert baseExpression != null
       : "Label expression should have base one: " + expression.getText();
   return baseExpression.accept(this, receiver);
 }
 @Override
 public void invoke(@NotNull Project project, Editor editor, KtFile file)
     throws IncorrectOperationException {
   if (getElement() instanceof KtBinaryExpressionWithTypeRHS) {
     KtExpression left = ((KtBinaryExpressionWithTypeRHS) getElement()).getLeft();
     KtTypeReference right = ((KtBinaryExpressionWithTypeRHS) getElement()).getRight();
     if (right != null) {
       KtExpression expression =
           KtPsiFactoryKt.KtPsiFactory(file)
               .createExpression(left.getText() + operation + right.getText());
       getElement().replace(expression);
     }
   }
 }
 @NotNull
 private static KtBinaryExpression createVariableAssignment(@NotNull KtProperty property) {
   String propertyName = property.getName();
   assert propertyName != null : "Property should have a name " + property.getText();
   KtBinaryExpression assignment =
       (KtBinaryExpression)
           KtPsiFactoryKt.KtPsiFactory(property).createExpression(propertyName + " = x");
   KtExpression right = assignment.getRight();
   assert right != null
       : "Created binary expression should have a right part " + assignment.getText();
   KtExpression initializer = property.getInitializer();
   assert initializer != null : "Initializer should exist for property " + property.getText();
   right.replace(initializer);
   return assignment;
 }
Example #4
0
  @Nullable
  public static KtExpression getParentCallIfPresent(@NotNull KtExpression expression) {
    PsiElement parent = expression.getParent();
    while (parent != null) {
      if (parent instanceof KtBinaryExpression
          || parent instanceof KtUnaryExpression
          || parent instanceof KtLabeledExpression
          || parent instanceof KtDotQualifiedExpression
          || parent instanceof KtCallExpression
          || parent instanceof KtArrayAccessExpression
          || parent instanceof KtDestructuringDeclaration) {

        if (parent instanceof KtLabeledExpression) {
          parent = parent.getParent();
          continue;
        }

        // check that it's in inlineable call would be in resolve call of parent
        return (KtExpression) parent;
      } else if (parent instanceof KtParenthesizedExpression
          || parent instanceof KtBinaryExpressionWithTypeRHS) {
        parent = parent.getParent();
      } else if (parent instanceof KtValueArgument || parent instanceof KtValueArgumentList) {
        parent = parent.getParent();
      } else if (parent instanceof KtLambdaExpression || parent instanceof KtAnnotatedExpression) {
        parent = parent.getParent();
      } else {
        return null;
      }
    }
    return null;
  }
  @NotNull
  public KotlinType safeGetType(
      @NotNull LexicalScope scope,
      @NotNull KtExpression expression,
      @NotNull KotlinType expectedType,
      @NotNull DataFlowInfo dataFlowInfo,
      @NotNull BindingTrace trace) {
    KotlinType type = getType(scope, expression, expectedType, dataFlowInfo, trace);

    return type != null ? type : ErrorUtils.createErrorType("Type for " + expression.getText());
  }
  /**
   * Visits block statements propagating data flow information from the first to the last.
   * Determines block returned type and data flow information at the end of the block AND at the
   * nearest jump point from the block beginning.
   */
  /*package*/ KotlinTypeInfo getBlockReturnedTypeWithWritableScope(
      @NotNull LexicalWritableScope scope,
      @NotNull List<? extends KtElement> block,
      @NotNull CoercionStrategy coercionStrategyForLastExpression,
      @NotNull ExpressionTypingContext context) {
    if (block.isEmpty()) {
      return TypeInfoFactoryKt.createTypeInfo(
          expressionTypingComponents.builtIns.getUnitType(), context);
    }

    ExpressionTypingInternals blockLevelVisitor =
        new ExpressionTypingVisitorDispatcher.ForBlock(
            expressionTypingComponents, annotationChecker, scope);
    ExpressionTypingContext newContext =
        context.replaceScope(scope).replaceExpectedType(NO_EXPECTED_TYPE);

    KotlinTypeInfo result = TypeInfoFactoryKt.noTypeInfo(context);
    // Jump point data flow info
    DataFlowInfo beforeJumpInfo = newContext.dataFlowInfo;
    boolean jumpOutPossible = false;
    for (Iterator<? extends KtElement> iterator = block.iterator(); iterator.hasNext(); ) {
      KtElement statement = iterator.next();
      if (!(statement instanceof KtExpression)) {
        continue;
      }
      KtExpression statementExpression = (KtExpression) statement;
      if (!iterator.hasNext()) {
        result =
            getTypeOfLastExpressionInBlock(
                statementExpression,
                newContext.replaceExpectedType(context.expectedType),
                coercionStrategyForLastExpression,
                blockLevelVisitor);
        if (result.getType() != null
            && statementExpression.getParent() instanceof KtBlockExpression) {
          DataFlowValue lastExpressionValue =
              DataFlowValueFactory.createDataFlowValue(
                  statementExpression, result.getType(), context);
          DataFlowValue blockExpressionValue =
              DataFlowValueFactory.createDataFlowValue(
                  (KtBlockExpression) statementExpression.getParent(), result.getType(), context);
          result =
              result.replaceDataFlowInfo(
                  result.getDataFlowInfo().assign(blockExpressionValue, lastExpressionValue));
        }
      } else {
        result =
            blockLevelVisitor.getTypeInfo(
                statementExpression,
                newContext.replaceContextDependency(ContextDependency.INDEPENDENT),
                true);
      }

      DataFlowInfo newDataFlowInfo = result.getDataFlowInfo();
      // If jump is not possible, we take new data flow info before jump
      if (!jumpOutPossible) {
        beforeJumpInfo = result.getJumpFlowInfo();
        jumpOutPossible = result.getJumpOutPossible();
      }
      if (newDataFlowInfo != context.dataFlowInfo) {
        newContext = newContext.replaceDataFlowInfo(newDataFlowInfo);
        // We take current data flow info if jump there is not possible
      }
      blockLevelVisitor =
          new ExpressionTypingVisitorDispatcher.ForBlock(
              expressionTypingComponents, annotationChecker, scope);
    }
    return result.replaceJumpOutPossible(jumpOutPossible).replaceJumpFlowInfo(beforeJumpInfo);
  }
Example #7
0
  public static boolean areParenthesesNecessary(
      @NotNull KtExpression innerExpression,
      @NotNull KtExpression currentInner,
      @NotNull KtElement parentElement) {
    if (parentElement instanceof KtParenthesizedExpression
        || innerExpression instanceof KtParenthesizedExpression) {
      return false;
    }

    if (parentElement instanceof KtPackageDirective) return false;

    if (parentElement instanceof KtWhenExpression || innerExpression instanceof KtWhenExpression) {
      return false;
    }

    if (innerExpression instanceof KtIfExpression) {
      if (parentElement instanceof KtQualifiedExpression) return true;

      PsiElement current = parentElement;

      while (!(current instanceof KtBlockExpression
          || current instanceof KtDeclaration
          || current instanceof KtStatementExpression
          || current instanceof KtFile)) {
        if (current.getTextRange().getEndOffset() != currentInner.getTextRange().getEndOffset()) {
          return !(current instanceof KtParenthesizedExpression)
              && !(current
                  instanceof
                  KtValueArgumentList); // if current expression is "guarded" by parenthesis, no
                                        // extra parenthesis is necessary
        }

        current = current.getParent();
      }
    }

    if (parentElement instanceof KtCallExpression
        && currentInner == ((KtCallExpression) parentElement).getCalleeExpression()) {
      if (innerExpression instanceof KtSimpleNameExpression) return false;
      if (KtPsiUtilKt.getQualifiedExpressionForSelector(parentElement) != null) return true;
      return !(innerExpression instanceof KtThisExpression
          || innerExpression instanceof KtArrayAccessExpression
          || innerExpression instanceof KtConstantExpression
          || innerExpression instanceof KtStringTemplateExpression
          || innerExpression instanceof KtCallExpression);
    }

    if (parentElement instanceof KtValueArgument) {
      // a(___, d > (e + f)) => a((b < c), d > (e + f)) to prevent parsing < c, d > as type argument
      // list
      KtValueArgument nextArg =
          PsiTreeUtil.getNextSiblingOfType(parentElement, KtValueArgument.class);
      PsiElement nextExpression = nextArg != null ? nextArg.getArgumentExpression() : null;
      if (innerExpression instanceof KtBinaryExpression
          && ((KtBinaryExpression) innerExpression).getOperationToken() == KtTokens.LT
          && nextExpression instanceof KtBinaryExpression
          && ((KtBinaryExpression) nextExpression).getOperationToken() == KtTokens.GT) return true;
    }

    if (!(parentElement instanceof KtExpression)) return false;

    IElementType innerOperation = getOperation(innerExpression);
    IElementType parentOperation = getOperation((KtExpression) parentElement);

    // 'return (@label{...})' case
    if (parentElement instanceof KtReturnExpression
        && (innerExpression instanceof KtLabeledExpression
            || innerExpression instanceof KtAnnotatedExpression)) return true;

    // '(x: Int) < y' case
    if (innerExpression instanceof KtBinaryExpressionWithTypeRHS
        && parentOperation == KtTokens.LT) {
      return true;
    }

    if (parentElement instanceof KtLabeledExpression) return false;

    // 'x ?: ...' case
    if (parentElement instanceof KtBinaryExpression
        && parentOperation == KtTokens.ELVIS
        && currentInner == ((KtBinaryExpression) parentElement).getRight()) {
      return false;
    }

    int innerPriority = getPriority(innerExpression);
    int parentPriority = getPriority((KtExpression) parentElement);

    if (innerPriority == parentPriority) {
      if (parentElement instanceof KtBinaryExpression) {
        if (innerOperation == KtTokens.ANDAND || innerOperation == KtTokens.OROR) {
          return false;
        }
        return ((KtBinaryExpression) parentElement).getRight() == currentInner;
      }

      // '-(-x)' case
      if (parentElement instanceof KtPrefixExpression
          && innerExpression instanceof KtPrefixExpression) {
        return innerOperation == parentOperation
            && (innerOperation == KtTokens.PLUS || innerOperation == KtTokens.MINUS);
      }
      return false;
    }

    return innerPriority < parentPriority;
  }
Example #8
0
 private static boolean isBooleanConstant(@Nullable KtExpression condition) {
   return condition != null
       && condition.getNode().getElementType() == KtNodeTypes.BOOLEAN_CONSTANT;
 }
Example #9
0
 public static boolean isFalseConstant(@Nullable KtExpression condition) {
   return isBooleanConstant(condition)
       && condition.getNode().findChildByType(KtTokens.FALSE_KEYWORD) != null;
 }
Example #10
0
 public static boolean isNullConstant(@NotNull KtExpression expression) {
   KtExpression deparenthesized = deparenthesize(expression);
   return deparenthesized instanceof KtConstantExpression
       && deparenthesized.getNode().getElementType() == KtNodeTypes.NULL;
 }
Example #11
0
 public static boolean isLHSOfDot(@NotNull KtExpression expression) {
   PsiElement parent = expression.getParent();
   if (!(parent instanceof KtQualifiedExpression)) return false;
   KtQualifiedExpression qualifiedParent = (KtQualifiedExpression) parent;
   return qualifiedParent.getReceiverExpression() == expression || isLHSOfDot(qualifiedParent);
 }