forked from phoedos/pmd
[cli] Move option "--relativize-paths-with" up to AbstractAnalysisPmdSubcommand
It applies to both PMD and CPD
This commit is contained in:
@ -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 <tom@infoether.com>
|
||||
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.
|
||||
|
@ -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<C extends AbstractConfigurat
|
||||
this.inputPaths.addAll(inputPaths);
|
||||
}
|
||||
|
||||
protected List<Path> 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<Path> 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();
|
||||
|
@ -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<CPDConfiguration>
|
||||
private boolean nonRecursive;
|
||||
|
||||
|
||||
private List<Path> 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<Path> 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.
|
||||
*
|
||||
|
@ -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<PMDConfiguration>
|
||||
|
||||
private boolean benchmark;
|
||||
|
||||
private List<Path> relativizeRootPaths;
|
||||
|
||||
private boolean showSuppressed;
|
||||
|
||||
private String suppressMarker;
|
||||
@ -143,23 +140,6 @@ public class PmdCommand extends AbstractAnalysisPmdSubcommand<PMDConfiguration>
|
||||
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<Path> 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;
|
||||
|
Reference in New Issue
Block a user