Merge pull request #9292 from dwijnand/non-implicit-enrich-CharSequence

Make the CharSequence wrappers in Predef non-implicit, for JDK 15
This commit is contained in:
Dale Wijnand 2020-11-04 16:26:18 +00:00 committed by GitHub
commit 7101549240
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 51 additions and 27 deletions

View File

@ -87,9 +87,9 @@ import scala.annotation.meta.{ companionClass, companionMethod }
* @groupprio implicit-classes-any 70
* @groupdesc implicit-classes-any These implicit classes add useful extension methods to every type.
*
* @groupname implicit-classes-char CharSequence Conversions
* @groupprio implicit-classes-char 80
* @groupdesc implicit-classes-char These implicit classes add CharSequence methods to Array[Char] and IndexedSeq[Char] instances.
* @groupname char-sequence-wrappers CharSequence Wrappers
* @groupprio char-sequence-wrappers 80
* @groupdesc char-sequence-wrappers Wrappers that implements CharSequence and were implicit classes.
*
* @groupname conversions-java-to-anyval Java to Scala
* @groupprio conversions-java-to-anyval 90
@ -380,21 +380,28 @@ object Predef extends LowPriorityImplicits {
def +(other: String): String = String.valueOf(self) + other
}
implicit final class SeqCharSequence(sequenceOfChars: scala.collection.IndexedSeq[Char]) extends CharSequence {
/** @group char-sequence-wrappers */
final class SeqCharSequence(sequenceOfChars: scala.collection.IndexedSeq[Char]) extends CharSequence {
def length: Int = sequenceOfChars.length
def charAt(index: Int): Char = sequenceOfChars(index)
def subSequence(start: Int, end: Int): CharSequence = new SeqCharSequence(sequenceOfChars.slice(start, end))
override def toString = sequenceOfChars.mkString
}
/** @group implicit-classes-char */
implicit final class ArrayCharSequence(arrayOfChars: Array[Char]) extends CharSequence {
/** @group char-sequence-wrappers */
def SeqCharSequence(sequenceOfChars: scala.collection.IndexedSeq[Char]): SeqCharSequence = new SeqCharSequence(sequenceOfChars)
/** @group char-sequence-wrappers */
final class ArrayCharSequence(arrayOfChars: Array[Char]) extends CharSequence {
def length: Int = arrayOfChars.length
def charAt(index: Int): Char = arrayOfChars(index)
def subSequence(start: Int, end: Int): CharSequence = new runtime.ArrayCharSequence(arrayOfChars, start, end)
override def toString = arrayOfChars.mkString
}
/** @group char-sequence-wrappers */
def ArrayCharSequence(arrayOfChars: Array[Char]): ArrayCharSequence = new ArrayCharSequence(arrayOfChars)
/** @group conversions-string */
@inline implicit def augmentString(x: String): StringOps = new StringOps(x)

View File

@ -12,8 +12,6 @@
package scala.collection.mutable
import java.lang.String
import scala.collection.{IterableFactoryDefaults, IterableOnce}
import scala.collection.immutable.WrappedString
@ -468,6 +466,14 @@ final class StringBuilder(val underlying: java.lang.StringBuilder) extends Abstr
* @return the last applicable index where target occurs, or -1 if not found.
*/
def lastIndexOf(str: String, fromIndex: Int): Int = underlying.lastIndexOf(str, fromIndex)
/** Tests whether this builder is empty.
*
* This method is required for JDK15+ compatibility
*
* @return `true` if this builder contains nothing, `false` otherwise.
*/
override def isEmpty: Boolean = underlying.length() == 0
}
object StringBuilder {

View File

@ -187,12 +187,17 @@ trait Names extends api.Names {
// Classes ----------------------------------------------------------------------
// Dummy trait to make Name#isEmpty with override keyword at JDK before 15
sealed trait NameHasIsEmpty {
def isEmpty: Boolean
}
/** The name class.
* TODO - resolve schizophrenia regarding whether to treat Names as Strings
* or Strings as Names. Give names the key functions the absence of which
* make people want Strings all the time.
*/
sealed abstract class Name(protected val index: Int, protected val len: Int, protected val cachedString: String) extends NameApi with CharSequence {
sealed abstract class Name(protected val index: Int, protected val len: Int, protected val cachedString: String) extends NameApi with NameHasIsEmpty with CharSequence {
type ThisNameType >: Null <: Name
protected[this] def thisName: ThisNameType
@ -208,8 +213,9 @@ trait Names extends api.Names {
/** The length of this name. */
final def length: Int = len
final def isEmpty = length == 0
final def nonEmpty = !isEmpty
// This method is implements NameHasIsEmpty, and overrides CharSequence's isEmpty on JDK 15+
override final def isEmpty = length == 0
def nameKind: String
def isTermName: Boolean

View File

@ -1,6 +1,6 @@
package scala
import org.junit.Assert.assertArrayEquals
import org.junit.Assert.{ assertArrayEquals, assertFalse, assertTrue }
import org.junit.Test
import scala.runtime.BoxedUnit
@ -13,4 +13,25 @@ class ArrayTest {
assertArrayEquals(expected, Array.copyAs[Unit](Array[Nothing](), 32).asInstanceOf[Array[AnyRef]])
assertArrayEquals(expected, Array.copyAs[Unit](Array[Unit](), 32).asInstanceOf[Array[AnyRef]])
}
@Test
def testArrayIsEmpty(): Unit = {
assertTrue(Array[Int]().isEmpty)
assertTrue(Array[Char]().isEmpty) // scala/bug#12172
assertTrue(Array[String]().isEmpty)
assertFalse(Array(1).isEmpty)
assertFalse(Array[Char](1).isEmpty)
assertFalse(Array("").isEmpty)
def ge[T](a: Array[T]) = a.isEmpty
assertTrue(ge(Array[Int]()))
assertTrue(ge(Array[Char]()))
assertTrue(ge(Array[String]()))
assertFalse(ge(Array(1)))
assertFalse(ge(Array[Char]('x')))
assertFalse(ge(Array("")))
}
}

View File

@ -1,16 +0,0 @@
package scala
import org.junit.Test
import org.junit.Assert._
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
// these two implicit conversions come from Predef
@RunWith(classOf[JUnit4])
class CharSequenceImplicitsTests {
@Test def arrayAsCharSequence(): Unit =
assertEquals("ab", (Array ('a', 'b'): CharSequence).toString)
@Test def indexedSeqAsCharSequence(): Unit =
assertEquals("ab", (IndexedSeq('a', 'b'): CharSequence).toString)
}