From df3abfd8c311d2b0046b9d0ee7064a30d53df085 Mon Sep 17 00:00:00 2001 From: "Anna.Kozlova" Date: Fri, 25 Nov 2016 11:46:26 +0100 Subject: [PATCH] check constructor only implicitly called constructor (IDEA-164500) --- .../impl/analysis/HighlightClassUtil.java | 92 +++++++------------ ...ExceptionsOverResolvedConstructorOnly.java | 17 ++++ .../daemon/LightAdvHighlightingJdk6Test.java | 3 + 3 files changed, 53 insertions(+), 59 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting6/SpeculateOnUnhandledExceptionsOverResolvedConstructorOnly.java diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java index c2d9c94ad154..fc1bc4b71533 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java @@ -527,70 +527,24 @@ public class HighlightClassUtil { PsiMethod[] constructors = baseClass.getConstructors(); if (constructors.length == 0) return null; - final HighlightInfo highlightInfo = constructors.length > 1 ? checkAmbiguityOfImplicitConstructorCall(constructors, range, aClass, baseClass) : null; - if (highlightInfo != null) { - return highlightInfo; - } - - for (PsiMethod constructor : constructors) { - if (resolveHelper.isAccessible(constructor, aClass, null)) { - if (constructor.getParameterList().getParametersCount() == 0 || - constructor.getParameterList().getParametersCount() == 1 && constructor.isVarArgs() - ) { - // it is an error if base ctr throws exceptions - String description = checkDefaultConstructorThrowsException(constructor, handledExceptions); - if (description != null) { - HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(range).descriptionAndTooltip(description).create(); - QuickFixAction.registerQuickFixAction(info, QUICK_FIX_FACTORY.createCreateConstructorMatchingSuperFix(aClass)); - return info; - } - if (refCountHolder != null) { - refCountHolder.registerLocallyReferenced(constructor); - } - return null; - } - } - } - - String description = JavaErrorMessages.message("no.default.constructor.available", HighlightUtil.formatClass(baseClass)); - - HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(range).descriptionAndTooltip(description).create(); - QuickFixAction.registerQuickFixAction(info, QUICK_FIX_FACTORY.createCreateConstructorMatchingSuperFix(aClass)); - - return info; - } - - @Nullable - private static HighlightInfo checkAmbiguityOfImplicitConstructorCall(@NotNull PsiMethod[] constructors, - @NotNull TextRange range, - @NotNull PsiClass subClass, - @NotNull PsiClass superClass) { - Project project = subClass.getProject(); - PsiElement resolved = JavaResolveUtil.resolveImaginarySuperCallInThisPlace(subClass, project, superClass); - if (resolved != null) { - return null; - } - - // find two ambiguous var-args-only constructors - List varargConstructors = Arrays.stream(constructors) - .filter(constructor -> constructor.getParameterList().getParameters().length == 1) - .filter(constructor -> constructor.getParameterList().getParameters()[0].isVarArgs()) - .filter(constructor -> PsiResolveHelper.SERVICE.getInstance(project).isAccessible(constructor, subClass, subClass)) + PsiElement resolved = JavaResolveUtil.resolveImaginarySuperCallInThisPlace(aClass, aClass.getProject(), baseClass); + List constructorCandidates = (resolved != null ? Collections.singletonList((PsiMethod)resolved) + : Arrays.asList(constructors)) + .stream() + .filter(constructor -> { + PsiParameter[] parameters = constructor.getParameterList().getParameters(); + return (parameters.length == 0 || parameters.length == 1 && parameters[0].isVarArgs()) && + resolveHelper.isAccessible(constructor, aClass, null); + }) .limit(2).collect(Collectors.toList()); - //List varargConstructors = Arrays.stream(constructors) - // .map(constructor -> Pair.create(constructor, constructor.getParameterList().getParameters())) - // .filter(p -> p.second.length == 1 && p.second[0].isVarArgs() && PsiResolveHelper.SERVICE.getInstance(project).isAccessible(p.first, subClass, subClass)) - // .map(p -> p.first) - // .limit(2).collect(Collectors.toList()); - // - if (varargConstructors.size() == 2) { - final String m1 = PsiFormatUtil.formatMethod(varargConstructors.get(0), PsiSubstitutor.EMPTY, + if (constructorCandidates.size() >= 2) {// two ambiguous var-args-only constructors + final String m1 = PsiFormatUtil.formatMethod(constructorCandidates.get(0), PsiSubstitutor.EMPTY, PsiFormatUtilBase.SHOW_CONTAINING_CLASS | PsiFormatUtilBase.SHOW_NAME | PsiFormatUtilBase.SHOW_PARAMETERS, PsiFormatUtilBase.SHOW_TYPE); - final String m2 = PsiFormatUtil.formatMethod(varargConstructors.get(1), PsiSubstitutor.EMPTY, + final String m2 = PsiFormatUtil.formatMethod(constructorCandidates.get(1), PsiSubstitutor.EMPTY, PsiFormatUtilBase.SHOW_CONTAINING_CLASS | PsiFormatUtilBase.SHOW_NAME | PsiFormatUtilBase.SHOW_PARAMETERS, @@ -600,7 +554,27 @@ public class HighlightClassUtil { .descriptionAndTooltip(JavaErrorMessages.message("ambiguous.method.call", m1, m2)) .create(); } - return null; + + if (!constructorCandidates.isEmpty()) { + PsiMethod constructor = constructorCandidates.get(0); + String description = checkDefaultConstructorThrowsException(constructor, handledExceptions); + if (description != null) { + HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(range).descriptionAndTooltip(description).create(); + QuickFixAction.registerQuickFixAction(info, QUICK_FIX_FACTORY.createCreateConstructorMatchingSuperFix(aClass)); + return info; + } + if (refCountHolder != null) { + refCountHolder.registerLocallyReferenced(constructor); + } + return null; + } + + String description = JavaErrorMessages.message("no.default.constructor.available", HighlightUtil.formatClass(baseClass)); + + HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(range).descriptionAndTooltip(description).create(); + QuickFixAction.registerQuickFixAction(info, QUICK_FIX_FACTORY.createCreateConstructorMatchingSuperFix(aClass)); + + return info; } @Nullable diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting6/SpeculateOnUnhandledExceptionsOverResolvedConstructorOnly.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting6/SpeculateOnUnhandledExceptionsOverResolvedConstructorOnly.java new file mode 100644 index 000000000000..7025fed586c2 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting6/SpeculateOnUnhandledExceptionsOverResolvedConstructorOnly.java @@ -0,0 +1,17 @@ +class Base { + + String[] items; + + public Base(String ... items) throws Exception { + this.items = items; + } + + public Base() { + this.items = null; + } +} + +class Derived extends Base { + public Derived() {} +} +class Derived1 extends Base {} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk6Test.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk6Test.java index cf7913720285..f18197b599ed 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk6Test.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk6Test.java @@ -86,4 +86,7 @@ public class LightAdvHighlightingJdk6Test extends LightDaemonAnalyzerTestCase { public void testAmbiguityChecksForImplicitSuperConstructorCall() { doTest(false, false); } + + public void testSpeculateOnUnhandledExceptionsOverResolvedConstructorOnly() throws Exception { + } }