我想从给定的Scala项目中提取所有方法的调用图,这些方法是项目自己的源代码的一部分.
据我所知,演示编译器没有启用它,它需要一直向下到实际的编译器(或编译器插件?).
您能否建议完整的代码,这些代码可以安全地用于大多数scala项目,但是那些使用最古怪的动态语言功能的代码?对于调用图,我的意思是包含class/trait + method顶点的有向(可能是循环的)图,其中边A-> B表示A可以调用B.
应避免或"标记"来自/来自图书馆的呼叫在项目自己的来源之外.
编辑:
看看我的宏天堂衍生原型解决方案,基于@ dk14的主角,作为下面的答案.在https://github.com/matanster/sbt-example-paradise上的github上托管.
我想在Scala 2.11+中使用注释宏生成方法的别名.我甚至不确定是否可能.如果有,怎么样?
示例 - 如下所示,我希望注释宏扩展为
class Socket {
@alias(aliases = Seq("!", "ask", "read"))
def load(n: Int): Seq[Byte] = {/* impl */}
}
Run Code Online (Sandbox Code Playgroud)
我想要上面生成同义词方法存根,如下所示:
class Socket {
def load(n: Int): Seq[Byte] = // ....
def !(n: Int) = load(n)
def ask(n: Int) = load(n)
def read(n: Int) = load(n)
}
Run Code Online (Sandbox Code Playgroud)
以上当然是一个诙谐的例子,但我可以看到这种技术对于自动生成API的同步/异步版本或在具有大量同义词的DSL中很有用.是否也可以在Scaladoc中公开这些生成的方法?这可能是使用Scala meta吗?
注意:我要问的是:https://github.com/ktoso/scala-macro-method-alias
也请不要纪念这个作为重复这个因为这个问题是有点不同,很多斯卡拉宏观土地已经改变了过去3年.
以下是三年多前的Macros: The Plan for Scala 3中的一段话:
例如,我们可以定义一个宏注释 @json,将 JSON 序列化器添加到一种类型中。
知道这在 Scala 3 中如何/是否可行吗?
更一般地说,Scala 3 中有什么可以提供“宏注释”功能吗?以下是宏注释 - Scala 2.13的引用:
与以前版本的宏天堂不同,2.0 中的宏注释在以下意义上是正确的:1) 不仅适用于类和对象,而且适用于任意定义,2)允许扩展类来修改甚至创建伴生对象
我想写一个丰富案例类的宏.当我声明我的案例类时:
case class User(int id, @tagged name)
我希望能够在Tree这个只有注释的类中注入一些东西.到目前为止,我只能够达到Symbol的封装类的,但看起来还不够(见尤金的答案在这里).我也不想使用弃用的api c.enclosingClass.有没有办法ClassDef在天堂2.1.0(Scala 2.11)达到父母?
我刚刚更新到scala meta 2.0.0-M1和最新的scala 2.12.3,现在宏不再编译了.我做的唯一改变是将元版本从1.8.0更改为2.0.0-M1.
错误:新式("内联")宏需要scala.meta
有人知道是否有快速的解决方法吗?
我希望开始玩一些语义改进.
我想做这样的事情:
def assuming[A](condition: => Boolean)(f: => A): A = {
require(condition, /* print source-code of condition */)
f
}
Run Code Online (Sandbox Code Playgroud)
样品用法:
def fib(n: Int) = n match { // yes, yes, I know this is not efficient
case 0 => 0
case 1 => 1
case i => assuming(i > 0) { fib(i-1) + fib(i-2) }
}
Run Code Online (Sandbox Code Playgroud)
现在,例如,如果你调用fib(-20),我希望它抛出一个带有Assertion failed: -20 > 0或的消息的异常Assertation failed: i > 0
scala scala-2.10 scala-macros scala-2.11 scala-macro-paradise
我正在写一个SBT插件.我想使用Circe JSON库,但它需要Scala 2.10上的Macro Paradise编译器插件.
通常,您将编译器插件添加到build.sbtSBT插件project/plugins.sbt.
现在,当您构建SBT插件时,其他插件将成为依赖项,因此您将它们放入并将build.sbt它们传播到您使用SBT插件的项目.
当我将以下片段放入build.sbt我的SBT插件时:
addCompilerPlugin("org.scalamacros" % "paradise" % "2.1.0" cross CrossVersion.full)
Run Code Online (Sandbox Code Playgroud)
Paradise编译器插件是否会传播到下游项目?
我想知道Scala是否支持递归宏扩展,例如我正在尝试使用透镜宏编写镜头库来执行此操作:
case class C(d: Int)
case class B(c: C)
case class A(b: B)
val a = A(B(C(10))
val aa = lens(a)(_.b.c.d)(_ + 12)
assert(aa.b.c.d == 22)
Run Code Online (Sandbox Code Playgroud)
鉴于lens(a)(_.b.c.d)(f),我想将其转换为a.copy(b = lens(a.b)(_.c.d)(f))
编辑: 我在这里取得了不错的进展
但是,我无法想出一个通用的方法来创建一个访问器,List[TermName]例如上面的例子,鉴于我有List(TermName('b'), TermName('c'), TermName('d'))),我想生成一个匿名函数,_.b.c.d即(x: A) => x.b.c.d.我怎么做?
基本上,我如何以通用方式编写这些行?
鉴于此,我想编写一个宏:
@MetaRest case class User(
@get id : Int,
@get @post @patch name : String,
@get @post email : String,
registeredOn : DateTime
)
Run Code Online (Sandbox Code Playgroud)
生成以下代码段:
object User {
case class Get(id: Int, name: String, email: String)
case class Post(name: String, email: String
case class Patch(name: Option[String]) // Note - the Option type here!
}
Run Code Online (Sandbox Code Playgroud)
我在这里取得了不错的进展:https : //github.com/pathikrit/metarest
这是我的尝试:https : //github.com/pathikrit/metarest/blob/master/src/main/scala/com/github/pathikrit/MetaRest.scala
class MetaRest extends StaticAnnotation {
def macroTransform(annottees: Any*): Any = macro MetaRest.impl
}
object MetaRest {
sealed trait …Run Code Online (Sandbox Code Playgroud) scala scala-macros scala-2.11 scala-macro-paradise scalameta
我有两个类,将它们称为Foo和Fizz。Foo使用一个被调用的注释宏expand来为其某些方法创建别名(实际实现所做的不仅仅是创建别名,但简单版本仍然会出现以下问题)。为简单起见,假设expand宏简单地获取带注释的类中的所有方法,并制作它们的副本,将“Copy”附加到方法名称的末尾,然后将调用转发到原始方法。
我的问题是,如果我使用expand宏 on Foo,它会创建一个Foo#bar名为的方法的副本barCopy,当barCopy在另一个类中调用时Fizz,一切都会编译,但 scaladoc 生成失败,如下所示:
[error] ../src/main/scala/Foo.scala:11: value barCopy is not a member of Foo
[error] def str = foo.barCopy("hey")
[error] ^
[info] No documentation generated with unsuccessful compiler run
Run Code Online (Sandbox Code Playgroud)
如果我删除标记正在复制的方法 ( Foo#bar)的 scaladoc ,该sbt doc命令将再次运行。就好像 scaladoc 生成器在不使用启用的宏天堂插件的情况下调用编译器的早期阶段一样,但如果从有问题的方法中删除文档,它会以某种方式工作。
这是expand宏:
import scala.annotation.{ StaticAnnotation, compileTimeOnly }
import scala.language.experimental.macros
import scala.reflect.macros.whitebox.Context
@compileTimeOnly("You must enable the macro …Run Code Online (Sandbox Code Playgroud) 我正在尝试在 Scala IDE 上开发一个项目,但我在 Scala IDE 上遇到了构建问题。
在 sbt 上,项目构建良好。我使用了 eclipse sbt 插件并在 Scala IDE 上导入了该项目。存在构建错误,这使得 ide 几乎无用。
错误之一是Compiler plugin paradise_2.12.1-2.1.0.jar is cross-compiled with incompatible version for this project: 2.12.1 vs 2.12.2
我认为 scala 次要版本是兼容的,但我看到某些实验模块有例外。宏天堂插件是这些例外之一吗?
我该如何解决?我可以告诉 Scala IDE 使用 2.12.1 吗?sbt eclipse 插件不应该解决这个问题吗?我应该报告错误(向哪个项目)?
我工作的项目将 scala 版本定义为“2.12.1”,但我不想更改它。我正在使用 Scala IDE 版本 4.6.1。
我正在诠释一个特征,例如:
@ScreenModel
trait TestTrait {
.......
}
Run Code Online (Sandbox Code Playgroud)
然后我得到了@ScreenModel的实现,例如:
def impl(c: whitebox.Context)(annottees: c.Expr[Any]*): c.Expr[Any] = {
import c.universe._
val output : List[Tree] = annottees.map(_.tree) match {
case(cd @ q"$mods trait $name[..$tparams] extends ..$parents { ..$body }") :: Nil =>
val compObjVar = s"""{
import models.presentation.blocks.BlockModel;
class AAAA {
class BBBB {
}
}
}""";
val rawTree=c.parse(compObjVar)
val merged = q"{..$rawTree}";
merged :: Nil
case _ => c.abort(c.enclosingPosition, "Invalid test target")
}
c.Expr[Any](q"..$output")
}
Run Code Online (Sandbox Code Playgroud)
所以,我得到了:
"没有伴侣的顶级课程只能扩展为同名课程或者成块"
但是,如果我在AAA类中的AAA类之前移动导入,那么它可以工作:
val compObjVar = s"""{
class …Run Code Online (Sandbox Code Playgroud) 我正在与外部Java API交互,如下所示:
val obj: SomeBigJavaObj = {
val _obj = new SomeBigJavaObj(p1, p2)
_obj.setFoo(p3)
_obj.setBar(p4)
val somethingElse = {
val _obj2 = new SomethingElse(p5)
_obj2.setBar(p6)
_obj2
}
_obj.setSomethingElse(somethingElse)
_obj
}
Run Code Online (Sandbox Code Playgroud)
基本上,Java API公开了.setXXXX许多返回void和设置内容的方法.我无法控制这些外部POJO.
因此,我想编写一个流畅的buildScala宏来检查对象,并.withXXXX()为每个void setXXXX()返回的方法创建一个builder-pattern类型方法 this:
val obj: SomeBigJavaObj =
build(new SomeBigJavaObj(p1, p2))
.withFoo(p3)
.withBar(p4)
.withSomethingElse(
build(new SomethingElse(p5))
.withBar(p6)
.result()
)
.result()
Run Code Online (Sandbox Code Playgroud)
这可能吗?我知道我无法使用def宏生成新的顶级对象,所以我可以使用类似的人体工程学设置.
scala ×12
scala-macros ×9
scalameta ×5
scala-2.11 ×2
builder ×1
lenses ×1
macros ×1
sbt ×1
sbt-plugin ×1
scala-2.10 ×1
scala-3 ×1
scala-ide ×1
scalac ×1
scaladoc ×1