Java: better error message when there are more arguments than parameters (IDEA-336129)

GitOrigin-RevId: a17a5f0f3878b9baf211737a614d1aa1a5103d31
This commit is contained in:
Bas Leijdekkers
2024-06-26 17:30:09 +02:00
committed by intellij-monorepo-bot
parent ed3ae46a60
commit 6916b6b005
22 changed files with 42 additions and 30 deletions

View File

@@ -565,7 +565,7 @@ generate.members.position.at.the.end.of.class=At the end of class
navigate.to.overridden.methods.title=Overriding methods of {0}
subclasses.search.progress.title=Searching for overridden methods
progress.title.searching.for.overridden.methods=Searching for overridden methods
arguments.count.mismatch=Expected {0} arguments but found {1}
arguments.count.mismatch=Expected {0, choice, 0#no arguments|1#1 argument|1<{0} arguments} but found {1}
inspection.message.nullable.method.implements.non.null.method=Nullable method ''{0}'' from ''{1}'' implements non-null method from ''{2}''
inspection.message.non.annotated.method.implements.non.null.method=Non-annotated method ''{0}'' from ''{1}'' implements non-null method from ''{2}''
inspection.message.non.null.parameter.should.not.override.nullable.parameter=Non-null parameter ''{0}'' in method ''{1}'' from ''{2}'' should not override nullable parameter from ''{3}''

View File

@@ -580,6 +580,7 @@ public final class HighlightMethodUtil {
if ((parameters.length == 0 || !parameters[parameters.length - 1].isVarArgs()) &&
parameters.length != expressions.length) {
toolTip = createMismatchedArgumentCountTooltip(parameters.length, expressions.length);
description = JavaAnalysisBundle.message("arguments.count.mismatch", parameters.length, expressions.length);
}
else if (mismatchedExpressions.isEmpty()) {
if (IncompleteModelUtil.isIncompleteModel(list)) return null;
@@ -629,6 +630,7 @@ public final class HighlightMethodUtil {
PsiType argType = wrongArg != null ? wrongArg.getType() : null;
if (argType != null) {
int idx = ArrayUtil.find(expressions, wrongArg);
if (idx > parameters.length - 1 && !parameters[parameters.length - 1].isVarArgs()) return null;
PsiType paramType = candidateInfo.getSubstitutor().substitute(PsiTypesUtil.getParameterType(parameters, idx, candidateInfo.isVarargs()));
String errorMessage = candidateInfo.getInferenceErrorMessage();
HtmlChunk reason = getTypeMismatchErrorHtml(errorMessage);
@@ -838,8 +840,7 @@ public final class HighlightMethodUtil {
boolean varargs) {
List<PsiExpression> result = new ArrayList<>();
for (int i = 0; i < Math.max(parameters.length, expressions.length); i++) {
if (parameters.length == 0 ||
!assignmentCompatible(i, parameters, expressions, substitutor, varargs)) {
if (parameters.length == 0 || !assignmentCompatible(i, parameters, expressions, substitutor, varargs)) {
result.add(i < expressions.length ? expressions[i] : null);
}
}
@@ -1200,8 +1201,7 @@ public final class HighlightMethodUtil {
@NotNull
private static @NlsContexts.Tooltip String createMismatchedArgumentCountTooltip(int expected, int actual) {
return HtmlChunk.text(JavaAnalysisBundle.message("arguments.count.mismatch", expected, actual))
.wrapWith("html").toString();
return HtmlChunk.text(JavaAnalysisBundle.message("arguments.count.mismatch", expected, actual)).wrapWith("html").toString();
}
@NotNull
@@ -1837,8 +1837,7 @@ public final class HighlightMethodUtil {
}
PsiJavaCodeReferenceElement classReference = expression.getClassOrAnonymousClassReference();
checkConstructorCall(project, typeResult, expression, type, classReference, javaSdkVersion, expression.getArgumentList(),
errorSink);
checkConstructorCall(project, typeResult, expression, type, classReference, javaSdkVersion, expression.getArgumentList(), errorSink);
}
static void checkAmbiguousConstructorCall(@NotNull Project project, PsiJavaCodeReferenceElement ref,

View File

@@ -27,5 +27,5 @@ class Base {
class Derived extends Base {
final static Object o1 = <error descr="Non-static method 'getObject()' cannot be referenced from a static context">getObject</error>(null);
final Object o2 = getObject<error descr="'getObject()' in 'P1.Base' cannot be applied to '(null)'">(null)</error>;
final Object o2 = getObject<error descr="Expected no arguments but found 1">(null)</error>;
}

View File

@@ -0,0 +1,12 @@
import java.util.function.Consumer;
class WrongNumberOfArguments {
void fun1(String str, Consumer<String> onFinish) { }
void getStr(String asd) { }
void asd() {
int asd = 1;
fun1("text", s -> getStr(s), <error descr="Expected 2 arguments but found 3">asd</error>);
}
}

View File

@@ -222,8 +222,8 @@ class NestedEnums {
}
enum EnumWithoutExpectedArguments {
<error descr="'EnumWithoutExpectedArguments(int)' in 'EnumWithoutExpectedArguments' cannot be applied to '()'">ONE</error>, //comment
<error descr="'EnumWithoutExpectedArguments(int)' in 'EnumWithoutExpectedArguments' cannot be applied to '()'">TWO</error>
<error descr="Expected 1 argument but found 0">ONE</error>, //comment
<error descr="Expected 1 argument but found 0">TWO</error>
;
EnumWithoutExpectedArguments(int a) {}
}

View File

@@ -13,6 +13,6 @@ class Test2 {}
class Test {
public void test(TestIF<?> testIF) {
testIF.run<error descr="'run(capture<?>)' in 'TestIF' cannot be applied to '()'">()</error>;
testIF.run<error descr="Expected 1 argument but found 0">()</error>;
}
}

View File

@@ -12,7 +12,7 @@ class Main {
<T extends Serializable> void m(Object[] obj) {
List<?> r1 = foo(null);
List<? extends Serializable> r2 = foo(null);
List<? super String> r3 = foo<error descr="'foo(? super java.lang.String & java.lang.Runnable)' in 'Main' cannot be applied to '()'">( )</error>;
List<? super String> r3 = foo<error descr="Expected 1 argument but found 0">( )</error>;
List<? extends Runnable> r4 = foo(null);
}
}

View File

@@ -1,6 +1,6 @@
class Test {
private <<error descr="Cyclic inheritance involving 'S'"></error>S extends K, K extends S> S b(S s) {
if (true) return b <error descr="'b(S)' in 'Test' cannot be applied to '()'">()</error>;
if (true) return b <error descr="Expected 1 argument but found 0">()</error>;
<error descr="Missing return statement">}</error>
}

View File

@@ -1,7 +1,7 @@
class Test{
void test() {
B b = new B<error descr="'B(java.lang.String, java.lang.String)' in 'Test.B' cannot be applied to '(java.lang.String)'">(true == false ? "bar" : null)</error>;
B b = new B<error descr="Expected 2 arguments but found 1">(true == false ? "bar" : null)</error>;
}
class B {

View File

@@ -13,6 +13,6 @@ class Test2 {}
class Test {
public void test(TestIF<?> testIF) {
testIF.run<error descr="'run(capture<?>)' in 'TestIF' cannot be applied to '()'">()</error>;
testIF.run<error descr="Expected 1 argument but found 0">()</error>;
}
}

View File

@@ -3,7 +3,7 @@ import java.util.function.UnaryOperator;
class Test<T> {
private void example() {
update(x -> x.flatMap<error descr="'flatMap()' in 'Test' cannot be applied to '(<lambda expression>)'">(y -> getEmpty())</error>);
update(x -> x.flatMap<error descr="Expected no arguments but found 1">(y -> getEmpty())</error>);
}
private <J> Test<J> flatMap() {

View File

@@ -5,7 +5,7 @@ class R<T> {
}
public static void main(String[] args) {
test(new R<>.O<error descr="'O(java.lang.Object)' in 'R.O' cannot be applied to '()'">()</error>);
test(new R<>.O<error descr="Expected 1 argument but found 0">()</error>);
}
private static void test(R.O o) { }

View File

@@ -1,6 +1,6 @@
class A<R>{
A(R value) {}
public static void main(String[] args) {
A<Integer> a = new A<><error descr="'A(R)' in 'A' cannot be applied to '(java.lang.String, int)'" tooltip="Expected 1 arguments but found 2">("hi", 1)</error>;
A<Integer> a = new A<><error descr="Expected 1 argument but found 2" tooltip="Expected 1 argument but found 2">("hi", 1)</error>;
}
}

View File

@@ -8,8 +8,8 @@ interface TypeB extends TypeA {
class Test {
void foo(final TypeB typeB) {
typeB.test<error descr="'test(java.lang.String[])' in 'TypeB' cannot be applied to '(java.lang.String, java.lang.String)'">("a", "b")</error>;
typeB.test<error descr="Expected 1 argument but found 2">("a", "b")</error>;
typeB.test<error descr="'test(java.lang.String[])' in 'TypeB' cannot be applied to '(java.lang.String)'">("a")</error>;
typeB.test<error descr="'test(java.lang.String[])' in 'TypeB' cannot be applied to '()'">()</error>;
typeB.test<error descr="Expected 1 argument but found 0">()</error>;
}
}

View File

@@ -7,8 +7,8 @@ class Test {
varargs(1);
varargs(1, "");
varargs(1, "", "");
usage<error descr="'usage(java.lang.String)' in 'Test' cannot be applied to '()'">()</error>;
usage<error descr="Expected 1 argument but found 0">()</error>;
usage("");
usage<error descr="'usage(java.lang.String)' in 'Test' cannot be applied to '(java.lang.String, java.lang.String)'">("", "")</error>;
usage<error descr="Expected 1 argument but found 2">("", "")</error>;
}
}

View File

@@ -5,7 +5,7 @@ interface ToStringBug {
class Inner implements ToStringBug {
{
toString<error descr="'toString()' in 'java.lang.Object' cannot be applied to '(java.lang.String)'">( "x")</error>;
toString<error descr="Expected no arguments but found 1">( "x")</error>;
}
}
}

View File

@@ -4,7 +4,7 @@ import static java.util.Objects.toString;
class Foo {
String go() {
return toString<error descr="'toString()' in 'Foo' cannot be applied to '(java.lang.String)'">("foo")</error>;
return toString<error descr="Expected no arguments but found 1">("foo")</error>;
}
public String toString() {

View File

@@ -9,7 +9,7 @@ public class EqualsCalled {
void one() {
E.A.<warning descr="'equals()' called on enum value">equals</warning>(E.C);
E.B.<warning descr="'equals()' called on enum value">equals</warning>(new Object());
E.C.equals<error descr="'equals(java.lang.Object)' in 'java.lang.Enum' cannot be applied to '()'">()</error>;
E.C.equals<error descr="Expected 1 argument but found 0">()</error>;
final Object A = new Object();
A.equals(1);
}

View File

@@ -4,6 +4,6 @@ public class Npe {
// Do something
}
o.<warning descr="Method invocation 'equals' may produce 'NullPointerException'">equals</warning><error descr="'equals(java.lang.Object)' in 'java.lang.Object' cannot be applied to '()'">()</error>;
o.<warning descr="Method invocation 'equals' may produce 'NullPointerException'">equals</warning><error descr="Expected 1 argument but found 0">()</error>;
}
}

View File

@@ -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-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.java.codeInsight.daemon;
import com.intellij.codeInsight.daemon.LightDaemonAnalyzerTestCase;
@@ -34,6 +34,7 @@ public class LightAdvHighlightingJdk8Test extends LightDaemonAnalyzerTestCase {
public void testLambdaExpressions() { doTest(false, true); }
public void testUnsupportedFeatures() { doTest(false, false); }
public void testModulesNotSupported() { doTest(false, false); }
public void testWrongNumberOfArguments() { doTest(false, false); }
public void testTooManyVarargsPolyArguments() {
doTest(true, false);

View File

@@ -1,4 +1,4 @@
// 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.
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.plugins.groovy.transformations
import com.intellij.testFramework.LightProjectDescriptor
@@ -78,7 +78,7 @@ class Pojo extends Pogo {
void foo() {
Pogo pogo = new Pogo();
<error descr="Unhandled exception: java.lang.CloneNotSupportedException">cloneOrCopyMembers</error>(pogo);
cloneOrCopyMembers<error descr="'cloneOrCopyMembers(Pogo)' in 'Pogo' cannot be applied to '()'">()</error>;
cloneOrCopyMembers<error descr="Expected 1 argument but found 0">()</error>;
}
}
'''

View File

@@ -11,7 +11,7 @@ public class ClassWithJavaConstructor {
public static class B extends A {
public B() {
super<error descr="'A(int, java.lang.String)' in 'ClassWithJavaConstructor.A' cannot be applied to '()'">()</error>;
super<error descr="Expected 2 arguments but found 0">()</error>;
}
public B(int i) {