stholzm
stholzm

Reputation: 3455

Type mismatch with Binding.scala involving scala.xml.Elem

I'm failing to compile a simple example of Binding.scala, and being a newbie, I have no intuition how to fix it. Maybe the README is slightly outdated? The example at https://github.com/ThoughtWorksInc/Binding.scala-sample is even older and causes deprecation warnings.

My code, which I basically stuck together from the README, and even simplified a bit:

import com.thoughtworks.binding.dom
import org.scalajs.dom.document
import scala.scalajs.js.annotation.JSExport

@JSExport
object SampleMain {

  @dom
  def table = {
    <table border="1" cellPadding="5">
      <thead>
        <tr>
          <th>Name</th>
          <th>E-mail</th>
        </tr>
      </thead>
      <tbody>
      </tbody>
    </table>
  }

  @JSExport
  def main(): Unit = {
    dom.render(document.body, table)
  }

}

fastOptJS causes a compile error:

SampleMain.scala:25:9: overloaded method value render with alternatives:
[error]   (parent: org.scalajs.dom.raw.Node,children: com.thoughtworks.binding.Binding[com.thoughtworks.binding.Binding.BindingSeq[org.scalajs.dom.raw.Node]],dummy: Unit)Unit <and>
[error]   (parent: org.scalajs.dom.raw.Node,children: com.thoughtworks.binding.Binding.BindingSeq[org.scalajs.dom.raw.Node])Unit <and>
[error]   (parent: org.scalajs.dom.raw.Node,child: com.thoughtworks.binding.Binding[org.scalajs.dom.raw.Node])Unit
[error]  cannot be applied to (org.scalajs.dom.raw.HTMLElement, scala.xml.Elem)
[error]     dom.render(document.body, table)
[error]         ^

I suspected a problem with type inference and tried this type annotation: def table: com.thoughtworks.binding.Binding[org.scalajs.dom.html.Table] but this caused another error:

SampleMain.scala:11:6: type mismatch;
[error]  found   : scala.xml.Elem
[error]  required: com.thoughtworks.binding.Binding[org.scalajs.dom.html.Table]
[error]     (which expands to)  com.thoughtworks.binding.Binding[org.scalajs.dom.raw.HTMLTableElement]
[error]     <table border="1" cellPadding="5">
[error]      ^

I'd appreciate an explanation what is going wrong here.


Solution: https://stackoverflow.com/a/55137909/1862339

Upvotes: 2

Views: 349

Answers (3)

stholzm
stholzm

Reputation: 3455

Turns out the problem was that the paradise compiler plugin was not picked up in my case. I'm building an SBT multi-project with Binding.scala in a sub-project only, and addCompilerPlugin does not propagate to sub-projects. To make it work, it needs to be added to the sub-project's settings like this:

lazy val client = (project in file("client"))
  .settings(
    libraryDependencies ++= Seq(
      "com.thoughtworks.binding" %%% "dom" % "11.6.0"
    ),
    addCompilerPlugin("org.scalamacros" % "paradise" % "2.1.0" cross CrossVersion.full)
  )
  .enablePlugins(ScalaJSPlugin)

Before I had addCompilerPlugin at the top-level of build.sbt, which did not work and caused the compile error.

Upvotes: 3

Yang Bo
Yang Bo

Reputation: 3718

There should be an error message, which asks you to enable the paradise compiler plug-in. Unfortunately because you are using Scala 2.10, a bug in macro-compat prevent you to see the error message.

So the long answer is:

  1. Upgrade Scala to 2.11 or 2.12, by setting something like scalaVersion in ThisBuild := "2.12.8" in your build.sbt.
  2. You will see an error message that asks you to add the paradise plug-in.
  3. Finally, add the following setting in your build.sbt according to the error message:
addCompilerPlugin("org.scalamacros" % "paradise" % "2.1.0" cross CrossVersion.full)

Upvotes: 2

lmars
lmars

Reputation: 302

Check that you have added this to your build.sbt

addCompilerPlugin("org.scalamacros" % "paradise" % "2.1.0" cross CrossVersion.full)

The main macro of Binding.scala (which translates Scala XML literals into special Binding types) does not work without this plugin and the compiler sees only the original types (scala.xml.Elem).

This is mentioned in the Step 1 of the README.

Upvotes: 2

Related Questions