Skip to content

Commit 1b3ea10

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

File tree

3 files changed

+140
-64
lines changed

3 files changed

+140
-64
lines changed

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

+66-5
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,26 @@ public final class CheckstyleRecord {
4343
*/
4444
private static final int CHECK_STRING_LENGTH = 5;
4545

46+
/**
47+
* Constant value for severity level "info".
48+
*/
49+
private static final int SEVERITY_INFO = 0;
50+
51+
/**
52+
* Constant value for severity level "warning".
53+
*/
54+
private static final int SEVERITY_WARNING = 1;
55+
56+
/**
57+
* Constant value for severity level "error".
58+
*/
59+
private static final int SEVERITY_ERROR = 2;
60+
61+
/**
62+
* Constant value for all other severity levels.
63+
*/
64+
private static final int SEVERITY_OTHER = 3;
65+
4666
/**
4767
* Index of the source.
4868
*/
@@ -180,14 +200,55 @@ public String getSimpleCuttedSourceName() {
180200
* It is used in a single controlled occasion in the code.
181201
*
182202
* @param other
183-
* another ChechstyleRecord instance under comparison
203+
* another CheckstyleRecord instance under comparison
184204
* with this instance.
185205
* @return true if instances are equal.
186206
*/
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);
207+
public int specificCompare(final CheckstyleRecord other) {
208+
int diff = this.source.compareTo(other.source);
209+
if (diff == 0) {
210+
diff = Integer.compare(this.line, other.line);
211+
}
212+
if (diff == 0) {
213+
diff = Integer.compare(this.column, other.column);
214+
}
215+
if (diff == 0) {
216+
if (!this.severity.equals(other.severity)) {
217+
if (getSeverityLevel(this.severity) < getSeverityLevel(other.severity)) {
218+
diff = -1;
219+
}
220+
else {
221+
diff = 1;
222+
}
223+
}
224+
}
225+
if (diff == 0) {
226+
diff = this.message.compareTo(other.message);
227+
}
228+
return diff;
229+
}
230+
231+
/**
232+
* Helper method to compare two records in predefined order by severity.
233+
*
234+
* @param severity to examine
235+
* @return the severity order
236+
*/
237+
private static int getSeverityLevel(String severity) {
238+
final int result;
239+
if ("info".equals(severity)) {
240+
result = SEVERITY_INFO;
241+
}
242+
else if ("warning".equals(severity)) {
243+
result = SEVERITY_WARNING;
244+
}
245+
else if ("error".equals(severity)) {
246+
result = SEVERITY_ERROR;
247+
}
248+
else {
249+
result = SEVERITY_OTHER;
250+
}
251+
return result;
191252
}
192253

193254
}

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

+63-58
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;
24+
import java.util.Iterator;
2525
import java.util.List;
2626
import java.util.Map;
27-
import java.util.TreeMap;
27+
import java.util.concurrent.ConcurrentSkipListMap;
2828

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

@@ -42,21 +42,21 @@ 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();
5252

5353
/**
5454
* Getter for data container.
5555
*
5656
* @return map containing parsed data.
5757
*/
5858
public Map<String, List<CheckstyleRecord>> getRecords() {
59-
return records;
59+
return Collections.unmodifiableMap(records);
6060
}
6161

