From df163482cfc42af8ebdfee2c8d2979dca75d738a Mon Sep 17 00:00:00 2001 From: Mikhail Pyltsin Date: Fri, 20 Jan 2023 13:12:46 +0100 Subject: [PATCH] IDEA-310500 JavaCodeStyleManager returns more common names for fields and parameters GitOrigin-RevId: 40dc2a001f35af6cc5cb7db8aeb4c0304016b9fd --- .../CreateExecutableFromJavaUsageRequest.kt | 3 +- .../codeStyle/JavaCodeStyleManagerImpl.java | 37 +++++--- .../psi/codeStyle/JavaCodeStyleManager.java | 9 ++ .../core/CoreJavaCodeStyleManager.java | 6 ++ .../replaceAll3_after.java | 4 +- .../codeStyle/CodeStyleManagerTest.java | 86 +++++++++++++++++++ 6 files changed, 129 insertions(+), 16 deletions(-) create mode 100644 java/java-tests/testSrc/com/intellij/codeStyle/CodeStyleManagerTest.java diff --git a/java/java-impl/src/com/intellij/lang/java/request/CreateExecutableFromJavaUsageRequest.kt b/java/java-impl/src/com/intellij/lang/java/request/CreateExecutableFromJavaUsageRequest.kt index 68a4f2dfd607..782de1162add 100644 --- a/java/java-impl/src/com/intellij/lang/java/request/CreateExecutableFromJavaUsageRequest.kt +++ b/java/java-impl/src/com/intellij/lang/java/request/CreateExecutableFromJavaUsageRequest.kt @@ -8,6 +8,7 @@ import com.intellij.lang.jvm.actions.* import com.intellij.openapi.components.service import com.intellij.psi.* import com.intellij.psi.codeStyle.JavaCodeStyleManager +import com.intellij.psi.codeStyle.VariableKind import com.intellij.psi.util.createSmartPointer import com.intellij.psi.util.parentOfTypes import com.intellij.util.CommonJavaRefactoringUtil @@ -37,7 +38,7 @@ internal abstract class CreateExecutableFromJavaUsageRequest( return argumentList.expressions.map { expression -> val argType: PsiType? = CommonJavaRefactoringUtil.getTypeByExpression(expression) val type = CreateFromUsageUtils.getParameterTypeByArgumentType(argType, psiManager, scope) - val names = codeStyleManager.suggestSemanticNames(expression) + val names = codeStyleManager.suggestSemanticNames(expression, VariableKind.PARAMETER) val expectedTypes = expectedTypes(type, ExpectedType.Kind.SUPERTYPE) expectedParameter(expectedTypes, names) } diff --git a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/JavaCodeStyleManagerImpl.java b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/JavaCodeStyleManagerImpl.java index c11ae01f708e..86ed15e0f812 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/JavaCodeStyleManagerImpl.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/JavaCodeStyleManagerImpl.java @@ -572,6 +572,7 @@ public class JavaCodeStyleManagerImpl extends JavaCodeStyleManager { @NotNull private NamesByExprInfo suggestVariableNameByExpression(@NotNull PsiExpression expr, @Nullable VariableKind variableKind) { final LinkedHashSet names = new LinkedHashSet<>(); + ContainerUtil.addIfNotNull(names, suggestVariableNameFromConstant(expr, variableKind)); ContainerUtil.addIfNotNull(names, suggestVariableNameFromLiterals(expr)); NamesByExprInfo byExpr = suggestVariableNameByExpressionOnly(expr, variableKind, false); @@ -591,6 +592,19 @@ public class JavaCodeStyleManagerImpl extends JavaCodeStyleManager { return new NamesByExprInfo(propertyName, names); } + @Nullable + private static String suggestVariableNameFromConstant(@NotNull PsiExpression expr, @Nullable VariableKind kind) { + if (kind == null || kind == VariableKind.LOCAL_VARIABLE) { + return null; + } + PsiExpression expression = PsiUtil.skipParenthesizedExprDown(expr); + if (expression instanceof PsiReferenceExpression referenceExpression && + referenceExpression.resolve() instanceof PsiEnumConstant enumConstant) { + return normalizeTypeName(getTypeName(enumConstant.getType())); + } + return null; + } + @Nullable private static String suggestVariableNameFromLiterals(@NotNull PsiExpression expr) { String text = findLiteralText(expr); @@ -1166,6 +1180,12 @@ public class JavaCodeStyleManagerImpl extends JavaCodeStyleManager { return suggestVariableNameByExpression(expression, null).names; } + @NotNull + @Override + public Collection suggestSemanticNames(@NotNull PsiExpression expression, @NotNull VariableKind kind) { + return suggestVariableNameByExpression(expression, kind).names; + } + @NotNull private Collection suggestSemanticNamesByType(@Nullable PsiType type, @NotNull VariableKind kind) { return type == null ? Collections.emptyList() : doSuggestNamesByType(type, kind); @@ -1174,13 +1194,10 @@ public class JavaCodeStyleManagerImpl extends JavaCodeStyleManager { @Override @NotNull public SuggestedNameInfo suggestNames(@NotNull Collection semanticNames, @NotNull VariableKind kind, @Nullable PsiType type) { - final Iterable allSemanticNames; - if (kind == VariableKind.LOCAL_VARIABLE || !isEnum(type)) { - allSemanticNames = ContainerUtil.concat(semanticNames, suggestSemanticNamesByType(type, kind)); - } - else { - allSemanticNames = ContainerUtil.concat(suggestSemanticNamesByType(type, kind), semanticNames); - } + final Iterable allSemanticNames = ContainerUtil.concat( + semanticNames, + suggestSemanticNamesByType(type, kind) + ); final Set suggestions = new LinkedHashSet<>(getSuggestionsByNames(allSemanticNames, kind, true)); final String propertyName = ContainerUtil.getFirstItem(semanticNames); @@ -1197,12 +1214,6 @@ public class JavaCodeStyleManagerImpl extends JavaCodeStyleManager { }; } - private static boolean isEnum(PsiType type) { - PsiClass aClass = PsiUtil.resolveClassInClassTypeOnly(type); - if (aClass == null) return false; - return aClass.isEnum(); - } - @NonNls @NotNull private String changeIfNotIdentifier(@NotNull String name) { diff --git a/java/java-psi-api/src/com/intellij/psi/codeStyle/JavaCodeStyleManager.java b/java/java-psi-api/src/com/intellij/psi/codeStyle/JavaCodeStyleManager.java index 670021f8f47c..3996eb021954 100644 --- a/java/java-psi-api/src/com/intellij/psi/codeStyle/JavaCodeStyleManager.java +++ b/java/java-psi-api/src/com/intellij/psi/codeStyle/JavaCodeStyleManager.java @@ -247,6 +247,15 @@ public abstract class JavaCodeStyleManager { @NotNull public abstract Collection suggestSemanticNames(@NotNull PsiExpression expression); + /** + * This method is not actually tied to Java Code Style and work similarly to {@link #suggestSemanticNames(PsiExpression)} + * Additionally, this method adds new names from the context, based on VariableKind + *

+ * Should be used with {@link #suggestNames(Collection, VariableKind, PsiType)}. + */ + @NotNull + public abstract Collection suggestSemanticNames(@NotNull PsiExpression expression, @NotNull VariableKind kind); + @NotNull public abstract SuggestedNameInfo suggestNames(@NotNull Collection semanticNames, @NotNull VariableKind kind, diff --git a/java/java-psi-impl/src/com/intellij/core/CoreJavaCodeStyleManager.java b/java/java-psi-impl/src/com/intellij/core/CoreJavaCodeStyleManager.java index ea713f535668..1f6855345221 100644 --- a/java/java-psi-impl/src/com/intellij/core/CoreJavaCodeStyleManager.java +++ b/java/java-psi-impl/src/com/intellij/core/CoreJavaCodeStyleManager.java @@ -201,6 +201,12 @@ public class CoreJavaCodeStyleManager extends JavaCodeStyleManager { return Collections.emptyList(); } + @NotNull + @Override + public Collection suggestSemanticNames(@NotNull PsiExpression expression, @NotNull VariableKind kind) { + return Collections.emptyList(); + } + @NotNull @Override public SuggestedNameInfo suggestNames(@NotNull Collection semanticNames, @NotNull VariableKind kind, @Nullable PsiType type) { diff --git a/java/java-tests/testData/refactoring/inplaceIntroduceParameter/replaceAll3_after.java b/java/java-tests/testData/refactoring/inplaceIntroduceParameter/replaceAll3_after.java index 8d7703ca4d04..ba3ce9458829 100644 --- a/java/java-tests/testData/refactoring/inplaceIntroduceParameter/replaceAll3_after.java +++ b/java/java-tests/testData/refactoring/inplaceIntroduceParameter/replaceAll3_after.java @@ -5,8 +5,8 @@ class C { void x(String s1, String s2) {} - private void y(E a) { - x(a.toString(), a.toString()); + private void y(E e) { + x(e.toString(), e.toString()); } } diff --git a/java/java-tests/testSrc/com/intellij/codeStyle/CodeStyleManagerTest.java b/java/java-tests/testSrc/com/intellij/codeStyle/CodeStyleManagerTest.java new file mode 100644 index 000000000000..6483503e0737 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/codeStyle/CodeStyleManagerTest.java @@ -0,0 +1,86 @@ +// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package com.intellij.codeStyle; + +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiExpression; +import com.intellij.psi.PsiFile; +import com.intellij.psi.codeStyle.JavaCodeStyleManager; +import com.intellij.psi.codeStyle.VariableKind; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.util.PsiUtilCore; +import com.intellij.testFramework.assertions.Assertions; +import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase; +import org.intellij.lang.annotations.Language; +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; + +public class CodeStyleManagerTest extends LightJavaCodeInsightFixtureTestCase { + + public void testSuggestSemanticNameEnumConstantVariable() { + testSuggestedFirstName(""" + public class Test { + public static void main(String[] args) { + check("Some", (Month.JANUARY), 17); + } + + private enum Month { + JANUARY + } + } + """, "january", VariableKind.LOCAL_VARIABLE); + } + + public void testSuggestSemanticNameStringConstant() { + testSuggestedFirstName(""" + public class Test { + public static void main(String[] args) { + check("Some", (Month.JANUARY), 17); + } + + private enum Month { + JANUARY + } + } + """, "Some", VariableKind.LOCAL_VARIABLE); + } + + public void testSuggestSemanticNameVariableNameParameter() { + testSuggestedFirstName(""" + public class Test { + public static void main(String[] args) { + Month month2 = Month.JANUARY; + check("Some", month2, 17); + } + + private enum Month { + JANUARY + } + } + """, "month2", VariableKind.PARAMETER); + } + + public void testSuggestSemanticNameEnumConstantParameter() { + testSuggestedFirstName(""" + public class Test { + public static void main(String[] args) { + check("Some",(Month.JANUARY), 17); + } + + private enum Month { + JANUARY + } + } + """, "month", VariableKind.PARAMETER); + } + + private void testSuggestedFirstName(@NotNull @Language("JAVA") String text, @NotNull String expected, @NotNull VariableKind parameter) { + PsiFile file = myFixture.configureByText("Test.java", text); + int offset = myFixture.getCaretOffset(); + PsiElement element = PsiUtilCore.getElementAtOffset(file, offset); + PsiExpression expression = PsiTreeUtil.getParentOfType(element, PsiExpression.class, false); + final JavaCodeStyleManager javaCodeStyleManager = JavaCodeStyleManager.getInstance(getProject()); + Collection names = javaCodeStyleManager.suggestSemanticNames(expression, parameter); + Assertions.assertThat(names.iterator().next()).isEqualToIgnoringCase(expected); + } +}