2024 年 Clojure 状态调查中分享您的想法!

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

+1
错误

使用不存在命名空间的 var 定义会产生此错误

用户 > (def foo/bar 1) 编译错误在 (REPL:1:1) 编译 def。无法在当前命名空间外创建定义

原因:如果已命名变量中的命名空间不存在,则 Compiler.lookupVar() 返回 null。

建议:如果命名空间是问题所在,则错误消息可通过命名符号并抛出带有文件/行/列信息的 CompilerException 来改进。这可能不是这个错误发生的唯一情况。如果是这样,错误消息可以更具体地指出命名空间部分不存在。

补丁:clj-1400-4.diff

审核人:Alex Miller

14 答案

0

由:scottbale 发表的评论

在我看来,这似乎是一个相当显而易见的问题,除非我有什么遗漏,否则我会处理这个问题。

0

由:scottbale 发表的评论

将补丁{{clj-1400-1.diff}}添加到{{Compiler.java}}。

使用此补丁,示例现在看起来会是这样

用户 > (def foo/bar 1) CompilerException java.lang.RuntimeException: Qualified symbol foo/bar refers to nonexistent namespace: foo, compiling:(NO_SOURCE_PATH:1:1)

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

(链接:脚注)

`
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

2014年6月26日的补丁“clj-1400-1.diff”在2014年8月29日对Clojure进行了一些提交之后,不再能够干净地应用在最新的master上。在此之前它是可以干净地应用的。

我没有检查更新这个补丁可能多么简单或者困难。请参阅本维基页面上的“更新过时的补丁”部分,以获取更新补丁的一些技巧:[http://dev.clojure.org/display/community/Developing+Patches](http://dev.clojure.org/display/community/Developing Patches)

0

由:scottbale 发表的评论

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

0

评论者:alexmiller

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

0

由:scottbale 发表的评论

同意你提到的所有三个要点。附上了更新后的补丁,clj-1400-4.diff。
我在Compiler.java中使用了制表符 在对lookupVar(...)的调用进行仔细检查后,我相信只有在本项票据的情况下才会返回null(符号有一个尚未加载的非null命名空间)。所以我移除了条件判断和第二个分支。
* (测试保持不变)

0

由:scottbale 发表的评论

(正确命名的补丁)

0

评论者:alexmiller

你可以(如票据描述建议的那样)抛出一个带有问题位置的CompilerException。

0

由:scottbale 发表的评论

抱歉,我应该提到这一点,因为这对我也不是很明显(实际上我直到刚才才意识到):RuntimeException已经被捕获并包装在CompilerException中。

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

在Repl...

用户 > (def foo/bar 1) CompilerException java.lang.RuntimeException: Qualified symbol foo/bar refers to nonexistent namespace: foo, compiling:(NO_SOURCE_PATH:1:1)

...或者在一个源文件中

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

此外,在这个补丁的RuntimeException被抛出的点上,CompilerException的{{source}} {{line}} 和 {{col}}参数不可用,或者至少不是afaict。

0

评论者:alexmiller

我将在之后跟进这个补丁 - Rich认为它做出了太多的假设。我认为我们验证了许多这些假设,但需要再次检查。

0
by

评论者:alexmiller

从Clojure 1.10版开始更新错误结果。现在它正抛出包含文件/行/列的编译语法异常阶段异常。

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