Dotty: Fails to parse XML literal as NodeBuffer

Created on 5 Feb 2020  路  4Comments  路  Source: lampepfl/dotty

In 2.13.1, it was possible to specify multiple XML literal elements and have them parsed as NodeBuffer (usually parsing one would be an Elem). I don't think this capability is used very often in Scala code bases, but given how much Scala code is out there, it is worth surfacing this regression.

import scala.xml.NodeBuffer
val nodeBuffer: NodeBuffer = <hello/><world/>
println()

It works fine in a REPL (dotty doesn't have :paste?), but not in a file:

[error] -- [E008] Member Not Found Error: src/main/scala/XMLHelloWorld.scala:9:4 
[error] 8 |    val nodeBuffer: NodeBuffer = <hello/><world/>
[error] 9 |    println()
[error]   |                                  ^
[error]   |                     value println is not a member of scala.xml.NodeBuffer
[error] one error found
[error] (Compile / compileIncremental) Compilation failed

Here's an example repo with a branch with this defect:

https://github.com/ashawley/dotty-scala-xml-example/tree/nodebuffer

parser scala2 help wanted bug

Most helpful comment

This is a duplicate of https://github.com/scala/bug/issues/9027. I'll attempt a PR that reapplies the patch.

That old PR was on 2.11, had a backport to 2.10, and now will have a forward port to 3.

All 4 comments

Somehow, the println on the last line is seen by the parser as part of the expression started on the previous line:

 ./bin/dotc -Xprint:parser -classpath "$(coursier fetch -p org.scala-lang.modules:scala-xml_2.13:2.0.0-M1)" try/i8214.scala
parsed:
package <empty> {
  import scala.xml.NodeBuffer
  module object Test {
    val nodeBuffer: NodeBuffer =
      {
        val $buf = new _root_.scala.xml.NodeBuffer()
        $buf.&+(
          {
            {
              new _root_.scala.xml.Elem(null, "hello", _root_.scala.xml.Null,
                $scope
              , true)
            }
          }
        )
        $buf.&+(
          {
            {
              new _root_.scala.xml.Elem(null, "world", _root_.scala.xml.Null,
                $scope
              , true)
            }
          }
        )
        $buf
      } println ()
  }
}
-- [E008] Member Not Found Error: try/i8214.scala:4:2 --------------------------
3 |  val nodeBuffer: NodeBuffer = <hello/><world/>
4 |  println()
  |                                ^
  |                     value println is not a member of scala.xml.NodeBuffer
1 error found

Since I am strongly in favor of abandoning XML literals for Scala 3 I won't put effort in fixing this. It seems like a non-obvious interaction between the XML parser (which I don't know) and the normal parser. Somebody else should take this on if there's interest in fixing this.

As a workaround, one can add braces around the xml expression:

import scala.xml.NodeBuffer
object Test {
  val nodeBuffer: NodeBuffer = {
    <hello/><world/>
  }

  println()
}

This is a duplicate of https://github.com/scala/bug/issues/9027. I'll attempt a PR that reapplies the patch.

That old PR was on 2.11, had a backport to 2.10, and now will have a forward port to 3.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

deusaquilus picture deusaquilus  路  3Comments

Blaisorblade picture Blaisorblade  路  3Comments

milessabin picture milessabin  路  3Comments

fommil picture fommil  路  3Comments

noti0na1 picture noti0na1  路  3Comments