Giter Site home page Giter Site logo

scalameta / scalafmt Goto Github PK

View Code? Open in Web Editor NEW
1.4K 29.0 276.0 17.77 MB

Code formatter for Scala

Home Page: http://scalameta.org/scalafmt

License: Apache License 2.0

Scala 96.18% Shell 1.71% HTML 0.01% Standard ML 0.11% PowerShell 0.01% CSS 0.41% JavaScript 0.78% Java 0.81% Dockerfile 0.01%
scala formatter

scalafmt's Introduction

scalafmt

Build Status Build status Join the discord chat Latest version

Head over to the user docs for instructions on how to install scalafmt.

Quick help

  • sbt compile or sbt core/compile (specific project).
  • Run all unit tests: sbt test
  • Run only formatting tests: tests/testOnly *FormatTests.
  • Write new formatting test: read this doc.
  • Build docs: See instructions on the site or locally at ./docs/contributing-website.md.
  • Hack on sbt plugin: run sbt scripted.
  • Run jmh benchmarks: ./bin/run-benchmarks.sh.
  • Run formatter on millions of lines of code: tests/test:runMain org.scalafmt.ScalafmtProps (slow, and requires a lot of memory/cpu)
  • Debug performance: after each test run in FormatTests, a flamegraph report like this one is generated in target/index.html. I usually keep a browser tab open at localhost:3000/target/index.html along with this background process: browser-sync start --server --files "target/*.html". See Browsersync.

Team

The current maintainers (people who can merge pull requests) are:

An up-to-date list of contributors is available here: https://github.com/scalameta/scalafmt/graphs/contributors

We strive to offer a welcoming environment to learn, teach and contribute.

Acknowledgements

JProfiler generously supports scalafmt with its full-featured Java Profiler.

scalafmt's People

Contributors

albertikm avatar caoilte avatar cb372 avatar daxten avatar dependabot[bot] avatar dwijnand avatar er1c avatar gabro avatar iantabolt avatar japgolly avatar jiminhsieh avatar kitbellew avatar lloydmeta avatar lorandszakacs avatar mads-hartmann avatar olafurpg avatar pjrt avatar poslegm avatar scala-steward avatar scalameta-bot avatar sideshowcoder avatar slavaschmidt avatar stefanobaghino avatar stremlenye avatar tanishiking avatar tdidriksen avatar tgodzik avatar unkarjedy avatar vovapolu avatar ysusuk avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

scalafmt's Issues

Absurd formatting of a (deprecated) secondary constructor

Original:

