Skip to content

Commit 306fe58

Browse files
authored
Merge pull request #396 from ashawley/issue-392
Fix 2.13 collections methods for NodeSeq
2 parents a410659 + df7d18e commit 306fe58

File tree

2 files changed

+119
-1
lines changed

2 files changed

+119
-1
lines changed

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

Lines changed: 16 additions & 1 deletion
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 =>
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
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)
17+
case res: Seq[Node] => fail("Should be NodeSeq") // 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)
30+
case res: NodeSeq => fail("Should be Seq[Node]") // 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[NodeSeq] => assertEquals(2, res.size)
43+
case res: NodeSeq => fail("Should be NodeSeq was Seq[Node]") // Unreachable code?
44+
}
45+
val res: Seq[NodeSeq] = a +: b
46+
val exp = <a>Hello</a><b>Hi</b>
47+
assertEquals(exp, res)
48+
}
49+
50+
@Test
51+
def testPrependedAll: Unit = {
52+
val a: NodeSeq = <a>Hello</a>
53+
val b = <b>Hi</b>
54+
val c = <c>Hey</c>
55+
a ++: <b>Hi</b> ++: <c>Hey</c> match {
56+
case res: Seq[Node] => assertEquals(3, res.size)
57+
case res: NodeSeq => fail("Should be Seq[Node]") // Unreachable code?
58+
}
59+
val res: NodeSeq = a ++: b ++: c
60+
val exp = NodeSeq.fromSeq(Seq(<a>Hello</a>, <b>Hi</b>, <c>Hey</c>))
61+
assertEquals(exp, res)
62+
}
63+
64+
@Test
65+
def testMap: Unit = {
66+
val a: NodeSeq = <a>Hello</a>
67+
val exp: NodeSeq = Seq(<b>Hi</b>)
68+
assertEquals(exp, a.map(_ => <b>Hi</b>))
69+
assertEquals(exp, for { _ <- a } yield { <b>Hi</b> })
70+
}
71+
72+
@Test
73+
def testFlatMap: Unit = {
74+
val a: NodeSeq = <a>Hello</a>
75+
val exp: NodeSeq = Seq(<b>Hi</b>)
76+
assertEquals(exp, a.flatMap(_ => Seq(<b>Hi</b>)))
77+
assertEquals(exp, for { b <- a; _ <- b } yield { <b>Hi</b> })
78+
assertEquals(exp, for { b <- a; c <- b; _ <- c } yield { <b>Hi</b> })
79+
}
80+
81+
@Test
82+
def testStringProjection: Unit = {
83+
val a =
84+
<a>
85+
<b>b</b>
86+
<b>
87+
<c d="d">
88+
<e>e</e>
89+
<e>e</e>
90+
</c>
91+
<c>c</c>
92+
</b>
93+
</a>
94+
val res = for {
95+
b <- a \ "b"
96+
c <- b.child
97+
e <- (c \ "e").headOption
98+
} yield {
99+
e.text.trim
100+
}
101+
assertEquals(Seq("e"), res)
102+
}
103+
}

0 commit comments

Comments
 (0)