All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.maven.plugins.checkstyle.CheckstyleViolationCheckMojo Maven / Gradle / Ivy

Go to download

Generates a report on violations of code style and optionally fails the build if violations are detected.

There is a newer version: 3.6.0
Show newest version
/*
 * 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.
 */
package org.apache.maven.plugins.checkstyle;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Reader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import com.puppycrawl.tools.checkstyle.DefaultLogger;
import com.puppycrawl.tools.checkstyle.SarifLogger;
import com.puppycrawl.tools.checkstyle.XMLLogger;
import com.puppycrawl.tools.checkstyle.api.AuditListener;
import com.puppycrawl.tools.checkstyle.api.AutomaticBean.OutputStreamOptions;
import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.model.Dependency;
import org.apache.maven.model.Plugin;
import org.apache.maven.model.PluginManagement;
import org.apache.maven.model.Resource;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugin.descriptor.PluginDescriptor;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.plugins.annotations.ResolutionScope;
import org.apache.maven.plugins.checkstyle.exec.CheckstyleExecutor;
import org.apache.maven.plugins.checkstyle.exec.CheckstyleExecutorException;
import org.apache.maven.plugins.checkstyle.exec.CheckstyleExecutorRequest;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.configuration.PlexusConfiguration;
import org.codehaus.plexus.util.FileUtils;
import org.codehaus.plexus.util.PathTool;
import org.codehaus.plexus.util.ReaderFactory;
import org.codehaus.plexus.util.xml.pull.MXParser;
import org.codehaus.plexus.util.xml.pull.XmlPullParser;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;

/**
 * Performs Checkstyle analysis and outputs violations or a count of violations
 * to the console, potentially failing the build.
 * It can also be configured to re-use an earlier analysis.
 *
 * @author Joakim Erdfelt
 *
 */
@Mojo(
        name = "check",
        defaultPhase = LifecyclePhase.VERIFY,
        requiresDependencyResolution = ResolutionScope.NONE,
        threadSafe = true)
public class CheckstyleViolationCheckMojo extends AbstractMojo {

    private static final String JAVA_FILES = "**\\/*.java";
    private static final String DEFAULT_CONFIG_LOCATION = "sun_checks.xml";

    /**
     * Specifies the path and filename to save the Checkstyle output. The format
     * of the output file is determined by the outputFileFormat
     * parameter.
     */
    @Parameter(property = "checkstyle.output.file", defaultValue = "${project.build.directory}/checkstyle-result.xml")
    private File outputFile;

    /**
     * Specifies the format of the output to be used when writing to the output
     * file. Valid values are "plain", "sarif" and "xml".
     */
    @Parameter(property = "checkstyle.output.format", defaultValue = "xml")
    private String outputFileFormat;

    /**
     * Fail the build on a violation. The goal checks for the violations
     * after logging them (if {@link #logViolationsToConsole} is {@code true}).
     * Compare this to {@link #failsOnError} which fails the build immediately
     * before examining the output log.
     */
    @Parameter(property = "checkstyle.failOnViolation", defaultValue = "true")
    private boolean failOnViolation;

    /**
     * The maximum number of allowed violations. The execution fails only if the
     * number of violations is above this limit.
     *
     * @since 2.3
     */
    @Parameter(property = "checkstyle.maxAllowedViolations", defaultValue = "0")
    private int maxAllowedViolations;

    /**
     * The lowest severity level that is considered a violation.
     * Valid values are "error", "warning" and "info".
     *
     * @since 2.2
     */
    @Parameter(property = "checkstyle.violationSeverity", defaultValue = "error")
    private String violationSeverity = "error";

    /**
     * Violations to ignore. This is a comma-separated list, each value being either
     * a rule name, a rule category or a java package name of rule class.
     *
     * @since 2.13
     */
    @Parameter(property = "checkstyle.violation.ignore")
    private String violationIgnore;

    /**
     * Skip entire check.
     *
     * @since 2.2
     */
    @Parameter(property = "checkstyle.skip", defaultValue = "false")
    private boolean skip;

