如何在scala宏中获取方法体树

时间:2018-06-04 10:47:08

标签: scala macros scala-macros

我正在尝试将scala对象转换为js对象

object SObject {
  def foo(in:String):String =  s"scalajs-$in" 
}

val o = ScalaObjectToJSObjectMacro(SObject) // js.Dynamical.literal(foo = (in:String) => s"scalajs-$in")

在宏中我能够获取所有对象的方法(in.tpe.decls.toList),然后对于每个方法名称,returnType,params在MethodSymbolApi中可用,但没有正文树:s

object ScalaObjectToJSObjectMacro {

  def apply[T](in: T): js.Object = macro macroImpl

  def macroImpl(c: blackbox.Context)(in: c.Tree): c.Tree = {
    import c.universe._
    val methods = in.tpe.decls.toList
      .filter(s => {
        s.isMethod && s.asMethod.isPublic && !s.asMethod.isConstructor
      })
      .map(m => {
        val mt = m.asMethod
        val name = mt.name
        val returnType = mt.returnType
        val params = mt.paramLists
        val body = ??? //TODO
      })

    println(s"methods: ${methods}")

    q"""
        scala.scalajs.js.Dynamic.literal()
     """
  }
}

2 个答案:

答案 0 :(得分:0)

我能够访问方法主体的一种方法是使用以下quasiquote

var googleearth = L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', {
  minZoom: 6,
  maxZoom: 17,
  attribution: 'Tiles © Esri — Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community'
});

// Note: replacing the Tile Server to comply with Google Maps Terms.
var googleTerrain = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
  attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
});

var map = L.map("mapid", {
  zoom: 10,
  center: [55.7363, -6.1771],
  layers: [googleearth, googleTerrain],
  zoomControl: false,
  attributionControl: true,
  measureControl: true

});

var baseLayers = {
  "Aerial Imagery": googleearth,
  "googleTerrain": googleTerrain
};

L.control.layers(baseLayers, null, {
  collapsed: false,
  //autoZIndex: false,
}).addTo(map);

var OpenTopoMap = L.tileLayer('https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png', {
  zIndex: 100, // Make sure you specify a high enough value.
  maxZoom: 17,
  visibility: true,
  attribution: 'Map data: &copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>, <a href="http://viewfinderpanoramas.org">SRTM</a> | Map style: &copy; <a href="https://opentopomap.org">OpenTopoMap</a> (<a href="https://creativecommons.org/licenses/by-sa/3.0/">CC-BY-SA</a>)'
});


$(document).ready(function() {
  $("#layercontrol2").change(function() {
    if ($(this).prop("checked")) {
      OpenTopoMap.addTo(map);
      return;
    } else {

      OpenTopoMap.remove();

      return;

    }
  });
});

方法正文包含在<!DOCTYPE html> <html> <head> <link rel="stylesheet" href="https://unpkg.com/leaflet@1.3.1/dist/leaflet.css" integrity="sha512-Rksm5RenBEKSKFjgI3a41vrjkw4EVPlJ3+OiI65vTjIdo9brlAacEuKOiQ5OFh7cOI1bkDwLqdLw3Zg0cRJAAQ==" crossorigin="" /> <script src="https://unpkg.com/leaflet@1.3.1/dist/leaflet-src.js" integrity="sha512-IkGU/uDhB9u9F8k+2OsA6XXoowIhOuQL1NTgNZHY1nkURnqEGlDZq3GsfmdJdKFe1k1zOc6YU2K7qY+hF9AodA==" crossorigin=""></script> <script src="https://code.jquery.com/jquery-3.3.1.js"></script> <style></style> </head> <body> <div id="mapid" style="height: 160px"></div> <div id="layercontrol"> <input id="layercontrol2" type="checkbox" /> Topo Map <br /> <!--input id="layercontrol3" type="checkbox" /> Satellite <br /--> </div> </body> </html>中。请注意,通过模式匹配访问以下代码段q"..$mods def $ename[..$tparams](...$paramss): $tpeopt = $expr"

expr

答案 1 :(得分:0)

您可以从Symbol获取Tree,但反之亦然。方法正文在此方法的Tree中不在此Tree的{​​{1}}中。因此,您应该使用原始Symbol Tree而不使用符号intutorial中描述了遍历s

尝试

Tree