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

org.codenarc.ant.CodeNarcTask.groovy Maven / Gradle / Ivy

There is a newer version: 3.5.0-groovy-4.0
Show newest version
/*
 * Copyright 2008 the original author or authors.
 * 
 * Licensed 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.codenarc.ant

import static java.lang.Thread.currentThread

import org.apache.tools.ant.BuildException
import org.apache.tools.ant.Task
import org.apache.tools.ant.types.FileSet
import org.apache.tools.ant.types.Path
import org.apache.tools.ant.types.Reference
import org.codenarc.CodeNarcRunner
import org.codenarc.analyzer.SourceAnalyzer
import org.codenarc.report.ReportWriterFactory
import org.codenarc.results.Results
import org.codenarc.util.BaselineResultsProcessor
import org.codenarc.util.io.DefaultResourceFactory
import org.slf4j.LoggerFactory

/**
 * Ant Task for running CodeNarc.
 * 

* The ruleSetFiles property specifies the path to the Groovy or XML RuleSet * definition files, relative to the classpath. This can be a single file path, or multiple * paths separated by commas. It is required. *

* The maxPriority1Violations property specifies the maximum number of priority 1 * violations allowed before failing the build (throwing a BuildException). Likewise, * maxPriority2Violations and maxPriority3Violations specifiy the * thresholds for violations of priority 2 and 3. *

* At least one nested fileset element is required, and is used to specify the source files * to be analyzed. This is the standard Ant FileSet, and is quite powerful and flexible. * See the Apache Ant Manual for more information on FileSets. *

* The report nested element defines the format and output file for the analysis report. * Currently, HTML (type="html") and XML (type="xml") are the only supported formats. Each report * is configured using nested option elements, with name, and * value attributes. * * @see "http://ant.apache.org/manual/index.html" * * @author Chris Mair */ class CodeNarcTask extends Task { private static final LOG = LoggerFactory.getLogger(CodeNarcTask) /** * The path to the Groovy or XML RuleSet definition files, relative to the classpath. This can be a * single file path, or multiple paths separated by commas. */ String ruleSetFiles /** * The path to a Baseline Violations report (report type "baseline"). If set, then all violations specified * within that report are excluded (filtered) from the current CodeNarc run. If null/empty, then do nothing. */ String excludeBaseline int maxPriority1Violations = Integer.MAX_VALUE int maxPriority2Violations = Integer.MAX_VALUE int maxPriority3Violations = Integer.MAX_VALUE /** * Classpath used when compiling analysed classes. */ Path classpath protected List reportWriters = [] protected List fileSets = [] protected ruleSet private final resourceFactory = new DefaultResourceFactory() // Abstract creation of the CodeNarcRunner instance to allow substitution of test spy for unit tests protected createCodeNarcRunner = { if (excludeBaseline) { LOG.info("Loading baseline violations from [$excludeBaseline]") def resource = resourceFactory.getResource(excludeBaseline) def resultsProcessor = new BaselineResultsProcessor(resource) return new CodeNarcRunner(resultsProcessor:resultsProcessor) } return new CodeNarcRunner() } /** * Execute this Ant Task */ void execute() throws BuildException { assert ruleSetFiles assert fileSets def sourceAnalyzer = createSourceAnalyzer() def codeNarcRunner = createCodeNarcRunner() codeNarcRunner.ruleSetFiles = ruleSetFiles codeNarcRunner.reportWriters = reportWriters codeNarcRunner.sourceAnalyzer = sourceAnalyzer def results = executeRunnerWithConfiguredClasspath(codeNarcRunner) checkMaxViolations(results) } void addFileset(FileSet fileSet) { assert fileSet this.fileSets << fileSet } /** * Ant-defined method (by convention), called with each instance of a nested * element within this task. */ void addConfiguredReport(Report report) { reportWriters << new ReportWriterFactory().getReportWriter(report.type, report.options) } Path createClasspath() { classpath = classpath ?: new Path(getProject()) classpath.createPath() } /** * Adds a reference to a classpath defined elsewhere to be used when compiling analysed classes. */ void setClasspathRef(Reference reference) { createClasspath().refid = reference } /** * Create and return the SourceAnalyzer * @return a configured SourceAnalyzer instance */ protected SourceAnalyzer createSourceAnalyzer() { new AntFileSetSourceAnalyzer(getProject(), fileSets) } private void checkMaxViolations(Results results) { def p1 = results.getNumberOfViolationsWithPriority(1, true) def p2 = results.getNumberOfViolationsWithPriority(2, true) def p3 = results.getNumberOfViolationsWithPriority(3, true) def countsText = "(p1=$p1; p2=$p2; p3=$p3)" checkMaxViolationForPriority(1, p1, countsText) checkMaxViolationForPriority(2, p2, countsText) checkMaxViolationForPriority(3, p3, countsText) } private void checkMaxViolationForPriority(int priority, int count, String countsText) { if (count > this."maxPriority${priority}Violations") { throw new BuildException("Exceeded maximum number of priority ${priority} violations: " + countsText) } } private Results executeRunnerWithConfiguredClasspath(codeNarcRunner) { def paths = classpath?.list() if (paths) { def oldContextClassLoader = currentThread().contextClassLoader try { currentThread().contextClassLoader = classLoaderForPaths(paths, oldContextClassLoader) codeNarcRunner.execute() } finally { currentThread().contextClassLoader = oldContextClassLoader } } else { codeNarcRunner.execute() } } private ClassLoader classLoaderForPaths(String[] paths, ClassLoader parent) { def urls = paths.collect { new File(it).toURI().toURL() } as URL[] new URLClassLoader(urls, parent) } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy