【问题标题】:Object not found when is in src_managed folder在 src_managed 文件夹中时找不到对象
【发布时间】:2019-01-04 02:34:59
【问题描述】:

这是(我认为)与Type not found: type .. when type is in src_managed folder 不同的问题。

我正在从 sbt 1.1.1 构建,我已经在 sbt 中设置了一个代码生成任务,它按预期运行并创建了许多具有相同结构的文件。

package com.a3.traffic
package object Vendor

它们在其他文件中被导入为:

import com.a3.traffic.Vendor._

文件在 src_managed 下生成。我尝试了两种不同的设置

src_managed / main / Vendor

src_managed / main / scala / com / a3 / traffic / Vendor

在这两种情况下,我都会收到以下错误:

[error] /Users/luis/IdeaProjects/SparkTrafficAllocation/core/src/main/scala/com/a3/traffic/Params.scala:5:28: object Vendor is not a member of package com.a3.traffic
[error] import com.a3.traffic.Vendor._      

我可以通过将生成的代码移动到 src/main/scala/com/a3/traffic/Vendor(与我的其余代码一起)来解决这个问题,但后来我明白了。

[error] /Users/luis/IdeaProjects/SparkTrafficAllocation/core/target/scala-2.11/src_managed/main/scala/com/a3/traffic /Vendor/Vendor.scala:3:16: package is already defined as package object Vendor
[error] package object Vendor {

我觉得这很令人费解。 src_managed 中定义的对象在我的代码中是看不到的,但是可以看到包里面有什么。如何让 src_managed 中的对象对包的其余部分可用?

编辑 我创建了一个最小的项目来展示这个https://github.com/sisamon/MinimalApp

编辑 2 我正在使用名称/package.scala/package.scala => 对象名称作为原始名称。scala 案例类/案例对象不起作用。

【问题讨论】:

  • 你能分享一个我们可以重现问题的示例 repo 吗?这很奇怪。我已经做过几次了,它总是有效的。您是否有任何机会修改了 SBT 中与编译类路径相关的内容 - 默认情况下,src_managed 文件夹始终存在用于编译,只要定义的对象在一个包并且是公开的,你可以使用它们。正如您在我制作的这个简单演示中看到的那样,我使用了在我的Main.scala 文件中生成的文件中创建的所有对象。
  • 另外,las 错误信息很奇怪,它说 package object Vendor 已经定义了。当你做将生成的文件移动到其余代码的实验时,你是否禁用了代码生成并删除了旧的? - 这样你就可以检查它是否会按预期工作。
  • 不,我没有(对于这个实验)对于“生产”我会这样做,但我真的很好奇为什么它没有找到对象。它并不像对象那么奇怪供应商位于托管和非托管源目录中。我将尝试构建一个仍然显示问题的较小项目。我使用的是相当复杂的。谢谢!
  • 好的,当你用链接编辑问题时,我会尽快看看。此外,我刚刚注意到我忘记将链接添加到我在第一条评论中提到的demo
  • 你的Vendor 类实际上应该命名为SparkTrafficAllocation/core/target/scala-2.11/src_managed/main/scala/com/a3/traffic/package.scala。它应该包含package com.a3.traffic \n package object Vendor { ... }

标签: scala sbt


【解决方案1】:

问题出在here

def generator (x: Country) = {
  generateADT("Vendor", x.vendor)
  generateADT("InstallationType", x.installationType)
}

请记住,您的任务必须返回一个Seq,其中生成ALL Files!。

而且,您的generateADT 每个都返回一个FileSeq,因此,您只返回最后一次调用的Seq(在这种情况下是InstallationType,这就是你的Vendor 找不到的原因!

您可以通过注释第二行来检查,这将使第一行返回,在这种情况下会找到Vendor

有几种方法可以解决这个问题,最简单和优雅 (恕我直言) 是这样的:

def generator (x: Country): List[File] =
  List(
    ("Vendor", x.vendor),
    ("InstallationType", x.installationType)
  ).map((generateADT _).tupled)

def generateADT (base: String, d: Descriptor): File = {
  // ...
  // The path really does not matter, as long as it is inside the src_managed folder.
  val adtFile = (sourceManaged in Compile).value / s"${base}.scala"
  IO.writeLines(adtFile, code)
  adtFile
}

PS:作为建议,您应该明确输入所有函数/方法的返回类型。它不仅有助于其他事物的类型推断,还可以避免一些编译错误,并增加代码的可读性。

【讨论】:

  • 是的,我应该输入带有返回值的函数。这有效地解决了这个问题,但我仍然不明白为什么我有第二个问题,在我将它们复制到我的主代码中之后看到它们。显然,我对范围规则不了解。
  • @LuisSisamon 我认为 (这只是纯粹的猜测)SBT 在编译正常之前仍然编译 src_managed 文件夹中的所有内容源代码。对于源代码,它只将它知道必须使用的文件放在范围内 - 或者它只是黑魔法,谁知道是 SBT
猜你喜欢
  • 2015-01-27
  • 1970-01-01
  • 2019-02-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多