mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-70602 Soft wrap in xml files: lines after long line are wrapped though they are not too long
This commit is contained in:
+6
-5
@@ -23,15 +23,15 @@ import org.jetbrains.annotations.Nullable;
|
||||
/**
|
||||
* {@link LineWrapPositionStrategy} implementation that uses
|
||||
* {@link LanguageLineWrapPositionStrategy#getDefaultImplementation() default line wrap strategy} but restricts its scope
|
||||
* by {@link #PsiAwareDefaultLineWrapPositionStrategy(IElementType...) target tokens/elements}.
|
||||
* by {@link #PsiAwareDefaultLineWrapPositionStrategy(boolean, IElementType...) target tokens/elements}.
|
||||
*
|
||||
* @author Denis Zhdanov
|
||||
* @since 5/12/11 12:50 PM
|
||||
*/
|
||||
public class PsiAwareDefaultLineWrapPositionStrategy extends PsiAwareLineWrapPositionStrategy {
|
||||
|
||||
public PsiAwareDefaultLineWrapPositionStrategy(@NotNull IElementType ... enabledTypes) {
|
||||
super(enabledTypes);
|
||||
public PsiAwareDefaultLineWrapPositionStrategy(boolean nonVirtualOnly, @NotNull IElementType ... enabledTypes) {
|
||||
super(nonVirtualOnly, enabledTypes);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -40,10 +40,11 @@ public class PsiAwareDefaultLineWrapPositionStrategy extends PsiAwareLineWrapPos
|
||||
int startOffset,
|
||||
int endOffset,
|
||||
int maxPreferredOffset,
|
||||
boolean allowToBeyondMaxPreferredOffset)
|
||||
boolean allowToBeyondMaxPreferredOffset,
|
||||
boolean virtual)
|
||||
{
|
||||
LineWrapPositionStrategy implementation = LanguageLineWrapPositionStrategy.INSTANCE.getDefaultImplementation();
|
||||
return implementation.calculateWrapPosition(document, project, startOffset, endOffset, maxPreferredOffset,
|
||||
allowToBeyondMaxPreferredOffset);
|
||||
allowToBeyondMaxPreferredOffset, virtual);
|
||||
}
|
||||
}
|
||||
|
||||
+20
-8
@@ -39,14 +39,17 @@ public abstract class PsiAwareLineWrapPositionStrategy implements LineWrapPositi
|
||||
private static final Logger LOG = Logger.getInstance("#" + PsiAwareLineWrapPositionStrategy.class.getName());
|
||||
|
||||
private final TokenSet myEnabledTypes;
|
||||
private final boolean myNonVirtualOnly;
|
||||
|
||||
/**
|
||||
* Creates new <code>PsiAwareLineWrapPositionStrategy</code> object.
|
||||
*
|
||||
* @param nonVirtualOnly defines if current PSI-aware logic should be exploited only for 'real wrap' position requests
|
||||
* @param enabledTypes target element/token types where line wrapping is allowed
|
||||
*/
|
||||
public PsiAwareLineWrapPositionStrategy(@NotNull IElementType ... enabledTypes) {
|
||||
public PsiAwareLineWrapPositionStrategy(boolean nonVirtualOnly, @NotNull IElementType ... enabledTypes) {
|
||||
myEnabledTypes = TokenSet.create(enabledTypes);
|
||||
myNonVirtualOnly = nonVirtualOnly;
|
||||
if (enabledTypes.length <= 0) {
|
||||
LOG.warn(String.format("%s instance is created with empty token/element types. That will lead to inability to perform line wrap",
|
||||
getClass().getName()));
|
||||
@@ -59,11 +62,19 @@ public abstract class PsiAwareLineWrapPositionStrategy implements LineWrapPositi
|
||||
int startOffset,
|
||||
int endOffset,
|
||||
int maxPreferredOffset,
|
||||
boolean allowToBeyondMaxPreferredOffset) {
|
||||
boolean allowToBeyondMaxPreferredOffset,
|
||||
boolean virtual) {
|
||||
if (virtual && myNonVirtualOnly) {
|
||||
LineWrapPositionStrategy implementation = LanguageLineWrapPositionStrategy.INSTANCE.getDefaultImplementation();
|
||||
return implementation.calculateWrapPosition(
|
||||
document, project, startOffset, endOffset, maxPreferredOffset, allowToBeyondMaxPreferredOffset, virtual
|
||||
);
|
||||
}
|
||||
|
||||
if (project == null) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
PsiDocumentManager documentManager = PsiDocumentManager.getInstance(project);
|
||||
if (documentManager == null) {
|
||||
return -1;
|
||||
@@ -84,7 +95,7 @@ public abstract class PsiAwareLineWrapPositionStrategy implements LineWrapPositi
|
||||
TextRange textRange = element.getTextRange();
|
||||
int start = Math.max(textRange.getStartOffset(), startOffset);
|
||||
int end = Math.min(textRange.getEndOffset(), endOffset);
|
||||
int result = doCalculateWrapPosition(document, project, start, end, end, false);
|
||||
int result = doCalculateWrapPosition(document, project, start, end, end, false, virtual);
|
||||
if (result >= 0) {
|
||||
return result;
|
||||
}
|
||||
@@ -96,15 +107,15 @@ public abstract class PsiAwareLineWrapPositionStrategy implements LineWrapPositi
|
||||
|
||||
if (start > startOffset) {
|
||||
return start;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Serves for the same purposes as {@link #calculateWrapPosition(Document, Project, int, int, int, boolean)} but ensures that given
|
||||
* offsets target {@link #PsiAwareLineWrapPositionStrategy(IElementType...) enabled token/element types}.
|
||||
* Serves for the same purposes as {@link #calculateWrapPosition(Document, Project, int, int, int, boolean, boolean)} but ensures
|
||||
* that given offsets target {@link #PsiAwareLineWrapPositionStrategy(boolean, IElementType...) enabled token/element types}.
|
||||
*
|
||||
* @param document target document which text is being processed
|
||||
* @param project target project
|
||||
@@ -117,12 +128,13 @@ public abstract class PsiAwareLineWrapPositionStrategy implements LineWrapPositi
|
||||
* @param allowToBeyondMaxPreferredOffset indicates if it's allowed to return value from
|
||||
* <code>(maxPreferredOffset; endOffset]</code> interval in case of inability to
|
||||
* find appropriate offset from <code>(startOffset; maxPreferredOffset]</code> interval
|
||||
* @param virtual identifies if current request is for virtual wrap (soft wrap) position
|
||||
* @return offset from <code>(startOffset; endOffset]</code> interval where
|
||||
* target line should be wrapped OR <code>-1</code> if no wrapping should be performed
|
||||
*/
|
||||
protected abstract int doCalculateWrapPosition(
|
||||
@NotNull Document document, @Nullable Project project, int startOffset, int endOffset, int maxPreferredOffset,
|
||||
boolean allowToBeyondMaxPreferredOffset
|
||||
boolean allowToBeyondMaxPreferredOffset, boolean virtual
|
||||
);
|
||||
|
||||
/**
|
||||
|
||||
+1
-1
@@ -150,7 +150,7 @@ public class AutoHardWrapHandler {
|
||||
new VisualPosition(caretModel.getVisualPosition().line, margin - FormatConstants.RESERVED_LINE_WRAP_WIDTH_IN_COLUMNS)
|
||||
));
|
||||
|
||||
int wrapOffset = strategy.calculateWrapPosition(document, project, startOffset, endOffset, maxPreferredOffset, true);
|
||||
int wrapOffset = strategy.calculateWrapPosition(document, project, startOffset, endOffset, maxPreferredOffset, true, false);
|
||||
if (wrapOffset < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
+1
-1
@@ -381,7 +381,7 @@ public class CodeFormatterFacade {
|
||||
// We know that current line exceeds right margin if control flow reaches this place, so, wrap it.
|
||||
int wrapOffset = strategy.calculateWrapPosition(
|
||||
document, editor.getProject(), Math.max(startLineOffset, startOffsetToUse), Math.min(endLineOffset, endOffsetToUse),
|
||||
preferredWrapPosition, false
|
||||
preferredWrapPosition, false, false
|
||||
);
|
||||
if (wrapOffset < 0) {
|
||||
continue;
|
||||
|
||||
@@ -104,7 +104,9 @@ public interface EditorSettings {
|
||||
void setUseSoftWraps(boolean use);
|
||||
boolean isAllSoftWrapsShown();
|
||||
boolean isUseCustomSoftWrapIndent();
|
||||
void setUseCustomSoftWrapIndent(boolean useCustomSoftWrapIndent);
|
||||
int getCustomSoftWrapIndent();
|
||||
void setCustomSoftWrapIndent(int indent);
|
||||
|
||||
boolean isAllowSingleLogicalLineFolding();
|
||||
void setAllowSingleLogicalLineFolding(boolean allow);
|
||||
|
||||
+2
-1
@@ -48,7 +48,8 @@ public class GenericLineWrapPositionStrategy implements LineWrapPositionStrategy
|
||||
int startOffset,
|
||||
int endOffset,
|
||||
int maxPreferredOffset,
|
||||
boolean allowToBeyondMaxPreferredOffset)
|
||||
boolean allowToBeyondMaxPreferredOffset,
|
||||
boolean virtual)
|
||||
{
|
||||
if (endOffset <= startOffset) {
|
||||
return endOffset;
|
||||
|
||||
@@ -45,11 +45,12 @@ public interface LineWrapPositionStrategy {
|
||||
* @param allowToBeyondMaxPreferredOffset indicates if it's allowed to return value from
|
||||
* <code>(maxPreferredOffset; endOffset]</code> interval in case of inability to
|
||||
* find appropriate offset from <code>(startOffset; maxPreferredOffset]</code> interval
|
||||
* @param virtual identifies if current request is for virtual wrap (soft wrap) position
|
||||
* @return offset from <code>(startOffset; endOffset]</code> interval where
|
||||
* target line should be wrapped OR <code>-1</code> if no wrapping should be performed
|
||||
*/
|
||||
int calculateWrapPosition(
|
||||
@NotNull Document document, @Nullable Project project, int startOffset, int endOffset, int maxPreferredOffset,
|
||||
boolean allowToBeyondMaxPreferredOffset
|
||||
boolean allowToBeyondMaxPreferredOffset, boolean virtual
|
||||
);
|
||||
}
|
||||
|
||||
+2
-1
@@ -85,7 +85,8 @@ public class DefaultLineWrapPositionStrategyTest {
|
||||
final Context context = new Context(document);
|
||||
context.init();
|
||||
int actual = myStrategy.calculateWrapPosition(
|
||||
createMockDocument(context.document), myProject, 0, context.document.length(), context.edgeIndex, allowToBeyondMaxPreferredOffset
|
||||
createMockDocument(context.document), myProject, 0, context.document.length(), context.edgeIndex,
|
||||
allowToBeyondMaxPreferredOffset, true
|
||||
);
|
||||
assertSame(context.wrapIndex, actual);
|
||||
}
|
||||
|
||||
@@ -77,6 +77,8 @@ public class SettingsImpl implements EditorSettings {
|
||||
private Boolean myIsRefrainFromScrolling = null;
|
||||
private Boolean myUseSoftWraps = null;
|
||||
private Boolean myIsAllSoftWrapsShown = null;
|
||||
private Boolean myUseCustomSoftWrapIndent = null;
|
||||
private Integer myCustomSoftWrapIndent = null;
|
||||
|
||||
public boolean isRightMarginShown() {
|
||||
return myIsRightMarginShown != null
|
||||
@@ -206,8 +208,6 @@ public class SettingsImpl implements EditorSettings {
|
||||
|
||||
public void reinitSettings() {
|
||||
myCachedTabSize = null;
|
||||
//TODO den check
|
||||
//myUseSoftWraps = null;
|
||||
}
|
||||
|
||||
public int getTabSize(Project project) {
|
||||
@@ -419,12 +419,23 @@ public class SettingsImpl implements EditorSettings {
|
||||
|
||||
@Override
|
||||
public boolean isUseCustomSoftWrapIndent() {
|
||||
return EditorSettingsExternalizable.getInstance().isUseCustomSoftWrapIndent();
|
||||
return myUseCustomSoftWrapIndent == null ? EditorSettingsExternalizable.getInstance().isUseCustomSoftWrapIndent()
|
||||
: myUseCustomSoftWrapIndent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUseCustomSoftWrapIndent(boolean useCustomSoftWrapIndent) {
|
||||
myUseCustomSoftWrapIndent = useCustomSoftWrapIndent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCustomSoftWrapIndent() {
|
||||
return EditorSettingsExternalizable.getInstance().getCustomSoftWrapIndent();
|
||||
return myCustomSoftWrapIndent == null ? EditorSettingsExternalizable.getInstance().getCustomSoftWrapIndent() : myCustomSoftWrapIndent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCustomSoftWrapIndent(int indent) {
|
||||
myCustomSoftWrapIndent = indent;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+10
-7
@@ -517,10 +517,14 @@ public class SoftWrapApplianceManager implements SoftWrapFoldingListener, Docume
|
||||
myLineWrapPositionStrategy = LanguageLineWrapPositionStrategy.INSTANCE.forEditor(myEditor);
|
||||
}
|
||||
|
||||
softWrapOffset = myLineWrapPositionStrategy.calculateWrapPosition(document, myEditor.getProject(), minOffset, maxOffset, preferredOffset, true);
|
||||
softWrapOffset = myLineWrapPositionStrategy.calculateWrapPosition(
|
||||
document, myEditor.getProject(), minOffset, maxOffset, preferredOffset, true, true
|
||||
);
|
||||
}
|
||||
|
||||
if (softWrapOffset >= lineData.endLineOffset || softWrapOffset < 0) {
|
||||
if (softWrapOffset >= lineData.endLineOffset || softWrapOffset < 0
|
||||
|| (myCustomIndentUsedLastTime && softWrapOffset == lineData.nonWhiteSpaceSymbolOffset))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -787,8 +791,7 @@ public class SoftWrapApplianceManager implements SoftWrapFoldingListener, Docume
|
||||
public int indentInColumns;
|
||||
public int indentInPixels;
|
||||
public int endLineOffset;
|
||||
|
||||
private int myNonWhiteSpaceSymbolOffset;
|
||||
public int nonWhiteSpaceSymbolOffset;
|
||||
|
||||
public void update(int logicalLine, int spaceWidth, Editor editor) {
|
||||
Document document = myEditor.getDocument();
|
||||
@@ -803,7 +806,7 @@ public class SoftWrapApplianceManager implements SoftWrapFoldingListener, Docume
|
||||
CharSequence text = document.getCharsSequence();
|
||||
indentInColumns = 0;
|
||||
indentInPixels = 0;
|
||||
myNonWhiteSpaceSymbolOffset = -1;
|
||||
nonWhiteSpaceSymbolOffset = -1;
|
||||
|
||||
for (int i = startLineOffset; i < endLineOffset; i++) {
|
||||
char c = text.charAt(i);
|
||||
@@ -814,7 +817,7 @@ public class SoftWrapApplianceManager implements SoftWrapFoldingListener, Docume
|
||||
indentInColumns += calculateWidthInColumns(c, x - indentInPixels, spaceWidth);
|
||||
indentInPixels = x;
|
||||
break;
|
||||
default: myNonWhiteSpaceSymbolOffset = i; return;
|
||||
default: nonWhiteSpaceSymbolOffset = i; return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -828,7 +831,7 @@ public class SoftWrapApplianceManager implements SoftWrapFoldingListener, Docume
|
||||
* @param softWrapOffset offset of the soft wrap that occurred on document line which data is stored at the current object
|
||||
*/
|
||||
public void update(int softWrapOffset) {
|
||||
if (myNonWhiteSpaceSymbolOffset >= 0 && softWrapOffset > myNonWhiteSpaceSymbolOffset) {
|
||||
if (nonWhiteSpaceSymbolOffset >= 0 && softWrapOffset > nonWhiteSpaceSymbolOffset) {
|
||||
return;
|
||||
}
|
||||
indentInColumns = 0;
|
||||
|
||||
+16
@@ -17,6 +17,7 @@ package com.intellij.openapi.editor.impl.softwrap.mapping;
|
||||
|
||||
import com.intellij.codeInsight.folding.CodeFoldingManager;
|
||||
import com.intellij.openapi.editor.*;
|
||||
import com.intellij.openapi.editor.ex.EditorEx;
|
||||
import com.intellij.openapi.editor.ex.SoftWrapModelEx;
|
||||
import com.intellij.openapi.editor.impl.AbstractEditorProcessingOnDocumentModificationTest;
|
||||
import com.intellij.openapi.editor.impl.SoftWrapModelImpl;
|
||||
@@ -793,6 +794,21 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorP
|
||||
assertEquals(new VisualPosition(1, 8), getEditor().offsetToVisualPosition(getEditor().getDocument().getTextLength() - 1));
|
||||
}
|
||||
|
||||
public void testNoWrapAtFirstNonWsSymbolWithCustomIndent() throws IOException {
|
||||
String text =
|
||||
" 1111111111111111111111111111111";
|
||||
init(70, text);
|
||||
getEditor().getSettings().setCustomSoftWrapIndent(0);
|
||||
getEditor().getSettings().setUseCustomSoftWrapIndent(true);
|
||||
int textLength = getEditor().getDocument().getTextLength();
|
||||
//Trigger soft wraps recalculation.
|
||||
assertEquals(new LogicalPosition(0, textLength), myEditor.offsetToLogicalPosition(textLength));
|
||||
|
||||
// Don't expect soft wraps to be registered as there is no point in wrapping at the first non-white space symbol position
|
||||
// in all cases when soft wrap is located at the left screen edge.
|
||||
assertEmpty(getSoftWrapModel().getRegisteredSoftWraps());
|
||||
}
|
||||
|
||||
public void testXmlWithLongCdata() throws IOException {
|
||||
String text =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
|
||||
|
||||
@@ -30,6 +30,6 @@ import com.intellij.psi.xml.XmlTokenType;
|
||||
public class MarkupLineWrapPositionStrategy extends PsiAwareDefaultLineWrapPositionStrategy {
|
||||
|
||||
public MarkupLineWrapPositionStrategy() {
|
||||
super(XmlElementType.XML_TEXT, TokenType.WHITE_SPACE);
|
||||
super(true, XmlElementType.XML_TEXT, TokenType.WHITE_SPACE);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user