diff --git a/java/java-impl/src/com/intellij/refactoring/actions/ChangeSignatureAction.java b/java/java-impl/src/com/intellij/refactoring/actions/ChangeSignatureAction.java index 8f850bc263e8..1da3be897e59 100644 --- a/java/java-impl/src/com/intellij/refactoring/actions/ChangeSignatureAction.java +++ b/java/java-impl/src/com/intellij/refactoring/actions/ChangeSignatureAction.java @@ -1,28 +1,27 @@ - /* - * Copyright 2000-2009 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-2009 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.refactoring.actions; import com.intellij.openapi.actionSystem.DataContext; +import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; -import com.intellij.psi.PsiClass; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiMethod; +import com.intellij.psi.*; import com.intellij.refactoring.RefactoringActionHandler; import com.intellij.refactoring.changeSignature.ChangeSignatureHandler; +import com.intellij.refactoring.changeSignature.ChangeSignatureTargetUtil; public class ChangeSignatureAction extends BaseRefactoringAction { public boolean isAvailableInEditorOnly() { @@ -34,10 +33,15 @@ public class ChangeSignatureAction extends BaseRefactoringAction { } protected boolean isAvailableOnElementInEditor(final PsiElement element, final Editor editor) { + final Document document = editor.getDocument(); + final PsiFile file = PsiDocumentManager.getInstance(element.getProject()).getPsiFile(document); + if (file != null && ChangeSignatureTargetUtil.findTargetMember(file, editor) != null) { + return true; + } return element instanceof PsiMethod || element instanceof PsiClass; } public RefactoringActionHandler getHandler(DataContext dataContext) { return new ChangeSignatureHandler(); } -} \ No newline at end of file +} diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureHandler.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureHandler.java index ad997fca7ce4..5c099c16bb49 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureHandler.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureHandler.java @@ -37,7 +37,10 @@ public class ChangeSignatureHandler implements RefactoringActionHandler { public void invoke(@NotNull Project project, Editor editor, PsiFile file, DataContext dataContext) { editor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE); - PsiElement element = LangDataKeys.PSI_ELEMENT.getData(dataContext); + PsiElement element = ChangeSignatureTargetUtil.findTargetMember(file, editor); + if (element == null) { + element = LangDataKeys.PSI_ELEMENT.getData(dataContext); + } invokeOnElement(project, editor, element); } @@ -93,4 +96,4 @@ public class ChangeSignatureHandler implements RefactoringActionHandler { ChangeClassSignatureDialog dialog = new ChangeClassSignatureDialog(aClass); dialog.show(); } -} \ No newline at end of file +} diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureTargetUtil.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureTargetUtil.java new file mode 100644 index 000000000000..5c947f4c48bb --- /dev/null +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureTargetUtil.java @@ -0,0 +1,77 @@ +/* + * Copyright 2000-2009 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. + */ + +/* + * User: anna + * Date: 24-Nov-2009 + */ +package com.intellij.refactoring.changeSignature; + +import com.intellij.openapi.editor.Editor; +import com.intellij.psi.*; +import com.intellij.psi.util.PsiTreeUtil; +import org.jetbrains.annotations.Nullable; + +public class ChangeSignatureTargetUtil { + private ChangeSignatureTargetUtil() {} + + @Nullable + public static PsiMember findTargetMember(PsiFile file, Editor editor) { + PsiElement element = file.findElementAt(editor.getCaretModel().getOffset()); + if (PsiTreeUtil.getParentOfType(element, PsiParameterList.class) != null) { + return PsiTreeUtil.getParentOfType(element, PsiMethod.class); + } + + final PsiMethodCallExpression expression = PsiTreeUtil.getParentOfType(element, PsiMethodCallExpression.class); + if (expression != null) { + assert element != null; + final PsiExpression qualifierExpression = expression.getMethodExpression().getQualifierExpression(); + if (PsiTreeUtil.isAncestor(qualifierExpression, element, false)) { + final PsiExpressionList expressionList = PsiTreeUtil.getParentOfType(qualifierExpression, PsiExpressionList.class); + if (expressionList != null) { + final PsiElement parent = expressionList.getParent(); + if (parent instanceof PsiMethodCallExpression) { + return ((PsiMethodCallExpression)parent).resolveMethod(); + } + } + } else { + return expression.resolveMethod(); + } + } + + final PsiTypeParameterList typeParameterList = PsiTreeUtil.getParentOfType(element, PsiTypeParameterList.class); + if (typeParameterList != null) { + return PsiTreeUtil.getParentOfType(typeParameterList, PsiMember.class); + } + + final PsiReferenceParameterList referenceParameterList = PsiTreeUtil.getParentOfType(element, PsiReferenceParameterList.class); + if (referenceParameterList != null) { + final PsiJavaCodeReferenceElement referenceElement = + PsiTreeUtil.getParentOfType(referenceParameterList, PsiJavaCodeReferenceElement.class); + if (referenceElement != null) { + final PsiElement resolved = referenceElement.resolve(); + if (resolved instanceof PsiClass) { + return (PsiMember)resolved; + } + else if (resolved instanceof PsiMethod) { + return (PsiMember)resolved; + } + } + } + return null; + } + +} diff --git a/java/java-tests/testData/refactoring/changeSignatureTarget/inClassTypeParameters.java b/java/java-tests/testData/refactoring/changeSignatureTarget/inClassTypeParameters.java new file mode 100644 index 000000000000..cd816bf9da2a --- /dev/null +++ b/java/java-tests/testData/refactoring/changeSignatureTarget/inClassTypeParameters.java @@ -0,0 +1,3 @@ +import java.util.*; +class A1<T> { +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/changeSignatureTarget/inMethodArguments.java b/java/java-tests/testData/refactoring/changeSignatureTarget/inMethodArguments.java new file mode 100644 index 000000000000..7b56e5dbd51e --- /dev/null +++ b/java/java-tests/testData/refactoring/changeSignatureTarget/inMethodArguments.java @@ -0,0 +1,12 @@ +import java.util.*; +class B{ + + public static void main(String[] args) { + B b = null; + b.bar(b.ing>foo("", "")); + } + + String foo(T t, String s){return null;} + String bar(String s) {return null;} + +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/changeSignatureTarget/inMethodParameters.java b/java/java-tests/testData/refactoring/changeSignatureTarget/inMethodParameters.java new file mode 100644 index 000000000000..a66333b6f871 --- /dev/null +++ b/java/java-tests/testData/refactoring/changeSignatureTarget/inMethodParameters.java @@ -0,0 +1,4 @@ +import java.util.*; +class B { + String foo(T t, String s){return null;} +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/changeSignatureTarget/inTypeArguments.java b/java/java-tests/testData/refactoring/changeSignatureTarget/inTypeArguments.java new file mode 100644 index 000000000000..d0fb0a13392e --- /dev/null +++ b/java/java-tests/testData/refactoring/changeSignatureTarget/inTypeArguments.java @@ -0,0 +1,23 @@ +import java.util.*; +class A1 { + public static void main(String[] args) { + + Callable callable = new Callable() { + public Object call() throws Exception { + return new A1ing>().toString(); + + } + }; + B b = null; + b.bar(b.foo("", "")); + } + + + String foo(T t, String s) { + return null; + } + + String bar(String s) { + return null; + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignatureTargetTest.java b/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignatureTargetTest.java new file mode 100644 index 000000000000..175bed687acf --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignatureTargetTest.java @@ -0,0 +1,50 @@ +/* + * User: anna + * Date: 25-Nov-2009 + */ +package com.intellij.refactoring; + +import com.intellij.JavaTestUtil; +import com.intellij.openapi.projectRoots.Sdk; +import com.intellij.openapi.projectRoots.impl.JavaSdkImpl; +import com.intellij.psi.PsiMember; +import com.intellij.refactoring.changeSignature.ChangeSignatureTargetUtil; +import com.intellij.testFramework.LightCodeInsightTestCase; +import org.jetbrains.annotations.NonNls; + +public class ChangeSignatureTargetTest extends LightCodeInsightTestCase { + @Override + protected String getTestDataPath() { + return JavaTestUtil.getJavaTestDataPath(); + } + + public void testInMethodParameters() throws Exception { + doTest("foo"); + } + + public void testInMethodArguments() throws Exception { + doTest("foo"); + } + + public void testInClassTypeParameters() throws Exception { + doTest("A1"); + } + + public void testInTypeArguments() throws Exception { + doTest("A1"); + } + + @Override + protected Sdk getProjectJDK() { + return JavaSdkImpl.getMockJdk15("java 1.5"); + } + + private void doTest(String expectedMemberName) throws Exception { + String basePath = "/refactoring/changeSignatureTarget/" + getTestName(false); + @NonNls final String filePath = basePath + ".java"; + configureByFile(filePath); + final PsiMember member = ChangeSignatureTargetUtil.findTargetMember(getFile(), getEditor()); + assertNotNull(member); + assertEquals(expectedMemberName, member.getName()); + } +} \ No newline at end of file