Author: rwhitcomb Date: Fri Apr 27 17:16:50 2018 New Revision: 1830370 URL: http://svn.apache.org/viewvc?rev=1830370&view=rev Log: PIVOT-1032: Add a program to summarize the results of the "check style" task. Note: not updating the "build.xml" yet because it would require the check-style plugin to be available with the Ant files.
Added: pivot/trunk/StyleErrors.java Added: pivot/trunk/StyleErrors.java URL: http://svn.apache.org/viewvc/pivot/trunk/StyleErrors.java?rev=1830370&view=auto ============================================================================== --- pivot/trunk/StyleErrors.java (added) +++ pivot/trunk/StyleErrors.java Fri Apr 27 17:16:50 2018 @@ -0,0 +1,151 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Read the file(s) given on the command line, which are presumed to be + * the output of the "check styles", and generate a summary of the results. + */ +public final class StyleErrors { + /** Private constructor because we only use static methods here. */ + private StyleErrors() { + } + + /** + * A summary object holding one type of error and the number of times + * it was encountered. + */ + private static class Info { + /** The error class from the check styles configuration. */ + private String errorClass; + /** The final count of how many times this error was encountered. */ + private Integer count; + + /** Construct one of these with the given information. + * @param errClass The checkstyle error. + * @param c The final count of these errors. + */ + Info(final String errClass, final Integer c) { + this.errorClass = errClass; + this.count = c; + } + /** @return The saved checkstyle error name. */ + String getErrorClass() { + return errorClass; + } + /** @return The final count of this error type. */ + Integer getCount() { + return count; + } + } + + /** + * A comparator that sorts first by count and then by the error class name. + */ + private static Comparator<Info> comparator = new Comparator<Info>() { + @Override + public int compare(final Info o1, final Info o2) { + // Order first by count, then by class name + int c1 = o1.count.intValue(); + int c2 = o2.count.intValue(); + if (c1 == c2) { + return o1.errorClass.compareTo(o2.errorClass); + } else { + return Integer.signum(c1 - c2); + } + } + }; + + /** Pattern used to parse each input line. */ + private static final Pattern LINE_PATTERN = + Pattern.compile("^\\[[A-Z]+\\]\\s+(.+)\\:(\\d+)\\:(\\d+\\:)?\\s+(.+)\\s+(\\[[a-zA-Z]+\\])$"); + /** The group in the {@link #LINE_PATTERN} that contains the checkstyle error name. */ + private static final int CLASS_NAME_GROUP = 5; + /** A format string used to output all the information in a uniform manner. */ + private static final String FORMAT = "%1$-32s%2$5d%n"; + /** Format string used to print the underlines. */ + private static final String UNDER_FORMAT = "%1$-32s%2$5s%n"; + /** For each type of checkstyle error, the name and running count for each. */ + private static Map<String, Integer> counts = new TreeMap<>(); + /** At the end of each file, the list used to sort by count and name. */ + private static List<Info> sortedList = new ArrayList<>(); + + /** + * The main method, executed from the command line, which reads through each file + * and processes it. + * @param args The command line arguments. + */ + public static void main(final String[] args) { + for (String arg : args) { + int lineNo = 0; + counts.clear(); + sortedList.clear(); + try (BufferedReader reader = new BufferedReader(new FileReader(new File(arg)))) { + String line; + while ((line = reader.readLine()) != null) { + lineNo++; + Matcher m = LINE_PATTERN.matcher(line); + if (m.matches()) { + String errorClass = m.group(CLASS_NAME_GROUP); + Integer count = counts.get(errorClass); + if (count == null) { + count = Integer.valueOf(1); + } else { + int i = count.intValue() + 1; + count = Integer.valueOf(i); + } + counts.put(errorClass, count); + } else if (line.equals("Starting audit...") || line.equals("Audit done.")) { + continue; + } else { + System.err.println("Line " + lineNo + ". Doesn't match the pattern."); + System.err.println("\t" + line); + } + } + } catch (IOException ioe) { + System.err.println("Error reading the \"" + arg + "\" file: " + ioe.getMessage()); + } + int total = 0; + for (String key : counts.keySet()) { + Integer count = counts.get(key); + total += count.intValue(); + Info info = new Info(key, count); + sortedList.add(info); + } + Collections.sort(sortedList, comparator); + for (Info info : sortedList) { + System.out.format(FORMAT, info.getErrorClass(), info.getCount()); + } + System.out.format(UNDER_FORMAT, "----------------------------", "-----"); + System.out.format(FORMAT, "Grand Total", total); + System.out.println(); + } + } + +} +