diff options
-rw-r--r-- | src/library/scala/xml/Atom.scala | 4 | ||||
-rw-r--r-- | src/library/scala/xml/Comment.scala | 3 | ||||
-rw-r--r-- | src/library/scala/xml/Elem.scala | 5 | ||||
-rw-r--r-- | src/library/scala/xml/EntityRef.scala | 3 | ||||
-rw-r--r-- | src/library/scala/xml/Group.scala | 2 | ||||
-rw-r--r-- | src/library/scala/xml/Node.scala | 6 | ||||
-rw-r--r-- | src/library/scala/xml/ProcInstr.scala | 3 | ||||
-rw-r--r-- | src/library/scala/xml/Utility.scala | 2 | ||||
-rw-r--r-- | src/library/scala/xml/transform/BasicTransformer.scala | 131 | ||||
-rw-r--r-- | src/library/scala/xml/transform/RuleTransformer.scala | 12 | ||||
-rw-r--r-- | test/files/run/bug2124.check | 1 | ||||
-rw-r--r-- | test/files/run/bug2124.scala | 25 | ||||
-rw-r--r-- | test/files/run/bug2125.check | 1 | ||||
-rw-r--r-- | test/files/run/bug2125.scala | 25 |
14 files changed, 96 insertions, 127 deletions
diff --git a/src/library/scala/xml/Atom.scala b/src/library/scala/xml/Atom.scala index 6f48d64f12..44770bce1a 100644 --- a/src/library/scala/xml/Atom.scala +++ b/src/library/scala/xml/Atom.scala @@ -23,7 +23,9 @@ class Atom[+A](val data: A) extends SpecialNode if (data.asInstanceOf[AnyRef] == null) throw new IllegalArgumentException("cannot construct Atom(null)") - final override def collectNamespacesAndDontTransform = false + final override def doCollectNamespaces = false + final override def doTransform = false + def label = "#PCDATA" override def equals(x: Any) = x match { diff --git a/src/library/scala/xml/Comment.scala b/src/library/scala/xml/Comment.scala index 421b5b4afb..c1b7c6645c 100644 --- a/src/library/scala/xml/Comment.scala +++ b/src/library/scala/xml/Comment.scala @@ -20,7 +20,8 @@ case class Comment(commentText: String) extends SpecialNode { def label = "#REM" override def text = "" - final override def collectNamespacesAndDontTransform = false + final override def doCollectNamespaces = false + final override def doTransform = false if (commentText contains "--") throw new IllegalArgumentException("text contains \"--\"") diff --git a/src/library/scala/xml/Elem.scala b/src/library/scala/xml/Elem.scala index 2392e1a002..28032fcc30 100644 --- a/src/library/scala/xml/Elem.scala +++ b/src/library/scala/xml/Elem.scala @@ -49,6 +49,9 @@ class Elem( val child: Node*) extends Node { + final override def doCollectNamespaces = true + final override def doTransform = true + if ((null != prefix) && 0 == prefix.length()) throw new IllegalArgumentException("prefix of zero length, use null instead") @@ -59,8 +62,6 @@ extends Node // setting namespace scope if necessary // cleaning adjacent text nodes if necessary - final override def collectNamespacesAndDontTransform = true - override def hashCode(): Int = Utility.hashCode(prefix, label, attributes.hashCode(), scope.hashCode(), child) diff --git a/src/library/scala/xml/EntityRef.scala b/src/library/scala/xml/EntityRef.scala index 3300af2963..1f241aa54c 100644 --- a/src/library/scala/xml/EntityRef.scala +++ b/src/library/scala/xml/EntityRef.scala @@ -19,7 +19,8 @@ package scala.xml * @param text the text contained in this node. */ case class EntityRef(entityName: String) extends SpecialNode { - final override def collectNamespacesAndDontTransform = false + final override def doCollectNamespaces = false + final override def doTransform = false def label = "#ENTITY" override def text = entityName match { diff --git a/src/library/scala/xml/Group.scala b/src/library/scala/xml/Group.scala index 7e4b983ec6..99a9f8c95d 100644 --- a/src/library/scala/xml/Group.scala +++ b/src/library/scala/xml/Group.scala @@ -18,7 +18,7 @@ package scala.xml */ @serializable case class Group(val nodes: Seq[Node]) extends Node { - + // final override def doTransform = false override def theSeq = nodes /** XXX this is ridiculous, we can't do equality like this. */ diff --git a/src/library/scala/xml/Node.scala b/src/library/scala/xml/Node.scala index 2b6427ae74..618c4de8d2 100644 --- a/src/library/scala/xml/Node.scala +++ b/src/library/scala/xml/Node.scala @@ -48,9 +48,9 @@ abstract class Node extends NodeSeq { */ def isAtom = this.isInstanceOf[Atom[_]] - /** The logic formerly found in typeTag$, as best I could infer it. - * XXX obviously this name is ludicrous. */ - def collectNamespacesAndDontTransform = true + /** The logic formerly found in typeTag$, as best I could infer it. */ + def doCollectNamespaces = true // if (tag >= 0) DO collect namespaces + def doTransform = true // if (tag < 0) DO NOT transform /** * method returning the namespace bindings of this node. by default, this diff --git a/src/library/scala/xml/ProcInstr.scala b/src/library/scala/xml/ProcInstr.scala index e70b606fb3..a4bff34271 100644 --- a/src/library/scala/xml/ProcInstr.scala +++ b/src/library/scala/xml/ProcInstr.scala @@ -25,7 +25,8 @@ case class ProcInstr(target:String, proctext:String) extends SpecialNode if (text.indexOf("?>") != -1) throw new IllegalArgumentException(proctext+" may not contain \"?>\"") - final override def collectNamespacesAndDontTransform = false + final override def doCollectNamespaces = false + final override def doTransform = false (target: Seq[Char]) match { case Seq('X'|'x','M'|'m','L'|'l') => diff --git a/src/library/scala/xml/Utility.scala b/src/library/scala/xml/Utility.scala index 17584ee40d..8e4c42c255 100644 --- a/src/library/scala/xml/Utility.scala +++ b/src/library/scala/xml/Utility.scala @@ -143,7 +143,7 @@ object Utility extends AnyRef with parsing.TokenTests * @param set ... */ def collectNamespaces(n: Node, set: Set[String]) { - if (n.collectNamespacesAndDontTransform) { + if (n.doCollectNamespaces) { set += n.namespace for (a <- n.attributes) a match { case _:PrefixedAttribute => diff --git a/src/library/scala/xml/transform/BasicTransformer.scala b/src/library/scala/xml/transform/BasicTransformer.scala index e566e27d02..90e248019d 100644 --- a/src/library/scala/xml/transform/BasicTransformer.scala +++ b/src/library/scala/xml/transform/BasicTransformer.scala @@ -18,136 +18,55 @@ package scala.xml.transform */ abstract class BasicTransformer extends Function1[Node,Node] { - protected case class NeedsCopy(result: Seq[Node]) extends Throwable - - /** Returns a new node buffer with the first <code>pos</code> elements - * from <code>ns</code>. - * - * @param pos .. - * @param ns .. - * @return .. - */ - protected def buffer(pos: Int, ns: Seq[Node]): NodeBuffer = { - val nb = new NodeBuffer() - var jt = ns.iterator - var j = 0; while (j < pos-1) { - nb.append(jt.next) - j += 1 - } - nb - } - - /** Turns a nodebuffer into a sequence, so hashcode works. - * - * @param nb .. - * @return .. - */ - protected def freeze(nb: NodeBuffer): Seq[Node] = { - val arr = new Array[Node](nb.length) - var i = 0 - val it = nb.iterator; while (it.hasNext) { - arr(i) = it.next - i += 1 - } - val seq: Seq[Node] = arr - seq - } - - protected def single(ns: Seq[Node]) = - 1 == ns.length - /** * @param n ... * @param ns ... * @return ... */ protected def unchanged(n: Node, ns: Seq[Node]) = - single(ns) && (ns.iterator.next.eq(n)) + ns.length == 1 && (ns.head eq n) /** Call transform(Node) for each node in ns, append results * to NodeBuffer. */ - def transform(it: Iterator[Node], nb: NodeBuffer): Seq[Node] = { - while (it.hasNext) - nb ++= transform(it.next); - freeze(nb) - } + def transform(it: Iterator[Node], nb: NodeBuffer): Seq[Node] = + it.foldLeft(nb)(_ ++= transform(_)) toArray /** Call transform(Node) to each node in ns, yield ns if nothing changes, * otherwise a new sequence of concatenated results. */ def transform(ns: Seq[Node]): Seq[Node] = { - var i = 0 - val it = ns.iterator - try { - while (it.hasNext) { - val n = it.next - val n2 = transform(n) - if (!unchanged(n, n2)) { - throw NeedsCopy(n2) - } - i += 1 - } - ns - } catch { - case NeedsCopy(n2) => - val nb = buffer(i, ns) - nb ++= (n2:Iterable[xml.Node]) - transform(it, nb) + def testForChange(n: Node): Option[Seq[Node]] = { + val n2 = transform(n) + if (unchanged(n, n2)) None + else Some(n2) } + // if any node is changed by the transform, concatenate + // the unchanged nodes with a recursive call. + for ((n, i) <- ns.zipWithIndex ; n2 <- testForChange(n)) + return (ns take i) ++ transform(n2) + + // no change, return original sequence + ns } def transform(n: Node): Seq[Node] = { - if (!n.collectNamespacesAndDontTransform) - n - else { - val ch = n.child - val nch = transform(ch) - if (ch.eq(nch)) - n - else - Elem(n.prefix, n.label, n.attributes, n.scope, nch:_*) + if (n.doTransform) n match { + case Group(xs) => Group(transform(xs)) // un-group the hack Group tag + case _ => + val ch = n.child + val nch = transform(ch) + + if (ch eq nch) n + else Elem(n.prefix, n.label, n.attributes, n.scope, nch:_*) } + else n } def apply(n: Node): Node = { val seq = transform(n) - if (!single(seq)) + if (seq.length > 1) throw new UnsupportedOperationException("transform must return single node for root"); - else seq.iterator.next - } -} - -/* -class IdentityTransformer extends BasicTransformer { - override def transform(n: Node): Seq[Node] = n.match { - case <world/> => <xml-world/> - case _ => super.transform(n); - } -} - -object Foo with Application { - - val tr = new IdentityTransformer; - val n = tr( <hello><world/></hello> ); - Console.println(n); - - val tr2 = new RewriteRule { - final override val name = "A rule"; - override def transform(n: Node) = n.match { - case <a/> => <b/><c/> - case _ => n - } - } - val tr3 = new RewriteRule { - final override val name = "E rule"; - override def transform(n: Node) = n.match { - case <e/> => <f><f/></f> - case _ => n - } + else seq.head } - val tr4 = new RuleTransformer(tr2, tr3); - val m = tr4( <hello><a/><e/></hello> ); - Console.println(m); } -*/ diff --git a/src/library/scala/xml/transform/RuleTransformer.scala b/src/library/scala/xml/transform/RuleTransformer.scala index 682d7f2f2b..52049115d5 100644 --- a/src/library/scala/xml/transform/RuleTransformer.scala +++ b/src/library/scala/xml/transform/RuleTransformer.scala @@ -12,14 +12,6 @@ package scala.xml.transform class RuleTransformer(rules: RewriteRule*) extends BasicTransformer { - override def transform(n: Node): Seq[Node] = { - var m: Seq[Node] = super.transform(n) - val it = rules.iterator; while (it.hasNext) { - val rule = it.next - val m2 = rule.transform(m) - //if(!m2.eq(m)) Console.println("applied rule \""+rule.name+"\""); - m = m2 - } - m - } + override def transform(n: Node): Seq[Node] = + rules.foldLeft(super.transform(n)) { (res, rule) => rule transform res } } diff --git a/test/files/run/bug2124.check b/test/files/run/bug2124.check new file mode 100644 index 0000000000..2b8840209f --- /dev/null +++ b/test/files/run/bug2124.check @@ -0,0 +1 @@ +<p><lost></lost><q></q></p> diff --git a/test/files/run/bug2124.scala b/test/files/run/bug2124.scala new file mode 100644 index 0000000000..ae16e66706 --- /dev/null +++ b/test/files/run/bug2124.scala @@ -0,0 +1,25 @@ +import scala.xml._ + +import scala.xml.transform._ + +object Test { + val sampleXml = <p><lost/><t><s><r></r></s></t></p> + + def main(args: scala.Array[String]) { + + println(new RuleTransformer(new RewriteRule { + + override def transform(n: Node): NodeSeq = { + val result = n match { + case <t>{_*}</t> => <q/> + + case n => n + + } +// println ("Rewriting '" +n+ "' to: '" + result+ "'") + + result + } + }).transform(sampleXml)) + } +}
\ No newline at end of file diff --git a/test/files/run/bug2125.check b/test/files/run/bug2125.check new file mode 100644 index 0000000000..2b8840209f --- /dev/null +++ b/test/files/run/bug2125.check @@ -0,0 +1 @@ +<p><lost></lost><q></q></p> diff --git a/test/files/run/bug2125.scala b/test/files/run/bug2125.scala new file mode 100644 index 0000000000..053798e3db --- /dev/null +++ b/test/files/run/bug2125.scala @@ -0,0 +1,25 @@ +import scala.xml._ + +import scala.xml.transform._ + +object Test { + + val sampleXml = <xml:group><p><lost/><t><s><r></r></s></t></p></xml:group> + + def main(args: scala.Array[String]) { + println(new RuleTransformer(new RewriteRule { + + override def transform(n: Node): NodeSeq = { + + val result = n match { + + case <t>{_*}</t> => <q/> + + case n => n + } +// println ("Rewriting '" +n+ "' to: '" + result+ "'") + result + } + }).transform(sampleXml)) + } +}
\ No newline at end of file |