diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateMembersUtil.java b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateMembersUtil.java index dd8697e7b968..aadcc3c13abc 100644 --- a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateMembersUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateMembersUtil.java @@ -1,4 +1,4 @@ -// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.codeInsight.generation; import com.intellij.application.options.CodeStyle; @@ -382,7 +382,10 @@ public final class GenerateMembersUtil { @NotNull PsiSubstitutor substitutor, @NotNull PsiMethod sourceMethod) { final PsiElement copy = ObjectUtils.notNull(typeParameter instanceof PsiCompiledElement ? ((PsiCompiledElement)typeParameter).getMirror() : typeParameter, typeParameter).copy(); - LOG.assertTrue(copy != null, typeParameter); + if (copy == null) { + List substitutedSupers = ContainerUtil.map(typeParameter.getSuperTypes(), t -> ObjectUtils.notNull(toClassType(substitutor.substitute(t)), t)); + return factory.createTypeParameter(Objects.requireNonNull(typeParameter.getName()), substitutedSupers.toArray(PsiClassType.EMPTY_ARRAY)); + } final Map replacementMap = new HashMap<>(); copy.accept(new JavaRecursiveElementVisitor() { @Override @@ -398,6 +401,19 @@ public final class GenerateMembersUtil { return (PsiTypeParameter)RefactoringUtil.replaceElementsWithMap(copy, replacementMap); } + private static PsiClassType toClassType(PsiType type) { + if (type instanceof PsiClassType) { + return (PsiClassType)type; + } + if (type instanceof PsiCapturedWildcardType) { + return toClassType(((PsiCapturedWildcardType)type).getUpperBound()); + } + if (type instanceof PsiWildcardType) { + return toClassType(((PsiWildcardType)type).getBound()); + } + return null; + } + private static void substituteParameters(@NotNull JVMElementFactory factory, @NotNull JavaCodeStyleManager codeStyleManager, @NotNull PsiParameterList sourceParameterList, diff --git a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/codeInsight/Java8OverrideImplementTest.kt b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/codeInsight/Java8OverrideImplementTest.kt index a12ef282d432..96f059a144fb 100644 --- a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/codeInsight/Java8OverrideImplementTest.kt +++ b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/codeInsight/Java8OverrideImplementTest.kt @@ -1,9 +1,17 @@ -// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package org.jetbrains.kotlin.idea.codeInsight +import com.intellij.codeInsight.generation.OverrideImplementExploreUtil +import com.intellij.codeInsight.generation.OverrideImplementUtil +import com.intellij.codeInsight.generation.PsiMethodMember +import com.intellij.psi.PsiJavaFile +import com.intellij.psi.PsiSubstitutor +import com.intellij.psi.util.TypeConversionUtil import org.jetbrains.kotlin.idea.test.IDEA_TEST_DATA_DIR import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor +import org.jetbrains.kotlin.idea.util.application.executeWriteCommand +import org.jetbrains.kotlin.psi.KtFile import org.junit.internal.runners.JUnit38ClassRunner import org.junit.runner.RunWith import java.io.File @@ -16,4 +24,24 @@ class Java8OverrideImplementTest : AbstractOverrideImplementTest() { override fun getProjectDescriptor() = KotlinWithJdkAndRuntimeLightProjectDescriptor.INSTANCE_FULL_JDK fun testOverrideCollectionStream() = doOverrideFileTest("stream") + + fun testImplementKotlinInterface() { + val file = myFixture.addFileToProject( + "A.kt", """interface A { + fun foo(l : L) +}""" + ) + + val superClass = (file as KtFile).classes[0] + val javaFile = myFixture.configureByFile(getTestName(true) + ".java") + val psiClass = (javaFile as PsiJavaFile).classes[0] + val method = superClass.methods[0] + val substitutor = TypeConversionUtil.getSuperClassSubstitutor(superClass, psiClass, PsiSubstitutor.EMPTY) + val candidates = listOf(PsiMethodMember(method, OverrideImplementExploreUtil.correctSubstitutor(method, substitutor))) + myFixture.project.executeWriteCommand("") { + OverrideImplementUtil.overrideOrImplementMethodsInRightPlace(myFixture.editor, psiClass, candidates, false, true) + } + + myFixture.checkResultByFile(getTestName(true) + ".after.java") + } } diff --git a/plugins/kotlin/idea/tests/testData/codeInsight/overrideImplement/jdk8/implementKotlinInterface.after.java b/plugins/kotlin/idea/tests/testData/codeInsight/overrideImplement/jdk8/implementKotlinInterface.after.java new file mode 100644 index 000000000000..ff70a61d92e7 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/codeInsight/overrideImplement/jdk8/implementKotlinInterface.after.java @@ -0,0 +1,7 @@ +class B extends A { + + @Override + public void foo(L l) { + + } +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/codeInsight/overrideImplement/jdk8/implementKotlinInterface.java b/plugins/kotlin/idea/tests/testData/codeInsight/overrideImplement/jdk8/implementKotlinInterface.java new file mode 100644 index 000000000000..80fbdc9736d6 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/codeInsight/overrideImplement/jdk8/implementKotlinInterface.java @@ -0,0 +1,3 @@ +class B extends A { + +} \ No newline at end of file