请在2024 Clojure 研究调查中分享您的想法!

欢迎!有关如何使用本站信息,请参阅 关于 页面。

+1
错误

定义一个不存在的命名空间中的变量将产生这个错误

user> (def foo/bar 1) 语法错误,在编译 def 时 (REPL:1:1)。不能在当前命名空间之外创建定义

原因: 当合格变量中的命名空间不存在时,Compiler.lookupVar() 会返回 null。

建议: 通过命名符号并抛出带有文件/行/列信息的 CompilerException,可以改进错误信息。虽然这不明显,但这可能是在此类错误发生唯一的情况。如果是这样,错误信息可以更具体地指出命名空间部分不存在。

补丁: clj-1400-4.diff

筛选: Alex Miller

14 个回答

0

评论者:scottbale

在我看来,这似乎是一个相对容易解决的问题,除非我对某个地方有所遗漏;我已指派给自己处理。

0

评论者:scottbale

Patch {{clj-1400-1.diff}} to {{Compiler.java}}.

使用此补丁,该示例现在将如下所示

user> (def foo/bar 1) CompilerException java.lang.RuntimeException: 合格符号 foo/bar 引用的命名空间不存在:foo, compiling:(NO_SOURCE_PATH:1:1)

我不确定 {{if(namesStaticMember(sym))}} (链接:见下方),以及第二个分支,是否甚至是有必要的。仅仅通过检查,我怀疑它不是。

(链接:脚注)

`
public static boolean namesStaticMember(Symbol sym){

return sym.ns != null && namespaceFor(sym) == null;

}
`

0

评论者:scottbale

补丁:代码和测试

0

评论者:scottbale

我实际测试了源文件,并且异常信息中包含了文件/行/列信息,符合要求

user=> CompilerException java.lang.RuntimeException: 有资格的符号 goo/bar 指向不存在的命名空间:goo,编译位置:(/home/scott/dev/foo.clj:3:1)

0

评论者:jafingerhut

补丁 clj-1400-1.diff 日期为 2014年6月26日,在某些更改提交到 Clojure 的日期 2014年8月29日之后,不再干净地应用到最新的 master。在此之前它可以干净地应用。

我还没有检查更新此补丁可能容易或困难。请在本页面的“更新过时的补丁”部分中查看有关更新补丁的一些提示:http://dev.clojure.org/display/community/Developing Patches

0

评论者:scottbale

附上更新后的补丁:“clj-1400-2.diff”。我已经删除了过时的补丁。

0

评论者:alexmiller

只有少数评论需要处理
- 编译器 diff 使用的是空格而不是制表符,这使 diff 操作变得困难。我附上了 -3.diff 来修复这个问题。
- namesStaticMember 的调用看起来很奇怪。这个方法的名字对于这个用途来说很令人困惑。除此之外,我认为它做的是你所不需要的。该方法将尝试以当前 ns 的形式解析资格名称,但我觉得你甚至不需要这么做。你只是想知道这个符号是否有 ns(sym.ns != null)- 这不是足够吗?
- 在什么情况下会触发其他错误“变量不存在”?换句话说,在什么情况下 lookupVar 不会在这里创建一个新的变量?如果没有这种情况,那么移除这个情况。如果有这种情况,那么添加一个测试。

0

评论者:scottbale

同意你提到的三个要点。附上更新后的补丁,clj-1400-4.diff。
我在Compiler.java中使用制表符
经过对lookupVar(...)调用的仔细检查,我相信只有在恰好是这个任务的情况下才会返回null(符号的命名空间非空但尚未加载)。因此,我移除了条件和第二个分支。
* (测试不变)

0

评论者:scottbale

(正确命名的补丁)

0

评论者:alexmiller

您可以考虑抛出一个标记了问题位置的CompilerException(如工单说明中所建议的)。

0

评论者:scottbale

抱歉,我应该提到的,因为我自己也觉得不是很明显(事实上,直到刚才才想起来):RuntimeException已经被捕获并包裹在CompilerException中。

我不确定这发生在Compiler.java中的哪个try-catch块,因为有多个。但从输出中可以看到,异常是CompilerException,并且有文件|行|列信息。

在Repl...

user> (def foo/bar 1) CompilerException java.lang.RuntimeException: 合格符号 foo/bar 引用的命名空间不存在:foo, compiling:(NO_SOURCE_PATH:1:1)

...或者在源文件中

user=> CompilerException java.lang.RuntimeException: 有资格的符号 goo/bar 指向不存在的命名空间:goo,编译位置:(/home/scott/dev/foo.clj:3:1)

此外,在抛出此补丁的RuntimeException的点,CompilerException的其他源码行和列参数不可用,或者至少不是AFAICT。

0

评论者:alexmiller

我会稍后跟进此补丁 - Rich认为它做了太多的假设。我想我们已经验证了许多这些,但需要再次检查。

0

评论者:alexmiller

截至 Clojure 1.10 更新错误结果。现在它会抛出带有文件/行/列的 :compile-syntax 错误阶段异常。

0
参考: https://clojure.atlassian.net/browse/CLJ-1400(由 hlewisship 报告)
...