From 3a2ec64c13442657c721dcb25a3501d83c8fdc9e Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 7 Mar 2012 16:52:18 +0400 Subject: [PATCH] IDEA-48401 Ctrl+D should place caret on the variable name when copying a line consisting of variable declaration --- .../codeInsight/DuplicateActionTest.groovy | 38 +++++++++ .../actions/NamedElementDuplicateHandler.java | 80 +++++++++++++++++++ .../src/META-INF/LangExtensions.xml | 2 + 3 files changed, 120 insertions(+) create mode 100644 java/java-tests/testSrc/com/intellij/codeInsight/DuplicateActionTest.groovy create mode 100644 platform/lang-impl/src/com/intellij/openapi/editor/actions/NamedElementDuplicateHandler.java diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/DuplicateActionTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/DuplicateActionTest.groovy new file mode 100644 index 000000000000..ad53d129f964 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/codeInsight/DuplicateActionTest.groovy @@ -0,0 +1,38 @@ +package com.intellij.codeInsight; + + +import com.intellij.openapi.actionSystem.IdeActions +import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase +import org.jetbrains.annotations.NonNls + +public class DuplicateActionTest extends LightCodeInsightFixtureTestCase { + public void testOneLine() { + doTest '''xxx +''', "txt", '''xxx +xxx +''' + } + + public void testEmpty() { + doTest '', "txt", '\n' + } + + private void doTest(String before, @NonNls String ext, String after) { + myFixture.configureByText("a." + ext, before); + myFixture.performEditorAction(IdeActions.ACTION_EDITOR_DUPLICATE) + myFixture.checkResult(after); + } + + public void testSelectName() { + doTest ''' +class C { + void foo() {} +} +''', 'java', ''' +class C { + void foo() {} + void foo() {} +} +''' + } +} 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 new file mode 100644 index 000000000000..5f0dce66445a --- /dev/null +++ b/platform/lang-impl/src/com/intellij/openapi/editor/actions/NamedElementDuplicateHandler.java @@ -0,0 +1,80 @@ +/* + * Copyright 2000-2012 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.actions; + +import com.intellij.openapi.actionSystem.DataContext; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.LogicalPosition; +import com.intellij.openapi.editor.VisualPosition; +import com.intellij.openapi.editor.actionSystem.EditorActionHandler; +import com.intellij.openapi.editor.actionSystem.EditorWriteActionHandler; +import com.intellij.openapi.editor.ex.util.EditorUtil; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.*; +import com.intellij.util.text.CharArrayUtil; +import org.jetbrains.annotations.Nullable; + +/** + * @author peter + */ +public class NamedElementDuplicateHandler extends EditorWriteActionHandler { + private final EditorActionHandler myOriginal; + + public NamedElementDuplicateHandler(EditorActionHandler original) { + myOriginal = original; + } + + @Override + public void executeWriteAction(Editor editor, DataContext dataContext) { + Project project = editor.getProject(); + if (project != null && !editor.getSelectionModel().hasSelection()) { + PsiDocumentManager.getInstance(project).commitDocument(editor.getDocument()); + PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); + if (file != null) { + VisualPosition caret = editor.getCaretModel().getVisualPosition(); + Pair lines = EditorUtil.calcCaretLinesRange(editor, caret, caret); + TextRange toDuplicate = new TextRange(editor.logicalPositionToOffset(lines.first), editor.logicalPositionToOffset(lines.second)); + + PsiNamedElement named = findNamedElement(editor, file, toDuplicate); + if (named != null) { + editor.getCaretModel().moveToOffset(named.getTextOffset()); + } + } + } + + myOriginal.execute(editor, dataContext); + } + + @Nullable + private static PsiNamedElement findNamedElement(Editor editor, PsiFile file, TextRange toDuplicate) { + int nonWs = CharArrayUtil.shiftForward(editor.getDocument().getCharsSequence(), toDuplicate.getStartOffset(), "\n\t "); + PsiElement psi = file.findElementAt(nonWs); + PsiNamedElement named = null; + while (psi != null) { + TextRange range = psi.getTextRange(); + if (range == null || psi instanceof PsiFile || !toDuplicate.contains(psi.getTextRange())) { + break; + } + if (psi instanceof PsiNamedElement) { + named = (PsiNamedElement)psi; + } + psi = psi.getParent(); + } + return named; + } +} diff --git a/platform/platform-resources/src/META-INF/LangExtensions.xml b/platform/platform-resources/src/META-INF/LangExtensions.xml index 0ca66b9dc425..e19855dc5a48 100644 --- a/platform/platform-resources/src/META-INF/LangExtensions.xml +++ b/platform/platform-resources/src/META-INF/LangExtensions.xml @@ -566,6 +566,8 @@ implementationClass="com.intellij.codeInsight.editorActions.BackspaceToWordStartHandler"/> + +