diff --git a/.gitattributes b/.gitattributes index d8127358..7b177085 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,5 +1,8 @@ +# All files default to text with LF line endings +* text eol=lf + +# Windows files always have CRLF eol +*.cmd text eol=crlf + # Test resources that need specific eol src/test/resources/org/checkstyle/autofix/recipe/newlineatendoffile/** -text - -# Force LF line endings for diff test files -*.diff text eol=lf diff --git a/config/pitest-suppressions.xml b/config/pitest-suppressions.xml index 41fa593d..7f413c54 100644 --- a/config/pitest-suppressions.xml +++ b/config/pitest-suppressions.xml @@ -460,6 +460,15 @@ header = config.getProperty(HEADER_PROPERTY); + + Header.java + org.checkstyle.autofix.recipe.Header + extractLicenseHeader + org.pitest.mutationtest.engine.gregor.mutators.experimental.ArgumentPropagationMutator + replaced call to org/checkstyle/autofix/recipe/Header::toLfLineEnding with argument + header = toLfLineEnding(Files.readString(Path.of(headerFilePath), charsetToUse)); + + Header.java org.checkstyle.autofix.recipe.Header @@ -487,6 +496,15 @@ return "Adds headers to Java source files when missing."; + + Header.java + org.checkstyle.autofix.recipe.Header + toLfLineEnding + org.pitest.mutationtest.engine.gregor.mutators.experimental.NakedReceiverMutator + replaced call to java/lang/String::replaceAll with receiver + return text.replaceAll("(?x)\\\\r(?=\\\\n)|\\r(?=\\n)", ""); + + Header.java org.checkstyle.autofix.recipe.Header @@ -505,13 +523,22 @@ return violations.removeIf(violation -> { + + Header.java + org.checkstyle.autofix.recipe.Header$HeaderVisitor + lambda$extractCurrentHeader$0 + org.pitest.mutationtest.engine.gregor.mutators.experimental.ArgumentPropagationMutator + replaced call to org/checkstyle/autofix/recipe/Header::toLfLineEnding with argument + + toLfLineEnding(comment.getSuffix()); + + Header.java org.checkstyle.autofix.recipe.Header$HeaderVisitor lambda$extractCurrentHeader$0 org.pitest.mutationtest.engine.gregor.mutators.NonVoidMethodCallMutator removed call to org/checkstyle/autofix/recipe/Header$HeaderVisitor::getCursor - return comment.printComment(getCursor()) + comment.getSuffix(); + return comment.printComment(getCursor()) @@ -1303,7 +1330,7 @@ parseErrorTag org.pitest.mutationtest.engine.gregor.mutators.NonVoidMethodCallMutator removed call to java/util/Optional::empty - Optional<CheckstyleCheck> source = Optional.empty(); + Optional<CheckstyleCheck> check = Optional.empty(); @@ -1312,7 +1339,7 @@ parseErrorTag org.pitest.mutationtest.engine.gregor.mutators.RemoveConditionalMutator_EQUAL_IF removed conditional - replaced equality check with true - if (source.isPresent()) { + if (check.isPresent()) { diff --git a/mvnw.cmd b/mvnw.cmd index 3fd2be86..2e2dbe03 100644 --- a/mvnw.cmd +++ b/mvnw.cmd @@ -1,189 +1,189 @@ -<# : batch portion -@REM ---------------------------------------------------------------------------- -@REM Licensed to the Apache Software Foundation (ASF) under one -@REM or more contributor license agreements. See the NOTICE file -@REM distributed with this work for additional information -@REM regarding copyright ownership. The ASF licenses this file -@REM to you under the Apache License, Version 2.0 (the -@REM "License"); you may not use this file except in compliance -@REM with the License. You may obtain a copy of the License at -@REM -@REM http://www.apache.org/licenses/LICENSE-2.0 -@REM -@REM Unless required by applicable law or agreed to in writing, -@REM software distributed under the License is distributed on an -@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -@REM KIND, either express or implied. See the License for the -@REM specific language governing permissions and limitations -@REM under the License. -@REM ---------------------------------------------------------------------------- - -@REM ---------------------------------------------------------------------------- -@REM Apache Maven Wrapper startup batch script, version 3.3.3 -@REM -@REM Optional ENV vars -@REM MVNW_REPOURL - repo url base for downloading maven distribution -@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven -@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output -@REM ---------------------------------------------------------------------------- - -@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0) -@SET __MVNW_CMD__= -@SET __MVNW_ERROR__= -@SET __MVNW_PSMODULEP_SAVE=%PSModulePath% -@SET PSModulePath= -@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @( - IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B) -) -@SET PSModulePath=%__MVNW_PSMODULEP_SAVE% -@SET __MVNW_PSMODULEP_SAVE= -@SET __MVNW_ARG0_NAME__= -@SET MVNW_USERNAME= -@SET MVNW_PASSWORD= -@IF NOT "%__MVNW_CMD__%"=="" ("%__MVNW_CMD__%" %*) -@echo Cannot start maven from wrapper >&2 && exit /b 1 -@GOTO :EOF -: end batch / begin powershell #> - -$ErrorActionPreference = "Stop" -if ($env:MVNW_VERBOSE -eq "true") { - $VerbosePreference = "Continue" -} - -# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties -$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl -if (!$distributionUrl) { - Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" -} - -switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) { - "maven-mvnd-*" { - $USE_MVND = $true - $distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip" - $MVN_CMD = "mvnd.cmd" - break - } - default { - $USE_MVND = $false - $MVN_CMD = $script -replace '^mvnw','mvn' - break - } -} - -# apply MVNW_REPOURL and calculate MAVEN_HOME -# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ -if ($env:MVNW_REPOURL) { - $MVNW_REPO_PATTERN = if ($USE_MVND -eq $False) { "/org/apache/maven/" } else { "/maven/mvnd/" } - $distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace "^.*$MVNW_REPO_PATTERN",'')" -} -$distributionUrlName = $distributionUrl -replace '^.*/','' -$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$','' - -$MAVEN_M2_PATH = "$HOME/.m2" -if ($env:MAVEN_USER_HOME) { - $MAVEN_M2_PATH = "$env:MAVEN_USER_HOME" -} - -if (-not (Test-Path -Path $MAVEN_M2_PATH)) { - New-Item -Path $MAVEN_M2_PATH -ItemType Directory | Out-Null -} - -$MAVEN_WRAPPER_DISTS = $null -if ((Get-Item $MAVEN_M2_PATH).Target[0] -eq $null) { - $MAVEN_WRAPPER_DISTS = "$MAVEN_M2_PATH/wrapper/dists" -} else { - $MAVEN_WRAPPER_DISTS = (Get-Item $MAVEN_M2_PATH).Target[0] + "/wrapper/dists" -} - -$MAVEN_HOME_PARENT = "$MAVEN_WRAPPER_DISTS/$distributionUrlNameMain" -$MAVEN_HOME_NAME = ([System.Security.Cryptography.SHA256]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join '' -$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME" - -if (Test-Path -Path "$MAVEN_HOME" -PathType Container) { - Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME" - Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" - exit $? -} - -if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) { - Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl" -} - -# prepare tmp dir -$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile -$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir" -$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null -trap { - if ($TMP_DOWNLOAD_DIR.Exists) { - try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } - catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } - } -} - -New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null - -# Download and Install Apache Maven -Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." -Write-Verbose "Downloading from: $distributionUrl" -Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" - -$webclient = New-Object System.Net.WebClient -if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) { - $webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD) -} -[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 -$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null - -# If specified, validate the SHA-256 sum of the Maven distribution zip file -$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum -if ($distributionSha256Sum) { - if ($USE_MVND) { - Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." - } - Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash - if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) { - Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property." - } -} - -# unzip and move -Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null - -# Find the actual extracted directory name (handles snapshots where filename != directory name) -$actualDistributionDir = "" - -# First try the expected directory name (for regular distributions) -$expectedPath = Join-Path "$TMP_DOWNLOAD_DIR" "$distributionUrlNameMain" -$expectedMvnPath = Join-Path "$expectedPath" "bin/$MVN_CMD" -if ((Test-Path -Path $expectedPath -PathType Container) -and (Test-Path -Path $expectedMvnPath -PathType Leaf)) { - $actualDistributionDir = $distributionUrlNameMain -} - -# If not found, search for any directory with the Maven executable (for snapshots) -if (!$actualDistributionDir) { - Get-ChildItem -Path "$TMP_DOWNLOAD_DIR" -Directory | ForEach-Object { - $testPath = Join-Path $_.FullName "bin/$MVN_CMD" - if (Test-Path -Path $testPath -PathType Leaf) { - $actualDistributionDir = $_.Name - } - } -} - -if (!$actualDistributionDir) { - Write-Error "Could not find Maven distribution directory in extracted archive" -} - -Write-Verbose "Found extracted Maven distribution directory: $actualDistributionDir" -Rename-Item -Path "$TMP_DOWNLOAD_DIR/$actualDistributionDir" -NewName $MAVEN_HOME_NAME | Out-Null -try { - Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null -} catch { - if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) { - Write-Error "fail to move MAVEN_HOME" - } -} finally { - try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } - catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } -} - -Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" +<# : batch portion +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Apache Maven Wrapper startup batch script, version 3.3.3 +@REM +@REM Optional ENV vars +@REM MVNW_REPOURL - repo url base for downloading maven distribution +@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output +@REM ---------------------------------------------------------------------------- + +@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0) +@SET __MVNW_CMD__= +@SET __MVNW_ERROR__= +@SET __MVNW_PSMODULEP_SAVE=%PSModulePath% +@SET PSModulePath= +@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @( + IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B) +) +@SET PSModulePath=%__MVNW_PSMODULEP_SAVE% +@SET __MVNW_PSMODULEP_SAVE= +@SET __MVNW_ARG0_NAME__= +@SET MVNW_USERNAME= +@SET MVNW_PASSWORD= +@IF NOT "%__MVNW_CMD__%"=="" ("%__MVNW_CMD__%" %*) +@echo Cannot start maven from wrapper >&2 && exit /b 1 +@GOTO :EOF +: end batch / begin powershell #> + +$ErrorActionPreference = "Stop" +if ($env:MVNW_VERBOSE -eq "true") { + $VerbosePreference = "Continue" +} + +# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties +$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl +if (!$distributionUrl) { + Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" +} + +switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) { + "maven-mvnd-*" { + $USE_MVND = $true + $distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip" + $MVN_CMD = "mvnd.cmd" + break + } + default { + $USE_MVND = $false + $MVN_CMD = $script -replace '^mvnw','mvn' + break + } +} + +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +if ($env:MVNW_REPOURL) { + $MVNW_REPO_PATTERN = if ($USE_MVND -eq $False) { "/org/apache/maven/" } else { "/maven/mvnd/" } + $distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace "^.*$MVNW_REPO_PATTERN",'')" +} +$distributionUrlName = $distributionUrl -replace '^.*/','' +$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$','' + +$MAVEN_M2_PATH = "$HOME/.m2" +if ($env:MAVEN_USER_HOME) { + $MAVEN_M2_PATH = "$env:MAVEN_USER_HOME" +} + +if (-not (Test-Path -Path $MAVEN_M2_PATH)) { + New-Item -Path $MAVEN_M2_PATH -ItemType Directory | Out-Null +} + +$MAVEN_WRAPPER_DISTS = $null +if ((Get-Item $MAVEN_M2_PATH).Target[0] -eq $null) { + $MAVEN_WRAPPER_DISTS = "$MAVEN_M2_PATH/wrapper/dists" +} else { + $MAVEN_WRAPPER_DISTS = (Get-Item $MAVEN_M2_PATH).Target[0] + "/wrapper/dists" +} + +$MAVEN_HOME_PARENT = "$MAVEN_WRAPPER_DISTS/$distributionUrlNameMain" +$MAVEN_HOME_NAME = ([System.Security.Cryptography.SHA256]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join '' +$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME" + +if (Test-Path -Path "$MAVEN_HOME" -PathType Container) { + Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME" + Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" + exit $? +} + +if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) { + Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl" +} + +# prepare tmp dir +$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile +$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir" +$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null +trap { + if ($TMP_DOWNLOAD_DIR.Exists) { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } + } +} + +New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null + +# Download and Install Apache Maven +Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +Write-Verbose "Downloading from: $distributionUrl" +Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +$webclient = New-Object System.Net.WebClient +if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) { + $webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD) +} +[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 +$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null + +# If specified, validate the SHA-256 sum of the Maven distribution zip file +$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum +if ($distributionSha256Sum) { + if ($USE_MVND) { + Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." + } + Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash + if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) { + Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property." + } +} + +# unzip and move +Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null + +# Find the actual extracted directory name (handles snapshots where filename != directory name) +$actualDistributionDir = "" + +# First try the expected directory name (for regular distributions) +$expectedPath = Join-Path "$TMP_DOWNLOAD_DIR" "$distributionUrlNameMain" +$expectedMvnPath = Join-Path "$expectedPath" "bin/$MVN_CMD" +if ((Test-Path -Path $expectedPath -PathType Container) -and (Test-Path -Path $expectedMvnPath -PathType Leaf)) { + $actualDistributionDir = $distributionUrlNameMain +} + +# If not found, search for any directory with the Maven executable (for snapshots) +if (!$actualDistributionDir) { + Get-ChildItem -Path "$TMP_DOWNLOAD_DIR" -Directory | ForEach-Object { + $testPath = Join-Path $_.FullName "bin/$MVN_CMD" + if (Test-Path -Path $testPath -PathType Leaf) { + $actualDistributionDir = $_.Name + } + } +} + +if (!$actualDistributionDir) { + Write-Error "Could not find Maven distribution directory in extracted archive" +} + +Write-Verbose "Found extracted Maven distribution directory: $actualDistributionDir" +Rename-Item -Path "$TMP_DOWNLOAD_DIR/$actualDistributionDir" -NewName $MAVEN_HOME_NAME | Out-Null +try { + Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null +} catch { + if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) { + Write-Error "fail to move MAVEN_HOME" + } +} finally { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } +} + +Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" diff --git a/pom.xml b/pom.xml index a0da0080..0c941c14 100644 --- a/pom.xml +++ b/pom.xml @@ -45,7 +45,7 @@ 3.6.0 - 12.1.0 + 12.2.0 1.22.0 diff --git a/src/main/java/org/checkstyle/autofix/CheckstyleAutoFix.java b/src/main/java/org/checkstyle/autofix/CheckstyleAutoFix.java index 76b76f36..a96393bb 100644 --- a/src/main/java/org/checkstyle/autofix/CheckstyleAutoFix.java +++ b/src/main/java/org/checkstyle/autofix/CheckstyleAutoFix.java @@ -88,7 +88,7 @@ public List getRecipeList() { final ReportParser reportParser = createReportParser(getViolationReportPath()); final List violations = reportParser .parse(Path.of(getViolationReportPath())); - final Map configuration = loadCheckstyleConfiguration(); return CheckstyleRecipeRegistry.getRecipes(violations, configuration); @@ -108,7 +108,7 @@ else if (path.endsWith(".sarif") || path.endsWith(".sarif.json")) { return result; } - private Map loadCheckstyleConfiguration() { + private Map loadCheckstyleConfiguration() { return ConfigurationLoader.loadConfiguration(getConfigurationPath(), getPropertiesPath()); } } diff --git a/src/main/java/org/checkstyle/autofix/CheckstyleCheck.java b/src/main/java/org/checkstyle/autofix/CheckstyleCheck.java index 946a2d3d..fa815cac 100644 --- a/src/main/java/org/checkstyle/autofix/CheckstyleCheck.java +++ b/src/main/java/org/checkstyle/autofix/CheckstyleCheck.java @@ -40,7 +40,7 @@ public String getId() { public static Optional fromSource(String source) { return Arrays.stream(values()) - .filter(check -> check.getId().contains(source)) + .filter(check -> check.getId().contains(source.split("#")[0])) .findFirst(); } } diff --git a/src/main/java/org/checkstyle/autofix/CheckstyleCheckInstance.java b/src/main/java/org/checkstyle/autofix/CheckstyleCheckInstance.java new file mode 100644 index 00000000..9ab92802 --- /dev/null +++ b/src/main/java/org/checkstyle/autofix/CheckstyleCheckInstance.java @@ -0,0 +1,24 @@ +/////////////////////////////////////////////////////////////////////////////////////////////// +// checkstyle-openrewrite-recipes: Automatically fix Checkstyle violations with OpenRewrite. +// Copyright (C) 2025 The Checkstyle OpenRewrite Recipes Authors +// +// 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 org.checkstyle.autofix; + +public record CheckstyleCheckInstance( + CheckstyleCheck check, + String id +) { +} diff --git a/src/main/java/org/checkstyle/autofix/CheckstyleRecipeRegistry.java b/src/main/java/org/checkstyle/autofix/CheckstyleRecipeRegistry.java index 5d2c299a..efb6d42d 100644 --- a/src/main/java/org/checkstyle/autofix/CheckstyleRecipeRegistry.java +++ b/src/main/java/org/checkstyle/autofix/CheckstyleRecipeRegistry.java @@ -67,7 +67,7 @@ private CheckstyleRecipeRegistry() { * @return a list of generated Recipe objects */ public static List getRecipes(List violations, - Map config) { + Map config) { return violations.stream() .collect(Collectors.groupingBy(CheckstyleViolation::getSource)) .entrySet() diff --git a/src/main/java/org/checkstyle/autofix/parser/CheckstyleViolation.java b/src/main/java/org/checkstyle/autofix/parser/CheckstyleViolation.java index d03dadb3..4cefbe3b 100644 --- a/src/main/java/org/checkstyle/autofix/parser/CheckstyleViolation.java +++ b/src/main/java/org/checkstyle/autofix/parser/CheckstyleViolation.java @@ -19,7 +19,7 @@ import java.nio.file.Path; -import org.checkstyle.autofix.CheckstyleCheck; +import org.checkstyle.autofix.CheckstyleCheckInstance; public final class CheckstyleViolation { @@ -29,14 +29,14 @@ public final class CheckstyleViolation { private final String severity; - private final CheckstyleCheck source; + private final CheckstyleCheckInstance source; private final String message; private final Path filePath; public CheckstyleViolation(int line, int column, String severity, - CheckstyleCheck source, String message, Path filePath) { + CheckstyleCheckInstance source, String message, Path filePath) { this.line = line; this.column = column; this.severity = severity; @@ -46,7 +46,7 @@ public CheckstyleViolation(int line, int column, String severity, } public CheckstyleViolation(int line, String severity, - CheckstyleCheck source, String message, Path filePath) { + CheckstyleCheckInstance source, String message, Path filePath) { this(line, -1, severity, source, message, filePath); } @@ -58,7 +58,7 @@ public Integer getColumn() { return column; } - public CheckstyleCheck getSource() { + public CheckstyleCheckInstance getSource() { return source; } diff --git a/src/main/java/org/checkstyle/autofix/parser/ConfigurationLoader.java b/src/main/java/org/checkstyle/autofix/parser/ConfigurationLoader.java index 1f1247ab..fce4f187 100644 --- a/src/main/java/org/checkstyle/autofix/parser/ConfigurationLoader.java +++ b/src/main/java/org/checkstyle/autofix/parser/ConfigurationLoader.java @@ -25,6 +25,7 @@ import java.util.Properties; import org.checkstyle.autofix.CheckstyleCheck; +import org.checkstyle.autofix.CheckstyleCheckInstance; import com.puppycrawl.tools.checkstyle.PropertiesExpander; import com.puppycrawl.tools.checkstyle.api.CheckstyleException; @@ -36,14 +37,16 @@ private ConfigurationLoader() { // utility class } - public static Map mapConfiguration(Configuration config) { - final Map result = new HashMap<>(); - final Map inherited = getProperties(config); + public static Map mapConfiguration(Configuration config) { + final Map result = new HashMap<>(); + final Map inherited = getProperties(config); final Optional module = CheckstyleCheck.fromSource(config.getName()); + module.ifPresent(checkstyleCheck -> { - result.put(checkstyleCheck, new CheckConfiguration(checkstyleCheck, new HashMap<>(), - getProperties(config))); + result.put(new CheckstyleCheckInstance(checkstyleCheck, inherited.get("id")), + new CheckConfiguration(checkstyleCheck, new HashMap<>(), inherited)); }); for (Configuration child : config.getChildren()) { @@ -69,7 +72,7 @@ private static Map getProperties(Configuration config) { return props; } - public static Map loadConfiguration( + public static Map loadConfiguration( String checkstyleConfigurationPath, String propFile) { Properties props = new Properties(); if (propFile == null) { diff --git a/src/main/java/org/checkstyle/autofix/parser/SarifReportParser.java b/src/main/java/org/checkstyle/autofix/parser/SarifReportParser.java index 5035b32f..e7332416 100644 --- a/src/main/java/org/checkstyle/autofix/parser/SarifReportParser.java +++ b/src/main/java/org/checkstyle/autofix/parser/SarifReportParser.java @@ -26,6 +26,7 @@ import java.util.Optional; import org.checkstyle.autofix.CheckstyleCheck; +import org.checkstyle.autofix.CheckstyleCheckInstance; import de.jcup.sarif_2_1_0.SarifSchema210ImportExportSupport; import de.jcup.sarif_2_1_0.model.PhysicalLocation; @@ -57,17 +58,22 @@ public List parse(Path reportPath) { for (final Run run: report.getRuns()) { if (run.getResults() != null) { run.getResults().forEach(resultEntry -> { - CheckstyleCheck.fromSource(resultEntry.getRuleId()).ifPresent(check -> { - final CheckstyleViolation violation = createViolation(check, resultEntry); - result.add(violation); - }); - }); + CheckstyleCheck.fromSource(resultEntry.getRuleId()).ifPresent( + check -> { + final String id = Optional.of(resultEntry.getRuleId()) + .filter(src -> src.contains("#")) + .map(src -> src.substring(src.indexOf('#') + 1)) + .orElse(null); + result.add(createViolation(new + CheckstyleCheckInstance(check, id), resultEntry)); + }); } + ); } } return result; } - private CheckstyleViolation createViolation(CheckstyleCheck check, Result result) { + private CheckstyleViolation createViolation(CheckstyleCheckInstance check, Result result) { final String severity = result.getLevel().name(); final String message = result.getMessage().getText(); final PhysicalLocation location = result.getLocations().get(0).getPhysicalLocation(); diff --git a/src/main/java/org/checkstyle/autofix/parser/XmlReportParser.java b/src/main/java/org/checkstyle/autofix/parser/XmlReportParser.java index a2c1f4d7..da1b5c0e 100644 --- a/src/main/java/org/checkstyle/autofix/parser/XmlReportParser.java +++ b/src/main/java/org/checkstyle/autofix/parser/XmlReportParser.java @@ -35,6 +35,7 @@ import javax.xml.stream.events.XMLEvent; import org.checkstyle.autofix.CheckstyleCheck; +import org.checkstyle.autofix.CheckstyleCheckInstance; public class XmlReportParser implements ReportParser { @@ -118,7 +119,8 @@ private Optional parseErrorTag(StartElement startElement, String message = null; String severity = null; CheckstyleViolation violation = null; - Optional source = Optional.empty(); + Optional check = Optional.empty(); + String id = null; final Iterator attributes = startElement.getAttributes(); while (attributes.hasNext()) { @@ -138,15 +140,20 @@ private Optional parseErrorTag(StartElement startElement, message = attribute.getValue(); break; case SOURCE_ATTR: - source = CheckstyleCheck.fromSource(attribute.getValue()); + final String attrValue = attribute.getValue(); + check = CheckstyleCheck.fromSource(attrValue); + final int index = attrValue.indexOf('#'); + if (index >= 0) { + id = attrValue.substring(index + 1); + } break; default: break; } } - if (source.isPresent()) { + if (check.isPresent()) { violation = new CheckstyleViolation(line, column, severity, - source.get(), message, Path.of(filename)); + new CheckstyleCheckInstance(check.get(), id), message, Path.of(filename)); } return Optional.ofNullable(violation); diff --git a/src/main/java/org/checkstyle/autofix/recipe/Header.java b/src/main/java/org/checkstyle/autofix/recipe/Header.java index 06fdc41c..0b07f949 100644 --- a/src/main/java/org/checkstyle/autofix/recipe/Header.java +++ b/src/main/java/org/checkstyle/autofix/recipe/Header.java @@ -39,7 +39,7 @@ public class Header extends Recipe { private static final String HEADER_PROPERTY = "header"; private static final String HEADER_FILE_PROPERTY = "headerFile"; private static final String CHARSET_PROPERTY = "charset"; - private static final String LINE_SEPARATOR = System.lineSeparator(); + private static final String LINE_SEPARATOR = "\n"; private final List violations; private final CheckConfiguration config; @@ -75,7 +75,7 @@ private static String extractLicenseHeader(CheckConfiguration config) { .getPropertyOrDefault(CHARSET_PROPERTY, Charset.defaultCharset().name())); final String headerFilePath = config.getProperty(HEADER_FILE_PROPERTY); try { - header = Files.readString(Path.of(headerFilePath), charsetToUse); + header = toLfLineEnding(Files.readString(Path.of(headerFilePath), charsetToUse)); } catch (IOException exception) { throw new IllegalArgumentException("Failed to extract header from config", @@ -85,6 +85,10 @@ private static String extractLicenseHeader(CheckConfiguration config) { return header; } + private static String toLfLineEnding(String text) { + return text.replaceAll("(?x)\\\\r(?=\\\\n)|\\r(?=\\n)", ""); + } + private static class HeaderVisitor extends JavaIsoVisitor { private final List violations; private final String licenseHeader; @@ -117,7 +121,8 @@ public J visit(Tree tree, ExecutionContext executionContext) { private String extractCurrentHeader(JavaSourceFile sourceFile) { return sourceFile.getComments().stream() .map(comment -> { - return comment.printComment(getCursor()) + comment.getSuffix(); + return comment.printComment(getCursor()) + + toLfLineEnding(comment.getSuffix()); }) .collect(Collectors.joining("")); } diff --git a/src/test/java/org/checkstyle/autofix/parser/CheckstyleReportsParserTest.java b/src/test/java/org/checkstyle/autofix/parser/CheckstyleReportsParserTest.java index 16a0eb57..78658e10 100644 --- a/src/test/java/org/checkstyle/autofix/parser/CheckstyleReportsParserTest.java +++ b/src/test/java/org/checkstyle/autofix/parser/CheckstyleReportsParserTest.java @@ -26,6 +26,7 @@ import java.util.stream.Collectors; import org.checkstyle.autofix.CheckstyleCheck; +import org.checkstyle.autofix.CheckstyleCheckInstance; import org.junit.jupiter.api.Test; public class CheckstyleReportsParserTest { @@ -49,7 +50,8 @@ public void testParseFromResource() throws Exception { assertEquals(13, record.getColumn()); assertEquals("error", record.getSeverity()); assertEquals("Example message", record.getMessage()); - assertEquals(CheckstyleCheck.UPPER_ELL, record.getSource()); + assertEquals(new CheckstyleCheckInstance(CheckstyleCheck.UPPER_ELL, null), + record.getSource()); assertEquals(Path.of("Example.java"), record.getFilePath()); } diff --git a/src/test/resources/org/checkstyle/autofix/recipe/finallocalvariable/finallocalvariable2one/DiffFinalLocalVariable2One.diff b/src/test/resources/org/checkstyle/autofix/recipe/finallocalvariable/finallocalvariable2one/DiffFinalLocalVariable2One.diff index 2d78bd24..552148d3 100644 --- a/src/test/resources/org/checkstyle/autofix/recipe/finallocalvariable/finallocalvariable2one/DiffFinalLocalVariable2One.diff +++ b/src/test/resources/org/checkstyle/autofix/recipe/finallocalvariable/finallocalvariable2one/DiffFinalLocalVariable2One.diff @@ -1,6 +1,6 @@ --- src/test/resources/org/checkstyle/autofix/recipe/finallocalvariable/finallocalvariable2one/InputFinalLocalVariable2One.java +++ src/test/resources/org/checkstyle/autofix/recipe/finallocalvariable/finallocalvariable2one/OutputFinalLocalVariable2One.java -@@ -10,7 +10,7 @@ +@@ -11,7 +11,7 @@ */ package org.checkstyle.autofix.recipe.finallocalvariable.finallocalvariable2one; @@ -9,7 +9,7 @@ private int m_ClassVariable = 0; //static block static -@@ -49,9 +49,7 @@ +@@ -50,9 +50,7 @@ } }; } diff --git a/src/test/resources/org/checkstyle/autofix/recipe/finallocalvariable/finallocalvariable2one/InputFinalLocalVariable2One.java b/src/test/resources/org/checkstyle/autofix/recipe/finallocalvariable/finallocalvariable2one/InputFinalLocalVariable2One.java index 39708ddd..8cc83d95 100644 --- a/src/test/resources/org/checkstyle/autofix/recipe/finallocalvariable/finallocalvariable2one/InputFinalLocalVariable2One.java +++ b/src/test/resources/org/checkstyle/autofix/recipe/finallocalvariable/finallocalvariable2one/InputFinalLocalVariable2One.java @@ -2,6 +2,7 @@ + diff --git a/src/test/resources/org/checkstyle/autofix/recipe/finallocalvariable/finallocalvariable2one/OutputFinalLocalVariable2One.java b/src/test/resources/org/checkstyle/autofix/recipe/finallocalvariable/finallocalvariable2one/OutputFinalLocalVariable2One.java index de570dfe..b1a67fa4 100644 --- a/src/test/resources/org/checkstyle/autofix/recipe/finallocalvariable/finallocalvariable2one/OutputFinalLocalVariable2One.java +++ b/src/test/resources/org/checkstyle/autofix/recipe/finallocalvariable/finallocalvariable2one/OutputFinalLocalVariable2One.java @@ -2,6 +2,7 @@ +