From 67cbb947efff16ea2be29c7fd860cf5f2feeb720 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 24 Aug 2023 09:25:29 +0200 Subject: [PATCH] [cli] Move option "--relativize-paths-with" up to AbstractAnalysisPmdSubcommand It applies to both PMD and CPD --- docs/pages/pmd/userdocs/cpd/cpd.md | 31 +++++++++++++++---- .../AbstractAnalysisPmdSubcommand.java | 20 ++++++++++++ .../pmd/cli/commands/internal/CpdCommand.java | 20 ------------ .../pmd/cli/commands/internal/PmdCommand.java | 20 ------------ 4 files changed, 45 insertions(+), 46 deletions(-) diff --git a/docs/pages/pmd/userdocs/cpd/cpd.md b/docs/pages/pmd/userdocs/cpd/cpd.md index aa8ca7496f..f396494e65 100644 --- a/docs/pages/pmd/userdocs/cpd/cpd.md +++ b/docs/pages/pmd/userdocs/cpd/cpd.md @@ -4,6 +4,7 @@ tags: [cpd, userdocs] summary: "Learn how to use CPD, the copy-paste detector shipped with PMD." permalink: pmd_userdocs_cpd.html author: Tom Copeland +last_updated: August 2023 (7.0.0) --- ## Overview @@ -22,19 +23,27 @@ See how to add it [here](pmd_devdocs_major_adding_new_cpd_language.html). ### Why should you care about duplicates? -It's certainly important to know where to get CPD, and how to call it, but it's worth stepping back for a moment and asking yourself why you should care about this, being the occurrence of duplicate code blocks. +It's certainly important to know where to get CPD, and how to call it, but it's worth stepping back for a moment and +asking yourself why you should care about this, being the occurrence of duplicate code blocks. -Assuming duplicated blocks of code are supposed to do the same thing, any refactoring, even simple, must be duplicated too -- which is unrewarding grunt work, and puts pressure on the developer to find every place in which to perform the refactoring. Automated tools like CPD can help with that to some extent. +Assuming duplicated blocks of code are supposed to do the same thing, any refactoring, even simple, must be duplicated +too -- which is unrewarding grunt work, and puts pressure on the developer to find every place in which to perform +the refactoring. Automated tools like CPD can help with that to some extent. -However, failure to keep the code in sync may mean automated tools will no longer recognise these blocks as duplicates. This means the task of finding duplicates to keep them in sync when doing subsequent refactorings can no longer be entrusted to an automated tool -- adding more burden on the maintainer. Segments of code initially supposed to do the same thing may grow apart undetected upon further refactoring. +However, failure to keep the code in sync may mean automated tools will no longer recognise these blocks as duplicates. +This means the task of finding duplicates to keep them in sync when doing subsequent refactorings can no longer be +entrusted to an automated tool -- adding more burden on the maintainer. Segments of code initially supposed to do the +same thing may grow apart undetected upon further refactoring. Now, if the code may never change in the future, then this is not a problem. -Otherwise, the most viable solution is to not duplicate. If the duplicates are already there, then they should be refactored out. We thus advise developers to use CPD to **help remove duplicates**, not to help keep duplicates in sync. +Otherwise, the most viable solution is to not duplicate. If the duplicates are already there, then they should be +refactored out. We thus advise developers to use CPD to **help remove duplicates**, not to help keep duplicates in sync. ### Refactoring duplicates -Once you have located some duplicates, several refactoring strategies may apply depending of the scope and extent of the duplication. Here's a quick summary: +Once you have located some duplicates, several refactoring strategies may apply depending of the scope and extent of +the duplication. Here's a quick summary: * If the duplication is local to a method or single class: * Extract a local variable if the duplicated logic is not prohibitively long @@ -45,7 +54,8 @@ Once you have located some duplicates, several refactoring strategies may apply * If the duplication occurs consistently in unrelated hierarchies: * Introduce a common ancestor to those class hierarchies -Novice as much as advanced readers may want to [read on on Refactoring Guru](https://refactoring.guru/smells/duplicate-code) for more in-depth strategies, use cases and explanations. +Novice as much as advanced readers may want to [read on on Refactoring Guru](https://refactoring.guru/smells/duplicate-code) +for more in-depth strategies, use cases and explanations. ## CLI Usage @@ -119,6 +129,15 @@ Novice as much as advanced readers may want to [read on on Refactoring Guru](htt are described [here](#available-report-formats)." default="text" %} + {% include custom/cli_option_row.html options="--relativize-paths-with,-z" + option_arg="path" + description="Path relative to which directories are rendered in the report. This option allows + shortening directories in the report; without it, paths are rendered as mentioned in the + source directory (option \"--dir\"). + The option can be repeated, in which case the shortest relative path will be used. + If the root path is mentioned (e.g. \"/\" or \"C:\\\"), then the paths will be rendered + as absolute." + %} {% include custom/cli_option_row.html options="--[no-]fail-on-violation" description="Specifies whether CPD exits with non-zero status if violations are found. By default CPD exits with status 4 if violations are found. diff --git a/pmd-cli/src/main/java/net/sourceforge/pmd/cli/commands/internal/AbstractAnalysisPmdSubcommand.java b/pmd-cli/src/main/java/net/sourceforge/pmd/cli/commands/internal/AbstractAnalysisPmdSubcommand.java index e0284063c0..758f0cb6c2 100644 --- a/pmd-cli/src/main/java/net/sourceforge/pmd/cli/commands/internal/AbstractAnalysisPmdSubcommand.java +++ b/pmd-cli/src/main/java/net/sourceforge/pmd/cli/commands/internal/AbstractAnalysisPmdSubcommand.java @@ -5,6 +5,7 @@ package net.sourceforge.pmd.cli.commands.internal; import java.net.URI; +import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; import java.util.List; @@ -60,6 +61,25 @@ public abstract class AbstractAnalysisPmdSubcommand relativizeRootPaths; + + @Option(names = { "--relativize-paths-with", "-z"}, description = "Path relative to which directories are rendered in the report. " + + "This option allows shortening directories in the report; " + + "without it, paths are rendered as mentioned in the source directory (option \"--dir\"). " + + "The option can be repeated, in which case the shortest relative path will be used. " + + "If the root path is mentioned (e.g. \"/\" or \"C:\\\"), then the paths will be rendered as absolute.", + arity = "1..*", split = ",") + public void setRelativizePathsWith(List rootPaths) { + this.relativizeRootPaths = rootPaths; + + for (Path path : this.relativizeRootPaths) { + if (Files.isRegularFile(path)) { + throw new ParameterException(spec.commandLine(), + "Expected a directory path for option '--relativize-paths-with', found a file: " + path); + } + } + } + @Override protected final void validate() throws ParameterException { super.validate(); diff --git a/pmd-cli/src/main/java/net/sourceforge/pmd/cli/commands/internal/CpdCommand.java b/pmd-cli/src/main/java/net/sourceforge/pmd/cli/commands/internal/CpdCommand.java index 62429b655a..e3bde23f6f 100644 --- a/pmd-cli/src/main/java/net/sourceforge/pmd/cli/commands/internal/CpdCommand.java +++ b/pmd-cli/src/main/java/net/sourceforge/pmd/cli/commands/internal/CpdCommand.java @@ -5,7 +5,6 @@ package net.sourceforge.pmd.cli.commands.internal; import java.io.IOException; -import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; import java.util.Iterator; @@ -89,25 +88,6 @@ public class CpdCommand extends AbstractAnalysisPmdSubcommand private boolean nonRecursive; - private List relativizeRootPaths; - - @Option(names = { "--relativize-paths-with", "-z"}, description = "Path relative to which directories are rendered in the report. " - + "This option allows shortening directories in the report; " - + "without it, paths are rendered as mentioned in the source directory (option \"--dir\"). " - + "The option can be repeated, in which case the shortest relative path will be used. " - + "If the root path is mentioned (e.g. \"/\" or \"C:\\\"), then the paths will be rendered as absolute.", - arity = "1..*", split = ",") - public void setRelativizePathsWith(List rootPaths) { - this.relativizeRootPaths = rootPaths; - - for (Path path : this.relativizeRootPaths) { - if (Files.isRegularFile(path)) { - throw new ParameterException(spec.commandLine(), - "Expected a directory path for option '--relativize-paths-with', found a file: " + path); - } - } - } - /** * Converts these parameters into a configuration. * diff --git a/pmd-cli/src/main/java/net/sourceforge/pmd/cli/commands/internal/PmdCommand.java b/pmd-cli/src/main/java/net/sourceforge/pmd/cli/commands/internal/PmdCommand.java index b9372e6394..ae2956238f 100644 --- a/pmd-cli/src/main/java/net/sourceforge/pmd/cli/commands/internal/PmdCommand.java +++ b/pmd-cli/src/main/java/net/sourceforge/pmd/cli/commands/internal/PmdCommand.java @@ -7,7 +7,6 @@ package net.sourceforge.pmd.cli.commands.internal; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.Writer; -import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; import java.util.Iterator; @@ -87,8 +86,6 @@ public class PmdCommand extends AbstractAnalysisPmdSubcommand private boolean benchmark; - private List relativizeRootPaths; - private boolean showSuppressed; private String suppressMarker; @@ -143,23 +140,6 @@ public class PmdCommand extends AbstractAnalysisPmdSubcommand this.benchmark = benchmark; } - @Option(names = { "--relativize-paths-with", "-z"}, description = "Path relative to which directories are rendered in the report. " - + "This option allows shortening directories in the report; " - + "without it, paths are rendered as mentioned in the source directory (option \"--dir\"). " - + "The option can be repeated, in which case the shortest relative path will be used. " - + "If the root path is mentioned (e.g. \"/\" or \"C:\\\"), then the paths will be rendered as absolute.", - arity = "1..*", split = ",") - public void setRelativizePathsWith(List rootPaths) { - this.relativizeRootPaths = rootPaths; - - for (Path path : this.relativizeRootPaths) { - if (Files.isRegularFile(path)) { - throw new ParameterException(spec.commandLine(), - "Expected a directory path for option '--relativize-paths-with', found a file: " + path); - } - } - } - @Option(names = "--show-suppressed", description = "Report should show suppressed rule violations.") public void setShowSuppressed(final boolean showSuppressed) { this.showSuppressed = showSuppressed;