summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/reflect/scala/reflect/internal/Names.scala2
-rw-r--r--src/reflect/scala/reflect/internal/StdNames.scala39
-rw-r--r--test/junit/scala/tools/nsc/symtab/StdNamesTest.scala46
3 files changed, 73 insertions, 14 deletions
diff --git a/src/reflect/scala/reflect/internal/Names.scala b/src/reflect/scala/reflect/internal/Names.scala
index ed248d6e1e..f998d95349 100644
--- a/src/reflect/scala/reflect/internal/Names.scala
+++ b/src/reflect/scala/reflect/internal/Names.scala
@@ -90,6 +90,8 @@ trait Names extends api.Names {
*/
final def newTermName(cs: Array[Char], offset: Int, len: Int, cachedString: String): TermName = {
def body = {
+ require(offset >= 0, "offset must be non-negative, got " + offset)
+ require(len >= 0, "length must be non-negative, got " + len)
val h = hashValue(cs, offset, len) & HASH_MASK
var n = termHashtable(h)
while ((n ne null) && (n.length != len || !equals(n.start, cs, offset, len)))
diff --git a/src/reflect/scala/reflect/internal/StdNames.scala b/src/reflect/scala/reflect/internal/StdNames.scala
index 686ebf5a1e..6407a3979c 100644
--- a/src/reflect/scala/reflect/internal/StdNames.scala
+++ b/src/reflect/scala/reflect/internal/StdNames.scala
@@ -413,32 +413,43 @@ trait StdNames {
@deprecated("Use Name#getterName", "2.11.0") def getterName(name: TermName): TermName = name.getterName
@deprecated("Use Name#getterName", "2.11.0") def setterToGetter(name: TermName): TermName = name.getterName
+ /**
+ * Convert `Tuple2$mcII` to `Tuple2`, or `T1$sp` to `T1`.
+ */
def unspecializedName(name: Name): Name = (
- if (name endsWith SPECIALIZED_SUFFIX)
- name.subName(0, name.lastIndexOf('m') - 1)
+ // DUPLICATED LOGIC WITH `splitSpecializedName`
+ if (name endsWith SPECIALIZED_SUFFIX) {
+ val idxM = name.lastIndexOf('m')
+ val to = (if (idxM > 0) idxM - 1 else name.length - SPECIALIZED_SUFFIX.length)
+ name.subName(0, to)
+ }
else name
)
/** Return the original name and the types on which this name
* is specialized. For example,
* {{{
- * splitSpecializedName("foo$mIcD$sp") == ('foo', "I", "D")
+ * splitSpecializedName("foo$mIcD$sp") == ('foo', "D", "I")
* }}}
* `foo$mIcD$sp` is the name of a method specialized on two type
* parameters, the first one belonging to the method itself, on Int,
* and another one belonging to the enclosing class, on Double.
+ *
+ * @return (unspecializedName, class tparam specializations, method tparam specializations)
*/
- def splitSpecializedName(name: Name): (Name, String, String) =
- if (name endsWith SPECIALIZED_SUFFIX) {
- val name1 = name dropRight SPECIALIZED_SUFFIX.length
- val idxC = name1 lastIndexOf 'c'
- val idxM = name1 lastIndexOf 'm'
-
- (name1.subName(0, idxM - 1),
- name1.subName(idxC + 1, name1.length).toString,
- name1.subName(idxM + 1, idxC).toString)
- } else
- (name, "", "")
+ def splitSpecializedName(name: Name): (Name, String, String) = {
+ // DUPLICATED LOGIC WITH `unspecializedName`
+ if (name endsWith SPECIALIZED_SUFFIX) {
+ val name1 = name dropRight SPECIALIZED_SUFFIX.length
+ val idxC = name1 lastIndexOf 'c'
+ val idxM = name1 lastIndexOf 'm'
+ if (idxC > idxM && idxM > 0)
+ (name1.subName(0, idxM - 1), name1.subName(idxC + 1, name1.length).toString, name1.subName(idxM + 1, idxC).toString)
+ else
+ (name.subName(0, name.length - SPECIALIZED_SUFFIX.length), "", "")
+ }
+ else (name, "", "")
+ }
// Nominally, name$default$N, encoded for <init>
def defaultGetterName(name: Name, pos: Int): TermName = (
diff --git a/test/junit/scala/tools/nsc/symtab/StdNamesTest.scala b/test/junit/scala/tools/nsc/symtab/StdNamesTest.scala
new file mode 100644
index 0000000000..05e69978c6
--- /dev/null
+++ b/test/junit/scala/tools/nsc/symtab/StdNamesTest.scala
@@ -0,0 +1,46 @@
+package scala.tools.nsc
+package symtab
+
+import org.junit.Assert._
+import scala.tools.testing.AssertUtil._
+import org.junit.{Ignore, Test}
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(classOf[JUnit4])
+class StdNamesTest {
+ object symbolTable extends SymbolTableForUnitTesting
+ import symbolTable._
+ import nme.{SPECIALIZED_SUFFIX, unspecializedName, splitSpecializedName}
+
+ @Test
+ def testNewTermNameInvalid(): Unit = {
+ assertThrows[IllegalArgumentException](newTermName("foo".toCharArray, 0, -1))
+ assertThrows[IllegalArgumentException](newTermName("foo".toCharArray, 0, 0))
+ assertThrows[IllegalArgumentException](newTermName("foo".toCharArray, -1, 1))
+ }
+
+ @Test
+ def testUnspecializedName(): Unit = {
+ def test(expected: Name, nme: Name) {
+ assertEquals(expected, unspecializedName(nme))
+ }
+ test(TermName("Tuple2"), TermName("Tuple2$mcII" + SPECIALIZED_SUFFIX))
+ test(TermName("foo"), TermName("foo$mIcD" + SPECIALIZED_SUFFIX))
+ test(TermName("foo"), TermName("foo$mIc" + SPECIALIZED_SUFFIX))
+ test(TermName("T1"), TermName(s"T1$SPECIALIZED_SUFFIX"))
+ test(TermName(""), SPECIALIZED_SUFFIX)
+ }
+
+ @Test
+ def testSplitSpecializedName(): Unit = {
+ def test(expected: (Name, String, String), nme: Name) {
+ assertEquals(expected, splitSpecializedName(nme))
+ }
+ test((TermName("Tuple2"), "II", ""), TermName("Tuple2$mcII" + SPECIALIZED_SUFFIX))
+ test((TermName("foo"), "D", "I"), TermName("foo$mIcD" + SPECIALIZED_SUFFIX))
+ test((TermName("foo"), "", "I"), TermName("foo$mIc" + SPECIALIZED_SUFFIX))
+ test((TermName("T1"), "", ""), TermName(s"T1$SPECIALIZED_SUFFIX"))
+ test((TermName(""), "", ""), SPECIALIZED_SUFFIX)
+ }
+}