    /**
     * Skip Checkstyle execution will only scan the outputFile.
     *
     * @since 2.5
     */
    @Parameter(property = "checkstyle.skipExec", defaultValue = "false")
    private boolean skipExec;

    /**
     * Output the detected violations to the console.
     *
     * @since 2.3
     */
    @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")
    private boolean logViolationCountToConsole;

    /**
     * Specifies the location of the resources to be used for Checkstyle.
     *
     * @since 2.11
     */
    @Parameter(defaultValue = "${project.resources}", readonly = true)
    protected List resources;

    /**
     * Specifies the location of the test resources to be used for Checkstyle.
     *
     * @since 2.16
     */
    @Parameter(defaultValue = "${project.testResources}", readonly = true)
    protected List testResources;

    /**
     * 

* Specifies the location of the XML configuration to use. *

* Potential values are a filesystem path, a URL, or a classpath resource. * This parameter expects that the contents of the location conform to the * xml format (Checkstyle Checker * module) configuration of rulesets. *

* This parameter is resolved as resource, URL, then file. If successfully * resolved, the contents of the configuration is copied into the * ${project.build.directory}/checkstyle-configuration.xml * file before being passed to Checkstyle as a configuration. *

* There are 2 predefined rulesets. *

    *
  • sun_checks.xml: Sun Checks.
  • *
  • google_checks.xml: Google Checks.
  • *
* * @since 2.5 */ @Parameter(property = "checkstyle.config.location", defaultValue = DEFAULT_CONFIG_LOCATION) private String configLocation; /** *

* Specifies the location of the properties file. *

* This parameter is resolved as URL, File then resource. If successfully * resolved, the contents of the properties location is copied into the * ${project.build.directory}/checkstyle-checker.properties * file before being passed to Checkstyle for loading. *

* The contents of the propertiesLocation will be made * available to Checkstyle for specifying values for parameters within the * xml configuration (specified in the configLocation * parameter). * * @since 2.5 */ @Parameter(property = "checkstyle.properties.location") private String propertiesLocation; /** * Allows for specifying raw property expansion information. */ @Parameter private String propertyExpansion; /** *

* Specifies the location of the License file (a.k.a. the header file) that * can be used by Checkstyle to verify that source code has the correct * license header. *

* You need to use ${checkstyle.header.file} in your Checkstyle xml * configuration to reference the name of this header file. *

* For instance: *

     * <module name="RegexpHeader">
     *   <property name="headerFile" value="${checkstyle.header.file}"/>
     * </module>
     * 
* * @since 2.0-beta-2 */ @Parameter(property = "checkstyle.header.file", defaultValue = "LICENSE.txt") private String headerLocation; /** * Specifies the cache file used to speed up Checkstyle on successive runs. */ @Parameter(defaultValue = "${project.build.directory}/checkstyle-cachefile") private String cacheFile; /** * The key to be used in the properties for the suppressions file. * * @since 2.1 */ @Parameter(property = "checkstyle.suppression.expression", defaultValue = "checkstyle.suppressions.file") private String suppressionsFileExpression; /** *

* Specifies the location of the suppressions XML file to use. *

* This parameter is resolved as resource, URL, then file. If successfully * resolved, the contents of the suppressions XML is copied into the * ${project.build.directory}/checkstyle-suppressions.xml file * before being passed to Checkstyle for loading. *

* See suppressionsFileExpression for the property that will * be made available to your Checkstyle configuration. * * @since 2.0-beta-2 */ @Parameter(property = "checkstyle.suppressions.location") private String suppressionsLocation; /** * The file encoding to use when reading the source files. If the property project.build.sourceEncoding * is not set, the platform default encoding is used. Note: This parameter always overrides the * property charset from Checkstyle's TreeWalker module. * * @since 2.2 */ @Parameter(property = "encoding", defaultValue = "${project.build.sourceEncoding}") private String inputEncoding; /** * @since 2.5 */ @Component(role = CheckstyleExecutor.class, hint = "default") protected CheckstyleExecutor checkstyleExecutor; /** * Output errors to console. */ @Parameter(property = "checkstyle.consoleOutput", defaultValue = "false") private boolean consoleOutput; /** * The Maven Project Object. */ @Parameter(defaultValue = "${project}", readonly = true, required = true) protected MavenProject project; /** * The Plugin Descriptor */ @Parameter(defaultValue = "${plugin}", readonly = true, required = true) private PluginDescriptor plugin; /** * If null, the Checkstyle plugin will display violations on stdout. * Otherwise, a text file will be created with the violations. */ @Parameter private File useFile; /** * Specifies the names filter of the source files to be excluded for * Checkstyle. */ @Parameter(property = "checkstyle.excludes") private String excludes; /** * Specifies the names filter of the source files to be used for Checkstyle. */ @Parameter(property = "checkstyle.includes", defaultValue = JAVA_FILES, required = true) private String includes; /** * Specifies the names filter of the files to be excluded for * Checkstyle when checking resources. * @since 2.11 */ @Parameter(property = "checkstyle.resourceExcludes") private String resourceExcludes; /** * Specifies the names filter of the files to be used for Checkstyle when checking resources. * @since 2.11 */ @Parameter(property = "checkstyle.resourceIncludes", defaultValue = "**/*.properties", required = true) private String resourceIncludes; /** * If this is true, and Checkstyle reported any violations or errors, * the build fails immediately after running Checkstyle, before checking the log * for {@link #logViolationsToConsole}. If you want to use {@link #logViolationsToConsole}, * use {@link #failOnViolation} instead of this. */ @Parameter(defaultValue = "false") private boolean failsOnError; /** * Specifies the location of the test source directory to be used for Checkstyle. * * @since 2.2 * @deprecated instead use {@link #testSourceDirectories}. For version 3.0.0, this parameter is only defined to * break the build if you use it! */ @Deprecated @Parameter private File testSourceDirectory; /** * Specifies the location of the test source directories to be used for Checkstyle. * Default value is ${project.testCompileSourceRoots}. * @since 2.13 */ // Compatibility with all Maven 3: default of 'project.testCompileSourceRoots' is done manually because of MNG-5440 @Parameter private List testSourceDirectories; /** * Include or not the test source directory to be used for Checkstyle. * * @since 2.2 */ @Parameter(defaultValue = "false") private boolean includeTestSourceDirectory; /** * Specifies the location of the source directory to be used for Checkstyle. * * @deprecated instead use {@link #sourceDirectories}. For version 3.0.0, this parameter is only defined to break * the build if you use it! */ @Deprecated @Parameter private File sourceDirectory; /** * Specifies the location of the source directories to be used for Checkstyle. * Default value is ${project.compileSourceRoots}. * @since 2.13 */ // Compatibility with all Maven 3: default of 'project.compileSourceRoots' is done manually because of MNG-5440 @Parameter private List sourceDirectories; /** * Whether to apply Checkstyle to resource directories. * @since 2.11 */ @Parameter(property = "checkstyle.includeResources", defaultValue = "true", required = true) private boolean includeResources = true; /** * Whether to apply Checkstyle to test resource directories. * @since 2.11 */ @Parameter(property = "checkstyle.includeTestResources", defaultValue = "true", required = true) private boolean includeTestResources = true; /** * By using this property, you can specify the whole Checkstyle rules * inline directly inside this pom. * *

