diff options
author | Eugene Burmako <xeno.by@gmail.com> | 2012-12-25 02:37:31 +0100 |
---|---|---|
committer | Eugene Burmako <xeno.by@gmail.com> | 2013-01-05 01:39:15 +0300 |
commit | 348c8fac9f897f9661f84e32949b8a4e0c99e93a (patch) | |
tree | 810b2d7d53451ceba5e43e1687a86cdedffd39f1 /test | |
parent | ed4f4798df2ac104d9557de2241d8e89283b0662 (diff) | |
download | scala-348c8fac9f897f9661f84e32949b8a4e0c99e93a.tar.gz scala-348c8fac9f897f9661f84e32949b8a4e0c99e93a.tar.bz2 scala-348c8fac9f897f9661f84e32949b8a4e0c99e93a.zip |
adds c.introduceTopLevel
The first in the family of mutators for the global symbol table,
`introduceTopLevel` is capable of creating synthetic top-level
classes and modules.
The addition of nme.EMPTY_PACKAGE_NAME is necessary to let
programmers insert definitions into the empty package. That's explicitly
discouraged in the docs, but at times might come in handy.
This patch introduce workarounds to avoid incompatibilities with SBT.
First of all SBT doesn't like VirtualFiles having JFile set to null.
Secondly SBT gets confused when someone depends on synthetic files
added by c.introduceTopLevel.
Strictly speaking these problems require changes to SBT, and that will be
done later. However the main target of the patch is paradise/macros,
which needs to be useful immediately, therefore we apply workarounds.
Diffstat (limited to 'test')
19 files changed, 139 insertions, 7 deletions
diff --git a/test/files/pos/annotated-treecopy/Impls_Macros_1.scala b/test/files/pos/annotated-treecopy/Impls_Macros_1.scala index d92fbca380..cf58bc3dfd 100644 --- a/test/files/pos/annotated-treecopy/Impls_Macros_1.scala +++ b/test/files/pos/annotated-treecopy/Impls_Macros_1.scala @@ -21,7 +21,7 @@ object Macros { // normalize argument name var b1 = new Transformer { override def transform(tree: Tree): Tree = tree match { - case Ident(x) if (x==n) => Ident(newTermName("_arg")) + case Ident(x) if (x==n) => Ident(TermName("_arg")) case tt @ TypeTree() if tt.original != null => TypeTree(tt.tpe) setOriginal transform(tt.original) // without the fix to LazyTreeCopier.Annotated, we would need to uncomment the line below to make the macro work // that's because the pattern match in the input expression gets expanded into Typed(<x>, TypeTree(<Int @unchecked>)) diff --git a/test/files/pos/attachments-typed-another-ident/Impls_1.scala b/test/files/pos/attachments-typed-another-ident/Impls_1.scala index 957bafc6ae..c3f541075e 100644 --- a/test/files/pos/attachments-typed-another-ident/Impls_1.scala +++ b/test/files/pos/attachments-typed-another-ident/Impls_1.scala @@ -6,7 +6,7 @@ object MyAttachment object Macros { def impl(c: Context) = { import c.universe._ - val ident = Ident(newTermName("bar")) updateAttachment MyAttachment + val ident = Ident(TermName("bar")) updateAttachment MyAttachment assert(ident.attachments.get[MyAttachment.type].isDefined, ident.attachments) val typed = c.typeCheck(ident) assert(typed.attachments.get[MyAttachment.type].isDefined, typed.attachments) diff --git a/test/files/pos/attachments-typed-ident/Impls_1.scala b/test/files/pos/attachments-typed-ident/Impls_1.scala index cc40893a93..c382cabc59 100644 --- a/test/files/pos/attachments-typed-ident/Impls_1.scala +++ b/test/files/pos/attachments-typed-ident/Impls_1.scala @@ -6,7 +6,7 @@ object MyAttachment object Macros { def impl(c: Context) = { import c.universe._ - val ident = Ident(newTermName("bar")) updateAttachment MyAttachment + val ident = Ident(TermName("bar")) updateAttachment MyAttachment assert(ident.attachments.get[MyAttachment.type].isDefined, ident.attachments) val typed = c.typeCheck(ident) assert(typed.attachments.get[MyAttachment.type].isDefined, typed.attachments) diff --git a/test/files/run/macro-duplicate/Impls_Macros_1.scala b/test/files/run/macro-duplicate/Impls_Macros_1.scala index de81923330..af80147a90 100644 --- a/test/files/run/macro-duplicate/Impls_Macros_1.scala +++ b/test/files/run/macro-duplicate/Impls_Macros_1.scala @@ -10,11 +10,11 @@ object Macros { case Template(_, _, ctor :: defs) => val defs1 = defs collect { case ddef @ DefDef(mods, name, tparams, vparamss, tpt, body) => - val future = Select(Select(Select(Ident(newTermName("scala")), newTermName("concurrent")), newTermName("package")), newTermName("future")) - val Future = Select(Select(Ident(newTermName("scala")), newTermName("concurrent")), newTypeName("Future")) + val future = Select(Select(Select(Ident(TermName("scala")), TermName("concurrent")), TermName("package")), TermName("future")) + val Future = Select(Select(Ident(TermName("scala")), TermName("concurrent")), TypeName("Future")) val tpt1 = if (tpt.isEmpty) tpt else AppliedTypeTree(Future, List(tpt)) val body1 = Apply(future, List(body)) - val name1 = newTermName("async" + name.toString.capitalize) + val name1 = TermName("async" + name.toString.capitalize) DefDef(mods, name1, tparams, vparamss, tpt1, body1) } Template(Nil, emptyValDef, ctor +: defs ::: defs1) diff --git a/test/files/run/macro-toplevel-companion-a.check b/test/files/run/macro-toplevel-companion-a.check new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/test/files/run/macro-toplevel-companion-a.check diff --git a/test/files/run/macro-toplevel-companion-a.flags b/test/files/run/macro-toplevel-companion-a.flags new file mode 100644 index 0000000000..cd66464f2f --- /dev/null +++ b/test/files/run/macro-toplevel-companion-a.flags @@ -0,0 +1 @@ +-language:experimental.macros
\ No newline at end of file diff --git a/test/files/run/macro-toplevel-companion-a/Impls_Macros_1.scala b/test/files/run/macro-toplevel-companion-a/Impls_Macros_1.scala new file mode 100644 index 0000000000..23e8694ddc --- /dev/null +++ b/test/files/run/macro-toplevel-companion-a/Impls_Macros_1.scala @@ -0,0 +1,14 @@ +import scala.reflect.macros.Context +import language.experimental.macros + +object Macros { + def impl(c: Context) = { + import c.universe._ + val synthetic = reify{ class C { override def toString = "C" }; object C { implicit val c = new C } }.tree + val defs = synthetic.asInstanceOf[Block].stats.asInstanceOf[List[ImplDef]] + if (c.topLevelRef(TypeName("C")).isEmpty) c.introduceTopLevel(nme.EMPTY_PACKAGE_NAME.toString, defs: _*) + c.literalUnit + } + + def foo = macro impl +}
\ No newline at end of file diff --git a/test/files/run/macro-toplevel-companion-a/Test_2.scala b/test/files/run/macro-toplevel-companion-a/Test_2.scala new file mode 100644 index 0000000000..78b65b5b1f --- /dev/null +++ b/test/files/run/macro-toplevel-companion-a/Test_2.scala @@ -0,0 +1,8 @@ +import Macros._ + +object Test extends App { + foo; + implicitly[C]; + foo; + implicitly[C]; +}
\ No newline at end of file diff --git a/test/files/run/macro-toplevel-companion-b.check b/test/files/run/macro-toplevel-companion-b.check new file mode 100644 index 0000000000..bd30dc75d3 --- /dev/null +++ b/test/files/run/macro-toplevel-companion-b.check @@ -0,0 +1,4 @@ +reflective compilation has failed: + +Companions 'class C' and 'object C' must be defined in same file: + Found in <synthetic file name> and <synthetic file name> diff --git a/test/files/run/macro-toplevel-companion-b.flags b/test/files/run/macro-toplevel-companion-b.flags new file mode 100644 index 0000000000..cd66464f2f --- /dev/null +++ b/test/files/run/macro-toplevel-companion-b.flags @@ -0,0 +1 @@ +-language:experimental.macros
\ No newline at end of file diff --git a/test/files/run/macro-toplevel-companion-b/Impls_Macros_1.scala b/test/files/run/macro-toplevel-companion-b/Impls_Macros_1.scala new file mode 100644 index 0000000000..f30adc2965 --- /dev/null +++ b/test/files/run/macro-toplevel-companion-b/Impls_Macros_1.scala @@ -0,0 +1,15 @@ +import scala.reflect.macros.Context +import language.experimental.macros + +object Macros { + def impl(c: Context) = { + import c.universe._ + val Block(List(cdef: ClassDef), _) = reify{ class C }.tree + val classRef = c.topLevelRef(TypeName("C")) orElse c.introduceTopLevel(nme.EMPTY_PACKAGE_NAME.toString, cdef) + val Block(List(mdef: ModuleDef), _) = reify{ object C }.tree + val moduleRef = c.topLevelRef(TermName("C")) orElse c.introduceTopLevel(nme.EMPTY_PACKAGE_NAME.toString, mdef) + c.literalUnit + } + + def foo = macro impl +}
\ No newline at end of file diff --git a/test/files/run/macro-toplevel-companion-b/Test_2.scala b/test/files/run/macro-toplevel-companion-b/Test_2.scala new file mode 100644 index 0000000000..ca202d053f --- /dev/null +++ b/test/files/run/macro-toplevel-companion-b/Test_2.scala @@ -0,0 +1,11 @@ +import scala.reflect.runtime.universe._ +import scala.reflect.runtime.{universe => ru} +import scala.reflect.runtime.{currentMirror => cm} +import scala.tools.reflect.{ToolBox, ToolBoxError} +import Macros._ + +object Test extends App { + val tb = cm.mkToolBox() + try tb.compile(Select(Ident(TermName("Macros")), TermName("foo"))) + catch { case ToolBoxError(message, _) => println("""macroSynthetic-.*?\.scala""".r.replaceAllIn(message, "<synthetic file name>")) } +}
\ No newline at end of file diff --git a/test/files/run/macro-toplevel-companion-c.check b/test/files/run/macro-toplevel-companion-c.check new file mode 100644 index 0000000000..8b422c2061 --- /dev/null +++ b/test/files/run/macro-toplevel-companion-c.check @@ -0,0 +1,3 @@ +error: Companions 'class C' and 'object C' must be defined in same file: + Found in <synthetic file name> and newSource1 + diff --git a/test/files/run/macro-toplevel-companion-c.flags b/test/files/run/macro-toplevel-companion-c.flags new file mode 100644 index 0000000000..cd66464f2f --- /dev/null +++ b/test/files/run/macro-toplevel-companion-c.flags @@ -0,0 +1 @@ +-language:experimental.macros
\ No newline at end of file diff --git a/test/files/run/macro-toplevel-companion-c.scala b/test/files/run/macro-toplevel-companion-c.scala new file mode 100644 index 0000000000..0e99903158 --- /dev/null +++ b/test/files/run/macro-toplevel-companion-c.scala @@ -0,0 +1,51 @@ +import scala.tools.partest._ +import java.io._ + +object Test extends DirectTest { + def code = ??? + + def macros_1 = """ + package test + + import scala.reflect.macros.Context + import language.experimental.macros + + object Macros { + def impl(c: Context) = { + import c.universe._ + val Block(List(cdef: ClassDef), _) = reify{ class C }.tree + val ref = c.topLevelRef(TypeName("test.C")) orElse c.introduceTopLevel("test", cdef) + c.literalUnit + } + + def foo = macro impl + } + """ + def compileMacros() = { + val classpath = List(sys.props("partest.lib"), sys.props("partest.reflect")) mkString sys.props("path.separator") + compileString(newCompiler("-language:experimental.macros", "-cp", classpath, "-d", testOutput.path))(macros_1) + } + + def test_2 = """ + package test + object C { Macros.foo } + """ + def compileTest() = { + val classpath = List(sys.props("partest.lib"), testOutput.path) mkString sys.props("path.separator") + compileString(newCompiler("-cp", classpath, "-d", testOutput.path))(test_2) + } + + def show(): Unit = { + // redirect err to string, for logging + val prevErr = System.err + val baos = new ByteArrayOutputStream() + System.setErr(new PrintStream(baos)) + log("Compiling Macros_1...") + if (compileMacros()) { + log("Compiling Test_2...") + if (compileTest()) log("Success!") else log("Failed...") + } + println("""macroSynthetic-.*?\.scala""".r.replaceAllIn(baos.toString, "<synthetic file name>")) + System.setErr(prevErr) + } +}
\ No newline at end of file diff --git a/test/files/run/macro-toplevel.check b/test/files/run/macro-toplevel.check new file mode 100644 index 0000000000..257c3764fd --- /dev/null +++ b/test/files/run/macro-toplevel.check @@ -0,0 +1,2 @@ +I've been created from Macros.foo +I've been created from Macros.foo diff --git a/test/files/run/macro-toplevel/Macros_1.scala b/test/files/run/macro-toplevel/Macros_1.scala new file mode 100644 index 0000000000..f681c86735 --- /dev/null +++ b/test/files/run/macro-toplevel/Macros_1.scala @@ -0,0 +1,15 @@ +import scala.reflect.macros.Context +import language.experimental.macros + +object Macros { + def impl(c: Context) = { + import c.universe._ + val msg = "I've been created from " + c.macroApplication + val Block(List(synthetic: ClassDef), _) = reify{ class SomeUniqueName { def hello = c.literal(msg).splice } }.tree + val ref = c.topLevelRef(synthetic.name) orElse c.introduceTopLevel(nme.EMPTY_PACKAGE_NAME.toString, synthetic) + c.Expr[String](Select(Apply(Select(New(ref), nme.CONSTRUCTOR), List()), TermName("hello"))) + } + + def foo = macro impl + def foo2 = macro impl +} diff --git a/test/files/run/macro-toplevel/Test_2.scala b/test/files/run/macro-toplevel/Test_2.scala new file mode 100644 index 0000000000..eee2d6ae13 --- /dev/null +++ b/test/files/run/macro-toplevel/Test_2.scala @@ -0,0 +1,6 @@ +import Macros._ + +object Test extends App { + println(Macros.foo) + println(Macros.foo2) +}
\ No newline at end of file diff --git a/test/files/run/t6548.scala b/test/files/run/t6548.scala index be3eb5b932..b4d09fd8f6 100644 --- a/test/files/run/t6548.scala +++ b/test/files/run/t6548.scala @@ -8,5 +8,5 @@ class Bean { object Test extends App { println(cm.staticClass("Bean").isCaseClass) - println(typeOf[Bean].declaration(newTermName("value")).annotations) + println(typeOf[Bean].declaration(TermName("value")).annotations) } |