Skip to content

Commit 1e1fff0

Browse files
committed
Use toVector for XML literal sequences
In `<a><b/><c/><a>`, a `NodeBuffer` (which extends `ArrayBuffer`) is used to accumulate the children. The buffer is passed to `new Elem($buf: _*)`, which only works thanks to the implicit `collection.Seq[Node] => NodeSeq` declared in scala-xml. With `-Vprint:typer`: ```scala scala> <a><b/></a> [[syntax trees at end of typer]] // rs$line$1 val res0: scala.xml.Elem = { new _root_.scala.xml.Elem(null, "a", _root_.scala.xml.Null, scala.xml.TopScope, false, { val $buf: scala.xml.NodeBuffer = new _root_.scala.xml.NodeBuffer() $buf.&+( { { new _root_.scala.xml.Elem(null, "b", _root_.scala.xml.Null, scala.xml.TopScope, true, [ : scala.xml.Node]*) } } ) scala.xml.NodeSeq.seqToNodeSeq($buf) }* ) } ``` The implicit was not inserted in 2.12 because the varargs parameter of Elem accepted a `collection.Seq`.
1 parent d5ca220 commit 1e1fff0

File tree

2 files changed

+15
-7
lines changed

2 files changed

+15
-7
lines changed

compiler/src/dotty/tools/dotc/parsing/xml/SymbolicXMLBuilder.scala

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,14 @@ class SymbolicXMLBuilder(parser: Parser, preserveWS: Boolean)(using Context) {
4242
val _Group: TypeName = "Group"
4343
val _MetaData: TypeName = "MetaData"
4444
val _NamespaceBinding: TypeName = "NamespaceBinding"
45+
val _Node: TypeName = "Node"
4546
val _NodeBuffer: TypeName = "NodeBuffer"
4647
val _PrefixedAttribute: TypeName = "PrefixedAttribute"
4748
val _ProcInstr: TypeName = "ProcInstr"
4849
val _Text: TypeName = "Text"
4950
val _Unparsed: TypeName = "Unparsed"
5051
val _UnprefixedAttribute: TypeName = "UnprefixedAttribute"
52+
val _Seq: TypeName = "Seq"
5153
}
5254

5355
private object xmlterms extends ScalaTermNames {
@@ -59,12 +61,13 @@ class SymbolicXMLBuilder(parser: Parser, preserveWS: Boolean)(using Context) {
5961
val _plus: TermName = "&+"
6062
val _tmpscope: TermName = "$tmpscope"
6163
val _xml: TermName = "xml"
64+
val _toVector: TermName = "toVector"
6265
}
6366

64-
import xmltypes.{_Comment, _Elem, _EntityRef, _Group, _MetaData, _NamespaceBinding, _NodeBuffer,
65-
_PrefixedAttribute, _ProcInstr, _Text, _Unparsed, _UnprefixedAttribute}
67+
import xmltypes.{_Comment, _Elem, _EntityRef, _Group, _MetaData, _NamespaceBinding, _NodeBuffer, _Node,
68+
_PrefixedAttribute, _ProcInstr, _Text, _Unparsed, _UnprefixedAttribute, _Seq}
6669

67-
import xmlterms.{_Null, __Elem, __Text, _buf, _md, _plus, _scope, _tmpscope, _xml}
70+
import xmlterms.{_Null, __Elem, __Text, _buf, _md, _plus, _scope, _tmpscope, _xml, _toVector}
6871

6972
// convenience methods
7073
private def LL[A](x: A*): List[List[A]] = List(x.toList)
@@ -89,6 +92,7 @@ class SymbolicXMLBuilder(parser: Parser, preserveWS: Boolean)(using Context) {
8992
private def _scala_xml_UnprefixedAttribute= _scala_xml(_UnprefixedAttribute)
9093
private def _scala_xml__Elem = _scala_xml(__Elem)
9194
private def _scala_xml__Text = _scala_xml(__Text)
95+
private def _scala_Seq_Node = AppliedTypeTree(_scala(_Seq), List(_scala_xml(_Node)))
9296

9397
/** Wildly wrong documentation deleted in favor of "self-documenting code." */
9498
protected def mkXML(
@@ -166,7 +170,7 @@ class SymbolicXMLBuilder(parser: Parser, preserveWS: Boolean)(using Context) {
166170
val buffer = ValDef(_buf, TypeTree(), New(_scala_xml_NodeBuffer, ListOfNil))
167171
val applies = args filterNot isEmptyText map (t => Apply(Select(Ident(_buf), _plus), List(t)))
168172

169-
atSpan(span)(new XMLBlock(buffer :: applies.toList, Ident(_buf)) )
173+
atSpan(span)(new XMLBlock(buffer :: applies.toList, Typed(Select(Ident(_buf), _toVector), _scala_Seq_Node)))
170174
}
171175

172176
/** Returns (Some(prefix) | None, rest) based on position of ':' */

tests/run/xml.scala

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11

22
object Test {
3-
import scala.xml.NodeBuffer
3+
import scala.xml._
44

55
def main(args: Array[String]): Unit = {
66
val xml = <hello>world</hello>
77
assert(xml.toString == "helloworld")
8-
val nodeBuffer: NodeBuffer = <hello/><world/>
9-
assert(nodeBuffer.mkString == "helloworld")
8+
val sq: Seq[Node] = <hello/><world/>
9+
assert(sq.mkString == "helloworld")
10+
assert(sq.isInstanceOf[Vector[_]]) // implementation detail
11+
12+
val subSq: Node = <a><b/><c/></a>
13+
assert(subSq.child.toString == "Vector(b, c)") // implementation detail
1014
}
1115
}
1216
package scala.xml {

0 commit comments

Comments
 (0)