diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/moveLeftRight/MoveElementLeftRightActionHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/moveLeftRight/MoveElementLeftRightActionHandler.java index d41efaed0e18..06fac6cef0cc 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/moveLeftRight/MoveElementLeftRightActionHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/moveLeftRight/MoveElementLeftRightActionHandler.java @@ -33,7 +33,7 @@ public final class MoveElementLeftRightActionHandler extends EditorWriteActionHa } @Override - protected boolean reverseCaretOrder() { + public boolean reverseCaretOrder() { return !myIsLeft; } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/moveUpDown/BaseMoveHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/moveUpDown/BaseMoveHandler.java index 6695e52228ab..ba9cbd0d118d 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/moveUpDown/BaseMoveHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/moveUpDown/BaseMoveHandler.java @@ -27,7 +27,7 @@ public abstract class BaseMoveHandler extends EditorWriteActionHandler.ForEachCa } @Override - protected boolean reverseCaretOrder() { + public boolean reverseCaretOrder() { return isDown; } diff --git a/platform/lang-impl/src/com/intellij/openapi/editor/actions/NamedElementDuplicateHandler.java b/platform/lang-impl/src/com/intellij/openapi/editor/actions/NamedElementDuplicateHandler.java index a7b4848a2aa2..f32bfbbedfe9 100644 --- a/platform/lang-impl/src/com/intellij/openapi/editor/actions/NamedElementDuplicateHandler.java +++ b/platform/lang-impl/src/com/intellij/openapi/editor/actions/NamedElementDuplicateHandler.java @@ -1,4 +1,4 @@ -// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.openapi.editor.actions; import com.intellij.openapi.actionSystem.DataContext; @@ -31,6 +31,14 @@ public final class NamedElementDuplicateHandler extends EditorWriteActionHandler return myOriginal.isEnabled(editor, caret, dataContext); } + @Override + public boolean reverseCaretOrder() { + if (myOriginal instanceof EditorWriteActionHandler handler) { + return handler.reverseCaretOrder(); + } + return false; + } + @Override public void executeWriteAction(@NotNull Editor editor, @NotNull Caret caret, DataContext dataContext) { Project project = editor.getProject(); @@ -63,8 +71,8 @@ public final class NamedElementDuplicateHandler extends EditorWriteActionHandler if (range == null || psi instanceof PsiFile || !toDuplicate.contains(psi.getTextRange())) { break; } - if (psi instanceof PsiNameIdentifierOwner) { - named = ((PsiNameIdentifierOwner)psi).getNameIdentifier(); + if (psi instanceof PsiNameIdentifierOwner owner) { + named = owner.getNameIdentifier(); } psi = psi.getParent(); } diff --git a/platform/platform-api/api-dump-unreviewed.txt b/platform/platform-api/api-dump-unreviewed.txt index 7d8ebca1a0e0..05765f8f0f70 100644 --- a/platform/platform-api/api-dump-unreviewed.txt +++ b/platform/platform-api/api-dump-unreviewed.txt @@ -2046,7 +2046,7 @@ a:com.intellij.openapi.editor.actionSystem.EditorActionHandler - isEnabled(com.intellij.openapi.editor.Editor,com.intellij.openapi.actionSystem.DataContext):Z - f:isEnabled(com.intellij.openapi.editor.Editor,com.intellij.openapi.editor.Caret,com.intellij.openapi.actionSystem.DataContext):Z - p:isEnabledForCaret(com.intellij.openapi.editor.Editor,com.intellij.openapi.editor.Caret,com.intellij.openapi.actionSystem.DataContext):Z -- p:reverseCaretOrder():Z +- reverseCaretOrder():Z - runForAllCarets():Z a:com.intellij.openapi.editor.actionSystem.EditorActionHandler$ForEachCaret - com.intellij.openapi.editor.actionSystem.EditorActionHandler diff --git a/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/DynamicEditorActionHandler.java b/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/DynamicEditorActionHandler.java index 79111969b7b0..f5b7c1f79f4f 100644 --- a/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/DynamicEditorActionHandler.java +++ b/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/DynamicEditorActionHandler.java @@ -42,7 +42,7 @@ final class DynamicEditorActionHandler extends EditorActionHandler { } @Override - protected boolean reverseCaretOrder() { + public boolean reverseCaretOrder() { return getHandler().reverseCaretOrder(); } diff --git a/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/EditorActionHandler.java b/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/EditorActionHandler.java index a7c99460d1e7..86406c46416f 100644 --- a/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/EditorActionHandler.java +++ b/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/EditorActionHandler.java @@ -179,7 +179,7 @@ public abstract class EditorActionHandler { return myRunForEachCaret; } - protected boolean reverseCaretOrder() { + public boolean reverseCaretOrder() { return false; } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/DuplicateAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/DuplicateAction.java index 9dc9fdb33850..69f3136cb488 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/DuplicateAction.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/DuplicateAction.java @@ -1,5 +1,4 @@ -// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. - +// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.openapi.editor.actions; import com.intellij.openapi.actionSystem.DataContext; @@ -26,6 +25,11 @@ public final class DuplicateAction extends EditorAction { public boolean isEnabledForCaret(@NotNull Editor editor, @NotNull Caret caret, DataContext dataContext) { return !editor.isOneLineMode() || editor.getSelectionModel().hasSelection(); } + + @Override + public boolean reverseCaretOrder() { + return true; + } } public static void duplicateLineOrSelectedBlockAtCaret(Editor editor) { diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/DuplicateLinesAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/DuplicateLinesAction.java index 332fd7edbe1b..a40cd3121d27 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/DuplicateLinesAction.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/DuplicateLinesAction.java @@ -1,4 +1,4 @@ -// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.openapi.editor.actions; import com.intellij.openapi.actionSystem.DataContext; @@ -36,5 +36,10 @@ public final class DuplicateLinesAction extends EditorAction { DuplicateAction.duplicateLinesRange(editor, caretPos, caretPos); } } + + @Override + public boolean reverseCaretOrder() { + return true; + } } } diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/EditorActionTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/EditorActionTest.java index 9957426b060c..23cffe89c455 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/EditorActionTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/EditorActionTest.java @@ -1,6 +1,4 @@ -/* - * 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. - */ +// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.openapi.editor.actions; import com.intellij.openapi.actionSystem.ActionManager; @@ -283,6 +281,30 @@ public class EditorActionTest extends AbstractEditorTest { executeAction(IdeActions.ACTION_EDITOR_DUPLICATE_LINES); checkResultByText("ab\ncd\nab\ncd"); } + + public void testDuplicateLinesMultiCaretLineStart() { + String before = """ + one + two + three + """; + String after = """ + one + one + two + two + three + three + """; + + initText(before); + executeAction(IdeActions.ACTION_EDITOR_DUPLICATE_LINES); + checkResultByText(after); + + initText(before); + ctrlD(); + checkResultByText(after); + } public void testDuplicateLineWithGuardedBlock() { initText("a\n#");