mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Smart trailing spaces filter and implementation for indents on empty lines (IDEA-163554, IDEA-144196)
This commit is contained in:
+8
-8
@@ -186,12 +186,12 @@ public class JavaFormatterInEditorTest extends LightPlatformCodeInsightTestCase
|
||||
"<caret>package com.acme;\n" +
|
||||
"\n" +
|
||||
"class Foo {\n" +
|
||||
" Integer[] foo() {\n" +
|
||||
" \n" +
|
||||
" \n" +
|
||||
" return new Integer[]{0, 1};\n" +
|
||||
" }\n" +
|
||||
" \n" +
|
||||
" Integer[] foo() {\n" +
|
||||
" \n" +
|
||||
" \n" +
|
||||
" return new Integer[]{0, 1};\n" +
|
||||
" }\n" +
|
||||
" \n" +
|
||||
"}";
|
||||
|
||||
final String expected =
|
||||
@@ -207,8 +207,8 @@ public class JavaFormatterInEditorTest extends LightPlatformCodeInsightTestCase
|
||||
"}";
|
||||
|
||||
configureFromFileText(getTestName(false) + ".java", initial);
|
||||
WriteCommandAction.runWriteCommandAction(getProject(), () -> CodeStyleManager.getInstance(getProject())
|
||||
.reformatText(getFile(), 0, getEditor().getDocument().getTextLength()));
|
||||
//WriteCommandAction.runWriteCommandAction(getProject(), () -> CodeStyleManager.getInstance(getProject())
|
||||
// .reformatText(getFile(), 0, getEditor().getDocument().getTextLength()));
|
||||
Document doc = getEditor().getDocument();
|
||||
EditorTestUtil.performTypingAction(getEditor(), ' ');
|
||||
PsiDocumentManager.getInstance(getProject()).commitDocument(doc);
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2000-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.openapi.editor;
|
||||
|
||||
/**
|
||||
* Allows to control how many whitespace characters must be left on any given line if not all of them can be removed.
|
||||
*/
|
||||
public abstract class SmartStripTrailingSpacesFilter implements StripTrailingSpacesFilter {
|
||||
@Override
|
||||
public final boolean isStripSpacesAllowedForLine(int line) {
|
||||
return getTrailingSpacesToLeave(line) >= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param line The line for which a number of whitespace characters to leave must be calculated.
|
||||
* @return The maximum number of whitespace characters to be left or -1 if the line should be left intact
|
||||
* (trailing spaces can not be removed). If the actual number of whitespace characters on the line is less than the
|
||||
* returned number, the line will not be changed.
|
||||
*/
|
||||
public abstract int getTrailingSpacesToLeave(int line);
|
||||
}
|
||||
@@ -236,7 +236,8 @@ public class DocumentImpl extends UserDataHolderBase implements DocumentEx {
|
||||
lineLoop:
|
||||
for (int line = 0; line < getLineCount(); line++) {
|
||||
LineSet lineSet = getLineSet();
|
||||
if (inChangedLinesOnly && !lineSet.isModified(line) || !canStripSpacesFrom(line, filters)) continue;
|
||||
int maxSpacesToLeave = getMaxSpacesToLeave(line, filters);
|
||||
if (inChangedLinesOnly && !lineSet.isModified(line) || maxSpacesToLeave < 0) continue;
|
||||
int whiteSpaceStart = -1;
|
||||
final int lineEnd = lineSet.getLineEnd(line) - lineSet.getSeparatorLength(line);
|
||||
int lineStart = lineSet.getLineStart(line);
|
||||
@@ -261,15 +262,17 @@ public class DocumentImpl extends UserDataHolderBase implements DocumentEx {
|
||||
}
|
||||
}
|
||||
}
|
||||
final int finalStart = whiteSpaceStart;
|
||||
// document must be unblocked by now. If not, some Save handler attempted to modify PSI
|
||||
// which should have been caught by assertion in com.intellij.pom.core.impl.PomModelImpl.runTransaction
|
||||
DocumentUtil.writeInRunUndoTransparentAction(new DocumentRunnable(DocumentImpl.this, project) {
|
||||
@Override
|
||||
public void run() {
|
||||
deleteString(finalStart, lineEnd);
|
||||
}
|
||||
});
|
||||
final int finalStart = whiteSpaceStart + maxSpacesToLeave;
|
||||
if (finalStart < lineEnd) {
|
||||
// document must be unblocked by now. If not, some Save handler attempted to modify PSI
|
||||
// which should have been caught by assertion in com.intellij.pom.core.impl.PomModelImpl.runTransaction
|
||||
DocumentUtil.writeInRunUndoTransparentAction(new DocumentRunnable(DocumentImpl.this, project) {
|
||||
@Override
|
||||
public void run() {
|
||||
deleteString(finalStart, lineEnd);
|
||||
}
|
||||
});
|
||||
}
|
||||
text = myText;
|
||||
}
|
||||
}
|
||||
@@ -294,11 +297,16 @@ public class DocumentImpl extends UserDataHolderBase implements DocumentEx {
|
||||
return markAsNeedsStrippingLater;
|
||||
}
|
||||
|
||||
private static boolean canStripSpacesFrom(int line, @NotNull List<StripTrailingSpacesFilter> filters) {
|
||||
private static int getMaxSpacesToLeave(int line, @NotNull List<StripTrailingSpacesFilter> filters) {
|
||||
for (StripTrailingSpacesFilter filter : filters) {
|
||||
if (!filter.isStripSpacesAllowedForLine(line)) return false;
|
||||
if (filter instanceof SmartStripTrailingSpacesFilter) {
|
||||
return ((SmartStripTrailingSpacesFilter)filter).getTrailingSpacesToLeave(line);
|
||||
}
|
||||
else if (!filter.isStripSpacesAllowedForLine(line)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+48
-3
@@ -16,6 +16,7 @@
|
||||
package com.intellij.psi.codeStyle;
|
||||
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.SmartStripTrailingSpacesFilter;
|
||||
import com.intellij.openapi.editor.StripTrailingSpacesFilter;
|
||||
import com.intellij.openapi.editor.StripTrailingSpacesFilterFactory;
|
||||
import com.intellij.openapi.project.Project;
|
||||
@@ -28,7 +29,7 @@ import static com.intellij.openapi.editor.StripTrailingSpacesFilter.ALL_LINES;
|
||||
|
||||
public class KeepTrailingSpacesOnEmptyLinesFilterFactory extends StripTrailingSpacesFilterFactory {
|
||||
|
||||
private static class KeepTrailingSpacesOnEmptyLinesFilter implements StripTrailingSpacesFilter {
|
||||
private static class KeepTrailingSpacesOnEmptyLinesFilter extends SmartStripTrailingSpacesFilter {
|
||||
private @NotNull Document myDocument;
|
||||
|
||||
public KeepTrailingSpacesOnEmptyLinesFilter(@NotNull Document document) {
|
||||
@@ -36,10 +37,10 @@ public class KeepTrailingSpacesOnEmptyLinesFilterFactory extends StripTrailingSp
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStripSpacesAllowedForLine(int line) {
|
||||
public int getTrailingSpacesToLeave(int line) {
|
||||
int startOffset = myDocument.getLineStartOffset(line);
|
||||
int endOffset = myDocument.getLineEndOffset(line);
|
||||
return !containsWhitespacesOnly(myDocument.getCharsSequence(), startOffset, endOffset);
|
||||
return containsWhitespacesOnly(myDocument.getCharsSequence(), startOffset, endOffset) ? getMaxIndentChars(line): 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -51,6 +52,50 @@ public class KeepTrailingSpacesOnEmptyLinesFilterFactory extends StripTrailingSp
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private int getMaxIndentChars(int line) {
|
||||
int lineBefore = getNonEmptyLineBefore(line);
|
||||
int indentCharCount = -1;
|
||||
if (lineBefore >= 0) {
|
||||
indentCharCount = countIndentCharsAt(lineBefore);
|
||||
}
|
||||
int lineAfter = getNonEmptyLineAfter(line);
|
||||
if (lineAfter >= 0) {
|
||||
indentCharCount = Math.max(indentCharCount, countIndentCharsAt(lineAfter));
|
||||
}
|
||||
return indentCharCount;
|
||||
}
|
||||
|
||||
private int getNonEmptyLineBefore(int line) {
|
||||
CharSequence docChars = myDocument.getCharsSequence();
|
||||
for (int lineBefore = line - 1; lineBefore >= 0; lineBefore --) {
|
||||
if (!containsWhitespacesOnly(docChars, myDocument.getLineStartOffset(lineBefore), myDocument.getLineEndOffset(lineBefore))) {
|
||||
return lineBefore;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private int getNonEmptyLineAfter(int line) {
|
||||
CharSequence docChars = myDocument.getCharsSequence();
|
||||
for (int lineAfter = line + 1; lineAfter < myDocument.getLineCount(); lineAfter ++) {
|
||||
if (!containsWhitespacesOnly(docChars, myDocument.getLineStartOffset(lineAfter), myDocument.getLineEndOffset(lineAfter))) {
|
||||
return lineAfter;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private int countIndentCharsAt(int line) {
|
||||
int count = 0;
|
||||
CharSequence docChars = myDocument.getCharsSequence();
|
||||
for (int offset = myDocument.getLineStartOffset(line); offset < myDocument.getTextLength(); offset ++) {
|
||||
char c = docChars.charAt(offset);
|
||||
if (c != ' ' && c != '\t') break;
|
||||
count ++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user