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: Qualified symbol foo/bar refers to nonexistent namespace: 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

2014年6月26日创建的 clj-1400-1.diff 补丁在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 调用看起来很奇怪。这个方法的名称对这个用途来说让人困惑。除此之外,我认为它做了你不需要做的事情。该方法将尝试根据当前 ns 解析已命名的名称,但我想你甚至不需要这样做。你只是想知道这个 sym 是否有一个 ns(sym.ns != null) - 这不是吗?
- 在什么情况下会发生其他的错误“变量不存在”?换句话说,在什么情况下 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...

user> (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 )

此外,在这个partial patch抛出RuntimeException的点,CompilerException的{{source}} {{line}}和{{col}}参数不可用,或者至少据我所知是这样的。

0

评论者:alexmiller

我将稍后继续处理这个补丁 - Rich认为这做出了太多的假设。我认为我们已经验证了其中许多,但需要再次检查这些。

0

评论者:alexmiller

截至Clojure 1.10更新错误结果。现在它将抛出一个包含文件/行/列的编译语法错误阶段异常。

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