Java: fix generating constructor/overriding methods in nested class of implicit class (IDEA-373945)

GitOrigin-RevId: cf4f72d56ac5e5ba0b71eb5d38d71c2ab71941b1
This commit is contained in:
Bas Leijdekkers
2025-06-04 13:36:10 +02:00
committed by intellij-monorepo-bot
parent 3b2753b729
commit 0874decf96
8 changed files with 71 additions and 28 deletions

View File

@@ -1,4 +1,4 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
// Copyright 2000-2025 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.CommonBundle;
@@ -63,7 +63,7 @@ public class GenerateConstructorHandler extends GenerateMembersHandlerBase {
if (aClass instanceof PsiImplicitClass) {
Messages.showMessageDialog(project,
JavaBundle.message("error.attempt.to.generate.constructor.for.anonymous.class"),
JavaBundle.message("error.attempt.to.generate.constructor.for.implicit.class"),
CommonBundle.getErrorTitle(),
Messages.getErrorIcon());
return null;

View File

@@ -729,7 +729,7 @@ public final class OverrideImplementUtil extends OverrideImplementExploreUtil {
final PsiClass aClass = (PsiClass)element;
if (aClass instanceof PsiSyntheticClass) return null;
if (file instanceof PsiJavaFile javaFile) {
if (aClass == null && file instanceof PsiJavaFile javaFile) {
PsiClass[] classes = javaFile.getClasses();
if (classes.length == 1 && classes[0] instanceof PsiImplicitClass implicitClass &&
implicitClass.getFirstChild() != null && PsiMethodUtil.hasMainMethod(implicitClass)) {
@@ -740,10 +740,10 @@ public final class OverrideImplementUtil extends OverrideImplementExploreUtil {
}
public static @NotNull List<PsiMethod> overrideOrImplementMethodCandidates(@NotNull PsiClass aClass, @NotNull Collection<? extends CandidateInfo> candidatesToImplement,
public static @NotNull List<PsiMethod> overrideOrImplementMethodCandidates(@NotNull PsiClass aClass,
@NotNull Collection<? extends CandidateInfo> candidatesToImplement,
boolean copyJavadoc) throws IncorrectOperationException {
boolean insert =
JavaCodeStyleSettings.getInstance(aClass.getContainingFile()).INSERT_OVERRIDE_ANNOTATION;
boolean insert = JavaCodeStyleSettings.getInstance(aClass.getContainingFile()).INSERT_OVERRIDE_ANNOTATION;
return overrideOrImplementMethodCandidates(aClass, candidatesToImplement, copyJavadoc, insert);
}
}

View File

@@ -0,0 +1,8 @@
class Nested {
Nested() {<caret>
}
}
void main() {
}

View File

@@ -0,0 +1,7 @@
class Nested {
<caret>
}
void main() {
}

View File

@@ -0,0 +1,33 @@
class Nested {
public Nested() {
super();
}
@Override
public int hashCode() {
return super.hashCode();
}
@Override
public boolean equals(Object obj) {
return super.equals(obj);
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
@Override
public String toString() {
return super.toString();
}
@Override
protected void finalize() throws Throwable {
super.finalize();
}
}
void main() {
}

View File

@@ -0,0 +1,6 @@
class Nested {
<caret>
}
void main() {
}

View File

@@ -1,4 +1,4 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.java.codeInsight;
import com.intellij.JavaTestUtil;
@@ -47,6 +47,7 @@ public class GenerateConstructorTest extends LightJavaCodeInsightFixtureTestCase
return JavaTestUtil.getRelativeJavaTestDataPath() + "/codeInsight/generateConstructor";
}
public void testClassNestedInImplicitClass() { doTest(); }
public void testAbstractClass() { doTest(); }
public void testNewLine() { doTest(); }
public void testPackageLocalClass() { doTest(); }

View File

@@ -10,14 +10,11 @@ import com.intellij.openapi.actionSystem.Presentation;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.impl.NonBlockingReadActionImpl;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiImplicitClass;
import com.intellij.psi.PsiJavaFile;
import com.intellij.psi.codeStyle.JavaCodeStyleSettings;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.testFramework.LightProjectDescriptor;
import com.intellij.testFramework.PsiTestUtil;
import com.intellij.testFramework.ServiceContainerUtil;
import com.intellij.testFramework.UsefulTestCase;
@@ -30,12 +27,8 @@ public class OverrideImplementTest extends LightJavaCodeInsightFixtureTestCase {
return JavaTestUtil.getRelativeJavaTestDataPath() + "/codeInsight/overrideImplement";
}
@Override
protected LightProjectDescriptor getProjectDescriptor() {
return JAVA_LATEST;
}
private void addRecordClass() {
//noinspection override
myFixture.addClass("package java.lang;public abstract class Record {" +
"public abstract boolean equals(Object obj);" +
"public abstract int hashCode();" +
@@ -61,9 +54,8 @@ public class OverrideImplementTest extends LightJavaCodeInsightFixtureTestCase {
doTest(false);
}
public void testOverrideForImplicitClass() {
doTest(false);
}
public void testOverrideForImplicitClass() { doTest(false); }
public void testOverrideForClassNestedInImplicitClass() { doTest(false); }
public void testImplementExtensionMethods() { doTest(true); }
@@ -710,15 +702,11 @@ public class OverrideImplementTest extends LightJavaCodeInsightFixtureTestCase {
}
private void invokeAction(boolean toImplement) {
int offset = myFixture.getEditor().getCaretModel().getOffset();
PsiFile psiFile = myFixture.getFile();
PsiClass psiClass = PsiTreeUtil.findElementOfClassAtOffset(psiFile, offset, PsiClass.class, false);
if (psiFile instanceof PsiJavaFile javaFile && javaFile.getClasses().length == 1 &&
javaFile.getClasses()[0] instanceof PsiImplicitClass implicitClass) {
psiClass = implicitClass;
}
assertNotNull(psiClass);
OverrideImplementUtil.chooseAndOverrideOrImplementMethods(getProject(), myFixture.getEditor(), psiClass, toImplement);
Editor editor = myFixture.getEditor();
PsiFile file = myFixture.getFile();
PsiClass aClass = OverrideImplementUtil.getContextClass(getProject(), editor, file, true);
assertNotNull(aClass);
OverrideImplementUtil.chooseAndOverrideOrImplementMethods(getProject(), editor, aClass, toImplement);
NonBlockingReadActionImpl.waitForAsyncTaskCompletion();
}
}