如何在不执行脚本并生成任何类文件的情况下检查Scala脚本?

问题描述:

可以在Scala中编写脚本。所以,你可以把这个变成Hello.scala如何在不执行脚本并生成任何类文件的情况下检查Scala脚本?

#!/bin/sh 
exec scala $0 [email protected] 
!# 

println("You supplied " + args.length + " arguments!") 

,并使其在Unix的可执行

chmod u+x Hello.scala 

然后你就可以通过

./Hello.scala 

这编译脚本,只需运行该脚本如果没有语法错误,则运行它。但是,这并不能解释当我仅仅想要执行脚本的语法检查而没有的情况。我不想修改脚本(即通过删除#!指令)并且我不想要生成任何* .class文件。

如何语法检查Scala脚本?

+0

仅使用语言中给定的语法创建基本解析器,使用ANTLR等工具来检查语法是最容易的。你是否也想执行名称和类型检查?如果是这样,事情会变得混乱,你可能想直接使用(部分)scalac。 – Raphael 2011-03-05 17:40:38

+0

我的问题并不确切。我想执行语法检查以及类型检查,我想使用Scala编译器/基础结构。迈尔斯的答案在右边。 – midinastasurazz 2011-03-06 10:06:15

我希望你确实想要的不仅仅是检查正确的语法......大概你想知道的是,如果你真的编译它,你的文件会正确编译。这涉及类型检查以及语法检查。

对于Scala源文件(即不是脚本),您可以指定-Ystop:refchecks命令行参数以使编译器在开始代码生成之前停止(如果您确实只对可以指定的语法正确性感兴趣 - Ystop:解析器)。如果出现错误,它们将以完全相同的方式显示在控制台上,就像完全编译源代码一样。

对于Scala脚本,您还可以指定-Ystop:refchecks参数。如果你这样做,那么你要么看到编译报道在控制台上的错误,或者,如果有脚本没有错误,你会看到下面

$ scala -Ystop:refchecks Hello.scala 
java.lang.ClassNotFoundException: Main 

的ClassNotFoundException的表示没有类文件都已经生成并您的脚本尚未执行。

+0

好的答案 - 今天学到了一些新的技巧。谢谢。 – Janx 2011-03-05 18:19:23

+0

优秀的答案。你的解释是正确的。如果我真的编译过它,我想知道该文件是否能够正确编译。谢谢。 – midinastasurazz 2011-03-06 09:48:51

+0

这仍然有效吗?似乎不适用于Scala 2.9。在搜索中找不到关于此的任何信息。谢谢。 – 2012-02-20 15:53:25

如果你想剪线把你的文件传递给解释器,你可以创建一个名为CutScala.scala脚本(或任何你喜欢):

#!/bin/sh 
exec scala $0 [email protected] 
!# 

import scala.collection.JavaConversions._ 
import java.io._ 

val p = new ProcessBuilder(
    List(
    "scala", 
    "-e", 
    io.Source.fromFile(args(1)).getLines().drop(args(0).toInt).mkString("\n") 
) ::: 
    args.drop(2).toList 
).start() 

p.waitFor 

val output = List(p.getInputStream,p.getErrorStream).map(
    x => new BufferedReader(new InputStreamReader(x)) 
) 

println("Exit code = " + p.exitValue) 
for ((reader,title) <- (output zip List("Output:","Errors:"))) { 
    println(title); 
    Iterator.continually(reader.readLine).takeWhile(_!=null).foreach(println) 
    println 
} 

,然后调用它像

./CutScala.scala 4 Hello.scala a b c 

删除前4行,只是解析其余的。迈尔斯的答案告诉你如何做其他(更难)的一半没有产生任何输出和没有运行任何东西。

+1

哇!如此之多的斯卡拉大惊小怪,而不像awk'NR> 4'那样简单...... – 2011-03-07 07:22:29

+1

@Elazar Leibovich - 或者'tail -n + 4'。问题是AFAICT Scala脚本解释器不会采用stdin,并且你不能强有力地避免标记化一个命令替换,所以将文本填入“-e”的相对简单的尝试是行不通的。 – 2011-03-07 10:43:59

+0

'cat $ 1 | awk'NR> 4'> /tmp/tmp.$1 && scalac /tmp/tmp.$1; rm/tmp/tmp。$ 1'或者更复杂一点的方式来生成唯一的文件名称以实现完整性。但是如此多的代码可以证明这对于这项工作来说是错误的工具。另外考虑一下,你必须经历两次JVM启动时间,脚本和'scala'。 – 2011-03-07 11:58:06