This is an automated email from the ASF dual-hosted git repository. eolivelli pushed a commit to branch MCHECKSTYLE-385 in repository https://gitbox.apache.org/repos/asf/maven-checkstyle-plugin.git
commit 4fa63778766714a2ae918d68d8743ce13215c6cd Author: Benjamin Marwell <bmarw...@gmail.com> AuthorDate: Wed Dec 11 22:51:48 2019 +0100 [MCHECKSTYLE-385] Violation should be a value class --- .../checkstyle/CheckstyleViolationCheckMojo.java | 137 ++++++++---- .../apache/maven/plugins/checkstyle/Violation.java | 229 +++++++++++++++++++++ 2 files changed, 323 insertions(+), 43 deletions(-) diff --git a/src/main/java/org/apache/maven/plugins/checkstyle/CheckstyleViolationCheckMojo.java b/src/main/java/org/apache/maven/plugins/checkstyle/CheckstyleViolationCheckMojo.java index b9c47d7..42c738e 100644 --- a/src/main/java/org/apache/maven/plugins/checkstyle/CheckstyleViolationCheckMojo.java +++ b/src/main/java/org/apache/maven/plugins/checkstyle/CheckstyleViolationCheckMojo.java @@ -156,10 +156,10 @@ public class CheckstyleViolationCheckMojo */ @Parameter( property = "checkstyle.console", defaultValue = "true" ) private boolean logViolationsToConsole; - + /** * Output the detected violation count to the console. - * + * * @since 3.0.1 */ @Parameter( property = "checkstyle.logViolationCount", defaultValue = "true" ) @@ -577,11 +577,14 @@ public class CheckstyleViolationCheckMojo XmlPullParser xpp = new MXParser(); xpp.setInput( reader ); - int violations = countViolations( xpp ); + final List<Violation> violationsList = getViolations( xpp ); + long violationCount = countViolations( violationsList ); + printViolations( violationsList ); + + String msg = "You have " + violationCount + " Checkstyle violation" + + ( ( violationCount > 1 || violationCount == 0 ) ? "s" : "" ) + "."; - String msg = "You have " + violations + " Checkstyle violation" - + ( ( violations > 1 || violations == 0 ) ? "s" : "" ) + "."; - if ( violations > maxAllowedViolations ) + if ( violationCount > maxAllowedViolations ) { if ( failOnViolation ) { @@ -591,7 +594,7 @@ public class CheckstyleViolationCheckMojo } throw new MojoFailureException( msg ); } - + getLog().warn( "checkstyle:check violations detected but failOnViolation set to false" ); } if ( logViolationCountToConsole ) @@ -621,16 +624,14 @@ public class CheckstyleViolationCheckMojo } } - private int countViolations( XmlPullParser xpp ) + private List<Violation> getViolations( XmlPullParser xpp ) throws XmlPullParserException, IOException { - int count = 0; - int ignoreCount = 0; - List<RuleUtil.Matcher> ignores = violationIgnore == null ? Collections.<RuleUtil.Matcher>emptyList() - : RuleUtil.parseMatchers( violationIgnore.split( "," ) ); + List<Violation> violations = new ArrayList<>(); String basedir = project.getBasedir().getAbsolutePath(); String file = ""; + for ( int eventType = xpp.getEventType(); eventType != XmlPullParser.END_DOCUMENT; eventType = xpp.next() ) { if ( eventType != XmlPullParser.START_TAG ) @@ -640,49 +641,99 @@ public class CheckstyleViolationCheckMojo else if ( "file".equals( xpp.getName() ) ) { file = PathTool.getRelativeFilePath( basedir, xpp.getAttributeValue( "", "name" ) ); - //file = file.substring( file.lastIndexOf( File.separatorChar ) + 1 ); + continue; } - else if ( "error".equals( xpp.getName() ) ) + else if ( ! "error".equals( xpp.getName() ) ) { - String severity = xpp.getAttributeValue( "", "severity" ); + continue; + } - if ( !isViolation( severity ) ) - { - continue; - } + String severity = xpp.getAttributeValue( "", "severity" ); + String source = xpp.getAttributeValue( "", "source" ); + String line = xpp.getAttributeValue( "", "line" ); + /* Nullable */ + String column = xpp.getAttributeValue( "", "column" ); + String message = xpp.getAttributeValue( "", "message" ); + String rule = RuleUtil.getName( source ); + String category = RuleUtil.getCategory( source ); + + Violation violation = new Violation( + source, + file, + line, + severity, + message, + rule, + category + ); + if ( column != null ) + { + violation.setColumn( column ); + } - String source = xpp.getAttributeValue( "", "source" ); + violations.add( violation ); + } - if ( ignore( ignores, source ) ) - { - ignoreCount++; - } - else - { - count++; + return violations; + } - if ( logViolationsToConsole ) - { - String line = xpp.getAttributeValue( "", "line" ); - String column = xpp.getAttributeValue( "", "column" ); - String message = xpp.getAttributeValue( "", "message" ); - String rule = RuleUtil.getName( source ); - String category = RuleUtil.getCategory( source ); - - log( severity, file + ":[" + line + ( ( column == null ) ? "" : ( ',' + column ) ) + "] (" - + category + ") " + rule + ": " + message ); - } - } + private int countViolations( List<Violation> violations ) + { + List<RuleUtil.Matcher> ignores = violationIgnore == null ? Collections.<RuleUtil.Matcher>emptyList() + : RuleUtil.parseMatchers( violationIgnore.split( "," ) ); + + int ignored = 0; + int countedViolations = 0; + + for ( Violation violation : violations ) + { + if ( ! isViolation( violation.getSeverity() ) ) + { + continue; + } + + if ( ignore( ignores, violation.getSource() ) ) + { + ignored++; + continue; } + + countedViolations++; } - if ( ignoreCount > 0 ) + if ( ignored > 0 ) { - getLog().info( "Ignored " + ignoreCount + " error" + ( ( ignoreCount > 1 ) ? "s" : "" ) + ", " + count - + " violation" + ( ( count > 1 ) ? "s" : "" ) + " remaining." ); + getLog().info( "Ignored " + ignored + " error" + ( ( ignored > 1L ) ? "s" : "" ) + ", " + countedViolations + + " violation" + ( ( countedViolations > 1 ) ? "s" : "" ) + " remaining." ); } - return count; + return countedViolations; + } + + private void printViolations( List<Violation> violations ) + { + if ( ! logViolationsToConsole ) + { + return; + } + + List<RuleUtil.Matcher> ignores = violationIgnore == null ? Collections.<RuleUtil.Matcher>emptyList() + : RuleUtil.parseMatchers( violationIgnore.split( "," ) ); + + violations.stream() + .filter( violation -> isViolation( violation.getSeverity() ) ) + .filter( violation -> !ignore( ignores, violation.getSource() ) ) + .forEach( violation -> + { + final String message = String.format( "%s:[%s%s] (%s) %s: %s", + violation.getFile(), + violation.getLine(), + ( Violation.NO_COLUMN.equals( violation.getColumn() ) ) ? "" : ( ',' + violation.getColumn() ), + violation.getCategory(), + violation.getRuleName(), + violation.getMessage() ); + log( violation.getSeverity(), message ); + } ); } private void log( String severity, String message ) diff --git a/src/main/java/org/apache/maven/plugins/checkstyle/Violation.java b/src/main/java/org/apache/maven/plugins/checkstyle/Violation.java new file mode 100644 index 0000000..803e948 --- /dev/null +++ b/src/main/java/org/apache/maven/plugins/checkstyle/Violation.java @@ -0,0 +1,229 @@ +package org.apache.maven.plugins.checkstyle; + +/* + * 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.util.Objects; +import java.util.StringJoiner; + +/** + * Holds data about a single violation and represents the violation itself. + */ +class Violation +{ + + /** + * Indicates that a column is not set. + */ + protected static final String NO_COLUMN = "-1"; + + /** The full qualified class name of the checkstyle rule */ + private final String source; + + /** The absolute path of the file containing the violation */ + private final String file; + + private final String line; + + private String column = NO_COLUMN; + + private final String severity; + + private final String message; + + private final String ruleName; + + private final String category; + + // Leaving out column, because there is no CHECKSTYLE:OFF support. + + /** + * Creates a violation instance without a column set. + * + * @param source + * the fully qualified class name of the checkstyle rule + * @param file + * the absolute file path in which the violation occurred + * @param line + * the line in the file on which the violation occurred + * @param severity + * the severity of the violation + * @param message + * the message from checkstyle for this violation + * @param ruleName + * the rule name from which this violation was created + * @param category + * the category of the checkstyle violation + */ + Violation( String source, + String file, + String line, + String severity, + String message, + String ruleName, + String category ) + { + this.source = Objects.requireNonNull( source ); + this.file = file; + this.line = line; + this.severity = Objects.requireNonNull( severity ); + this.message = Objects.requireNonNull( message ); + this.ruleName = Objects.requireNonNull( ruleName ); + this.category = Objects.requireNonNull( category ); + } + + /** + * Returns the fully qualified class name of the checker rule. + * + * @return the fully qualified class name of the checker rule + */ + protected String getSource( ) + { + return source; + } + + /** + * Returns the absolute file path to the checked file. + * + * @return the absolute file path to the checked file + */ + protected String getFile( ) + { + return file; + } + + /** + * Returns the line in the checked file on which the violation occurred. + * + * @return the line in the checked file on which the violation occurred + */ + protected String getLine( ) + { + return line; + } + + /** + * Returns the column in which the violation occurred, if available. + * + * @return the column in which the violation occurred, if available. Otherwise returns {@link #NO_COLUMN}. + */ + protected String getColumn( ) + { + return column; + } + + /** + * Sets the column value for this violation to the given string value. + * @param column the column value to set. May be {@code null}, which will set it to the {@link #NO_COLUMN} value. + */ + protected void setColumn( /* Nullable */ String column ) + { + if ( column == null || column.length() < 1 ) + { + this.column = NO_COLUMN; + } + else + { + this.column = column; + } + } + + /** + * Returns the severity of the current violation. + * + * @return the severity of the current violation + */ + protected String getSeverity( ) + { + return severity; + } + + /** + * Returns the message produced by checkstyle for the current violation. + * + * @return the message produced by checkstyle for the current violation + */ + protected String getMessage( ) + { + return message; + } + + /** + * Returns the name of the rule which led to the current violation. + * + * @return the name of the rule which led to the current violation + */ + protected String getRuleName( ) + { + return ruleName; + } + + /** + * Returns the category of the current violation. + * + * @return the category of the current violation + */ + protected String getCategory( ) + { + return category; + } + + @Override + public boolean equals( Object other ) + { + if ( this == other ) + { + return true; + } + if ( !( other instanceof Violation ) ) + { + return false; + } + Violation violation = ( Violation ) other; + return line.equals( violation.line ) + && Objects.equals( column, violation.column ) + && source.equals( violation.source ) + && file.equals( violation.file ) + && severity.equals( violation.severity ) + && message.equals( violation.message ) + && ruleName.equals( violation.ruleName ) + && category.equals( violation.category ); + } + + @Override + public int hashCode() + { + return Objects.hash( source, file, line, column, severity, message, ruleName, category ); + } + + @Override + public String toString() + { + return new StringJoiner( ", ", Violation.class.getSimpleName() + "[", "]" ) + .add( "source='" + source + "'" ) + .add( "file='" + file + "'" ) + .add( "line=" + line ) + .add( "column=" + column ) + .add( "severity='" + severity + "'" ) + .add( "message='" + message + "'" ) + .add( "ruleName='" + ruleName + "'" ) + .add( "category='" + category + "'" ) + .toString(); + } +}