Example #1
0
  @Nullable
  private static JetBlockExpression findClosestBlock(
      @NotNull PsiElement anchor, boolean down, boolean strict) {
    PsiElement current = PsiTreeUtil.getParentOfType(anchor, JetBlockExpression.class, strict);
    while (current != null) {
      PsiElement parent = current.getParent();
      if (parent instanceof JetClassBody
          || parent instanceof JetClassInitializer
          || parent instanceof JetNamedFunction
          || (parent instanceof JetProperty && !((JetProperty) parent).isLocal())) {
        return null;
      }

      if (parent instanceof JetBlockExpression) return (JetBlockExpression) parent;

      PsiElement sibling = down ? current.getNextSibling() : current.getPrevSibling();
      if (sibling != null) {
        //noinspection unchecked
        JetBlockExpression block =
            (JetBlockExpression)
                JetPsiUtil.getOutermostDescendantElement(sibling, down, CHECK_BLOCK);
        if (block != null) return block;

        current = sibling;
      } else {
        current = parent;
      }
    }

    return null;
  }
Example #2
0
  // Returns null if standalone closing brace is not found
  private static BraceStatus checkForMovableClosingBrace(
      @NotNull Editor editor, @NotNull PsiFile file, @NotNull MoveInfo info, boolean down) {
    PsiElement closingBrace = getStandaloneClosingBrace(file, editor);
    if (closingBrace == null) return BraceStatus.NOT_FOUND;

    PsiElement blockLikeElement = closingBrace.getParent();
    if (!(blockLikeElement instanceof JetBlockExpression)) return BraceStatus.NOT_MOVABLE;

    PsiElement blockParent = blockLikeElement.getParent();
    if (blockParent instanceof JetWhenEntry) return BraceStatus.NOT_FOUND;
    if (PsiTreeUtil.instanceOf(blockParent, FUNCTIONLIKE_ELEMENT_CLASSES))
      return BraceStatus.NOT_FOUND;

    PsiElement enclosingExpression =
        PsiTreeUtil.getParentOfType(blockLikeElement, JetExpression.class);

    if (enclosingExpression instanceof JetDoWhileExpression) return BraceStatus.NOT_MOVABLE;

    if (enclosingExpression instanceof JetIfExpression) {
      JetIfExpression ifExpression = (JetIfExpression) enclosingExpression;

      if (blockLikeElement == ifExpression.getThen() && ifExpression.getElse() != null)
        return BraceStatus.NOT_MOVABLE;
    }

    return down
        ? checkForMovableDownClosingBrace(closingBrace, blockLikeElement, editor, info)
        : checkForMovableUpClosingBrace(closingBrace, blockLikeElement, editor, info);
  }
Example #3
0
  private static BraceStatus checkForMovableDownClosingBrace(
      @NotNull PsiElement closingBrace,
      @NotNull PsiElement block,
      @NotNull Editor editor,
      @NotNull MoveInfo info) {
    PsiElement current = block;
    PsiElement nextElement = null;
    PsiElement nextExpression = null;
    do {
      PsiElement sibling = firstNonWhiteElement(current.getNextSibling(), true);
      if (sibling != null && nextElement == null) {
        nextElement = sibling;
      }

      if (sibling instanceof JetExpression) {
        nextExpression = sibling;
        break;
      }

      current = current.getParent();
    } while (current != null && !(PsiTreeUtil.instanceOf(current, BLOCKLIKE_ELEMENT_CLASSES)));

    if (nextExpression == null) return BraceStatus.NOT_MOVABLE;

    Document doc = editor.getDocument();

    info.toMove = new LineRange(closingBrace, closingBrace, doc);
    info.toMove2 = new LineRange(nextElement, nextExpression);
    info.indentSource = true;

    return BraceStatus.MOVABLE;
  }
Example #4
0
 @NotNull
 @Override
 public Boolean invoke(PsiElement element) {
   return (!(element instanceof JetExpression)
       || element instanceof JetDeclaration
       || element instanceof JetBlockExpression
       || element.getParent() instanceof JetBlockExpression);
 }
Example #5
0
  @Nullable
  private static PsiElement getMovableElement(@NotNull PsiElement element, boolean lookRight) {
    //noinspection unchecked
    PsiElement movableElement =
        PsiUtilPackage.getParentByTypesAndPredicate(
            element, false, MOVABLE_ELEMENT_CLASSES, MOVABLE_ELEMENT_CONSTRAINT);
    if (movableElement == null) return null;

    if (isBracelessBlock(movableElement)) {
      movableElement =
          firstNonWhiteElement(
              lookRight ? movableElement.getLastChild() : movableElement.getFirstChild(),
              !lookRight);
    }

    return movableElement;
  }
Example #6
0
 /**
  * Add import directive corresponding to a type to file when it is needed.
  *
  * @param type type to import
  * @param file file where import directive should be added
  */
 public static void addImportDirectivesIfNeeded(@NotNull JetType type, @NotNull JetFile file) {
   if (JetPluginUtil.checkTypeIsStandard(type, file.getProject())
       || ErrorUtils.isErrorType(type)) {
     return;
   }
   BindingContext bindingContext = getContextForSingleFile(file);
   PsiElement element =
       BindingContextUtils.descriptorToDeclaration(
           bindingContext, type.getMemberScope().getContainingDeclaration());
   if (element != null
       && element.getContainingFile()
           == file) { // declaration is in the same file, so no import is needed
     return;
   }
   for (ClassDescriptor clazz : TypeUtils.getAllClassDescriptors(type)) {
     addImportDirective(DescriptorUtils.getFQName(getTopLevelClass(clazz)).toSafe(), file);
   }
 }
Example #7
0
  public static void addImportDirectiveOrChangeToFqName(
      @NotNull FqName importFqn,
      @NotNull JetFile file,
      int refOffset,
      @NotNull PsiElement targetElement) {
    PsiReference reference = file.findReferenceAt(refOffset);
    if (reference instanceof JetPsiReference) {
      PsiElement target = reference.resolve();
      if (target != null) {
        boolean same = file.getManager().areElementsEquivalent(target, targetElement);

        if (!same) {
          same =
              target instanceof PsiClass
                  && importFqn.getFqName().equals(((PsiClass) target).getQualifiedName());
        }

        if (!same) {
          if (target instanceof PsiMethod) {
            PsiMethod method = (PsiMethod) target;
            same =
                (method.isConstructor()
                    && file.getManager()
                        .areElementsEquivalent(method.getContainingClass(), targetElement));
          }
        }

        if (!same) {
          if (target instanceof JetObjectDeclarationName) {
            same = file.getManager().areElementsEquivalent(target.getParent(), targetElement);
          }
        }

        if (!same) {
          Document document = PsiDocumentManager.getInstance(file.getProject()).getDocument(file);
          TextRange refRange = reference.getElement().getTextRange();
          document.replaceString(
              refRange.getStartOffset(), refRange.getEndOffset(), importFqn.getFqName());
        }
        return;
      }
    }
    addImportDirective(new ImportPath(importFqn, false), null, file);
  }
Example #8
0
  @Nullable
  private static LineRange getWhenEntryTargetRange(
      @NotNull Editor editor, @NotNull PsiElement sibling, boolean down) {
    if (sibling.getNode().getElementType() == (down ? JetTokens.RBRACE : JetTokens.LBRACE)
        && PsiTreeUtil.getParentOfType(sibling, JetWhenEntry.class) == null) {
      return null;
    }

    return new LineRange(sibling, sibling, editor.getDocument());
  }
Example #9
0
  @Override
  protected LineRange getElementSourceLineRange(
      @NotNull PsiElement element, @NotNull Editor editor, @NotNull LineRange oldRange) {
    TextRange textRange = element.getTextRange();
    if (editor.getDocument().getTextLength() < textRange.getEndOffset()) return null;

    int startLine = editor.offsetToLogicalPosition(textRange.getStartOffset()).line;
    int endLine = editor.offsetToLogicalPosition(textRange.getEndOffset()).line + 1;

    return new LineRange(startLine, endLine);
  }
Example #10
0
  @Nullable
  private LineRange getValueParamOrArgTargetRange(
      @NotNull Editor editor,
      @NotNull PsiElement elementToCheck,
      @NotNull PsiElement sibling,
      boolean down) {
    PsiElement next = sibling;

    if (next.getNode().getElementType() == JetTokens.COMMA) {
      next = firstNonWhiteSibling(next, down);
    }

    LineRange range =
        (next instanceof JetParameter || next instanceof JetValueArgument)
            ? new LineRange(next, next, editor.getDocument())
            : null;

    if (range != null) {
      parametersOrArgsToMove = new Pair<PsiElement, PsiElement>(elementToCheck, next);
    }

    return range;
  }
