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);
}
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);
}
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;
}
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;
}
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;
}
}
Aggregations