diff --git a/CHANGES.md b/CHANGES.md index 6d506cd2e2..5209b1dcd8 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -10,6 +10,8 @@ This document is intended for Spotless developers. We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (starting after version `1.27.0`). ## [Unreleased] +### Fixed +- `forbidWildcardImports` and `forbidModuleImports` now detect imports that have leading whitespace (indentation/tabs). ([#2939](https://github.com/diffplug/spotless/pull/2939)) ### Changes - `Formatter` no longer recomputes line-ending normalization (`LineEnding.toUnix`) a second time for every formatter step that changes content, removing redundant O(n) work from the core formatting loop. ([#2934](https://github.com/diffplug/spotless/pull/2934)) diff --git a/lib/src/main/java/com/diffplug/spotless/java/ForbidModuleImportsStep.java b/lib/src/main/java/com/diffplug/spotless/java/ForbidModuleImportsStep.java index 98098df63d..3e92080d11 100644 --- a/lib/src/main/java/com/diffplug/spotless/java/ForbidModuleImportsStep.java +++ b/lib/src/main/java/com/diffplug/spotless/java/ForbidModuleImportsStep.java @@ -1,5 +1,5 @@ /* - * Copyright 2025 DiffPlug + * Copyright 2025-2026 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,7 +24,7 @@ public final class ForbidModuleImportsStep { /** * Matches lines like 'import module java.base;' or 'import module java.sql;'. */ - private static final String REGEX = "(?m)^import module[^;\\n]*;\\R?"; + private static final String REGEX = "(?m)^[ \\t]*import\\s+module\\s+[^;\\n]*;\\R?"; private static final String NAME = "forbidModuleImports"; private static final String ERROR = "Do not use module imports - replace with specific class imports as 'spotlessApply' cannot auto-fix this"; diff --git a/lib/src/main/java/com/diffplug/spotless/java/ForbidWildcardImportsStep.java b/lib/src/main/java/com/diffplug/spotless/java/ForbidWildcardImportsStep.java index 71116768f6..73eab5be9b 100644 --- a/lib/src/main/java/com/diffplug/spotless/java/ForbidWildcardImportsStep.java +++ b/lib/src/main/java/com/diffplug/spotless/java/ForbidWildcardImportsStep.java @@ -1,5 +1,5 @@ /* - * Copyright 2025 DiffPlug + * Copyright 2025-2026 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,7 +24,7 @@ public final class ForbidWildcardImportsStep { /** * Matches lines like 'import foo.*;' or 'import static foo.*;'. */ - private static final String REGEX = "(?m)^import\\s+(?:static\\s+)?[^;\\n]*\\*;\\R?"; + private static final String REGEX = "(?m)^[ \\t]*import\\s+(?:static\\s+)?[^;\\n]*\\*;\\R?"; private static final String NAME = "forbidWildcardImports"; private static final String ERROR = "Do not use wildcard imports (e.g. java.util.*) - replace with specific class imports (e.g. java.util.List) as 'spotlessApply' cannot auto-fix this"; diff --git a/plugin-gradle/CHANGES.md b/plugin-gradle/CHANGES.md index 4393e93660..ed375603ba 100644 --- a/plugin-gradle/CHANGES.md +++ b/plugin-gradle/CHANGES.md @@ -3,6 +3,8 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (starting after version `3.27.0`). ## [Unreleased] +### Fixed +- `forbidWildcardImports` and `forbidModuleImports` now detect imports that have leading whitespace (indentation/tabs). ([#2939](https://github.com/diffplug/spotless/pull/2939)) ### Changes - Improved formatting performance by eliminating redundant per-step line-ending normalization in the core formatter loop. ([#2934](https://github.com/diffplug/spotless/pull/2934)) diff --git a/plugin-maven/CHANGES.md b/plugin-maven/CHANGES.md index e8db904b02..5a98f11888 100644 --- a/plugin-maven/CHANGES.md +++ b/plugin-maven/CHANGES.md @@ -5,6 +5,7 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format ( ## [Unreleased] ### Fixed - `spotless:apply` no longer aborts on the first file with lints; it now formats all files and reports a single aggregated lint failure across every file, matching the Gradle plugin's behavior. ([#2937](https://github.com/diffplug/spotless/pull/2937)) +- `forbidWildcardImports` and `forbidModuleImports` now detect imports that have leading whitespace (indentation/tabs). ([#2939](https://github.com/diffplug/spotless/pull/2939)) ### Changes - Improved formatting performance by eliminating redundant per-step line-ending normalization in the core formatter loop. ([#2934](https://github.com/diffplug/spotless/pull/2934)) diff --git a/testlib/src/test/java/com/diffplug/spotless/java/ForbidModuleImportsStepTest.java b/testlib/src/test/java/com/diffplug/spotless/java/ForbidModuleImportsStepTest.java new file mode 100644 index 0000000000..7ef406ea6b --- /dev/null +++ b/testlib/src/test/java/com/diffplug/spotless/java/ForbidModuleImportsStepTest.java @@ -0,0 +1,45 @@ +/* + * Copyright 2026 DiffPlug + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.diffplug.spotless.java; + +import org.junit.jupiter.api.Test; + +import com.diffplug.common.base.StringPrinter; +import com.diffplug.spotless.FormatterStep; +import com.diffplug.spotless.StepHarness; + +class ForbidModuleImportsStepTest { + @Test + void detectsModuleImport() { + FormatterStep step = ForbidModuleImportsStep.create(); + StepHarness.forStep(step) + .expectLintsOf(StringPrinter.buildStringFromLines( + "import module java.base;", + "import java.util.List;")) + .toBe("L1 forbidModuleImports(import module java.base;) Do not use module imports - replace with specific class imports as 'spotlessApply' cannot auto-fix this"); + } + + @Test + void detectsIndentedModuleImport() { + FormatterStep step = ForbidModuleImportsStep.create(); + StepHarness.forStep(step) + .expectLintsOf(StringPrinter.buildStringFromLines( + " import module java.base;", + "\timport module java.sql;")) + .toBe("L1 forbidModuleImports(import module java.base;) Do not use module imports - replace with specific class imports as 'spotlessApply' cannot auto-fix this", + "L2 forbidModuleImports(import module java.sql;) Do not use module imports - replace with specific class imports as 'spotlessApply' cannot auto-fix this"); + } +} diff --git a/testlib/src/test/java/com/diffplug/spotless/java/ForbidWildcardImportsStepTest.java b/testlib/src/test/java/com/diffplug/spotless/java/ForbidWildcardImportsStepTest.java new file mode 100644 index 0000000000..e7025a3f43 --- /dev/null +++ b/testlib/src/test/java/com/diffplug/spotless/java/ForbidWildcardImportsStepTest.java @@ -0,0 +1,47 @@ +/* + * Copyright 2026 DiffPlug + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.diffplug.spotless.java; + +import org.junit.jupiter.api.Test; + +import com.diffplug.common.base.StringPrinter; +import com.diffplug.spotless.FormatterStep; +import com.diffplug.spotless.StepHarness; + +class ForbidWildcardImportsStepTest { + @Test + void detectsPlainAndStaticWildcards() { + FormatterStep step = ForbidWildcardImportsStep.create(); + StepHarness.forStep(step) + .expectLintsOf(StringPrinter.buildStringFromLines( + "import java.util.*;", + "import static java.util.Collections.*;", + "import java.util.List;")) + .toBe("L1 forbidWildcardImports(import java.util.*;) Do not use wildcard imports (e.g. java.util.*) - replace with specific class imports (e.g. java.util.List) as 'spotlessApply' cannot auto-fix this", + "L2 forbidWildcardImports(import static java.util.Collections.*;) Do not use wildcard imports (e.g. java.util.*) - replace with specific class imports (e.g. java.util.List) as 'spotlessApply' cannot auto-fix this"); + } + + @Test + void detectsIndentedWildcardImport() { + FormatterStep step = ForbidWildcardImportsStep.create(); + StepHarness.forStep(step) + .expectLintsOf(StringPrinter.buildStringFromLines( + " import java.util.*;", + "\timport static java.util.Collections.*;")) + .toBe("L1 forbidWildcardImports(import java.util.*;) Do not use wildcard imports (e.g. java.util.*) - replace with specific class imports (e.g. java.util.List) as 'spotlessApply' cannot auto-fix this", + "L2 forbidWildcardImports(import static java.util.Collections.*;) Do not use wildcard imports (e.g. java.util.*) - replace with specific class imports (e.g. java.util.List) as 'spotlessApply' cannot auto-fix this"); + } +}