@js.native
class ClipboardEvent(`type`: String, settings: ClipboardEventInit) extends Event {
  @deprecated("Use the overload with a ClipboardEventInit instead.", "0.8.1")
  def this(`type`: String, settings: js.Dynamic) = this(`type`, settings.asInstanceOf[ClipboardEventInit])

Scalafmt:

@js.native
class ClipboardEvent(`type` : String, settings: ClipboardEventInit)
    extends Event {
  @deprecated("Use the overload with a ClipboardEventInit instead.", "0.8.1") def this (`type` : String,
  settings: js.Dynamic) = this(
      `type`, settings.asInstanceOf[ClipboardEventInit])

I would like the input to look like this:

@js.native
class ClipboardEvent(`type` : String, settings: ClipboardEventInit)
    extends Event {
  @deprecated("Use the overload with a ClipboardEventInit instead.", "0.8.1")
  def this (`type`: String, settings: js.Dynamic) =
    this(`type`, settings.asInstanceOf[ClipboardEventInit])

Using

  • 0.1.1
  • default

Optimize policies.

Currently, each FormatToken is run against all policies. This can lead to O(n^2) overhead (each token is run against policies for all previous tokens).

Spurious breaking of a class header (it's not too long for one line)

Original:

 *
 */
@js.native
class MediaStream() extends EventTarget {

  /**
   * Is a Boolean value set to true if the ended event has been
   * fired on the object, meaning that the stream has been completely read,

Scalafmt:

 *
 */
@js.native
class MediaStream()
    extends EventTarget {
  /**
   * Is a Boolean value set to true if the ended event has been
   * fired on the object, meaning that the stream has been completely read,

I would like the input to look like this:

 *
 */
@js.native
class MediaStream() extends EventTarget {

  /**
   * Is a Boolean value set to true if the ended event has been
   * fired on the object, meaning that the stream has been completely read,

Using

  • 0.1.1
  • default

some indentation of long, nested types

Original:

val x:FooBarrrrrr[BaaaaaaaaaaaazBazzz[String, Option[List[Either[Int, Option[String]]]]]

Scalafmt (this is a guess):

val x: FooBarrrrrr[BaaaaaaaaaaaazBazzz[String, Option[List[Either[Int, Option[String]]]]]

I would like the input to look like this (roughly):

val x: FooBarrrrrr[
  BaaaaaaaaaaaazBazzz[
    String,
    Option[ List[
        Either[ Int, Option[String] ]
 ]]]

Breaking between params should be preferred over breaking inside []

Original:

@js.native
class MutationObserver(callback: js.Function2[js.Array[MutationRecord], MutationObserver, _]

Scalafmt:

@js.native
class MutationObserver(callback: js.Function2[js.Array[MutationRecord],
    MutationObserver, _])
    extends js.Object {

I would like the input to look like this:

@js.native
class MutationObserver(
    callback: js.Function2[js.Array[MutationRecord], MutationObserver, _])
    extends js.Object {

Using

  • 0.1.1
  • default

Preserve . chains

Unit test

<<< SKIP preserve chains, this is scala.js style.
  val files = FilesUtil.listFiles(".")
    .filter(_.endsWith(".scala"))
    .filterNot(_.contains("/target/"))
    .filterNot(_.contains("/resources/"))
>>>
val files = FilesUtil.listFiles(".")
  .filter(_.endsWith(".scala"))
  .filterNot(_.contains("/target/"))
  .filterNot(_.contains("/resources/"))

Members with backticks should not force a space before :

Original:

val `type`: String = js.native

Scalafmt:

val `type` : String = js.native

I would like the input to look like this:

val `type`: String = js.native

The space before : is not necessary after a backtick.

Using

  • 0.1.1
  • default

Existing blank line between comments should be kept

Original:

  // =======================================================================================
  // 6.3.2 Modifier Keys

  /** The Alternative (Alt, Option, Menu) key. Enable alternate modifier function for interp
  final val Alt = "Alt"

Scalafmt:

  // =======================================================================================
  // 6.3.2 Modifier Keys
  /** The Alternative (Alt, Option, Menu) key. Enable alternate modifier function for interp
  final val Alt = "Alt"

I would like the input to look like this:

  // =======================================================================================
  // 6.3.2 Modifier Keys

  /** The Alternative (Alt, Option, Menu) key. Enable alternate modifier function for interp
  final val Alt = "Alt"

i.e., the blank line that existed between two existing comments should be kept.

Using

  • 0.1.1
  • default

private[this] (and qualified-private?) is wrongly formatted

From Reddit

Original:

private[this] val root = Path(s"/$path")

Scalafmt:

private [ this] val root = Path(s"/$path")

I would like the input to look like this:

private[this] val root = Path(s"/$path")

This probably also applies to protected, as well as qualified-private private[EnclosingEntity].

Using

  • 0.1.1
  • (don't know)

Newline between `Defn`s

The current implentation is buggy, see output

[info]   case object OneArgOneLine extends ArgumentHandling trait ScalaStyle {
[info]     def maxColumn: Int
[info]       = 80 def argumentHandling: ArgumentHandling = OneArgOneLine
[info]   }

There should be a newline before the second def.

Support splitting strategies

Current model only supports local decisions for each FormatToken, however in some cases (e.g. argument list) I may want to make decisions at one FormatToken for multiple upcoming FormatTokens (e.g. opening '(' controls all commas and closing ')' of argument list).

Shrink search space

Two lines like this

val x = 1
val y = 2

do not interfere with each other. When we find the cheapest path to val in the second line, we can clear the search queue since we know no other path will lead to better results.

Escape hatch

Original:

// format: OFF
val identityMatrix = Array(1, 0, 0
                           0, 1, 0
                           0, 0, 1)
// format: ON

I would like the input to look like this:

// format: OFF
val identityMatrix = Array(1, 0, 0
                           0, 1, 0
                           0, 0, 1)
// format: ON

[Scala.js-specific] = js.native should always be kept on the same line

Note that this is not a question of preference of the Scala.js style guide. It should apply equally to all style guides, but it's specific to Scala.js code. The = js.native is a very special beast.

Original:

  def uniform4fv(location: WebGLUniformLocation, v: Float32Array): Unit = js.native

Scalafmt:

  def uniform4fv(location: WebGLUniformLocation, v: Float32Array): Unit =
    js.native

I would like the input to look like this:

  def uniform4fv(location: WebGLUniformLocation,
      v: Float32Array): Unit = js.native

In all cases, js.native should be kept right next to its =. Which means that the line should be broken somewhere else.

Using

  • 0.1.1
  • default

Prefer splitting at higher levels of nesting

This should be possible with policies, for example

<<< SKIP #15 Split at higher levels
object Object {
  val x = function(first(a, b), second(c, d))
}
>>>
object Object {
  val x = function(first(a, b),
                   second(c, d))
}

Format boolean conditions

Input

object a {
  if (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa &&
        bbbbbbbbbbbbbbbbbb) println("a")
}

Current output

[info]   object a {
[info]     if(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa && bbbbbbbbbbbbbbbbbb) println(
[info]         "a")
[info]   }

Strategies can constrain future splits

For example, the one-liner block strategy should be able to make sure that no newlines are introduced inside the block. Below the formatter is happy to insert a newline after function( even though we are trying to define Object in a single line.

object Object { function(
  argument) }

A possible solution is to increase the cost of newlines inside the block.

@annotations in front of `def` should be kept there

Original:

  @inline def Rule = raw.CSSRule

Scalafmt:

  @inline
  def Rule = raw.CSSRule

I would like the input to look like this:

  @inline def Rule = raw.CSSRule

at least if the everything up to = stays on one line.

Although, if the original had @inline on a separate line, I'd like scalafmt to keep it on a separate line.

Using

  • 0.1.1
  • default

Breaking before . in .-chain should be preferred over breaking inside []

Original:

object RsaHashedImportParams {
  @inline
  def apply(name: String, hash: HashAlgorithmIdentifier): RsaHashedImportParams =
    js.Dynamic.literal(name = name, hash = hash.asInstanceOf[js.Any]).asInstanceOf[RsaHashed
}

Scalafmt:

object RsaHashedImportParams {
  @inline
  def apply(
      name: String, hash: HashAlgorithmIdentifier): RsaHashedImportParams =
    js.Dynamic
      .literal(name = name, hash = hash.asInstanceOf[js.Any]).asInstanceOf[
        RsaHashedImportParams]
}

I would like the input to look like this:

object RsaHashedImportParams {
  @inline
  def apply(
      name: String, hash: HashAlgorithmIdentifier): RsaHashedImportParams =
    js.Dynamic
      .literal(name = name, hash = hash.asInstanceOf[js.Any])
      .asInstanceOf[RsaHashedImportParams]
}

Using

  • 0.1.1
  • default

Safer/richer indentation abstraction

The indentation is managed by State.indent: Int. Splits and policies can increment/decrement the int.

  • This makes it tricky for example to indent a function argument to the same column as the opening ( because we don't know the exact integer value of the state's column.
  • unindenting the same number of spaces at the closing ) requires us to know integer value at the opening )
  • We violate DRY by relying on decrementing the same number as we increment.

A more powerful abstraction would work like a stack, you push an Indent which can be a concrete number or a useful object like state.column

/* */ comment at EOL should be attached like a //

Original:

  final val BLEND_EQUATION = 0x8009
  final val BLEND_EQUATION_RGB = 0x8009   /* same as BLEND_EQUATION */
  final val BLEND_EQUATION_ALPHA = 0x883D

Scalafmt:

  final val BLEND_EQUATION = 0x8009
  final val BLEND_EQUATION_RGB = 0x8009
  /* same as BLEND_EQUATION */
  final val BLEND_EQUATION_ALPHA = 0x883D

I would like the input to look like this:

  final val BLEND_EQUATION = 0x8009
  final val BLEND_EQUATION_RGB = 0x8009 /* same as BLEND_EQUATION */
  final val BLEND_EQUATION_ALPHA = 0x883D

Of course, that comment should have been a // comment in the first place. But that's no excuse ;) The current reformatting actively harms further readability.

Using

  • 0.1.1
  • default

Disappearing blank line between method and Scaladoc of the next method

Original:

  /**
   * See [[https://streams.spec.whatwg.org/#reader-cancel §3.4.4.2. cancel(reason)]]
   * of whatwg Streams spec.
   *
   * If the reader is active, the cancel method behaves the same as that for
   * the associated stream. When done, it automatically releases the lock.
   *
   * //todo determine type of reason
   */
  def cancel(reason: Any): js.Promise[Any] = js.native //not actually sure what the return type is here

  /**
   * See [[https://streams.spec.whatwg.org/#reader-read 3.4.4.3. read()]] of
   * whatwg Stream spec.
   *
   * The read method will return a promise that allows access to the next chunk
   * from the stream’s internal queue, if available. If the chunk does become
   * available, the promise will be fulfilled with an object of the form {
   * value: theChunk, done: false }. If the stream becomes closed, the
   * promise will be fulfilled with an object of the form { value: undefined,
   * done: true }. If the stream becomes errored, the promise will be
   * rejected with the relevant error. If reading a chunk causes the queue to
   * become empty, more data will be pulled from the underlying source.
   */
  def read(): js.Promise[Chunk[T]] = js.native

Scalafmt:

  /**
   * See [[https://streams.spec.whatwg.org/#reader-cancel §3.4.4.2. cancel(reason)]]
   * of whatwg Streams spec.
   *
   * If the reader is active, the cancel method behaves the same as that for
   * the associated stream. When done, it automatically releases the lock.
   *
   * //todo determine type of reason
   */
  def cancel(reason: Any): js.Promise[Any] =
    js.native //not actually sure what the return type is here
  /**
   * See [[https://streams.spec.whatwg.org/#reader-read 3.4.4.3. read()]] of
   * whatwg Stream spec.
   *
   * The read method will return a promise that allows access to the next chunk
   * from the stream’s internal queue, if available. If the chunk does become
   * available, the promise will be fulfilled with an object of the form {
   * value: theChunk, done: false }. If the stream becomes closed, the
   * promise will be fulfilled with an object of the form { value: undefined,
   * done: true }. If the stream becomes errored, the promise will be
   * rejected with the relevant error. If reading a chunk causes the queue to
   * become empty, more data will be pulled from the underlying source.
   */
  def read(): js.Promise[Chunk[T]] = js.native

I would like the input to look like this:

  /**
   * See [[https://streams.spec.whatwg.org/#reader-cancel §3.4.4.2. cancel(reason)]]
   * of whatwg Streams spec.
   *
   * If the reader is active, the cancel method behaves the same as that for
   * the associated stream. When done, it automatically releases the lock.
   *
   * //todo determine type of reason
   */
  def cancel(reason: Any): js.Promise[Any] =
    js.native //not actually sure what the return type is here

  /**
   * See [[https://streams.spec.whatwg.org/#reader-read 3.4.4.3. read()]] of
   * whatwg Stream spec.
   *
   * The read method will return a promise that allows access to the next chunk
   * from the stream’s internal queue, if available. If the chunk does become
   * available, the promise will be fulfilled with an object of the form {
   * value: theChunk, done: false }. If the stream becomes closed, the
   * promise will be fulfilled with an object of the form { value: undefined,
   * done: true }. If the stream becomes errored, the promise will be
   * rejected with the relevant error. If reading a chunk causes the queue to
   * become empty, more data will be pulled from the underlying source.
   */
  def read(): js.Promise[Chunk[T]] = js.native

Using

  • 0.1.1
  • default

Correctly unindent multiline comments

It's not enough to unindent the comment token here, we also want to remove 2 spaces before the * starting each line afterwards.

[info]   object a {
[info]     /**
[info]        * One
[info]        */
[info]     def one = 1
[info]   }

There should be no space before a * of repeated param

Original:

    def fillPath(points: (Double, Double)*) = {
      prepPath(points)
      ctx.fill()
    }

Scalafmt:

    def fillPath(points: (Double, Double) *) = {
      prepPath(points)
      ctx.fill()
    }

I would like the input to look like this:

    def fillPath(points: (Double, Double)*) = {
      prepPath(points)
      ctx.fill()
    }

Using

  • 0.1.1
  • default

Make it easy to validate performance improvements.

For example, keep a golden-performance.csv file under tests and after every test run compare performance of last run to golden performance. We need to take into account different hardware, of course.

More robust indentation

Push should expire at a certain token, and then we can eliminate Pop.

The current implementation makes it too easy to pop the wrong indentation, and get output like

[info]   ===========
[info]   => Obtained
[info]   ===========
[info]   {
[info]     val x = 1
[info]
[info]     def log(split: Split): String =
[info]       s"$split"
[info]     }

Breaking of import lines

Original:

import scala.language.implicitConversions

import org.scalajs.dom.experimental.serviceworkers.{ServiceWorkerGlobalScope, ServiceWorkerRegistration}

import scala.scalajs.js

Scalafmt:

import scala.language.implicitConversions

import org.scalajs.dom.experimental.serviceworkers.{ServiceWorkerGlobalScope,
ServiceWorkerRegistration}

import scala.scalajs.js

I would like the input to look like this:

import scala.language.implicitConversions

import org.scalajs.dom.experimental.serviceworkers.{ServiceWorkerGlobalScope, ServiceWorkerRegistration}

import scala.scalajs.js

or

import scala.language.implicitConversions

import org.scalajs.dom.experimental.serviceworkers.{
  ServiceWorkerGlobalScope, ServiceWorkerRegistration
}

import scala.scalajs.js

Using

  • 0.1.1
  • default

Test for mis-formatted text

Would love (specifically in SBT but probably in other contexts) to have an option to test for formatting violations (so we can fail a build) without having to actually format the code.

(personal preference?) If breaking before `with`, should break before `extends` beforehand

Original:

trait WorkerNavigator extends NavigatorID with NavigatorOnLine with NavigatorLanguage

Scalafmt:

trait WorkerNavigator extends NavigatorID with NavigatorOnLine
    with NavigatorLanguage

I would like the input to look like this:

trait WorkerNavigator
    extends NavigatorID with NavigatorOnLine with NavigatorLanguage

or, if that does not fit on the line length either:

trait WorkerNavigator
    extends NavigatorID with NavigatorOnLine
    with NavigatorLanguage

Using

  • 0.1.1
  • default

(personal preference?) Empty {} should be kept on separate lines

Original:

abstract class HTMLTableHeaderCellElement extends HTMLTableCellElement {
}

Scalafmt:

abstract class HTMLTableHeaderCellElement extends HTMLTableCellElement {}

I would like the input to look like this:

abstract class HTMLTableHeaderCellElement extends HTMLTableCellElement {
}

Using

  • 0.1.1
  • default

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.