Skip to content

Commit 38653b1

Browse files
i10416WojciechMazur
authored andcommitted
fix(#16458): regression in xml syntax parsing
xLiteral mistakenly assumed that the element just after `<` is always non-special element, but it is not true. It could be xCharData, comment, xProcInstr. [Cherry-picked 77aa363]
1 parent 6cbc994 commit 38653b1

File tree

3 files changed

+56
-4
lines changed

3 files changed

+56
-4
lines changed

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

+8
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,14 @@ private[dotty] trait MarkupParserCommon {
202202
/** skip optional space S? */
203203
def xSpaceOpt(): Unit = while (isSpace(ch) && !eof) nextch()
204204

205+
/** skip optional space S? and return the number of consumed characters */
206+
def xSpaceOptN(): Int =
207+
var i = 0
208+
while (isSpace(ch) && !eof) do
209+
nextch()
210+
i += 1
211+
i
212+
205213
/** scan [3] S ::= (#x20 | #x9 | #xD | #xA)+ */
206214
def xSpace(): Unit =
207215
if (isSpace(ch)) { nextch(); xSpaceOpt() }

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

+11-4
Original file line numberDiff line numberDiff line change
@@ -370,10 +370,17 @@ object MarkupParsers {
370370
// parse more XML?
371371
if (charComingAfter(xSpaceOpt()) == '<') {
372372
while {
373-
xSpaceOpt()
374-
nextch()
375-
ts.append(element)
376-
charComingAfter(xSpaceOpt()) == '<'
373+
if xSpaceOptN() == 0 then
374+
nextch()
375+
if content_LT(ts) then // Is `</>` valid xml?
376+
xToken("/>")
377+
charComingAfter(xSpaceOpt()) == '<'
378+
else
379+
// this is surely not a special node as any special node
380+
// should start with `<{special symbol}` without space.
381+
nextch()
382+
ts.append(element)
383+
charComingAfter(xSpaceOpt()) == '<'
377384
} do ()
378385
handle.makeXMLseq(Span(start, curOffset, start), ts)
379386
}

tests/pos/i16458.scala

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
def x = <div>FooBar</div><!-- /.modal-content -->
2+
3+
package scala.xml {
4+
type MetaData = AnyRef
5+
6+
trait NamespaceBinding
7+
object TopScope extends NamespaceBinding
8+
object Null
9+
abstract class Node {
10+
def label: String
11+
def child: Seq[Node]
12+
override def toString = label + child.mkString
13+
}
14+
class Comment(commentText: String) extends Node{
15+
def label = commentText
16+
def child = Nil
17+
}
18+
class Elem(prefix: String, val label: String, attributes1: MetaData, scope: NamespaceBinding, minimizeEmpty: Boolean, val child: Node*) extends Node
19+
class NodeBuffer extends Seq[Node] {
20+
val nodes = scala.collection.mutable.ArrayBuffer.empty[Node]
21+
def &+(o: Any): NodeBuffer =
22+
o match {
23+
case n: Node => nodes.addOne(n) ; this
24+
case t: Text => nodes.addOne(Atom(t)) ; this
25+
}
26+
// Members declared in scala.collection.IterableOnce
27+
def iterator: Iterator[scala.xml.Node] = nodes.iterator
28+
// Members declared in scala.collection.SeqOps
29+
def apply(i: Int): scala.xml.Node = nodes(i)
30+
def length: Int = nodes.length
31+
}
32+
case class Text(text: String)
33+
case class Atom(t: Text) extends Node {
34+
def label = t.text
35+
def child = Nil
36+
}
37+
}

0 commit comments

Comments
 (0)