Skip to content

Commit d76d65d

Browse files
authored
Merge pull request #402 from ashawley/issue-392-cont
Fix 2.13 collections methods for NodeSeq
2 parents 8f1a541 + 0a1578d commit d76d65d

File tree

2 files changed

+121
-1
lines changed

2 files changed

+121
-1
lines changed

shared/src/main/scala-2.13+/scala/xml/ScalaVersionSpecific.scala

+16-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package scala.xml
22

33
import scala.collection.immutable.StrictOptimizedSeqOps
4-
import scala.collection.{SeqOps, IterableOnce, immutable, mutable}
4+
import scala.collection.{View, SeqOps, IterableOnce, immutable, mutable}
55
import scala.collection.BuildFrom
66
import scala.collection.mutable.Builder
77

@@ -20,6 +20,21 @@ private[xml] trait ScalaVersionSpecificNodeSeq
2020
override def fromSpecific(coll: IterableOnce[Node]): NodeSeq = (NodeSeq.newBuilder ++= coll).result()
2121
override def newSpecificBuilder: mutable.Builder[Node, NodeSeq] = NodeSeq.newBuilder
2222
override def empty: NodeSeq = NodeSeq.Empty
23+
def concat(suffix: IterableOnce[Node]): NodeSeq =
24+
fromSpecific(iterator ++ suffix.iterator)
25+
@inline final def ++ (suffix: Seq[Node]): NodeSeq = concat(suffix)
26+
def appended(base: Node): NodeSeq =
27+
fromSpecific(new View.Appended(this, base))
28+
def appendedAll(suffix: IterableOnce[Node]): NodeSeq =
29+
concat(suffix)
30+
def prepended(base: Node): NodeSeq =
31+
fromSpecific(new View.Prepended(base, this))
32+
def prependedAll(prefix: IterableOnce[Node]): NodeSeq =
33+
fromSpecific(prefix.iterator ++ iterator)
34+
def map(f: Node => Node): NodeSeq =
35+
fromSpecific(new View.Map(this, f))
36+
def flatMap(f: Node => IterableOnce[Node]): NodeSeq =
37+
fromSpecific(new View.FlatMap(this, f))
2338
}
2439

2540
private[xml] trait ScalaVersionSpecificNodeBuffer { self: NodeBuffer =>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
package scala.xml
2+
3+
import scala.xml.NodeSeq.seqToNodeSeq
4+
5+
import org.junit.Test
6+
import org.junit.Assert.assertEquals
7+
import org.junit.Assert.fail
8+
9+
class NodeSeqTest {
10+
11+
@Test
12+
def testAppend: Unit = { // Bug #392.
13+
val a: NodeSeq = <a>Hello</a>
14+
val b = <b>Hi</b>
15+
a ++ <b>Hi</b> match {
16+
case res: NodeSeq => assertEquals(2, res.size.toLong)
17+
case res: Seq[Node] => fail("Should be NodeSeq was Seq[Node]") // Unreachable code?
18+
}
19+
val res: NodeSeq = a ++ b
20+
val exp = NodeSeq.fromSeq(Seq(<a>Hello</a>, <b>Hi</b>))
21+
assertEquals(exp, res)
22+
}
23+
24+
@Test
25+
def testAppendedAll: Unit = { // Bug #392.
26+
val a: NodeSeq = <a>Hello</a>
27+
val b = <b>Hi</b>
28+
a :+ <b>Hi</b> match {
29+
case res: Seq[Node] => assertEquals(2, res.size.toLong)
30+
case res: NodeSeq => fail("Should be Seq[Node] was NodeSeq") // Unreachable code?
31+
}
32+
val res: NodeSeq = a :+ b
33+
val exp = NodeSeq.fromSeq(Seq(<a>Hello</a>, <b>Hi</b>))
34+
assertEquals(exp, res)
35+
}
36+
37+
@Test
38+
def testPrepended: Unit = {
39+
val a: NodeSeq = <a>Hello</a>
40+
val b = <b>Hi</b>
41+
a +: <b>Hi</b> match {
42+
case res: Seq[Node] => assertEquals(2, res.size.toLong)
43+
case res: NodeSeq => fail("Should be Seq[Node] was NodeSeq") // Unreachable code?
44+
}
45+
val res: Seq[NodeSeq] = a +: b
46+
val exp: NodeBuffer = {
47+
<a>Hello</a><b>Hi</b>
48+
}
49+
assertEquals(exp, res)
50+
}
51+
52+
@Test
53+
def testPrependedAll: Unit = {
54+
val a: NodeSeq = <a>Hello</a>
55+
val b = <b>Hi</b>
56+
val c = <c>Hey</c>
57+
a ++: <b>Hi</b> ++: <c>Hey</c> match {
58+
case res: Seq[Node] => assertEquals(3, res.size.toLong)
59+
case res: NodeSeq => fail("Should be Seq[Node] was NodeSeq") // Unreachable code?
60+
}
61+
val res: NodeSeq = a ++: b ++: c
62+
val exp = NodeSeq.fromSeq(Seq(<a>Hello</a>, <b>Hi</b>, <c>Hey</c>))
63+
assertEquals(exp, res)
64+
}
65+
66+
@Test
67+
def testMap: Unit = {
68+
val a: NodeSeq = <a>Hello</a>
69+
val exp: NodeSeq = Seq(<b>Hi</b>)
70+
assertEquals(exp, a.map(_ => <b>Hi</b>))
71+
assertEquals(exp, for { _ <- a } yield { <b>Hi</b> })
72+
}
73+
74+
@Test
75+
def testFlatMap: Unit = {
76+
val a: NodeSeq = <a>Hello</a>
77+
val exp: NodeSeq = Seq(<b>Hi</b>)
78+
assertEquals(exp, a.flatMap(_ => Seq(<b>Hi</b>)))
79+
assertEquals(exp, for { b <- a; _ <- b } yield { <b>Hi</b> })
80+
assertEquals(exp, for { b <- a; c <- b; _ <- c } yield { <b>Hi</b> })
81+
}
82+
83+
@Test
84+
def testStringProjection: Unit = {
85+
val a =
86+
<a>
87+
<b>b</b>
88+
<b>
89+
<c d="d">
90+
<e>e</e>
91+
<e>e</e>
92+
</c>
93+
<c>c</c>
94+
</b>
95+
</a>
96+
val res = for {
97+
b <- a \ "b"
98+
c <- b.child
99+
e <- (c \ "e").headOption
100+
} yield {
101+
e.text.trim
102+
}
103+
assertEquals(Seq("e"), res)
104+
}
105+
}

0 commit comments

Comments
 (0)