From 3e97203f8509e607414a0e33dec18f1b6ea9cc35 Mon Sep 17 00:00:00 2001 From: "Pavel V. Talanov" Date: Mon, 11 Nov 2013 17:27:46 +0400 Subject: [PATCH] Check that target functions can be modified in JetChangeSignature --- .../changeSignature/JetChangeSignature.kt | 35 +++++++++++++++- .../UnmodifiableFromBuiltinsBefore.kt | 3 ++ .../UnmodifiableFromLibraryBefore.kt | 3 ++ .../JetChangeSignatureTest.java | 41 ++++++++++++++++++- 4 files changed, 78 insertions(+), 4 deletions(-) create mode 100644 idea/testData/refactoring/changeSignature/UnmodifiableFromBuiltinsBefore.kt create mode 100644 idea/testData/refactoring/changeSignature/UnmodifiableFromLibraryBefore.kt diff --git a/idea/src/org/jetbrains/jet/plugin/refactoring/changeSignature/JetChangeSignature.kt b/idea/src/org/jetbrains/jet/plugin/refactoring/changeSignature/JetChangeSignature.kt index 06ae54ccf32..b3670093b51 100644 --- a/idea/src/org/jetbrains/jet/plugin/refactoring/changeSignature/JetChangeSignature.kt +++ b/idea/src/org/jetbrains/jet/plugin/refactoring/changeSignature/JetChangeSignature.kt @@ -33,6 +33,9 @@ import org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor.Kind.* import org.jetbrains.jet.lang.resolve.BindingContextUtils.* import org.jetbrains.annotations.TestOnly import org.jetbrains.jet.plugin.codeInsight.DescriptorToDeclarationUtil +import org.jetbrains.jet.plugin.quickfix.QuickFixUtil +import com.intellij.CommonBundle +import com.intellij.refactoring.RefactoringBundle public trait JetChangeSignatureConfiguration { fun configure(changeSignatureData: JetChangeSignatureData, bindingContext: BindingContext) @@ -125,8 +128,14 @@ public class JetChangeSignature(val project: Project, return } - if (configuration.performSilently(dialog.getMethodDescriptor().getAffectedFunctions()) - || ApplicationManager.getApplication()!!.isUnitTestMode()) { + val affectedFunctions = dialog.getMethodDescriptor().getAffectedFunctions() + + if (affectedFunctions.any { !checkModifiable(it) }) { + return + } + + if (configuration.performSilently(affectedFunctions) + || ApplicationManager.getApplication()!!.isUnitTestMode()) { performRefactoringSilently(dialog) } else { @@ -142,11 +151,33 @@ public class JetChangeSignature(val project: Project, return null } + if (!checkModifiable(functionDeclaration)) { + return null + } + val changeSignatureData = JetChangeSignatureData(baseDescriptor, functionDeclaration, bindingContext, descriptorsForSignatureChange) configuration.configure(changeSignatureData, bindingContext) return JetChangeSignatureDialog(project, changeSignatureData, defaultValueContext, commandName) } + private fun checkModifiable(function: PsiElement): Boolean { + if (QuickFixUtil.canModifyElement(function)) { + return true + } + + val unmodifiableFile = function.getContainingFile()?.getVirtualFile()?.getPresentableUrl() + if (unmodifiableFile != null) { + val message = RefactoringBundle.message("refactoring.cannot.be.performed") + "\n" + + IdeBundle.message("error.message.cannot.modify.file.0", unmodifiableFile) + Messages.showErrorDialog(project, message, CommonBundle.getErrorTitle()!!) + } + else { + LOG.error("Could not find file for Psi element: " + function.getText()) + } + + return false + } + private fun performRefactoringSilently(dialog: JetChangeSignatureDialog) { ApplicationManager.getApplication()!!.runWriteAction { dialog.createRefactoringProcessor().run() diff --git a/idea/testData/refactoring/changeSignature/UnmodifiableFromBuiltinsBefore.kt b/idea/testData/refactoring/changeSignature/UnmodifiableFromBuiltinsBefore.kt new file mode 100644 index 00000000000..5070e7a63ea --- /dev/null +++ b/idea/testData/refactoring/changeSignature/UnmodifiableFromBuiltinsBefore.kt @@ -0,0 +1,3 @@ +fun f(a: Number) { + a.toFloat() +} \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignature/UnmodifiableFromLibraryBefore.kt b/idea/testData/refactoring/changeSignature/UnmodifiableFromLibraryBefore.kt new file mode 100644 index 00000000000..5641895e2cc --- /dev/null +++ b/idea/testData/refactoring/changeSignature/UnmodifiableFromLibraryBefore.kt @@ -0,0 +1,3 @@ +fun f(a: Any) { + a.equals("a") +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/jet/plugin/refactoring/changeSignature/JetChangeSignatureTest.java b/idea/tests/org/jetbrains/jet/plugin/refactoring/changeSignature/JetChangeSignatureTest.java index 84677708e09..1f18762b59b 100644 --- a/idea/tests/org/jetbrains/jet/plugin/refactoring/changeSignature/JetChangeSignatureTest.java +++ b/idea/tests/org/jetbrains/jet/plugin/refactoring/changeSignature/JetChangeSignatureTest.java @@ -16,6 +16,7 @@ package org.jetbrains.jet.plugin.refactoring.changeSignature; +import com.intellij.codeInsight.CodeInsightTestCase; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Disposer; @@ -24,7 +25,6 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.refactoring.BaseRefactoringProcessor; import com.intellij.refactoring.util.CommonRefactoringUtil; -import com.intellij.testFramework.LightCodeInsightTestCase; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; import org.jetbrains.jet.lang.descriptors.Visibilities; @@ -38,12 +38,13 @@ import org.jetbrains.jet.plugin.refactoring.JetRefactoringBundle; import java.io.File; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.List; import static org.jetbrains.jet.plugin.refactoring.changeSignature.ChangeSignaturePackage.getChangeSignatureDialog; -public class JetChangeSignatureTest extends LightCodeInsightTestCase { +public class JetChangeSignatureTest extends CodeInsightTestCase { public void testBadSelection() throws Exception { configureByFile(getTestName(false) + "Before.kt"); Editor editor = getEditor(); @@ -185,6 +186,42 @@ public class JetChangeSignatureTest extends LightCodeInsightTestCase { fail("Exception expected"); } + public void testUnmodifiableFromLibrary() throws Exception { + doTestUnmodifiableCheck(); + } + + + public void testUnmodifiableFromBuiltins() throws Exception { + doTestUnmodifiableCheck(); + } + + private void doTestUnmodifiableCheck() throws Exception { + try { + JetChangeInfo changeInfo = getChangeInfo(); + PsiFile containingFile = changeInfo.getMethod().getContainingFile(); + JetChangeSignatureConfiguration empty = new JetChangeSignatureConfiguration() { + @Override + public void configure( + JetChangeSignatureData data, BindingContext bindingContext + ) { + } + + @Override + public boolean performSilently(Collection elements) { + return true; + } + }; + BindingContext context = AnalyzerFacadeWithCache.analyzeFileWithCache((JetFile) containingFile).getBindingContext(); + ChangeSignaturePackage + .runChangeSignature(getProject(), changeInfo.getOldDescriptor(), empty, context, changeInfo.getMethod(), "test"); + } + catch (RuntimeException e) { + assertTrue(e.getMessage().startsWith("Refactoring cannot be")); + return; + } + fail("Exception expected"); + } + public void testInnerFunctionsConflict() throws Exception { JetChangeInfo changeInfo = getChangeInfo(); changeInfo.setNewName("inner2");