Skip to content

Latest commit

 

History

History
248 lines (195 loc) · 12.4 KB

README.md

File metadata and controls

248 lines (195 loc) · 12.4 KB

Spotless: Keep your code spotless with Gradle

Gradle plugin Maven central Javadoc

Changelog Travis CI Live chat License Apache

Spotless is a general-purpose formatting plugin. It is completely à la carte, but also includes powerful "batteries-included" if you opt-in.

To people who use your build, it looks like this:

cmd> gradlew build
...
:spotlessJavaCheck FAILED
> 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
:spotlessApply
BUILD SUCCESSFUL

cmd> gradlew build
BUILD SUCCESSFUL

Inside your buildscript, it looks like this:

spotless {
	format 'misc', {
		target '**/*.gradle', '**/*.md', '**/.gitignore'

		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', '#'
	}
}

Spotless can check and apply formatting to any plain-text file, using simple rules (javadoc) like those above. It also supports more powerful formatters:

  • Eclipse's java code formatter (including style and import ordering)
  • Google's google-java-format
  • FreshMark (markdown with variables)
  • Any user-defined function which takes an unformatted string and outputs a formatted version.

Contributions are welcome, see the contributing guide for development info.

Spotless requires Gradle to be running on JRE 8+.See issue #7 for details.

Applying to Java source

apply plugin: 'java'
...

spotless {
	java {
		// By default, all Java source sets will be formatted.  To change
		// this, set the 'target' parameter as described in the next section.

		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', '']	// An array 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

		eclipseFormatFile 'spotless.eclipseformat.xml'	// XML file dumped out by the Eclipse formatter
		// If you have an older Eclipse properties file, you can use that too.
	}
}

See ECLIPSE_SCREENSHOTS for screenshots that demonstrate how to get and install the eclipseFormatFile and importOrderFile mentioned above.

Applying to Java source (google-java-format)

spotless {
	java {
		googleJavaFormat() // googleJavaFormat('1.1') to specify a specific version
		// you can then layer other format steps, such as
		licenseHeaderFile 'spotless.license.java'
	}
}

Applying FreshMark to markdown files

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).

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:

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
		}
	}
}

Applying scalafmt to Scala files

spotless {
	scala {
		scalafmt()
		// optional: you can specify a specific version or config file
		scalafmt('0.5.1').configFile('scalafmt.conf')
	}
}

Custom rules

Spotless is a generic system for specifying a sequence of steps which are applied to a set of files.

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'

		// 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!
		}
	}
}

If you use custom or customLazy, you might want to take a look at this javadoc for a big performance win.

See 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.

Line endings and encodings (invisible stuff)

Spotless uses UTF-8 by default, but you can use any encoding which Java supports. You can set it globally, and you can also set it per-format.

spotless {
	java {
		...
		encoding 'Cp1252' // java will have Cp1252
	}
	encoding 'US-ASCII'   // but all other formats will be interpreted as US-ASCII
}

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. Here's an example .gitattributes which sets all files to unix newlines: * text eol=lf.

How do I preview what spotlessApply will do?

  • Save your working tree with git add -A, then git commit -m "Checkpoint before spotless."
  • Run gradlew spotlessApply
  • View the changes with git diff
  • 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.

Example configurations (from real-world projects)

Spotless is hosted on jcenter and at plugins.gradle.org. Go here if you're not sure how to import the plugin.