From 9de81a8590dfd67f1afeec51f05eb9da4612848c Mon Sep 17 00:00:00 2001 From: Mikhail Pyltsin Date: Wed, 5 Nov 2025 11:39:38 +0100 Subject: [PATCH] [java-refactoring] IDEA-380516 JavaSuggestedRefactoringAvailability.extractAnnotationsWithResolve: IllegalArgumentException: Failed requirement GitOrigin-RevId: 76f78b44e8595f57beca1306ac2868e96630cfb8 --- .../JavaSuggestedRefactoringAvailability.kt | 15 +++++-- .../suggested/JavaSuggestedRefactoringTest.kt | 43 +++++++++++++++++-- .../suggested/BaseSuggestedRefactoringTest.kt | 2 +- 3 files changed, 51 insertions(+), 9 deletions(-) diff --git a/java/java-impl-refactorings/src/com/intellij/java/refactoring/suggested/JavaSuggestedRefactoringAvailability.kt b/java/java-impl-refactorings/src/com/intellij/java/refactoring/suggested/JavaSuggestedRefactoringAvailability.kt index 8fcad0d533a0..b7ccd5fdc1d5 100644 --- a/java/java-impl-refactorings/src/com/intellij/java/refactoring/suggested/JavaSuggestedRefactoringAvailability.kt +++ b/java/java-impl-refactorings/src/com/intellij/java/refactoring/suggested/JavaSuggestedRefactoringAvailability.kt @@ -18,6 +18,7 @@ class JavaSuggestedRefactoringAvailability(refactoringSupport: SuggestedRefactor SuggestedRefactoringAvailability(refactoringSupport) { private val HAS_OVERRIDES = Key("JavaSuggestedRefactoringAvailability.HAS_OVERRIDES") private val HAS_USAGES = Key("JavaSuggestedRefactoringAvailability.HAS_USAGES") + private val HAS_NOT_MATCHED_PARAMETERS = Key("JavaSuggestedRefactoringAvailability.HAS_NOT_MATCHED_PARAMETERS") // disable refactoring suggestion for method which overrides another method override fun shouldSuppressRefactoringForDeclaration(state: SuggestedRefactoringState): Boolean { @@ -113,9 +114,14 @@ class JavaSuggestedRefactoringAvailability(refactoringSupport: SuggestedRefactor val declaration = anchor as? PsiMethod ?: return state val restoredDeclarationCopy = state.restoredDeclarationCopy() as PsiMethod val psiFile = declaration.containingFile + val oldSignature = extractAnnotationsWithResolve(state.oldSignature, restoredDeclarationCopy, psiFile) + val newSignature = extractAnnotationsWithResolve(state.newSignature, declaration, psiFile) + if(oldSignature == null || newSignature == null) { + return state.withAdditionalData(HAS_NOT_MATCHED_PARAMETERS, true) + } return state - .withOldSignature(extractAnnotationsWithResolve(state.oldSignature, restoredDeclarationCopy, psiFile)) - .withNewSignature(extractAnnotationsWithResolve(state.newSignature, declaration, psiFile)) + .withOldSignature(oldSignature) + .withNewSignature(newSignature) } override fun detectAvailableRefactoring(state: SuggestedRefactoringState): SuggestedRefactoringData? { @@ -123,6 +129,7 @@ class JavaSuggestedRefactoringAvailability(refactoringSupport: SuggestedRefactor val whatToUpdate: String val declaration: PsiElement val anchor = state.anchor + if (updatedState.additionalData[HAS_NOT_MATCHED_PARAMETERS] == true) return null if (anchor is PsiCallExpression) { updatedState = callStateToDeclarationState(updatedState) ?: return null declaration = anchor.resolveMethod() ?: return null @@ -183,9 +190,9 @@ class JavaSuggestedRefactoringAvailability(refactoringSupport: SuggestedRefactor } // Annotations were extracted without use of resolve. We must extract them again using more precise method. - private fun extractAnnotationsWithResolve(signature: Signature, declaration: PsiMethod, psiFile: PsiFile): Signature { + private fun extractAnnotationsWithResolve(signature: Signature, declaration: PsiMethod, psiFile: PsiFile): Signature? { val psiParameters = declaration.parameterList.parameters - require(signature.parameters.size == psiParameters.size) + if(signature.parameters.size != psiParameters.size) return null return Signature.create( signature.name, diff --git a/java/java-tests/testSrc/com/intellij/java/refactoring/suggested/JavaSuggestedRefactoringTest.kt b/java/java-tests/testSrc/com/intellij/java/refactoring/suggested/JavaSuggestedRefactoringTest.kt index 8790c1e8905b..f6b0e44c0560 100644 --- a/java/java-tests/testSrc/com/intellij/java/refactoring/suggested/JavaSuggestedRefactoringTest.kt +++ b/java/java-tests/testSrc/com/intellij/java/refactoring/suggested/JavaSuggestedRefactoringTest.kt @@ -11,9 +11,10 @@ import com.intellij.psi.PsiElementFactory import com.intellij.psi.PsiJavaFile import com.intellij.psi.search.GlobalSearchScope import com.intellij.refactoring.BaseRefactoringProcessor -import com.intellij.refactoring.suggested.BaseSuggestedRefactoringTest -import com.intellij.refactoring.suggested.SuggestedRefactoringExecution -import com.intellij.refactoring.suggested._suggestedChangeSignatureNewParameterValuesForTests +import com.intellij.refactoring.RefactoringBundle.message +import com.intellij.refactoring.suggested.* +import com.intellij.refactoring.suggested.SuggestedRefactoringSupport.Parameter +import com.intellij.refactoring.suggested.SuggestedRefactoringSupport.Signature class JavaSuggestedRefactoringTest : BaseSuggestedRefactoringTest() { override val fileType: LanguageFileType @@ -1315,7 +1316,41 @@ class JavaSuggestedRefactoringTest : BaseSuggestedRefactoringTest() { executeCommand(project) { type(", int p2") } } } - + + fun testBrokenParameters() { + doTest( + initialText = """ + interface I { + void foo(); + } + """.trimIndent(), + actionName = message("suggested.refactoring.change.signature.intention.text", "usages"), + textAfterRefactoring = """ + interface I { + void foo(String s); + } + """.trimIndent(), + checkPresentation = { + var state = SuggestedRefactoringProviderImpl.getInstance(this.project).state!! + val oldSignature = state.oldSignature + state = state.withOldSignature(Signature.create(oldSignature.name, oldSignature.type, + oldSignature.parameters.let { + val list = it.toMutableList() + list.add(Parameter("s", "s", "String")) + list + }, + oldSignature.additionalData)!!) + state = state.refactoringSupport.availability.refineSignaturesWithResolve(state) + val refactoringSupport = state.refactoringSupport + val refactoring = refactoringSupport.availability.detectAvailableRefactoring(state) + assertNull(refactoring) + }, + editingActions = { + type("String s") + } + ) + } + private fun addFileWithAnnotations() { myFixture.addFileToProject( "Annotations.java", diff --git a/java/testFramework/src/com/intellij/refactoring/suggested/BaseSuggestedRefactoringTest.kt b/java/testFramework/src/com/intellij/refactoring/suggested/BaseSuggestedRefactoringTest.kt index 9411d3ba4631..5ab5dfa83972 100644 --- a/java/testFramework/src/com/intellij/refactoring/suggested/BaseSuggestedRefactoringTest.kt +++ b/java/testFramework/src/com/intellij/refactoring/suggested/BaseSuggestedRefactoringTest.kt @@ -64,7 +64,7 @@ abstract class BaseSuggestedRefactoringTest : LightJavaCodeInsightFixtureTestCas ) } - private fun doTest( + protected fun doTest( initialText: String, actionName: String, textAfterRefactoring: String,