summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSom Snytt <som.snytt@gmail.com>2013-09-29 13:46:02 -0700
committerSom Snytt <som.snytt@gmail.com>2015-02-08 22:25:43 -0800
commit40bef79974de3ed00f0173a65fdf7aa19170900e (patch)
treedfb108e9332ec522ea60efb4fac4b117b2674f85
parent178e8df9b6a91375a6162721a0cbc2d90bcc7451 (diff)
downloadscala-40bef79974de3ed00f0173a65fdf7aa19170900e.tar.gz
scala-40bef79974de3ed00f0173a65fdf7aa19170900e.tar.bz2
scala-40bef79974de3ed00f0173a65fdf7aa19170900e.zip
SI-9140 Allow deprecating current parameter name
Allow deprecatedName to specify the name of the parameter it qualifies. This tells the user, That's my name, don't wear it out. I.e., don't use my name when calling me. Use cases include: the name will change; normally a name should be provided for a boolean, but not in this case (perhaps because there is only one argument). ``` scala> def f(@deprecatedName('foo) bar: String) = bar.reverse f: (bar: String)String scala> f(foo = "hello") <console>:9: warning: the parameter name foo has been deprecated. Use bar instead. f(foo = "hello") ^ res0: String = olleh scala> def g(@deprecatedName('foo) foo: String) = foo.reverse g: (foo: String)String scala> g(foo = "hello") <console>:9: warning: naming parameter foo has been deprecated. g(foo = "hello") ^ res1: String = olleh ```
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala24
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala2
-rw-r--r--test/files/neg/names-defaults-neg.check45
-rw-r--r--test/files/neg/names-defaults-neg.scala2
4 files changed, 43 insertions, 30 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
index 50f658f68d..119b415d51 100644
--- a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
@@ -9,6 +9,7 @@ package typechecker
import symtab.Flags._
import scala.collection.mutable
import scala.reflect.ClassTag
+import PartialFunction.{ cond => when }
/**
* @author Lukas Rytz
@@ -552,15 +553,22 @@ trait NamesDefaults { self: Analyzer =>
val namelessArgs = mapWithIndex(args) { (arg, argIndex) =>
arg match {
case arg @ AssignOrNamedArg(Ident(name), rhs) =>
- def matchesName(param: Symbol) = !param.isSynthetic && (
- (param.name == name) || (param.deprecatedParamName match {
- case Some(`name`) =>
- context0.deprecationWarning(arg.pos, param,
+ def matchesName(param: Symbol) = {
+ def checkDeprecation = when(param.deprecatedParamName) { case Some(`name`) => true }
+ def checkName = {
+ val res = param.name == name
+ if (res && checkDeprecation)
+ context0.deprecationWarning(arg.pos, param, s"naming parameter $name has been deprecated.")
+ res
+ }
+ def checkAltName = {
+ val res = checkDeprecation
+ if (res) context0.deprecationWarning(arg.pos, param,
s"the parameter name $name has been deprecated. Use ${param.name} instead.")
- true
- case _ => false
- })
- )
+ res
+ }
+ !param.isSynthetic && (checkName || checkAltName)
+ }
val paramPos = params indexWhere matchesName
if (paramPos == -1) {
if (positionalAllowed) {
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 2dd79075ee..baa09bb14e 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -2214,7 +2214,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
val allParams = meth.paramss.flatten
for (p <- allParams) {
for (n <- p.deprecatedParamName) {
- if (allParams.exists(p1 => p1.name == n || (p != p1 && p1.deprecatedParamName.exists(_ == n))))
+ if (allParams.exists(p1 => p != p1 && (p1.name == n || p1.deprecatedParamName.exists(_ == n))))
DeprecatedParamNameError(p, n)
}
}
diff --git a/test/files/neg/names-defaults-neg.check b/test/files/neg/names-defaults-neg.check
index 20ddd55f1f..249d227e93 100644
--- a/test/files/neg/names-defaults-neg.check
+++ b/test/files/neg/names-defaults-neg.check
@@ -118,68 +118,71 @@ names-defaults-neg.scala:93: warning: the parameter name y has been deprecated.
names-defaults-neg.scala:93: error: parameter 'b' is already specified at parameter position 1
deprNam3(y = 10, b = 2)
^
-names-defaults-neg.scala:98: error: unknown parameter name: m
+names-defaults-neg.scala:96: warning: naming parameter deprNam4Arg has been deprecated.
+ deprNam4(deprNam4Arg = null)
+ ^
+names-defaults-neg.scala:100: error: unknown parameter name: m
f3818(y = 1, m = 1)
^
-names-defaults-neg.scala:131: error: reference to var2 is ambiguous; it is both a method parameter and a variable in scope.
+names-defaults-neg.scala:133: error: reference to var2 is ambiguous; it is both a method parameter and a variable in scope.
delay(var2 = 40)
^
-names-defaults-neg.scala:134: error: missing parameter type for expanded function ((x$1) => a = x$1)
+names-defaults-neg.scala:136: error: missing parameter type for expanded function ((x$1) => a = x$1)
val taf2: Int => Unit = testAnnFun(a = _, b = get("+"))
^
-names-defaults-neg.scala:134: error: not found: value a
+names-defaults-neg.scala:136: error: not found: value a
val taf2: Int => Unit = testAnnFun(a = _, b = get("+"))
^
-names-defaults-neg.scala:134: error: not found: value get
+names-defaults-neg.scala:136: error: not found: value get
val taf2: Int => Unit = testAnnFun(a = _, b = get("+"))
^
-names-defaults-neg.scala:135: error: parameter 'a' is already specified at parameter position 1
+names-defaults-neg.scala:137: error: parameter 'a' is already specified at parameter position 1
val taf3 = testAnnFun(b = _: String, a = get(8))
^
-names-defaults-neg.scala:136: error: missing parameter type for expanded function ((x$3) => testAnnFun(x$3, ((x$4) => b = x$4)))
+names-defaults-neg.scala:138: error: missing parameter type for expanded function ((x$3) => testAnnFun(x$3, ((x$4) => b = x$4)))
val taf4: (Int, String) => Unit = testAnnFun(_, b = _)
^
-names-defaults-neg.scala:136: error: missing parameter type for expanded function ((x$4) => b = x$4)
+names-defaults-neg.scala:138: error: missing parameter type for expanded function ((x$4) => b = x$4)
val taf4: (Int, String) => Unit = testAnnFun(_, b = _)
^
-names-defaults-neg.scala:136: error: not found: value b
+names-defaults-neg.scala:138: error: not found: value b
val taf4: (Int, String) => Unit = testAnnFun(_, b = _)
^
-names-defaults-neg.scala:144: error: variable definition needs type because 'x' is used as a named argument in its body.
+names-defaults-neg.scala:146: error: variable definition needs type because 'x' is used as a named argument in its body.
def t3 { var x = t.f(x = 1) }
^
-names-defaults-neg.scala:147: error: variable definition needs type because 'x' is used as a named argument in its body.
+names-defaults-neg.scala:149: error: variable definition needs type because 'x' is used as a named argument in its body.
object t6 { var x = t.f(x = 1) }
^
-names-defaults-neg.scala:147: warning: type-checking the invocation of method f checks if the named argument expression 'x = ...' is a valid assignment
+names-defaults-neg.scala:149: warning: type-checking the invocation of method f checks if the named argument expression 'x = ...' is a valid assignment
in the current scope. The resulting type inference error (see above) can be fixed by providing an explicit type in the local definition for x.
object t6 { var x = t.f(x = 1) }
^
-names-defaults-neg.scala:150: error: variable definition needs type because 'x' is used as a named argument in its body.
+names-defaults-neg.scala:152: error: variable definition needs type because 'x' is used as a named argument in its body.
class t9 { var x = t.f(x = 1) }
^
-names-defaults-neg.scala:150: warning: type-checking the invocation of method f checks if the named argument expression 'x = ...' is a valid assignment
+names-defaults-neg.scala:152: warning: type-checking the invocation of method f checks if the named argument expression 'x = ...' is a valid assignment
in the current scope. The resulting type inference error (see above) can be fixed by providing an explicit type in the local definition for x.
class t9 { var x = t.f(x = 1) }
^
-names-defaults-neg.scala:164: error: variable definition needs type because 'x' is used as a named argument in its body.
+names-defaults-neg.scala:166: error: variable definition needs type because 'x' is used as a named argument in its body.
def u3 { var x = u.f(x = 1) }
^
-names-defaults-neg.scala:167: error: variable definition needs type because 'x' is used as a named argument in its body.
+names-defaults-neg.scala:169: error: variable definition needs type because 'x' is used as a named argument in its body.
def u6 { var x = u.f(x = "32") }
^
-names-defaults-neg.scala:170: error: reference to x is ambiguous; it is both a method parameter and a variable in scope.
+names-defaults-neg.scala:172: error: reference to x is ambiguous; it is both a method parameter and a variable in scope.
def u9 { var x: Int = u.f(x = 1) }
^
-names-defaults-neg.scala:177: error: variable definition needs type because 'x' is used as a named argument in its body.
+names-defaults-neg.scala:179: error: variable definition needs type because 'x' is used as a named argument in its body.
class u15 { var x = u.f(x = 1) }
^
-names-defaults-neg.scala:177: warning: type-checking the invocation of method f checks if the named argument expression 'x = ...' is a valid assignment
+names-defaults-neg.scala:179: warning: type-checking the invocation of method f checks if the named argument expression 'x = ...' is a valid assignment
in the current scope. The resulting type inference error (see above) can be fixed by providing an explicit type in the local definition for x.
class u15 { var x = u.f(x = 1) }
^
-names-defaults-neg.scala:180: error: reference to x is ambiguous; it is both a method parameter and a variable in scope.
+names-defaults-neg.scala:182: error: reference to x is ambiguous; it is both a method parameter and a variable in scope.
class u18 { var x: Int = u.f(x = 1) }
^
-four warnings found
+5 warnings found
46 errors found
diff --git a/test/files/neg/names-defaults-neg.scala b/test/files/neg/names-defaults-neg.scala
index 042f73708c..d11c9910a1 100644
--- a/test/files/neg/names-defaults-neg.scala
+++ b/test/files/neg/names-defaults-neg.scala
@@ -92,6 +92,8 @@ object Test extends App {
def deprNam3(@deprecatedName('x) a: Int, @deprecatedName('y) b: Int) = a + b
deprNam3(y = 10, b = 2)
+ def deprNam4(@deprecatedName('deprNam4Arg) deprNam4Arg: String) = 0
+ deprNam4(deprNam4Arg = null)
// t3818
def f3818(x: Int = 1, y: Int, z: Int = 1) = 0