加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

通过IMain在scala repl中获取类型信息

发布时间:2020-12-16 18:51:16 所属栏目:安全 来源:网络整理
导读:意图 我是trying to add支持:对scala repl的亲切命令.感谢Eugene Burmako,我得到了working prototype.虽然它只适用于完全限定的名称,但无法解析导入的名称. 我现在正在尝试使用 IMain.exprTyper 来完成这项工作,因为它知道导入到repl中的类型.但有一个问题.
意图

我是trying to add支持:对scala repl的亲切命令.感谢Eugene Burmako,我得到了working prototype.虽然它只适用于完全限定的名称,但无法解析导入的名称.

我现在正在尝试使用IMain.exprTyper来完成这项工作,因为它知道导入到repl中的类型.但有一个问题.我尝试过的所有内容都返回ClassInfoType,如下所示(与showRaw一起显示):

ClassInfoType(List(TypeRef(TypeRef(TypeRef(TypeRef(NoPrefix(),package <root>,List()),package java,package lang,class Object,TypeRef(TypeRef(TypeRef(NoPrefix(),package scala,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)

工作实现返回特定类型:

PolyType(List(TypeName("A")),ClassInfoType(List(TypeRef(ThisType(scala),TypeName("AnyRef"),TypeRef(ThisType(scala),scala.Product,scala.Serializable,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))

我觉得我真的很亲密.这是一个游乐场,您可以自己尝试一切:

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")),scala.Option))

scala> showRaw(typer.typeOfExpression(expr).typeSymbol.typeSignature) // Wrong signature
res7: String = 
ClassInfoType(List(TypeRef(TypeRef(TypeRef(TypeRef(NoPrefix(),object Option)

如何将ClassInfoType转换为包含所需信息的有效类型?或者,我如何首先使用IMain获取Type?

解决方法

这个怎么样?我正在使用电源模式,它允许您从当前运行的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>

编辑:

OP获得ClassInfoType而不是PolyType的原因是由于阶段.要获得与电源模式的全局相同的结果,必须将阶段设置为typer.从REPL: intp.global vs “global” available in :power mode引用@ retronym的解释:

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

Symbols have an list of types (aka info-s),indexed by compiler phase. (aka TypeHistory). Many compiler phases install InfoTransformers to morph the type. See src/compiler/scala/tools/nsc/transform/InfoTransform.scala for some documentation.

To inspect the type as-at particular phase,you can use methods like ‘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

Or,a little more conveniently in :power mode:

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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读