我有一个文件 src/main/scala/foo.scala
需要在包内 bar
. 理想情况下,该文件应该在 src/main/scala/bar/foo.scala
.
// src/main/scala/foo.scala
package bar
// ...
我怎样才能在整个项目中自动修复这个问题,使文件夹结构与包结构相匹配?
有没有什么SBT插件等可以帮助我解决这个问题?
据我所知,没有这样的工具,虽然AFAIR IntelliJ可以警告包目录不匹配。
我能想到的最好的办法是自定义scalafix (https:/scalacenter.github.iosalafix。)规则-- scalafixscalameta 将用于检查文件的实际包,将其翻译成预期的目录,如果它们不同,则移动文件。
我建议使用 scalafixscalameta,因为在一些角落的情况下,比如说,你可以把你的包写成这样,比如说,你可以把你的包写成这样,比如说,你可以把你的包写成这样,比如说,你可以把你的包写成这样,比如说,你可以把你的包写成这样,比如说,你可以把你的包写成这样,比如说,你可以把你的包写成这样,比如说,你可以把你的包写成这样,比如说,你可以把你的包写成这样,比如说,你可以把你的包写成这样,比如说,你可以把你的包写成这样,比如说,你可以把你的包写成这样,比如说,你可以把你的包写成这样,比如说,你可以把你的包写成这样,比如说,你可以把你的包写成这样,比如说,你可以把你的包写成这样,比如说,你可以把你的包写成这样。
你可以把你的包写成:
package a
package b
package c
而它 几乎 喜欢 package a.b.c
除了它自动从 a
和 b
你可以拥有 package object
在您的文件中,如果您有
package a.b
package object c
这个文件应该在 a/b/c
目录
所以我更愿意使用一些现有的工具来检查文件是否不属于这些情况。
如果你确定你没有这种情况(我不会不检查),你可以。
^package (.*)
)a.b.c
变成 a/b/c
(matched.split('.').map(_.trim).mkString(File.separator)
)如果有可能出现比这更复杂的情况,我可以通过查询scalafixscalameta实用程序来代替第一步。
这里有一个sbt插件,提供 packageStructureToDirectoryStructure
任务,从源文件中读取包声明,创建相应的目录,然后将文件移动到这些目录。
import sbt._
import sbt.Keys._
import better.files._
object PackagesToDirectories extends AutoPlugin {
object autoImport {
val packageStructureToDirectoryStructure = taskKey[Unit]("Make directory structure match package structure")
}
import autoImport._
override def trigger = allRequirements
override lazy val projectSettings = Seq(
packageStructureToDirectoryStructure := {
val log = streams.value.log
log.info(s"Refactoring directory structure to match package structure...")
val sourceFiles = (Compile / sources).value
val sourceBase = (Compile / scalaSource).value
def packageStructure(lines: Traversable[String]): String = {
val packageObjectRegex = """package object\s(.+)\s\{""".r
val packageNestingRegex = """package\s(.+)\s\{""".r
val packageRegex = """package\s(.+)""".r
lines
.collect {
case packageObjectRegex(name) => name
case packageNestingRegex(name) => name
case packageRegex(name) => name
}
.flatMap(_.split('.'))
.mkString("/")
}
sourceFiles.foreach { sourceFile =>
val packagePath = packageStructure(sourceFile.toScala.lines)
val destination = file"$sourceBase/$packagePath"
destination.createDirectoryIfNotExists(createParents = true)
val result = sourceFile.toScala.moveToDirectory(destination)
log.info(s"$sourceFile moved to $result")
}
}
)
}
警告:在运行项目之前,请确保备份项目。