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

欢迎!请参阅关于页面了解此功能的更多信息。

0票数
tools.namespace

在路径 {{public/js/out/foo/bar.cljc}} 处有一个 cljc 文件,其中 ns 形式为 {{(ns foo.bar)}},这将导致命名空间 {{foo.bar}} 被重新加载。

这可能导致问题,因为 ClojureScript 编译器会复制所有输入文件到 {{:output-dir}} 用于源映射。最近,随着越来越多的库开始使用 cljc,这导致了在库在 Clojure 环境中使用时产生问题。Cljs 编译将导致库代码重新加载,这可能会重新定义协议等,并破坏 Clojure 环境。

我认为对于 tools.namespace 而言,忽略文件路径和命名空间不匹配的变更是有意义的。
另一个问题是,我们需要了解为什么在这个情况下依赖关系解析不起作用:依赖输出目录中 cljc 文件上的协议的命名空间不会重新加载。

19 答案

0票数

作者:deraen

这与http://dev.clojure.org/jira/browse/TNS-24几乎相同,但在这个情况下,不一致命名的命名空间将因为正确的路径中有一个副本而重新加载。

0票数

作者:deraen

带有测试的补丁建议。

{{find-sources-in-dir}} 是进行此检查的简单之处,因为我们需要目录路径。

  • 这可能会对直接使用 {{find-sources-in-dir}} 的用户造成破坏?
  • 现在Both {{find-sources-in-dir}} 和 {{file/files-and-deps}} 都需要读取 ns 格式。
0票数
by

作者:deraen

在补丁中修复了一个拼写错误。

0票数
by

评论者:severeoverfl0w

我也遇到过这个bug。当与bidi结合使用时尤其严重,因为它的使用协议和记录。这个补丁完美解决了我的问题。

0票数
by

评论者:Stuart.sierra

这个问题的根本原因是将编译后的“网络资产”如编译后的ClojureScript代码等放在Java类路径上{{resources/public}}的通用做法。

