Search in sources :

Example 76 with TextRange

use of com.intellij.openapi.util.TextRange in project intellij-community by JetBrains.

the class IntroduceHandler method performAction.

public void performAction(IntroduceOperation operation) {
    final PsiFile file = operation.getFile();
    if (!CommonRefactoringUtil.checkReadOnlyStatus(file)) {
        return;
    }
    final Editor editor = operation.getEditor();
    if (editor.getSettings().isVariableInplaceRenameEnabled()) {
        final TemplateState templateState = TemplateManagerImpl.getTemplateState(operation.getEditor());
        if (templateState != null && !templateState.isFinished()) {
            return;
        }
    }
    PsiElement element1 = null;
    PsiElement element2 = null;
    final SelectionModel selectionModel = editor.getSelectionModel();
    boolean singleElementSelection = false;
    if (selectionModel.hasSelection()) {
        element1 = file.findElementAt(selectionModel.getSelectionStart());
        element2 = file.findElementAt(selectionModel.getSelectionEnd() - 1);
        if (element1 instanceof PsiWhiteSpace) {
            int startOffset = element1.getTextRange().getEndOffset();
            element1 = file.findElementAt(startOffset);
        }
        if (element2 instanceof PsiWhiteSpace) {
            int endOffset = element2.getTextRange().getStartOffset();
            element2 = file.findElementAt(endOffset - 1);
        }
        if (element1 == element2) {
            singleElementSelection = true;
        }
    } else {
        if (smartIntroduce(operation)) {
            return;
        }
        final CaretModel caretModel = editor.getCaretModel();
        final Document document = editor.getDocument();
        int lineNumber = document.getLineNumber(caretModel.getOffset());
        if ((lineNumber >= 0) && (lineNumber < document.getLineCount())) {
            element1 = file.findElementAt(document.getLineStartOffset(lineNumber));
            element2 = file.findElementAt(document.getLineEndOffset(lineNumber) - 1);
        }
    }
    final Project project = operation.getProject();
    if (element1 == null || element2 == null) {
        showCannotPerformError(project, editor);
        return;
    }
    element1 = PyRefactoringUtil.getSelectedExpression(project, file, element1, element2);
    final PyComprehensionElement comprehension = PsiTreeUtil.getParentOfType(element1, PyComprehensionElement.class, true);
    if (element1 == null || comprehension != null) {
        showCannotPerformError(project, editor);
        return;
    }
    if (singleElementSelection && element1 instanceof PyStringLiteralExpression) {
        final PyStringLiteralExpression literal = (PyStringLiteralExpression) element1;
        // Currently introduce for substrings of a multi-part string literals is not supported
        if (literal.getStringNodes().size() > 1) {
            showCannotPerformError(project, editor);
            return;
        }
        final int offset = element1.getTextOffset();
        final TextRange selectionRange = TextRange.create(selectionModel.getSelectionStart(), selectionModel.getSelectionEnd());
        final TextRange elementRange = element1.getTextRange();
        if (!elementRange.equals(selectionRange) && elementRange.contains(selectionRange)) {
            final TextRange innerRange = literal.getStringValueTextRange();
            final TextRange intersection = selectionRange.shiftRight(-offset).intersection(innerRange);
            final TextRange finalRange = intersection != null ? intersection : selectionRange;
            final String text = literal.getText();
            if (getFormatValueExpression(literal) != null && breaksStringFormatting(text, finalRange) || getNewStyleFormatValueExpression(literal) != null && breaksNewStyleStringFormatting(text, finalRange) || breaksStringEscaping(text, finalRange)) {
                showCannotPerformError(project, editor);
                return;
            }
            element1.putUserData(PyReplaceExpressionUtil.SELECTION_BREAKS_AST_NODE, Pair.create(element1, finalRange));
        }
    }
    if (!checkIntroduceContext(file, editor, element1)) {
        return;
    }
    operation.setElement(element1);
    performActionOnElement(operation);
}
Also used : CaretModel(com.intellij.openapi.editor.CaretModel) TextRange(com.intellij.openapi.util.TextRange) Document(com.intellij.openapi.editor.Document) TemplateState(com.intellij.codeInsight.template.impl.TemplateState) Project(com.intellij.openapi.project.Project) SelectionModel(com.intellij.openapi.editor.SelectionModel) Editor(com.intellij.openapi.editor.Editor)

Example 77 with TextRange

use of com.intellij.openapi.util.TextRange in project intellij-community by JetBrains.

the class PyExpressionAsConditionSurrounder method surroundExpression.

@Override
public TextRange surroundExpression(@NotNull Project project, @NotNull Editor editor, @NotNull PyExpression expression) throws IncorrectOperationException {
    TextRange currentCaretPosition = TextRange.from(editor.getCaretModel().getOffset(), 0);
    PyStatement statement = PyElementGenerator.getInstance(project).createFromText(LanguageLevel.forElement(expression), PyStatement.class, getTextToGenerate());
    final PyExpression condition = getCondition(statement);
    if (condition == null) {
        return currentCaretPosition;
    }
    condition.replace(expression);
    statement = (PyStatement) CodeStyleManager.getInstance(project).reformat(statement);
    statement = (PyStatement) expression.getParent().replace(statement);
    PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(editor.getDocument());
    PyStatementListContainer statementListContainer = getStatementListContainer(statement);
    if (statementListContainer == null) {
        return currentCaretPosition;
    }
    PyStatementList statementList = statementListContainer.getStatementList();
    PyStatement[] statements = statementList.getStatements();
    if (statements.length == 0) {
        return currentCaretPosition;
    }
    final TextRange range = statements[0].getTextRange();
    editor.getDocument().deleteString(range.getStartOffset(), range.getEndOffset());
    return TextRange.from(range.getStartOffset(), 0);
}
Also used : TextRange(com.intellij.openapi.util.TextRange)

Example 78 with TextRange

use of com.intellij.openapi.util.TextRange in project intellij-community by JetBrains.

the class PyWithTryExceptSurrounder method surroundStatement.

@Override
@Nullable
protected TextRange surroundStatement(@NotNull Project project, @NotNull Editor editor, @NotNull PsiElement[] elements) throws IncorrectOperationException {
    PyTryExceptStatement tryStatement = PyElementGenerator.getInstance(project).createFromText(LanguageLevel.getDefault(), PyTryExceptStatement.class, getTemplate());
    final PsiElement parent = elements[0].getParent();
    final PyStatementList statementList = tryStatement.getTryPart().getStatementList();
    statementList.addRange(elements[0], elements[elements.length - 1]);
    statementList.getFirstChild().delete();
    tryStatement = (PyTryExceptStatement) parent.addBefore(tryStatement, elements[0]);
    parent.deleteChildRange(elements[0], elements[elements.length - 1]);
    final PsiFile psiFile = parent.getContainingFile();
    final Document document = psiFile.getViewProvider().getDocument();
    final TextRange range = tryStatement.getTextRange();
    assert document != null;
    final RangeMarker rangeMarker = document.createRangeMarker(range);
    final PsiElement element = psiFile.findElementAt(rangeMarker.getStartOffset());
    tryStatement = PsiTreeUtil.getParentOfType(element, PyTryExceptStatement.class);
    if (tryStatement != null) {
        return getResultRange(tryStatement);
    }
    return null;
}
Also used : PsiFile(com.intellij.psi.PsiFile) TextRange(com.intellij.openapi.util.TextRange) RangeMarker(com.intellij.openapi.editor.RangeMarker) Document(com.intellij.openapi.editor.Document) PsiElement(com.intellij.psi.PsiElement) Nullable(org.jetbrains.annotations.Nullable)

Example 79 with TextRange

use of com.intellij.openapi.util.TextRange in project intellij-community by JetBrains.

the class XmlGtTypedHandler method beforeCharTyped.

@Override
public Result beforeCharTyped(final char c, final Project project, Editor editor, PsiFile editedFile, final FileType fileType) {
    final WebEditorOptions webEditorOptions = WebEditorOptions.getInstance();
    if (c == '>' && webEditorOptions != null && webEditorOptions.isAutomaticallyInsertClosingTag() && fileContainsXmlLanguage(editedFile)) {
        PsiDocumentManager.getInstance(project).commitAllDocuments();
        PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument());
        FileViewProvider provider = editedFile.getViewProvider();
        int offset = editor.getCaretModel().getOffset();
        PsiElement element, elementAtCaret = null;
        if (offset < editor.getDocument().getTextLength()) {
            elementAtCaret = element = provider.findElementAt(offset, XMLLanguage.class);
            if (element == null && offset > 0) {
                // seems like a template language
                // <xml_code><caret><outer_element>
                elementAtCaret = element = provider.findElementAt(offset - 1, XMLLanguage.class);
            }
            if (!(element instanceof PsiWhiteSpace)) {
                boolean nonAcceptableDelimiter = true;
                if (element instanceof XmlToken) {
                    IElementType tokenType = ((XmlToken) element).getTokenType();
                    if (tokenType == XmlTokenType.XML_START_TAG_START || tokenType == XmlTokenType.XML_END_TAG_START) {
                        if (offset > 0) {
                            PsiElement previousElement = provider.findElementAt(offset - 1, XMLLanguage.class);
                            if (previousElement instanceof XmlToken) {
                                tokenType = ((XmlToken) previousElement).getTokenType();
                                element = previousElement;
                                nonAcceptableDelimiter = false;
                            }
                        }
                    } else if (tokenType == XmlTokenType.XML_NAME || tokenType == XmlTokenType.XML_TAG_NAME) {
                        if (element.getNextSibling() instanceof PsiErrorElement) {
                            nonAcceptableDelimiter = false;
                        }
                    }
                    if (tokenType == XmlTokenType.XML_TAG_END || tokenType == XmlTokenType.XML_EMPTY_ELEMENT_END && element.getTextOffset() == offset - 1) {
                        EditorModificationUtil.moveCaretRelatively(editor, 1);
                        editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
                        return Result.STOP;
                    }
                }
                if (nonAcceptableDelimiter)
                    return Result.CONTINUE;
            } else {
                // check if right after empty end
                PsiElement previousElement = provider.findElementAt(offset - 1, XMLLanguage.class);
                if (previousElement instanceof XmlToken) {
                    final IElementType tokenType = ((XmlToken) previousElement).getTokenType();
                    if (tokenType == XmlTokenType.XML_EMPTY_ELEMENT_END) {
                        return Result.STOP;
                    }
                }
            }
            PsiElement parent = element.getParent();
            if (parent instanceof XmlText) {
                final String text = parent.getText();
                // check /
                final int index = offset - parent.getTextOffset() - 1;
                if (index >= 0 && text.charAt(index) == '/') {
                    // already seen /
                    return Result.CONTINUE;
                }
                element = parent.getPrevSibling();
            } else if (parent instanceof XmlTag && !(element.getPrevSibling() instanceof XmlTag) && !(element.getPrevSibling() instanceof OuterLanguageElement)) {
                element = parent;
            } else if (parent instanceof XmlAttributeValue) {
                element = parent;
            }
        } else {
            element = provider.findElementAt(editor.getDocument().getTextLength() - 1, XMLLanguage.class);
            if (element == null)
                return Result.CONTINUE;
            element = element.getParent();
        }
        if (offset > 0 && offset <= editor.getDocument().getTextLength()) {
            if (editor.getDocument().getCharsSequence().charAt(offset - 1) == '/') {
                // Some languages (e.g. GSP) allow character '/' in tag name.
                return Result.CONTINUE;
            }
        }
        if (element instanceof XmlAttributeValue) {
            element = element.getParent().getParent();
        }
        while (element instanceof PsiWhiteSpace || element instanceof OuterLanguageElement) element = element.getPrevSibling();
        if (element instanceof XmlDocument) {
            // hack for closing tags in RHTML
            element = element.getLastChild();
        }
        if (element == null)
            return Result.CONTINUE;
        if (!(element instanceof XmlTag)) {
            if (element instanceof XmlTokenImpl && element.getPrevSibling() != null && element.getPrevSibling().getText().equals("<")) {
                // tag is started and there is another text in the end
                EditorModificationUtil.insertStringAtCaret(editor, "</" + element.getText() + ">", false, 0);
            }
            return Result.CONTINUE;
        }
        XmlTag tag = (XmlTag) element;
        if (XmlUtil.getTokenOfType(tag, XmlTokenType.XML_TAG_END) != null)
            return Result.CONTINUE;
        if (XmlUtil.getTokenOfType(tag, XmlTokenType.XML_EMPTY_ELEMENT_END) != null)
            return Result.CONTINUE;
        final XmlToken startToken = XmlUtil.getTokenOfType(tag, XmlTokenType.XML_START_TAG_START);
        if (startToken == null || !startToken.getText().equals("<"))
            return Result.CONTINUE;
        String name = tag.getName();
        if (elementAtCaret instanceof XmlToken && (((XmlToken) elementAtCaret).getTokenType() == XmlTokenType.XML_NAME || ((XmlToken) elementAtCaret).getTokenType() == XmlTokenType.XML_TAG_NAME)) {
            name = name.substring(0, offset - elementAtCaret.getTextOffset());
        }
        if (tag instanceof HtmlTag && HtmlUtil.isSingleHtmlTag(name))
            return Result.CONTINUE;
        if (name.isEmpty())
            return Result.CONTINUE;
        int tagOffset = tag.getTextRange().getStartOffset();
        final XmlToken nameToken = XmlUtil.getTokenOfType(tag, XmlTokenType.XML_NAME);
        if (nameToken != null && nameToken.getTextRange().getStartOffset() > offset)
            return Result.CONTINUE;
        HighlighterIterator iterator = ((EditorEx) editor).getHighlighter().createIterator(tagOffset);
        if (BraceMatchingUtil.matchBrace(editor.getDocument().getCharsSequence(), editedFile.getFileType(), iterator, true, true)) {
            PsiElement parent = tag.getParent();
            boolean hasBalance = true;
            loop: while (parent instanceof XmlTag) {
                if (name.equals(((XmlTag) parent).getName())) {
                    hasBalance = false;
                    ASTNode astNode = XmlChildRole.CLOSING_TAG_NAME_FINDER.findChild(parent.getNode());
                    if (astNode == null) {
                        hasBalance = true;
                        break;
                    }
                    for (PsiElement el = parent.getNextSibling(); el != null; el = el.getNextSibling()) {
                        if (el instanceof PsiErrorElement && el.getText().startsWith("</" + name)) {
                            hasBalance = true;
                            break loop;
                        }
                    }
                }
                parent = parent.getParent();
            }
            if (hasBalance)
                return Result.CONTINUE;
        }
        Collection<TextRange> cdataReformatRanges = null;
        final XmlElementDescriptor descriptor = tag.getDescriptor();
        EditorModificationUtil.insertStringAtCaret(editor, "</" + name + ">", false, 0);
        if (descriptor instanceof XmlElementDescriptorWithCDataContent) {
            final XmlElementDescriptorWithCDataContent cDataContainer = (XmlElementDescriptorWithCDataContent) descriptor;
            cdataReformatRanges = ContainerUtil.newSmartList();
            if (cDataContainer.requiresCdataBracesInContext(tag)) {
                @NonNls final String cDataStart = "><![CDATA[";
                final String inserted = cDataStart + "\n]]>";
                EditorModificationUtil.insertStringAtCaret(editor, inserted, false, cDataStart.length());
                int caretOffset = editor.getCaretModel().getOffset();
                if (caretOffset >= cDataStart.length()) {
                    cdataReformatRanges.add(TextRange.from(caretOffset - cDataStart.length(), inserted.length() + 1));
                }
            }
        }
        if (cdataReformatRanges != null && !cdataReformatRanges.isEmpty()) {
            PsiDocumentManager.getInstance(project).commitDocument(editor.getDocument());
            try {
                CodeStyleManager.getInstance(project).reformatText(file, cdataReformatRanges);
            } catch (IncorrectOperationException e) {
                LOG.error(e);
            }
        }
        return cdataReformatRanges != null && !cdataReformatRanges.isEmpty() ? Result.STOP : Result.CONTINUE;
    }
    return Result.CONTINUE;
}
Also used : OuterLanguageElement(com.intellij.psi.templateLanguages.OuterLanguageElement) XmlTokenImpl(com.intellij.psi.impl.source.xml.XmlTokenImpl) TemplateLanguageFileViewProvider(com.intellij.psi.templateLanguages.TemplateLanguageFileViewProvider) WebEditorOptions(com.intellij.application.options.editor.WebEditorOptions) ASTNode(com.intellij.lang.ASTNode) XMLLanguage(com.intellij.lang.xml.XMLLanguage) NonNls(org.jetbrains.annotations.NonNls) HtmlTag(com.intellij.psi.html.HtmlTag) TextRange(com.intellij.openapi.util.TextRange) IElementType(com.intellij.psi.tree.IElementType) XmlElementDescriptorWithCDataContent(com.intellij.xml.XmlElementDescriptorWithCDataContent) IncorrectOperationException(com.intellij.util.IncorrectOperationException) XmlElementDescriptor(com.intellij.xml.XmlElementDescriptor) HighlighterIterator(com.intellij.openapi.editor.highlighter.HighlighterIterator)

Example 80 with TextRange

use of com.intellij.openapi.util.TextRange in project intellij-community by JetBrains.

the class XmlTokenSelectioner method select.

@Override
public List<TextRange> select(PsiElement e, CharSequence editorText, int cursorOffset, Editor editor) {
    XmlToken token = (XmlToken) e;
    if (shouldSelectToken(token)) {
        List<TextRange> ranges = super.select(e, editorText, cursorOffset, editor);
        SelectWordUtil.addWordSelection(editor.getSettings().isCamelWords(), editorText, cursorOffset, ranges);
        return ranges;
    } else {
        List<TextRange> result = new ArrayList<>();
        SelectWordUtil.addWordSelection(editor.getSettings().isCamelWords(), editorText, cursorOffset, result);
        return result;
    }
}
Also used : ArrayList(java.util.ArrayList) TextRange(com.intellij.openapi.util.TextRange) XmlToken(com.intellij.psi.xml.XmlToken)

Aggregations

TextRange (com.intellij.openapi.util.TextRange)1314 PsiElement (com.intellij.psi.PsiElement)261 NotNull (org.jetbrains.annotations.NotNull)237 Nullable (org.jetbrains.annotations.Nullable)167 Document (com.intellij.openapi.editor.Document)132 ArrayList (java.util.ArrayList)117 Project (com.intellij.openapi.project.Project)96 PsiFile (com.intellij.psi.PsiFile)96 ASTNode (com.intellij.lang.ASTNode)95 Editor (com.intellij.openapi.editor.Editor)75 PsiReference (com.intellij.psi.PsiReference)54 VirtualFile (com.intellij.openapi.vfs.VirtualFile)51 IElementType (com.intellij.psi.tree.IElementType)48 IncorrectOperationException (com.intellij.util.IncorrectOperationException)48 Pair (com.intellij.openapi.util.Pair)47 HighlightInfo (com.intellij.codeInsight.daemon.impl.HighlightInfo)33 ProperTextRange (com.intellij.openapi.util.ProperTextRange)32 FoldingDescriptor (com.intellij.lang.folding.FoldingDescriptor)31 XmlTag (com.intellij.psi.xml.XmlTag)31 List (java.util.List)31