All Downloads are FREE. Search and download functionalities are using the official Maven repository.

mill.scalalib.GenIdeaModule.scala Maven / Gradle / Ivy

There is a newer version: 0.12.0-RC2-17-07e173
Show newest version
package mill.scalalib

import mill.define.Task
import mill.{Module, PathRef, T}
import os.SubPath

/**
 * Module specific configuration of the Idea project file generator.
 */
trait GenIdeaModule extends Module {
  import GenIdeaModule._

  def intellijModulePath: os.Path = millSourcePath

  /**
   * Skip Idea project file generation.
   */
  def skipIdea: Boolean = false

  /**
   * Contribute facets to the Java module configuration.
   * @param ideaConfigVersion The IDEA configuration version in use. Probably `4`.
   * @return
   */
  def ideaJavaModuleFacets(ideaConfigVersion: Int): Task[Seq[JavaFacet]] =
    T.task { Seq[JavaFacet]() }

  /**
   * Contribute components to idea config files.
   */
  def ideaConfigFiles(ideaConfigVersion: Int): Task[Seq[IdeaConfigFile]] =
    T.task { Seq[IdeaConfigFile]() }

  def ideaCompileOutput: T[PathRef] = T.persistent {
    PathRef(T.dest / "classes")
  }

}

object GenIdeaModule {
  import upickle.default._

  /**
   * Encoding of an Idea XML configuraiton fragment.
   * @param name The XML element name
   * @param attributes The optional XML element attributes
   * @param childs The optional XML child elements.
   */
  final case class Element(
      name: String,
      attributes: Map[String, String] = Map(),
      childs: Seq[Element] = Seq()
  )
  object Element {
    implicit def rw: ReadWriter[Element] = macroRW
  }

  final case class JavaFacet(`type`: String, name: String, config: Element)
  object JavaFacet {
    implicit def rw: ReadWriter[JavaFacet] = macroRW
  }

  /**
   * A Idea config file contribution
   * @param subPath The sub-path of the config file, relative to the Idea config directory (`.idea`)
   * @param component The Idea component
   * @param config The actual (XML) configuration, encoded as [[Element]]s
   *
   * Note: the `name` fields is deprecated in favour of `subPath`, but kept for backward compatibility.
   */
  final case class IdeaConfigFile(
      subPath: SubPath,
      component: Option[String],
      config: Seq[Element]
  ) {
    // An empty component name meas we contribute a whole file
    // If we have a fill file, we only accept a single root xml node.
    require(
      component.forall(_.nonEmpty) && (component.nonEmpty || config.size == 1),
      "Files contributions must have exactly one root element."
    )

    def asWholeFile: Option[(SubPath, Element)] =
      if (component.isEmpty) {
        Option(subPath -> config.head)
      } else None
  }
  object IdeaConfigFile {

    /** Alternative creator accepting a component string. */
    def apply(
        subPath: SubPath,
        component: String,
        config: Seq[Element]
    ): IdeaConfigFile =
      IdeaConfigFile(subPath, if (component == "") None else Option(component), config)

    implicit def subPathRw: ReadWriter[SubPath] = readwriter[String].bimap(_.toString(), SubPath(_))
    implicit def rw: ReadWriter[IdeaConfigFile] = macroRW
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy