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

org.scalafmt.cli.InputMethod.scala Maven / Gradle / Ivy

package org.scalafmt.cli

import scala.io.Source

import java.io.InputStream
import java.nio.file.{Path, Paths}

import org.scalafmt.Error.MisformattedFile
import org.scalafmt.sysops.AbsoluteFile

sealed abstract class InputMethod {
  def readInput(options: CliOptions): String
  def path: Path

  protected def print(text: String, options: CliOptions): Unit
  protected def list(options: CliOptions): Unit
  protected def overwrite(text: String, options: CliOptions): Unit

  final def write(
      formatted: String,
      original: String,
      options: CliOptions
  ): ExitCode = {
    val codeChanged = formatted != original
    if (options.writeMode == WriteMode.Stdout) print(formatted, options)
    else if (codeChanged)
      options.writeMode match {
        case WriteMode.Test =>
          val diff = InputMethod.unifiedDiff(path.toString, original, formatted)
          throw MisformattedFile(path, diff)
        case WriteMode.Override => overwrite(formatted, options)
        case WriteMode.List => list(options)
        case _ =>
      }
    if (options.error && codeChanged) ExitCode.TestError else ExitCode.Ok
  }

}

object InputMethod {

  object StdinCode {
    def apply(assumeFilename: String, inputStream: InputStream): StdinCode = {
      StdinCode.apply(
        assumeFilename,
        Source.fromInputStream(inputStream).mkString
      )
    }
  }
  case class StdinCode(filename: String, input: String) extends InputMethod {
    override def path: Path = Paths.get(filename)

    def readInput(options: CliOptions): String = input

    override protected def print(text: String, options: CliOptions): Unit =
      options.common.out.print(text)

    override protected def overwrite(text: String, options: CliOptions): Unit =
      print(text, options)

    override protected def list(options: CliOptions): Unit =
      options.common.out.println(filename)
  }

  case class FileContents(file: AbsoluteFile) extends InputMethod {
    override def path = file.path
    def readInput(options: CliOptions): String =
      file.readFile(options.encoding)

    override protected def print(text: String, options: CliOptions): Unit =
      options.common.out.print(text)

    override protected def overwrite(text: String, options: CliOptions): Unit =
      file.writeFile(text)(options.encoding)

    override protected def list(options: CliOptions): Unit = {
      val cwd = options.cwd.toUri
      options.common.out.println(cwd.relativize(file.toUri))
    }
  }

  def unifiedDiff(
      filename: String,
      original: String,
      revised: String
  ): String = {
    import org.scalafmt.CompatCollections.JavaConverters._
    @inline def noEol(ch: Char) = ch != '\n' && ch != '\r'
    def jList(code: String, addEol: Boolean) = {
      val last = if (addEol) Iterator.single("") else Iterator.empty
      (code.linesIterator ++ last).toList.asJava
    }
    val a = jList(original, false)
    // formatted always has EOL
    val b = jList(revised, original.isEmpty || noEol(original.last))
    val diff = difflib.DiffUtils.diff(a, b)
    if (diff.getDeltas.isEmpty) ""
    else {
      difflib.DiffUtils
        .generateUnifiedDiff(
          s"a$filename",
          s"b$filename",
          a,
          diff,
          1
        )
        .iterator()
        .asScala
        .mkString("\n")
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy