예제 #1
0
 @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;
 }
예제 #4
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);
  }
  @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());
  }
예제 #6
0
  @Nullable
  @Override
  protected TextRange surroundStatements(
      Project project, Editor editor, PsiElement container, PsiElement[] statements) {
    statements =
        MoveDeclarationsOutHelper.move(container, statements, isGenerateDefaultInitializers());

    if (statements.length == 0) {
      KotlinSurrounderUtils.showErrorHint(
          project, editor, KotlinSurrounderUtils.SURROUND_WITH_ERROR);
      return null;
    }

    KtIfExpression ifExpression =
        (KtIfExpression) KtPsiFactoryKt.KtPsiFactory(project).createExpression(getCodeTemplate());
    ifExpression =
        (KtIfExpression) container.addAfter(ifExpression, statements[statements.length - 1]);

    // TODO move a comment for first statement

    KtBlockExpression thenBranch = (KtBlockExpression) ifExpression.getThen();
    assert thenBranch != null
        : "Then branch should exist for created if expression: " + ifExpression.getText();
    // Add statements in then branch of created if
    KotlinSurrounderUtils.addStatementsInBlock(thenBranch, statements);

    // Delete statements from original code
    container.deleteChildRange(statements[0], statements[statements.length - 1]);

    ifExpression = CodeInsightUtilBase.forcePsiPostprocessAndRestoreElement(ifExpression);

    KtExpression condition = ifExpression.getCondition();
    assert condition != null
        : "Condition should exists for created if expression: " + ifExpression.getText();
    // Delete condition from created if
    TextRange range = condition.getTextRange();
    TextRange textRange = new TextRange(range.getStartOffset(), range.getStartOffset());
    editor.getDocument().deleteString(range.getStartOffset(), range.getEndOffset());
    return textRange;
  }
  /**
   * 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);
  }