Skip to content

Commit 611ef49

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

File tree

4 files changed

+222
-87
lines changed

4 files changed

+222
-87
lines changed

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/DiffReport.java

+40-78
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@
2121

2222
import java.util.ArrayList;
2323
import java.util.Collections;
24-
import java.util.Comparator;
2524
import java.util.List;
2625
import java.util.Map;
27-
import java.util.TreeMap;
26+
import java.util.concurrent.CompletableFuture;
27+
import java.util.concurrent.ConcurrentSkipListMap;
2828

2929
import com.github.checkstyle.parser.CheckstyleReportsParser;
3030

@@ -42,21 +42,26 @@ public final class DiffReport {
4242
* Container for parsed data,
4343
* note it is a TreeMap for memory keeping purposes.
4444
*/
45-
private Map<String, List<CheckstyleRecord>> records =
46-
new TreeMap<>();
45+
private final Map<String, List<CheckstyleRecord>> records =
46+
new ConcurrentSkipListMap<>();
4747

4848
/**
4949
* Container for statistical data.
5050
*/
51-
private Statistics statistics = new Statistics();
51+
private final Statistics statistics = new Statistics();
52+
53+
/**
54+
* Asynchronous tasks for difference calculation.
55+
*/
56+
private final List<CompletableFuture<Void>> asyncTasks = new ArrayList<>();
5257

5358
/**
5459
* Getter for data container.
5560
*
5661
* @return map containing parsed data.
5762
*/
5863
public Map<String, List<CheckstyleRecord>> getRecords() {
59-
return records;
64+
return Collections.unmodifiableMap(records);
6065
}
6166

6267
public Statistics getStatistics() {
@@ -76,111 +81,68 @@ public Statistics getStatistics() {
7681
public void addRecords(List<CheckstyleRecord> newRecords,
7782
String filename) {
7883
if (!newRecords.isEmpty()) {
84+
Collections.sort(newRecords);
7985
final List<CheckstyleRecord> popped =
8086
records.put(filename, newRecords);
8187
if (popped != null) {
8288
final List<CheckstyleRecord> diff =
83-
produceDiff(popped, newRecords);
89+
DiffUtils.produceDiff(popped, newRecords);
8490
if (diff.isEmpty()) {
8591
records.remove(filename);
8692
}
8793
else {
88-
Collections.sort(diff, new PositionOrderComparator());
8994
records.put(filename, diff);
9095
}
9196
}
9297
}
9398
}
9499

95100
/**
96-
* Creates difference between 2 lists of records.
101+
* Adds new records to the diff report asynchronously,
102+
* when there are records with this filename, comparison
103+
* between them and new record is performed and only difference is saved.
97104
*
98-
* @param list1
99-
* the first list.
100-
* @param list2
101-
* the second list.
102-
* @return the difference list.
105+
* @param newRecords
106+
* a new records list.
107+
* @param filename
108+
* name of a file which is a cause of records generation.
103109
*/
104-
private static List<CheckstyleRecord> produceDiff(
105-
List<CheckstyleRecord> list1, List<CheckstyleRecord> list2) {
106-
final List<CheckstyleRecord> diff = new ArrayList<>();
107-
for (CheckstyleRecord rec1 : list1) {
108-
if (!isInList(list2, rec1)) {
109-
diff.add(rec1);
110-
}
111-
}
112-
for (CheckstyleRecord rec2 : list2) {
113-
if (!isInList(list1, rec2)) {
114-
diff.add(rec2);
115-
}
116-
}
117-
return diff;
110+
public void addRecordsAsync(
111+
List<CheckstyleRecord> newRecords, String filename) {
112+
asyncTasks.add(CompletableFuture.runAsync(() -> addRecords(newRecords, filename)));
118113
}
119114

120115
/**
121-
* Compares the record against list of records.
122-
*
123-
* @param list
124-
* of records.
125-
* @param testedRecord
126-
* the record.
127-
* @return true, if has its copy in a list.
116+
* Await completion of all asynchronous tasks.
128117
*/
129-
private static boolean isInList(List<CheckstyleRecord> list,
130-
CheckstyleRecord testedRecord) {
131-
boolean belongsToList = false;
132-
for (CheckstyleRecord checkstyleRecord : list) {
133-
if (testedRecord.specificEquals(checkstyleRecord)) {
134-
belongsToList = true;
135-
break;
136-
}
137-
}
138-
return belongsToList;
118+
public void joinAsyncTasksAll() {
119+
asyncTasks.forEach(CompletableFuture::join);
139120
}
140121

141122
/**
142123
* Generates statistical information and puts in in the accumulator.
143124
*/
144125
public void getDiffStatistics() {
145126
statistics.setFileNumDiff(records.size());
146-
for (Map.Entry<String, List<CheckstyleRecord>> entry
147-
: records.entrySet()) {
148-
final List<CheckstyleRecord> list = entry.getValue();
149-
for (CheckstyleRecord rec : list) {
150-
if (rec.getIndex() == CheckstyleReportsParser.BASE_REPORT_INDEX) {
151-
statistics.addSeverityRecordRemoved(rec.getSeverity());
152-
statistics.addModuleRecordRemoved(rec.getSource());
153-
}
154-
else {
155-
statistics.addSeverityRecordAdded(rec.getSeverity());
156-
statistics.addModuleRecordAdded(rec.getSource());
157-
}
158-
statistics.incrementUniqueMessageCount(rec.getIndex());
159-
}
160-
}
127+
records.entrySet().parallelStream()
128+
.flatMap(entry -> entry.getValue().stream())
129+
.forEach(this::addRecordStatistics);
161130
}
162131

163132
/**
164-
* Comparator used to sort lists of CheckstyleRecord objects
165-
* by their position in code.
166-
*
167-
* @author atta_troll
133+
* Generates statistical information for one CheckstyleRecord.
168134
*
135+
* @param checkstyleRecord the checkstyleRecord to process
169136
*/
170-
private static class PositionOrderComparator
171-
implements Comparator<CheckstyleRecord> {
172-
173-
@Override
174-
public int compare(final CheckstyleRecord arg0,
175-
final CheckstyleRecord arg1) {
176-
final int difference = arg0.getLine() - arg1.getLine();
177-
if (difference == 0) {
178-
return arg0.getColumn() - arg1.getColumn();
179-
}
180-
else {
181-
return difference;
182-
}
137+
private void addRecordStatistics(CheckstyleRecord checkstyleRecord) {
138+
if (checkstyleRecord.getIndex() == CheckstyleReportsParser.BASE_REPORT_INDEX) {
139+
statistics.addSeverityRecordRemoved(checkstyleRecord.getSeverity());
140+
statistics.addModuleRecordRemoved(checkstyleRecord.getSource());
141+
}
142+
else {
143+
statistics.addSeverityRecordAdded(checkstyleRecord.getSeverity());
144+
statistics.addModuleRecordAdded(checkstyleRecord.getSource());
183145
}
146+
statistics.incrementUniqueMessageCount(checkstyleRecord.getIndex());
184147
}
185-
186148
}

0 commit comments

Comments
 (0)