Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ This document is intended for Spotless developers.
We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (starting after version `1.27.0`).

## [Unreleased]
### Added
- Add `tabletest-formatter` support for Java and Kotlin. ([#2860](https://github.com/diffplug/spotless/pull/2860))
### Fixed
- Fix the ability to specify a wildcard version (`*`) for external formatter executables, which did not work. ([#2848](https://github.com/diffplug/spotless/pull/2848))

Expand Down
3 changes: 3 additions & 0 deletions lib/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ def NEEDS_GLUE = [
'palantirJavaFormat',
'scalafmt',
'sortPom',
'tableTestFormatter',
'zjsonPatch',
]
for (glue in NEEDS_GLUE) {
Expand Down Expand Up @@ -122,6 +123,8 @@ dependencies {
// sortPom
sortPomCompileOnly 'com.github.ekryd.sortpom:sortpom-sorter:4.0.0'
sortPomCompileOnly 'org.slf4j:slf4j-api:2.0.17'
// tableTestFormatter
tableTestFormatterCompileOnly 'org.tabletest:tabletest-formatter-core:1.0.1'
// zjsonPatch
zjsonPatchCompileOnly 'com.flipkart.zjsonpatch:zjsonpatch:0.4.16'
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/*
* Copyright 2026 DiffPlug
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.diffplug.spotless.java;

import java.io.Serial;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.util.Objects;

import com.diffplug.spotless.FormatterFunc;
import com.diffplug.spotless.FormatterStep;
import com.diffplug.spotless.JarState;
import com.diffplug.spotless.Provisioner;

/**
* Formats {@code @TableTest} annotation tables in Java and Kotlin source files.
* Configuration is read from {@code .editorconfig} files.
*/
public final class TableTestFormatterStep implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
private static final String NAME = "tableTestFormatter";
private static final String MAVEN_COORDINATE = "org.tabletest:tabletest-formatter-core:";
private static final String DEFAULT_VERSION = "1.0.1";

private final JarState.Promised jarState;
private final String version;

private TableTestFormatterStep(JarState.Promised jarState, String version) {
this.jarState = jarState;
this.version = version;
}

/** Creates a step which formats {@code @TableTest} tables using the default version. */
public static FormatterStep create(Provisioner provisioner) {
return create(defaultVersion(), provisioner);
}

/** Creates a step which formats {@code @TableTest} tables using the given version. */
public static FormatterStep create(String version, Provisioner provisioner) {
Objects.requireNonNull(version, "version");
Objects.requireNonNull(provisioner, "provisioner");
return FormatterStep.create(NAME,
new TableTestFormatterStep(JarState.promise(() -> JarState.from(MAVEN_COORDINATE + version, provisioner)), version),
TableTestFormatterStep::equalityState,
State::createFormat);
}

/** Get default formatter version. */
public static String defaultVersion() {
return DEFAULT_VERSION;
}

private State equalityState() {
return new State(jarState.get(), version);
}

private static final class State implements Serializable {
@Serial
private static final long serialVersionUID = 1L;

private final JarState jarState;
private final String version;

State(JarState jarState, String version) {
this.jarState = jarState;
this.version = version;
}

FormatterFunc createFormat() throws Exception {
ClassLoader classLoader = jarState.getClassLoader();
Class<?> formatterClazz = classLoader.loadClass("com.diffplug.spotless.glue.java.TableTestFormatterFunc");
Constructor<?> constructor = formatterClazz.getConstructor();
return (FormatterFunc.NeedsFile) constructor.newInstance();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Copyright 2026 DiffPlug
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.diffplug.spotless.glue.java;

import java.io.File;

import org.tabletest.formatter.config.Config;
import org.tabletest.formatter.config.EditorConfigProvider;
import org.tabletest.formatter.core.SourceFileFormatter;
import org.tabletest.formatter.core.TableTestFormatter;

import com.diffplug.spotless.FormatterFunc;

/**
* Formats {@code @TableTest} annotation tables in Java and Kotlin source files.
*/
public class TableTestFormatterFunc implements FormatterFunc.NeedsFile {

private static final EditorConfigProvider CONFIG_PROVIDER = new EditorConfigProvider();

private final TableTestFormatter tableFormatter = new TableTestFormatter();
private final SourceFileFormatter sourceFormatter = new SourceFileFormatter();

@Override
public String applyWithFile(String unix, File file) throws Exception {
String fileName = file.getName();

if (fileName.endsWith(".java") || fileName.endsWith(".kt")) {
Config config = CONFIG_PROVIDER.lookupConfig(file.toPath(), Config.SPACES_4);
String formatted = sourceFormatter.format(unix, config);
return formatted.equals(unix) ? unix : formatted;
}

return unix;
}
}
2 changes: 2 additions & 0 deletions plugin-gradle/CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (starting after version `3.27.0`).

## [Unreleased]
### Added
- Add `tabletest-formatter` support for Java and Kotlin. ([#2860](https://github.com/diffplug/spotless/pull/2860))
### Fixed
- Fix the ability to specify a wildcard version (`*`) for external formatter executables, which did not work. ([#2848](https://github.com/diffplug/spotless/pull/2848))

Expand Down
30 changes: 28 additions & 2 deletions plugin-gradle/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,9 @@ Spotless supports all of Gradle's built-in performance features (incremental bui
- [Git hook (optional)](#git-hook)
- [Linting](#linting)
- **Languages**
- [Java](#java) ([google-java-format](#google-java-format), [eclipse jdt](#eclipse-jdt), [clang-format](#clang-format), [prettier](#prettier), [palantir-java-format](#palantir-java-format), [formatAnnotations](#formatAnnotations), [cleanthat](#cleanthat), [IntelliJ IDEA](#intellij-idea))
- [Java](#java) ([google-java-format](#google-java-format), [eclipse jdt](#eclipse-jdt), [clang-format](#clang-format), [prettier](#prettier), [palantir-java-format](#palantir-java-format), [formatAnnotations](#formatAnnotations), [cleanthat](#cleanthat), [tabletest-formatter](#tabletest-formatter), [IntelliJ IDEA](#intellij-idea))
- [Groovy](#groovy) ([eclipse groovy](#eclipse-groovy))
- [Kotlin](#kotlin) ([ktfmt](#ktfmt), [ktlint](#ktlint), [diktat](#diktat), [prettier](#prettier))
- [Kotlin](#kotlin) ([ktfmt](#ktfmt), [ktlint](#ktlint), [diktat](#diktat), [tabletest-formatter](#tabletest-formatter-1), [prettier](#prettier))
- [Scala](#scala) ([scalafmt](#scalafmt))
- [C/C++](#cc) ([clang-format](#clang-format), [eclipse cdt](#eclipse-cdt))
- [Protobuf](#protobuf) ([buf](#buf), [clang-format](#clang-format))
Expand Down Expand Up @@ -220,6 +220,8 @@ spotless {
clangFormat() // has its own section below
idea() // has its own section below

tableTestFormatter() // has its own section below

formatAnnotations() // fixes formatting of type annotations, see below

licenseHeader '/* (C) $YEAR */' // or licenseHeaderFile
Expand Down Expand Up @@ -428,6 +430,17 @@ spotless {
.includeDraft(false) // You may exclude draft mutators (from Composite ones)
```

### tabletest-formatter

[homepage](https://github.com/nchaugen/tabletest-formatter). [changelog](https://github.com/nchaugen/tabletest-formatter/releases). Formats [`@TableTest`](https://github.com/nchaugen/tabletest) tables in Java source files. All configuration is read from `.editorconfig` files.

```gradle
spotless {
java {
tableTestFormatter()
// optional: you can specify a specific version
tableTestFormatter('1.0.1')
```

<a name="applying-to-groovy-source"></a>

Expand Down Expand Up @@ -510,6 +523,7 @@ spotless { // if you are using build.gradle.kts, instead of 'spotless {' use:
ktlint() // has its own section below
diktat() // has its own section below
prettier() // has its own section below
tableTestFormatter() // has its own section below
licenseHeader '/* (C)$YEAR */' // or licenseHeaderFile
}
kotlinGradle {
Expand Down Expand Up @@ -593,6 +607,18 @@ spotless {
diktat('1.0.1').configFile("full/path/to/diktat-analysis.yml")
```

### tabletest-formatter

[homepage](https://github.com/nchaugen/tabletest-formatter). [changelog](https://github.com/nchaugen/tabletest-formatter/releases). Formats [`@TableTest`](https://github.com/nchaugen/tabletest) tables in Kotlin source files. All configuration is read from `.editorconfig` files.

```kotlin
spotless {
kotlin {
tableTestFormatter()
// optional: you can specify a specific version
tableTestFormatter('1.0.1')
```

<a name="applying-scalafmt-to-scala-files"></a>

## Scala
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2023-2025 DiffPlug
* Copyright 2023-2026 DiffPlug
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -29,6 +29,7 @@
import com.diffplug.common.collect.ImmutableSortedMap;
import com.diffplug.spotless.FileSignature;
import com.diffplug.spotless.FormatterStep;
import com.diffplug.spotless.java.TableTestFormatterStep;
import com.diffplug.spotless.kotlin.DiktatStep;
import com.diffplug.spotless.kotlin.KtLintStep;
import com.diffplug.spotless.kotlin.KtfmtStep;
Expand Down Expand Up @@ -69,6 +70,30 @@ public KtfmtConfig ktfmt(String version) {
return new KtfmtConfig(version);
}

/** Formats {@code @TableTest} annotation tables using <a href="https://github.com/nchaugen/tabletest-formatter">tabletest-formatter</a>. */
public TableTestFormatterConfig tableTestFormatter() {
return tableTestFormatter(TableTestFormatterStep.defaultVersion());
}

/** Formats {@code @TableTest} annotation tables using the given version of tabletest-formatter. */
public TableTestFormatterConfig tableTestFormatter(String version) {
Objects.requireNonNull(version);
return new TableTestFormatterConfig(version);
}

public final class TableTestFormatterConfig {
final String version;

TableTestFormatterConfig(String version) {
this.version = Objects.requireNonNull(version);
addStep(createStep());
}

private FormatterStep createStep() {
return TableTestFormatterStep.create(version, provisioner());
}
}

protected abstract boolean isScript();

public final class DiktatConfig {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
import com.diffplug.spotless.java.ImportOrderStep;
import com.diffplug.spotless.java.PalantirJavaFormatStep;
import com.diffplug.spotless.java.RemoveUnusedImportsStep;
import com.diffplug.spotless.java.TableTestFormatterStep;

public class JavaExtension extends FormatExtension implements HasBuiltinDelimiterForLicense, JvmLang {
static final String NAME = "java";
Expand Down Expand Up @@ -507,6 +508,30 @@ private FormatterStep createStep() {
}
}

/** Formats {@code @TableTest} annotation tables using <a href="https://github.com/nchaugen/tabletest-formatter">tabletest-formatter</a>. */
public TableTestFormatterConfig tableTestFormatter() {
return tableTestFormatter(TableTestFormatterStep.defaultVersion());
}

/** Formats {@code @TableTest} annotation tables using <a href="https://github.com/nchaugen/tabletest-formatter">tabletest-formatter</a>. */
public TableTestFormatterConfig tableTestFormatter(String version) {
Objects.requireNonNull(version);
return new TableTestFormatterConfig(version);
}

public class TableTestFormatterConfig {
final String version;

TableTestFormatterConfig(String version) {
this.version = Objects.requireNonNull(version);
addStep(createStep());
}

private FormatterStep createStep() {
return TableTestFormatterStep.create(version, provisioner());
}
}

/** If the user hasn't specified the files yet, we'll assume he/she means all of the java files. */
@Override
protected void setupTask(SpotlessTask task) {
Expand Down
2 changes: 2 additions & 0 deletions plugin-maven/CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (starting after version `1.27.0`).

## [Unreleased]
### Added
- Add `tabletest-formatter` support for Java and Kotlin. ([#2860](https://github.com/diffplug/spotless/pull/2860))
### Fixed
- Fix the ability to specify a wildcard version (`*`) for external formatter executables, which did not work. ([#2848](https://github.com/diffplug/spotless/pull/2848))

Expand Down
28 changes: 26 additions & 2 deletions plugin-maven/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ user@machine repo % mvn spotless:check
- [Git hook (optional)](#git-hook)
- [Binding to maven phase](#binding-to-maven-phase)
- **Languages**
- [Java](#java) ([google-java-format](#google-java-format), [eclipse jdt](#eclipse-jdt), [prettier](#prettier), [palantir-java-format](#palantir-java-format), [formatAnnotations](#formatAnnotations), [cleanthat](#cleanthat), [IntelliJ IDEA](#intellij-idea))
- [Java](#java) ([google-java-format](#google-java-format), [eclipse jdt](#eclipse-jdt), [prettier](#prettier), [palantir-java-format](#palantir-java-format), [formatAnnotations](#formatAnnotations), [cleanthat](#cleanthat), [tabletest-formatter](#tabletest-formatter), [IntelliJ IDEA](#intellij-idea))
- [Groovy](#groovy) ([eclipse groovy](#eclipse-groovy))
- [Kotlin](#kotlin) ([ktfmt](#ktfmt), [ktlint](#ktlint), [diktat](#diktat), [prettier](#prettier))
- [Kotlin](#kotlin) ([ktfmt](#ktfmt), [ktlint](#ktlint), [diktat](#diktat), [tabletest-formatter](#tabletest-formatter-1), [prettier](#prettier))
- [Scala](#scala) ([scalafmt](#scalafmt))
- [C/C++](#cc) ([eclipse cdt](#eclipse-cdt), [clang-format](#clang-format))
- [Python](#python) ([black](#black))
Expand Down Expand Up @@ -216,6 +216,8 @@ any other maven phase (i.e. compile) then it can be configured as below;
<prettier /> <!-- has its own section below -->
<idea /> <!-- has its own section below -->

<tableTestFormatter /> <!-- has its own section below -->

<importOrder /> <!-- standard import order -->
<importOrder> <!-- or a custom ordering -->
<wildcardsLast>false</wildcardsLast> <!-- Optional, default false. Sort wildcard import after specific imports -->
Expand Down Expand Up @@ -399,6 +401,16 @@ These mechanisms already exist for the Gradle plugin.
</cleanthat>
```

### tabletest-formatter

[homepage](https://github.com/nchaugen/tabletest-formatter). [changelog](https://github.com/nchaugen/tabletest-formatter/releases). [code](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/TableTestFormatter.java). Formats [`@TableTest`](https://github.com/nchaugen/tabletest) tables in Java source files. All configuration is read from `.editorconfig` files.

```xml
<tableTestFormatter>
<version>1.0.1</version> <!-- optional -->
</tableTestFormatter>
```

## Groovy

[code](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/groovy/Groovy.java). [available steps](https://github.com/diffplug/spotless/tree/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/groovy).
Expand Down Expand Up @@ -462,6 +474,8 @@ Groovy-Eclipse formatting errors/warnings lead per default to a build failure. T
<diktat /> <!-- has its own section below -->
<prettier /> <!-- has its own section below -->

<tableTestFormatter /> <!-- has its own section below -->

<licenseHeader>
<content>/* (C)$YEAR */</content> <!-- or <file>${project.basedir}/license-header</file> -->
</licenseHeader>
Expand Down Expand Up @@ -523,6 +537,16 @@ Additionally, `editorConfigOverride` options will override what's supplied in `.
</diktat>
```

### tabletest-formatter

[homepage](https://github.com/nchaugen/tabletest-formatter). [changelog](https://github.com/nchaugen/tabletest-formatter/releases). [code](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/kotlin/TableTestFormatter.java). Formats [`@TableTest`](https://github.com/nchaugen/tabletest) tables in Kotlin source files. All configuration is read from `.editorconfig` files.

```xml
<tableTestFormatter>
<version>1.0.1</version> <!-- optional -->
</tableTestFormatter>
```

<a name="applying-to-scala-source"></a>

## Scala
Expand Down
Loading