     * <plugin>
     *   ...
     *   <configuration>
     *     <checkstyleRules>
     *       <module name="Checker">
     *         <module name="FileTabCharacter">
     *           <property name="eachLine" value="true" />
     *         </module>
     *         <module name="TreeWalker">
     *           <module name="EmptyBlock"/>
     *         </module>
     *       </module>
     *     </checkstyleRules>
     *   </configuration>
     *   ...
     * 
* * @since 2.12 */ @Parameter private PlexusConfiguration checkstyleRules; /** * Dump file for inlined Checkstyle rules. */ @Parameter( property = "checkstyle.output.rules.file", defaultValue = "${project.build.directory}/checkstyle-rules.xml") private File rulesFiles; /** * The header to use for the inline configuration. * Only used when you specify {@code checkstyleRules}. */ @Parameter( defaultValue = "\n" + "\n") private String checkstyleRulesHeader; /** * Specifies whether modules with a configured severity of ignore should be omitted during Checkstyle * invocation. * * @since 3.0.0 */ @Parameter(defaultValue = "false") private boolean omitIgnoredModules; /** * Specifies whether generated source files should be excluded from Checkstyle. * * @since 3.3.1 */ @Parameter(property = "checkstyle.excludeGeneratedSources", defaultValue = "false") private boolean excludeGeneratedSources; private ByteArrayOutputStream stringOutputStream; private File outputXmlFile; /** {@inheritDoc} */ public void execute() throws MojoExecutionException, MojoFailureException { checkDeprecatedParameterUsage(sourceDirectory, "sourceDirectory", "sourceDirectories"); checkDeprecatedParameterUsage(testSourceDirectory, "testSourceDirectory", "testSourceDirectories"); if (skip) { return; } outputXmlFile = outputFile; if (!skipExec) { String effectiveConfigLocation = configLocation; if (checkstyleRules != null) { if (!DEFAULT_CONFIG_LOCATION.equals(configLocation)) { throw new MojoExecutionException( "If you use inline configuration for rules, don't specify " + "a configLocation"); } if (checkstyleRules.getChildCount() > 1) { throw new MojoExecutionException("Currently only one root module is supported"); } PlexusConfiguration checkerModule = checkstyleRules.getChild(0); try { FileUtils.forceMkdir(rulesFiles.getParentFile()); FileUtils.fileWrite(rulesFiles, checkstyleRulesHeader + checkerModule.toString()); } catch (final IOException e) { throw new MojoExecutionException(e.getMessage(), e); } effectiveConfigLocation = rulesFiles.getAbsolutePath(); } ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader(); try { CheckstyleExecutorRequest request = new CheckstyleExecutorRequest(); request.setConsoleListener(getConsoleListener()) .setConsoleOutput(consoleOutput) .setExcludes(excludes) .setFailsOnError(failsOnError) .setIncludes(includes) .setResourceIncludes(resourceIncludes) .setResourceExcludes(resourceExcludes) .setIncludeResources(includeResources) .setIncludeTestResources(includeTestResources) .setIncludeTestSourceDirectory(includeTestSourceDirectory) .setListener(getListener()) .setProject(project) .setSourceDirectories(getSourceDirectories()) .setResources(resources) .setTestResources(testResources) .setStringOutputStream(stringOutputStream) .setSuppressionsLocation(suppressionsLocation) .setTestSourceDirectories(getTestSourceDirectories()) .setConfigLocation(effectiveConfigLocation) .setConfigurationArtifacts(collectArtifacts("config")) .setPropertyExpansion(propertyExpansion) .setHeaderLocation(headerLocation) .setLicenseArtifacts(collectArtifacts("license")) .setCacheFile(cacheFile) .setSuppressionsFileExpression(suppressionsFileExpression) .setEncoding(inputEncoding) .setPropertiesLocation(propertiesLocation) .setOmitIgnoredModules(omitIgnoredModules); checkstyleExecutor.executeCheckstyle(request); } catch (CheckstyleException e) { throw new MojoExecutionException("Failed during checkstyle configuration", e); } catch (CheckstyleExecutorException e) { throw new MojoExecutionException("Failed during checkstyle execution", e); } finally { // be sure to restore original context classloader Thread.currentThread().setContextClassLoader(currentClassLoader); } } if (!"xml".equals(outputFileFormat) && skipExec) { throw new MojoExecutionException("Output format is '" + outputFileFormat + "', checkstyle:check requires format to be 'xml' when using skipExec."); } if (!outputXmlFile.exists()) { getLog().info("Unable to perform checkstyle:check, unable to find checkstyle:checkstyle outputFile."); return; } try (Reader reader = new BufferedReader(ReaderFactory.newXmlReader(outputXmlFile))) { XmlPullParser xpp = new MXParser(); xpp.setInput(reader); final List violationsList = getViolations(xpp); long violationCount = countViolations(violationsList); printViolations(violationsList); String msg = "You have " + violationCount + " Checkstyle violation" + ((violationCount > 1 || violationCount == 0) ? "s" : "") + "."; if (violationCount > maxAllowedViolations) { if (failOnViolation) { if (maxAllowedViolations > 0) { msg += " The maximum number of allowed violations is " + maxAllowedViolations + "."; } throw new MojoFailureException(msg); } getLog().warn("checkstyle:check violations detected but failOnViolation set to false"); } if (logViolationCountToConsole) { if (maxAllowedViolations > 0) { msg += " The maximum number of allowed violations is " + maxAllowedViolations + "."; } getLog().info(msg); } } catch (IOException | XmlPullParserException e) { throw new MojoExecutionException( "Unable to read Checkstyle results xml: " + outputXmlFile.getAbsolutePath(), e); } } private void checkDeprecatedParameterUsage(Object parameter, String name, String replacement) throws MojoFailureException { if (parameter != null) { throw new MojoFailureException("You are using '" + name + "' which has been removed" + " from the maven-checkstyle-plugin. " + "Please use '" + replacement + "' and refer to the >>Major Version Upgrade to version 3.0.0<< " + "on the plugin site."); } } private List getViolations(XmlPullParser xpp) throws XmlPullParserException, IOException { List 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) { continue; } else if ("file".equals(xpp.getName())) { file = PathTool.getRelativeFilePath(basedir, xpp.getAttributeValue("", "name")); continue; } else if (!"error".equals(xpp.getName())) { 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); } violations.add(violation); } return violations; } private int countViolations(List violations) { List ignores = violationIgnore == null ? Collections.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 (ignored > 0) { getLog().info("Ignored " + ignored + " error" + ((ignored > 1L) ? "s" : "") + ", " + countedViolations + " violation" + ((countedViolations > 1) ? "s" : "") + " remaining."); } return countedViolations; } private void printViolations(List violations) { if (!logViolationsToConsole) { return; } List ignores = violationIgnore == null ? Collections.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) { if ("info".equals(severity)) { getLog().info(message); } else if ("warning".equals(severity)) { getLog().warn(message); } else { getLog().error(message); } } /** * Checks if the given severity is considered a violation. * * @param severity The severity to check * @return true if the given severity is a violation, otherwise false */ private boolean isViolation(String severity) { if ("error".equals(severity)) { return "error".equals(violationSeverity) || "warning".equals(violationSeverity) || "info".equals(violationSeverity); } else if ("warning".equals(severity)) { return "warning".equals(violationSeverity) || "info".equals(violationSeverity); } else if ("info".equals(severity)) { return "info".equals(violationSeverity); } else { return false; } } private boolean ignore(List ignores, String source) { for (RuleUtil.Matcher ignore : ignores) { if (ignore.match(source)) { return true; } } return false; } private DefaultLogger getConsoleListener() throws MojoExecutionException { DefaultLogger consoleListener; if (useFile == null) { stringOutputStream = new ByteArrayOutputStream(); consoleListener = new DefaultLogger(stringOutputStream, OutputStreamOptions.NONE); } else { OutputStream out = getOutputStream(useFile); consoleListener = new DefaultLogger(out, OutputStreamOptions.CLOSE); } return consoleListener; } private OutputStream getOutputStream(File file) throws MojoExecutionException { File parentFile = file.getAbsoluteFile().getParentFile(); if (!parentFile.exists()) { parentFile.mkdirs(); } FileOutputStream fileOutputStream; try { fileOutputStream = new FileOutputStream(file); } catch (FileNotFoundException e) { throw new MojoExecutionException("Unable to create output stream: " + file, e); } return fileOutputStream; } private AuditListener getListener() throws MojoFailureException, MojoExecutionException { AuditListener listener = null; if (outputFileFormat != null && !outputFileFormat.isEmpty()) { File resultFile = outputFile; OutputStream out = getOutputStream(resultFile); if ("xml".equals(outputFileFormat)) { listener = new XMLLogger(out, OutputStreamOptions.CLOSE); } else if ("plain".equals(outputFileFormat)) { try { // Write a plain output file to the standard output file, // and write an XML output file to the temp directory that can be used to count violations outputXmlFile = Files.createTempFile("checkstyle-result", ".xml").toFile(); outputXmlFile.deleteOnExit(); OutputStream xmlOut = getOutputStream(outputXmlFile); CompositeAuditListener compoundListener = new CompositeAuditListener(); compoundListener.addListener(new XMLLogger(xmlOut, OutputStreamOptions.CLOSE)); compoundListener.addListener(new DefaultLogger(out, OutputStreamOptions.CLOSE)); listener = compoundListener; } catch (IOException e) { throw new MojoExecutionException("Unable to create temporary file", e); } } else if ("sarif".equals(outputFileFormat)) { try { // Write a sarif output file to the standard output file, // and write an XML output file to the temp directory that can be used to count violations outputXmlFile = Files.createTempFile("checkstyle-result", ".xml").toFile(); outputXmlFile.deleteOnExit(); OutputStream xmlOut = getOutputStream(outputXmlFile); CompositeAuditListener compoundListener = new CompositeAuditListener(); compoundListener.addListener(new XMLLogger(xmlOut, OutputStreamOptions.CLOSE)); compoundListener.addListener(new SarifLogger(out, OutputStreamOptions.CLOSE)); listener = compoundListener; } catch (IOException e) { throw new MojoExecutionException("Unable to create temporary file", e); } } else { throw new MojoFailureException( "Invalid output file format: (" + outputFileFormat + "). Must be 'plain' or 'xml'."); } } return listener; } private List collectArtifacts(String hint) { List artifacts = new ArrayList<>(); PluginManagement pluginManagement = project.getBuild().getPluginManagement(); if (pluginManagement != null) { artifacts.addAll(getCheckstylePluginDependenciesAsArtifacts(pluginManagement.getPluginsAsMap(), hint)); } artifacts.addAll( getCheckstylePluginDependenciesAsArtifacts(project.getBuild().getPluginsAsMap(), hint)); return artifacts; } private List getCheckstylePluginDependenciesAsArtifacts(Map plugins, String hint) { List artifacts = new ArrayList<>(); Plugin checkstylePlugin = plugins.get(plugin.getGroupId() + ":" + plugin.getArtifactId()); if (checkstylePlugin != null) { for (Dependency dep : checkstylePlugin.getDependencies()) { // @todo if we can filter on hints, it should be done here... String depKey = dep.getGroupId() + ":" + dep.getArtifactId(); artifacts.add(plugin.getArtifactMap().get(depKey)); } } return artifacts; } private List getSourceDirectories() { if (sourceDirectories == null) { sourceDirectories = filterBuildTarget(project.getCompileSourceRoots()); } List sourceDirs = new ArrayList<>(sourceDirectories.size()); for (String sourceDir : sourceDirectories) { sourceDirs.add(FileUtils.resolveFile(project.getBasedir(), sourceDir)); } return sourceDirs; } private List getTestSourceDirectories() { if (testSourceDirectories == null) { testSourceDirectories = filterBuildTarget(project.getTestCompileSourceRoots()); } List testSourceDirs = new ArrayList<>(testSourceDirectories.size()); for (String testSourceDir : testSourceDirectories) { testSourceDirs.add(FileUtils.resolveFile(project.getBasedir(), testSourceDir)); } return testSourceDirs; } private List filterBuildTarget(List sourceDirectories) { if (!excludeGeneratedSources) { return sourceDirectories; } List filtered = new ArrayList<>(sourceDirectories.size()); Path buildTarget = FileUtils.resolveFile( project.getBasedir(), project.getBuild().getDirectory()) .toPath(); for (String sourceDir : sourceDirectories) { Path src = FileUtils.resolveFile(project.getBasedir(), sourceDir).toPath(); if (!src.startsWith(buildTarget)) { filtered.add(sourceDir); } } return filtered; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy