Search in sources :

Example 36 with CodeStyleManager

use of com.intellij.psi.codeStyle.CodeStyleManager in project intellij-community by JetBrains.

the class PasteHandler method indentEachLine.

private static void indentEachLine(Project project, Editor editor, int startOffset, int endOffset) {
    PsiDocumentManager.getInstance(project).commitAllDocuments();
    PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument());
    CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(project);
    final CharSequence text = editor.getDocument().getCharsSequence();
    if (startOffset > 0 && endOffset > startOffset + 1 && text.charAt(endOffset - 1) == '\n' && text.charAt(startOffset - 1) == '\n') {
        // There is a possible situation that pasted text ends by a line feed. We don't want to proceed it when a text is
        // pasted at the first line column.
        // Example:
        //    text to paste:
        //'if (true) {
        //'
        //    source:
        // if (true) {
        //     int i = 1;
        //     int j = 1;
        // }
        //
        //
        // We get the following on paste then:
        // if (true) {
        //     if (true) {
        //         int i = 1;
        //     int j = 1;
        // }
        //
        // We don't want line 'int i = 1;' to be indented here.
        endOffset--;
    }
    try {
        codeStyleManager.adjustLineIndent(file, new TextRange(startOffset, endOffset));
    } catch (IncorrectOperationException e) {
        LOG.error(e);
    }
}
Also used : CodeStyleManager(com.intellij.psi.codeStyle.CodeStyleManager) PsiFile(com.intellij.psi.PsiFile) TextRange(com.intellij.openapi.util.TextRange) IncorrectOperationException(com.intellij.util.IncorrectOperationException)

Example 37 with CodeStyleManager

use of com.intellij.psi.codeStyle.CodeStyleManager in project intellij-community by JetBrains.

the class PasteHandler method indentBlockWithFormatter.

private static void indentBlockWithFormatter(Project project, final Document document, int startOffset, int endOffset, PsiFile file) {
    // Algorithm: the main idea is to process the first line of the pasted block, adjust its indent if necessary, calculate indent
    // adjustment string and apply to each line of the pasted block starting from the second one.
    //
    // We differentiate the following possible states here:
    //   --- pasted block doesn't start new line, i.e. there are non-white space symbols before it at the first line.
    //      Example:
    //         old content [pasted line 1
    //                pasted line 2]
    //      Indent adjustment string is just the first line indent then.
    //
    //   --- pasted block starts with empty line(s)
    //      Example:
    //         old content [
    //            pasted line 1
    //            pasted line 2]
    //      We parse existing indents of the pasted block then, adjust its first non-blank line via formatter and adjust indent
    //      of subsequent pasted lines in order to preserve old indentation.
    //
    //   --- pasted block is located at the new line and starts with white space symbols.
    //       Example:
    //          [   pasted line 1
    //                 pasted line 2]
    //       We parse existing indents of the pasted block then, adjust its first line via formatter and adjust indent of the pasted lines
    //       starting from the second one in order to preserve old indentation.
    //
    //   --- pasted block is located at the new line but doesn't start with white space symbols.
    //       Example:
    //           [pasted line 1
    //         pasted line 2]
    //       We adjust the first line via formatter then and apply first line's indent to all subsequent pasted lines.
    final CharSequence chars = document.getCharsSequence();
    final int firstLine = document.getLineNumber(startOffset);
    final int firstLineStart = document.getLineStartOffset(firstLine);
    // There is a possible case that we paste block that ends with new line that is empty or contains only white space symbols.
    // We want to preserve indent for the original document line where paste was performed.
    // Example:
    //   Original:
    //       if (test) {
    //   <caret>    }
    //
    //   Pasting: 'int i = 1;\n'
    //   Expected:
    //       if (test) {
    //           int i = 1;
    //       }
    boolean saveLastLineIndent = false;
    for (int i = endOffset - 1; i >= startOffset; i--) {
        final char c = chars.charAt(i);
        if (c == '\n') {
            saveLastLineIndent = true;
            break;
        }
        if (c != ' ' && c != '\t') {
            break;
        }
    }
    final int lastLine;
    if (saveLastLineIndent) {
        lastLine = document.getLineNumber(endOffset) - 1;
        // Remove white space symbols at the pasted text if any.
        int start = document.getLineStartOffset(lastLine + 1);
        if (start < endOffset) {
            int i = CharArrayUtil.shiftForward(chars, start, " \t");
            if (i > start) {
                i = Math.min(i, endOffset);
                document.deleteString(start, i);
            }
        }
        // Insert white space from the start line of the pasted block.
        int indentToKeepEndOffset = Math.min(startOffset, CharArrayUtil.shiftForward(chars, firstLineStart, " \t"));
        if (indentToKeepEndOffset > firstLineStart) {
            document.insertString(start, chars.subSequence(firstLineStart, indentToKeepEndOffset));
        }
    } else {
        lastLine = document.getLineNumber(endOffset);
    }
    final int i = CharArrayUtil.shiftBackward(chars, startOffset - 1, " \t");
    // Handle a situation when pasted block doesn't start a new line.
    if (chars.charAt(startOffset) != '\n' && i > 0 && chars.charAt(i) != '\n') {
        int firstNonWsOffset = CharArrayUtil.shiftForward(chars, firstLineStart, " \t");
        if (firstNonWsOffset > firstLineStart) {
            CharSequence toInsert = chars.subSequence(firstLineStart, firstNonWsOffset);
            indentLines(document, firstLine + 1, lastLine, toInsert);
        }
        return;
    }
    // Sync document and PSI for correct formatting processing.
    PsiDocumentManager.getInstance(project).commitAllDocuments();
    if (file == null) {
        return;
    }
    CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(project);
    final int j = CharArrayUtil.shiftForward(chars, startOffset, " \t\n");
    if (j >= endOffset) {
        // Pasted text contains white space/line feed symbols only, do nothing.
        return;
    }
    final int anchorLine = document.getLineNumber(j);
    final int anchorLineStart = document.getLineStartOffset(anchorLine);
    codeStyleManager.adjustLineIndent(file, j);
    // Handle situation when pasted block starts with non-white space symbols.
    if (anchorLine == firstLine && j == startOffset) {
        int indentOffset = CharArrayUtil.shiftForward(chars, firstLineStart, " \t");
        if (indentOffset > firstLineStart) {
            CharSequence toInsert = chars.subSequence(firstLineStart, indentOffset);
            indentLines(document, firstLine + 1, lastLine, toInsert);
        }
        return;
    }
    // Handle situation when pasted block starts from white space symbols. Assume that the pasted text started at the line start,
    // i.e. correct indentation level is stored at the blocks structure.
    final int firstNonWsOffset = CharArrayUtil.shiftForward(chars, anchorLineStart, " \t");
    final int diff = firstNonWsOffset - j;
    if (diff == 0) {
        return;
    }
    if (diff > 0) {
        CharSequence toInsert = chars.subSequence(anchorLineStart, anchorLineStart + diff);
        indentLines(document, anchorLine + 1, lastLine, toInsert);
        return;
    }
    //                              line2'
    if (anchorLine == firstLine && -diff == startOffset - firstLineStart) {
        return;
    }
    if (anchorLine != firstLine || -diff > startOffset - firstLineStart) {
        final int desiredSymbolsToRemove;
        if (anchorLine == firstLine) {
            desiredSymbolsToRemove = -diff - (startOffset - firstLineStart);
        } else {
            desiredSymbolsToRemove = -diff;
        }
        Runnable deindentTask = () -> {
            for (int line = anchorLine + 1; line <= lastLine; line++) {
                int currentLineStart = document.getLineStartOffset(line);
                int currentLineIndentOffset = CharArrayUtil.shiftForward(chars, currentLineStart, " \t");
                int symbolsToRemove = Math.min(currentLineIndentOffset - currentLineStart, desiredSymbolsToRemove);
                if (symbolsToRemove > 0) {
                    document.deleteString(currentLineStart, currentLineStart + symbolsToRemove);
                }
            }
        };
        DocumentUtil.executeInBulk(document, lastLine - anchorLine > LINE_LIMIT_FOR_BULK_CHANGE, deindentTask);
    } else {
        CharSequence toInsert = chars.subSequence(anchorLineStart, diff + startOffset);
        indentLines(document, anchorLine + 1, lastLine, toInsert);
    }
}
Also used : CodeStyleManager(com.intellij.psi.codeStyle.CodeStyleManager)

Example 38 with CodeStyleManager

use of com.intellij.psi.codeStyle.CodeStyleManager in project intellij-community by JetBrains.

the class TemplateState method reformat.

private void reformat() {
    final PsiFile file = getPsiFile();
    if (file != null) {
        CodeStyleManager style = CodeStyleManager.getInstance(myProject);
        DumbService dumbService = DumbService.getInstance(myProject);
        for (TemplateOptionalProcessor processor : dumbService.filterByDumbAwareness(Extensions.getExtensions(TemplateOptionalProcessor.EP_NAME))) {
            try {
                processor.processText(myProject, myTemplate, myDocument, myTemplateRange, myEditor);
            } catch (IncorrectOperationException e) {
                LOG.error(e);
            }
        }
        PsiDocumentManager.getInstance(myProject).doPostponedOperationsAndUnblockDocument(myDocument);
        // and reformat wouldn't be able to fix them
        if (myTemplate.isToIndent()) {
            if (!myTemplateIndented) {
                LOG.assertTrue(myTemplateRange.isValid(), presentTemplate(myTemplate));
                smartIndent(myTemplateRange.getStartOffset(), myTemplateRange.getEndOffset());
                myTemplateIndented = true;
            }
        }
        if (myTemplate.isToReformat()) {
            try {
                int endSegmentNumber = myTemplate.getEndSegmentNumber();
                PsiDocumentManager.getInstance(myProject).commitDocument(myDocument);
                RangeMarker dummyAdjustLineMarkerRange = null;
                int endVarOffset = -1;
                if (endSegmentNumber >= 0) {
                    endVarOffset = mySegments.getSegmentStart(endSegmentNumber);
                    TextRange range = CodeStyleManagerImpl.insertNewLineIndentMarker(file, myDocument, endVarOffset);
                    if (range != null)
                        dummyAdjustLineMarkerRange = myDocument.createRangeMarker(range);
                }
                int reformatStartOffset = myTemplateRange.getStartOffset();
                int reformatEndOffset = myTemplateRange.getEndOffset();
                if (dummyAdjustLineMarkerRange == null && endVarOffset >= 0) {
                    // There is a possible case that indent marker element was not inserted (e.g. because there is no blank line
                    // at the target offset). However, we want to reformat white space adjacent to the current template (if any).
                    PsiElement whiteSpaceElement = CodeStyleManagerImpl.findWhiteSpaceNode(file, endVarOffset);
                    if (whiteSpaceElement != null) {
                        TextRange whiteSpaceRange = whiteSpaceElement.getTextRange();
                        if (whiteSpaceElement.getContainingFile() != null) {
                            // Support injected white space nodes.
                            whiteSpaceRange = InjectedLanguageManager.getInstance(file.getProject()).injectedToHost(whiteSpaceElement, whiteSpaceRange);
                        }
                        reformatStartOffset = Math.min(reformatStartOffset, whiteSpaceRange.getStartOffset());
                        reformatEndOffset = Math.max(reformatEndOffset, whiteSpaceRange.getEndOffset());
                    }
                }
                style.reformatText(file, reformatStartOffset, reformatEndOffset);
                unblockDocument();
                if (dummyAdjustLineMarkerRange != null && dummyAdjustLineMarkerRange.isValid()) {
                    //[ven] TODO: [max] correct javadoc reformatting to eliminate isValid() check!!!
                    mySegments.replaceSegmentAt(endSegmentNumber, dummyAdjustLineMarkerRange.getStartOffset(), dummyAdjustLineMarkerRange.getEndOffset());
                    myDocument.deleteString(dummyAdjustLineMarkerRange.getStartOffset(), dummyAdjustLineMarkerRange.getEndOffset());
                    PsiDocumentManager.getInstance(myProject).commitDocument(myDocument);
                }
                if (endSegmentNumber >= 0) {
                    final int offset = mySegments.getSegmentStart(endSegmentNumber);
                    final int lineStart = myDocument.getLineStartOffset(myDocument.getLineNumber(offset));
                    // if $END$ is at line start, put it at correct indentation
                    if (myDocument.getCharsSequence().subSequence(lineStart, offset).toString().trim().isEmpty()) {
                        final int adjustedOffset = style.adjustLineIndent(file, offset);
                        mySegments.replaceSegmentAt(endSegmentNumber, adjustedOffset, adjustedOffset);
                    }
                }
            } catch (IncorrectOperationException e) {
                LOG.error(e);
            }
        }
    }
}
Also used : CodeStyleManager(com.intellij.psi.codeStyle.CodeStyleManager) PsiFile(com.intellij.psi.PsiFile) TextRange(com.intellij.openapi.util.TextRange) DumbService(com.intellij.openapi.project.DumbService) PsiElement(com.intellij.psi.PsiElement)

Example 39 with CodeStyleManager

use of com.intellij.psi.codeStyle.CodeStyleManager in project intellij-community by JetBrains.

the class Match method replaceByStatement.

public PsiElement replaceByStatement(final PsiMethod extractedMethod, final PsiMethodCallExpression methodCallExpression, final PsiVariable outputVariable) throws IncorrectOperationException {
    PsiStatement statement = null;
    if (outputVariable != null) {
        ReturnValue returnValue = getOutputVariableValue(outputVariable);
        if (returnValue == null && outputVariable instanceof PsiField) {
            returnValue = new FieldReturnValue((PsiField) outputVariable);
        }
        if (returnValue == null)
            return null;
        statement = returnValue.createReplacement(extractedMethod, methodCallExpression);
    } else if (getReturnValue() != null) {
        statement = getReturnValue().createReplacement(extractedMethod, methodCallExpression);
    }
    if (statement == null) {
        final PsiElementFactory elementFactory = JavaPsiFacade.getInstance(methodCallExpression.getProject()).getElementFactory();
        PsiExpressionStatement expressionStatement = (PsiExpressionStatement) elementFactory.createStatementFromText("x();", null);
        final CodeStyleManager styleManager = CodeStyleManager.getInstance(methodCallExpression.getManager());
        expressionStatement = (PsiExpressionStatement) styleManager.reformat(expressionStatement);
        expressionStatement.getExpression().replace(methodCallExpression);
        statement = expressionStatement;
    }
    return replaceWith(statement);
}
Also used : JavaCodeStyleManager(com.intellij.psi.codeStyle.JavaCodeStyleManager) CodeStyleManager(com.intellij.psi.codeStyle.CodeStyleManager)

Example 40 with CodeStyleManager

use of com.intellij.psi.codeStyle.CodeStyleManager in project intellij-community by JetBrains.

the class VariableReturnValue method createReplacement.

public PsiStatement createReplacement(final PsiMethod extractedMethod, final PsiMethodCallExpression methodCallExpression) throws IncorrectOperationException {
    final PsiDeclarationStatement statement;
    final PsiElementFactory elementFactory = JavaPsiFacade.getInstance(methodCallExpression.getProject()).getElementFactory();
    final CodeStyleManager styleManager = CodeStyleManager.getInstance(methodCallExpression.getProject());
    statement = (PsiDeclarationStatement) styleManager.reformat(elementFactory.createVariableDeclarationStatement(myVariable.getName(), myVariable.getType(), methodCallExpression));
    ((PsiVariable) statement.getDeclaredElements()[0]).getModifierList().replace(myVariable.getModifierList());
    return statement;
}
Also used : CodeStyleManager(com.intellij.psi.codeStyle.CodeStyleManager)

Aggregations

CodeStyleManager (com.intellij.psi.codeStyle.CodeStyleManager)97 JavaCodeStyleManager (com.intellij.psi.codeStyle.JavaCodeStyleManager)29 Project (com.intellij.openapi.project.Project)26 TextRange (com.intellij.openapi.util.TextRange)19 NonNls (org.jetbrains.annotations.NonNls)18 IncorrectOperationException (com.intellij.util.IncorrectOperationException)16 NotNull (org.jetbrains.annotations.NotNull)8 Document (com.intellij.openapi.editor.Document)6 PsiFile (com.intellij.psi.PsiFile)6 Module (com.intellij.openapi.module.Module)5 PsiElement (com.intellij.psi.PsiElement)4 PsiDocComment (com.intellij.psi.javadoc.PsiDocComment)4 Nullable (org.jetbrains.annotations.Nullable)4 CaretModel (com.intellij.openapi.editor.CaretModel)3 CodeStyleSettings (com.intellij.psi.codeStyle.CodeStyleSettings)3 JavaLanguage (com.intellij.lang.java.JavaLanguage)2 FileType (com.intellij.openapi.fileTypes.FileType)2 Comparing (com.intellij.openapi.util.Comparing)2 StringUtil (com.intellij.openapi.util.text.StringUtil)2 com.intellij.psi (com.intellij.psi)2