通过 IMain 获取 scala repl 内的类型信息

2024-02-23

Intent

I am 试图添加 https://groups.google.com/forum/?fromgroups=#!topic/scala-internals/DdSg-qxOvyo支持:kind命令到scala /questions/tagged/scala代表。多亏了 Eugene Burmako,我才得以获得工作原型 https://gist.github.com/folone/5261743。尽管它仅适用于完全限定的名称,并且无法解析导入的名称。

我现在正在尝试使用IMain.exprTyper http://www.scala-lang.org/archives/downloads/distrib/files/nightly/docs/compiler/index.html#scala.tools.nsc.interpreter.IMain来完成这项工作,因为它知道类型,导入到 repl 中。但有一个问题。我尝试过的一切都会返回ClassInfoType http://www.scala-lang.org/api/current/index.html#scala.reflect.api.Types%24ClassInfoType如下所示(显示为showRaw http://www.scala-lang.org/api/current/index.html#scala.reflect.api.Printers):

ClassInfoType(List(TypeRef(TypeRef(TypeRef(TypeRef(NoPrefix(), package <root>, List()), package java, List()), package lang, List()), class Object, List()), TypeRef(TypeRef(TypeRef(NoPrefix(), package <root>, List()), package scala, List()), trait Serializable, List())), Scope{
  def <init>(): Option.type;
  implicit def option2Iterable(xo: Option): Iterable;
  def apply(x: Object): Option;
  def empty(): Option;
  private def readResolve(): Object
}, object Option)

虽然工作实现返回特定的Type:

PolyType(List(TypeName("A")), ClassInfoType(List(TypeRef(ThisType(scala), TypeName("AnyRef"), List()), TypeRef(ThisType(scala), scala.Product, List()), TypeRef(ThisType(scala), scala.Serializable, List())), Scope(nme.CONSTRUCTOR, TermName("isEmpty"), TermName("isDefined"), TermName("get"), TermName("getOrElse"), TermName("orNull"), TermName("map"), TermName("fold"), TermName("flatMap"), TermName("flatten"), TermName("filter"), TermName("filterNot"), TermName("nonEmpty"), TermName("withFilter"), TypeName("WithFilter"), TermName("contains"), TermName("exists"), TermName("forall"), TermName("foreach"), TermName("collect"), TermName("orElse"), TermName("iterator"), TermName("toList"), TermName("toRight"), TermName("toLeft")), scala.Option))

Question

我感觉我真的很亲近。这是一个游乐场,您可以自己尝试一切:

Welcome to Scala version 2.11.0-20130328-093148-47645c7e7e (OpenJDK 64-Bit Server VM, Java 1.7.0_17).
Type in expressions to have them evaluated.
Type :help for more information.

scala> import scala.reflect.runtime.universe._
import scala.reflect.runtime.universe._

scala> import scala.tools.nsc.interpreter.IMain
import scala.tools.nsc.interpreter.IMain

scala> val mirror = runtimeMirror(getClass.getClassLoader) // Working approach
mirror: reflect.runtime.universe.Mirror = JavaMirror with scala.tools.nsc.interpreter.IMain$TranslatingClassLoader@3d34ec98 of type class scala.tools.nsc.interpreter.IMain$TranslatingClassLoader with classpath [<unknown>] and parent being scala.tools.nsc.util.ScalaClassLoader$URLClassLoader@5d990e8c of type class scala.tools.nsc.util.ScalaClassLoader$URLClassLoader with classpath [file:/usr/lib/jvm/java-7-openjdk/jre/lib/resources.jar,file:/usr/lib/jvm/java-7-openjdk/jre/lib/rt.jar,file:/usr/lib/jvm/java-7-openjdk/jre/lib/jsse.jar,file:/usr/lib/jvm/java-7-openjdk/jre/lib/jce.jar,file:/usr/lib/jvm/java-7-openjdk/jre/lib/charsets.jar,file:/usr/lib/jvm/java-7-openjdk/jre/lib/rhino.jar,file:/home/folone/workspace/scala-myfork/build/pack/lib/jline.jar,file:/home/folone/workspace/scala-myfork...

scala> val typer = new IMain().exprTyper // Not working approach
typer: scala.tools.nsc.interpreter.IMain#exprTyper.type = scala.tools.nsc.interpreter.IMain$exprTyper$@68c181f0

scala> val expr = "scala.Option"
expr: String = scala.Option

scala> showRaw(mirror.staticClass(expr).toType.typeSymbol.typeSignature) // Correct signature
res6: String = PolyType(List(TypeName("A")), ClassInfoType(List(TypeRef(ThisType(scala), TypeName("AnyRef"), List()), TypeRef(ThisType(scala), scala.Product, List()), TypeRef(ThisType(scala), scala.Serializable, List())), Scope(nme.CONSTRUCTOR, TermName("isEmpty"), TermName("isDefined"), TermName("get"), TermName("getOrElse"), TermName("orNull"), TermName("map"), TermName("fold"), TermName("flatMap"), TermName("flatten"), TermName("filter"), TermName("filterNot"), TermName("nonEmpty"), TermName("withFilter"), TypeName("WithFilter"), TermName("contains"), TermName("exists"), TermName("forall"), TermName("foreach"), TermName("collect"), TermName("orElse"), TermName("iterator"), TermName("toList"), TermName("toRight"), TermName("toLeft")), scala.Option))

scala> showRaw(typer.typeOfExpression(expr).typeSymbol.typeSignature) // Wrong signature
res7: String = 
ClassInfoType(List(TypeRef(TypeRef(TypeRef(TypeRef(NoPrefix(), package <root>, List()), package java, List()), package lang, List()), class Object, List()), TypeRef(TypeRef(TypeRef(NoPrefix(), package <root>, List()), package scala, List()), trait Serializable, List())), Scope{
  def <init>(): Option.type;
  implicit def option2Iterable(xo: Option): Iterable;
  def apply(x: Object): Option;
  def empty(): Option;
  private def readResolve(): Object
}, object Option)

我该如何转型ClassInfoType转化为有效的Type包含所需的信息?或者,我如何获得Type using IMain首先?


这个怎么样?我正在使用电源模式,它使您可以从当前运行的 REPL 访问全局,这比创建新的 REPL 更方便IMain.

scala> :power
Already in power mode.

scala> val g = global
g: $r.intp.global.type = <global>

scala> val context = g.analyzer.rootContext(NoCompilationUnit)
context: g.analyzer.Context = Context(<root>@EmptyTree unit=NoCompilationUnit scope=997093283 errors=false, reportErrors=true, throwErrors=false)

// aware imports of scala._, etc.
scala> val sym = context.lookupSymbol("Option": TypeName, _ => true).symbol
sym: g.analyzer.global.Symbol = class Option

scala> sym.tpeHK.typeParams
res21: List[g.analyzer.global.Symbol] = List(type A)

也可以看看:

scala> intp.symbolOfType("Foo")
res26: $r.intp.global.Symbol = class Foo

但我不确定如何获取以前导入的符号:

scala> object Bar { class Bop }
defined object Bar

scala> import Bar.Bop
import Bar.Bop

scala> intp.symbolOfType("Bop")
res27: $r.intp.global.Symbol = <none>

Edit:

OP 获得的原因ClassInfoType代替PolyType是由于相位。为了获得与功率模式相同的结果global,必须将相位设置为typer。引用@retronym的解释REPL:intp.global 与“global”在 :power 模式下可用 https://groups.google.com/d/msg/scala-internals/fBLwvcjNGTc/9V-8kl7zue0J:

scala> :power
** Power User mode enabled - BEEP WHIR GYVE **
** :phase has been set to 'typer'.          **
    ^
    `----  this part is relevant

符号有一个类型列表(又名info-s),按编译器阶段索引。 (又名类型历史)。许多编译阶段安装InfoTransformers 改变类型。有关一些文档,请参阅 src/compiler/scala/tools/nsc/transform/InfoTransform.scala。

要检查特定阶段的类型,您可以使用“exitingTyper”等方法。

scala> exitingPostErasure($intp.global.rootMirror.staticClass("scala.Option").typeSignature).getClass
res6: Class[_ <: $intp.global.Type] = class scala.reflect.internal.Types$ClassInfoType

scala> exitingTyper($intp.global.rootMirror.staticClass("scala.Option").typeSignature).getClass
res7: Class[_ <: $intp.global.Type] = class scala.reflect.internal.Types$PolyType

或者,在 :power 模式下更方便一点:

scala> :phase typer
Active phase is now: Typer

scala> global.rootMirror.staticClass("scala.Option").typeSignature.getClass
res16: Class[_ <: $r.global.Type] = class scala.reflect.internal.Types$PolyType

scala> :phase cleanup
Active phase is now: Cleanup

scala> global.rootMirror.staticClass("scala.Option").typeSignature.getClass
res17: Class[_ <: $r.global.Type] = class scala.reflect.internal.Types$ClassInfoType
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

通过 IMain 获取 scala repl 内的类型信息 的相关文章

随机推荐

  • 由于组合框未突出显示,如何“获取”WPF 组合框 PART_EditableTextbox?

    每次单击按钮时 我的 WPF 组合框都会填充一组不同的字符串 窗口上还有其他控件 组合框是窗口中的 第一个 顶部 但文本不会突出显示 当用户通过控件切换时 文本会突出显示 但当它是窗口上的第一个时 文本不会突出显示 也许我需要在组合框本身
  • Python:使用自定义分隔符格式化字符串[重复]

    这个问题在这里已经有答案了 EDITED 我必须使用字典中的值格式化字符串 但该字符串已经包含大括号 例如 raw string DATABASE name DB NAME 但是当然 raw string format my diction
  • 在 Active Directory 中,什么是资源?

    在 AAD node js 库的示例和测试中 00000002 0000 0000 c000 000000000000始终作为资源传递 什么是00000002 0000 0000 c000 000000000000 The 文档 https
  • 函数中的空参数不为 Null

    鉴于这个基本功能 Function TestFunction Param int Par1 string Par2 string Par3 If Par1 ne Null Write Output Par1 Par1 If Par2 ne
  • Scala 检查元素是否存在于列表中

    我需要检查列表中是否存在字符串 并调用相应接受布尔值的函数 是否可以通过一个衬垫来实现这一目标 下面的代码是我能得到的最好的 val strings List a b c val myString a strings find x gt x
  • 从Python中的文本文件中删除二进制数据

    我有一个包含一些二进制数据的文本文件 当我使用 Python 3 在文本模式下读取文件时 我收到一个 UniCodeDecodeError 编解码器无法解码字节 其中包含以下代码行 fo open myfile txt r for line
  • Yii2:scenario()模型方法

    有2个需要的功能 注册时设置密码和如果用户忘记密码则更改密码 用户注册时 密码长度必须至少为4个字符 当更改通过时 至少 5 个字符 视图对于注册和更改通行证很常见 显然 还存在两种操作 其中使用 注册 或 更改 场景 模型中的代码片段 p
  • android:以编程方式选择默认启动器

    我想弹出一个对话框 让用户选择要启动的启动器设置为默认选项 我试过 Intent home new Intent Intent ACTION DEFAULT home addCategory Intent CATEGORY LAUNCHER
  • nuget中的所有软件包都有免费使用许可证吗?

    我正在做一个需要操作 Excel 文件的项目 我找到了一个适合这项工作的库 名为 Aspose cells 它不是一个免费的库 我们应该从其网站购买其许可证才能在我们的项目中使用它 然而我发现这个库有一个nuget包 所以我有点困惑 想问以
  • 添加 .resx 文件时 WPF .net Core 3.0 编译错误

    以下工作按预期进行 VS Studio 2019 经过专业人士和社区的测试 创建新的 APF 应用程序 NET Framework 打开属性文件夹 将 Resources resx 更改为公共 创建一个新的资源文件 Resources de
  • cabal-install 配置文件的文档

    The cabal config存储 cabal install 使用的配置 我想对它进行一些黑客攻击 具体来说 安装了多个 GHC 版本 我希望有单独的文档索引 但是 除了默认文件中包含的内容之外 我找不到任何有关其语法或变量的文档 有可
  • 在运行 Kestrel 服务器时构建 .NET Core 应用程序

    在经典的 NET 应用程序中 我会设置本地 IIS 来运行指定的应用程序 我可以构建应用程序并点击端点以立即查看更改 我不需要每次都启动调试器 我想通过使用 Kestrel 服务器的 NET core 来实现这一点 我可以通过运行来运行我的
  • Android 应用程序中的静态信息在哪里安全保存?

    在我的 Android 应用程序中 我使用很少的密钥和令牌进行身份验证和初始化 我需要存储这些静态键安全地在应用程序中的某处 同时 我也需要在代码中访问它 我知道我现在使用的 SharedPreference 和 Gradle 变量 我也尝
  • 检测对象是否可重复迭代

    Does obj iter obj 暗示obj不是可重复迭代的 反之亦然 我在文档中没有看到任何这样的措辞 但根据这条评论 https stackoverflow com questions 9884132 what exactly are
  • 具有 2 个变量、2 个 y 轴的条形图

    我有以下数据 test lt data frame group 1 10 var a rnorm n 10 mean 500 sd 20 var b runif 10 我想要一个带有 2 y 轴的条形图 一个用于 var a 一个用于 va
  • WordPress 密码哈希是如何工作的?

    我需要将 Django 系统与 WordPress 站点集成 因为在 WordPress 中用户应该能够登录 DJnago 部分 反之亦然 为此 我需要了解密码哈希在 Wordpress 中的工作原理 我可以看到wp users存储用户名和
  • 如何使用html、php在网页中显示视频

    如何使用html php 在网页中显示视频 任何示例代码 请任何人帮忙 如果您正在寻找 Flash 播放器 我建议您流动播放器 http flowplayer org 如果您正在寻找 HTML 5 视频 请前往there http hack
  • 是否可以重写派生类中的静态方法?

    我在基类中定义了一个静态方法 我想在其子类中重写该方法 这可能吗 我尝试了这个 但它没有按我的预期工作 当我创建类 B 的实例并调用其 callMe 方法时 将调用类 A 中的静态 foo 方法 public abstract class
  • Rails 3 SQLite3 布尔值 false

    我试图在 SQLite3 表中插入一个假布尔值 但它总是插入一个真值 这是我的迁移 class CreateUsers lt ActiveRecord Migration def self up create table users do
  • 通过 IMain 获取 scala repl 内的类型信息

    Intent I am 试图添加 https groups google com forum fromgroups topic scala internals DdSg qxOvyo支持 kind命令到scala questions tag