请在2024 Clojure状态调查!中分享您的想法。

欢迎!请参阅关于页面以获取有关此工作方式的一些更多信息。

+1
错误

对于不存在的命名空间中的变量的定义将产生此错误

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

原因:当受限变量中的命名空间不存在时,编译器 lookupVar() 返回 null。

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

补丁:clj-1400-4.diff

筛选者:Alex Miller

14个答案

0

评论:scottbale

在我看来,这似乎是一个相对简单的问题,除非我忽略了什么;让我自己处理。

0

评论:scottbale

将补丁 {{clj-1400-1.diff}} 应用到 {{Compiler.java}}。

在此补丁的情况下,示例现在看起来是这样的

user> (def foo/bar 1) CompilerException java.lang.RuntimeException:受限符号 foo/bar 指向不存在的命名空间:foo,编译:(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: Qualified symbol goo/bar refers to nonexistent namespace: goo, compiling:(/home/scott/dev/foo.clj:3:1)

0

评论人:jafingerhut

补丁 clj-1400-1.diff 日期为 2014 年 6 月 26 日,在 2014 年 8 月 29 日的 Clojure 提交之后,无法干净地应用到最新的 master 分支上。在那一天之前可以干净地应用。

我还没检查更新此补丁的难易程度。请参阅本页面的“更新旧补丁”部分以获取一些更新补丁的技巧:http://dev.clojure.org/display/community/Developing Patches

0

评论:scottbale

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

0

评论人:alexmiller

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

0

评论:scottbale

完全同意你提到的三个要点。附上更新的补丁,clj-1400-4.diff。
我在Compiler.java中使用的是制表符
经过仔细检查lookupVar(...)的调用后,我认为只有在这个专用票据的情况下才会返回null(符号具有尚未加载的非null命名空间)。因此,我移除了条件语句和第2分支。
* (测试未变)

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,编译:(NO_SOURCE_PATH:1:1)

...或者在源文件中

user> CompilerException java.lang.RuntimeException: Qualified symbol goo/bar refers to nonexistent namespace: goo, compiling:(/home/scott/dev/foo.clj:3:1)

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

0

评论人:alexmiller

稍后我会跟进这个补丁 - Rich认为它在很大程度上是基于假设的。我认为我们已经验证了许多这些假设,但需要再次核实。

0

评论人:alexmiller

截至Clojure 1.10更新错误结果。现在它会在文件/行/列上抛出编译语法错误。

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