我如何在 Scala 中获取行号、函数名、包名?
How i can get lineNumber, function name, pkg name in scala?
我尝试 google 它并搜索给我 java 个示例...
Thread.currentThread().getStackTrace()(2).getLineNumber
但在 worksheet
中总是返回 5,而在工作项目 scala/playframework 2.5
中 - 总是返回 35
我尝试用 level
玩,但它不起作用。
明白了,比如创建services/Log.scala
package services
object Log {
def info(text: String) = {
val systemStr = makeSystemStr
Console.out.println(Console.BLUE + "[INFO] " + systemStr + Console.RESET + text)
}
def makeSystemStr() = {
val fileName = Thread.currentThread().getStackTrace()(3).getFileName
val lineNumber = Thread.currentThread().getStackTrace()(3).getLineNumber
val cnArr = Thread.currentThread().getStackTrace()(3).getClassName.split("[$]")
val pkgName = cnArr(0).split("[.]")(0)
val name = cnArr(0).split("[.]")(1)
val defName = cnArr(3)
s"$pkgName : $fileName : $name : $defName : line $lineNumber - "
}
}
然后在控制器中
package controllers
import play.api.mvc._
import services.Log
class SomeCtrl extends Controller {
def Index = Action { request =>
Log.info("some text")
Ok("ok")
}
}
使用宏,可以轻松获取行号和文件名
//编辑
import scala.language.experimental.macros
import scala.reflect.macros.blackbox
object SrcFile {
def currentLine: Int = macro SrcFileImpl.currentLine
def currentFileName: String = macro SrcFileImpl.currentFileName
def currentPackage: String = macro SrcFileImpl.currentPackage
def currentClassName: String = macro SrcFileImpl.currentClassName
def currentFuncName :String = macro SrcFileImpl.currentFuncName
}
class SrcFileImpl(val c: blackbox.Context) {
import c.universe._
def getPackage(symbol: Symbol): String =
if(symbol.isPackage) symbol.fullName else getPackage(symbol.owner)
def getClass(symbol: Symbol): String =
if(symbol.isClass) symbol.name.toTypeName.toString else getClass(symbol.owner)
def currentPackage: c.Expr[String] = c.Expr(q"${getPackage(c.internal.enclosingOwner)}")
def currentFileName: c.Expr[String] = c.Expr(q"${c.enclosingPosition.source.file.name}")
def currentLine: c.Expr[Int] = c.Expr(q"${c.enclosingPosition.line}")
def currentClassName: c.Expr[String] = c.Expr(q"${getClass(c.internal.enclosingOwner)}")
def currentFuncName: c.Expr[String] = c.Expr(q"${c.internal.enclosingOwner.name.toTermName.toString}")
}
// 测试
package so
object SrcFileTest extends App {
def f() = {
println(SrcFile.currentFileName)
println(SrcFile.currentLine)
println(SrcFile.currentPackage)
println(SrcFile.currentClassName)
println(SrcFile.currentFuncName)
}
f()
}
我尝试 google 它并搜索给我 java 个示例...
Thread.currentThread().getStackTrace()(2).getLineNumber
但在 worksheet
中总是返回 5,而在工作项目 scala/playframework 2.5
中 - 总是返回 35
我尝试用 level
玩,但它不起作用。
明白了,比如创建services/Log.scala
package services
object Log {
def info(text: String) = {
val systemStr = makeSystemStr
Console.out.println(Console.BLUE + "[INFO] " + systemStr + Console.RESET + text)
}
def makeSystemStr() = {
val fileName = Thread.currentThread().getStackTrace()(3).getFileName
val lineNumber = Thread.currentThread().getStackTrace()(3).getLineNumber
val cnArr = Thread.currentThread().getStackTrace()(3).getClassName.split("[$]")
val pkgName = cnArr(0).split("[.]")(0)
val name = cnArr(0).split("[.]")(1)
val defName = cnArr(3)
s"$pkgName : $fileName : $name : $defName : line $lineNumber - "
}
}
然后在控制器中
package controllers
import play.api.mvc._
import services.Log
class SomeCtrl extends Controller {
def Index = Action { request =>
Log.info("some text")
Ok("ok")
}
}
使用宏,可以轻松获取行号和文件名
//编辑
import scala.language.experimental.macros
import scala.reflect.macros.blackbox
object SrcFile {
def currentLine: Int = macro SrcFileImpl.currentLine
def currentFileName: String = macro SrcFileImpl.currentFileName
def currentPackage: String = macro SrcFileImpl.currentPackage
def currentClassName: String = macro SrcFileImpl.currentClassName
def currentFuncName :String = macro SrcFileImpl.currentFuncName
}
class SrcFileImpl(val c: blackbox.Context) {
import c.universe._
def getPackage(symbol: Symbol): String =
if(symbol.isPackage) symbol.fullName else getPackage(symbol.owner)
def getClass(symbol: Symbol): String =
if(symbol.isClass) symbol.name.toTypeName.toString else getClass(symbol.owner)
def currentPackage: c.Expr[String] = c.Expr(q"${getPackage(c.internal.enclosingOwner)}")
def currentFileName: c.Expr[String] = c.Expr(q"${c.enclosingPosition.source.file.name}")
def currentLine: c.Expr[Int] = c.Expr(q"${c.enclosingPosition.line}")
def currentClassName: c.Expr[String] = c.Expr(q"${getClass(c.internal.enclosingOwner)}")
def currentFuncName: c.Expr[String] = c.Expr(q"${c.internal.enclosingOwner.name.toTermName.toString}")
}
// 测试
package so
object SrcFileTest extends App {
def f() = {
println(SrcFile.currentFileName)
println(SrcFile.currentLine)
println(SrcFile.currentPackage)
println(SrcFile.currentClassName)
println(SrcFile.currentFuncName)
}
f()
}