From 662cb5deae1af2c0f009a1dfeb3c46898cdc45cb Mon Sep 17 00:00:00 2001 From: Tagir Valeev Date: Wed, 18 Dec 2019 17:16:16 +0700 Subject: [PATCH] Handle compact constructor in regular class: quick-fix to add () (IDEA-228460) GitOrigin-RevId: c019e19e8023c0209f6e5ed54f8a486689bb0e0a --- .../intention/QuickFixFactory.java | 3 ++ .../impl/analysis/HighlightMethodUtil.java | 22 +++++--- .../impl/quickfix/AddParameterListFix.java | 54 +++++++++++++++++++ .../impl/config/QuickFixFactoryImpl.java | 6 +++ .../intellij/psi/util/JavaPsiRecordUtil.java | 11 +++- .../src/messages/JavaErrorMessages.properties | 1 + .../RecordCompactConstructors.java | 5 ++ .../addParameterList/afterSimple.java | 6 +++ .../addParameterList/beforeSimple.java | 6 +++ .../daemon/LightRecordsHighlightingTest.java | 3 ++ .../daemon/quickFix/AddParameterListTest.java | 14 +++++ 11 files changed, 123 insertions(+), 8 deletions(-) create mode 100644 java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddParameterListFix.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlightingRecords/RecordCompactConstructors.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addParameterList/afterSimple.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addParameterList/beforeSimple.java create mode 100644 java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/quickFix/AddParameterListTest.java diff --git a/java/java-analysis-api/src/com/intellij/codeInsight/intention/QuickFixFactory.java b/java/java-analysis-api/src/com/intellij/codeInsight/intention/QuickFixFactory.java index 7fbe7f816764..93e2d2fd3368 100644 --- a/java/java-analysis-api/src/com/intellij/codeInsight/intention/QuickFixFactory.java +++ b/java/java-analysis-api/src/com/intellij/codeInsight/intention/QuickFixFactory.java @@ -480,4 +480,7 @@ public abstract class QuickFixFactory { @NotNull public abstract IntentionAction createWrapSwitchRuleStatementsIntoBlockFix(PsiSwitchLabeledRuleStatement rule); + + @NotNull + public abstract IntentionAction createAddParameterListFix(PsiMethod method); } \ No newline at end of file diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java index 1c3280681834..4e9aae0a10c3 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java @@ -1937,7 +1937,18 @@ public class HighlightMethodUtil { public static HighlightInfo checkRecordConstructorDeclaration(PsiMethod method) { if (!method.isConstructor()) return null; PsiClass aClass = method.getContainingClass(); - if (aClass == null || !aClass.isRecord()) return null; + if (aClass == null) return null; + PsiIdentifier identifier = method.getNameIdentifier(); + if (identifier == null) return null; + if (!aClass.isRecord()) { + if (JavaPsiRecordUtil.isCompactConstructor(method)) { + HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range( + identifier).descriptionAndTooltip(JavaErrorMessages.message("compact.constructor.in.regular.class")).create(); + QuickFixAction.registerQuickFixAction(info, QUICK_FIX_FACTORY.createAddParameterListFix(method)); + return info; + } + return null; + } if (JavaPsiRecordUtil.isCanonicalConstructor(method)) { PsiParameter[] parameters = method.getParameterList().getParameters(); PsiRecordComponent[] components = aClass.getRecordComponents(); @@ -1961,12 +1972,9 @@ public class HighlightMethodUtil { // Non-canonical constructor PsiMethodCallExpression call = JavaPsiConstructorUtil.findThisOrSuperCallInConstructor(method); if (call == null || JavaPsiConstructorUtil.isSuperConstructorCall(call)) { - PsiIdentifier identifier = method.getNameIdentifier(); - if (identifier != null) { - String message = JavaErrorMessages.message("record.no.constructor.call.in.non.canonical"); - return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(identifier) - .descriptionAndTooltip(message).create(); - } + String message = JavaErrorMessages.message("record.no.constructor.call.in.non.canonical"); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(identifier) + .descriptionAndTooltip(message).create(); } return null; } diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddParameterListFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddParameterListFix.java new file mode 100644 index 000000000000..5fe3919a0c20 --- /dev/null +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddParameterListFix.java @@ -0,0 +1,54 @@ +// Copyright 2000-2019 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. +package com.intellij.codeInsight.daemon.impl.quickfix; + +import com.intellij.codeInspection.LocalQuickFixAndIntentionActionOnPsiElement; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.Project; +import com.intellij.psi.*; +import com.intellij.psi.util.JavaPsiRecordUtil; +import com.intellij.util.ArrayUtil; +import org.jetbrains.annotations.Nls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class AddParameterListFix extends LocalQuickFixAndIntentionActionOnPsiElement { + public AddParameterListFix(PsiMethod method) { + super(method); + } + + @Override + public void invoke(@NotNull Project project, + @NotNull PsiFile file, + @Nullable Editor editor, + @NotNull PsiElement startElement, + @NotNull PsiElement endElement) { + if (!(startElement instanceof PsiMethod)) return; + PsiMethod method = (PsiMethod)startElement; + method.getParameterList() + .replace(JavaPsiFacade.getElementFactory(project).createParameterList(ArrayUtil.EMPTY_STRING_ARRAY, PsiType.EMPTY_ARRAY)); + } + + @Nls(capitalization = Nls.Capitalization.Sentence) + @NotNull + @Override + public String getText() { + return getFamilyName(); + } + + @Nls(capitalization = Nls.Capitalization.Sentence) + @NotNull + @Override + public String getFamilyName() { + return "Insert '()'"; + } + + @Override + public boolean isAvailable(@NotNull Project project, + @NotNull PsiFile file, + @Nullable Editor editor, + @NotNull PsiElement startElement, + @NotNull PsiElement endElement) { + return super.isAvailable(project, file, editor, startElement, endElement) && + startElement instanceof PsiMethod && JavaPsiRecordUtil.isCompactConstructor((PsiMethod)startElement); + } +} diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/config/QuickFixFactoryImpl.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/config/QuickFixFactoryImpl.java index 3b6c1dfcb5f0..1ecaaa663083 100644 --- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/config/QuickFixFactoryImpl.java +++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/config/QuickFixFactoryImpl.java @@ -907,4 +907,10 @@ public class QuickFixFactoryImpl extends QuickFixFactory { public IntentionAction createWrapSwitchRuleStatementsIntoBlockFix(PsiSwitchLabeledRuleStatement rule) { return new WrapSwitchRuleStatementsIntoBlockFix(rule); } + + @NotNull + @Override + public IntentionAction createAddParameterListFix(PsiMethod method) { + return new AddParameterListFix(method); + } } diff --git a/java/java-psi-api/src/com/intellij/psi/util/JavaPsiRecordUtil.java b/java/java-psi-api/src/com/intellij/psi/util/JavaPsiRecordUtil.java index 2b65e2042c2b..36668095c6d9 100644 --- a/java/java-psi-api/src/com/intellij/psi/util/JavaPsiRecordUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/util/JavaPsiRecordUtil.java @@ -46,7 +46,16 @@ public class JavaPsiRecordUtil { } /** - * @param method to check + * @param method method to check + * @return true if given method is a compact constructor (has no parameter list), + * regardless whether it's declared in the record or not + */ + public static boolean isCompactConstructor(@NotNull PsiMethod method) { + return method.isConstructor() && method.getParameterList().textMatches(""); + } + + /** + * @param method method to check * @return true if given method is a canonical constructor for a record class */ public static boolean isCanonicalConstructor(@NotNull PsiMethod method) { diff --git a/java/java-psi-impl/src/messages/JavaErrorMessages.properties b/java/java-psi-impl/src/messages/JavaErrorMessages.properties index 04b4363646b3..5db7672b0029 100644 --- a/java/java-psi-impl/src/messages/JavaErrorMessages.properties +++ b/java/java-psi-impl/src/messages/JavaErrorMessages.properties @@ -484,6 +484,7 @@ record.special.method.throws={0} cannot declare thrown exceptions record.canonical.constructor=Canonical constructor record.accessor=Record component accessor record.component.not.initialized=Record component ''{0}'' might not be initialized in canonical constructor +compact.constructor.in.regular.class=Parameter list expected feature.generics=Generics feature.annotations=Annotations diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlightingRecords/RecordCompactConstructors.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlightingRecords/RecordCompactConstructors.java new file mode 100644 index 000000000000..95cf0142c6d3 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlightingRecords/RecordCompactConstructors.java @@ -0,0 +1,5 @@ +class NotRecord { + public NotRecord { + + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addParameterList/afterSimple.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addParameterList/afterSimple.java new file mode 100644 index 000000000000..8cca25a23580 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addParameterList/afterSimple.java @@ -0,0 +1,6 @@ +// "Insert '()'" "true" +class NotRecord { + public NotRecord() { + + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addParameterList/beforeSimple.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addParameterList/beforeSimple.java new file mode 100644 index 000000000000..a8f52eca187a --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addParameterList/beforeSimple.java @@ -0,0 +1,6 @@ +// "Insert '()'" "true" +class NotRecord { + public NotRecord { + + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/LightRecordsHighlightingTest.java b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/LightRecordsHighlightingTest.java index 43a91438a5b2..b20979eaac18 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/LightRecordsHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/LightRecordsHighlightingTest.java @@ -27,6 +27,9 @@ public class LightRecordsHighlightingTest extends LightJavaCodeInsightFixtureTes public void testRecordConstructors() { doTest(); } + public void testRecordCompactConstructors() { + doTest(); + } private void doTest() { myFixture.configureByFile(getTestName(false) + ".java"); diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/quickFix/AddParameterListTest.java b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/quickFix/AddParameterListTest.java new file mode 100644 index 000000000000..d5104eed9506 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/quickFix/AddParameterListTest.java @@ -0,0 +1,14 @@ +// Copyright 2000-2019 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. +package com.intellij.java.codeInsight.daemon.quickFix; + +import com.intellij.codeInsight.daemon.quickFix.LightQuickFixParameterizedTestCase; + +public class AddParameterListTest extends LightQuickFixParameterizedTestCase { + + @Override + protected String getBasePath() { + return "/codeInsight/daemonCodeAnalyzer/quickFix/addParameterList"; + } + +} +