现在有两种简单的解决方案

  1. 配置ClojureScript以便将编译文件放在一个不在类路径上的目录中
  2. 使用(链接:http://clojure.github.io/tools.namespace/#clojure.tools.namespace.repl/set-refresh-dirs 终端:set-refresh-dirs)来省略这些目录的工具命名空间搜索。

任何改变工具命名空间行为的东西,尤其是低级API,都有可能破坏其他用例,所以必须仔细考虑。例如,一个代码检查器可能会使用{{find-sources-in-dir}}来搜索所有Clojure源文件,包括那些具有无效的{{ns}}声明的文件。

0票数
by

作者:deraen

  1. 将配置ClojureScript以便将编译文件放在一个不在类路径上的目录中

使用类路径来提供服务是最常见的方式,并且不太可能改变。许多工具,如Boot,鼓励使用类路径来提供服务。

  1. 使用set-refresh-dirs来省略这些目录的工具命名空间搜索。

在Boot中这是不可能的。在Boot中,类路径由Boot管理,一个目录将包含来自多个源文件,例如Boot-cljs和{{source-paths}}。

0票数
by

评论者:severeoverfl0w

如果您接受这个补丁,那么请问是否希望 do-refresh 接受一个选项,并将其映射到 sane-paths-only?,然后将它传递给下面的调用 find/find-sources-in-dir?在 find-sources-in-dir 中,是否可以接受一个可选的第三个参数来指定是否需要 sane-paths-only?

非常好,我们可以将最终的参数 find-sources-in-dir 修改为一个选项映射,但也许修改 API 超出了范围。

长话短说,如果您接受这个补丁,那么请考虑在 repl/refresh 时仅运行 sane-paths-only? 并且通过参数传递。

0票数

评论者:malcolmjuxt

我同意你不应该将构建的工件编译到类路径中。

但是,这由于 uberjars 的存在,在 Clojure 世界上是一个极为普遍的做法。

我自己并不喜欢 uberjars,但似乎我是少数派!只要人们在生产中使用 uberjars,他们就会希望在开发中使用从类路径中提供的。

因此,我认为 Stuart 提出的简单的解决方案都不令人满意。

这是一个相当讨厌的 bug,尤其对于那些使用 cljc 库(如 bidi)的人来说。如果能提出另一个解决方案就太好了。

0票数

评论者:severeoverfl0w

  1. 使用set-refresh-dirs来省略这些目录的工具命名空间搜索。

我注意到的另一个问题是,这种策略并不处理具有不同 :source-paths 的 Leiningen 配置文件。每次你需要切换配置文件时,你必须更改对 set-refresh-dirs 的调用(并在出错时感到困惑)。

0票数

评论者:Stuart.sierra

tools.namespace 从未设计用于部署的应用程序中,所以我认为现在忽略 (link: https://dev.clojure.org/jira/browse/TNS-45?focusedCommentId=44822épage=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-44822 文本: uberjars) 的情况是安全的。

如果意外路径中的文件被静默跳过,就很难理解为什么一个名字错误文件没有被加载。作为一个可能的折衷方法,当 {{c.t.n.find}} 遇到一个 {{ns}} 声明与路径不匹配的文件时,它可以在 * } 上打印一个警告,并将其从搜索结果中省略。

这留下了虚假错误信息的问题。如上面注释中所述,(链接:https://dev.clojure.org/jira/browse/TNS-45?focusedCommentId=45080&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-45080 text: Leiningen profiles) 和 (链接:https://dev.clojure.org/jira/browse/TNS-45?focusedCommentId=44149&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-44149 text: Boot) 使静态定义需要扫描源文件的目录集变得困难。如果我们能够指定要排除搜索的目录,这将足以绕过ClojureScript将{{.cljc}}文件复制到资源目录的问题吗?

0票数

作者:deraen

我认为uberjars被提到是关于为什么人们从类路径提供服务,而不是因为人们使用c.t.n与部署的应用程序结合使用。

排除的目录会被定义为文件路径还是类路径前缀?

在Boot中,用户不能控制包含在类路径中的目录。相反,Boot创建了一些它控制的临时目录,并将它们包含在类路径中。来自多个来源的文件(项目资源路径、Cljs工件等)都被复制到同一个临时目录中,因此无法根据这些来源排除Cljs工件。

定义要忽略的类路径前缀可能与Boot兼容。

0票数

评论者:Stuart.sierra

通过类路径前缀排除可能可行,但很复杂。目前,{{t.n.s.dir}}在不知道这些目录是否位于类路径上的情况下搜索任意文件系统目录。然而,如果排除是以类路径相对目录路径的形式 expressing 的,它们可以被解析为实际的文件系统路径。

还有一个更早应该想到的可能性是使用文件 哈希,而不是像现在这样使用时间戳来确定文件何时“已更改”。这将防止因为ClojureScript编译器将它们复制,而只是简单地重新加载{{.cljc}}文件。另一方面,这将是一个更大的变化,并且它会防止使用{{touch}}(或在编辑器中重新保存)来强制重新加载文件。

0票数

评论者:Stuart.sierra

新补丁TNS-42-3.patch将责任从c.t.n.find提升到c.t.n.dir。这避免了c.t.n.find/find-sources-in-dir的任何破坏性更改,同时实现了c.t.n.repl/refresh所需的特性。

这可能是一个足够好的妥协,尽管我仍然有些担心误命名的文件被静默忽略导致混淆。

0票数

评论者:severeoverfl0w

可以将废弃的文件/命名空间添加到跟踪器中,以减轻混淆。然后刷新可以像现在一样用 prn 警告那些文件。

如果文件变得有效,则需要从废弃列表中删除。

我不确定这应该阻止 TNS-45,但这可能是某个人跟进的东西。

0票数

评论者:Stuart.sierra

新的补丁文件 TNS-45-4.patch 将打印警告并将被忽略的目录添加到跟踪器中,遵循在 (链接: https://dev.clojure.org/jira/browse/TNS-45?focusedCommentId=47280&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-47280 文本:评论) 中提出由 Dominic Monroe 的建议。

这仅适用于 {{c.t.n.dir/scan-dirs}},因此 tools.namespace 中的底层 API 的其他用途不应受到影响。

在首次遇到不符合 {{scan-dirs}} 的文件时,将打印包含声明过的 {{ns}} 名称和未匹配的文件路径的警告到 * 中。之后,整个目录都将被忽略,并且在每次调用 {{scan-dirs}} 时都会打印通知。我希望这会在信息性消息和过多的虚假警告之间取得良好的平衡。

注意:之前的补丁文件 TNS-42-3.patch 被误命名,但它始终旨在应用于 TNS-45。

...