Skip to content

Commit

Permalink
Issue checkstyle#344: add multi-thread support to CheckstyleReportsPa…
Browse files Browse the repository at this point in the history
…rser
  • Loading branch information
Pavel Bludov committed Oct 31, 2020
1 parent be315ba commit f0ca9ad
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -180,14 +180,22 @@ public String getSimpleCuttedSourceName() {
* It is used in a single controlled occasion in the code.
*
* @param other
* another ChechstyleRecord instance under comparison
* another CheckstyleRecord instance under comparison
* with this instance.
* @return true if instances are equal.
*/
public boolean specificEquals(final CheckstyleRecord other) {
return this.line == other.line && this.column == other.column
&& this.source.equals(other.source)
&& this.message.equals(other.message);
public int specificCompare(final CheckstyleRecord other) {
int diff = Integer.compare(this.line, other.line);
if (diff == 0) {
diff = Integer.compare(this.column, other.column);
}
if (diff == 0) {
diff = this.source.compareTo(other.source);
}
if (diff == 0) {
diff = this.message.compareTo(other.message);
}
return diff;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
Expand All @@ -42,21 +43,21 @@ public final class DiffReport {
* Container for parsed data,
* note it is a TreeMap for memory keeping purposes.
*/
private Map<String, List<CheckstyleRecord>> records =
private final Map<String, List<CheckstyleRecord>> records =
new TreeMap<>();

/**
* Container for statistical data.
*/
private Statistics statistics = new Statistics();
private final Statistics statistics = new Statistics();

/**
* Getter for data container.
*
* @return map containing parsed data.
*/
public Map<String, List<CheckstyleRecord>> getRecords() {
return records;
return Collections.unmodifiableMap(records);
}

public Statistics getStatistics() {
Expand All @@ -76,6 +77,7 @@ public Statistics getStatistics() {
public void addRecords(List<CheckstyleRecord> newRecords,
String filename) {
if (!newRecords.isEmpty()) {
newRecords.sort(new PositionOrderComparator());
final List<CheckstyleRecord> popped =
records.put(filename, newRecords);
if (popped != null) {
Expand All @@ -85,57 +87,84 @@ public void addRecords(List<CheckstyleRecord> newRecords,
records.remove(filename);
}
else {
Collections.sort(diff, new PositionOrderComparator());
records.put(filename, diff);
}
}
}
}

/**
* Creates difference between 2 lists of records.
* Creates difference between 2 sorted lists of records.
*
* @param list1
* @param firstList
* the first list.
* @param list2
* @param secondList
* the second list.
* @return the difference list.
*/
private static List<CheckstyleRecord> produceDiff(
List<CheckstyleRecord> list1, List<CheckstyleRecord> list2) {
final List<CheckstyleRecord> diff = new ArrayList<>();
for (CheckstyleRecord rec1 : list1) {
if (!isInList(list2, rec1)) {
diff.add(rec1);
}
List<CheckstyleRecord> firstList, List<CheckstyleRecord> secondList) {
final List<CheckstyleRecord> result;
if (firstList.isEmpty()) {
result = secondList;
}
for (CheckstyleRecord rec2 : list2) {
if (!isInList(list1, rec2)) {
diff.add(rec2);
}
else if (secondList.isEmpty()) {
result = firstList;
}
else {
result = produceDiff(firstList.iterator(), secondList.iterator());
}
return diff;
return result;
}

/**
* Compares the record against list of records.
* Creates difference between 2 non-empty iterators of records.
*
* @param list
* of records.
* @param testedRecord
* the record.
* @return true, if has its copy in a list.
* @param firstIterator
* the first iterator.
* @param secondIterator
* the second iterator.
* @return the difference list (always sorted).
*/
private static boolean isInList(List<CheckstyleRecord> list,
CheckstyleRecord testedRecord) {
boolean belongsToList = false;
for (CheckstyleRecord checkstyleRecord : list) {
if (testedRecord.specificEquals(checkstyleRecord)) {
belongsToList = true;
break;
private static List<CheckstyleRecord> produceDiff(
Iterator<CheckstyleRecord> firstIterator, Iterator<CheckstyleRecord> secondIterator) {
CheckstyleRecord firstVal = firstIterator.next();
CheckstyleRecord secondVal = secondIterator.next();
final List<CheckstyleRecord> result = new ArrayList<>();
while (true) {
final int diff = firstVal.specificCompare(secondVal);
if (diff < 0) {
result.add(firstVal);
if (!firstIterator.hasNext()) {
result.add(secondVal);
break;
}
firstVal = firstIterator.next();
}
else if (diff > 0) {
result.add(secondVal);
if (!secondIterator.hasNext()) {
result.add(firstVal);
break;
}
secondVal = secondIterator.next();
}
else {
if (!firstIterator.hasNext() || !secondIterator.hasNext()) {
break;
}
firstVal = firstIterator.next();
secondVal = secondIterator.next();
}
}
return belongsToList;
// add tails
while (firstIterator.hasNext()) {
result.add(firstIterator.next());
}
while (secondIterator.hasNext()) {
result.add(secondIterator.next());
}
return result;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CompletableFuture;

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

/**
* Parses portion of the XML report.
* Difference generation is performed asynchronously for efficient CPU usage.
*
* @param diffReport
* container for parsed data.
Expand All @@ -157,6 +159,7 @@ private static void parseXmlPortion(DiffReport diffReport,
int counter = numOfFilenames;
String filename = null;
List<CheckstyleRecord> records = null;
final List<CompletableFuture<Void>> tasks = new ArrayList<>();
while (reader.hasNext()) {
final XMLEvent event = reader.nextEvent();
if (event.isStartElement()) {
Expand Down Expand Up @@ -187,13 +190,20 @@ else if (startElementName.equals(ERROR_TAG)) {
if (event.isEndElement()) {
final EndElement endElement = event.asEndElement();
if (endElement.getName().getLocalPart().equals(FILE_TAG)) {
diffReport.addRecords(records, filename);
final List<CheckstyleRecord> currRecords = records;
records = null;
final String currFile = filename;
filename = null;
tasks.add(CompletableFuture.runAsync(() -> {
diffReport.addRecords(currRecords, currFile);
}));
if (counter == 0) {
break;
}
}
}
}
tasks.forEach(CompletableFuture::join);
}

/**
Expand Down

0 comments on commit f0ca9ad

Please sign in to comment.