Skip to content

Commit b65b85a

Browse files
author
Pavel Bludov
committed
Issue checkstyle#344: add multi-thread support to CheckstyleReportsParser
1 parent fbccbcb commit b65b85a

File tree

12 files changed

+516
-150
lines changed

12 files changed

+516
-150
lines changed

patch-diff-report-tool/src/main/java/com/github/checkstyle/CliArgsValidator.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121

2222
import java.nio.file.Files;
2323

24-
import com.github.checkstyle.data.CliPaths;
24+
import com.github.checkstyle.data.CliOptions;
2525
import com.github.checkstyle.data.CompareMode;
2626

2727
/**
@@ -52,7 +52,7 @@ private CliArgsValidator() {
5252
* @throws IllegalArgumentException
5353
* on failure of any check.
5454
*/
55-
public static void checkPaths(CliPaths paths) throws IllegalArgumentException {
55+
public static void checkPaths(CliOptions paths) throws IllegalArgumentException {
5656
if (paths.getPatchReportPath() == null) {
5757
throw new IllegalArgumentException("obligatory argument --patchReportPath "
5858
+ "not present, -h for help");

patch-diff-report-tool/src/main/java/com/github/checkstyle/Main.java

+42-27
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,11 @@
3232
import org.apache.commons.cli.Options;
3333
import org.apache.commons.cli.ParseException;
3434

35-
import com.github.checkstyle.data.CliPaths;
35+
import com.github.checkstyle.data.CliOptions;
3636
import com.github.checkstyle.data.CompareMode;
3737
import com.github.checkstyle.data.DiffReport;
3838
import com.github.checkstyle.data.MergedConfigurationModule;
39+
import com.github.checkstyle.data.ThreadingMode;
3940
import com.github.checkstyle.parser.CheckstyleConfigurationsParser;
4041
import com.github.checkstyle.parser.CheckstyleReportsParser;
4142
import com.github.checkstyle.parser.CheckstyleTextParser;
@@ -65,6 +66,7 @@ public final class Main {
6566
+ "\t--output - path to store the resulting diff report (optional, if absent then "
6667
+ "default path will be used: ~/XMLDiffGen_report_yyyy.mm.dd_hh_mm_ss), remember, "
6768
+ "if this folder exists its content will be purged;\n"
69+
+ "\t--threadingMode - which type of threading mode to use: SINGLE or MULTI;\n"
6870
+ "\t-h - simply shows help message.";
6971

7072
/**
@@ -107,6 +109,11 @@ public final class Main {
107109
*/
108110
private static final String OPTION_REFFILES_PATH = "refFiles";
109111

112+
/**
113+
* Name for command line option "threadingMode".
114+
*/
115+
private static final String OPTION_THREADING_MODE = "threadingMode";
116+
110117
/**
111118
* Name for command line option "outputPath".
112119
*/
@@ -155,39 +162,40 @@ public static void main(final String... args) throws Exception {
155162
System.out.println(MSG_HELP);
156163
}
157164
else {
158-
final CliPaths paths = getCliPaths(commandLine);
165+
final CliOptions options = getCliOptions(commandLine);
159166
final DiffReport diffReport;
160167

161-
if (paths.getCompareMode() == CompareMode.XML) {
168+
if (options.getCompareMode() == CompareMode.XML) {
162169
// XML parsing stage
163170
System.out.println("XML parsing is started.");
164-
diffReport = CheckstyleReportsParser.parse(paths.getBaseReportPath(),
165-
paths.getPatchReportPath(), XML_PARSE_PORTION_SIZE);
171+
diffReport = CheckstyleReportsParser.parse(options.getBaseReportPath(),
172+
options.getPatchReportPath(), options.getThreadingMode(),
173+
XML_PARSE_PORTION_SIZE);
166174
}
167175
else {
168176
// file parsing stage
169177
System.out.println("File parsing is started.");
170-
diffReport = CheckstyleTextParser.parse(paths.getBaseReportPath(),
171-
paths.getPatchReportPath());
178+
diffReport = CheckstyleTextParser.parse(options.getBaseReportPath(),
179+
options.getPatchReportPath(), options.getThreadingMode());
172180
}
173181

174182
// Configuration processing stage.
175183
MergedConfigurationModule diffConfiguration = null;
176-
if (paths.configurationPresent()) {
184+
if (options.configurationPresent()) {
177185
System.out.println("Creation of configuration report is started.");
178-
diffConfiguration = CheckstyleConfigurationsParser.parse(paths.getBaseConfigPath(),
179-
paths.getPatchConfigPath());
186+
diffConfiguration = CheckstyleConfigurationsParser.parse(
187+
options.getBaseConfigPath(), options.getPatchConfigPath());
180188
}
181189
else {
182-
System.out.println(
183-
"Configuration processing skipped: " + "no configuration paths provided.");
190+
System.out.println("Configuration processing skipped: "
191+
+ "no configuration options provided.");
184192
}
185193

186194
// Site and XREF generation stage
187195
System.out.println("Creation of diff html site is started.");
188196
try {
189-
exportResources(paths);
190-
SiteGenerator.generate(diffReport, diffConfiguration, paths);
197+
exportResources(options);
198+
SiteGenerator.generate(diffReport, diffConfiguration, options);
191199
}
192200
finally {
193201
for (String message : JxrDummyLog.getLogs()) {
@@ -223,8 +231,8 @@ private static CommandLine parseCli(String... args) throws ParseException {
223231
* CLI arguments.
224232
* @return CliPaths instance.
225233
*/
226-
private static CliPaths getCliPaths(CommandLine commandLine) {
227-
final CliPaths paths = parseCliToPojo(commandLine);
234+
private static CliOptions getCliOptions(CommandLine commandLine) {
235+
final CliOptions paths = parseCliToPojo(commandLine);
228236
CliArgsValidator.checkPaths(paths);
229237
return paths;
230238
}
@@ -237,7 +245,7 @@ private static CliPaths getCliPaths(CommandLine commandLine) {
237245
* @throws IOException
238246
* thrown on failure to perform checks.
239247
*/
240-
private static void exportResources(CliPaths paths) throws IOException {
248+
private static void exportResources(CliOptions paths) throws IOException {
241249
final Path outputPath = paths.getOutputPath();
242250
Files.createDirectories(outputPath);
243251
FilesystemUtils.createOverwriteDirectory(outputPath.resolve(CSS_FILEPATH));
@@ -265,6 +273,8 @@ private static Options buildOptions() {
265273
"Path to the patch checkstyle-report.xml");
266274
options.addOption(null, OPTION_REFFILES_PATH, true,
267275
"Path to the directory containing source under checkstyle check, optional.");
276+
options.addOption(null, OPTION_THREADING_MODE, true,
277+
"Option to control which type of threading mode to use.");
268278
options.addOption(null, OPTION_OUTPUT_PATH, true,
269279
"Path to directory where diff results will be stored.");
270280
options.addOption(null, OPTION_BASE_CONFIG_PATH, true,
@@ -286,9 +296,9 @@ private static Options buildOptions() {
286296
* @throws IllegalArgumentException
287297
* on failure to find necessary arguments.
288298
*/
289-
private static CliPaths parseCliToPojo(CommandLine commandLine)
299+
private static CliOptions parseCliToPojo(CommandLine commandLine)
290300
throws IllegalArgumentException {
291-
final CompareMode compareMode = getCompareMode(OPTION_COMPARE_MODE, commandLine,
301+
final CompareMode compareMode = getEnumOption(OPTION_COMPARE_MODE, commandLine,
292302
CompareMode.XML);
293303
final Path xmlBasePath = getPath(OPTION_BASE_REPORT_PATH, commandLine, null);
294304
final Path xmlPatchPath = getPath(OPTION_PATCH_REPORT_PATH, commandLine, null);
@@ -300,8 +310,10 @@ private static CliPaths parseCliToPojo(CommandLine commandLine)
300310
final Path configBasePath = getPath(OPTION_BASE_CONFIG_PATH, commandLine, null);
301311
final Path configPatchPath = getPath(OPTION_PATCH_CONFIG_PATH, commandLine, null);
302312
final boolean shortFilePaths = commandLine.hasOption(OPTION_SHORT_PATHS);
303-
return new CliPaths(compareMode, xmlBasePath, xmlPatchPath, refFilesPath, outputPath,
304-
configBasePath, configPatchPath, shortFilePaths);
313+
final ThreadingMode threadingMode = getEnumOption(OPTION_THREADING_MODE, commandLine,
314+
ThreadingMode.MULTI);
315+
return new CliOptions(compareMode, xmlBasePath, xmlPatchPath, refFilesPath, outputPath,
316+
configBasePath, configPatchPath, shortFilePaths, threadingMode);
305317
}
306318

307319
/**
@@ -311,18 +323,21 @@ private static CliPaths parseCliToPojo(CommandLine commandLine)
311323
* name of the option.
312324
* @param commandLine
313325
* parsed CLI.
314-
* @param defaultMode
326+
* @param defaultValue
315327
* mode which is used if CLI option is absent.
328+
* @param <T>
329+
* type of the enum.
316330
* @return compare mode.
317331
*/
318-
private static CompareMode getCompareMode(String optionName, CommandLine commandLine,
319-
CompareMode defaultMode) {
320-
final CompareMode result;
332+
private static <T extends Enum<T>> T getEnumOption(String optionName, CommandLine commandLine,
333+
T defaultValue) {
334+
final T result;
321335
if (commandLine.hasOption(optionName)) {
322-
result = CompareMode.valueOf(commandLine.getOptionValue(optionName).toUpperCase());
336+
final Class<T> enumType = (Class<T>) defaultValue.getClass();
337+
result = Enum.valueOf(enumType, commandLine.getOptionValue(optionName).toUpperCase());
323338
}
324339
else {
325-
result = defaultMode;
340+
result = defaultValue;
326341
}
327342
return result;
328343
}

patch-diff-report-tool/src/main/java/com/github/checkstyle/data/CheckstyleRecord.java

+67-8
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919

2020
package com.github.checkstyle.data;
2121

22+
import java.util.Arrays;
23+
import java.util.List;
2224
import java.util.regex.Matcher;
2325
import java.util.regex.Pattern;
2426

@@ -30,14 +32,21 @@
3032
* @author attatrol
3133
*
3234
*/
33-
public final class CheckstyleRecord {
35+
public final class CheckstyleRecord implements Comparable<CheckstyleRecord> {
3436

3537
/**
3638
* It is usual for sources of records to have name that
3739
* matches this pattern. It is used for shortening source names.
3840
*/
3941
private static final Pattern CHECKSTYLE_CHECK_NAME = Pattern.compile(".+Check");
4042

43+
/**
44+
* Predefined severities for sorting. All other severities has lower priority
45+
* and will be arranged in the default order for strings.
46+
*/
47+
private static final List<String> PREDEFINED_SEVERITIES =
48+
Arrays.asList("info", "warning", "error");
49+
4150
/**
4251
* Length of "Check" string.
4352
*/
@@ -177,17 +186,67 @@ public String getSimpleCuttedSourceName() {
177186

178187
/**
179188
* Compares CheckstyleRecord instances by their content.
180-
* It is used in a single controlled occasion in the code.
189+
* The order is source, line, column, severity, message.
190+
* Properties index and xref are ignored.
181191
*
182192
* @param other
183-
* another ChechstyleRecord instance under comparison
193+
* another CheckstyleRecord instance under comparison
184194
* with this instance.
185-
* @return true if instances are equal.
195+
* @return 0 if the objects are equal, a negative integer if this record is before the specified
196+
* record, or a positive integer if this record is after the specified record.
186197
*/
187-
public boolean specificEquals(final CheckstyleRecord other) {
188-
return this.line == other.line && this.column == other.column
189-
&& this.source.equals(other.source)
190-
&& this.message.equals(other.message);
198+
public int compareTo(final CheckstyleRecord other) {
199+
int diff = this.source.compareTo(other.source);
200+
if (diff == 0) {
201+
diff = Integer.compare(this.line, other.line);
202+
}
203+
if (diff == 0) {
204+
diff = Integer.compare(this.column, other.column);
205+
}
206+
if (diff == 0) {
207+
diff = compareSeverity(this.severity, other.severity);
208+
}
209+
if (diff == 0) {
210+
diff = this.message.compareTo(other.message);
211+
}
212+
return diff;
213+
}
214+
215+
/**
216+
* Compares record severities in the order "info", "warning", "error", all other.
217+
*
218+
* @param severity1 first severity
219+
* @param severity2 second severity
220+
* @return the value {@code 0} if both severities are the same
221+
* a value less than {@code 0} if severity1 should be first and
222+
* a value greater than {@code 0} if severity2 should be first
223+
*/
224+
private int compareSeverity(String severity1, String severity2) {
225+
final int result;
226+
if (severity1.equals(severity2)) {
227+
result = 0;
228+
}
229+
else {
230+
final int index1 = PREDEFINED_SEVERITIES.indexOf(severity1);
231+
final int index2 = PREDEFINED_SEVERITIES.indexOf(severity2);
232+
if (index1 < 0 && index2 < 0) {
233+
// Both severity levels are unknown, so use regular order for strings.
234+
result = severity1.compareTo(severity2);
235+
}
236+
else if (index1 < 0) {
237+
// First is unknown, second is known: second before
238+
result = 1;
239+
}
240+
else if (index2 < 0) {
241+
// First is known, second is unknown: first before
242+
result = -1;
243+
}
244+
else {
245+
// Both result are well-known, use predefined order
246+
result = Integer.compare(index1, index2);
247+
}
248+
}
249+
return result;
191250
}
192251

193252
}

patch-diff-report-tool/src/main/java/com/github/checkstyle/data/CliPaths.java renamed to patch-diff-report-tool/src/main/java/com/github/checkstyle/data/CliOptions.java

+24-11
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,11 @@
2222
import java.nio.file.Path;
2323

2424
/**
25-
* POJO class that hold input paths.
25+
* POJO class that hold input options.
2626
*
2727
* @author attatrol
2828
*/
29-
public final class CliPaths {
29+
public final class CliOptions {
3030
/**
3131
* Option to control which type of diff comparison to do.
3232
*/
@@ -67,6 +67,12 @@ public final class CliPaths {
6767
*/
6868
private final boolean shortFilePaths;
6969

70+
/**
71+
* Switch specifying if report generation should be done in a single-threaded
72+
* or multi-threaded mode.
73+
*/
74+
private final ThreadingMode threadingMode;
75+
7076
/**
7177
* POJO ctor.
7278
*
@@ -75,22 +81,24 @@ public final class CliPaths {
7581
* @param baseReportPath
7682
* path to the base checkstyle-report.xml.
7783
* @param patchReportPath
78-
* path to the patch checkstyle-report.xml.
84+
* path to the patch checkstyle-report.xml.
7985
* @param refFilesPath
80-
* path to the data, tested by checkstyle.
86+
* path to the data, tested by checkstyle.
8187
* @param outputPath
82-
* path to the result site.
83-
* @param patchConfigPath
84-
* path to the configuration of the base report.
88+
* path to the result site.
8589
* @param baseConfigPath
86-
* path to the configuration of the patch report.
90+
* path to the configuration of the patch report.
91+
* @param patchConfigPath
92+
* path to the configuration of the base report.
8793
* @param shortFilePaths
88-
* {@code true} if only short file names should be used with no paths.
94+
* {@code true} if only short file names should be used with no paths.
95+
* @param threadingMode
96+
* type of threading mode to use.
8997
*/
9098
// -@cs[ParameterNumber] Helper class to pass all CLI attributes around.
91-
public CliPaths(CompareMode compareMode, Path baseReportPath, Path patchReportPath,
99+
public CliOptions(CompareMode compareMode, Path baseReportPath, Path patchReportPath,
92100
Path refFilesPath, Path outputPath, Path baseConfigPath, Path patchConfigPath,
93-
boolean shortFilePaths) {
101+
boolean shortFilePaths, ThreadingMode threadingMode) {
94102
this.compareMode = compareMode;
95103
this.baseReportPath = baseReportPath;
96104
this.patchReportPath = patchReportPath;
@@ -99,6 +107,7 @@ public CliPaths(CompareMode compareMode, Path baseReportPath, Path patchReportPa
99107
this.baseConfigPath = baseConfigPath;
100108
this.patchConfigPath = patchConfigPath;
101109
this.shortFilePaths = shortFilePaths;
110+
this.threadingMode = threadingMode;
102111
}
103112

104113
public CompareMode getCompareMode() {
@@ -133,6 +142,10 @@ public boolean isShortFilePaths() {
133142
return shortFilePaths;
134143
}
135144

145+
public ThreadingMode getThreadingMode() {
146+
return threadingMode;
147+
}
148+
136149
/**
137150
* Checks if the necessary configuration paths are present to display them on the reports.
138151
*

0 commit comments

Comments
 (0)