基于scala包的自动修复目录结构。

问题描述 投票:2回答:1

我有一个文件 src/main/scala/foo.scala 需要在包内 bar. 理想情况下,该文件应该在 src/main/scala/bar/foo.scala.

// src/main/scala/foo.scala


package bar

// ... 

我怎样才能在整个项目中自动修复这个问题,使文件夹结构与包结构相匹配?

有没有什么SBT插件等可以帮助我解决这个问题?

scala package sbt scalafix
1个回答
3
投票

据我所知,没有这样的工具,虽然AFAIR IntelliJ可以警告包目录不匹配。

我能想到的最好的办法是自定义scalafix (https:/scalacenter.github.iosalafix。)规则-- scalafixscalameta 将用于检查文件的实际包,将其翻译成预期的目录,如果它们不同,则移动文件。

我建议使用 scalafixscalameta,因为在一些角落的情况下,比如说,你可以把你的包写成这样,比如说,你可以把你的包写成这样,比如说,你可以把你的包写成这样,比如说,你可以把你的包写成这样,比如说,你可以把你的包写成这样,比如说,你可以把你的包写成这样,比如说,你可以把你的包写成这样,比如说,你可以把你的包写成这样,比如说,你可以把你的包写成这样,比如说,你可以把你的包写成这样,比如说,你可以把你的包写成这样,比如说,你可以把你的包写成这样,比如说,你可以把你的包写成这样,比如说,你可以把你的包写成这样,比如说,你可以把你的包写成这样,比如说,你可以把你的包写成这样,比如说,你可以把你的包写成这样。

  • 你可以把你的包写成:

    package a
    package b
    package c
    

    而它 几乎 喜欢 package a.b.c 除了它自动从 ab

  • 你可以拥有 package object 在您的文件中,如果您有

package a.b

package object c

这个文件应该在 a/b/c 目录

所以我更愿意使用一些现有的工具来检查文件是否不属于这些情况。

如果你确定你没有这种情况(我不会不检查),你可以。

  • 用regexp匹配第一行(^package (.*))
  • 翻译 a.b.c 变成 a/b/c (matched.split('.').map(_.trim).mkString(File.separator))
  • 将生成的位置与实际位置进行比较(我建议解析绝对文件位置
  • 调档

如果有可能出现比这更复杂的情况,我可以通过查询scalafixscalameta实用程序来代替第一步。


2
投票

这里有一个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")
      }
    }
  )

}

警告:在运行项目之前,请确保备份项目。

© www.soinside.com 2019 - 2024. All rights reserved.