IDEA-180797 End and Shift-End work incorrectly in case of soft wraps

This commit is contained in:
Dmitry Batrak
2017-11-09 19:41:03 +03:00
parent a94b169bdd
commit af71c74d70
2 changed files with 26 additions and 123 deletions
@@ -1,18 +1,4 @@
/*
* Copyright 2000-2017 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.
*/
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.openapi.editor.actions;
@@ -322,7 +308,7 @@ public class EditorActionUtil {
if (currentVisCaret.line > caretLogLineStartVis.line) {
// Caret is located not at the first visual line of soft-wrapped logical line.
if (editorSettings.isSmartHome()) {
moveCaretToStartOfSoftWrappedLine(editor, currentVisCaret, currentVisCaret.line - caretLogLineStartVis.line);
moveCaretToStartOfSoftWrappedLine(editor, currentVisCaret);
}
else {
caretModel.moveToVisualPosition(new VisualPosition(currentVisCaret.line, 0));
@@ -361,7 +347,7 @@ public class EditorActionUtil {
VisualPosition logLineEndVis = editor.logicalToVisualPosition(logLineEndLog);
int softWrapCount = EditorUtil.getSoftWrapCountAfterLineStart(editor, logLineEndLog);
if (softWrapCount > 0) {
moveCaretToStartOfSoftWrappedLine(editor, logLineEndVis, softWrapCount);
moveCaretToStartOfSoftWrappedLine(editor, logLineEndVis);
}
else {
int line = logLineEndVis.line;
@@ -380,7 +366,7 @@ public class EditorActionUtil {
EditorModificationUtil.scrollToCaret(editor);
}
private static void moveCaretToStartOfSoftWrappedLine(@NotNull Editor editor, VisualPosition currentVisual, int softWrappedLines) {
private static void moveCaretToStartOfSoftWrappedLine(@NotNull Editor editor, VisualPosition currentVisual) {
CaretModel caretModel = editor.getCaretModel();
LogicalPosition startLineLogical = editor.visualToLogicalPosition(new VisualPosition(currentVisual.line, 0));
int startLineOffset = editor.logicalPositionToOffset(startLineLogical);
@@ -405,19 +391,9 @@ public class EditorActionUtil {
}
else {
// We assume that caret is already located at zero visual column of soft-wrapped line if control flow reaches this place.
int newVisualCaretLine = currentVisual.line - 1;
int newVisualCaretColumn = -1;
if (softWrappedLines > 1) {
int offset = editor.logicalPositionToOffset(editor.visualToLogicalPosition(new VisualPosition(newVisualCaretLine, 0)));
SoftWrap prevLineSoftWrap = softWrapModel.getSoftWrap(offset);
if (prevLineSoftWrap != null) {
newVisualCaretColumn = prevLineSoftWrap.getIndentInColumns();
}
}
if (newVisualCaretColumn < 0) {
newVisualCaretColumn = findFirstNonSpaceColumnOnTheLine(editor, newVisualCaretLine);
}
caretModel.moveToVisualPosition(new VisualPosition(newVisualCaretLine, newVisualCaretColumn));
int lineStartOffset = EditorUtil.getNotFoldedLineStartOffset(editor, startLineOffset);
int visualLine = editor.offsetToVisualPosition(lineStartOffset).line;
caretModel.moveToVisualPosition(new VisualPosition(visualLine, findFirstNonSpaceColumnOnTheLine(editor, visualLine)));
}
}
@@ -575,26 +551,13 @@ public class EditorActionUtil {
= new VisualPosition(currentVisualCaret.line, EditorUtil.getLastVisualLineColumnNumber(editor, currentVisualCaret.line), true);
// There is a possible case that the caret is already located at the visual end of line and the line is soft wrapped.
// We want to move the caret to the end of the next visual line then.
// We want to move the caret to the end of the logical line then.
if (currentVisualCaret.equals(visualEndOfLineWithCaret)) {
LogicalPosition logical = editor.visualToLogicalPosition(visualEndOfLineWithCaret);
int offset = editor.logicalPositionToOffset(logical);
if (offset < editor.getDocument().getTextLength()) {
SoftWrap softWrap = softWrapModel.getSoftWrap(offset);
if (softWrap == null) {
// Same offset may correspond to positions on different visual lines in case of soft wraps presence
// (all soft-wrap introduced virtual text is mapped to the same offset as the first document symbol after soft wrap).
// Hence, we check for soft wraps presence at two offsets.
softWrap = softWrapModel.getSoftWrap(offset + 1);
}
int line = currentVisualCaret.line;
int column = currentVisualCaret.column;
if (softWrap != null) {
line++;
column = EditorUtil.getLastVisualLineColumnNumber(editor, line);
}
visualEndOfLineWithCaret = new VisualPosition(line, column, true);
int logicalLineEndOffset = EditorUtil.getNotFoldedLineEndOffset(editor, offset);
visualEndOfLineWithCaret = editor.offsetToVisualPosition(logicalLineEndOffset, true, false);
}
}
@@ -1,18 +1,4 @@
/*
* 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.
*/
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.openapi.editor.impl.softwrap.mapping;
import com.intellij.codeInsight.folding.CodeFoldingManager;
@@ -478,36 +464,20 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorT
init(30, text);
myEditor.getCaretModel().moveToOffset(text.indexOf("}") - 1);
List<? extends SoftWrap> softWraps = new ArrayList<>(getSoftWrapModel().getRegisteredSoftWraps());
assertTrue(!softWraps.isEmpty());
checkSoftWraps(41, 66, 89, 116);
CaretModel caretModel = myEditor.getCaretModel();
int expectedVisualLine = caretModel.getVisualPosition().line;
while (!softWraps.isEmpty()) {
SoftWrap softWrap = softWraps.get(softWraps.size() - 1);
int caretOffsetBefore = caretModel.getOffset();
home();
// Expecting the caret to be moved at the nearest soft wrap start offset.
int caretOffset = caretModel.getOffset();
assertTrue(caretOffset < caretOffsetBefore);
assertEquals(softWrap.getStart(), caretOffset);
assertEquals(new VisualPosition(expectedVisualLine, softWrap.getIndentInColumns()), caretModel.getVisualPosition());
// Expected that caret is moved to visual line start when it's located on soft wrap start offset at the moment.
home();
assertEquals(softWrap.getStart(), caretModel.getOffset());
assertEquals(new VisualPosition(expectedVisualLine, 0), caretModel.getVisualPosition());
softWraps.remove(softWraps.size() - 1);
expectedVisualLine--;
}
home();
assertEquals(116, caretModel.getOffset());
assertEquals(new VisualPosition(5, 1), caretModel.getVisualPosition());
home();
assertEquals(116, caretModel.getOffset());
assertEquals(new VisualPosition(5, 0), caretModel.getVisualPosition());
// Expecting caret to be located on the first non-white space symbol of non-soft wrapped line.
home();
assertEquals(text.indexOf("public"), caretModel.getOffset());
assertEquals(new VisualPosition(expectedVisualLine, text.indexOf("public") - text.indexOf("{\n") - 2), caretModel.getVisualPosition());
assertEquals(new VisualPosition(1, 4), caretModel.getVisualPosition());
}
public void testEndProcessing() throws IOException {
@@ -519,57 +489,27 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorT
init(30, text);
myEditor.getCaretModel().moveToOffset(text.indexOf("\n") + 1);
List<? extends SoftWrap> softWraps = new ArrayList<>(getSoftWrapModel().getRegisteredSoftWraps());
assertTrue(!softWraps.isEmpty());
checkSoftWraps(41, 66, 89, 116);
CaretModel caretModel = myEditor.getCaretModel();
int expectedVisualLine = caretModel.getVisualPosition().line;
while (!softWraps.isEmpty()) {
SoftWrap softWrap = softWraps.get(0);
int caretOffsetBefore = caretModel.getOffset();
end();
// Expecting the caret to be moved at the last non-white space symbol on the current visual line.
int caretOffset = caretModel.getOffset();
assertTrue(caretOffset > caretOffsetBefore);
assertFalse(caretOffset > softWrap.getStart());
if (caretOffset < softWrap.getStart()) {
// There is a possible case that there are white space symbols between caret position applied on 'end' processing and
// soft wrap. Let's check that and emulate one more 'end' typing in order to move caret right before soft wrap.
for (int i = caretOffset; i < softWrap.getStart(); i++) {
char c = text.charAt(i);
assertTrue(c == ' ' || c == '\t');
}
caretOffsetBefore = caretOffset;
end();
caretOffset = caretModel.getOffset();
assertTrue(caretOffset > caretOffsetBefore);
}
assertEquals(softWrap.getStart(), caretOffset);
assertEquals(
new VisualPosition(expectedVisualLine, myEditor.offsetToVisualPosition(softWrap.getStart() - 1).column + 1),
caretModel.getVisualPosition()
);
softWraps.remove(0);
expectedVisualLine++;
}
end();
assertEquals(40, caretModel.getOffset());
assertEquals(new VisualPosition(1, 27), caretModel.getVisualPosition());
end();
assertEquals(41, caretModel.getOffset());
assertEquals(new VisualPosition(1, 28), caretModel.getVisualPosition());
// Check that caret is placed on a last non-white space symbol on current logical line.
end();
int lastNonWhiteSpaceSymbolOffset = text.indexOf("\";") + 2;
assertEquals(lastNonWhiteSpaceSymbolOffset, caretModel.getOffset());
assertEquals(myEditor.offsetToVisualPosition(lastNonWhiteSpaceSymbolOffset), caretModel.getVisualPosition());
assertEquals(expectedVisualLine, caretModel.getVisualPosition().line);
// Check that caret is place to the very end of the logical line.
end();
int lastSymbolOffset = myEditor.getDocument().getLineEndOffset(caretModel.getLogicalPosition().line);
assertEquals(lastSymbolOffset, caretModel.getOffset());
assertEquals(myEditor.offsetToVisualPosition(lastSymbolOffset), caretModel.getVisualPosition());
assertEquals(expectedVisualLine, caretModel.getVisualPosition().line);
}
public void testSoftWrapToHardWrapConversion() {