Example #11
0
  protected static PsiElement adjustSibling(
      @NotNull Editor editor,
      @NotNull LineRange sourceRange,
      @NotNull MoveInfo info,
      boolean down) {
    PsiElement element = down ? sourceRange.lastElement : sourceRange.firstElement;
    PsiElement sibling = down ? element.getNextSibling() : element.getPrevSibling();

    PsiElement whiteSpaceTestSubject = sibling;
    if (sibling == null) {
      PsiElement parent = element.getParent();
      if (parent != null && isBracelessBlock(parent)) {
        whiteSpaceTestSubject = down ? parent.getNextSibling() : parent.getPrevSibling();
      }
    }

    if (whiteSpaceTestSubject instanceof PsiWhiteSpace) {
      if (getElementLineCount(whiteSpaceTestSubject, editor) > 1) {
        int nearLine = down ? sourceRange.endLine : sourceRange.startLine - 1;

        info.toMove = sourceRange;
        info.toMove2 = new LineRange(nearLine, nearLine + 1);
        info.indentTarget = false;

        return null;
      }

      if (sibling != null) {
        sibling = firstNonWhiteElement(sibling, down);
      }
    }

    if (sibling == null) {
      JetCallExpression callExpression =
          PsiTreeUtil.getParentOfType(element, JetCallExpression.class);
      if (callExpression != null) {
        JetBlockExpression dslBlock = getDSLLambdaBlock(callExpression, down);
        if (PsiTreeUtil.isAncestor(dslBlock, element, false)) {
          //noinspection ConstantConditions
          PsiElement blockParent = dslBlock.getParent();
          return down
              ? JetPsiUtil.findChildByType(blockParent, JetTokens.RBRACE)
              : JetPsiUtil.findChildByType(blockParent, JetTokens.LBRACE);
        }
      }

      info.toMove2 = null;
      return null;
    }

    return sibling;
  }
Example #12
0
  private static void fixCommaIfNeeded(@NotNull PsiElement element, boolean willBeLast) {
    PsiElement comma = getComma(element);
    if (willBeLast && comma != null) {
      comma.delete();
    } else if (!willBeLast && comma == null) {
      PsiElement parent = element.getParent();
      assert parent != null;

      parent.addAfter(JetPsiFactory(parent.getProject()).createComma(), element);
    }
  }
Example #13
0
 private static PsiElement getComma(@NotNull PsiElement element) {
   PsiElement sibling = firstNonWhiteSibling(element, true);
   return sibling != null && (sibling.getNode().getElementType() == JetTokens.COMMA)
       ? sibling
       : null;
 }
Example #14
0
 private static boolean isLastOfItsKind(@NotNull PsiElement element, boolean down) {
   return getSiblingOfType(element, down, element.getClass()) == null;
 }
Example #15
0
  @Nullable
  private static LineRange getExpressionTargetRange(
      @NotNull Editor editor, @NotNull PsiElement sibling, boolean down) {
    if (sibling instanceof JetIfExpression && !down) {
      JetExpression elseBranch = ((JetIfExpression) sibling).getElse();
      if (elseBranch instanceof JetBlockExpression) {
        sibling = elseBranch;
      }
    }

    PsiElement start = sibling;
    PsiElement end = sibling;

    // moving out of code block
    if (sibling.getNode().getElementType() == (down ? JetTokens.RBRACE : JetTokens.LBRACE)) {
      PsiElement parent = sibling.getParent();
      if (!(parent instanceof JetBlockExpression || parent instanceof JetFunctionLiteral))
        return null;

      JetBlockExpression newBlock;
      if (parent instanceof JetFunctionLiteral) {
        //noinspection ConstantConditions
        newBlock = findClosestBlock(((JetFunctionLiteral) parent).getBodyExpression(), down, false);

        if (!down) {
          ASTNode arrow = ((JetFunctionLiteral) parent).getArrowNode();
          if (arrow != null) {
            end = arrow.getPsi();
          }
        }
      } else {
        newBlock = findClosestBlock(sibling, down, true);
      }

      if (newBlock == null) return null;

      if (PsiTreeUtil.isAncestor(newBlock, parent, true)) {
        PsiElement outermostParent = JetPsiUtil.getOutermostParent(parent, newBlock, true);

        if (down) {
          end = outermostParent;
        } else {
          start = outermostParent;
        }
      } else {
        if (down) {
          end = newBlock.getLBrace();
        } else {
          start = newBlock.getRBrace();
        }
      }
    }
    // moving into code block
    else {
      PsiElement blockLikeElement;

      JetBlockExpression dslBlock = getDSLLambdaBlock(sibling, down);
      if (dslBlock != null) {
        // Use JetFunctionLiteral (since it contains braces)
        blockLikeElement = dslBlock.getParent();
      } else {
        // JetBlockExpression and other block-like elements
        blockLikeElement =
            JetPsiUtil.getOutermostDescendantElement(sibling, down, CHECK_BLOCK_LIKE_ELEMENT);
      }

      if (blockLikeElement != null) {
        if (down) {
          end = JetPsiUtil.findChildByType(blockLikeElement, JetTokens.LBRACE);
          if (blockLikeElement instanceof JetFunctionLiteral) {
            ASTNode arrow = ((JetFunctionLiteral) blockLikeElement).getArrowNode();
            if (arrow != null) {
              end = arrow.getPsi();
            }
          }
        } else {
          start = JetPsiUtil.findChildByType(blockLikeElement, JetTokens.RBRACE);
        }
      }
    }

    return start != null && end != null ? new LineRange(start, end, editor.getDocument()) : null;
  }