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