diff options
author | Eugene Burmako <xeno.by@gmail.com> | 2015-02-22 18:50:33 +0100 |
---|---|---|
committer | Eugene Burmako <xeno.by@gmail.com> | 2015-02-22 18:50:33 +0100 |
commit | 97f7f5868961264d60a65cfdc3f8e8cdd6502164 (patch) | |
tree | d71ae18664d0fac9a8ae95f0e78112bac2fbaa2b | |
parent | 3a32ae3651f69237bde32598674bc135ad9e4064 (diff) | |
download | scala-97f7f5868961264d60a65cfdc3f8e8cdd6502164.tar.gz scala-97f7f5868961264d60a65cfdc3f8e8cdd6502164.tar.bz2 scala-97f7f5868961264d60a65cfdc3f8e8cdd6502164.zip |
fixes pluginsEnterStats
Initial implementation of pluginsEnterStats was incorrect, because I got
the foldLeft wrong, making it perpetuate the initial value of stats.
This worked fine if zero or one macro plugins were active at a time,
but broke down if there were multiple of such plugins (concretely,
I discovered this issue when trying to marry macro paradise with scalahost).
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/AnalyzerPlugins.scala | 2 | ||||
-rw-r--r-- | test/files/run/macroPlugins-enterStats.check | 30 | ||||
-rw-r--r-- | test/files/run/macroPlugins-enterStats.scala | 50 |
3 files changed, 81 insertions, 1 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/AnalyzerPlugins.scala b/src/compiler/scala/tools/nsc/typechecker/AnalyzerPlugins.scala index 5a70d4c524..2c27bdb03a 100644 --- a/src/compiler/scala/tools/nsc/typechecker/AnalyzerPlugins.scala +++ b/src/compiler/scala/tools/nsc/typechecker/AnalyzerPlugins.scala @@ -447,6 +447,6 @@ trait AnalyzerPlugins { self: Analyzer => // performance opt if (macroPlugins.isEmpty) stats else macroPlugins.foldLeft(stats)((current, plugin) => - if (!plugin.isActive()) current else plugin.pluginsEnterStats(typer, stats)) + if (!plugin.isActive()) current else plugin.pluginsEnterStats(typer, current)) } } diff --git a/test/files/run/macroPlugins-enterStats.check b/test/files/run/macroPlugins-enterStats.check new file mode 100644 index 0000000000..133b1ae1af --- /dev/null +++ b/test/files/run/macroPlugins-enterStats.check @@ -0,0 +1,30 @@ +[[syntax trees at end of typer]] // newSource1.scala +package <empty> { + class C extends scala.AnyRef { + def <init>(): C = { + C.super.<init>(); + () + }; + def x: Int = 2; + def xmacroPlugin1: Nothing = scala.this.Predef.???; + def xmacroPlugin2: Nothing = scala.this.Predef.???; + def xmacroPlugin2macroPlugin1: Nothing = scala.this.Predef.???; + def y: Int = 3; + def ymacroPlugin1: Nothing = scala.this.Predef.???; + def ymacroPlugin2: Nothing = scala.this.Predef.???; + def ymacroPlugin2macroPlugin1: Nothing = scala.this.Predef.??? + } +} + +macroPlugin2:enterStat(class C extends scala.AnyRef { def <init>() = { super.<init>(); () }; def x = 2; def y = 3 }) +macroPlugin1:enterStat(class C extends scala.AnyRef { def <init>() = { super.<init>(); () }; def x = 2; def y = 3 }) +macroPlugin2:enterStat(def <init>() = { super.<init>(); () }) +macroPlugin2:enterStat(def x = 2) +macroPlugin2:enterStat(def y = 3) +macroPlugin1:enterStat(def <init>() = { super.<init>(); () }) +macroPlugin1:enterStat(def x = 2) +macroPlugin1:enterStat(def xmacroPlugin2 = $qmark$qmark$qmark) +macroPlugin1:enterStat(def y = 3) +macroPlugin1:enterStat(def ymacroPlugin2 = $qmark$qmark$qmark) +macroPlugin2:enterStat(super.<init>()) +macroPlugin1:enterStat(super.<init>()) diff --git a/test/files/run/macroPlugins-enterStats.scala b/test/files/run/macroPlugins-enterStats.scala new file mode 100644 index 0000000000..917233e990 --- /dev/null +++ b/test/files/run/macroPlugins-enterStats.scala @@ -0,0 +1,50 @@ +import scala.tools.partest._ +import scala.tools.nsc._ + +object Test extends DirectTest { + override def extraSettings: String = "-usejavacp -Xprint:typer" + + def code = """ + class C { + def x = 2 + def y = 3 + } + """.trim + + def show() { + val global = newCompiler() + import global._ + import analyzer._ + + val output = collection.mutable.ListBuffer[String]() + def log(what: String) = output += what.replace(String.format("%n"), " ") + + def logEnterStat(pluginName: String, stat: Tree): Unit = log(s"$pluginName:enterStat($stat)") + def deriveStat(pluginName: String, typer: Typer, stat: Tree): List[Tree] = stat match { + case DefDef(mods, name, Nil, Nil, TypeTree(), body) => + val derived = DefDef(NoMods, TermName(name + pluginName), Nil, Nil, TypeTree(), Ident(TermName("$qmark$qmark$qmark"))) + newNamer(typer.context).enterSym(derived) + List(derived) + case _ => + Nil + } + + object macroPlugin1 extends MacroPlugin { + override def pluginsEnterStats(typer: Typer, stats: List[Tree]): List[Tree] = { + stats.foreach(stat => logEnterStat("macroPlugin1", stat)) + stats.flatMap(stat => stat +: deriveStat("macroPlugin1", typer, stat)) + } + } + object macroPlugin2 extends MacroPlugin { + override def pluginsEnterStats(typer: Typer, stats: List[Tree]): List[Tree] = { + stats.foreach(stat => logEnterStat("macroPlugin2", stat)) + stats.flatMap(stat => stat +: deriveStat("macroPlugin2", typer, stat)) + } + } + + addMacroPlugin(macroPlugin1) + addMacroPlugin(macroPlugin2) + compileString(global)(code) + println(output.mkString("\n")) + } +} |