diff options
author | Som Snytt <som.snytt@gmail.com> | 2016-05-04 15:52:01 -0700 |
---|---|---|
committer | Som Snytt <som.snytt@gmail.com> | 2016-05-13 08:36:01 -0700 |
commit | a6d5eb507bbeac2055a224a15fd76e7f9425520b (patch) | |
tree | 9ef73469b5a29d85be211502f8328dc5fdb97155 /src | |
parent | 9e30bee0c9363f6cf36a7b65ddbaaa225b57d6a9 (diff) | |
download | scala-a6d5eb507bbeac2055a224a15fd76e7f9425520b.tar.gz scala-a6d5eb507bbeac2055a224a15fd76e7f9425520b.tar.bz2 scala-a6d5eb507bbeac2055a224a15fd76e7f9425520b.zip |
SI-8667 Improve too-many-args message
Use removeNames to help diagnose the application.
Supplement the error message with how many extra
args and any other residual assignments that the
user might have thought was a properly named arg.
The error message is gradual: succinct for short
arg lists, more verbose for longer applications.
Very long arg lists are probably generated, so
that message is the least colloquial.
Diffstat (limited to 'src')
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala | 31 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Typers.scala | 10 |
2 files changed, 36 insertions, 5 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala index e190b57017..e1055144f8 100644 --- a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala +++ b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala @@ -538,8 +538,33 @@ trait ContextErrors { def NamedAndDefaultArgumentsNotSupportedForMacros(tree: Tree, fun: Tree) = NormalTypeError(tree, "macro applications do not support named and/or default arguments") - def TooManyArgsNamesDefaultsError(tree: Tree, fun: Tree) = - NormalTypeError(tree, "too many arguments for "+treeSymTypeMsg(fun)) + def TooManyArgsNamesDefaultsError(tree: Tree, fun: Tree, expected: Int, supplied: Int, unknowns: List[Name]) = { + val msg = { + val badappl = { + val excess = supplied - expected + val target = treeSymTypeMsg(fun) + + if (expected == 0) s"no arguments allowed for nullary $target" + else if (excess < 3 && expected <= 5) s"too many arguments ($supplied) for $target" + else if (expected > 10) s"$supplied arguments but expected $expected for $target" + else { + val oneOf = + if (excess == 1) "one more argument" + else if (excess > 0) s"$excess more arguments" + else "too many arguments" + s"$oneOf than can be applied to $target" + } + } + val suppl = + unknowns.size match { + case 0 => "" + case 1 => s"\nNote that '${unknowns.head}' is not a parameter name of the invoked method." + case _ => unknowns.mkString("\nNote that '", "', '", "' are not parameter names of the invoked method.") + } + s"${badappl}${suppl}" + } + NormalTypeError(tree, msg) + } // can it still happen? see test case neg/overloaded-unapply.scala def OverloadedUnapplyError(tree: Tree) = @@ -551,7 +576,7 @@ trait ContextErrors { def MultipleVarargError(tree: Tree) = NormalTypeError(tree, "when using named arguments, the vararg parameter has to be specified exactly once") - def ModuleUsingCompanionClassDefaultArgsErrror(tree: Tree) = + def ModuleUsingCompanionClassDefaultArgsError(tree: Tree) = NormalTypeError(tree, "module extending its companion class cannot use default constructor arguments") def NotEnoughArgsError(tree: Tree, fun: Tree, missing: List[Symbol]) = { diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 329ce8c23b..1d24d8c232 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -3330,7 +3330,13 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper // #2064 duplErrorTree(WrongNumberOfArgsError(tree, fun)) } else if (lencmp > 0) { - tryTupleApply orElse duplErrorTree(TooManyArgsNamesDefaultsError(tree, fun)) + tryTupleApply orElse duplErrorTree { + val (namelessArgs, _) = removeNames(Typer.this)(args, params) + val wrongs = (namelessArgs zip args) collect { + case (_: Assign, AssignOrNamedArg(Ident(name), _)) => name + } + TooManyArgsNamesDefaultsError(tree, fun, expected = formals.size, supplied = args.size, wrongs) + } } else if (lencmp == 0) { // we don't need defaults. names were used, so this application is transformed // into a block (@see transformNamedApplication in NamesDefaults) @@ -3394,7 +3400,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper val lencmp2 = compareLengths(allArgs, formals) if (!sameLength(allArgs, args) && callToCompanionConstr(context, funSym)) { - duplErrorTree(ModuleUsingCompanionClassDefaultArgsErrror(tree)) + duplErrorTree(ModuleUsingCompanionClassDefaultArgsError(tree)) } else if (lencmp2 > 0) { removeNames(Typer.this)(allArgs, params) // #3818 duplErrTree |