diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 335f233a8d..7af707b059 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -36,7 +36,6 @@ For the folders below in monospace text, they are published on maven central at | `lib-extra` | Contains the optional parts of Spotless which require external dependencies. `LineEnding.GIT_ATTRIBUTES` won't work unless `lib-extra` is available. | | `plugin-gradle` | Integrates spotless and all of its formatters into Gradle. | | `plugin-maven` | Integrates spotless and all of its formatters into Maven. | -| javadoc-publish | Logic for publishing javadoc to github-pages. | | ide | Generates and launches an IDE for developing spotless. | | _ext | Folder for generating glue jars (specifically packaging Eclipse jars from p2 for consumption using maven). @@ -105,8 +104,7 @@ Here's a checklist for creating a new step for Spotless: The `_ext` projects are disabled per default, since: -* some of the projects perform vasts downloads at configuration time - +* some of the projects perform vast downloads at configuration time * the downloaded content may change on server side and break CI builds @@ -116,7 +114,6 @@ Activate the the property via command line, like for example: ``` gradlew -Pcom.diffplug.spotless.include.ext=true build - ``` Or set the property in your user `gradle.properties` file, which is especially recommended if you like to work with the `_ext` projects using IDEs. diff --git a/README.md b/README.md index f0a7d9c616..f0d6a4a63c 100644 --- a/README.md +++ b/README.md @@ -33,13 +33,20 @@ function extra(className) { return '| [`' + className + '`](lib-extra/src/main/j output = [ '| Feature / FormatterStep | [plugin-gradle](plugin-gradle/README.md) | [plugin-maven](plugin-maven/README.md) | [(Your build tool here)](CONTRIBUTING.md#how-to-add-a-new-plugin-for-a-build-system) |', '| --------------------------------------------- | ------------- | ------------ | --------|', -lib('generic.EndWithNewlineStep') +'{{yes}} | {{yes}} | {{no}} |', -lib('generic.IndentStep') +'{{yes}} | {{yes}} | {{no}} |', +'| Automatic [idempotency safeguard](PADDEDCELL.md) | {{yes}} | {{yes}} | {{no}} |', +'| Misconfigured [encoding safeguard](https://github.com/diffplug/spotless/blob/08340a11566cdf56ecf50dbd4d557ed84a70a502/testlib/src/test/java/com/diffplug/spotless/EncodingErrorMsgTest.java#L34-L38) | {{yes}} | {{yes}} | {{no}} |', +'| [Ratchet from](https://github.com/diffplug/spotless/tree/main/plugin-gradle#ratchet) `origin/main` or other git ref | {{yes}} | {{yes}} | {{no}} |', +'| Define [line endings using git](https://github.com/diffplug/spotless/tree/main/plugin-gradle#line-endings-and-encodings-invisible-stuff) | {{yes}} | {{yes}} | {{no}} |', +'| Fast incremental format and up-to-date check | {{yes}} | {{no}} | {{no}} |', +'| Fast format on fresh checkout using buildcache | {{yes}} | {{no}} | {{no}} |', +lib('generic.EndWithNewlineStep') +'{{yes}} | {{yes}} | {{no}} |', +lib('generic.IndentStep') +'{{yes}} | {{yes}} | {{no}} |', lib('generic.LicenseHeaderStep') +'{{yes}} | {{yes}} | {{no}} |', -lib('generic.ReplaceRegexStep') +'{{yes}} | {{yes}} | {{no}} |', -lib('generic.ReplaceStep') +'{{yes}} | {{yes}} | {{no}} |', -lib('generic.TrimTrailingWhitespaceStep') +'{{yes}} | {{yes}} | {{no}} |', -extra('cpp.EclipseFormatterStep') +'{{yes}} | {{yes}} | {{no}} |', +lib('generic.ReplaceRegexStep') +'{{yes}} | {{yes}} | {{no}} |', +lib('generic.ReplaceStep') +'{{yes}} | {{yes}} | {{no}} |', +lib('generic.TrimTrailingWhitespaceStep') +'{{yes}} | {{yes}} | {{no}} |', +lib('antlr4.Antlr4FormatterStep') +'{{yes}} | {{yes}} | {{no}} |', +extra('cpp.EclipseFormatterStep') +'{{yes}} | {{yes}} | {{no}} |', extra('groovy.GrEclipseFormatterStep') +'{{yes}} | {{no}} | {{no}} |', lib('java.GoogleJavaFormatStep') +'{{yes}} | {{yes}} | {{no}} |', lib('java.ImportOrderStep') +'{{yes}} | {{yes}} | {{no}} |', @@ -48,26 +55,30 @@ extra('java.EclipseFormatterStep') +'{{yes}} | {{yes}} lib('kotlin.KtLintStep') +'{{yes}} | {{yes}} | {{no}} |', lib('kotlin.KtfmtStep') +'{{yes}} | {{yes}} | {{no}} |', lib('markdown.FreshMarkStep') +'{{yes}} | {{no}} | {{no}} |', -lib('npm.PrettierFormatterStep') +'{{yes}} | {{yes}} | {{no}} |', -lib('npm.TsFmtFormatterStep') +'{{yes}} | {{yes}} | {{no}} |', -lib('scala.ScalaFmtStep') +'{{yes}} | {{yes}} | {{no}} |', +lib('npm.PrettierFormatterStep') +'{{yes}} | {{yes}} | {{no}} |', +lib('npm.TsFmtFormatterStep') +'{{yes}} | {{yes}} | {{no}} |', +lib('scala.ScalaFmtStep') +'{{yes}} | {{yes}} | {{no}} |', lib('sql.DBeaverSQLFormatterStep') +'{{yes}} | {{no}} | {{no}} |', extra('wtp.EclipseWtpFormatterStep') +'{{yes}} | {{yes}} | {{no}} |', -'| [(Your FormatterStep here)](CONTRIBUTING.md#how-to-add-a-new-formatterstep) | {{no}} | {{no}} | {{no}} |', -'| Fast up-to-date checking | {{yes}} | {{no}} | {{no}} |', -'| Automatic idempotency safeguard | {{yes}} | {{no}} | {{no}} |', -'' +'| [(Your FormatterStep here)](CONTRIBUTING.md#how-to-add-a-new-formatterstep) | {{no}} | {{no}} | {{no}} |', ].join('\n'); --> | Feature / FormatterStep | [plugin-gradle](plugin-gradle/README.md) | [plugin-maven](plugin-maven/README.md) | [(Your build tool here)](CONTRIBUTING.md#how-to-add-a-new-plugin-for-a-build-system) | | --------------------------------------------- | ------------- | ------------ | --------| -| [`generic.EndWithNewlineStep`](lib/src/main/java/com/diffplug/spotless/generic/EndWithNewlineStep.java) | :+1: | :+1: | :white_large_square: | -| [`generic.IndentStep`](lib/src/main/java/com/diffplug/spotless/generic/IndentStep.java) | :+1: | :+1: | :white_large_square: | +| Automatic [idempotency safeguard](PADDEDCELL.md) | :+1: | :+1: | :white_large_square: | +| Misconfigured [encoding safeguard](https://github.com/diffplug/spotless/blob/08340a11566cdf56ecf50dbd4d557ed84a70a502/testlib/src/test/java/com/diffplug/spotless/EncodingErrorMsgTest.java#L34-L38) | :+1: | :+1: | :white_large_square: | +| [Ratchet from](https://github.com/diffplug/spotless/tree/main/plugin-gradle#ratchet) `origin/main` or other git ref | :+1: | :+1: | :white_large_square: | +| Define [line endings using git](https://github.com/diffplug/spotless/tree/main/plugin-gradle#line-endings-and-encodings-invisible-stuff) | :+1: | :+1: | :white_large_square: | +| Fast incremental format and up-to-date check | :+1: | :white_large_square: | :white_large_square: | +| Fast format on fresh checkout using buildcache | :+1: | :white_large_square: | :white_large_square: | +| [`generic.EndWithNewlineStep`](lib/src/main/java/com/diffplug/spotless/generic/EndWithNewlineStep.java) | :+1: | :+1: | :white_large_square: | +| [`generic.IndentStep`](lib/src/main/java/com/diffplug/spotless/generic/IndentStep.java) | :+1: | :+1: | :white_large_square: | | [`generic.LicenseHeaderStep`](lib/src/main/java/com/diffplug/spotless/generic/LicenseHeaderStep.java) | :+1: | :+1: | :white_large_square: | -| [`generic.ReplaceRegexStep`](lib/src/main/java/com/diffplug/spotless/generic/ReplaceRegexStep.java) | :+1: | :+1: | :white_large_square: | -| [`generic.ReplaceStep`](lib/src/main/java/com/diffplug/spotless/generic/ReplaceStep.java) | :+1: | :+1: | :white_large_square: | -| [`generic.TrimTrailingWhitespaceStep`](lib/src/main/java/com/diffplug/spotless/generic/TrimTrailingWhitespaceStep.java) | :+1: | :+1: | :white_large_square: | -| [`cpp.EclipseFormatterStep`](lib-extra/src/main/java/com/diffplug/spotless/extra/cpp/EclipseFormatterStep.java) | :+1: | :+1: | :white_large_square: | +| [`generic.ReplaceRegexStep`](lib/src/main/java/com/diffplug/spotless/generic/ReplaceRegexStep.java) | :+1: | :+1: | :white_large_square: | +| [`generic.ReplaceStep`](lib/src/main/java/com/diffplug/spotless/generic/ReplaceStep.java) | :+1: | :+1: | :white_large_square: | +| [`generic.TrimTrailingWhitespaceStep`](lib/src/main/java/com/diffplug/spotless/generic/TrimTrailingWhitespaceStep.java) | :+1: | :+1: | :white_large_square: | +| [`antlr4.Antlr4FormatterStep`](lib/src/main/java/com/diffplug/spotless/antlr4/Antlr4FormatterStep.java) | :+1: | :+1: | :white_large_square: | +| [`cpp.EclipseFormatterStep`](lib-extra/src/main/java/com/diffplug/spotless/extra/cpp/EclipseFormatterStep.java) | :+1: | :+1: | :white_large_square: | | [`groovy.GrEclipseFormatterStep`](lib-extra/src/main/java/com/diffplug/spotless/extra/groovy/GrEclipseFormatterStep.java) | :+1: | :white_large_square: | :white_large_square: | | [`java.GoogleJavaFormatStep`](lib/src/main/java/com/diffplug/spotless/java/GoogleJavaFormatStep.java) | :+1: | :+1: | :white_large_square: | | [`java.ImportOrderStep`](lib/src/main/java/com/diffplug/spotless/java/ImportOrderStep.java) | :+1: | :+1: | :white_large_square: | @@ -76,14 +87,12 @@ extra('wtp.EclipseWtpFormatterStep') +'{{yes}} | {{yes}} | [`kotlin.KtLintStep`](lib/src/main/java/com/diffplug/spotless/kotlin/KtLintStep.java) | :+1: | :+1: | :white_large_square: | | [`kotlin.KtfmtStep`](lib/src/main/java/com/diffplug/spotless/kotlin/KtfmtStep.java) | :+1: | :+1: | :white_large_square: | | [`markdown.FreshMarkStep`](lib/src/main/java/com/diffplug/spotless/markdown/FreshMarkStep.java) | :+1: | :white_large_square: | :white_large_square: | -| [`npm.PrettierFormatterStep`](lib/src/main/java/com/diffplug/spotless/npm/PrettierFormatterStep.java) | :+1: | :+1: | :white_large_square: | -| [`npm.TsFmtFormatterStep`](lib/src/main/java/com/diffplug/spotless/npm/TsFmtFormatterStep.java) | :+1: | :+1: | :white_large_square: | -| [`scala.ScalaFmtStep`](lib/src/main/java/com/diffplug/spotless/scala/ScalaFmtStep.java) | :+1: | :+1: | :white_large_square: | +| [`npm.PrettierFormatterStep`](lib/src/main/java/com/diffplug/spotless/npm/PrettierFormatterStep.java) | :+1: | :+1: | :white_large_square: | +| [`npm.TsFmtFormatterStep`](lib/src/main/java/com/diffplug/spotless/npm/TsFmtFormatterStep.java) | :+1: | :+1: | :white_large_square: | +| [`scala.ScalaFmtStep`](lib/src/main/java/com/diffplug/spotless/scala/ScalaFmtStep.java) | :+1: | :+1: | :white_large_square: | | [`sql.DBeaverSQLFormatterStep`](lib/src/main/java/com/diffplug/spotless/sql/DBeaverSQLFormatterStep.java) | :+1: | :white_large_square: | :white_large_square: | | [`wtp.EclipseWtpFormatterStep`](lib-extra/src/main/java/com/diffplug/spotless/extra/wtp/EclipseWtpFormatterStep.java) | :+1: | :+1: | :white_large_square: | -| [(Your FormatterStep here)](CONTRIBUTING.md#how-to-add-a-new-formatterstep) | :white_large_square: | :white_large_square: | :white_large_square: | -| Fast up-to-date checking | :+1: | :white_large_square: | :white_large_square: | -| Automatic idempotency safeguard | :+1: | :white_large_square: | :white_large_square: | +| [(Your FormatterStep here)](CONTRIBUTING.md#how-to-add-a-new-formatterstep) | :white_large_square: | :white_large_square: | :white_large_square: | *Why are there empty squares?* Many projects get harder to work on as they get bigger. Spotless is easier to work on than ever, and one of the reasons why is that we don't require contributors to "fill the matrix". If you want to [add Bazel support](https://github.com/diffplug/spotless/issues/76), we'd happily accept the PR even if it only supports the one formatter you use. And if you want to add FooFormatter support, we'll happily accept the PR even if it only supports the one build system you use. diff --git a/plugin-gradle/README.md b/plugin-gradle/README.md index 0a58a9ce9a..ab0a0e8b89 100644 --- a/plugin-gradle/README.md +++ b/plugin-gradle/README.md @@ -35,174 +35,188 @@ Spotless is a general-purpose formatting plugin used by [3,500 projects on GitHu To people who use your build, it looks like this ([IDE support also available]()): -``` -cmd> gradlew build -... +```console +user@machine repo % ./gradlew build :spotlessJavaCheck FAILED -> The following files had format violations: + The following files had format violations: src\main\java\com\diffplug\gradle\spotless\FormatExtension.java - @@ -109,7 +109,7 @@ - ... -\t\t····if·(targets.length·==·0)·{ +\t\tif·(targets.length·==·0)·{ - ... - Run 'gradlew spotlessApply' to fix these violations. - -cmd> gradlew spotlessApply + Run './gradlew spotlessApply' to fix these violations. +user@machine repo % ./gradlew spotlessApply :spotlessApply BUILD SUCCESSFUL - -cmd> gradlew build +user@machine repo % ./gradlew build BUILD SUCCESSFUL ``` +### Table of Contents + +- [**Quickstart**](#quickstart) + - [Requirements](#requirements) +- **Languages** + - [Java](#java) ([google-java-format](#google-java-format), [eclipse jdt](#eclipse-jdt), [prettier](#prettier)) + - [Groovy](#groovy) ([eclipse groovy](#eclipse-groovy)) + - [Kotlin](#kotlin) ([ktlint](#ktlint), [ktfmt](#ktfmt), [prettier](#prettier)) + - [Scala](#scala) ([scalafmt](#scalafmt)) + - [C/C++](#c-c++) ([eclipse cdt](#eclipse-cdt)) + - [FreshMark](#freshmark) aka markdown + - [Antlr4](#antlr4) ([antlr4formatter](#antlr4formatter)) + - [SQL](#sql) ([dbeaver](#dbeaver), [prettier](#prettier)) + - [Typescript](#typescript) ([tsfmt](#tsfmt), [prettier](#prettier)) + - Multiple languages + - [Prettier](#prettier) ([plugins](#prettier-plugins), [npm detection](#npm-detection)) + - [eclipse web tools platform](#eclipse-web-tools-platform) +- **Language independent** + - [License header](#license-header) ([slurp year from git](#retroactively-slurp-years-from-git-history)) + - [How can I enforce formatting gradually? (aka "ratchet")](#ratchet) + - [Line endings and encodings (invisible stuff)](#line-endings-and-encodings-invisible-stuff) + - [Custom steps](#custom-steps) + - [Multiple (or custom) language-specific blocks](#multiple-or-custom-language-specific-blocks) + - [Disabling warnings and error messages](#disabling-warnings-and-error-messages) + - [How do I preview what `spotlessApply` will do?](#how-do-i-preview-what-spotlessapply-will-do) + - [Example configurations (from real-world projects)](#example-configurations-from-real-world-projects) + +***Contributions are welcome, see [the contributing guide](../CONTRIBUTING.md) for development info.*** + +## Quickstart + To use it in your buildscript, just [add the Spotless dependency](https://plugins.gradle.org/plugin/com.diffplug.gradle.spotless), and configure it like so: ```gradle spotless { + // optional: limit format enforcement to just the files changed by this feature branch + ratchetFrom 'origin/main' + format 'misc', { - target '**/*.gradle', '**/*.md', '**/.gitignore' + // define the files to apply `misc` to + target '*.gradle', '*.md', '.gitignore' + // define the steps to apply to those files trimTrailingWhitespace() indentWithTabs() // or spaces. Takes an integer argument if you don't like 4 endWithNewline() } - format 'cpp', { - target '**/*.hpp', '**/*.cpp' - - replace 'Not enough space after if', 'if(', 'if (' - replaceRegex 'Too much space after if', 'if +\\(', 'if (' - - // Everything before the first #include or #pragma will - // be replaced with whatever is in `spotless.license.cpp` - licenseHeaderFile 'spotless.license.cpp', '#' + java { + // don't need to set target, it is inferred from java + + // apply a specific flavor of google-java-format + googleJavaFormat('1.8').aosp() + // make sure every file has the following copyright header. + // optionally, Spotless can set copyright years by digging + // through git history (see "license" section below) + licenseHeader '/* (C)$YEAR */' } } ``` -Spotless can check and apply formatting to any plain-text file, using simple rules ([javadoc](https://javadoc.io/static/com.diffplug.spotless/spotless-plugin-gradle/4.4.0/com/diffplug/gradle/spotless/FormatExtension.html)) like those above. It also supports more powerful formatters: +Spotless consists of a list of formats (in the example above, `misc` and `java`), and each format has: +- a `target` (the files to format), which you set with [`target`](https://javadoc.io/static/com.diffplug.spotless/spotless-plugin-gradle/4.4.0/com/diffplug/gradle/spotless/FormatExtension.html#target-java.lang.Object...-) and [`targetExclude`](https://javadoc.io/static/com.diffplug.spotless/spotless-plugin-gradle/4.4.0/com/diffplug/gradle/spotless/FormatExtension.html#targetExclude-java.lang.Object...-) +- a list of `FormatterStep`, which are just `String -> String` functions, such as [`replace`](https://javadoc.io/static/com.diffplug.spotless/spotless-plugin-gradle/4.4.0/com/diffplug/gradle/spotless/FormatExtension.html#replace-java.lang.String-java.lang.CharSequence-java.lang.CharSequence-), [`replaceRegex`](https://javadoc.io/static/com.diffplug.spotless/spotless-plugin-gradle/4.4.0/com/diffplug/gradle/spotless/FormatExtension.html#replaceRegex-java.lang.String-java.lang.String-java.lang.String-), [`trimTrailingWhitespace`](https://javadoc.io/static/com.diffplug.spotless/spotless-plugin-gradle/4.4.0/com/diffplug/gradle/spotless/FormatExtension.html#replace-java.lang.String-java.lang.CharSequence-java.lang.CharSequence-), [`custom`](https://javadoc.io/static/com.diffplug.spotless/spotless-plugin-gradle/4.4.0/com/diffplug/gradle/spotless/FormatExtension.html#custom-java.lang.String-groovy.lang.Closure-), [`prettier`](https://javadoc.io/static/com.diffplug.spotless/spotless-plugin-gradle/4.4.0/com/diffplug/gradle/spotless/FormatExtension.html#prettier--), [`eclipseWtp`](https://javadoc.io/static/com.diffplug.spotless/spotless-plugin-gradle/4.4.0/com/diffplug/gradle/spotless/FormatExtension.html#eclipseWtp-com.diffplug.spotless.extra.wtp.EclipseWtpFormatterStep-), [`licenseHeader`](https://javadoc.io/static/com.diffplug.spotless/spotless-plugin-gradle/4.4.0/com/diffplug/gradle/spotless/FormatExtension.html#licenseHeader-java.lang.String-java.lang.String-) etc. -* Eclipse's [CDT](#eclipse-cdt) C/C++ code formatter -* Eclipse's java code formatter (including style and import ordering) -* Eclipse's [WTP](#eclipse-wtp) HTML, XML, ... code formatters -* Google's [google-java-format](https://github.com/google/google-java-format) -* [Groovy Eclipse](#groovy-eclipse)'s groovy code formatter -* [FreshMark](https://github.com/diffplug/freshmark) (markdown with variables) -* [ktlint](https://github.com/pinterest/ktlint) -* [ktfmt](https://github.com/facebookincubator/ktfmt) -* [scalafmt](https://github.com/olafurpg/scalafmt) -* [DBeaver sql format](https://dbeaver.jkiss.org/) -* [Prettier: An opinionated code formatter](https://prettier.io) -* [TypeScript Formatter (tsfmt)](https://github.com/vvakame/typescript-formatter) -* Any user-defined function which takes an unformatted string and outputs a formatted version. +All the generic steps live in [`FormatExtension`](https://javadoc.io/static/com.diffplug.spotless/spotless-plugin-gradle/4.4.0/com/diffplug/gradle/spotless/FormatExtension.html), and there are many language-specific steps which live in its language-specific subclasses, which are described below. -Contributions are welcome, see [the contributing guide](../CONTRIBUTING.md) for development info. +Spotless supports all of Gradle's built-in performance features (incremental build, buildcache, lazy configuration, etc), and also automatically fixes [idempotence issues](https://github.com/diffplug/spotless/blob/main/PADDEDCELL.md), infers [line-endings from git](#line-endings-and-encodings-invisible-stuff), is cautious about [misconfigured encoding](https://github.com/diffplug/spotless/blob/08340a11566cdf56ecf50dbd4d557ed84a70a502/testlib/src/test/java/com/diffplug/spotless/EncodingErrorMsgTest.java#L34-L38) bugs, and can use git to [ratchet formatting](#ratchet) without "format-everything" commits. -Spotless requires Gradle to be running on JRE 8+.See [issue #7](https://github.com/diffplug/spotless/issues/7) for details. +### Requirements - +Spotless requires JRE 8+, and Gradle 2.14+. Some steps require JRE 11+, `Unsupported major.minor version` means you're using a step that needs a newer JRE. -## Applying to Java source + -By default, all Java source sets will be formatted. To change this, -set the `target` parameter as described in the [Custom rules](#custom) section. +## Java -```gradle -apply plugin: 'java' -... +`com.diffplug.gradle.spotless.JavaExtension` [javadoc](https://javadoc.io/static/com.diffplug.spotless/spotless-plugin-gradle/4.4.0/com/diffplug/gradle/spotless/JavaExtension.html), [code](https://github.com/diffplug/spotless/blob/main/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/JavaExtension.java) +```gradle spotless { java { - licenseHeader '/* Licensed under Apache-2.0 */' // License header - licenseHeaderFile 'spotless.license.java' // License header file - // Obviously, you can't specify both licenseHeader and licenseHeaderFile at the same time - - importOrder 'java', 'javax', 'org', 'com', 'com.diffplug', '' // A sequence of package names - importOrderFile 'spotless.importorder' // An import ordering file, exported from Eclipse - // As before, you can't specify both importOrder and importOrderFile at the same time - // You probably want an empty string at the end - all of the imports you didn't specify - // explicitly will go there. - - removeUnusedImports() // removes any unused imports - - eclipse().configFile 'spotless.eclipseformat.xml' // XML file dumped out by the Eclipse formatter - // If you have Eclipse preference or property files, you can use them too. - // eclipse('4.7.1') to specify a specific version of eclipse, - // available versions are: https://github.com/diffplug/spotless/tree/main/lib-extra/src/main/resources/com/diffplug/spotless/extra/eclipse_jdt_formatter + importOrder() // standard import order + importOrder('java', 'javax', 'com.acme', '') // or importOrderFile + // You probably want an empty string at the end - all of the + // imports you didn't specify explicitly will go there. + + removeUnusedImports() + + googleJavaFormat() // has its own section below + eclipse() // has its own section below + prettier() // has its own section below + + licenseHeader '/* (C) $YEAR */' // or licenseHeaderFile } } ``` -See [ECLIPSE_SCREENSHOTS](../ECLIPSE_SCREENSHOTS.md) for screenshots that demonstrate how to get and install the eclipseFormatFile and importOrderFile mentioned above. - - + -### Applying to Android Java source -Be sure to add `target 'src/*/java/**/*.java'` otherwise spotless will not detect Java code inside Android modules. +The target is usually inferred automatically from the java source sets. However, Spotless cannot automatically detect [android](https://github.com/diffplug/spotless/issues/111) or [java-gradle-plugin](https://github.com/diffplug/spotless/issues/437) sources, but you can fix this easily: ```gradle spotless { java { - // ... target 'src/*/java/**/*.java' - // ... - } -} ``` - - -### Applying to Java source with [google-java-format](https://github.com/google/google-java-format) +### google-java-format +[homepage](https://github.com/google/google-java-format). [changelog](https://github.com/google/google-java-format/releases). ```gradle spotless { java { googleJavaFormat() // optional: you can specify a specific version and/or switch to AOSP style - googleJavaFormat('1.1').aosp() - // you can then layer other format steps, such as - licenseHeaderFile 'spotless.license.java' - } -} + // + googleJavaFormat('1.7').aosp() +``` + +### eclipse jdt + +[homepage](https://www.eclipse.org/downloads/packages/). [compatible versions](https://github.com/diffplug/spotless/tree/main/lib-extra/src/main/resources/com/diffplug/spotless/extra/eclipse_jdt_formatter). See [here](../ECLIPSE_SCREENSHOTS.md) for screenshots that demonstrate how to get and install the config file mentioned below. + +```gradle +spotless { + java { + eclipse() + // optional: you can specify a specific version and/or config file + eclipse('4.17').configFile('eclipse-prefs.xml') ``` - -## Applying to Groovy source + + +## Groovy + +- `com.diffplug.gradle.spotless.GroovyExtension` [javadoc](https://javadoc.io/static/com.diffplug.spotless/spotless-plugin-gradle/4.4.0/com/diffplug/gradle/spotless/GroovyExtension.html), [code](https://github.com/diffplug/spotless/blob/main/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/GroovyExtension.java) +- `com.diffplug.gradle.spotless.GroovyGradleExtension` [javadoc](https://javadoc.io/static/com.diffplug.spotless/spotless-plugin-gradle/4.4.0/com/diffplug/gradle/spotless/GroovyGradleExtension.html), [code](https://github.com/diffplug/spotless/blob/main/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/GroovyGradleExtension.java) -Configuration for Groovy is similar to [Java](#java). Most java steps, like `licenseHeader` and `importOrder`, support Groovy as well as Java. +Configuration for Groovy is similar to [Java](#java), in that it also supports `licenseHeader` and `importOrder`. -The groovy formatter's default behavior is to format all `.groovy` and `.java` files found in the Groovy source directories. If you would like to exclude the `.java` files, set the parameter `excludeJava`, or you can set the `target` parameter as described in the [Custom rules](#custom) section. +The groovy formatter's default behavior is to format all `.groovy` and `.java` files found in the Java and Groovy source sets. If you would like to exclude the `.java` files, set the parameter `excludeJava`, or you can set the `target` parameter as described in the [Custom rules](#custom) section. ```gradle apply plugin: 'groovy' -... - spotless { - java { - licenseHeaderFile 'spotless.license.java' - googleJavaFormat() // use a specific formatter for Java files - } groovy { - licenseHeaderFile 'spotless.license.java' + importOrder() // standard import order + importOrder('java', 'javax', 'com.acme', '') // or importOrderFile + excludeJava() // excludes all Java sources within the Groovy source dirs from formatting // the Groovy Eclipse formatter extends the Java Eclipse formatter, // so it formats Java files by default (unless `excludeJava` is used). - greclipse().configFile('greclipse.properties') + greclipse() // has its own section below + + licenseHeader '/* (C) $YEAR */' // or licenseHeaderFile } groovyGradle { - // same as groovy, but for .gradle (defaults to '*.gradle') - target '*.gradle', 'additionalScripts/*.gradle' - greclipse().configFile('greclipse.properties') + target '*.gradle' // default target of groovyGradle + greclipse() } } ``` - -### [Groovy-Eclipse](https://github.com/groovy/groovy-eclipse) formatter - -The Groovy formatter uses some of the Eclipse [Java formatter](#java) configuration parameters in addition to Groovy-Eclipse specific ones. All parameters can be configured within a single file, like the Java properties file [greclipse.properties](../testlib/src/main/resources/groovy/greclipse/format/greclipse.properties) in the previous example. The formatter step can also load the [exported Eclipse properties](../ECLIPSE_SCREENSHOTS.md) and augment it with the `.metadata/.plugins/org.eclipse.core.runtime/.settings/org.codehaus.groovy.eclipse.ui.prefs` from your Eclipse workspace as shown below. +### eclipse groovy +[homepage](https://github.com/groovy/groovy-eclipse/wiki). [changelog](https://github.com/groovy/groovy-eclipse/releases). [compatible versions](https://github.com/diffplug/spotless/tree/main/lib-extra/src/main/resources/com/diffplug/spotless/extra/groovy_eclipse_formatter). The Groovy formatter uses some of the [eclipse jdt](#eclipse-jdt) configuration parameters in addition to groovy-specific ones. All parameters can be configured within a single file, like the Java properties file [greclipse.properties](../testlib/src/main/resources/groovy/greclipse/format/greclipse.properties) in the previous example. The formatter step can also load the [exported Eclipse properties](../ECLIPSE_SCREENSHOTS.md) and augment it with the `.metadata/.plugins/org.eclipse.core.runtime/.settings/org.codehaus.groovy.eclipse.ui.prefs` from your Eclipse workspace as shown below. ```gradle spotless { @@ -210,193 +224,251 @@ spotless { // Use the default version and Groovy-Eclipse default configuration greclipse() // optional: you can specify a specific version or config file(s) - // available versions: https://github.com/diffplug/spotless/tree/main/lib-extra/src/main/resources/com/diffplug/spotless/extra/groovy_eclipse_formatter + // compatible versions: https://github.com/diffplug/spotless/tree/main/lib-extra/src/main/resources/com/diffplug/spotless/extra/groovy_eclipse_formatter greclipse('2.3.0').configFile('spotless.eclipseformat.xml', 'org.codehaus.groovy.eclipse.ui.prefs') +``` + +Groovy-Eclipse formatting errors/warnings lead per default to a build failure. This behavior can be changed by adding the property/key value `ignoreFormatterProblems=true` to a configuration file. In this scenario, files causing problems, will not be modified by this formatter step. + +## Kotlin + +- `com.diffplug.gradle.spotless.KotlinExtension` [javadoc](https://javadoc.io/static/com.diffplug.spotless/spotless-plugin-gradle/4.4.0/com/diffplug/gradle/spotless/KotlinExtension.html), [code](https://github.com/diffplug/spotless/blob/main/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/KotlinExtension.java) +- `com.diffplug.gradle.spotless.KotlinGradleExtension` [javadoc](https://javadoc.io/static/com.diffplug.spotless/spotless-plugin-gradle/4.4.0/com/diffplug/gradle/spotless/KotlinGradleExtension.html), [code](https://github.com/diffplug/spotless/blob/main/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/KotlinGradleExtension.java) + +```kotlin +configure { + kotlin { + // by default the target is every '.kt' and '.kts` file in the java sourcesets + ktlint() // has its own section below + ktfmt() // has its own section below + prettier() // has its own section below + licenseHeader '/* (C)$YEAR */' // or licenseHeaderFile + } + kotlinGradle { + target '*.gradle.kts' // default target for kotlinGradle + ktlint() // or ktfmt() or prettier() } } ``` -Groovy-Eclipse formatting errors/warnings lead per default to a build failure. This behavior can be changed by adding the property/key value `ignoreFormatterProblems=true` to a configuration file. In this scenario, files causing problems, will not be modified by this formatter step. + - +### ktlint -## Applying [FreshMark](https://github.com/diffplug/freshmark) to markdown files +[homepage](https://github.com/pinterest/ktlint). [changelog](https://github.com/pinterest/ktlint/releases). Spotless does not ([yet](https://github.com/diffplug/spotless/issues/142)) respect the `.editorconfig` settings ([ktlint docs](https://github.com/pinterest/ktlint#editorconfig)), but you can provide them manually as `userData`. -Freshmark lets you generate markdown in the comments of your markdown. This helps to keep badges and links up-to-date (see the source for this file), and can -also be helpful for generating complex tables (see the source for [the parent readme](../README.md)). +```kotlin +configure { + kotlin { + // version and userData are both optional + ktlint('0.37.2').userData(mapOf('indent_size' to '2', 'continuation_indent_size' to '2']) +``` -To apply freshmark to all of the `.md` files in your project, with all of your project's properties available for templating, use this snippet: + + +### ktfmt + +[homepage](https://github.com/facebookincubator/ktfmt). [changelog](https://github.com/facebookincubator/ktfmt/releases). + +```kotlin +configure { + kotlin { + ktfmt('0.13') // version is optional +``` + + + +## Scala + +`com.diffplug.gradle.spotless.ScalaExtension` [javadoc](https://javadoc.io/static/com.diffplug.spotless/spotless-plugin-gradle/4.4.0/com/diffplug/gradle/spotless/ScalaExtension.html), [code](https://github.com/diffplug/spotless/blob/main/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/ScalaExtension.java) ```gradle spotless { - freshmark { - target 'README.md', 'CONTRIBUTING.md' // defaults to '**/*.md' - propertiesFile('gradle.properties') // loads all the properties in the given file - properties { - it.put('key', 'value') // specify other properties manually - } + scala { + // by default, all `.scala` and `.sc` files in the java sourcesets will be formatted + + scalafmt() // has its own section below + + licenseHeader '/* (C) $YEAR */', 'package ' // or licenseHeaderFile + // note the 'package ' argument - this is a regex which identifies the top + // of the file, be careful that all of your sources have a package declaration, + // or pick a regex which works better for your code } } ``` - +### scalafmt -## Applying [scalafmt](https://olafurpg.github.io/scalafmt/#Scalafmt-codeformatterforScala) to Scala files +[homepage](https://scalameta.org/scalafmt/). [changelog](https://github.com/scalameta/scalafmt/releases). [config docs](https://scalameta.org/scalafmt/docs/configuration.html). ```gradle spotless { scala { - scalafmt() - // optional: you can specify a specific version or config file - scalafmt('0.5.1').configFile('scalafmt.conf') - } -} + // version and configFile are both optional + scalafmt('2.6.1').configFile('scalafmt.conf') ``` - + + +## C/C++ -## Applying [ktlint](https://github.com/pinterest/ktlint) to Kotlin files +`com.diffplug.gradle.spotless.CppExtension` [javadoc](https://javadoc.io/static/com.diffplug.spotless/spotless-plugin-gradle/4.4.0/com/diffplug/gradle/spotless/CppExtension.html), [code](https://github.com/diffplug/spotless/blob/main/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/CppExtension.java) ```gradle spotless { - kotlin { - // optionally takes a version - ktlint() - // Optional user arguments can be set as such: - ktlint().userData(['indent_size': '2', 'continuation_indent_size' : '2']) - - // also supports license headers - licenseHeader '/* Licensed under Apache-2.0 */' // License header - licenseHeaderFile 'path-to-license-file' // License header file + cpp { + target 'src/native/**' // you have to set the target manually + + eclipseCdt() // has its own section below + + licenseHeader '/* (C) $YEAR */' // or licenseHeaderFile } - kotlinGradle { - // same as kotlin, but for .gradle.kts files (defaults to '*.gradle.kts') - target '*.gradle.kts', 'additionalScripts/*.gradle.kts' +} +``` + + - ktlint() +### eclipse cdt - // Optional user arguments can be set as such: - ktlint().userData(['indent_size': '2', 'continuation_indent_size' : '2']) +[homepage](https://www.eclipse.org/cdt/). [compatible versions](https://github.com/diffplug/spotless/tree/main/lib-extra/src/main/resources/com/diffplug/spotless/extra/eclipse_cdt_formatter). - // doesn't support licenseHeader, because scripts don't have a package statement - // to clearly mark where the license should go +```gradle +spotles { + cpp { + // version and configFile are both optional + eclipseCdt('4.13.0').configFile('eclipse-cdt.xml') } } ``` - + + +## FreshMark + +`com.diffplug.gradle.spotless.FreshMarkExtension` [javadoc](https://javadoc.io/static/com.diffplug.spotless/spotless-plugin-gradle/4.4.0/com/diffplug/gradle/spotless/FreshMarkExtension.html), [code](https://github.com/diffplug/spotless/blob/main/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FreshMarkExtension.java) -## Applying [ktfmt](https://github.com/facebookincubator/ktfmt) to Kotlin files +[homepage](https://github.com/diffplug/freshmark). [changelog](https://github.com/diffplug/freshmark/blob/master/CHANGES.md). FreshMark lets you generate markdown in the comments of your markdown. This helps to keep badges and links up-to-date (see the source for this file), and can +also be helpful for generating complex tables (see the source for [the parent readme](../README.md)). + +To apply freshmark to all of the `.md` files in your project, with all of your project's properties available for templating, use this snippet: ```gradle spotless { - kotlin { - // optionally takes a version - ktfmt() - - // also supports license headers - licenseHeader '/* Licensed under Apache-2.0 */' // License header - licenseHeaderFile 'path-to-license-file' // License header file + freshmark { + target '*.md' // you have to set the target manually + propertiesFile('gradle.properties') // loads all the properties in the given file + properties { + it.put('key', 'value') // specify other properties manually + } } } ``` - +## Antlr4 -## Applying [DBeaver](https://dbeaver.jkiss.org/) to SQL scripts +`com.diffplug.gradle.spotless.Antlr4Extension` [javadoc](https://javadoc.io/static/com.diffplug.spotless/spotless-plugin-gradle/4.4.0/com/diffplug/gradle/spotless/Antlr4Extension.html), [code](https://github.com/diffplug/spotless/blob/main/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/Antlr4Extension.java) ```gradle spotless { - sql { - // default value for target files - target '**/*.sql' - // configFile is optional, arguments available here: https://github.com/diffplug/spotless/blob/main/lib/src/main/java/com/diffplug/spotless/sql/dbeaver/DBeaverSQLFormatterConfiguration.java - dbeaver().configFile('dbeaver.props') + antlr4 { + target 'src/*/antlr4/**/*.g4' // default value, you can change if you want + antlr4Formatter() // has its own section below + licenseHeader '/* (C) $YEAR */' // or licenseHeaderFile } } ``` -Default configuration file: -```properties -# case of the keywords (UPPER, LOWER or ORIGINAL) -sql.formatter.keyword.case=UPPER -# Statement delimiter -sql.formatter.statement.delimiter=; -# Indentation style (space or tab) -sql.formatter.indent.type=space -# Number of identation characters -sql.formatter.indent.size=4 +### antlr4formatter + +[homepage](https://github.com/antlr/Antlr4Formatter). [available versions](https://search.maven.org/artifact/com.khubla.antlr4formatter/antlr4-formatter). + +```gradle +antlr4formatter('1.2.1') // version is optional ``` - + + + +## SQL -## Applying to C/C++ sources +`com.diffplug.gradle.spotless.SqlExtension` [javadoc](https://javadoc.io/static/com.diffplug.spotless/spotless-plugin-gradle/4.4.0/com/diffplug/gradle/spotless/SqlExtension.html), [code](https://github.com/diffplug/spotless/blob/main/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/SqlExtension.java) ```gradle spotless { - cpp { - target '**/*.CPP' // Change file filter. By default files with 'c', 'h', 'C', 'cpp', 'cxx', 'cc', 'c++', 'h', 'hpp', 'hh', 'hxx' and 'inc' extension are supported - eclipse().configFile 'spotless.eclipseformat.xml' // XML file dumped out by the Eclipse formatter - // If you have Eclipse preference or property files, you can use them too. - // eclipse('4.7.1') to specify a specific version of Eclipse, - // available versions are: https://github.com/diffplug/spotless/tree/main/lib-extra/src/main/resources/com/diffplug/spotless/extra/eclipse_cdt_formatter - licenseHeader '// Licensed under Apache' // License header - licenseHeaderFile './license.txt' // License header file + sql { + target 'src/main/resources/**/*.sql' // have to set manually + + dbeaver() // has its own section below + prettier() // has its own section below } } ``` - +### dbeaver + +[homepage](https://dbeaver.io/). DBeaver is only distributed as a monolithic jar, so the formatter used here was copy-pasted into Spotless, and thus there is no version to change. -### Eclipse [CDT](https://www.eclipse.org/cdt/) formatter +```gradle +spotless { + sql { + dbeaver().configFile('dbeaver.props') // configFile is optional +``` -Use the Eclipse to define the *Code Style preferences* (see [Eclipse documentation](https://www.eclipse.org/documentation/)). Within the preferences *Edit...* dialog, you can export your configuration as XML file, which can be used as a `configFile`. If no `configFile` is provided, the CDT default configuration is used. +Default configuration file, other options [available here](https://github.com/diffplug/spotless/blob/main/lib/src/main/java/com/diffplug/spotless/sql/dbeaver/DBeaverSQLFormatterConfiguration.java). - +```properties +# case of the keywords (UPPER, LOWER or ORIGINAL) +sql.formatter.keyword.case=UPPER +# Statement delimiter +sql.formatter.statement.delimiter=; +# Indentation style (space or tab) +sql.formatter.indent.type=space +# Number of identation characters +sql.formatter.indent.size=4 +``` -## Applying to Typescript source + -To use tsfmt, you first have to specify the files that you want it to apply to. -Then you specify `tsfmt()`, and optionally how you want to apply it. +## Typescript -By default, all typescript source sets will be formatted. To change this, -set the `target` parameter as described in the [Custom rules](#custom) section. +- `com.diffplug.gradle.spotless.TypescriptExtension` [javadoc](https://javadoc.io/static/com.diffplug.spotless/spotless-plugin-gradle/4.4.0/com/diffplug/gradle/spotless/TypescriptExtension.html), [code](https://github.com/diffplug/spotless/blob/main/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/TypescriptExtension.java) ```gradle spotless { typescript { - // using existing config files - tsfmt().tslintFile('/path/to/repo/tslint.json') - // tsfmt('7.2.2') to specify specific version of tsfmt - // tsfmt(['typescript-formatter': '7.2.2', 'typescript': '3.3.3', 'tslint': '5.12.1') to specify all of the npm dependencies that you want + target 'src/**/*.ts' // you have to set the target manually + + tsfmt() // has its own section below + prettier() // has its own section below + + licenseHeader '/* (C) $YEAR */', '(import|const|declare|export|var) ' // or licenseHeaderFile + // note the '(import|const|...' argument - this is a regex which identifies the top + // of the file, be careful that all of your sources have a suitable top-level declaration, + // or pick a regex which works better for your code } } ``` -Supported config file types are `tsconfigFile`, `tslintFile`, `vscodeFile` and `tsfmtFile`. They are corresponding to the respective -[tsfmt-parameters](https://github.com/vvakame/typescript-formatter/blob/7764258ad42ac65071399840d1b8701868510ca7/lib/index.ts#L27L34). -*Please note:* -The auto-discovery of config files (up the file tree) will not work when using tsfmt within spotless, - hence you are required to provide resolvable file paths for config files. +### tsfmt -... or alternatively provide the configuration inline ... +[npm](https://www.npmjs.com/package/typescript-formatter). [changelog](https://github.com/vvakame/typescript-formatter/blob/master/CHANGELOG.md). *Please note:* +The auto-discovery of config files (up the file tree) will not work when using tsfmt within spotless, + hence you are required to provide resolvable file paths for config files, or alternatively provide the configuration inline. See [tsfmt's default config settings](https://github.com/vvakame/typescript-formatter/blob/7764258ad42ac65071399840d1b8701868510ca7/lib/utils.ts#L11L32) for what is available. ```gradle spotless { typescript { - // custom file-set - target 'src/main/resources/**/*.ts' - // provide config inline - tsfmt().config(['indentSize': 1, 'convertTabsToSpaces': true]) - } -} + tsfmt('7.2.2') + // provide config inline: https://github.com/vvakame/typescript-formatter/blob/7764258ad42ac65071399840d1b8701868510ca7/lib/utils.ts#L11L32 + .config(['indentSize': 1, 'convertTabsToSpaces': true]) + // or according to tsfmt-parameters: https://github.com/vvakame/typescript-formatter/blob/7764258ad42ac65071399840d1b8701868510ca7/lib/index.ts#L27L34 + .tsconfigFile('tsconfig.json') + .tslintFile('tslint.json') + .vscodeFile('vscode.json') + .tsfmtFile('tsfmt.json') ``` -See [tsfmt's default config settings](https://github.com/vvakame/typescript-formatter/blob/7764258ad42ac65071399840d1b8701868510ca7/lib/utils.ts#L11L32) for what is available. - -... and it is also possible to apply `prettier()` instead of `tsfmt()` as formatter. For details see the section about [prettier](#typescript-prettier). - -### Prerequisite: tsfmt requires a working NodeJS version +**Prerequisite: tsfmt requires a working NodeJS version** tsfmt is based on NodeJS, so to use it, a working NodeJS installation (especially npm) is required on the host running spotless. Spotless will try to auto-discover an npm installation. If that is not working for you, it is possible to directly configure the npm binary to use. @@ -405,89 +477,55 @@ Spotless will try to auto-discover an npm installation. If that is not working f spotless { typescript { tsfmt().npmExecutable('/usr/bin/npm').config(...) - } -} ``` -Spotless uses npm to install necessary packages and run the `typescript-formatter` (`tsfmt`) package. + - +## Prettier -## Applying [Prettier](https://prettier.io) to javascript | flow | typeScript | css | scss | less | jsx | graphQL | yaml | etc. +[homepage](https://prettier.io/). [changelog](https://github.com/prettier/prettier/blob/master/CHANGELOG.md). [official plugins](https://prettier.io/docs/en/plugins.html#official-plugins). [community plugins](https://prettier.io/docs/en/plugins.html#community-plugins). Prettier is a formatter that can format almost every anything - JavaScript, JSX, Angular, Vue, Flow, TypeScript, CSS, Less, SCSS, HTML, JSON, GraphQL, Markdown (including GFM and MDX), and YAML. It can format even more [using plugins](https://prettier.io/docs/en/plugins.html) (PHP, Ruby, Swift, XML, Apex, Elm, Java (!!), Kotlin, pgSQL, .properties, solidity, svelte, toml, shellscript, ...). -Prettier is a formatter that can format [multiple file types](https://prettier.io/docs/en/language-support.html). - -To use prettier, you first have to specify the files that you want it to apply to. Then you specify prettier, and how you want to apply it. +You can use prettier in any language-specific format, but usually you will be creating a generic format. ```gradle spotless { format 'styling', { - target 'src/*/webapp/**/*.css', 'src/*/webapp/**/*.scss', 'app/**/*.css', 'app/**/*.scss' - - // at least provide the parser to use - prettier().config(['parser': 'css']) - // prettier('1.16.4') to specify specific version of prettier - // prettier(['my-prettier-fork': '1.16.4']) to specify exactly which npm packages to use + // you have to set the target manually + target 'src/*/webapp/**/*.css', 'src/*/webapp/**/*.scss' - // or provide a typical filename - prettier().config(['filepath': 'style.scss']) - } -} -``` + prettier('2.0.4') // version is optional + prettier(['my-prettier-fork': '1.16.4']) // can specify exactly which npm packages to use -Supported config options are documented on [prettier.io](https://prettier.io/docs/en/options.html). + // by default, prettier uses the file's extension to guess a parser + // but you can override that and specify the parser manually + prettier().config(['parser': 'css']) -It is also possible to specify the config via file: + // you can also set some style options + // https://prettier.io/docs/en/configuration.html + prettier().config(['tabWidth: 4']) -```gradle -spotless { - format 'styling', { - target 'src/*/webapp/**/*.css', 'src/*/webapp/**/*.scss', 'app/**/*.css', 'app/**/*.scss' - prettier().configFile('/path-to/.prettierrc.yml') - // or provide both (config options take precedence over configFile options) - prettier().config(['parser': 'css']).configFile('path-to/.prettierrc.yml') + // you can also slurp from a file or even provide both (inline always takes precedence over file) + prettier().config(['tabWidth: 4']).configFile('path-to/.prettierrc.yml') } } ``` -Supported config file variants are documented on [prettier.io](https://prettier.io/docs/en/configuration.html). -*Please note:* +**Limitations:** - The auto-discovery of config files (up the file tree) will not work when using prettier within spotless. - Prettier's override syntax is not supported when using prettier within spotless. To apply prettier to more kinds of files, just add more formats -```gradle -spotless { - format 'javascript', { - target 'src/main/resources/**/*.js' - prettier().config(['filepath': 'file.js']) - } -} -``` - -Or you might even let prettier detect the file type and choose the parser on its own such as: - -```gradle -spotless { - format 'webResources', { - target 'src/*/webapp/**', 'app/**' - prettier() - } -} -``` - + - -### Using plugins for prettier +### prettier plugins Since spotless uses the actual npm prettier package behind the scenes, it is possible to use prettier with [plugins](https://prettier.io/docs/en/plugins.html#official-plugins) or [community-plugins](https://www.npmjs.com/search?q=prettier-plugin) in order to support even more file types. ```gradle spotless { - format 'prettierJava', { - target 'src/*/java/**/*.java' + java { prettier(['prettier': '2.0.5', 'prettier-plugin-java': '0.8.0']).config(['parser': 'java', 'tabWidth': 4]) } format 'php', { @@ -497,50 +535,31 @@ spotless { } ``` - -### Note: Prettier can also be applied from within the [typescript config block](#typescript-formatter) +### npm detection -```gradle -spotless { - typescript { - // no parser or filepath needed - // -> will default to 'typescript' parser when used in the typescript block - prettier() - } -} -``` - -### Prerequisite: prettier requires a working NodeJS version - -Prettier, like tsfmt, is based on NodeJS, so to use it, a working NodeJS installation (especially npm) is required on the host running spotless. +Prettier is based on NodeJS, so a working NodeJS installation (especially npm) is required on the host running spotless. Spotless will try to auto-discover an npm installation. If that is not working for you, it is possible to directly configure the npm binary to use. ```gradle spotless { format 'javascript', { prettier().npmExecutable('/usr/bin/npm').config(...) - } -} ``` -Spotless uses npm to install necessary packages and run the `prettier` (`tsfmt`) package. + - +## Eclipse web tools platform -## Applying [Eclipse WTP](https://www.eclipse.org/webtools/) to css | html | etc. - -The Eclipse [WTP](https://www.eclipse.org/webtools/) formatter can be applied as follows: +[changelog](https://www.eclipse.org/webtools/). [compatible versions](https://github.com/diffplug/spotless/tree/main/lib-extra/src/main/resources/com/diffplug/spotless/extra/eclipse_wtp_formatters). ```gradle spotless { format 'xml', { - target fileTree('.') { - include '**/*.xml', '**/*.xsd' - exclude '**/build/**' - } - // Use for example eclipseWtp('xml', '4.7.3a') to specify a specific version of Eclipse, - // available versions are: https://github.com/diffplug/spotless/tree/main/lib-extra/src/main/resources/com/diffplug/spotless/extra/eclipse_wtp_formatters - eclipseWtp('xml').configFile 'spotless.xml.prefs', 'spotless.common.properties' + target 'src/**/*/xml' // must specify target + eclipseWtp('xml') // must specify a type (table below) + eclipseWtp('xml', '4.7.3a') // optional version + // you can also specify an arbitrary number of config files + eclipseWtp('xml').configFile('spotless.xml.prefs', 'spotless.common.properties' } } ``` @@ -568,9 +587,9 @@ Unlike Eclipse, Spotless WTP ignores per default external URIs in schema locatio external entities. To allow the access of external URIs, set the property `resolveExternalURI` to true. - + -## License header options +## License header If the license header (specified with `licenseHeader` or `licenseHeaderFile`) contains `$YEAR` or `$today.year`, then that token will be replaced with the current 4-digit year. For example, if Spotless is launched in 2020, then `/* Licensed under Apache-2.0 $YEAR. */` will produce `/* Licensed under Apache-2.0 2020. */` @@ -582,61 +601,28 @@ Once a file's license header has a valid year, whether it is a year (`2020`) or See the [javadoc](https://javadoc.io/static/com.diffplug.spotless/spotless-plugin-gradle/4.4.0/com/diffplug/gradle/spotless/FormatExtension.LicenseHeaderConfig.html) for a complete listing of options. -### Retroactively populating year range from git history + + +### Retroactively slurp years from git history If your project has not been rigorous with copyright headers, and you'd like to use git history to repair this retroactively, you can do so with `-PspotlessSetLicenseHeaderYearsFromGitHistory=true`. When run in this mode, Spotless will do an expensive search through git history for each file, and set the copyright header based on the oldest and youngest commits for that file. This is intended to be a one-off sort of thing. - + -## Custom rules +## How can I enforce formatting gradually? (aka "ratchet") -Spotless is a generic system for specifying a sequence of steps which are applied to a set of files. +If your project is not currently enforcing formatting, then it can be a noisy transition. Having a giant commit where every single file gets changed makes the history harder to read. To address this, you can use the `ratchet` feature: ```gradle spotless { - // this will create two tasks: spotlessMiscCheck and spotlessMiscApply - format 'misc', { - // target determines which files this format will apply to - // - if you pass a string or a list of strings, they will be treated - // as 'include' parameters to a fileTree in the root directory - // - if you pass a FileCollection, it will pass through untouched - // e.g. project.files('build.gradle', 'settings.gradle') - // - if you pass anything else, it will be sent to project.files(yourArg) - target '**/*.gradle', '**/*.md', '**/.gitignore' - - targetExclude 'src/main/codegen/**', 'src/test/codegen/**' - // the files to be formatted = (target - targetExclude) - // NOTE: if target or targetExclude is called multiple times, only the - // last call is effective - - // spotless has built-in rules for the most basic formatting tasks - trimTrailingWhitespace() - indentWithTabs() // or spaces. Takes an integer argument if you don't like 4 - endWithNewline() - - // you can also call out to your own function - custom 'superFormatter', { - // when writing a custom step, it will be helpful to know - // how the formatting process works, which is as follows: - - // 1) Load each target file, and convert it to unix-style line endings ('\n') - // 2) Pass its content through a series of steps, feeding the output of each step to the next - // 3) Put the correct line endings back on, then either check or apply - - // each step receives a string as input, and should output - // a formatted string as output. Each step can trust that its - // input will have unix newlines, and it must promise to output - // only unix newlines. Other than that, anything is fair game! - } - } -} + ratchetFrom 'origin/main' // only format files which have changed since origin/main ``` -If you use `custom` or `customLazy`, you might want to take a look at [this javadoc](https://javadoc.io/static/com.diffplug.spotless/spotless-plugin-gradle/4.4.0/com/diffplug/gradle/spotless/FormatExtension.html#bumpThisNumberIfACustomStepChanges-int-) for a big performance win. +In this mode, Spotless will apply only to files which have changed since `origin/main`. You can ratchet from [any point you want](https://javadoc.io/static/org.eclipse.jgit/org.eclipse.jgit/5.6.1.202002131546-r/org/eclipse/jgit/lib/Repository.html#resolve-java.lang.String-), even `HEAD`. You can also set `ratchetFrom` per-format if you prefer (e.g. `spotless { java { ratchetFrom ...`). -See [`JavaExtension.java`](src/main/java/com/diffplug/gradle/spotless/JavaExtension.java) if you'd like to see how a language-specific set of custom rules is implemented. We'd love PR's which add support for other languages. +However, we strongly recommend that you use a non-local branch, such as a tag or `origin/main`. The problem with `HEAD` or any local branch is that as soon as you commit a file, that is now the canonical formatting, even if it was formatted incorrectly. By instead specifying `origin/main` or a tag, your CI server will fail unless every changed file is at least as good or better than it was before the change. -If you'd like to create a one-off Spotless task outside of the `check`/`apply` framework, see [`FormatExtension.createIndependentTask`](https://github.com/diffplug/spotless/blob/91ed7203994e52058ea6c2e0f88d023ed290e433/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java#L613-L639). +This is especially helpful for injecting accurate copyright dates using the [license step](#license-header). @@ -646,18 +632,72 @@ Spotless uses UTF-8 by default, but you can use [any encoding which Java support ```gradle spotless { + encoding 'UTF-8' // all formats will be interpreted as UTF-8 java { - ... - encoding 'Cp1252' // java will have Cp1252 - } - encoding 'US-ASCII' // but all other formats will be interpreted as US-ASCII -} + encoding 'Cp1252' // except java, which will be Cp1252 ``` Line endings can also be set globally or per-format using the `lineEndings` property. Spotless supports four line ending modes: `UNIX`, `WINDOWS`, `PLATFORM_NATIVE`, and `GIT_ATTRIBUTES`. The default value is `GIT_ATTRIBUTES`, and *we highly recommend that you* ***do not change*** *this value*. Git has opinions about line endings, and if Spotless and git disagree, then you're going to have a bad time. You can easily set the line endings of different files using [a `.gitattributes` file](https://help.github.com/articles/dealing-with-line-endings/). Here's an example `.gitattributes` which sets all files to unix newlines: `* text eol=lf`. + + + +## Custom steps + +As described in the [quickstart](#quickstart), Spotless is just a set of files ("target"), passed through a list of `String -> String` functions. The string each function gets will always have unix `\n` endings, and Spotless doesn't care which endings the function provides back, it will renormalize regardless. You can easily make a new step directly in your buildscript, like so: + +```gradle +spotless { + format 'misc', { + custom 'lowercase', { str -> str.toLowerCase() } +``` + +However, custom rules will disable up-to-date checking and caching, unless you read [this javadoc](https://javadoc.io/static/com.diffplug.spotless/spotless-plugin-gradle/4.4.0/com/diffplug/gradle/spotless/FormatExtension.html#bumpThisNumberIfACustomStepChanges-int-) and follow its instructions carefully. + +Another option is to create proper `FormatterStep` in your `buildSrc`, and then call [`addStep`](https://javadoc.io/static/com.diffplug.spotless/spotless-plugin-gradle/4.4.0/com/diffplug/gradle/spotless/FormatExtension.html#addStep-com.diffplug.spotless.FormatterStep-). The contributing guide describes [how to do this](https://github.com/diffplug/spotless/blob/main/CONTRIBUTING.md#how-to-add-a-new-formatterstep). If the step is generally-useful, we hope you'll open a PR to share it! + + +```gradle +spotless { + format 'misc', { + addStep(MyFormatterStep.create()) +``` + +### Throwing errors + +Ideally, your formatter will be able to silently fix any problems that it finds, that's the beauty of the `String -> String` model. But sometimes that's not possible. If you throw + +- `AssertionError` or a subclass -> Spotless reports as a problem in the file being formatted +- anything else -> Spotless reports as a bug in the formatter itself + +## Multiple (or custom) language-specific blocks + +The following two lines are exact synonyms: + +```gradle +spotless { format 'java', com.diffplug.gradle.spotless.JavaExtension, { ... } } +spotless { java { ... } } +``` + +So if you want to have two different `java` blocks, you can do something like this: + +```gradle +spotless { java { ... } } +spotless { format 'javaFoo', com.diffplug.gradle.spotless.JavaExtension, { ... } } +// has to be 'javaFoo' not 'java' because each format needs a unique name +``` + +As a follow-on, you can make your own subclass to `FormatExtension` in the `buildSrc` directory, and then use it in your buildscript like so: + +```gradle +spotless { + format 'foo', com.acme.FooLanguageExtension, { +``` + +If you'd like to create a one-off Spotless task outside of the `check`/`apply` framework, see [`FormatExtension.createIndependentApplyTask`](https://javadoc.io/static/com.diffplug.spotless/spotless-plugin-gradle/4.4.0/com/diffplug/gradle/spotless/FormatExtension.html#createIndependentApplyTask-java.lang.String-). + ## Disabling warnings and error messages @@ -677,18 +717,15 @@ When a misformatted file throws an exception, it will be for one of two reasons: 1) Spotless calculated the properly formatted version, and it is different than the current contents. 2) One of the formatters threw an exception while attempting to calculate the properly formatted version. -You can fix (1) by excluding the file from formatting using the `targetExclude` method, see the [custom rules](#custom) section for details. You can fix (2) and turn these exceptions into warnings like this: +You can fix (1) by excluding the file from formatting using the `targetExclude` method, see the [quickstart](#quickstart) section for details. You can fix (2) and turn these exceptions into warnings like this: ```gradle spotless { java { - googleJavaFormat() - custom 'my-glitchy-step', { } + custom 'my-glitchy-step', { ... } ignoreErrorForStep('my-glitchy-step') // ignore errors on all files thrown by a specific step ignoreErrorForPath('path/to/file.java') // ignore errors by all steps on this specific file - } -} ``` @@ -701,44 +738,11 @@ spotless { - If you don't like what spotless did, `git reset --hard` - If you'd like to remove the "checkpoint" commit, `git reset --soft head~1` will make the checkpoint commit "disappear" from history, but keeps the changes in your working directory. - - -## How can I enforce formatting gradually? - -If your project is not currently enforcing formatting, then it can be a noisy transition. Having a giant commit where every single file gets changed makes the history harder to read. To address this, you can use the `ratchet` feature: - -```gradle -spotless { - ratchetFrom 'origin/main' // only format files which have changed since origin/main - ... -} -``` - -In this mode, Spotless will apply only to files which have changed since `origin/main`. You can ratchet from [any point you want](https://javadoc.io/static/org.eclipse.jgit/org.eclipse.jgit/5.6.1.202002131546-r/org/eclipse/jgit/lib/Repository.html#resolve-java.lang.String-), even `HEAD`. You can also set `ratchetFrom` per-format if you prefer (e.g. `spotless { java { ratchetFrom ...`). - -However, we strongly recommend that you use a non-local branch, such as a tag or `origin/main`. The problem with `HEAD` or any local branch is that as soon as you commit a file, that is now the canonical formatting, even if it was formatted incorrectly. By instead specifying `origin/main` or a tag, your CI server will fail unless every changed file is at least as good or better than it was before the change. - -This is especially helpful for injecting accurate copyright dates using the [license step](#license-header). - -## Can I apply Spotless to specific files? - -**DEPRECATED: use [`ratchetFrom`]($ratchet) instead. The regex API below is difficult to use correctly, especially for cross-platform (win/unix) builds.** - -You can target specific files by setting the `spotlessFiles` project property to a comma-separated list of file patterns: - -``` -cmd> gradlew spotlessApply -PspotlessFiles=my/file/pattern.java,more/generic/.*-pattern.java -``` - -The patterns are matched using `String#matches(String)` against the absolute file path. - ## Example configurations (from real-world projects) -Spotless is hosted on jcenter and at plugins.gradle.org. [Go here](https://plugins.gradle.org/plugin/com.diffplug.gradle.spotless) if you're not sure how to import the plugin. - -* [One thousand github projects](https://github.com/search?l=gradle&q=spotless&type=Code) +* [A few thousand github projects](https://github.com/search?l=gradle&q=spotless&type=Code) * [JUnit 5](https://github.com/junit-team/junit-lambda/blob/151d52ffab07881de71a8396a9620f18072c65ec/build.gradle#L86-L101) (aka JUnit Lambda) * [Apache Beam](https://beam.apache.org/) ([direct link to spotless section in its build.gradle](https://github.com/apache/beam/blob/1d9daf1aca101fa5a194cbbba969886734e08902/buildSrc/src/main/groovy/org/apache/beam/gradle/BeamModulePlugin.groovy#L776-L789)) * [opentest4j](https://github.com/ota4j-team/opentest4j/blob/aab8c204be05609e9f76c2c964c3d6845cd0de14/build.gradle#L63-L80) diff --git a/plugin-maven/README.md b/plugin-maven/README.md index d27620abf3..e74c5d92d8 100644 --- a/plugin-maven/README.md +++ b/plugin-maven/README.md @@ -28,30 +28,47 @@ Spotless is a general-purpose formatting plugin. It is completely à la carte, To people who use your build, it looks like this: -``` -cmd> mvn spotless:check -... -[ERROR] ... The following files had format violations: +```console +user@machine repo % mvn spotless:check +[ERROR] > The following files had format violations: [ERROR] src\main\java\com\diffplug\gradle\spotless\FormatExtension.java -[ERROR] @@ -109,7 +109,7 @@ -[ERROR] ... [ERROR] -\t\t····if·(targets.length·==·0)·{ [ERROR] +\t\tif·(targets.length·==·0)·{ -[ERROR] ... [ERROR] Run 'mvn spotless:apply' to fix these violations. -... - -cmd> mvn spotless:apply -... +user@machine repo % mvn spotless:apply [INFO] BUILD SUCCESS -... - -cmd> mvn spotless:check -... +user@machine repo % mvn spotless:check [INFO] BUILD SUCCESS -... ``` +### Table of Contents + +- [**Quickstart**](#quickstart) + - [Requirements](#requirements) +- **Languages** + - [Java](#java) ([google-java-format](#google-java-format), [eclipse jdt](#eclipse-jdt), [prettier](#prettier)) + - [Kotlin](#kotlin) ([ktlint](#ktlint), [ktfmt](#ktfmt), [prettier](#prettier)) + - [Scala](#scala) ([scalafmt](#scalafmt)) + - [C/C++](#c-c++) ([eclipse cdt](#eclipse-cdt)) + - [Antlr4](#antlr4) ([antlr4formatter](#antlr4formatter)) + - [Typescript](#typescript) ([tsfmt](#tsfmt), [prettier](#prettier)) + - Multiple languages + - [Prettier](#prettier) ([plugins](#prettier-plugins), [npm detection](#npm-detection)) + - [eclipse web tools platform](#eclipse-web-tools-platform) +- **Language independent** + - [Generic steps](#generic-steps) + - [License header](#license-header) ([slurp year from git](#retroactively-slurp-years-from-git-history)) + - [How can I enforce formatting gradually? (aka "ratchet")](#ratchet) + - [Line endings and encodings (invisible stuff)](#line-endings-and-encodings-invisible-stuff) + - [Disabling warnings and error messages](#disabling-warnings-and-error-messages) + - [How do I preview what `spotlessApply` will do?](#how-do-i-preview-what-spotlessapply-will-do) + - [Can I apply Spotless to specific files?](#can-i-apply-spotless-to-specific-files) + - [Example configurations (from real-world projects)](#examples) + +***Contributions are welcome, see [the contributing guide](../CONTRIBUTING.md) for development info.*** + +## Quickstart + To use it in your pom, just [add the Spotless dependency](https://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22com.diffplug.spotless%22%20AND%20a%3A%22spotless-maven-plugin%22), and configure it like so: ```xml @@ -60,227 +77,353 @@ To use it in your pom, just [add the Spotless dependency](https://search.maven.o spotless-maven-plugin ${spotless.version} + + origin/main + + + + + + *.md + .gitignore + + + + + + true + 4 + + + + - - ${basedir}/eclipse-fmt.xml - 4.7.1 - + + + + + 1.8 + + + + + + /* (C)$YEAR */ + ``` -Spotless supports the following powerful formatters: +Spotless consists of a list of formats (in the example above, `misc` and `java`), and each format has: +- a `target` (the files to format), which you set with [`includes` and `excludes`](https://github.com/diffplug/spotless/blob/989abbecff4d8373c6111c1a98f359eadc532429/plugin-maven/src/main/java/com/diffplug/spotless/maven/FormatterFactory.java#L51-L55) +- a list of `FormatterStep`, which are just `String -> String` functions, such as [`replace`](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/generic/Replace.java), [`replaceRegex`](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/generic/ReplaceRegex.java), [`trimTrailingWhitespace`](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/generic/TrimTrailingWhitespace.java), [`indent`](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/generic/Indent.java), [`prettier`](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/generic/Prettier.java), [`eclipseWtp`](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/generic/EclipseWtp.java), and [`licenseHeader`](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/generic/LicenseHeader.java). -* Eclipse's java code formatter (including style and import ordering) -* Eclipse's [CDT](https://www.eclipse.org/cdt/) C/C++ code formatter -* Eclipse's [WTP](https://www.eclipse.org/webtools/) Web-Tools code formatters -* Google's [google-java-format](https://github.com/google/google-java-format) -* [Typescript Tsfmt formatter](https://github.com/vvakame/typescript-formatter) -* [Prettier formatter](https://prettier.io) -* User-defined license enforcement, regex replacement, etc. -Contributions are welcome, see [the contributing guide](../CONTRIBUTING.md) for development info. +### Requirements Spotless requires Maven to be running on JRE 8+. - + -## Applying to Java source +## Java -By default, all files matching `src/main/java/**/*.java` and `src/test/java/**/*.java` Ant style pattern will be formatted. Each element under `` is a step, and they will be applied in the order specified. Every step is optional, and they will be applied in the order specified. It doesn't make sense to use both eclipse and google-java-format. +[code](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/Java.java). [available steps](https://github.com/diffplug/spotless/tree/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/java). ```xml - - - /* Licensed under Apache-2.0 */ - ${basedir}/license-header - - - - ${basedir}/eclipse-format.xml - - 4.7.1 - - - - 1.5 - - - - - - - java,javax,org,com,com.diffplug, - ${basedir}/eclipse.importorder - + + + src/main/java/**/*.java + src/test/java/**/*.java + + + + + java,javax,org,com,com.diffplug, + + + + + + + + + + + /* (C)$YEAR */ + ``` -See [ECLIPSE_SCREENSHOTS](../ECLIPSE_SCREENSHOTS.md) for screenshots that demonstrate how to get and install the Eclipse format configuration file and Eclipse import order file mentioned above. +### google-java-format - +[homepage](https://github.com/google/google-java-format). [changelog](https://github.com/google/google-java-format/releases). [code](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/GoogleJavaFormat.java). + +```xml + + 1.7 + + +``` -## Applying to Scala source +### eclipse jdt -By default, all files matching `src/main/scala/**/*.scala`, `src/test/scala/**/*.scala`, `src/main/scala/**/*.sc` and `src/test/scala/**/*.sc` Ant style pattern will be formatted. Each element under `` is a step, and they will be applied in the order specified. Every step is optional. +[homepage](https://www.eclipse.org/downloads/packages/). [compatible versions](https://github.com/diffplug/spotless/tree/main/lib-extra/src/main/resources/com/diffplug/spotless/extra/eclipse_jdt_formatter). [code](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/Eclipse.java). See [here](../ECLIPSE_SCREENSHOTS.md) for screenshots that demonstrate how to get and install the config file mentioned below. ```xml - - - - - /* Licensed under Apache-2.0 */ - ${basedir}/license-header - - - - - ${basedir}/scalafmt.conf - - 1.1.0 - - - + + 4.13.0 + ${basedir}/eclipse-formatter.xml + ``` - + -## Applying to Kotlin source +## Kotlin -By default, all files matching `src/main/kotlin/**/*.kt` and `src/test/kotlin/**/*.kt` Ant style pattern will be formatted. Each element under `` is a step, and they will be applied in the order specified. Every step is optional. - -### Applying [ktlint](https://github.com/pinterest/ktlint) to Kotlin files +[code](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/kotlin/Kotlin.java). [available steps](https://github.com/diffplug/spotless/tree/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/kotlin). ```xml - - - /* Licensed under Apache-2.0 */ - ${basedir}/license-header - - - - - - 0.14.0 - + + + src/main/kotlin/**/*.kt + src/test/kotlin/**/*.kt + + + + + java,javax,org,com,com.diffplug, + + + + + + + + + + + /* (C)$YEAR */ + ``` -### Applying [ktfmt](https://github.com/facebookincubator/ktfmt) to Kotlin files + + +### ktlint + +[homepage](https://github.com/pinterest/ktlint). [changelog](https://github.com/pinterest/ktlint/releases). [code](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/kotlin/Ktlint.java). Spotless does not ([yet](https://github.com/diffplug/spotless/issues/142)) respect the `.editorconfig` settings. + +```xml + + 0.37.2 + +``` + + + +### ktfmt + +[homepage](https://github.com/facebookincubator/ktfmt). [changelog](https://github.com/facebookincubator/ktfmt/releases). [code](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/kotlin/Ktfmt.java). + +```xml + + 0.13 + +``` + + + +## Scala + +[code](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/scala/Scala.java). [available steps](https://github.com/diffplug/spotless/tree/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/scala). ```xml - - - - /* Licensed under Apache-2.0 */ - ${basedir}/license-header - - - - - - 0.11 - - + + + + src/main/scala/**/*.scala + src/test/scala/**/*.scala + src/main/scala/**/*.sc + src/test/scala/**/*.sc + + + + + + /* (C)$YEAR */ + package + + ``` +### scalafmt + +[homepage](https://scalameta.org/scalafmt/). [changelog](https://github.com/scalameta/scalafmt/releases). [config docs](https://scalameta.org/scalafmt/docs/configuration.html). [code](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/scala/Scalafmt.java). + +```xml + + 2.0.1 + ${basedir}/scalafmt.conf + +``` + -## Applying to C/C++ source + -By default, all files matching `src/main/cpp/**/*.` and `src/test/cpp/**/*.` Ant style pattern will be formatted, whereas the file extensions `c`, `h`, `C`, `cpp`, `cxx`, `cc`, `c++`, `h`, `hpp`, `hh`, `hxx` and `inc` are supported. Each element under `` is a step, and they will be applied in the order specified. Every step is optional, and they will be applied in the order specified. +## C/C++ + +[code](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/cpp/Cpp.java). [available steps](https://github.com/diffplug/spotless/tree/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/cpp). ```xml - - - /* Licensed under Apache-2.0 */ - ${basedir}/license-header - - - ${basedir}/eclipse-fmt.xml - - 4.7.3a - + + + src/native/** + + + + + + /* (C)$YEAR */ + ``` -Use the Eclipse to define the *Code Style preferences* (see [Eclipse documentation](https://www.eclipse.org/documentation/)). Within the preferences *Edit...* dialog, you can export your configuration as XML file, which can be used as a configuration ``. If no `` is provided, the CDT default configuration is used. - +### eclipse cdt + +[homepage](https://www.eclipse.org/cdt/). [compatible versions](https://github.com/diffplug/spotless/tree/main/lib-extra/src/main/resources/com/diffplug/spotless/extra/eclipse_cdt_formatter). [code](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/cpp/EclipseCdt.java). + +```xml + + 4.13.0 + ${basedir}/eclipse-cdt.xml + +``` + +## Antlr4 -## Applying to Typescript source +[code](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/antlr4/Antlr4.java). [available steps](https://github.com/diffplug/spotless/tree/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/antlr4). ```xml - + + + + src/*/antlr4/**/*.g4 + + + + + + /* (C)$YEAR */ + + + +``` + +### antlr4formatter + +[homepage](https://github.com/antlr/Antlr4Formatter). [available versions](https://search.maven.org/artifact/com.khubla.antlr4formatter/antlr4-formatter). [code](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/antlr4/Antlr4Formatter.java). + +```xml + + 1.2.1 + +``` + + + +## Typescript - - - src/**/*.ts - - - - - ${basedir}/path/to/repo/tslint.json - ${basedir}/path/to/repo/tsfmt.json - ${basedir}/path/to/repo/tsconfig.json - ${basedir}/path/to/repo/vscode.json - - 1 - true - - - 7.2.2 - 3.3.3 - 5.12.1 - +[code](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/typescript/Typescript.java). [available steps](https://github.com/diffplug/spotless/tree/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/typescript). + +```xml + + + + + src/**/*.ts + + + + + + + /* (C)$YEAR */ + (import|const|declare|export|var) + ``` -Supported config file types are `tsconfigFile`, `tslintFile`, `vscodeFile` and `tsfmtFile`. They are corresponding to the respective -[tsfmt-parameters](https://github.com/vvakame/typescript-formatter/blob/7764258ad42ac65071399840d1b8701868510ca7/lib/index.ts#L27L34). See [tsfmt's default config settings](https://github.com/vvakame/typescript-formatter/blob/7764258ad42ac65071399840d1b8701868510ca7/lib/utils.ts#L11L32) for what is available. +### tsfmt -*Please note:* +[npm](https://www.npmjs.com/package/typescript-formatter). [changelog](https://github.com/vvakame/typescript-formatter/blob/master/CHANGELOG.md). [code](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/typescript/Tsfmt.java). *Please note:* The auto-discovery of config files (up the file tree) will not work when using tsfmt within spotless, - hence you are required to provide resolvable file paths for config files. + hence you are required to provide resolvable file paths for config files, or alternatively provide the configuration inline. See [tsfmt's default config settings](https://github.com/vvakame/typescript-formatter/blob/7764258ad42ac65071399840d1b8701868510ca7/lib/utils.ts#L11L32) for what is available. + +```xml + + 7.2.2 + 3.9.5 + 6.1.2 + + + 1 + true + + + ${basedir}/tsconfig.json + ${basedir}/tslint.json + ${basedir}/vscode.json + ${basedir}/tsfmt.json + +``` -### Prerequisite: tsfmt requires a working NodeJS version +**Prerequisite: tsfmt requires a working NodeJS version** tsfmt is based on NodeJS, so to use it, a working NodeJS installation (especially npm) is required on the host running spotless. Spotless will try to auto-discover an npm installation. If that is not working for you, it is possible to directly configure the npm binary to use. ```xml - - ... + /usr/bin/npm + ``` -Spotless uses npm to install necessary packages locally. It runs tsfmt using [J2V8](https://github.com/eclipsesource/J2V8) internally after that. + - +## Prettier -## Applying [Prettier](https://prettier.io) to javascript | flow | typeScript | css | scss | less | jsx | graphQL | yaml | etc. +[homepage](https://prettier.io/). [changelog](https://github.com/prettier/prettier/blob/master/CHANGELOG.md). [official plugins](https://prettier.io/docs/en/plugins.html#official-plugins). [community plugins](https://prettier.io/docs/en/plugins.html#community-plugins). Prettier is a formatter that can format almost every anything - JavaScript, JSX, Angular, Vue, Flow, TypeScript, CSS, Less, SCSS, HTML, JSON, GraphQL, Markdown (including GFM and MDX), and YAML. It can format even more [using plugins](https://prettier.io/docs/en/plugins.html) (PHP, Ruby, Swift, XML, Apex, Elm, Java (!!), Kotlin, pgSQL, .properties, solidity, svelte, toml, shellscript, ...). -Prettier is a formatter that can format [multiple file types](https://prettier.io/docs/en/language-support.html). - -To use prettier, you first have to specify the files that you want it to apply to. Then you specify prettier, and how you want to apply it. +You can use prettier in any language-specific format, but usually you will be creating a generic format. ```xml - src/**/typescript/**/*.ts @@ -302,7 +445,7 @@ To use prettier, you first have to specify the files that you want it to apply t 0.14.2 - + ${basedir}/path/to/configfile true @@ -314,34 +457,22 @@ To use prettier, you first have to specify the files that you want it to apply t ``` -Supported config options are documented on [prettier.io](https://prettier.io/docs/en/options.html). -Supported config file variants are documented on [prettier.io](https://prettier.io/docs/en/configuration.html). - -*Please note:* +**Limitations:** - The auto-discovery of config files (up the file tree) will not work when using prettier within spotless. - Prettier's override syntax is not supported when using prettier within spotless. -To apply prettier to more kinds of files, just add more formats. - - -Or you might even let prettier detect the file type and choose the parser on its own such as: +To apply prettier to more kinds of files, just add more formats ```xml - - - src/*/webapp/** - app/** - - - - - + src/**/*.ts + src/**/*.css ``` - -### Using plugins for prettier + + +### prettier plugins Since spotless uses the actual npm prettier package behind the scenes, it is possible to use prettier with [plugins](https://prettier.io/docs/en/plugins.html#official-plugins) or [community-plugins](https://www.npmjs.com/search?q=prettier-plugin) in order to support even more file types. @@ -396,91 +527,25 @@ Since spotless uses the actual npm prettier package behind the scenes, it is pos ``` -### Prerequisite: prettier requires a working NodeJS version +### npm detection -Prettier, like tsfmt, is based on NodeJS, so to use it, a working NodeJS installation (especially npm) is required on the host running spotless. +Prettier is based on NodeJS, so to use it, a working NodeJS installation (especially npm) is required on the host running spotless. Spotless will try to auto-discover an npm installation. If that is not working for you, it is possible to directly configure the npm binary to use. ```xml - + /usr/bin/npm - ... ``` -Spotless uses npm to install necessary packages and to run the prettier formatter after that. - - + -## Applying to custom sources +## Eclipse web tools platform -By default, no Ant-Style include patterns are defined. Each element under `` is a step, and they will be applied in the order specified. Every step is optional, and they will be applied in the order specified. It is possible to define multiple custom formats. +[changelog](https://www.eclipse.org/webtools/). [compatible versions](https://github.com/diffplug/spotless/tree/main/lib-extra/src/main/resources/com/diffplug/spotless/extra/eclipse_wtp_formatters). ```xml - - - - - - src/**/resources/**/*.properties - - - - - /* Licensed under Apache-2.0 */ - ${basedir}/license-header - - # - - - - - - - - - true - true - - 4 - - - - - - - - Say Hello to Mars - World - Mars - - - - - Say Hello to Mars from Regex - (Hello) W[a-z]{3}d - $1 Mars - - - - - - - -``` - - - - -## Applying [Eclipse WTP](https://www.eclipse.org/webtools/) to css | html | etc. - -The Eclipse [WTP](https://www.eclipse.org/webtools/) formatter can be applied as follows: - -```xml - - - src/**/resources/**/*.xml @@ -488,20 +553,18 @@ The Eclipse [WTP](https://www.eclipse.org/webtools/) formatter can be applied as - - XML - - + XML + ${basedir}/xml.prefs ${basedir}/additional.properties - - 4.7.3a + 4.7.3a ``` + The WTP formatter accept multiple configuration files. All Eclipse configuration file formats are accepted as well as simple Java property files. Omit the `` entirely to use the default Eclipse configuration. The following formatters and configurations are supported: | Type | Configuration | File location @@ -526,22 +589,47 @@ Unlike Eclipse, Spotless WTP ignores per default external URIs in schema locatio external entities. To allow the access of external URIs, set the property `resolveExternalURI` to true. - + + + +## Generic steps + +[Prettier](#prettier), [eclipse wtp](#eclipse-web-tools-platform), and [license header](#license-header) are available in every format, and they each have their own section. As mentioned in the [quickstart](#quickstart), there are a variety of simple generic steps which are also available in every format, here are examples of these: + +```xml + + + + + + true + 4 + + + + Say Hello to Mars + World + Mars + + + + Say Hello to Mars from Regex + (Hello) W[a-z]{3}d + $1 Mars + +``` + + ## License header Spotless can inject a license header into your files, including populating an accurate copyright header from today's date or from git history. ```xml - - - - /* Licensed under Apache-2.0 */ - ${basedir}/license-header - - - # - + + /* (C)$YEAR */ + # + ``` If the license header (specified with `content` or `file`) contains `$YEAR` or `$today.year`, then that token will be replaced with the current 4-digit year. For example, if Spotless is launched in 2020, then `/* Licensed under Apache-2.0 $YEAR. */` will produce `/* Licensed under Apache-2.0 2020. */` @@ -552,12 +640,32 @@ Once a file's license header has a valid year, whether it is a year (`2020`) or * `2017` -> `2017-2020` * `2017-2019` -> `2017-2020` -### Retroactively populating year range from git history +### Retroactively slurp years from git history If your project has not been rigorous with copyright headers, and you'd like to use git history to repair this retroactively, you can do so with `-DspotlessSetLicenseHeaderYearsFromGitHistory=true`. When run in this mode, Spotless will do an expensive search through git history for each file, and set the copyright header based on the oldest and youngest commits for that file. This is intended to be a one-off sort of thing. + + +## How can I enforce formatting gradually? (aka "ratchet") + +If your project is not currently enforcing formatting, then it can be a noisy transition. Having a giant commit where every single file gets changed makes the history harder to read. To address this, you can use the `ratchet` feature: + +```xml + + origin/main + + +``` + +In this mode, Spotless will apply only to files which have changed since `origin/main`. You can ratchet from [any point you want](https://javadoc.io/static/org.eclipse.jgit/org.eclipse.jgit/5.6.1.202002131546-r/org/eclipse/jgit/lib/Repository.html#resolve-java.lang.String-), even `HEAD`. You can also set `ratchetFrom` per-format if you prefer (e.g. `...`). + +However, we strongly recommend that you use a non-local branch, such as a tag or `origin/main`. The problem with `HEAD` or any local branch is that as soon as you commit a file, that is now the canonical formatting, even if it was formatted incorrectly. By instead specifying `origin/main` or a tag, your CI server will fail unless every changed file is at least as good or better than it was before the change. + +This is especially helpful for injecting accurate copyright dates using the [license step](#license-header). + + ## Line endings and encodings (invisible stuff) Spotless uses UTF-8 by default, but you can use [any encoding which Java supports](https://docs.oracle.com/javase/8/docs/technotes/guides/intl/encoding.doc.html). You can set it globally, and you can also set it per-format. @@ -578,35 +686,6 @@ You can easily set the line endings of different files using [a `.gitattributes` - - -## File includes and excludes - -Spotless uses [Ant style patterns](https://ant.apache.org/manual/dirtasks.html) to define included and excluded files. -By default, most common compile and test source roots for the supported languages are included. They are `src/main/java/**/*.java`, `src/test/java/**/*.java` for Java and `src/main/scala/**/*.scala`, `src/main/scala/**/*.sc`, `src/test/scala/**/*.scala`, `src/test/scala/**/*.sc` for Scala. -Includes can be completely overriden using `...` configuration section. - -Default excludes only contain output directory (usually `target/`) and various temporary and VCS-related files. Additional excludes can also be configured. - -Includes and excludes can be configured the same way for all supported languages. Excample for Java: - -```xml - - - - src/**/java/**/*.java - - - other/java/**/*.java - - - - - src/test/java/**/*Example.java - - -``` - ## Disabling warnings and error messages By default, `spotless:check` is bound to the `verify` phase. You might want to disable this behavior. We [recommend against this](https://github.com/diffplug/spotless/issues/79#issuecomment-290844602), but it's easy to do if you'd like: @@ -624,26 +703,6 @@ By default, `spotless:check` is bound to the `verify` phase. You might want to - If you don't like what spotless did, `git reset --hard` - If you'd like to remove the "checkpoint" commit, `git reset --soft head~1` will make the checkpoint commit "disappear" from history, but keeps the changes in your working directory. - - -## How can I enforce formatting gradually? - -If your project is not currently enforcing formatting, then it can be a noisy transition. Having a giant commit where every single file gets changed makes the history harder to read. To address this, you can use the `ratchet` feature: - -```xml - - origin/main - - -``` - -In this mode, Spotless will apply only to files which have changed since `origin/main`. You can ratchet from [any point you want](https://javadoc.io/static/org.eclipse.jgit/org.eclipse.jgit/5.6.1.202002131546-r/org/eclipse/jgit/lib/Repository.html#resolve-java.lang.String-), even `HEAD`. You can also set `ratchetFrom` per-format if you prefer (e.g. `...`). - -However, we strongly recommend that you use a non-local branch, such as a tag or `origin/main`. The problem with `HEAD` or any local branch is that as soon as you commit a file, that is now the canonical formatting, even if it was formatted incorrectly. By instead specifying `origin/main` or a tag, your CI server will fail unless every changed file is at least as good or better than it was before the change. - -This is especially helpful for injecting accurate copyright dates using the [license step](#license-header). - - ## Can I apply Spotless to specific files? You can target specific files by setting the `spotlessFiles` project property to a comma-separated list of file patterns: