diff --git a/.circleci/config.yml b/.circleci/config.yml index dd9adf4c00..b9f91766c9 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -140,121 +140,6 @@ jobs: path: lib-extra/build/test-results/test - store_test_results: path: plugin-gradle/build/test-results/test - changelog_print: - << : *env_gradle - steps: - - checkout - - *restore_cache_wrapper - - *restore_cache_deps - - run: - name: gradlew changelogPrint - command: ./gradlew changelogPrint - do_release_all: - << : *env_gradle - steps: - - checkout - - *restore_cache_wrapper - - *restore_cache_deps - - *set_git_origin_to_https - - run: - name: gradlew :changelogPush - command: ./gradlew :changelogPush -Prelease=true --stacktrace --warning-mode all - - run: - name: gradlew :plugin-gradle:changelogPush - command: ./gradlew :plugin-gradle:changelogPush -Prelease=true -Pgradle.publish.key=${gradle_key} -Pgradle.publish.secret=${gradle_secret} --stacktrace --warning-mode all - - run: - name: gradlew :plugin-maven:changelogPush - command: ./gradlew :plugin-maven:changelogPush -Prelease=true --stacktrace --warning-mode all - do_release_lib: - << : *env_gradle - steps: - - checkout - - *restore_cache_wrapper - - *restore_cache_deps - - *set_git_origin_to_https - - run: - name: gradlew :changelogPush - command: ./gradlew :changelogPush -Prelease=true --stacktrace --warning-mode all - do_release_plugin_gradle: - << : *env_gradle - steps: - - checkout - - *restore_cache_wrapper - - *restore_cache_deps - - *set_git_origin_to_https - - run: - name: gradlew :plugin-gradle:changelogPush - command: ./gradlew :plugin-gradle:changelogPush -Prelease=true -Pgradle.publish.key=${gradle_key} -Pgradle.publish.secret=${gradle_secret} --stacktrace - do_release_plugin_maven: - << : *env_gradle - steps: - - checkout - - *restore_cache_wrapper - - *restore_cache_deps - - *set_git_origin_to_https - - run: - name: gradlew :plugin-maven:changelogPush - command: ./gradlew :plugin-maven:changelogPush -Prelease=true --stacktrace - ext_changelog_print: - << : *env_gradle - steps: - - checkout - - *restore_cache_wrapper - - *restore_cache_deps - - *set_git_origin_to_https - - run: - name: gradlew -Pcom.diffplug.spotless.include.ext.nop2=true changelogPrint - command: ./gradlew -Pcom.diffplug.spotless.include.ext.nop2=true changelogPrint - ext_do_release_base: - << : *env_gradle - steps: - - checkout - - *restore_cache_wrapper - - *restore_cache_deps - - *set_git_origin_to_https - - run: - name: gradlew :eclipse-base:changelogPush - command: ./gradlew -Pcom.diffplug.spotless.include.ext.nop2=true :eclipse-base:changelogPush -Prelease=true --stacktrace - ext_do_release_jdt: - << : *env_gradle - steps: - - checkout - - *restore_cache_wrapper - - *restore_cache_deps - - *set_git_origin_to_https - - run: - name: gradlew :eclipse-jdt:changelogPush - command: ./gradlew -Pcom.diffplug.spotless.include.ext.nop2=true :eclipse-jdt:changelogPush -Prelease=true --stacktrace - ext_do_release_cdt: - << : *env_gradle - steps: - - checkout - - *restore_cache_wrapper - - *restore_cache_deps - - *set_git_origin_to_https - - run: - name: gradlew :eclipse-cdt:changelogPush - command: ./gradlew -Pcom.diffplug.spotless.include.ext.cdt=true :eclipse-cdt:changelogPush -Prelease=true --stacktrace - ext_do_release_groovy: - << : *env_gradle - steps: - - checkout - - *restore_cache_wrapper - - *restore_cache_deps - - *set_git_origin_to_https - - run: - name: gradlew :eclipse-groovy:changelogPush - command: ./gradlew -Pcom.diffplug.spotless.include.ext.groovy=true :eclipse-groovy:changelogPush -Prelease=true --stacktrace - ext_do_release_wtp: - << : *env_gradle - steps: - - checkout - - *restore_cache_wrapper - - *restore_cache_deps - - *set_git_origin_to_https - - run: - name: gradlew :eclipse-wtp:changelogPush - command: ./gradlew -Pcom.diffplug.spotless.include.ext.wtp=true :eclipse-wtp:changelogPush -Prelease=true --stacktrace workflows: version: 2 @@ -274,105 +159,3 @@ workflows: - test_npm_8: requires: - assemble_testClasses - deploy: - jobs: - - changelog_print: - filters: - branches: - only: main - - release_all: - type: approval - requires: - - changelog_print - - do_release_all: - requires: - - release_all - context: - - SonatypeDeploy - - release_plugin_gradle: - type: approval - requires: - - changelog_print - - do_release_plugin_gradle: - requires: - - release_plugin_gradle - context: - - SonatypeDeploy - - release_plugin_maven: - type: approval - requires: - - changelog_print - - do_release_plugin_maven: - requires: - - release_plugin_maven - context: - - SonatypeDeploy - - release_lib: - type: approval - requires: - - changelog_print - - do_release_lib: - requires: - - release_lib - context: - - SonatypeDeploy - ext_deploy: - jobs: - - ext_changelog_print: - filters: - branches: - only: main - - ext_release_base: - type: approval - requires: - - ext_changelog_print - - ext_do_release_base: - requires: - - ext_release_base - context: - - SonatypeDeploy - - ext_release_jdt: - type: approval - requires: - - ext_changelog_print - - ext_do_release_jdt: - requires: - - ext_release_jdt - context: - - SonatypeDeploy - - ext_release_cdt: - type: approval - requires: - - ext_changelog_print - - ext_do_release_cdt: - filters: - branches: - only: main - requires: - - ext_release_cdt - context: - - SonatypeDeploy - - ext_release_groovy: - type: approval - requires: - - ext_changelog_print - - ext_do_release_groovy: - filters: - branches: - only: main - requires: - - ext_release_groovy - context: - - SonatypeDeploy - - ext_release_wtp: - type: approval - requires: - - ext_changelog_print - - ext_do_release_wtp: - filters: - branches: - only: main - requires: - - ext_release_wtp - context: - - SonatypeDeploy diff --git a/.github/workflows/changelog-print.yml b/.github/workflows/changelog-print.yml new file mode 100644 index 0000000000..0641124750 --- /dev/null +++ b/.github/workflows/changelog-print.yml @@ -0,0 +1,20 @@ +name: changelogPrint + +on: + push: + branches: [main] + +jobs: + build: + runs-on: ubuntu-latest + name: changelogPrint + steps: + - uses: actions/checkout@v3 + - name: jdk 11 + uses: actions/setup-java@v3 + with: + java-version: 11 + distribution: 'temurin' + - name: gradle caching + uses: gradle/gradle-build-action@v2 + - run: ./gradlew changelogPrint diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000000..6af73db448 --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,63 @@ +# GH_TOKEN +# NEXUS_USER +# NEXUS_PASS +# GPG_PASSPHRASE +# GPG_KEY (base64) +# gpg --export-secret-keys --armor KEY_ID | openssl base64 | pbcopy +# GRADLE_PORTAL_KEY +# GRADLE_PORTAL_SECRET + +name: deploy +on: + workflow_dispatch: + inputs: + to_publish: + description: 'What to publish' + required: true + default: 'all' + type: choice + options: + - plugin-gradle + - plugin-maven + - all + - lib + +jobs: + build: + runs-on: ubuntu-latest + name: deploy + env: + gh_token: ${{ secrets.GH_TOKEN }} + ORG_GRADLE_PROJECT_nexus_user: ${{ secrets.NEXUS_USER }} + ORG_GRADLE_PROJECT_nexus_pass: ${{ secrets.NEXUS_PASS }} + ORG_GRADLE_PROJECT_gpg_passphrase: ${{ secrets.GPG_PASSPHRASE }} + ORG_GRADLE_PROJECT_gpg_key64: ${{ secrets.GPG_KEY }} + + gradle_key + steps: + - uses: actions/checkout@v3 + - name: jdk 11 + uses: actions/setup-java@v3 + with: + java-version: 11 + distribution: 'temurin' + - name: gradle caching + uses: gradle/gradle-build-action@v2 + - name: publish all + if: "${{ github.event.inputs.to_publish == 'all' }}" + run: | + ./gradlew :changelogPush -Prelease=true --stacktrace --warning-mode all + ./gradlew :plugin-gradle:changelogPush -Prelease=true -Pgradle.publish.key=${{ secrets.GRADLE_PORTAL_KEY }} -Pgradle.publish.secret=${{ secrets.GRADLE_PORTAL_SECRET }} --stacktrace --warning-mode all + ./gradlew :plugin-maven:changelogPush -Prelease=true --stacktrace --warning-mode all + - name: publish just plugin-gradle + if: "${{ github.event.inputs.to_publish == 'plugin-gradle' }}" + run: | + ./gradlew :plugin-gradle:changelogPush -Prelease=true -Pgradle.publish.key=${{ secrets.GRADLE_PORTAL_KEY }} -Pgradle.publish.secret=${{ secrets.GRADLE_PORTAL_SECRET }} --stacktrace --warning-mode all + - name: publish just plugin-maven + if: "${{ github.event.inputs.to_publish == 'plugin-maven' }}" + run: | + ./gradlew :plugin-maven:changelogPush -Prelease=true --stacktrace --warning-mode all + - name: publish just lib + if: "${{ github.event.inputs.to_publish == 'lib' }}" + run: | + ./gradlew :changelogPush -Prelease=true --stacktrace --warning-mode all diff --git a/CHANGES.md b/CHANGES.md index 95a657e334..dcbf4b8cd9 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -11,9 +11,14 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format ( ## [Unreleased] ### Added +* Add option `editorConfigFile` for `ktLint` [#142](https://github.com/diffplug/spotless/issues/142) +* Added `skipLinesMatching` option to `licenseHeader` to support formats where license header cannot be immediately added to the top of the file (e.g. xml, sh). ([#1441](https://github.com/diffplug/spotless/pull/1441)). +### Fixed +* Support `ktlint` 0.48+ new rule disabling syntax ([#1456](https://github.com/diffplug/spotless/pull/1456)) fixes ([#1444](https://github.com/diffplug/spotless/issues/1444)) * Added support for npm-based [ESLint](https://eslint.org/)-formatter for javascript and typescript ([#1453](https://github.com/diffplug/spotless/pull/1453)) + ### Changes -* Bump default Version for `prettier` from `2.0.5` to `2.8.1` +* Bump default version for `prettier` from `2.0.5` to `2.8.1` ([#1453](https://github.com/diffplug/spotless/pull/1453)) * Bump the dev version of Gradle from `7.5.1` to `7.6` ([#1409](https://github.com/diffplug/spotless/pull/1409)) * We also removed the no-longer-required dependency `org.codehaus.groovy:groovy-xml` * Breaking changes to Spotless' internal testing infrastructure `testlib` ([#1443](https://github.com/diffplug/spotless/pull/1443)) @@ -21,6 +26,9 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format ( * `StepHarness` now operates on `Formatter` rather than a `FormatterStep` * `StepHarnessWithFile` now takes a `ResourceHarness` in its constructor to handle the file manipulation parts * Standardized that we test exception *messages*, not types, which will ease the transition to linting later on + * Bump default `ktlint` version to latest `0.47.1` -> `0.48.1` ([#1456](https://github.com/diffplug/spotless/pull/1456)) +* Switch our publishing infrastructure from CircleCI to GitHub Actions ([#1462](https://github.com/diffplug/spotless/pull/1462)). + * Help wanted for moving our tests too ([#1472](https://github.com/diffplug/spotless/issues/1472)) ## [2.31.1] - 2023-01-02 diff --git a/gradle.properties b/gradle.properties index 577ed87535..e966c09437 100644 --- a/gradle.properties +++ b/gradle.properties @@ -27,7 +27,7 @@ VER_SLF4J=[1.6,2.0[ VER_DURIAN=1.2.0 VER_JGIT=5.13.1.202206130422-r VER_JUNIT=5.9.1 -VER_ASSERTJ=3.23.1 +VER_ASSERTJ=3.24.1 VER_MOCKITO=4.11.0 # Used for Maven Plugin diff --git a/lib/build.gradle b/lib/build.gradle index 0cc258afca..115d27195f 100644 --- a/lib/build.gradle +++ b/lib/build.gradle @@ -45,9 +45,9 @@ dependencies { compileOnly 'org.slf4j:slf4j-api:2.0.0' // zero runtime reqs is a hard requirements for spotless-lib // if you need a dep, put it in lib-extra - testImplementation "org.junit.jupiter:junit-jupiter:$VER_JUNIT" - testImplementation "org.assertj:assertj-core:$VER_ASSERTJ" - testImplementation "com.diffplug.durian:durian-testlib:$VER_DURIAN" + testCommonImplementation "org.junit.jupiter:junit-jupiter:$VER_JUNIT" + testCommonImplementation "org.assertj:assertj-core:$VER_ASSERTJ" + testCommonImplementation "com.diffplug.durian:durian-testlib:$VER_DURIAN" // used for pom sorting sortPomCompileOnly 'com.github.ekryd.sortpom:sortpom-sorter:3.0.0' @@ -91,9 +91,9 @@ dependencies { compatKtLint0Dot47Dot0CompileOnly 'com.pinterest.ktlint:ktlint-core:0.47.0' compatKtLint0Dot47Dot0CompileOnly 'com.pinterest.ktlint:ktlint-ruleset-experimental:0.47.0' compatKtLint0Dot47Dot0CompileOnly 'com.pinterest.ktlint:ktlint-ruleset-standard:0.47.0' - compatKtLint0Dot48Dot0CompileOnly 'com.pinterest.ktlint:ktlint-core:0.48.0' - compatKtLint0Dot48Dot0CompileOnly 'com.pinterest.ktlint:ktlint-ruleset-experimental:0.48.0' - compatKtLint0Dot48Dot0CompileOnly 'com.pinterest.ktlint:ktlint-ruleset-standard:0.48.0' + compatKtLint0Dot48Dot0CompileAndTestOnly 'com.pinterest.ktlint:ktlint-core:0.48.0' + compatKtLint0Dot48Dot0CompileAndTestOnly 'com.pinterest.ktlint:ktlint-ruleset-experimental:0.48.0' + compatKtLint0Dot48Dot0CompileAndTestOnly 'com.pinterest.ktlint:ktlint-ruleset-standard:0.48.0' String VER_SCALAFMT="3.6.1" scalafmtCompileOnly "org.scalameta:scalafmt-core_2.13:$VER_SCALAFMT" @@ -108,7 +108,9 @@ dependencies { // we'll hold the core lib to a high standard spotbugs { reportLevel = 'low' } // low|medium|high (low = sensitive to even minor mistakes) -test { useJUnitPlatform() } +tasks.withType(Test).configureEach { + useJUnitPlatform() +} jar { for (glue in NEEDS_GLUE) { diff --git a/lib/src/compatKtLint0Dot31Dot0/java/com/diffplug/spotless/glue/ktlint/compat/KtLintCompat0Dot31Dot0Adapter.java b/lib/src/compatKtLint0Dot31Dot0/java/com/diffplug/spotless/glue/ktlint/compat/KtLintCompat0Dot31Dot0Adapter.java index 56b8da2d20..7a956de86a 100644 --- a/lib/src/compatKtLint0Dot31Dot0/java/com/diffplug/spotless/glue/ktlint/compat/KtLintCompat0Dot31Dot0Adapter.java +++ b/lib/src/compatKtLint0Dot31Dot0/java/com/diffplug/spotless/glue/ktlint/compat/KtLintCompat0Dot31Dot0Adapter.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 DiffPlug + * Copyright 2022-2023 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,6 +15,7 @@ */ package com.diffplug.spotless.glue.ktlint.compat; +import java.nio.file.Path; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -41,9 +42,9 @@ public Unit invoke(LintError lint, Boolean corrected) { } @Override - public String format(final String text, final String name, final boolean isScript, + public String format(final String text, Path path, final boolean isScript, final boolean useExperimental, - final Map userData, + Path editorConfigPath, final Map userData, final Map editorConfigOverrideMap) { final FormatterCallback formatterCallback = new FormatterCallback(); diff --git a/lib/src/compatKtLint0Dot32Dot0/java/com/diffplug/spotless/glue/ktlint/compat/KtLintCompat0Dot32Dot0Adapter.java b/lib/src/compatKtLint0Dot32Dot0/java/com/diffplug/spotless/glue/ktlint/compat/KtLintCompat0Dot32Dot0Adapter.java index 6f69fcc7ce..94c41c3716 100644 --- a/lib/src/compatKtLint0Dot32Dot0/java/com/diffplug/spotless/glue/ktlint/compat/KtLintCompat0Dot32Dot0Adapter.java +++ b/lib/src/compatKtLint0Dot32Dot0/java/com/diffplug/spotless/glue/ktlint/compat/KtLintCompat0Dot32Dot0Adapter.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 DiffPlug + * Copyright 2022-2023 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,6 +15,7 @@ */ package com.diffplug.spotless.glue.ktlint.compat; +import java.nio.file.Path; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -41,9 +42,9 @@ public Unit invoke(LintError lint, Boolean corrected) { } @Override - public String format(final String text, final String name, final boolean isScript, + public String format(final String text, Path path, final boolean isScript, final boolean useExperimental, - final Map userData, + Path editorConfigPath, final Map userData, final Map editorConfigOverrideMap) { final FormatterCallback formatterCallback = new FormatterCallback(); diff --git a/lib/src/compatKtLint0Dot34Dot2/java/com/diffplug/spotless/glue/ktlint/compat/KtLintCompat0Dot34Dot2Adapter.java b/lib/src/compatKtLint0Dot34Dot2/java/com/diffplug/spotless/glue/ktlint/compat/KtLintCompat0Dot34Dot2Adapter.java index a3c8c8df3b..8926a8e21f 100644 --- a/lib/src/compatKtLint0Dot34Dot2/java/com/diffplug/spotless/glue/ktlint/compat/KtLintCompat0Dot34Dot2Adapter.java +++ b/lib/src/compatKtLint0Dot34Dot2/java/com/diffplug/spotless/glue/ktlint/compat/KtLintCompat0Dot34Dot2Adapter.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 DiffPlug + * Copyright 2022-2023 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,6 +15,7 @@ */ package com.diffplug.spotless.glue.ktlint.compat; +import java.nio.file.Path; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -41,9 +42,9 @@ public Unit invoke(LintError lint, Boolean corrected) { } @Override - public String format(final String text, final String name, final boolean isScript, + public String format(final String text, Path path, final boolean isScript, final boolean useExperimental, - final Map userData, + Path editorConfigPath, final Map userData, final Map editorConfigOverrideMap) { final FormatterCallback formatterCallback = new FormatterCallback(); @@ -55,13 +56,13 @@ public String format(final String text, final String name, final boolean isScrip } return KtLint.INSTANCE.format(new KtLint.Params( - name, + path.toFile().getAbsolutePath(), text, rulesets, userData, formatterCallback, isScript, - null, + editorConfigPath.toFile().getAbsolutePath(), false)); } } diff --git a/lib/src/compatKtLint0Dot45Dot2/java/com/diffplug/spotless/glue/ktlint/compat/KtLintCompat0Dot45Dot2Adapter.java b/lib/src/compatKtLint0Dot45Dot2/java/com/diffplug/spotless/glue/ktlint/compat/KtLintCompat0Dot45Dot2Adapter.java index f7eadada3d..c90cf59d2b 100644 --- a/lib/src/compatKtLint0Dot45Dot2/java/com/diffplug/spotless/glue/ktlint/compat/KtLintCompat0Dot45Dot2Adapter.java +++ b/lib/src/compatKtLint0Dot45Dot2/java/com/diffplug/spotless/glue/ktlint/compat/KtLintCompat0Dot45Dot2Adapter.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 DiffPlug + * Copyright 2022-2023 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,6 +15,7 @@ */ package com.diffplug.spotless.glue.ktlint.compat; +import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -49,9 +50,9 @@ public Unit invoke(LintError lint, Boolean corrected) { } @Override - public String format(final String text, final String name, final boolean isScript, + public String format(final String text, Path path, final boolean isScript, final boolean useExperimental, - final Map userData, + Path editorConfigPath, final Map userData, final Map editorConfigOverrideMap) { final FormatterCallback formatterCallback = new FormatterCallback(); @@ -70,13 +71,13 @@ public String format(final String text, final String name, final boolean isScrip } return KtLint.INSTANCE.format(new KtLint.ExperimentalParams( - name, + path.toFile().getAbsolutePath(), text, rulesets, userData, formatterCallback, isScript, - null, + editorConfigPath.toFile().getAbsolutePath(), false, editorConfigOverride, false)); diff --git a/lib/src/compatKtLint0Dot46Dot0/java/com/diffplug/spotless/glue/ktlint/compat/KtLintCompat0Dot46Dot0Adapter.java b/lib/src/compatKtLint0Dot46Dot0/java/com/diffplug/spotless/glue/ktlint/compat/KtLintCompat0Dot46Dot0Adapter.java index 873b91af80..54b34296a4 100644 --- a/lib/src/compatKtLint0Dot46Dot0/java/com/diffplug/spotless/glue/ktlint/compat/KtLintCompat0Dot46Dot0Adapter.java +++ b/lib/src/compatKtLint0Dot46Dot0/java/com/diffplug/spotless/glue/ktlint/compat/KtLintCompat0Dot46Dot0Adapter.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 DiffPlug + * Copyright 2022-2023 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,6 +15,7 @@ */ package com.diffplug.spotless.glue.ktlint.compat; +import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -49,9 +50,9 @@ public Unit invoke(LintError lint, Boolean corrected) { } @Override - public String format(final String text, final String name, final boolean isScript, + public String format(final String text, Path path, final boolean isScript, final boolean useExperimental, - final Map userData, + Path editorConfigPath, final Map userData, final Map editorConfigOverrideMap) { final FormatterCallback formatterCallback = new FormatterCallback(); @@ -70,13 +71,13 @@ public String format(final String text, final String name, final boolean isScrip } return KtLint.INSTANCE.format(new KtLint.ExperimentalParams( - name, + path.toFile().getAbsolutePath(), text, rulesets, userData, formatterCallback, isScript, - null, + editorConfigPath.toFile().getAbsolutePath(), false, editorConfigOverride, false)); diff --git a/lib/src/compatKtLint0Dot47Dot0/java/com/diffplug/spotless/glue/ktlint/compat/KtLintCompat0Dot47Dot0Adapter.java b/lib/src/compatKtLint0Dot47Dot0/java/com/diffplug/spotless/glue/ktlint/compat/KtLintCompat0Dot47Dot0Adapter.java index 757ffc922b..0a38730b6a 100644 --- a/lib/src/compatKtLint0Dot47Dot0/java/com/diffplug/spotless/glue/ktlint/compat/KtLintCompat0Dot47Dot0Adapter.java +++ b/lib/src/compatKtLint0Dot47Dot0/java/com/diffplug/spotless/glue/ktlint/compat/KtLintCompat0Dot47Dot0Adapter.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 DiffPlug + * Copyright 2022-2023 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,6 +17,8 @@ import static java.util.Collections.emptySet; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.List; @@ -54,9 +56,9 @@ public Unit invoke(LintError lint, Boolean corrected) { } @Override - public String format(final String text, final String name, final boolean isScript, + public String format(final String text, Path path, final boolean isScript, final boolean useExperimental, - final Map userData, + Path editorConfigPath, final Map userData, final Map editorConfigOverrideMap) { final FormatterCallback formatterCallback = new FormatterCallback(); @@ -68,7 +70,7 @@ public String format(final String text, final String name, final boolean isScrip EditorConfigOverride editorConfigOverride; if (editorConfigOverrideMap.isEmpty()) { - editorConfigOverride = EditorConfigOverride.Companion.getEmptyEditorConfigOverride(); + editorConfigOverride = new EditorConfigOverride(); } else { editorConfigOverride = createEditorConfigOverride(allRuleProviders.stream().map( RuleProvider::createNewRuleInstance).collect( @@ -76,8 +78,15 @@ public String format(final String text, final String name, final boolean isScrip editorConfigOverrideMap); } + EditorConfigDefaults editorConfig; + if (editorConfigPath == null || !Files.exists(editorConfigPath)) { + editorConfig = EditorConfigDefaults.Companion.getEmptyEditorConfigDefaults(); + } else { + editorConfig = EditorConfigDefaults.Companion.load(editorConfigPath); + } + return KtLint.INSTANCE.format(new KtLint.ExperimentalParams( - name, + path.toFile().getAbsolutePath(), text, emptySet(), allRuleProviders, @@ -86,7 +95,7 @@ public String format(final String text, final String name, final boolean isScrip isScript, null, false, - EditorConfigDefaults.Companion.getEmptyEditorConfigDefaults(), + editorConfig, editorConfigOverride, false)); } diff --git a/lib/src/compatKtLint0Dot48Dot0/java/com/diffplug/spotless/glue/ktlint/compat/KtLintCompat0Dot48Dot0Adapter.java b/lib/src/compatKtLint0Dot48Dot0/java/com/diffplug/spotless/glue/ktlint/compat/KtLintCompat0Dot48Dot0Adapter.java index 8235c535a5..5d24603f70 100644 --- a/lib/src/compatKtLint0Dot48Dot0/java/com/diffplug/spotless/glue/ktlint/compat/KtLintCompat0Dot48Dot0Adapter.java +++ b/lib/src/compatKtLint0Dot48Dot0/java/com/diffplug/spotless/glue/ktlint/compat/KtLintCompat0Dot48Dot0Adapter.java @@ -15,6 +15,10 @@ */ package com.diffplug.spotless.glue.ktlint.compat; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Collections; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; @@ -23,15 +27,21 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -import com.pinterest.ktlint.core.KtLint; +import com.pinterest.ktlint.core.KtLintRuleEngine; import com.pinterest.ktlint.core.LintError; import com.pinterest.ktlint.core.Rule; import com.pinterest.ktlint.core.RuleProvider; -import com.pinterest.ktlint.core.api.DefaultEditorConfigProperties; import com.pinterest.ktlint.core.api.EditorConfigDefaults; import com.pinterest.ktlint.core.api.EditorConfigOverride; import com.pinterest.ktlint.core.api.UsesEditorConfigProperties; +import com.pinterest.ktlint.core.api.editorconfig.CodeStyleEditorConfigPropertyKt; +import com.pinterest.ktlint.core.api.editorconfig.DisabledRulesEditorConfigPropertyKt; import com.pinterest.ktlint.core.api.editorconfig.EditorConfigProperty; +import com.pinterest.ktlint.core.api.editorconfig.IndentSizeEditorConfigPropertyKt; +import com.pinterest.ktlint.core.api.editorconfig.IndentStyleEditorConfigPropertyKt; +import com.pinterest.ktlint.core.api.editorconfig.InsertFinalNewLineEditorConfigPropertyKt; +import com.pinterest.ktlint.core.api.editorconfig.MaxLineLengthEditorConfigPropertyKt; +import com.pinterest.ktlint.core.api.editorconfig.RuleExecutionEditorConfigPropertyKt; import com.pinterest.ktlint.ruleset.experimental.ExperimentalRuleSetProvider; import com.pinterest.ktlint.ruleset.standard.StandardRuleSetProvider; @@ -41,20 +51,36 @@ public class KtLintCompat0Dot48Dot0Adapter implements KtLintCompatAdapter { + private static final List> DEFAULT_EDITOR_CONFIG_PROPERTIES; + + static { + List> list = new ArrayList<>(); + list.add(CodeStyleEditorConfigPropertyKt.getCODE_STYLE_PROPERTY()); + //noinspection deprecation + list.add(DisabledRulesEditorConfigPropertyKt.getDISABLED_RULES_PROPERTY()); + //noinspection KotlinInternalInJava,deprecation + list.add(DisabledRulesEditorConfigPropertyKt.getKTLINT_DISABLED_RULES_PROPERTY()); + list.add(IndentStyleEditorConfigPropertyKt.getINDENT_STYLE_PROPERTY()); + list.add(IndentSizeEditorConfigPropertyKt.getINDENT_SIZE_PROPERTY()); + list.add(InsertFinalNewLineEditorConfigPropertyKt.getINSERT_FINAL_NEWLINE_PROPERTY()); + list.add(MaxLineLengthEditorConfigPropertyKt.getMAX_LINE_LENGTH_PROPERTY()); + DEFAULT_EDITOR_CONFIG_PROPERTIES = Collections.unmodifiableList(list); + } + static class FormatterCallback implements Function2 { @Override public Unit invoke(LintError lint, Boolean corrected) { if (!corrected) { KtLintCompatReporting.report(lint.getLine(), lint.getCol(), lint.getRuleId(), lint.getDetail()); } - return null; + return Unit.INSTANCE; } } @Override - public String format(final String text, final String name, final boolean isScript, + public String format(final String text, Path path, final boolean isScript, final boolean useExperimental, - final Map userData, + Path editorConfigPath, final Map userData, final Map editorConfigOverrideMap) { final FormatterCallback formatterCallback = new FormatterCallback(); @@ -66,25 +92,26 @@ public String format(final String text, final String name, final boolean isScrip EditorConfigOverride editorConfigOverride; if (editorConfigOverrideMap.isEmpty()) { - editorConfigOverride = EditorConfigOverride.Companion.getEmptyEditorConfigOverride(); + editorConfigOverride = EditorConfigOverride.Companion.getEMPTY_EDITOR_CONFIG_OVERRIDE(); } else { editorConfigOverride = createEditorConfigOverride(allRuleProviders.stream().map( RuleProvider::createNewRuleInstance).collect( Collectors.toList()), editorConfigOverrideMap); } + EditorConfigDefaults editorConfig; + if (editorConfigPath == null || !Files.exists(editorConfigPath)) { + editorConfig = EditorConfigDefaults.Companion.getEMPTY_EDITOR_CONFIG_DEFAULTS(); + } else { + editorConfig = EditorConfigDefaults.Companion.load(editorConfigPath); + } - return KtLint.INSTANCE.format(new KtLint.ExperimentalParams( - name, - text, + return new KtLintRuleEngine( allRuleProviders, - userData, - formatterCallback, - isScript, - false, - EditorConfigDefaults.Companion.getEmptyEditorConfigDefaults(), + editorConfig, editorConfigOverride, - false)); + false) + .format(path, formatterCallback); } /** @@ -98,7 +125,7 @@ private static EditorConfigOverride createEditorConfigOverride(final List // Create a mapping of properties to their names based on rule properties and default properties Map> supportedProperties = Stream - .concat(ruleProperties, DefaultEditorConfigProperties.INSTANCE.getEditorConfigProperties().stream()) + .concat(ruleProperties, DEFAULT_EDITOR_CONFIG_PROPERTIES.stream()) .distinct() .collect(Collectors.toMap(EditorConfigProperty::getName, property -> property)); @@ -109,6 +136,18 @@ private static EditorConfigOverride createEditorConfigOverride(final List EditorConfigProperty property = supportedProperties.get(entry.getKey()); if (property != null) { return new Pair<>(property, entry.getValue()); + } else if (entry.getKey().startsWith("ktlint_")) { + String[] parts = entry.getKey().substring(7).split("_", 2); + if (parts.length == 1) { + // convert ktlint_{ruleset} to {ruleset} + String qualifiedRuleId = parts[0]; + property = RuleExecutionEditorConfigPropertyKt.createRuleSetExecutionEditorConfigProperty(qualifiedRuleId); + } else { + // convert ktlint_{ruleset}_{rulename} to {ruleset}:{rulename} + String qualifiedRuleId = parts[0] + ":" + parts[1]; + property = RuleExecutionEditorConfigPropertyKt.createRuleExecutionEditorConfigProperty(qualifiedRuleId); + } + return new Pair<>(property, entry.getValue()); } else { return null; } diff --git a/lib/src/compatKtLintApi/java/com/diffplug/spotless/glue/ktlint/compat/KtLintCompatAdapter.java b/lib/src/compatKtLintApi/java/com/diffplug/spotless/glue/ktlint/compat/KtLintCompatAdapter.java index 5097cac135..68a65eb6c8 100644 --- a/lib/src/compatKtLintApi/java/com/diffplug/spotless/glue/ktlint/compat/KtLintCompatAdapter.java +++ b/lib/src/compatKtLintApi/java/com/diffplug/spotless/glue/ktlint/compat/KtLintCompatAdapter.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 DiffPlug + * Copyright 2022-2023 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,10 +15,11 @@ */ package com.diffplug.spotless.glue.ktlint.compat; +import java.nio.file.Path; import java.util.Map; public interface KtLintCompatAdapter { - String format(String text, String name, boolean isScript, boolean useExperimental, Map userData, + String format(String text, Path path, boolean isScript, boolean useExperimental, Path editorConfigPath, Map userData, Map editorConfigOverrideMap); } diff --git a/lib/src/ktlint/java/com/diffplug/spotless/glue/ktlint/KtlintFormatterFunc.java b/lib/src/ktlint/java/com/diffplug/spotless/glue/ktlint/KtlintFormatterFunc.java index fc64cdb23e..e6f3715d25 100644 --- a/lib/src/ktlint/java/com/diffplug/spotless/glue/ktlint/KtlintFormatterFunc.java +++ b/lib/src/ktlint/java/com/diffplug/spotless/glue/ktlint/KtlintFormatterFunc.java @@ -16,19 +16,14 @@ package com.diffplug.spotless.glue.ktlint; import java.io.File; +import java.nio.file.Path; import java.util.Map; import org.jetbrains.annotations.NotNull; +import com.diffplug.spotless.FileSignature; import com.diffplug.spotless.FormatterFunc; -import com.diffplug.spotless.glue.ktlint.compat.KtLintCompat0Dot31Dot0Adapter; -import com.diffplug.spotless.glue.ktlint.compat.KtLintCompat0Dot32Dot0Adapter; -import com.diffplug.spotless.glue.ktlint.compat.KtLintCompat0Dot34Dot2Adapter; -import com.diffplug.spotless.glue.ktlint.compat.KtLintCompat0Dot45Dot2Adapter; -import com.diffplug.spotless.glue.ktlint.compat.KtLintCompat0Dot46Dot0Adapter; -import com.diffplug.spotless.glue.ktlint.compat.KtLintCompat0Dot47Dot0Adapter; -import com.diffplug.spotless.glue.ktlint.compat.KtLintCompat0Dot48Dot0Adapter; -import com.diffplug.spotless.glue.ktlint.compat.KtLintCompatAdapter; +import com.diffplug.spotless.glue.ktlint.compat.*; public class KtlintFormatterFunc implements FormatterFunc.NeedsFile { @@ -37,9 +32,10 @@ public class KtlintFormatterFunc implements FormatterFunc.NeedsFile { @NotNull private final KtLintCompatAdapter adapter; private final boolean useExperimental; + private final FileSignature editorConfigPath; private final Map editorConfigOverrideMap; - public KtlintFormatterFunc(String version, boolean isScript, boolean useExperimental, Map userData, + public KtlintFormatterFunc(String version, boolean isScript, boolean useExperimental, FileSignature editorConfigPath, Map userData, Map editorConfigOverrideMap) { int minorVersion = Integer.parseInt(version.split("\\.")[1]); if (minorVersion >= 48) { @@ -64,6 +60,7 @@ public KtlintFormatterFunc(String version, boolean isScript, boolean useExperime // the OG this.adapter = new KtLintCompat0Dot31Dot0Adapter(); } + this.editorConfigPath = editorConfigPath; this.useExperimental = useExperimental; this.editorConfigOverrideMap = editorConfigOverrideMap; this.userData = userData; @@ -71,7 +68,12 @@ public KtlintFormatterFunc(String version, boolean isScript, boolean useExperime } @Override - public String applyWithFile(String unix, File file) throws Exception { - return adapter.format(unix, file.getName(), isScript, useExperimental, userData, editorConfigOverrideMap); + public String applyWithFile(String unix, File file) { + + Path absoluteEditorConfigPath = null; + if (editorConfigPath != null) { + absoluteEditorConfigPath = editorConfigPath.getOnlyFile().toPath(); + } + return adapter.format(unix, file.toPath(), isScript, useExperimental, absoluteEditorConfigPath, userData, editorConfigOverrideMap); } } diff --git a/lib/src/main/java/com/diffplug/spotless/generic/LicenseHeaderStep.java b/lib/src/main/java/com/diffplug/spotless/generic/LicenseHeaderStep.java index 6a34c08828..46312ca07a 100644 --- a/lib/src/main/java/com/diffplug/spotless/generic/LicenseHeaderStep.java +++ b/lib/src/main/java/com/diffplug/spotless/generic/LicenseHeaderStep.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2021 DiffPlug + * Copyright 2016-2023 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -51,7 +51,7 @@ public static LicenseHeaderStep headerDelimiter(String header, String delimiter) } public static LicenseHeaderStep headerDelimiter(ThrowingEx.Supplier headerLazy, String delimiter) { - return new LicenseHeaderStep(null, null, headerLazy, delimiter, DEFAULT_YEAR_DELIMITER, () -> YearMode.PRESERVE); + return new LicenseHeaderStep(null, null, headerLazy, delimiter, DEFAULT_YEAR_DELIMITER, () -> YearMode.PRESERVE, null); } final String name; @@ -60,14 +60,16 @@ public static LicenseHeaderStep headerDelimiter(ThrowingEx.Supplier head final String delimiter; final String yearSeparator; final Supplier yearMode; + final @Nullable String skipLinesMatching; - private LicenseHeaderStep(@Nullable String name, @Nullable String contentPattern, ThrowingEx.Supplier headerLazy, String delimiter, String yearSeparator, Supplier yearMode) { + private LicenseHeaderStep(@Nullable String name, @Nullable String contentPattern, ThrowingEx.Supplier headerLazy, String delimiter, String yearSeparator, Supplier yearMode, @Nullable String skipLinesMatching) { this.name = sanitizeName(name); - this.contentPattern = sanitizeContentPattern(contentPattern); + this.contentPattern = sanitizePattern(contentPattern); this.headerLazy = Objects.requireNonNull(headerLazy); this.delimiter = Objects.requireNonNull(delimiter); this.yearSeparator = Objects.requireNonNull(yearSeparator); this.yearMode = Objects.requireNonNull(yearMode); + this.skipLinesMatching = sanitizePattern(skipLinesMatching); } public String getName() { @@ -75,11 +77,11 @@ public String getName() { } public LicenseHeaderStep withName(String name) { - return new LicenseHeaderStep(name, contentPattern, headerLazy, delimiter, yearSeparator, yearMode); + return new LicenseHeaderStep(name, contentPattern, headerLazy, delimiter, yearSeparator, yearMode, skipLinesMatching); } public LicenseHeaderStep withContentPattern(String contentPattern) { - return new LicenseHeaderStep(name, contentPattern, headerLazy, delimiter, yearSeparator, yearMode); + return new LicenseHeaderStep(name, contentPattern, headerLazy, delimiter, yearSeparator, yearMode, skipLinesMatching); } public LicenseHeaderStep withHeaderString(String header) { @@ -87,15 +89,15 @@ public LicenseHeaderStep withHeaderString(String header) { } public LicenseHeaderStep withHeaderLazy(ThrowingEx.Supplier headerLazy) { - return new LicenseHeaderStep(name, contentPattern, headerLazy, delimiter, yearSeparator, yearMode); + return new LicenseHeaderStep(name, contentPattern, headerLazy, delimiter, yearSeparator, yearMode, skipLinesMatching); } public LicenseHeaderStep withDelimiter(String delimiter) { - return new LicenseHeaderStep(name, contentPattern, headerLazy, delimiter, yearSeparator, yearMode); + return new LicenseHeaderStep(name, contentPattern, headerLazy, delimiter, yearSeparator, yearMode, skipLinesMatching); } public LicenseHeaderStep withYearSeparator(String yearSeparator) { - return new LicenseHeaderStep(name, contentPattern, headerLazy, delimiter, yearSeparator, yearMode); + return new LicenseHeaderStep(name, contentPattern, headerLazy, delimiter, yearSeparator, yearMode, skipLinesMatching); } public LicenseHeaderStep withYearMode(YearMode yearMode) { @@ -103,7 +105,11 @@ public LicenseHeaderStep withYearMode(YearMode yearMode) { } public LicenseHeaderStep withYearModeLazy(Supplier yearMode) { - return new LicenseHeaderStep(name, contentPattern, headerLazy, delimiter, yearSeparator, yearMode); + return new LicenseHeaderStep(name, contentPattern, headerLazy, delimiter, yearSeparator, yearMode, skipLinesMatching); + } + + public LicenseHeaderStep withSkipLinesMatching(@Nullable String skipLinesMatching) { + return new LicenseHeaderStep(name, contentPattern, headerLazy, delimiter, yearSeparator, yearMode, skipLinesMatching); } public FormatterStep build() { @@ -112,7 +118,7 @@ public FormatterStep build() { if (yearMode.get() == YearMode.SET_FROM_GIT) { formatterStep = FormatterStep.createNeverUpToDateLazy(name, () -> { boolean updateYear = false; // doesn't matter - Runtime runtime = new Runtime(headerLazy.get(), delimiter, yearSeparator, updateYear); + Runtime runtime = new Runtime(headerLazy.get(), delimiter, yearSeparator, updateYear, skipLinesMatching); return FormatterFunc.needsFile(runtime::setLicenseHeaderYearsFromGitHistory); }); } else { @@ -130,7 +136,7 @@ public FormatterStep build() { default: throw new IllegalStateException(yearMode.toString()); } - return new Runtime(headerLazy.get(), delimiter, yearSeparator, updateYear); + return new Runtime(headerLazy.get(), delimiter, yearSeparator, updateYear, skipLinesMatching); }, step -> step::format); } @@ -156,18 +162,18 @@ private String sanitizeName(@Nullable String name) { } @Nullable - private String sanitizeContentPattern(@Nullable String contentPattern) { - if (contentPattern == null) { - return contentPattern; + private String sanitizePattern(@Nullable String pattern) { + if (pattern == null) { + return pattern; } - contentPattern = contentPattern.trim(); + pattern = pattern.trim(); - if (contentPattern.isEmpty()) { + if (pattern.isEmpty()) { return null; } - return contentPattern; + return pattern; } private static final String DEFAULT_NAME_PREFIX = LicenseHeaderStep.class.getName(); @@ -195,6 +201,7 @@ private static class Runtime implements Serializable { private static final long serialVersionUID = 1475199492829130965L; private final Pattern delimiterPattern; + private final @Nullable Pattern skipLinesMatching; private final String yearSepOrFull; private final @Nullable String yearToday; private final @Nullable String beforeYear; @@ -203,7 +210,7 @@ private static class Runtime implements Serializable { private final boolean licenseHeaderWithRange; /** The license that we'd like enforced. */ - private Runtime(String licenseHeader, String delimiter, String yearSeparator, boolean updateYearWithLatest) { + private Runtime(String licenseHeader, String delimiter, String yearSeparator, boolean updateYearWithLatest, @Nullable String skipLinesMatching) { if (delimiter.contains("\n")) { throw new IllegalArgumentException("The delimiter must not contain any newlines."); } @@ -213,6 +220,7 @@ private Runtime(String licenseHeader, String delimiter, String yearSeparator, bo licenseHeader = licenseHeader + "\n"; } this.delimiterPattern = Pattern.compile('^' + delimiter, Pattern.UNIX_LINES | Pattern.MULTILINE); + this.skipLinesMatching = skipLinesMatching == null ? null : Pattern.compile(skipLinesMatching); Optional yearToken = getYearToken(licenseHeader); if (yearToken.isPresent()) { @@ -254,6 +262,31 @@ private static Optional getYearToken(String licenseHeader) { /** Formats the given string. */ private String format(String raw) { + if (skipLinesMatching == null) { + return addOrUpdateLicenseHeader(raw); + } else { + String[] lines = raw.split("\n"); + StringBuilder skippedLinesBuilder = new StringBuilder(); + StringBuilder remainingLinesBuilder = new StringBuilder(); + boolean lastMatched = true; + for (String line : lines) { + if (lastMatched) { + Matcher matcher = skipLinesMatching.matcher(line); + if (matcher.find()) { + skippedLinesBuilder.append(line).append('\n'); + } else { + remainingLinesBuilder.append(line).append('\n'); + lastMatched = false; + } + } else { + remainingLinesBuilder.append(line).append('\n'); + } + } + return skippedLinesBuilder + addOrUpdateLicenseHeader(remainingLinesBuilder.toString()); + } + } + + private String addOrUpdateLicenseHeader(String raw) { Matcher contentMatcher = delimiterPattern.matcher(raw); if (!contentMatcher.find()) { throw new IllegalArgumentException("Unable to find delimiter regex " + delimiterPattern); diff --git a/lib/src/main/java/com/diffplug/spotless/kotlin/KtLintStep.java b/lib/src/main/java/com/diffplug/spotless/kotlin/KtLintStep.java index b444f0f1a7..835e997f8e 100644 --- a/lib/src/main/java/com/diffplug/spotless/kotlin/KtLintStep.java +++ b/lib/src/main/java/com/diffplug/spotless/kotlin/KtLintStep.java @@ -23,6 +23,9 @@ import java.util.Objects; import java.util.TreeMap; +import javax.annotation.Nullable; + +import com.diffplug.spotless.FileSignature; import com.diffplug.spotless.FormatterFunc; import com.diffplug.spotless.FormatterStep; import com.diffplug.spotless.JarState; @@ -33,7 +36,7 @@ public class KtLintStep { // prevent direct instantiation private KtLintStep() {} - private static final String DEFAULT_VERSION = "0.48.0"; + private static final String DEFAULT_VERSION = "0.48.1"; static final String NAME = "ktlint"; static final String PACKAGE_PRE_0_32 = "com.github.shyiko"; static final String PACKAGE = "com.pinterest"; @@ -50,24 +53,54 @@ public static FormatterStep create(String version, Provisioner provisioner) { public static FormatterStep create(String version, Provisioner provisioner, boolean useExperimental, Map userData, Map editorConfigOverride) { - return create(version, provisioner, false, useExperimental, userData, editorConfigOverride); + return create(version, provisioner, false, useExperimental, null, userData, editorConfigOverride); } public static FormatterStep createForScript(String version, Provisioner provisioner) { - return create(version, provisioner, true, false, Collections.emptyMap(), Collections.emptyMap()); + return create(version, provisioner, true, false, null, Collections.emptyMap(), Collections.emptyMap()); } - public static FormatterStep createForScript(String version, Provisioner provisioner, boolean useExperimental, - Map userData, Map editorConfigOverride) { - return create(version, provisioner, true, useExperimental, userData, editorConfigOverride); + public static FormatterStep createForScript(String version, + Provisioner provisioner, + boolean useExperimental, + @Nullable FileSignature editorConfigPath, + Map userData, + Map editorConfigOverride) { + return create(version, + provisioner, + true, + useExperimental, + editorConfigPath, + userData, + editorConfigOverride); } - private static FormatterStep create(String version, Provisioner provisioner, boolean isScript, boolean useExperimental, - Map userData, Map editorConfigOverride) { + private static FormatterStep create(String version, + Provisioner provisioner, + boolean isScript, + boolean useExperimental, + Map userData, + Map editorConfigOverride) { + return create(version, + provisioner, + useExperimental, + isScript, + null, + userData, + editorConfigOverride); + } + + public static FormatterStep create(String version, + Provisioner provisioner, + boolean isScript, + boolean useExperimental, + @Nullable FileSignature editorConfig, + Map userData, + Map editorConfigOverride) { Objects.requireNonNull(version, "version"); Objects.requireNonNull(provisioner, "provisioner"); return FormatterStep.createLazy(NAME, - () -> new State(version, provisioner, isScript, useExperimental, userData, editorConfigOverride), + () -> new State(version, provisioner, isScript, useExperimental, editorConfig, userData, editorConfigOverride), State::createFormat); } @@ -86,9 +119,16 @@ static final class State implements Serializable { private final TreeMap userData; private final TreeMap editorConfigOverride; private final String version; - - State(String version, Provisioner provisioner, boolean isScript, boolean useExperimental, - Map userData, Map editorConfigOverride) throws IOException { + @Nullable + private final FileSignature editorConfigPath; + + State(String version, + Provisioner provisioner, + boolean isScript, + boolean useExperimental, + @Nullable FileSignature editorConfigPath, + Map userData, + Map editorConfigOverride) throws IOException { this.version = version; String coordinate; @@ -104,6 +144,7 @@ static final class State implements Serializable { this.userData = new TreeMap<>(userData); this.editorConfigOverride = new TreeMap<>(editorConfigOverride); this.jarState = JarState.from(coordinate + version, provisioner); + this.editorConfigPath = editorConfigPath; this.isScript = isScript; } @@ -111,8 +152,8 @@ FormatterFunc createFormat() throws Exception { final ClassLoader classLoader = jarState.getClassLoader(); Class formatterFunc = classLoader.loadClass("com.diffplug.spotless.glue.ktlint.KtlintFormatterFunc"); Constructor constructor = formatterFunc.getConstructor( - String.class, boolean.class, boolean.class, Map.class, Map.class); - return (FormatterFunc.NeedsFile) constructor.newInstance(version, isScript, useExperimental, userData, editorConfigOverride); + String.class, boolean.class, boolean.class, FileSignature.class, Map.class, Map.class); + return (FormatterFunc.NeedsFile) constructor.newInstance(version, isScript, useExperimental, editorConfigPath, userData, editorConfigOverride); } } } diff --git a/lib/src/testCompatKtLint0Dot48Dot0/java/com/diffplug/spotless/glue/ktlint/compat/KtLintCompat0Dot48Dot0AdapterTest.java b/lib/src/testCompatKtLint0Dot48Dot0/java/com/diffplug/spotless/glue/ktlint/compat/KtLintCompat0Dot48Dot0AdapterTest.java new file mode 100644 index 0000000000..6825b3d818 --- /dev/null +++ b/lib/src/testCompatKtLint0Dot48Dot0/java/com/diffplug/spotless/glue/ktlint/compat/KtLintCompat0Dot48Dot0AdapterTest.java @@ -0,0 +1,67 @@ +/* + * Copyright 2023 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.ktlint.compat; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.HashMap; +import java.util.Map; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; + +public class KtLintCompat0Dot48Dot0AdapterTest { + @Test + public void testDefaults(@TempDir Path path) throws IOException { + KtLintCompat0Dot48Dot0Adapter ktLintCompat0Dot48Dot0Adapter = new KtLintCompat0Dot48Dot0Adapter(); + String text = loadAndWriteText(path, "empty_class_body.kt"); + + Map userData = new HashMap<>(); + + Map editorConfigOverrideMap = new HashMap<>(); + + String formatted = ktLintCompat0Dot48Dot0Adapter.format(text, path, false, false, null, userData, editorConfigOverrideMap); + assertEquals("class empty_class_body\n", formatted); + } + + @Test + public void testEditorConfigCanDisable(@TempDir Path path) throws IOException { + KtLintCompat0Dot48Dot0Adapter ktLintCompat0Dot48Dot0Adapter = new KtLintCompat0Dot48Dot0Adapter(); + String text = loadAndWriteText(path, "fails_no_semicolons.kt"); + + Map userData = new HashMap<>(); + + Map editorConfigOverrideMap = new HashMap<>(); + editorConfigOverrideMap.put("indent_style", "tab"); + editorConfigOverrideMap.put("ktlint_standard_no-semi", "disabled"); + + String formatted = ktLintCompat0Dot48Dot0Adapter.format(text, path, false, false, null, userData, editorConfigOverrideMap); + assertEquals("class fails_no_semicolons {\n\tval i = 0;\n}\n", formatted); + } + + private static String loadAndWriteText(Path path, String name) throws IOException { + try (InputStream is = KtLintCompat0Dot48Dot0AdapterTest.class.getResourceAsStream("/" + name)) { + Files.copy(is, path.resolve(name)); + } + return new String(Files.readAllBytes(path.resolve(name)), StandardCharsets.UTF_8); + } + +} diff --git a/lib/src/testCompatKtLint0Dot48Dot0/resources/empty_class_body.kt b/lib/src/testCompatKtLint0Dot48Dot0/resources/empty_class_body.kt new file mode 100644 index 0000000000..b84774d572 --- /dev/null +++ b/lib/src/testCompatKtLint0Dot48Dot0/resources/empty_class_body.kt @@ -0,0 +1,3 @@ +class empty_class_body { + +} diff --git a/lib/src/testCompatKtLint0Dot48Dot0/resources/fails_no_semicolons.kt b/lib/src/testCompatKtLint0Dot48Dot0/resources/fails_no_semicolons.kt new file mode 100644 index 0000000000..20ab460913 --- /dev/null +++ b/lib/src/testCompatKtLint0Dot48Dot0/resources/fails_no_semicolons.kt @@ -0,0 +1,3 @@ +class fails_no_semicolons { + val i = 0; +} diff --git a/plugin-gradle/CHANGES.md b/plugin-gradle/CHANGES.md index bb05d07554..439b074caf 100644 --- a/plugin-gradle/CHANGES.md +++ b/plugin-gradle/CHANGES.md @@ -4,11 +4,15 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format ( ## [Unreleased] ### Added +* Add option `editorConfigFile` for `ktLint` [#142](https://github.com/diffplug/spotless/issues/142) +* Added `skipLinesMatching` option to `licenseHeader` to support formats where license header cannot be immediately added to the top of the file (e.g. xml, sh). ([#1441](https://github.com/diffplug/spotless/pull/1441)) * Added support for npm-based [ESLint](https://eslint.org/) formatter for javascript and typescript ([#1453](https://github.com/diffplug/spotless/pull/1453)) ### Fixed * Prevent tool configurations from being resolved outside project ([#1447](https://github.com/diffplug/spotless/pull/1447) fixes [#1215](https://github.com/diffplug/spotless/issues/1215)) +* Support `ktlint` 0.48+ new rule disabling syntax ([#1456](https://github.com/diffplug/spotless/pull/1456)) fixes ([#1444](https://github.com/diffplug/spotless/issues/1444)) ### Changes -* Bump default Version for `prettier` from `2.0.5` to `2.8.1` +* Bump default `ktlint` version to latest `0.47.1` -> `0.48.1` ([#1456](https://github.com/diffplug/spotless/pull/1456)) +* Bump default version for `prettier` from `2.0.5` to `2.8.1` ([#1453](https://github.com/diffplug/spotless/pull/1453)) ## [6.12.1] - 2023-01-02 ### Fixed diff --git a/plugin-gradle/README.md b/plugin-gradle/README.md index 1e34cdc88a..1ed2b942b5 100644 --- a/plugin-gradle/README.md +++ b/plugin-gradle/README.md @@ -355,7 +355,14 @@ spotless { ### ktlint -[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 `editorConfigOverride`. +[homepage](https://github.com/pinterest/ktlint). [changelog](https://github.com/pinterest/ktlint/releases). + +Spotless respects the `.editorconfig` settings by providing `editorConfigPath` option. +([ktlint docs](https://github.com/pinterest/ktlint#editorconfig)). +Default value is the `.editorconfig` file located in the top project. +Passing `null` will clear the option. + +Additionally, `editorConfigOverride` options will override what's supplied in `.editorconfig` file. ```kotlin spotless { @@ -364,6 +371,7 @@ spotless { ktlint("0.45.2") .setUseExperimental(true) .userData(mapOf("android" to "true")) + .editorConfigPath("$projectDir/config/.editorconfig") // sample unusual placement .editorConfigOverride(mapOf("indent_size" to 2)) } } @@ -961,6 +969,12 @@ See the [javadoc](https://javadoc.io/doc/com.diffplug.spotless/spotless-plugin-g 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. +### Files with fixed header lines + +Some files have fixed header lines (e.g. ` ## How can I enforce formatting gradually? (aka "ratchet") diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java index c72c9339a0..4e33c45ed0 100644 --- a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java +++ b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java @@ -463,6 +463,12 @@ public LicenseHeaderConfig yearSeparator(String yearSeparator) { return this; } + public LicenseHeaderConfig skipLinesMatching(String skipLinesMatching) { + builder = builder.withSkipLinesMatching(skipLinesMatching); + replaceStep(createStep()); + return this; + } + /** * @param updateYearWithLatest * Will turn {@code 2004} into {@code 2004-2020}, and {@code 2004-2019} into {@code 2004-2020} diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/KotlinExtension.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/KotlinExtension.java index 546efab46d..5d1c484521 100644 --- a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/KotlinExtension.java +++ b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/KotlinExtension.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2022 DiffPlug + * Copyright 2016-2023 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,12 +17,14 @@ import static com.diffplug.spotless.kotlin.KotlinConstants.LICENSE_HEADER_DELIMITER; +import java.io.File; import java.io.IOException; import java.util.Collections; import java.util.Map; import java.util.Objects; import java.util.function.Consumer; +import javax.annotation.Nullable; import javax.inject.Inject; import org.gradle.api.GradleException; @@ -58,12 +60,14 @@ public LicenseHeaderConfig licenseHeaderFile(Object licenseHeaderFile) { } /** Adds the specified version of ktlint. */ - public KotlinFormatExtension ktlint(String version) { + public KotlinFormatExtension ktlint(String version) throws IOException { Objects.requireNonNull(version); - return new KotlinFormatExtension(version, false, Collections.emptyMap(), Collections.emptyMap()); + File defaultEditorConfig = getProject().getRootProject().file(".editorconfig"); + FileSignature editorConfigPath = FileSignature.signAsList(defaultEditorConfig); + return new KotlinFormatExtension(version, false, editorConfigPath, Collections.emptyMap(), Collections.emptyMap()); } - public KotlinFormatExtension ktlint() { + public KotlinFormatExtension ktlint() throws IOException { return ktlint(KtLintStep.defaultVersion()); } @@ -71,13 +75,16 @@ public class KotlinFormatExtension { private final String version; private boolean useExperimental; + @Nullable + private FileSignature editorConfigPath; private Map userData; private Map editorConfigOverride; - KotlinFormatExtension(String version, boolean useExperimental, Map config, + KotlinFormatExtension(String version, boolean useExperimental, @Nullable FileSignature editorConfigPath, Map config, Map editorConfigOverride) { this.version = version; this.useExperimental = useExperimental; + this.editorConfigPath = editorConfigPath; this.userData = config; this.editorConfigOverride = editorConfigOverride; addStep(createStep()); @@ -89,6 +96,16 @@ public KotlinFormatExtension setUseExperimental(boolean useExperimental) { return this; } + public KotlinFormatExtension setEditorConfigPath(Object editorConfigFile) throws IOException { + if (editorConfigFile == null) { + this.editorConfigPath = null; + } else { + this.editorConfigPath = FileSignature.signAsList(getProject().file(editorConfigFile)); + } + replaceStep(createStep()); + return this; + } + public KotlinFormatExtension userData(Map userData) { // Copy the map to a sorted map because up-to-date checking is based on binary-equals of the serialized // representation. @@ -106,7 +123,7 @@ public KotlinFormatExtension editorConfigOverride(Map editorConf } private FormatterStep createStep() { - return KtLintStep.create(version, provisioner(), useExperimental, userData, editorConfigOverride); + return KtLintStep.create(version, provisioner(), useExperimental, false, editorConfigPath, userData, editorConfigOverride); } } diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/KotlinGradleExtension.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/KotlinGradleExtension.java index c1abe62bd1..82a8edd9a5 100644 --- a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/KotlinGradleExtension.java +++ b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/KotlinGradleExtension.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2022 DiffPlug + * Copyright 2016-2023 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,12 +15,14 @@ */ package com.diffplug.gradle.spotless; +import java.io.File; import java.io.IOException; import java.util.Collections; import java.util.Map; import java.util.Objects; import java.util.function.Consumer; +import javax.annotation.Nullable; import javax.inject.Inject; import com.diffplug.common.collect.ImmutableSortedMap; @@ -43,12 +45,14 @@ public KotlinGradleExtension(SpotlessExtension spotless) { } /** Adds the specified version of ktlint. */ - public KotlinFormatExtension ktlint(String version) { + public KotlinFormatExtension ktlint(String version) throws IOException { Objects.requireNonNull(version, "version"); - return new KotlinFormatExtension(version, false, Collections.emptyMap(), Collections.emptyMap()); + File defaultEditorConfig = getProject().getRootProject().file(".editorconfig"); + FileSignature editorConfigPath = FileSignature.signAsList(defaultEditorConfig); + return new KotlinFormatExtension(version, false, editorConfigPath, Collections.emptyMap(), Collections.emptyMap()); } - public KotlinFormatExtension ktlint() { + public KotlinFormatExtension ktlint() throws IOException { return ktlint(KtLintStep.defaultVersion()); } @@ -56,18 +60,32 @@ public class KotlinFormatExtension { private final String version; private boolean useExperimental; + @Nullable + private FileSignature editorConfigPath; private Map userData; private Map editorConfigOverride; - KotlinFormatExtension(String version, boolean useExperimental, Map config, + KotlinFormatExtension(String version, boolean useExperimental, FileSignature editorConfigPath, Map config, Map editorConfigOverride) { this.version = version; this.useExperimental = useExperimental; + this.editorConfigPath = editorConfigPath; this.userData = config; this.editorConfigOverride = editorConfigOverride; addStep(createStep()); } + public KotlinFormatExtension setEditorConfigPath(Object editorConfigPath) throws IOException { + + if (editorConfigPath == null) { + this.editorConfigPath = null; + } else { + this.editorConfigPath = FileSignature.signAsList(getProject().file(editorConfigPath)); + } + replaceStep(createStep()); + return this; + } + public KotlinFormatExtension setUseExperimental(boolean useExperimental) { this.useExperimental = useExperimental; replaceStep(createStep()); @@ -91,7 +109,13 @@ public KotlinFormatExtension editorConfigOverride(Map editorConf } private FormatterStep createStep() { - return KtLintStep.createForScript(version, provisioner(), useExperimental, userData, editorConfigOverride); + return KtLintStep.createForScript( + version, + provisioner(), + useExperimental, + editorConfigPath, + userData, + editorConfigOverride); } } diff --git a/plugin-maven/CHANGES.md b/plugin-maven/CHANGES.md index 4f5d30cb74..c2c9c5e368 100644 --- a/plugin-maven/CHANGES.md +++ b/plugin-maven/CHANGES.md @@ -4,13 +4,20 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format ( ## [Unreleased] ### Added +* Add option `editorConfigFile` for `ktLint` [#142](https://github.com/diffplug/spotless/issues/142) +* Added `skipLinesMatching` option to `licenseHeader` to support formats where license header cannot be immediately added to the top of the file (e.g. xml, sh). ([#1441](https://github.com/diffplug/spotless/pull/1441)) +### Fixed +* Support `ktlint` 0.48+ new rule disabling syntax ([#1456](https://github.com/diffplug/spotless/pull/1456)) fixes ([#1444](https://github.com/diffplug/spotless/issues/1444)) * Added support for npm-based [ESLint](https://eslint.org/)-formatter for javascript and typescript ([#1453](https://github.com/diffplug/spotless/pull/1453)) ### Changes -* Bump default Version for `prettier` from `2.0.5` to `2.8.1` +* Bump default `ktlint` version to latest `0.47.1` -> `0.48.1` ([#1456](https://github.com/diffplug/spotless/pull/1456)) +* Reduce spurious invalidations of the up-to-date index file ([#1461](https://github.com/diffplug/spotless/pull/1461)) +* Bump default version for `prettier` from `2.0.5` to `2.8.1` ([#1453](https://github.com/diffplug/spotless/pull/1453)) ## [2.29.0] - 2023-01-02 ### Added * Added support for M2E's incremental compilation ([#1414](https://github.com/diffplug/spotless/pull/1414) fixes [#1413](https://github.com/diffplug/spotless/issues/1413)) +* Add JSON support ([#1446](https://github.com/diffplug/spotless/pull/1446)) ### Fixed * Improve memory usage when using git ratchet ([#1426](https://github.com/diffplug/spotless/pull/1426)) * Support `ktlint` 0.48+ ([#1432](https://github.com/diffplug/spotless/pull/1432)) fixes ([#1430](https://github.com/diffplug/spotless/issues/1430)) diff --git a/plugin-maven/README.md b/plugin-maven/README.md index b246bcb035..dcf9df45d9 100644 --- a/plugin-maven/README.md +++ b/plugin-maven/README.md @@ -59,6 +59,7 @@ user@machine repo % mvn spotless:check - [Markdown](#markdown) ([flexmark](#flexmark)) - [Typescript](#typescript) ([tsfmt](#tsfmt), [prettier](#prettier), [ESLint](#eslint--typescript-)) - [Javascript](#javascript) ([prettier](#prettier), [ESLint](#eslint--javascript-)) + - [JSON](#json) - Multiple languages - [Prettier](#prettier) ([plugins](#prettier-plugins), [npm detection](#npm-detection), [`.npmrc` detection](#npmrc-detection)) - [eclipse web tools platform](#eclipse-web-tools-platform) @@ -129,7 +130,16 @@ To use it in your pom, just [add the Spotless dependency](https://search.maven.o 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). - +- **order matters**, and this is good! (More info [here](https://github.com/diffplug/spotless/blob/main/PADDEDCELL.md) and [here](https://github.com/diffplug/spotless/blob/main/CONTRIBUTING.md#how-spotless-works)) + - For example, `googleJavaFormat` always indents with spaces, but some wish it had a tab mode + - ```xml + // this works + true2 + ``` + - ```xml + true2 + // the tab indentation gets overwritten + ``` ### Requirements @@ -179,6 +189,10 @@ any other maven phase (i.e. compile) then it can be configured as below; src/test/java/**/*.java + + + + false @@ -188,10 +202,6 @@ any other maven phase (i.e. compile) then it can be configured as below; - - - - @@ -355,7 +365,13 @@ Groovy-Eclipse formatting errors/warnings lead per default to a build failure. T ### 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. +[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 respects the `.editorconfig` settings by providing `editorConfigPath` option. +([ktlint docs](https://github.com/pinterest/ktlint#editorconfig)). + +Additionally, `editorConfigOverride` options will override what's supplied in `.editorconfig` file. ```xml @@ -432,7 +448,7 @@ Groovy-Eclipse formatting errors/warnings lead per default to a build failure. T - src/native/** + src/native/** @@ -760,7 +776,6 @@ styleguides and the requirement for a tsconfigFile. For details, see the [npm detection](#npm-detection) and [`.npmrc` detection](#npmrc-detection) sections of prettier, which apply also to ESLint. - ## Javascript @@ -784,7 +799,6 @@ For details, see the [npm detection](#npm-detection) and [`.npmrc` detection](#n ``` - ### ESLint (Javascript) [npm](https://www.npmjs.com/package/eslint). [changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md). *Please note:* @@ -840,6 +854,55 @@ styleguides and no requirement for a tsconfig (of course). For details, see the [npm detection](#npm-detection) and [`.npmrc` detection](#npmrc-detection) sections of prettier, which apply also to ESLint. +## JSON + +- `com.diffplug.spotless.maven.json.Json` [code](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/json/json.java) + +```xml + + + + src/**/*.json + + + + + + +``` + +### simple + +Uses a JSON pretty-printer that optionally allows configuring the number of spaces that are used to pretty print objects: + +```xml + + 4 + +``` + +### Gson + +Uses Google Gson to also allow sorting by keys besides custom indentation - useful for i18n files. + +```xml + + 4 + false + false + 2.8.1 + +``` + +Notes: +* There's no option in Gson to leave HTML as-is (i.e. escaped HTML would remain escaped, raw would remain raw). Either +all HTML characters are written escaped or none. Set `escapeHtml` if you prefer the former. +* `sortByKeys` will apply lexicographic order on the keys of the input JSON. See the +[javadoc of String](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/String.html#compareTo(java.lang.String)) +for details. + + + ## Prettier [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, ...). @@ -1094,6 +1157,12 @@ Once a file's license header has a valid year, whether it is a year (`2020`) or 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. +### Files with fixed header lines + +Some files have fixed header lines (e.g. `^#!.+?$` to skip shebangs). + diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/generic/LicenseHeader.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/generic/LicenseHeader.java index ee2ae4fda0..ff89f55ead 100644 --- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/generic/LicenseHeader.java +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/generic/LicenseHeader.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 DiffPlug + * Copyright 2016-2023 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -37,6 +37,9 @@ public class LicenseHeader implements FormatterStepFactory { @Parameter private String delimiter; + @Parameter + private String skipLinesMatching; + @Override public final FormatterStep newFormatterStep(FormatterStepConfig config) { String delimiterString = delimiter != null ? delimiter : config.getLicenseHeaderDelimiter(); @@ -53,6 +56,7 @@ public final FormatterStep newFormatterStep(FormatterStepConfig config) { } return LicenseHeaderStep.headerDelimiter(() -> readFileOrContent(config), delimiterString) .withYearMode(yearMode) + .withSkipLinesMatching(skipLinesMatching) .build() .filterByFile(LicenseHeaderStep.unsupportedJvmFilesFilter()); } else { diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/incremental/FileIndex.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/incremental/FileIndex.java index 728f8a57bc..8330319cfb 100644 --- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/incremental/FileIndex.java +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/incremental/FileIndex.java @@ -1,5 +1,5 @@ /* - * Copyright 2021 DiffPlug + * Copyright 2021-2023 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -76,7 +76,7 @@ static FileIndex read(FileIndexConfig config, Log log) { PluginFingerprint computedFingerprint = config.getPluginFingerprint(); PluginFingerprint storedFingerprint = PluginFingerprint.from(firstLine); if (!computedFingerprint.equals(storedFingerprint)) { - log.info("Fingerprint mismatch in the index file. Fallback to an empty index"); + log.info("Index file corresponds to a different configuration of the plugin. Either the plugin version or its configuration has changed. Fallback to an empty index"); return emptyIndexFallback(config); } else { Content content = readIndexContent(reader, config.getProjectDir(), log); diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/incremental/PluginFingerprint.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/incremental/PluginFingerprint.java index 3805cf4600..9efd6f2586 100644 --- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/incremental/PluginFingerprint.java +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/incremental/PluginFingerprint.java @@ -1,5 +1,5 @@ /* - * Copyright 2021-2022 DiffPlug + * Copyright 2021-2023 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,17 +17,21 @@ import java.io.IOException; import java.io.UncheckedIOException; -import java.util.ArrayList; import java.util.Base64; -import java.util.List; import java.util.Objects; -import org.apache.maven.model.Dependency; import org.apache.maven.model.Plugin; import org.apache.maven.project.MavenProject; import com.diffplug.spotless.Formatter; +/** + * Represents a particular Spotless Maven plugin setup using a Base64-encoded serialized form of: + *
    + *
  1. Plugin version as configured in the POM
  2. + *
  3. Formatter instances created according to the POM configuration
  4. + *
+ */ class PluginFingerprint { private static final String SPOTLESS_PLUGIN_KEY = "com.diffplug.spotless:spotless-maven-plugin"; @@ -83,12 +87,8 @@ public String toString() { } private static byte[] digest(Plugin plugin, Iterable formatters) { - // dependencies can be an unserializable org.apache.maven.model.merge.ModelMerger$MergingList - // replace it with a serializable ArrayList - List dependencies = plugin.getDependencies(); - plugin.setDependencies(new ArrayList<>(dependencies)); try (ObjectDigestOutputStream out = ObjectDigestOutputStream.create()) { - out.writeObject(plugin); + out.writeObject(plugin.getVersion()); for (Formatter formatter : formatters) { out.writeObject(formatter); } @@ -96,9 +96,6 @@ private static byte[] digest(Plugin plugin, Iterable formatters) { return out.digest(); } catch (IOException e) { throw new UncheckedIOException("Unable to serialize plugin " + plugin, e); - } finally { - // reset the original list - plugin.setDependencies(dependencies); } } } diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/json/Gson.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/json/Gson.java new file mode 100644 index 0000000000..7962ecb1f7 --- /dev/null +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/json/Gson.java @@ -0,0 +1,45 @@ +/* + * Copyright 2023 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.maven.json; + +import org.apache.maven.plugins.annotations.Parameter; + +import com.diffplug.spotless.FormatterStep; +import com.diffplug.spotless.json.gson.GsonStep; +import com.diffplug.spotless.maven.FormatterStepConfig; +import com.diffplug.spotless.maven.FormatterStepFactory; + +public class Gson implements FormatterStepFactory { + private static final String DEFAULT_GSON_VERSION = "2.8.9"; + + @Parameter + int indentSpaces = Json.DEFAULT_INDENTATION; + + @Parameter + boolean sortByKeys = false; + + @Parameter + boolean escapeHtml = false; + + @Parameter + String version = DEFAULT_GSON_VERSION; + + @Override + public FormatterStep newFormatterStep(FormatterStepConfig stepConfig) { + int indentSpaces = this.indentSpaces; + return GsonStep.create(indentSpaces, sortByKeys, escapeHtml, version, stepConfig.getProvisioner()); + } +} diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/json/Json.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/json/Json.java new file mode 100644 index 0000000000..c326525d0c --- /dev/null +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/json/Json.java @@ -0,0 +1,47 @@ +/* + * Copyright 2023 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.maven.json; + +import java.util.Collections; +import java.util.Set; + +import com.diffplug.spotless.maven.FormatterFactory; + +/** + * A {@link FormatterFactory} implementation that corresponds to {@code ...} configuration element. + */ +public class Json extends FormatterFactory { + public static final int DEFAULT_INDENTATION = 4; + + @Override + public Set defaultIncludes() { + return Collections.emptySet(); + } + + @Override + public String licenseHeaderDelimiter() { + return null; + } + + public void addSimple(Simple simple) { + addStepFactory(simple); + } + + public void addGson(Gson gson) { + addStepFactory(gson); + } + +} diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/json/Simple.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/json/Simple.java new file mode 100644 index 0000000000..f1cc114da2 --- /dev/null +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/json/Simple.java @@ -0,0 +1,35 @@ +/* + * Copyright 2023 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.maven.json; + +import org.apache.maven.plugins.annotations.Parameter; + +import com.diffplug.spotless.FormatterStep; +import com.diffplug.spotless.json.JsonSimpleStep; +import com.diffplug.spotless.maven.FormatterStepConfig; +import com.diffplug.spotless.maven.FormatterStepFactory; + +public class Simple implements FormatterStepFactory { + + @Parameter + int indentSpaces = Json.DEFAULT_INDENTATION; + + @Override + public FormatterStep newFormatterStep(FormatterStepConfig stepConfig) { + int indentSpaces = this.indentSpaces; + return JsonSimpleStep.create(indentSpaces, stepConfig.getProvisioner()); + } +} diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/kotlin/Ktlint.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/kotlin/Ktlint.java index 45bda05065..2825980733 100644 --- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/kotlin/Ktlint.java +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/kotlin/Ktlint.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2022 DiffPlug + * Copyright 2016-2023 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,7 +21,9 @@ import org.apache.maven.plugins.annotations.Parameter; +import com.diffplug.spotless.FileSignature; import com.diffplug.spotless.FormatterStep; +import com.diffplug.spotless.ThrowingEx; import com.diffplug.spotless.kotlin.KtLintStep; import com.diffplug.spotless.maven.FormatterStepConfig; import com.diffplug.spotless.maven.FormatterStepFactory; @@ -30,18 +32,22 @@ public class Ktlint implements FormatterStepFactory { @Parameter private String version; - + @Parameter + private String editorConfigPath; @Parameter private Map editorConfigOverride; @Override - public FormatterStep newFormatterStep(FormatterStepConfig config) { + public FormatterStep newFormatterStep(final FormatterStepConfig stepConfig) { String ktlintVersion = version != null ? version : KtLintStep.defaultVersion(); - + FileSignature configPath = null; + if (editorConfigPath != null) { + configPath = ThrowingEx.get(() -> FileSignature.signAsList(stepConfig.getFileLocator().locateFile(editorConfigPath))); + } if (editorConfigOverride == null) { editorConfigOverride = new HashMap<>(); } - return KtLintStep.create(ktlintVersion, config.getProvisioner(), false, Collections.emptyMap(), editorConfigOverride); + return KtLintStep.create(ktlintVersion, stepConfig.getProvisioner(), false, false, configPath, Collections.emptyMap(), editorConfigOverride); } } diff --git a/plugin-maven/src/test/java/com/diffplug/spotless/maven/MavenIntegrationHarness.java b/plugin-maven/src/test/java/com/diffplug/spotless/maven/MavenIntegrationHarness.java index d9a23cdb74..33d63296c4 100644 --- a/plugin-maven/src/test/java/com/diffplug/spotless/maven/MavenIntegrationHarness.java +++ b/plugin-maven/src/test/java/com/diffplug/spotless/maven/MavenIntegrationHarness.java @@ -160,6 +160,10 @@ protected void writePomWithMarkdownSteps(String... steps) throws IOException { writePom(groupWithSteps("markdown", including("**/*.md"), steps)); } + protected void writePomWithJsonSteps(String... steps) throws IOException { + writePom(groupWithSteps("json", including("**/*.json"), steps)); + } + protected void writePom(String... configuration) throws IOException { writePom(null, configuration, null); } diff --git a/plugin-maven/src/test/java/com/diffplug/spotless/maven/incremental/FileIndexTest.java b/plugin-maven/src/test/java/com/diffplug/spotless/maven/incremental/FileIndexTest.java index ce9c0077e8..8cd5e8a2f7 100644 --- a/plugin-maven/src/test/java/com/diffplug/spotless/maven/incremental/FileIndexTest.java +++ b/plugin-maven/src/test/java/com/diffplug/spotless/maven/incremental/FileIndexTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2021 DiffPlug + * Copyright 2021-2023 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -60,7 +60,7 @@ void readFallsBackToEmptyIndexOnFingerprintMismatch() throws Exception { FileIndex index = FileIndex.read(config, log); assertThat(index.size()).isZero(); - verify(log).info("Fingerprint mismatch in the index file. Fallback to an empty index"); + verify(log).info("Index file corresponds to a different configuration of the plugin. Either the plugin version or its configuration has changed. Fallback to an empty index"); } @Test diff --git a/plugin-maven/src/test/java/com/diffplug/spotless/maven/incremental/PluginFingerprintTest.java b/plugin-maven/src/test/java/com/diffplug/spotless/maven/incremental/PluginFingerprintTest.java index 90e59d657e..c344580d37 100644 --- a/plugin-maven/src/test/java/com/diffplug/spotless/maven/incremental/PluginFingerprintTest.java +++ b/plugin-maven/src/test/java/com/diffplug/spotless/maven/incremental/PluginFingerprintTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2021-2022 DiffPlug + * Copyright 2021-2023 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -43,126 +43,22 @@ class PluginFingerprintTest extends MavenIntegrationHarness { private static final String VERSION_1 = "1.0.0"; private static final String VERSION_2 = "2.0.0"; - private static final String[] EXECUTION_1 = { - "", - " check", - " ", - " check", - " ", - "" - }; - private static final String[] EXECUTION_2 = {}; - - private static final String[] CONFIGURATION_1 = { - "", - " 1.2", - "" - }; - private static final String[] CONFIGURATION_2 = { - "", - " 1.8", - " true", - "" - }; - - private static final String[] DEPENDENCIES_1 = { - "", - " ", - " unknown", - " unknown", - " 1.0", - " ", - "" - }; - private static final String[] DEPENDENCIES_2 = { - "", - " ", - " unknown", - " unknown", - " 2.0", - " ", - "" - }; - private static final List FORMATTERS = singletonList(formatter(formatterStep("default"))); @Test - void sameFingerprint() throws Exception { - String xml1 = createPomXmlContent(VERSION_1, EXECUTION_1, CONFIGURATION_1); - String xml2 = createPomXmlContent(VERSION_1, EXECUTION_1, CONFIGURATION_1); + void sameFingerprintWhenVersionAndFormattersAreTheSame() throws Exception { + MavenProject project = mavenProject(VERSION_1); - MavenProject project1 = mavenProject(xml1); - MavenProject project2 = mavenProject(xml2); - - PluginFingerprint fingerprint1 = PluginFingerprint.from(project1, FORMATTERS); - PluginFingerprint fingerprint2 = PluginFingerprint.from(project2, FORMATTERS); + PluginFingerprint fingerprint1 = PluginFingerprint.from(project, FORMATTERS); + PluginFingerprint fingerprint2 = PluginFingerprint.from(project, FORMATTERS); assertThat(fingerprint1).isEqualTo(fingerprint2); } @Test - void sameFingerprintWithDependencies() throws Exception { - String xml1 = createPomXmlContent(VERSION_1, EXECUTION_1, CONFIGURATION_1, DEPENDENCIES_1); - String xml2 = createPomXmlContent(VERSION_1, EXECUTION_1, CONFIGURATION_1, DEPENDENCIES_1); - - MavenProject project1 = mavenProject(xml1); - MavenProject project2 = mavenProject(xml2); - - PluginFingerprint fingerprint1 = PluginFingerprint.from(project1, FORMATTERS); - PluginFingerprint fingerprint2 = PluginFingerprint.from(project2, FORMATTERS); - - assertThat(fingerprint1).isEqualTo(fingerprint2); - } - - @Test - void differentFingerprintForDifferentDependencies() throws Exception { - String xml1 = createPomXmlContent(VERSION_1, EXECUTION_1, CONFIGURATION_1, DEPENDENCIES_1); - String xml2 = createPomXmlContent(VERSION_1, EXECUTION_1, CONFIGURATION_1, DEPENDENCIES_2); - - MavenProject project1 = mavenProject(xml1); - MavenProject project2 = mavenProject(xml2); - - PluginFingerprint fingerprint1 = PluginFingerprint.from(project1, FORMATTERS); - PluginFingerprint fingerprint2 = PluginFingerprint.from(project2, FORMATTERS); - - assertThat(fingerprint1).isNotEqualTo(fingerprint2); - } - - @Test - void differentFingerprintForDifferentPluginVersion() throws Exception { - String xml1 = createPomXmlContent(VERSION_1, EXECUTION_1, CONFIGURATION_1); - String xml2 = createPomXmlContent(VERSION_2, EXECUTION_1, CONFIGURATION_1); - - MavenProject project1 = mavenProject(xml1); - MavenProject project2 = mavenProject(xml2); - - PluginFingerprint fingerprint1 = PluginFingerprint.from(project1, FORMATTERS); - PluginFingerprint fingerprint2 = PluginFingerprint.from(project2, FORMATTERS); - - assertThat(fingerprint1).isNotEqualTo(fingerprint2); - } - - @Test - void differentFingerprintForDifferentExecution() throws Exception { - String xml1 = createPomXmlContent(VERSION_2, EXECUTION_1, CONFIGURATION_1); - String xml2 = createPomXmlContent(VERSION_2, EXECUTION_2, CONFIGURATION_1); - - MavenProject project1 = mavenProject(xml1); - MavenProject project2 = mavenProject(xml2); - - PluginFingerprint fingerprint1 = PluginFingerprint.from(project1, FORMATTERS); - PluginFingerprint fingerprint2 = PluginFingerprint.from(project2, FORMATTERS); - - assertThat(fingerprint1).isNotEqualTo(fingerprint2); - } - - @Test - void differentFingerprintForDifferentConfiguration() throws Exception { - String xml1 = createPomXmlContent(VERSION_1, EXECUTION_2, CONFIGURATION_2); - String xml2 = createPomXmlContent(VERSION_1, EXECUTION_2, CONFIGURATION_1); - - MavenProject project1 = mavenProject(xml1); - MavenProject project2 = mavenProject(xml2); + void differentFingerprintForDifferentPluginVersions() throws Exception { + MavenProject project1 = mavenProject(VERSION_1); + MavenProject project2 = mavenProject(VERSION_2); PluginFingerprint fingerprint1 = PluginFingerprint.from(project1, FORMATTERS); PluginFingerprint fingerprint2 = PluginFingerprint.from(project2, FORMATTERS); @@ -172,11 +68,8 @@ void differentFingerprintForDifferentConfiguration() throws Exception { @Test void differentFingerprintForFormattersWithDifferentSteps() throws Exception { - String xml1 = createPomXmlContent(VERSION_1, EXECUTION_1, CONFIGURATION_1); - String xml2 = createPomXmlContent(VERSION_1, EXECUTION_1, CONFIGURATION_1); - - MavenProject project1 = mavenProject(xml1); - MavenProject project2 = mavenProject(xml2); + MavenProject project1 = mavenProject(VERSION_1); + MavenProject project2 = mavenProject(VERSION_1); FormatterStep step1 = formatterStep("step1"); FormatterStep step2 = formatterStep("step2"); @@ -192,11 +85,8 @@ void differentFingerprintForFormattersWithDifferentSteps() throws Exception { @Test void differentFingerprintForFormattersWithDifferentLineEndings() throws Exception { - String xml1 = createPomXmlContent(VERSION_1, EXECUTION_1, CONFIGURATION_1); - String xml2 = createPomXmlContent(VERSION_1, EXECUTION_1, CONFIGURATION_1); - - MavenProject project1 = mavenProject(xml1); - MavenProject project2 = mavenProject(xml2); + MavenProject project1 = mavenProject(VERSION_1); + MavenProject project2 = mavenProject(VERSION_1); FormatterStep step = formatterStep("step"); List formatters1 = singletonList(formatter(LineEnding.UNIX, step)); @@ -224,7 +114,8 @@ void failsWhenProjectDoesNotContainSpotlessPlugin() { .hasMessageContaining("Spotless plugin absent from the project"); } - private static MavenProject mavenProject(String xml) throws Exception { + private MavenProject mavenProject(String spotlessVersion) throws Exception { + String xml = createPomXmlContent(spotlessVersion, new String[0], new String[0]); return new MavenProject(readPom(xml)); } diff --git a/plugin-maven/src/test/java/com/diffplug/spotless/maven/json/JsonTest.java b/plugin-maven/src/test/java/com/diffplug/spotless/maven/json/JsonTest.java new file mode 100644 index 0000000000..fe6560cbec --- /dev/null +++ b/plugin-maven/src/test/java/com/diffplug/spotless/maven/json/JsonTest.java @@ -0,0 +1,40 @@ +/* + * Copyright 2023 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.maven.json; + +import org.junit.jupiter.api.Test; + +import com.diffplug.spotless.maven.MavenIntegrationHarness; + +public class JsonTest extends MavenIntegrationHarness { + @Test + public void testFormatJson_WithSimple_defaultConfig() throws Exception { + writePomWithJsonSteps(""); + + setFile("json_test.json").toResource("json/sortByKeysBefore.json"); + mavenRunner().withArguments("spotless:apply").runNoError().error(); + assertFile("json_test.json").sameAsResource("json/sortByKeysAfterDisabled.json"); + } + + @Test + public void testFormatJson_WithGson_defaultConfig() throws Exception { + writePomWithJsonSteps(""); + + setFile("json_test.json").toResource("json/sortByKeysBefore.json"); + mavenRunner().withArguments("spotless:apply").runNoError().error(); + assertFile("json_test.json").sameAsResource("json/sortByKeysAfterDisabled.json"); + } +} diff --git a/settings.gradle b/settings.gradle index 786baa1eba..741e4b6ccc 100644 --- a/settings.gradle +++ b/settings.gradle @@ -16,7 +16,7 @@ pluginManagement { // https://github.com/radarsh/gradle-test-logger-plugin/blob/develop/CHANGELOG.md id 'com.adarshr.test-logger' version '3.2.0' // https://github.com/davidburstrom/version-compatibility-gradle-plugin/tags - id 'io.github.davidburstrom.version-compatibility' version '0.3.0' + id 'io.github.davidburstrom.version-compatibility' version '0.4.0' } } plugins { diff --git a/testlib/src/main/resources/license/SkipLines.test b/testlib/src/main/resources/license/SkipLines.test new file mode 100644 index 0000000000..4048868ac6 --- /dev/null +++ b/testlib/src/main/resources/license/SkipLines.test @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/testlib/src/main/resources/license/SkipLinesHasLicense.test b/testlib/src/main/resources/license/SkipLinesHasLicense.test new file mode 100644 index 0000000000..f645c5b2e2 --- /dev/null +++ b/testlib/src/main/resources/license/SkipLinesHasLicense.test @@ -0,0 +1,13 @@ + + + + + + + + + + diff --git a/testlib/src/test/java/com/diffplug/spotless/generic/LicenseHeaderStepTest.java b/testlib/src/test/java/com/diffplug/spotless/generic/LicenseHeaderStepTest.java index 137937beb9..2b1d0aff07 100644 --- a/testlib/src/test/java/com/diffplug/spotless/generic/LicenseHeaderStepTest.java +++ b/testlib/src/test/java/com/diffplug/spotless/generic/LicenseHeaderStepTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2022 DiffPlug + * Copyright 2016-2023 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -122,6 +122,13 @@ void should_remove_header_when_empty() throws Throwable { .test(getTestResource("license/HasLicense.test"), getTestResource("license/MissingLicense.test")); } + @Test + void should_skip_lines_matching_predefined_pattern() throws Throwable { + StepHarness.forStep(LicenseHeaderStep.headerDelimiter("", "^(?!