JohnReedLOL / scala-trace-debug

Macro based print debugging. Locates log statements in your IDE.
https://github.com/JohnReedLOL/pos
MIT License
115 stars 5 forks source link

macros desugars code blocks #2

Open MasseGuillaume opened 8 years ago

MasseGuillaume commented 8 years ago

for example I see this in the trace

{
  val someVal = 2;
  (1).+(someVal).==(4)
}

I expect

{
  val someVal = 2
  1 + someVal == 4
}

this project solve the problem https://github.com/lihaoyi/sourcecode#debug-prints

scalameta also has a good print of ast, but no def macro support yet. https://github.com/scalameta/tutorial/tree/advanced-dendrology#showsyntax

JohnReedLOL commented 8 years ago

"sourcecode.Text[T]: when you want to take a value of type T, but also want to get the "source text" of that particular value. Note that if you have multiple statements in a {} block, "sourcecode.Text" will only capture the source code for the last expression that gets returned... sourcecode does not rely on runtime reflection or stack inspection, and is done at compile-time using macros. " - lihaoyi/sourcecode

Wait a second. If you have multiple statements... only capture the last expression that gets returned. I don't know if I am reading this correctly, but I don't think that this will work with multi-line expressions.

"The simplest prettyprinter in scala.meta is show[Syntax] that prints the code that the tree represents." - scalameta/tutorial

That looks nice, but it is pre-release, so I don't know if it will work in production.

In case neither of those things work, a temporary fix would be to manually get rid of the "." on all the scala operators via string manipulation and wait for scalameta to come out of pre-release

// Removal of "." produces a small but noticeable improvement
{
  val someVal = 2;
  (1) +(someVal) ==(4)
}

You can choose any of these three solutions as long as it works and it does not break anything and I will approve it.

JohnReedLOL commented 8 years ago

Hey Gaullaume,

I was wrong about the source code. Check this out:

case class Text[T](value: T, source: String) object Text{ implicit def generate[T](v: T): Text[T] = macro Impls.text[T] def apply[T](v: T): Text[T] = macro Impls.text[T]

} object Impls{ def text[T: c.WeakTypeTag](c: Compat.Context)(v: c.Expr[T]): c.Expr[sourcecode.Text[T]] = { import c.universe._ val fileContent = new String(v.tree.pos.source.content) val start = v.tree.collect{case tree => tree.pos.startOrPoint}.min val g = c.asInstanceOf[reflect.macros.runtime.Context].global val parser = g.newUnitParser(fileContent.drop(start)) parser.expr() val end = parser.in.lastOffset val txt = fileContent.slice(start, start + end) val tree = q"""${c.prefix}(${v.tree}, $txt)""" c.Exprsourcecode.Text[T] }

^ You mentioned sourceCode.Text and I didn't actually read it.

/* Java file corresponding to the source file of this position.

^ The line "v.tree.pos.source.content" actually appears to be able to get the actual raw string.

JohnReedLOL commented 8 years ago

I solved the problem.

val fooVar = "foo"
val barVar = "bar"
Debug.traceCode{fooVar + barVar} // "(fooVar + barVar) -> foobar" in thread run-main-0:
Debug.traceCode({fooVar + barVar}, 3)
Debug.traceStackCode{fooVar + barVar}

Note that it does not always behave as you would expect. Example:

val trueVar = true
val falseVar = false
Debug.assertCode{(trueVar || falseVar || false) && false} // "trueVar || falseVar || false -> false" in thread run-main-1:

The reason is because if you wrap an expression in parenthesis, it cuts off everything outside the parenthesis. So (lala).toString becomes lala.

libraryDependencies += "scala-trace-debug" %% "scala-trace-debug" % "0.1.6"