From 0db27b80528294112d5e051f2b7af991ab25caab Mon Sep 17 00:00:00 2001 From: Daniil Ovchinnikov Date: Tue, 28 Mar 2017 14:35:31 +0300 Subject: [PATCH] [groovy] inplace rename method with spaces (IDEA-170254) Now ranges for literal method identifiers and literal references don't include quotes. --- .../rename/inplace/InplaceRefactoring.java | 7 +- .../GrReferenceExpressionImpl.java | 9 +- .../groovy/lang/psi/util/GrStringUtil.java | 17 +- .../inplace/GrMethodInplaceRenamer.java | 21 +- .../rename/InplaceRenameTest.groovy | 189 ++++++++++++++++++ 5 files changed, 237 insertions(+), 6 deletions(-) create mode 100644 plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/rename/InplaceRenameTest.groovy diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/InplaceRefactoring.java b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/InplaceRefactoring.java index 2bd7570243c9..23c96049f27c 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/InplaceRefactoring.java +++ b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/InplaceRefactoring.java @@ -486,7 +486,12 @@ public abstract class InplaceRefactoring { @Nullable protected PsiElement getNameIdentifier() { - return myElementToRename instanceof PsiNameIdentifierOwner ? ((PsiNameIdentifierOwner)myElementToRename).getNameIdentifier() : null; + return getNameIdentifier(myElementToRename); + } + + @Nullable + protected PsiElement getNameIdentifier(PsiElement elementToRename) { + return elementToRename instanceof PsiNameIdentifierOwner ? ((PsiNameIdentifierOwner)elementToRename).getNameIdentifier() : null; } public static EditorEx createPreviewComponent(Project project, FileType languageFileType) { diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrReferenceExpressionImpl.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrReferenceExpressionImpl.java index 373a8a09d7a1..9057feb507d1 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrReferenceExpressionImpl.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrReferenceExpressionImpl.java @@ -20,6 +20,7 @@ import com.intellij.lang.ASTNode; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.AtomicNotNullLazyValue; import com.intellij.openapi.util.NotNullLazyValue; +import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.impl.source.resolve.ResolveCache.PolyVariantResolver; @@ -123,9 +124,11 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl null") + public static TextRange getStringContentRange(@Nullable PsiElement element) { + if (element == null) return null; + IElementType elementType = element.getNode().getElementType(); + if (elementType != GroovyTokenTypes.mSTRING_LITERAL && elementType != GroovyTokenTypes.mGSTRING_LITERAL) return null; + + String text = element.getText(); + String startQuote = getStartQuote(text); + String endQuote = getEndQuote(text); + return new TextRange(startQuote.length(), element.getTextLength() - endQuote.length()); + } + public static boolean parseRegexCharacters(@NotNull String chars, @NotNull StringBuilder outChars, diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/rename/inplace/GrMethodInplaceRenamer.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/rename/inplace/GrMethodInplaceRenamer.java index f68ecd1da86a..e1e9f3fdacbe 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/rename/inplace/GrMethodInplaceRenamer.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/rename/inplace/GrMethodInplaceRenamer.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * 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. @@ -17,9 +17,14 @@ package org.jetbrains.plugins.groovy.refactoring.rename.inplace; import com.intellij.lang.Language; import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiNamedElement; import com.intellij.refactoring.rename.inplace.MemberInplaceRenamer; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.groovy.lang.psi.GrNamedElement; +import org.jetbrains.plugins.groovy.lang.psi.util.GrStringUtil; /** * Created by Max Medvedev on 26/03/14 @@ -33,4 +38,18 @@ public class GrMethodInplaceRenamer extends MemberInplaceRenamer { protected boolean isIdentifier(String newName, Language language) { return true; } + + @Nullable + @Override + protected PsiElement getNameIdentifier(PsiElement elementToRename) { + return elementToRename instanceof GrNamedElement ? ((GrNamedElement)elementToRename).getNameIdentifierGroovy() : null; + } + + @NotNull + @Override + protected TextRange getRangeToRename(@NotNull PsiElement element) { + TextRange stringContentRange = GrStringUtil.getStringContentRange(element); + if (stringContentRange != null) return stringContentRange; + return super.getRangeToRename(element); + } } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/rename/InplaceRenameTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/rename/InplaceRenameTest.groovy new file mode 100644 index 000000000000..768f0b9abd17 --- /dev/null +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/rename/InplaceRenameTest.groovy @@ -0,0 +1,189 @@ +/* + * 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. + */ +package org.jetbrains.plugins.groovy.refactoring.rename + +import com.intellij.testFramework.LightProjectDescriptor +import com.intellij.testFramework.fixtures.CodeInsightTestUtil +import groovy.transform.CompileStatic +import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor +import org.jetbrains.plugins.groovy.LightGroovyTestCase +import org.jetbrains.plugins.groovy.refactoring.rename.inplace.GrMethodInplaceRenameHandler + +@CompileStatic +class InplaceRenameTest extends LightGroovyTestCase { + + final LightProjectDescriptor projectDescriptor = GroovyLightProjectDescriptor.GROOVY_LATEST + + private void doTest(String before, String newName, String after) { + fixture.configureByText '_.groovy', before + CodeInsightTestUtil.doInlineRename(new GrMethodInplaceRenameHandler(), newName, fixture) + fixture.checkResult after + } + + void 'test inplace rename method add space'() { + doTest(/\ +def foo() {} + +foo() +/, 'foo bar', /\ +def 'foo bar'() {} + +'foo bar'() +/) + } + + void "test inplace rename method remove space '"() { + doTest(/\ +def 'foo bar'() {} + +'foo bar'() +'''foo bar'''() +"foo bar"() +"""foo bar"""() +/, 'foo', /\ +def foo() {} + +foo() +foo() +foo() +foo() +/) + } + + void "test inplace rename method remove space '''"() { + doTest(/\ +def '''foo bar'''() {} +'foo bar'() +'''foo bar'''() +"foo bar"() +"""foo bar"""() +/, 'foo', /\ +def foo() {} +foo() +foo() +foo() +foo() +/) + } + + void 'test inplace rename method remove space "'() { + doTest(/\ +def "foo bar"() {} + +'foo bar'() +'''foo bar'''() +"foo bar"() +"""foo bar"""() +/, 'foo', /\ +def foo() {} + +foo() +foo() +foo() +foo() +/) + } + + void 'test inplace rename method remove space """'() { + doTest(/\ +def """foo bar"""() {} + +'foo bar'() +'''foo bar'''() +"foo bar"() +"""foo bar"""() +/, 'foo', /\ +def foo() {} + +foo() +foo() +foo() +foo() +/) + } + + void "test inplace rename method '"() { + doTest(/\ +def 'foo bar'() {} + +'foo bar'() +'''foo bar'''() +"foo bar"() +"""foo bar"""() +/, 'foo baz', /\ +def 'foo baz'() {} + +'foo baz'() +'foo baz'() +'foo baz'() +'foo baz'() +/) + } + + void "test inplace rename method '''"() { + doTest(/\ +def '''foo bar'''() {} + +'foo bar'() +'''foo bar'''() +"foo bar"() +"""foo bar"""() +/, 'foo baz', /\ +def 'foo baz'() {} + +'foo baz'() +'foo baz'() +'foo baz'() +'foo baz'() +/) + } + + void 'test inplace rename method "'() { + doTest(/\ +def "foo bar"() {} + +'foo bar'() +'''foo bar'''() +"foo bar"() +"""foo bar"""() +/, 'foo baz', /\ +def 'foo baz'() {} + +'foo baz'() +'foo baz'() +'foo baz'() +'foo baz'() +/) + } + + void 'test inplace rename method """'() { + doTest(/\ +def """foo bar"""() {} + +'foo bar'() +'''foo bar'''() +"foo bar"() +"""foo bar"""() +/, 'foo baz', /\ +def 'foo baz'() {} + +'foo baz'() +'foo baz'() +'foo baz'() +'foo baz'() +/) + } +}