6262
public Statistics getStatistics() {
@@ -76,6 +76,7 @@ public Statistics getStatistics() {
7676
public void addRecords(List<CheckstyleRecord> newRecords,
7777
String filename) {
7878
if (!newRecords.isEmpty()) {
79+
newRecords.sort(CheckstyleRecord::specificCompare);
7980
final List<CheckstyleRecord> popped =
8081
records.put(filename, newRecords);
8182
if (popped != null) {
@@ -85,57 +86,84 @@ public void addRecords(List<CheckstyleRecord> newRecords,
8586
records.remove(filename);
8687
}
8788
else {
88-
Collections.sort(diff, new PositionOrderComparator());
8989
records.put(filename, diff);
9090
}
9191
}
9292
}
9393
}
9494

9595
/**
96-
* Creates difference between 2 lists of records.
96+
* Creates difference between 2 sorted lists of records.
9797
*
98-
* @param list1
98+
* @param firstList
9999
* the first list.
100-
* @param list2
100+
* @param secondList
101101
* the second list.
102102
* @return the difference list.
103103
*/
104104
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-
}
105+
List<CheckstyleRecord> firstList, List<CheckstyleRecord> secondList) {
106+
final List<CheckstyleRecord> result;
107+
if (firstList.isEmpty()) {
108+
result = secondList;
111109
}
112-
for (CheckstyleRecord rec2 : list2) {
113-
if (!isInList(list1, rec2)) {
114-
diff.add(rec2);
115-
}
110+
else if (secondList.isEmpty()) {
111+
result = firstList;
112+
}
113+
else {
114+
result = produceDiff(firstList.iterator(), secondList.iterator());
116115
}
117-
return diff;
116+
return result;
118117
}
119118

120119
/**
121-
* Compares the record against list of records.
120+
* Creates difference between 2 non-empty iterators of records.
122121
*
123-
* @param list
124-
* of records.
125-
* @param testedRecord
126-
* the record.
127-
* @return true, if has its copy in a list.
122+
* @param firstIterator
123+
* the first iterator.
124+
* @param secondIterator
125+
* the second iterator.
126+
* @return the difference list (always sorted).
128127
*/
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;
128+
private static List<CheckstyleRecord> produceDiff(
129+
Iterator<CheckstyleRecord> firstIterator, Iterator<CheckstyleRecord> secondIterator) {
130+
CheckstyleRecord firstVal = firstIterator.next();
131+
CheckstyleRecord secondVal = secondIterator.next();
132+
final List<CheckstyleRecord> result = new ArrayList<>();
133+
while (true) {
134+
final int diff = firstVal.specificCompare(secondVal);
135+
if (diff < 0) {
136+
result.add(firstVal);
137+
if (!firstIterator.hasNext()) {
138+
result.add(secondVal);
139+
break;
140+
}
141+
firstVal = firstIterator.next();
142+
}
143+
else if (diff > 0) {
144+
result.add(secondVal);
145+
if (!secondIterator.hasNext()) {
146+
result.add(firstVal);
147+
break;
148+
}
149+
secondVal = secondIterator.next();
150+
}
151+
else {
152+
if (!firstIterator.hasNext() || !secondIterator.hasNext()) {
153+
break;
154+
}
155+
firstVal = firstIterator.next();
156+
secondVal = secondIterator.next();
136157
}
137158
}
138-
return belongsToList;
159+
// add tails
160+
while (firstIterator.hasNext()) {
161+
result.add(firstIterator.next());
162+
}
163+
while (secondIterator.hasNext()) {
164+
result.add(secondIterator.next());
165+
}
166+
return result;
139167
}
140168

141169
/**
@@ -160,27 +188,4 @@ public void getDiffStatistics() {
160188
}
161189
}
162190

163-
/**
164-
* Comparator used to sort lists of CheckstyleRecord objects
165-
* by their position in code.
166-
*
167-
* @author atta_troll
168-
*
169-
*/
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-
}
183-
}
184-
}
185-
186191
}

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

+11-1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import java.util.ArrayList;
2525
import java.util.Iterator;
2626
import java.util.List;
27+
import java.util.concurrent.CompletableFuture;
2728

2829
import javax.xml.stream.XMLEventReader;
2930
import javax.xml.stream.XMLStreamException;
@@ -139,6 +140,7 @@ public static DiffReport parse(Path baseXml, Path patchXml, int portionSize)
139140

140141
/**
141142
* Parses portion of the XML report.
143+
* Difference generation is performed asynchronously for efficient CPU usage.
142144
*
143145
* @param diffReport
144146
* container for parsed data.
@@ -157,6 +159,7 @@ private static void parseXmlPortion(DiffReport diffReport,
157159
int counter = numOfFilenames;
158160
String filename = null;
159161
List<CheckstyleRecord> records = null;
162+
final List<CompletableFuture<Void>> tasks = new ArrayList<>();
160163
while (reader.hasNext()) {
161164
final XMLEvent event = reader.nextEvent();
162165
if (event.isStartElement()) {
@@ -187,13 +190,20 @@ else if (startElementName.equals(ERROR_TAG)) {
187190
if (event.isEndElement()) {
188191
final EndElement endElement = event.asEndElement();
189192
if (endElement.getName().getLocalPart().equals(FILE_TAG)) {
190-
diffReport.addRecords(records, filename);
193+
final List<CheckstyleRecord> currRecords = records;
194+
records = null;
195+
final String currFile = filename;
196+
filename = null;
197+
tasks.add(CompletableFuture.runAsync(() -> {
198+
diffReport.addRecords(currRecords, currFile);
199+
}));
191200
if (counter == 0) {
192201
break;
193202
}
194203
}
195204
}
196205
}
206+
tasks.forEach(CompletableFuture::join);
197207
}
198208

199209
/**

0 commit comments

Comments
 (0)