Skip to content

Change Node.child and Node.attribute return type to immutable.Seq on 2.13+ #760

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
May 27, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion build.sbt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import sbtcrossproject.CrossPlugin.autoImport.{crossProject, CrossType}
import com.typesafe.tools.mima.core._
import sbtcrossproject.CrossPlugin.autoImport.{CrossType, crossProject}

publish / skip := true // root project

Expand Down Expand Up @@ -68,6 +69,12 @@ lazy val xml = crossProject(JSPlatform, JVMPlatform, NativePlatform)
//import com.typesafe.tools.mima.core.{}
//import com.typesafe.tools.mima.core.ProblemFilters
Seq( // exclusions for all Scala versions
// new method in `Node` with return type `immutable.Seq`
ProblemFilters.exclude[ReversedMissingMethodProblem]("scala.xml.Node.child"),
// these used to be declared methods, but are now bridges without generic signature
ProblemFilters.exclude[IncompatibleSignatureProblem]("scala.xml.Node.nonEmptyChildren"),
ProblemFilters.exclude[IncompatibleSignatureProblem]("scala.xml.Group.child"),
ProblemFilters.exclude[IncompatibleSignatureProblem]("scala.xml.SpecialNode.child"),
) ++ (CrossVersion.partialVersion(scalaVersion.value) match {
case Some((3, _)) => Seq( // Scala 3-specific exclusions
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ private[xml] object ScalaVersionSpecific {
override def apply(): mutable.Builder[Node, NodeSeq] = NodeSeq.newBuilder
}
type SeqNodeUnapplySeq = scala.collection.Seq[Node]

type ChildReturnType = scala.collection.Seq[Node]
}

private[xml] trait ScalaVersionSpecificNodeSeq extends SeqLike[Node, NodeSeq] { self: NodeSeq =>
Expand All @@ -33,3 +35,5 @@ private[xml] trait ScalaVersionSpecificNodeSeq extends SeqLike[Node, NodeSeq] {
private[xml] trait ScalaVersionSpecificNodeBuffer { self: NodeBuffer =>
override def stringPrefix: String = "NodeBuffer"
}

private[xml] trait ScalaVersionSpecificNode {self: Node => }
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ private[xml] object ScalaVersionSpecific {
def fromSpecific(from: Coll)(it: IterableOnce[Node]): NodeSeq = (NodeSeq.newBuilder ++= from).result()
}
type SeqNodeUnapplySeq = scala.collection.immutable.Seq[Node]

type ChildReturnType = scala.collection.immutable.Seq[Node]
}

private[xml] trait ScalaVersionSpecificNodeSeq
Expand Down Expand Up @@ -53,3 +55,10 @@ private[xml] trait ScalaVersionSpecificNodeSeq
private[xml] trait ScalaVersionSpecificNodeBuffer { self: NodeBuffer =>
override def className: String = "NodeBuffer"
}

private[xml] trait ScalaVersionSpecificNode { self: Node =>
// These methods are overridden in Node with return type `immutable.Seq`. The declarations here result
// in a bridge method in `Node` with result type `collection.Seq` which is needed for binary compatibility.
def child: scala.collection.Seq[Node]
def nonEmptyChildren: scala.collection.Seq[Node]
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,18 @@ package scala.xml
What should have been specified explicitly is given in the comments;
next time we break binary compatibility the types should be changed in the code and this class removed.
*/
private[xml] object ScalaVersionSpecificReturnTypes { // should be
type ExternalIDAttribute = MetaData // Null.type
type NoExternalIDId = String // scala.Null
type NodeNoAttributes = MetaData // Null.type
type NullFilter = MetaData // Null.type
type NullGetNamespace = String // scala.Null
type NullNext = MetaData // scala.Null
type NullKey = String // scala.Null
type NullValue = scala.collection.Seq[Node] // scala.Null
type NullApply1 = scala.collection.Seq[Node] // scala.Null
type NullApply3 = scala.collection.Seq[Node] // scala.Null
type NullRemove = MetaData // Null.type
type SpecialNodeChild = scala.collection.Seq[Node] // Nil.type
type GroupChild = scala.collection.Seq[Node] // Nothing
private[xml] object ScalaVersionSpecificReturnTypes { // should be
type ExternalIDAttribute = MetaData // Null.type
type NoExternalIDId = String // scala.Null
type NodeNoAttributes = MetaData // Null.type
type NullFilter = MetaData // Null.type
type NullGetNamespace = String // scala.Null
type NullNext = MetaData // scala.Null
type NullKey = String // scala.Null
type NullValue = scala.collection.Seq[Node] // scala.Null
type NullApply1 = scala.collection.Seq[Node] // scala.Null
type NullApply3 = scala.collection.Seq[Node] // scala.Null
type NullRemove = MetaData // Null.type
type SpecialNodeChild = scala.collection.immutable.Seq[Node] // Nil.type
type GroupChild = scala.collection.immutable.Seq[Node] // Nothing
}
6 changes: 3 additions & 3 deletions shared/src/main/scala/scala/xml/Node.scala
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ object Node {
*
* @author Burak Emir and others
*/
abstract class Node extends NodeSeq {
abstract class Node extends NodeSeq with ScalaVersionSpecificNode {

/** prefix of this node */
def prefix: String = null
Expand Down Expand Up @@ -120,12 +120,12 @@ abstract class Node extends NodeSeq {
*
* @return all children of this node
*/
def child: Seq[Node]
def child: ScalaVersionSpecific.ChildReturnType

/**
* Children which do not stringify to "" (needed for equality)
*/
def nonEmptyChildren: Seq[Node] = child.filterNot(_.toString.isEmpty)
def nonEmptyChildren: ScalaVersionSpecific.ChildReturnType = child.filterNot(_.toString.isEmpty)

/**
* Descendant axis (all descendants of this node, not including node itself)
Expand Down