mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Java: correct find usages on default constructor (IDEA-67203)
GitOrigin-RevId: 5ce84cf2a8444fbf666f762af14090d000195c35
This commit is contained in:
committed by
intellij-monorepo-bot
parent
b5ea94c4a7
commit
91b5aadb07
+5
@@ -26,6 +26,7 @@ import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleSettings;
|
||||
import com.intellij.psi.codeStyle.VariableKind;
|
||||
import com.intellij.psi.impl.FindSuperElementsHelper;
|
||||
import com.intellij.psi.impl.light.LightDefaultConstructor;
|
||||
import com.intellij.psi.impl.light.LightRecordMethod;
|
||||
import com.intellij.psi.impl.source.javadoc.PsiDocParamRef;
|
||||
import com.intellij.psi.javadoc.PsiDocTag;
|
||||
@@ -131,6 +132,7 @@ public class JavaSafeDeleteProcessor extends SafeDeleteProcessorDelegateBase {
|
||||
@Nullable Module module,
|
||||
@NotNull Collection<? extends PsiElement> allElementsToDelete) {
|
||||
Project project = element.getProject();
|
||||
if (element instanceof SyntheticElement && !(element instanceof LightDefaultConstructor)) return null;
|
||||
if (element instanceof PsiPackage aPackage && module != null) {
|
||||
PsiDirectory[] directories = aPackage.getDirectories(module.getModuleScope());
|
||||
if (directories.length == 0) return null;
|
||||
@@ -145,6 +147,9 @@ public class JavaSafeDeleteProcessor extends SafeDeleteProcessorDelegateBase {
|
||||
if (ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
return Collections.singletonList(element);
|
||||
}
|
||||
if (method.isDefaultConstructor()) {
|
||||
return Collections.singletonList(method.getContainingClass());
|
||||
}
|
||||
PsiMethod[] methods = SuperMethodWarningUtil.checkSuperMethods(method, allElementsToDelete);
|
||||
if (methods.length == 0) return null;
|
||||
ArrayList<PsiMethod> psiMethods = new ArrayList<>(Arrays.asList(methods));
|
||||
|
||||
@@ -6,7 +6,6 @@ import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.augment.PsiExtensionMethod;
|
||||
import com.intellij.psi.impl.light.LightDefaultConstructor;
|
||||
import com.intellij.psi.impl.light.LightRecordCanonicalConstructor;
|
||||
import com.intellij.psi.impl.light.LightRecordMember;
|
||||
import com.intellij.psi.javadoc.PsiDocTag;
|
||||
@@ -162,9 +161,6 @@ public class JavaTargetElementEvaluator extends TargetElementEvaluatorEx2 implem
|
||||
if (refElement instanceof LightRecordCanonicalConstructor) {
|
||||
return ((LightRecordCanonicalConstructor)refElement).getContainingClass();
|
||||
}
|
||||
if (refElement instanceof LightDefaultConstructor def) {
|
||||
return def.getContainingClass();
|
||||
}
|
||||
}
|
||||
return super.adjustReferenceOrReferencedElement(file, editor, offset, flags, refElement);
|
||||
}
|
||||
|
||||
-3
@@ -5,7 +5,6 @@ import com.intellij.codeInsight.completion.command.CompletionCommand
|
||||
import com.intellij.codeInsight.completion.command.commands.AbstractSafeDeleteCompletionCommandProvider
|
||||
import com.intellij.codeInsight.completion.command.commands.DirectInspectionFixCompletionCommand
|
||||
import com.intellij.codeInsight.completion.command.getCommandContext
|
||||
import com.intellij.codeInsight.completion.command.getTargetContext
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
@@ -33,8 +32,6 @@ private class JavaSafeDeleteCompletionCommandProvider : AbstractSafeDeleteComple
|
||||
return targetElement
|
||||
}
|
||||
}
|
||||
val targetContext = getTargetContext(offset, editor)
|
||||
if (targetContext?.isWritable != true) return null
|
||||
return element
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
public class Animal {
|
||||
|
||||
public static void main(String[] args) {
|
||||
Animal animal = new <caret>Animal();
|
||||
}
|
||||
}
|
||||
class OneLeggedDog extends Animal {
|
||||
OneLeggedDog() {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
public class DefaultConstructor {
|
||||
|
||||
public static void main(String[] args) {
|
||||
DefaultConstructor constructor = new <caret>DefaultConstructor();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
public class HeadlessHorseman {
|
||||
|
||||
public static void main(String[] args) {
|
||||
HeadlessHorseman constructor = new HeadlessHorseman();
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2022 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.psi.search;
|
||||
|
||||
import com.intellij.openapi.actionSystem.CommonDataKeys;
|
||||
@@ -47,6 +47,18 @@ public class FindUsagesTargetTest extends LightJavaCodeInsightFixtureTestCase {
|
||||
assertTrue(((PsiMethod)element).isConstructor());
|
||||
assertEquals("Xyz", ((PsiMethod)element).getName());
|
||||
}
|
||||
|
||||
public void testDefaultConstructor() {
|
||||
myFixture.configureByText("OneLeggedDog.java", """
|
||||
public class OneLeggedDog {
|
||||
static void main(){
|
||||
OneLeggedDog dog = new <caret>OneLeggedDog();
|
||||
}
|
||||
}
|
||||
""");
|
||||
PsiElement element = getTargetElement();
|
||||
assertTrue(element instanceof PsiMethod m && m.isConstructor() && "OneLeggedDog".equals(m.getName()));
|
||||
}
|
||||
|
||||
private PsiElement getTargetElement() {
|
||||
DataContext dataContext = ((EditorEx)myFixture.getEditor()).getDataContext();
|
||||
@@ -55,7 +67,7 @@ public class FindUsagesTargetTest extends LightJavaCodeInsightFixtureTestCase {
|
||||
PsiElement psiElement = CommonDataKeys.PSI_ELEMENT.getData(dataContext);
|
||||
|
||||
UsageTarget[] targets = UsageTargetUtil.findUsageTargets(editor, psiFile, psiElement);
|
||||
assertTrue(targets.length > 0);
|
||||
assertTrue("<caret> is ", targets.length > 0);
|
||||
assertTrue(targets[0] instanceof PsiElementUsageTarget);
|
||||
return ((PsiElementUsageTarget)targets[0]).getElement();
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
// 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.psi.search;
|
||||
|
||||
import com.intellij.JavaTestUtil;
|
||||
@@ -40,6 +40,7 @@ import com.intellij.util.ProcessingContext;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.TimeoutUtil;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.siyeh.ig.psiutils.PsiElementOrderComparator;
|
||||
import it.unimi.dsi.fastutil.ints.IntArrayList;
|
||||
import it.unimi.dsi.fastutil.ints.IntList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -119,6 +120,20 @@ public class FindUsagesTest extends JavaPsiTestCase {
|
||||
((PsiCompiledElement)myJavaFacade.findClass("javax.swing.JLabel", GlobalSearchScope.allScope(myProject))).getMirror();
|
||||
assertEquals(2, ReferencesSearch.search(decompiled, GlobalSearchScope.projectScope(myProject)).findAll().size());
|
||||
}
|
||||
|
||||
public void testDefaultConstructor() {
|
||||
PsiClass aClass = myJavaFacade.findClass("Animal", GlobalSearchScope.allScope(myProject));
|
||||
PsiMethod main = aClass.findMethodsByName("main", false)[0];
|
||||
PsiLocalVariable variable = (PsiLocalVariable)main.getBody().getStatements()[0].getFirstChild();
|
||||
PsiNewExpression newExpression = (PsiNewExpression)variable.getInitializer();
|
||||
PsiMethod defaultConstructor = newExpression.resolveMethod();
|
||||
Collection<PsiReference> references = ReferencesSearch.search(defaultConstructor, GlobalSearchScope.projectScope(myProject)).findAll();
|
||||
List<@NotNull PsiElement> result =
|
||||
references.stream().map(r -> r.getElement()).sorted(PsiElementOrderComparator.getInstance()).toList();
|
||||
assertEquals(2, references.size());
|
||||
assertTrue(result.get(0).getParent() instanceof PsiNewExpression);
|
||||
assertTrue(result.get(1) instanceof PsiMethod m && m.isConstructor() && "OneLeggedDog".equals(m.getName()));
|
||||
}
|
||||
|
||||
public void testImplicitConstructorUsage() {
|
||||
PsiMethod[] ctrs = myJavaFacade.findClass("Foo", GlobalSearchScope.allScope(myProject)).getConstructors();
|
||||
|
||||
@@ -62,6 +62,10 @@ public class RenameMembersInplaceTest extends LightJavaCodeInsightTestCase {
|
||||
public void testSuperMethodAnonymousInheritor() {
|
||||
doTestInplaceRename("xxx");
|
||||
}
|
||||
|
||||
public void testDefaultConstructor() {
|
||||
doTestInplaceRename("HeadlessHorseman");
|
||||
}
|
||||
|
||||
public void testMultipleConstructors() {
|
||||
doTestInplaceRename("Bar");
|
||||
|
||||
@@ -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.refactoring.actions;
|
||||
|
||||
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
|
||||
@@ -227,18 +227,18 @@ public abstract class BaseRefactoringAction extends AnAction {
|
||||
@ApiStatus.Internal
|
||||
public static PsiElement findRefactoringTargetInEditor(@NotNull DataContext dataContext,
|
||||
@NotNull Predicate<? super Language> elementLanguagePredicate) {
|
||||
Editor editor = dataContext.getData(CommonDataKeys.EDITOR);
|
||||
PsiFile file = dataContext.getData(CommonDataKeys.PSI_FILE);
|
||||
PsiElement element = dataContext.getData(CommonDataKeys.PSI_ELEMENT);
|
||||
Language[] languages = dataContext.getData(LangDataKeys.CONTEXT_LANGUAGES);
|
||||
if (element == null || element instanceof SyntheticElement || !elementLanguagePredicate.test(element.getLanguage())) {
|
||||
if (element == null || !elementLanguagePredicate.test(element.getLanguage())) {
|
||||
Editor editor = dataContext.getData(CommonDataKeys.EDITOR);
|
||||
PsiFile file = dataContext.getData(CommonDataKeys.PSI_FILE);
|
||||
if (file == null || editor == null) {
|
||||
return null;
|
||||
}
|
||||
element = getElementAtCaret(editor, file);
|
||||
}
|
||||
|
||||
if (element == null || element instanceof SyntheticElement || languages == null) {
|
||||
Language[] languages = dataContext.getData(LangDataKeys.CONTEXT_LANGUAGES);
|
||||
if (element == null || languages == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
+15
-8
@@ -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.refactoring.rename.inplace;
|
||||
|
||||
import com.intellij.codeInsight.TargetElementUtil;
|
||||
@@ -228,9 +228,8 @@ public class MemberInplaceRenamer extends VariableInplaceRenamer {
|
||||
private void appendAdditionalElement(Collection<? super Pair<PsiElement, TextRange>> stringUsages,
|
||||
PsiNamedElement variable,
|
||||
PsiElement element) {
|
||||
if (element != variable && element instanceof PsiNameIdentifierOwner &&
|
||||
!notSameFile(null, element.getContainingFile())) {
|
||||
final PsiElement identifier = ((PsiNameIdentifierOwner)element).getNameIdentifier();
|
||||
if (element != variable && element instanceof PsiNameIdentifierOwner owner && !notSameFile(null, element.getContainingFile())) {
|
||||
final PsiElement identifier = owner.getNameIdentifier();
|
||||
if (identifier != null) {
|
||||
stringUsages.add(Pair.create(identifier, new TextRange(0, identifier.getTextLength())));
|
||||
}
|
||||
@@ -242,7 +241,14 @@ public class MemberInplaceRenamer extends VariableInplaceRenamer {
|
||||
try {
|
||||
startDumbIfPossible();
|
||||
tryRollback();
|
||||
final PsiNamedElement variable = getVariable();
|
||||
PsiNamedElement variable = getVariable();
|
||||
if (variable == null) {
|
||||
PsiFile psiFile = PsiDocumentManager.getInstance(myProject).getPsiFile(myEditor.getDocument());
|
||||
if (psiFile != null) {
|
||||
variable = PsiTreeUtil.findElementOfClassAtRange(psiFile, mySubstitutedRange.getStartOffset(), mySubstitutedRange.getEndOffset(),
|
||||
PsiNameIdentifierOwner.class);
|
||||
}
|
||||
}
|
||||
if (variable != null && !newName.equals(myOldName)) {
|
||||
if (isIdentifier(newName, variable.getLanguage())) {
|
||||
final PsiElement substituted = getSubstituted();
|
||||
@@ -250,6 +256,8 @@ public class MemberInplaceRenamer extends VariableInplaceRenamer {
|
||||
return;
|
||||
}
|
||||
|
||||
String type = UsageViewUtil.getType(variable);
|
||||
String name = DescriptiveNameUtil.getDescriptiveName(variable);
|
||||
Runnable performRunnable = () -> {
|
||||
try (var ignored = SlowOperations.startSection(SlowOperations.ACTION_PERFORM)) {
|
||||
if (DumbService.isDumb(myProject)) {
|
||||
@@ -259,9 +267,8 @@ public class MemberInplaceRenamer extends VariableInplaceRenamer {
|
||||
return;
|
||||
}
|
||||
|
||||
final String commandName = RefactoringBundle.message("renaming.0.1.to.2",
|
||||
UsageViewUtil.getType(variable),
|
||||
DescriptiveNameUtil.getDescriptiveName(variable), newName);
|
||||
|
||||
final String commandName = RefactoringBundle.message("renaming.0.1.to.2", type, name, newName);
|
||||
CommandProcessor.getInstance().executeCommand(myProject, () -> {
|
||||
performRenameInner(substituted, newName);
|
||||
PsiDocumentManager.getInstance(myProject).commitAllDocuments();
|
||||
|
||||
@@ -456,7 +456,6 @@ public final class SafeDeleteProcessor extends BaseRefactoringProcessor {
|
||||
|
||||
public static boolean validElement(@NotNull PsiElement element) {
|
||||
if (element instanceof PsiFile) return true;
|
||||
if (!element.isPhysical()) return false;
|
||||
RefactoringSupportProvider provider = LanguageRefactoringSupport.getInstance().forContext(element);
|
||||
return provider != null && provider.isSafeDeleteAvailable(element);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user