Search code examples
scalascala-macrosspotify-scio

Scala macros: string literal assigned to a variable does not match


I am using a macro annotation from Spotify's Scio library. I would like to define a variable of String type and annotate like this:

val schemaString = """schema here"""
@BigQueryType.fromSchema(outputString) class BigQuery

This does not compile, however, if I annotate the String directly, it works:

@BigQueryType.fromSchema("""schema here""") class BigQuery

Looking at the code, this matching is done here, essentially the code is as follows:

def str(tree: c.Tree) = tree match {
      // "string literal"
      case Literal(Constant(s: String)) => s
      // "string literal".stripMargin
      case Select(Literal(Constant(s: String)), TermName("stripMargin")) => s.stripMargin
      case _ => c.abort(c.enclosingPosition, errorMessage)
    }

The question is why this does not match the variable, but does the string? And if there is any way to make the first example work?


Solution

  • The problem is that the value of string variables might not be available at compile-time, when macros are executed. What if it was:

    val schemaString = doSomeComplexFunction()
    @BigQueryType.fromSchema(schemaString) class BigQuery
    

    In theory, maybe the macro could search for where the val is defined and allow it to work if it's just assigned a literal value, but even that can get complex if you start to think about scope.

    So no, there's probably no way to get the first example to work.