2024 大 Clojure 调查!中分享您的想法。

欢迎!请查看关于页面以了解更多有关此如何使用的信息。

+1
错误

在不存在 ns 的情况下定义 var 将引发此错误

user> (def foo/bar 1) 编译错误编译 def 在 (REPL:1:1)。不能在当前 ns 之外创建定义

原因: Compiler.lookupVar() 返回 null 如果合格 var 中的 ns 不存在。

建议: 通过命名符号并抛出带文件/行/列信息的 CompilerException 来改进错误信息。这可能不容易理解,但这可能是在这种情况下发生的唯一情况。如果是这样,错误信息可以更具体地指出不存在的部分是 ns。

Patch: 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: Qualified symbol foo/bar refers to nonexistent namespace: foo, compiling:(NO_SOURCE_PATH:1:1)

我不确定 {{if(namesStaticMember(sym))}} (link: see below) 和第二个分支是否必要。仅凭观察,我怀疑这不是必要的。

(链接:脚注)

`
public static boolean namesStaticMember(Symbol sym){

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

}
`

0
by

评论者:scottbale

补丁:代码和测试

0
by

评论者:scottbale

我在实际的源文件上进行了测试,异常信息包含了所需的文件/行/列信息

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

0
by

评论者:jafingerhut

2014年6月26日签发的补丁 clj-1400-1.diff 由于在2014年8月29日对Clojure做了几次提交,无法干净地应用到最新的master分支上。在此之前,它是可以干净应用的。

我还没有检查更新此补丁的难易程度。请参阅本维基页面上的“更新过时的补丁”部分,以获取有关更新补丁的一些提示:http://dev.clojure.org/display/community/Developing Patches

0
by

评论者:scottbale

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

0
by

评论者:alexmiller

有一些评论需要处理
- 编译器差异使用了空格而不是制表符,这使得差异更难做。我附上了 -3.diff 修正了这个问题。
- namesStaticMember 的调用看起来很奇怪。这个方法的名称对于这种用途来说令人困惑。除此之外,我认为它做了比您需要的更多的事情。该方法将尝试根据当前 ns 解析有资格的名字,但我觉得您甚至不需要这样做。您只想知道 sym 是否有 ns(sym.ns != null)——这难道还不够吗?
- 其他错误“未找到 Var”会在什么情况下发生?换句话说,在什么情况下 lookupVar 无法在这里创建一个新的 var?如果没有这样的情况,那么就去掉这个情况。如果有这种情况,那么添加一个测试。

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: 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}} 参数不可用,或者至少不是这样说的。

0

评论者:alexmiller

我稍后会对这个补丁进行跟进 - Rich 认为它做了太多假设。我认为我们已经验证了许多那样的情况,但需要再次检查。

0

评论者:alexmiller

由于Clojure 1.10已经更新,现在将抛出带有文件/行/列的编译语法错误阶段异常。

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