summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugene Burmako <xeno.by@gmail.com>2014-01-27 15:19:07 +0300
committerEugene Burmako <xeno.by@gmail.com>2014-02-12 14:50:17 +0100
commit7c06c9d7f6a12c2b13c83b195fffa30c5a4ec3ce (patch)
tree6b99b01a0de8330174afef9ae615651e7ffcecc8
parent30174f9453a44845156f4abca0cd6317da3e27cc (diff)
downloadscala-7c06c9d7f6a12c2b13c83b195fffa30c5a4ec3ce.tar.gz
scala-7c06c9d7f6a12c2b13c83b195fffa30c5a4ec3ce.tar.bz2
scala-7c06c9d7f6a12c2b13c83b195fffa30c5a4ec3ce.zip
SI-6733 LOCAL, isLocal, and private[this]
Due to an unfortunate name collision, internal.Symbols#Symbol.isLocal means something different from Flag.LOCAL. Therefore api.Symbols#Symbol.isLocal was directly violating its documentation. Since we can’t give api#isLocal an implementation different from internal#isLocal, we have to rename, and for that occasion I have come up with names api#isPrivateThis and api#isProtectedThis, which in my opinion suits the public API better than internal#isPrivateLocal and internal#isProtectedLocal. Given the extraordinary circumstances of having no way for api#isLocal to work correctly, I’m forced to remove api#isLocal without a deprecation notice, exercising our right to break experimental APIs, something that we have never done before for reflection or macros. This is sad.
-rw-r--r--src/reflect/scala/reflect/api/FlagSets.scala4
-rw-r--r--src/reflect/scala/reflect/api/Symbols.scala21
-rw-r--r--src/reflect/scala/reflect/internal/Symbols.scala2
-rw-r--r--test/files/run/t6733.check27
-rw-r--r--test/files/run/t6733.scala35
5 files changed, 79 insertions, 10 deletions
diff --git a/src/reflect/scala/reflect/api/FlagSets.scala b/src/reflect/scala/reflect/api/FlagSets.scala
index 44c5f78a48..f36056cc3b 100644
--- a/src/reflect/scala/reflect/api/FlagSets.scala
+++ b/src/reflect/scala/reflect/api/FlagSets.scala
@@ -131,8 +131,8 @@ trait FlagSets { self: Universe =>
/** Flag indicating that tree has `protected` modifier set */
val PROTECTED: FlagSet
- /** Flag indicating that tree represents a member local to current class
- * (i.e. private[this] or protected[this].
+ /** Flag indicating that tree represents a member local to current class,
+ * i.e. private[this] or protected[this].
* This requires having either PRIVATE or PROTECTED set as well.
*/
val LOCAL: FlagSet
diff --git a/src/reflect/scala/reflect/api/Symbols.scala b/src/reflect/scala/reflect/api/Symbols.scala
index 1c3ae77d45..15d4fae59b 100644
--- a/src/reflect/scala/reflect/api/Symbols.scala
+++ b/src/reflect/scala/reflect/api/Symbols.scala
@@ -380,16 +380,13 @@ trait Symbols { self: Universe =>
*/
def isImplementationArtifact: Boolean
- /** Does this symbol represent a local declaration or definition?
- *
- * If yes, either `isPrivate` or `isProtected` are guaranteed to be true.
- * Local symbols can only be accessed from the same object instance.
- *
- * If yes, `privateWithin` might tell more about this symbol's visibility scope.
+ /** Does this symbol represent a declaration or definition written in a source file as `private[this]`
+ * or generated in tree/symbol form with the combination of flags LOCAL and PRIVATE?
+ * If yes, `isPrivate` is guaranteed to be true,
*
* @group Tests
*/
- def isLocal: Boolean
+ def isPrivateThis: Boolean
/** Does this symbol represent a private declaration or definition?
* If yes, `privateWithin` might tell more about this symbol's visibility scope.
@@ -398,6 +395,14 @@ trait Symbols { self: Universe =>
*/
def isPrivate: Boolean
+ /** Does this symbol represent a declaration or definition written in a source file as `protected[this]`
+ * or generated in tree/symbol form with the combination of flags LOCAL and PROTECTED?
+ * If yes, `isProtected` is guaranteed to be true,
+ *
+ * @group Tests
+ */
+ def isProtectedThis: Boolean
+
/** Does this symbol represent a protected declaration or definition?
* If yes, `privateWithin` might tell more about this symbol's visibility scope.
*
@@ -412,7 +417,7 @@ trait Symbols { self: Universe =>
def isPublic: Boolean
/**
- * Set when symbol has a modifier of the form private[X], NoSymbol otherwise.
+ * Set when symbol has a modifier of the form private[X] or protected[X], NoSymbol otherwise.
*
* Access level encoding: there are three scala flags (PRIVATE, PROTECTED,
* and LOCAL) which combine with value privateWithin (the "foo" in private[foo])
diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala
index 593c5e314a..6fedb74f86 100644
--- a/src/reflect/scala/reflect/internal/Symbols.scala
+++ b/src/reflect/scala/reflect/internal/Symbols.scala
@@ -90,6 +90,8 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
def isVal: Boolean = isTerm && !isModule && !isMethod && !isMutable
def isVar: Boolean = isTerm && !isModule && !isMethod && !isLazy && isMutable
def isAbstract: Boolean = isAbstractClass || isDeferred || isAbstractType
+ def isPrivateThis = (this hasFlag PRIVATE) && (this hasFlag LOCAL)
+ def isProtectedThis = (this hasFlag PROTECTED) && (this hasFlag LOCAL)
def newNestedSymbol(name: Name, pos: Position, newFlags: Long, isClass: Boolean): Symbol = name match {
case n: TermName => newTermSymbol(n, pos, newFlags)
diff --git a/test/files/run/t6733.check b/test/files/run/t6733.check
new file mode 100644
index 0000000000..aeb595fbfd
--- /dev/null
+++ b/test/files/run/t6733.check
@@ -0,0 +1,27 @@
+method $init$: isPrivateThis = false, isProtectedThis = false
+value pri1a: isPrivateThis = true, isProtectedThis = false
+method pri2a: isPrivateThis = true, isProtectedThis = false
+variable pri3a: isPrivateThis = true, isProtectedThis = false
+value pri4a: isPrivateThis = true, isProtectedThis = false
+lazy value pri4a: isPrivateThis = true, isProtectedThis = false
+type Pri5a: isPrivateThis = true, isProtectedThis = false
+class Pri6: isPrivateThis = true, isProtectedThis = false
+trait Pri7: isPrivateThis = true, isProtectedThis = false
+object Pri8: isPrivateThis = true, isProtectedThis = false
+value pro1a: isPrivateThis = false, isProtectedThis = true
+value pro1a: isPrivateThis = true, isProtectedThis = false
+value pro1b: isPrivateThis = false, isProtectedThis = true
+method pro2a: isPrivateThis = false, isProtectedThis = true
+method pro2b: isPrivateThis = false, isProtectedThis = true
+method pro3a: isPrivateThis = false, isProtectedThis = true
+method pro3a_=: isPrivateThis = false, isProtectedThis = true
+variable pro3a: isPrivateThis = true, isProtectedThis = false
+method pro3b: isPrivateThis = false, isProtectedThis = true
+method pro3b_=: isPrivateThis = false, isProtectedThis = true
+value pro4a: isPrivateThis = false, isProtectedThis = true
+lazy value pro4a: isPrivateThis = true, isProtectedThis = false
+type Pro5a: isPrivateThis = false, isProtectedThis = true
+type Pro5b: isPrivateThis = false, isProtectedThis = true
+class Pro6: isPrivateThis = false, isProtectedThis = true
+trait Pro7: isPrivateThis = false, isProtectedThis = true
+object Pro8: isPrivateThis = false, isProtectedThis = true
diff --git a/test/files/run/t6733.scala b/test/files/run/t6733.scala
new file mode 100644
index 0000000000..525b276811
--- /dev/null
+++ b/test/files/run/t6733.scala
@@ -0,0 +1,35 @@
+import scala.reflect.runtime.universe._
+
+trait Foo {
+ private[this] val pri1a = 0
+ // private[this] val pri1b: Int
+ private[this] def pri2a = 1
+ // private[this] def pri2b: Int
+ private[this] var pri3a = 0
+ // private[this] var pri3b: Int
+ private[this] lazy val pri4a = 0
+ // private[this] lazy val pri4b: Int
+ private[this] type Pri5a = Int
+ // private[this] type Pri5b <: Int
+ private[this] class Pri6
+ private[this] trait Pri7
+ private[this] object Pri8
+
+ protected[this] val pro1a = 0
+ protected[this] val pro1b: Int
+ protected[this] def pro2a = 1
+ protected[this] def pro2b: Int
+ protected[this] var pro3a = 0
+ protected[this] var pro3b: Int
+ protected[this] lazy val pro4a = 0
+ // protected[this] lazy val pro4b: Int
+ protected[this] type Pro5a = Int
+ protected[this] type Pro5b <: Int
+ protected[this] class Pro6
+ protected[this] trait Pro7
+ protected[this] object Pro8
+}
+
+object Test extends App {
+ typeOf[Foo].declarations.sorted.foreach(m => println(s"$m: isPrivateThis = ${m.isPrivateThis}, isProtectedThis = ${m.isProtectedThis}"))
+} \ No newline at end of file