sonar-checkstyle plugin 与 sonar-findbugs plugin 差不多,代码目录也几乎很相近。
sonar 插件需要扩展sensor,Exporter,Plugin,Importer类:
CheckstyleSensor 类:
import java.io.File;
import java.util.Iterator;
import java.util.List;
import org.sonar.api.batch.Sensor;
import org.sonar.api.batch.SensorContext;
import org.sonar.api.batch.fs.FilePredicates;
import org.sonar.api.batch.fs.FileSystem;
import org.sonar.api.batch.fs.InputFile.Type;
import org.sonar.api.profiles.RulesProfile;
import org.sonar.api.resources.Project;
public class CheckstyleSensor
implements Sensor
{
private final RulesProfile profile;
private final CheckstyleExecutor executor;
private final FileSystem fileSystem;
public CheckstyleSensor(RulesProfile profile, CheckstyleExecutor executor, FileSystem fileSystem)
{
this.profile = profile;
this.executor = executor;
this.fileSystem = fileSystem;
}
public boolean shouldExecuteOnProject(Project project)
{
FilePredicates predicates = this.fileSystem.predicates();
Iterable mainFiles = this.fileSystem.files(predicates.and(predicates.hasLanguage("java"), predicates
.hasType(InputFile.Type.MAIN)));
boolean mainFilesIsEmpty = !mainFiles.iterator().hasNext();
if (!mainFilesIsEmpty) {}
return
!this.profile.getActiveRulesByRepository("checkstyle").isEmpty();
}
public void analyse(Project project, SensorContext context)
{
this.executor.execute();
}
public String toString()
{
return getClass().getSimpleName();
}
CheckstylePlugin 继承sonarPlugin类:
public final class CheckstylePlugin
extends SonarPlugin
{
private static final String CHECKSTYLE_SUB_CATEGORY_NAME = "Checkstyle";
public List getExtensions()
{
return
Arrays.asList(new Object[] {
PropertyDefinition.builder("sonar.checkstyle.filters")
.defaultValue(" ")
.category("java")
.subCategory("Checkstyle")
.name("Filters")
.description("Checkstyle supports four error filtering mechanisms: SuppressionCommentFilter
, SuppressWithNearbyCommentFilter
, SuppressionFilter
, and SuppressWarningsFilter
.This property allows the configuration of those filters with a native XML format. See the Checkstyle configuration for more information.")
.type(PropertyType.TEXT)
.onQualifiers("TRK", new String[] { "BRC" }).build(),
PropertyDefinition.builder("sonar.checkstyle.generateXml")
.defaultValue("false").category("java")
.subCategory("Checkstyle")
.name("Generate XML Report").type(PropertyType.BOOLEAN).hidden()
.build(), CheckstyleSensor.class, CheckstyleConfiguration.class, CheckstyleExecutor.class, CheckstyleAuditListener.class, CheckstyleProfileExporter.class, CheckstyleProfileImporter.class, CheckstyleRulesDefinition.class });
}
}
CheckstyleProfileExporter 继承ProfileExporter
public class CheckstyleProfileExporter
extends ProfileExporter
{
public static final String DOCTYPE_DECLARATION = "";
private static final String CLOSE_MODULE = "";
private final Settings settings;
public CheckstyleProfileExporter(Settings settings)
{
super("checkstyle", "Checkstyle");
this.settings = settings;
setSupportedLanguages(new String[] { "java" });
setMimeType("application/xml");
}
public void exportProfile(RulesProfile profile, Writer writer)
{
try
{
List activeRules = profile.getActiveRulesByRepository("checkstyle");
if (activeRules != null)
{
Map> activeRulesByConfigKey = arrangeByConfigKey(activeRules);
generateXml(writer, activeRulesByConfigKey);
}
}
catch (IOException ex)
{
throw new IllegalStateException("Fail to export the profile " + profile, ex);
}
}
private void generateXml(Writer writer, Map> activeRulesByConfigKey)
throws IOException
{
appendXmlHeader(writer);
appendCustomFilters(writer);
appendCheckerModules(writer, activeRulesByConfigKey);
appendTreeWalker(writer, activeRulesByConfigKey);
appendXmlFooter(writer);
}
private static void appendXmlHeader(Writer writer)
throws IOException
{
writer.append("");
}
private void appendCustomFilters(Writer writer)
throws IOException
{
String filtersXml = this.settings.getString("sonar.checkstyle.filters");
if (StringUtils.isNotBlank(filtersXml)) {
writer.append(filtersXml);
}
}
private static void appendCheckerModules(Writer writer, Map> activeRulesByConfigKey)
throws IOException
{
for (Map.Entry> entry : activeRulesByConfigKey.entrySet())
{
String configKey = (String)entry.getKey();
if (!isInTreeWalker(configKey))
{
List activeRules = (List)entry.getValue();
for (ActiveRule activeRule : activeRules) {
appendModule(writer, activeRule);
}
}
}
}
private void appendTreeWalker(Writer writer, Map> activeRulesByConfigKey)
throws IOException
{
writer.append("");
writer.append(" ");
if (isSuppressWarningsEnabled()) {
writer.append(" ");
}
List ruleSet = new ArrayList(activeRulesByConfigKey.keySet());
Collections.sort(ruleSet);
for (String configKey : ruleSet) {
if (isInTreeWalker(configKey))
{
List activeRules = (List)activeRulesByConfigKey.get(configKey);
for (ActiveRule activeRule : activeRules) {
appendModule(writer, activeRule);
}
}
}
writer.append(" ");
}
private boolean isSuppressWarningsEnabled()
{
String filtersXml = this.settings.getString("sonar.checkstyle.filters");
boolean result = false;
if (filtersXml != null) {
result = filtersXml.contains(" ");
}
return result;
}
private static void appendXmlFooter(Writer writer)
throws IOException
{
writer.append(" ");
}
@VisibleForTesting
static boolean isInTreeWalker(String configKey)
{
return StringUtils.startsWithIgnoreCase(configKey, "Checker/TreeWalker/");
}
private static Map> arrangeByConfigKey(List activeRules)
{
Map> result = new HashMap();
for (ActiveRule activeRule : activeRules)
{
String key = activeRule.getConfigKey();
if (result.containsKey(key))
{
List rules = (List)result.get(key);
rules.add(activeRule);
}
else
{
List rules = new ArrayList();
rules.add(activeRule);
result.put(key, rules);
}
}
return result;
}
private static void appendModule(Writer writer, ActiveRule activeRule)
throws IOException
{
String moduleName = StringUtils.substringAfterLast(activeRule.getConfigKey(), "/");
writer.append("");
if (activeRule.getRule().getTemplate() != null) {
appendModuleProperty(writer, "id", activeRule.getRuleKey());
}
appendModuleProperty(writer, "severity",
CheckstyleSeverityUtils.toSeverity(activeRule.getSeverity()));
appendRuleParameters(writer, activeRule);
writer.append(" ");
}
private static void appendRuleParameters(Writer writer, ActiveRule activeRule)
throws IOException
{
for (RuleParam ruleParam : activeRule.getRule().getParams())
{
String value = activeRule.getParameter(ruleParam.getKey());
if (StringUtils.isNotBlank(value)) {
appendModuleProperty(writer, ruleParam.getKey(), value);
}
}
}
private static void appendModuleProperty(Writer writer, String propertyKey, String propertyValue)
throws IOException
{
if (StringUtils.isNotBlank(propertyValue))
{
writer.append(" ");
}
}
}
CheckstyleProfileImporter 继承ProfileImporter,checkstyle 是针对java语言的规则提供者
public class CheckstyleProfileImporter
extends ProfileImporter
{
private static final Logger LOG = LoggerFactory.getLogger(CheckstyleProfileImporter.class);
private static final String CHECKER_MODULE = "Checker";
private static final String TREEWALKER_MODULE = "TreeWalker";
private static final String MODULE_NODE = "module";
private static final String[] FILTERS = { "SeverityMatchFilter", "SuppressionFilter", "SuppressWarningsFilter", "SuppressionCommentFilter", "SuppressWithNearbyCommentFilter" };
private final RuleFinder ruleFinder;
public CheckstyleProfileImporter(RuleFinder ruleFinder)
{
super("checkstyle", "Checkstyle");
setSupportedLanguages(new String[] { "java" });
this.ruleFinder = ruleFinder;
}
private Module loadModule(SMInputCursor parentCursor)
throws XMLStreamException
{
Module result = new Module(null);
result.name = parentCursor.getAttrValue("name");
SMInputCursor cursor = parentCursor.childElementCursor();
while (cursor.getNext() != null)
{
String nodeName = cursor.getLocalName();
if ("module".equals(nodeName))
{
result.modules.add(loadModule(cursor));
}
else if ("property".equals(nodeName))
{
String key = cursor.getAttrValue("name");
String value = cursor.getAttrValue("value");
result.properties.put(key, value);
}
}
return result;
}
public RulesProfile importProfile(Reader reader, ValidationMessages messages)
{
SMInputFactory inputFactory = initStax();
RulesProfile profile = RulesProfile.create();
try
{
checkerModule = loadModule(inputFactory.rootElementCursor(reader)
.advance());
for (Module rootModule : checkerModule.modules)
{
Map rootModuleProperties = new HashMap(checkerModule.properties);
rootModuleProperties.putAll(rootModule.properties);
if (StringUtils.equals("TreeWalker", rootModule.name)) {
processTreewalker(profile, rootModule, rootModuleProperties, messages);
} else {
processModule(profile, "Checker/", rootModule.name, rootModuleProperties, messages);
}
}
}
catch (XMLStreamException ex)
{
Module checkerModule;
String message = "XML is not valid: " + ex.getMessage();
LOG.error(message, ex);
messages.addErrorText(message);
}
return profile;
}
private void processTreewalker(RulesProfile profile, Module rootModule, Map rootModuleProperties, ValidationMessages messages)
{
for (Module treewalkerModule : rootModule.modules)
{
Map treewalkerModuleProperties = new HashMap(rootModuleProperties);
treewalkerModuleProperties.putAll(treewalkerModule.properties);
processModule(profile, "Checker/TreeWalker/",
treewalkerModule.name, treewalkerModuleProperties, messages);
}
}
private static SMInputFactory initStax()
{
XMLInputFactory xmlFactory = XMLInputFactory.newInstance();
xmlFactory.setProperty("javax.xml.stream.isCoalescing", Boolean.TRUE);
xmlFactory.setProperty("javax.xml.stream.isNamespaceAware", Boolean.FALSE);
xmlFactory.setProperty("javax.xml.stream.supportDTD", Boolean.FALSE);
xmlFactory.setProperty("javax.xml.stream.isValidating", Boolean.FALSE);
return new SMInputFactory(xmlFactory);
}
private void processModule(RulesProfile profile, String path, String moduleName, Map properties, ValidationMessages messages)
{
if (isFilter(moduleName)) {
messages.addWarningText("Checkstyle filters are not imported: " + moduleName);
} else if (!isIgnored(moduleName)) {
processRule(profile, path, moduleName, properties, messages);
}
}
@VisibleForTesting
static boolean isIgnored(String configKey)
{
return (StringUtils.equals(configKey, "FileContentsHolder")) ||
(StringUtils.equals(configKey, "SuppressWarningsHolder"));
}
@VisibleForTesting
static boolean isFilter(String configKey)
{
boolean result = false;
for (String filter : FILTERS) {
if (StringUtils.equals(configKey, filter))
{
result = true;
break;
}
}
return result;
}
private void processRule(RulesProfile profile, String path, String moduleName, Map properties, ValidationMessages messages)
{
String id = (String)properties.get("id");
String warning;
Rule rule;
String warning;
if (StringUtils.isNotBlank(id))
{
Rule rule = this.ruleFinder.find(RuleQuery.create()
.withRepositoryKey("checkstyle").withKey(id));
warning = "Checkstyle rule with key '" + id + "' not found";
}
else
{
String configKey = path + moduleName;
rule = this.ruleFinder.find(RuleQuery.create().withRepositoryKey("checkstyle")
.withConfigKey(configKey));
warning = "Checkstyle rule with config key '" + configKey + "' not found";
}
if (rule == null)
{
messages.addWarningText(warning);
}
else
{
ActiveRule activeRule = profile.activateRule(rule, null);
activateProperties(activeRule, properties);
}
}
private static void activateProperties(ActiveRule activeRule, Map properties)
{
for (Map.Entry property : properties.entrySet()) {
if (StringUtils.equals("severity", (String)property.getKey())) {
activeRule.setSeverity(CheckstyleSeverityUtils.fromSeverity((String)property.getValue()));
} else if (!StringUtils.equals("id", (String)property.getKey())) {
activeRule.setParameter((String)property.getKey(), (String)property.getValue());
}
}
}
private static class Module
{
private final Map properties = new HashMap();
private final List modules = new ArrayList();
private String name;
}
}
对于sonar plugin 如果要具有导出规则的能力,需要声明一个类继承BatchExtension,类BatchExtension来自于sonar-api包
package org.sonar.plugins.checkstyle;
import com.google.common.annotations.VisibleForTesting;
import com.puppycrawl.tools.checkstyle.Checker;
import com.puppycrawl.tools.checkstyle.PackageNamesLoader;
import com.puppycrawl.tools.checkstyle.XMLLogger;
import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Locale;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.BatchExtension;
import org.sonar.api.utils.TimeProfiler;
import org.sonar.plugins.java.api.JavaResourceLocator;
public class CheckstyleExecutor
implements BatchExtension
{
public static final String PROPERTIES_PATH = "/org/sonar/plugins/checkstyle/checkstyle-plugin.properties";
private static final Logger LOG = LoggerFactory.getLogger(CheckstyleExecutor.class);
private final CheckstyleConfiguration configuration;
private final CheckstyleAuditListener listener;
private final JavaResourceLocator javaResourceLocator;
public CheckstyleExecutor(CheckstyleConfiguration configuration, CheckstyleAuditListener listener, JavaResourceLocator javaResourceLocator)
{
this.configuration = configuration;
this.listener = listener;
this.javaResourceLocator = javaResourceLocator;
}
public void execute()
{
Locale initialLocale = Locale.getDefault();
Locale.setDefault(Locale.ENGLISH);
ClassLoader initialClassLoader = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(PackageNamesLoader.class.getClassLoader());
URLClassLoader projectClassloader = createClassloader();
try
{
executeWithClassLoader(projectClassloader);
}
finally
{
Thread.currentThread().setContextClassLoader(initialClassLoader);
Locale.setDefault(initialLocale);
close(projectClassloader);
}
}
private void executeWithClassLoader(URLClassLoader projectClassloader)
{
TimeProfiler profiler = new TimeProfiler().start("Execute Checkstyle " + new CheckstyleVersion()
.getVersion("/org/sonar/plugins/checkstyle/checkstyle-plugin.properties"));
Checker checker = new Checker();
OutputStream xmlOutput = null;
try
{
checker.setClassLoader(projectClassloader);
checker.setModuleClassLoader(Thread.currentThread().getContextClassLoader());
checker.addListener(this.listener);
File xmlReport = this.configuration.getTargetXmlReport();
if (xmlReport != null)
{
LOG.info("Checkstyle output report: {}", xmlReport.getAbsolutePath());
xmlOutput = FileUtils.openOutputStream(xmlReport);
checker.addListener(new XMLLogger(xmlOutput, true));
}
checker.setCharset(this.configuration.getCharset().name());
checker.configure(this.configuration.getCheckstyleConfiguration());
checker.process(this.configuration.getSourceFiles());
profiler.stop();
}
catch (Exception ex)
{
throw new IllegalStateException("Can not execute Checkstyle", ex);
}
finally
{
checker.destroy();
if (xmlOutput != null) {
close(xmlOutput);
}
}
}
@VisibleForTesting
static void close(Closeable closeable)
{
try
{
closeable.close();
}
catch (IOException ex)
{
throw new IllegalStateException("failed to close object", ex);
}
}
@VisibleForTesting
URL getUrl(URI uri)
{
try
{
return uri.toURL();
}
catch (MalformedURLException ex)
{
throw new IllegalStateException("Fail to create the project classloader. Classpath element is invalid: " + uri, ex);
}
}
private URLClassLoader createClassloader()
{
Collection classpathElements = this.javaResourceLocator.classpath();
List urls = new ArrayList(classpathElements.size());
for (File file : classpathElements) {
urls.add(getUrl(file.toURI()));
}
return new URLClassLoader((URL[])urls.toArray(new URL[urls.size()]), null);
}
}
CheckstyleConfiguration implements BatchExtension类:
////////////////////////////////////////////////////////////////////////////////
// checkstyle: Checks Java source code for adherence to a set of rules.
// Copyright (C) 2001-2017 the original author or authors.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
////////////////////////////////////////////////////////////////////////////////
package org.sonar.plugins.checkstyle;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.BatchExtension;
import org.sonar.api.batch.fs.FilePredicates;
import org.sonar.api.batch.fs.FileSystem;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.config.Settings;
import org.sonar.api.profiles.RulesProfile;
import com.google.common.annotations.VisibleForTesting;
import com.puppycrawl.tools.checkstyle.ConfigurationLoader;
import com.puppycrawl.tools.checkstyle.DefaultConfiguration;
import com.puppycrawl.tools.checkstyle.PropertiesExpander;
import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
import com.puppycrawl.tools.checkstyle.api.Configuration;
public class CheckstyleConfiguration implements BatchExtension {
public static final String PROPERTY_GENERATE_XML = "sonar.checkstyle.generateXml";
private static final Logger LOG = LoggerFactory.getLogger(CheckstyleConfiguration.class);
private final CheckstyleProfileExporter confExporter;
private final RulesProfile profile;
private final Settings conf;
private final FileSystem fileSystem;
public CheckstyleConfiguration(Settings conf, CheckstyleProfileExporter confExporter,
RulesProfile profile, FileSystem fileSystem) {
this.conf = conf;
this.confExporter = confExporter;
this.profile = profile;
this.fileSystem = fileSystem;
}
public File getXmlDefinitionFile() {
final File xmlFile = new File(fileSystem.workDir(), "checkstyle.xml");
try (Writer writer = new OutputStreamWriter(new FileOutputStream(xmlFile, false),
StandardCharsets.UTF_8)) {
confExporter.exportProfile(profile, writer);
writer.flush();
return xmlFile;
}
catch (IOException ex) {
throw new IllegalStateException("Fail to save the Checkstyle configuration to "
+ xmlFile.getPath(), ex);
}
}
public List getSourceFiles() {
final FilePredicates predicates = fileSystem.predicates();
final Iterable files = fileSystem.files(predicates.and(
predicates.hasLanguage(CheckstyleConstants.JAVA_KEY),
predicates.hasType(InputFile.Type.MAIN)));
final List fileList = new ArrayList<>();
for (File file : files) {
fileList.add(file);
}
return fileList;
}
public File getTargetXmlReport() {
File result = null;
if (conf.getBoolean(PROPERTY_GENERATE_XML)) {
result = new File(fileSystem.workDir(), "checkstyle-result.xml");
}
return result;
}
public Configuration getCheckstyleConfiguration() throws CheckstyleException {
final File xmlConfig = getXmlDefinitionFile();
LOG.info("Checkstyle configuration: {}", xmlConfig.getAbsolutePath());
final Configuration configuration = toCheckstyleConfiguration(xmlConfig);
defineCharset(configuration);
return configuration;
}
@VisibleForTesting
static Configuration toCheckstyleConfiguration(File xmlConfig) throws CheckstyleException {
return ConfigurationLoader.loadConfiguration(xmlConfig.getAbsolutePath(),
new PropertiesExpander(new Properties()));
}
private void defineCharset(Configuration configuration) {
defineModuleCharset(configuration);
for (Configuration module : configuration.getChildren()) {
defineModuleCharset(module);
}
}
private void defineModuleCharset(Configuration module) {
if (module instanceof DefaultConfiguration
&& ("Checker".equals(module.getName())
|| "com.puppycrawl.tools.checkstyle.Checker".equals(module.getName()))) {
final Charset charset = getCharset();
final String charsetName = charset.name();
LOG.info("Checkstyle charset: {}", charsetName);
((DefaultConfiguration) module).addAttribute("charset", charsetName);
}
}
public Charset getCharset() {
return fileSystem.encoding();
}
}
checkstyle 中依赖的jar包:
pom中依赖的jar包,其中是sonar-api包:
4.0.0
com.github.checkstyle
checkstyle-sonar-plugin-parent
4.0
checkstyle-sonar-plugin
sonar-plugin
Checkstyle SonarQube Plugin
Checkstyle is a code analyser to help programmers write Java code that adheres to a coding standard.
2.17
1.25.0
org.sonarsource.sonarqube
sonar-plugin-api
provided
${sonar.version}
org.sonarsource.java
sonar-java-plugin
sonar-plugin
${sonar-java.version}
provided
org.codehaus.sonar
sonar-plugin-api
org.sonarsource.sslr-squid-bridge
sslr-squid-bridge
2.6.1
org.codehaus.sonar
sonar-plugin-api
org.codehaus.sonar
sonar-colorizer
commons-io
commons-io
2.5
commons-lang
commons-lang
2.6
${project.groupId}
checkstyle-all
${project.version}
shaded
com.puppycrawl.tools
checkstyle
org.sonarsource.sonarqube
sonar-plugin-api
${sonar.version}
test-jar
test
xmlunit
xmlunit
test
1.4
org.apache.maven
maven-project
2.0.7
test
org.sonarsource.sonarqube
sonar-testing-harness
test
${sonar.version}
org.easytesting
fest-assert
test
1.4
org.slf4j
slf4j-nop
1.5.6
test
org.apache.ant
ant
1.9.7
test
src/main/resources
true
**/checkstyle-plugin.properties
src/main/resources
false
**/checkstyle-plugin.properties
org.apache.maven.plugins
maven-checkstyle-plugin
${maven.checkstyle.plugin.version}
com.puppycrawl.tools
checkstyle
${checkstyle.version}
com.github.sevntu-checkstyle
sevntu-checkstyle-maven-plugin
${maven.sevntu.checkstyle.plugin.version}
checkstyle-check
verify
check
https://raw.githubusercontent.com/checkstyle/checkstyle/checkstyle-${checkstyle.version}/config/checkstyle_checks.xml
true
I just need to put here smth to let it not use default - LICENSE.txt
config/checkstyle.properties
${project.basedir}/src
false
sevntu-checkstyle-check
verify
check
https://raw.githubusercontent.com/checkstyle/checkstyle/checkstyle-${checkstyle.version}/config/checkstyle_sevntu_checks.xml
true
false
false
true
0
error
project.basedir=${project.basedir}
${project.basedir}/src
org.apache.maven.plugins
maven-pmd-plugin
3.7
${java.version}
20
false
true
true
false
true
config/pmd.xml
check
org.codehaus.mojo
findbugs-maven-plugin
3.0.4
Max
Low
config/findbugs-exclude.xml
check
de.thetaphi
forbiddenapis
2.2
${java.version}
false
jdk-unsafe
jdk-deprecated
jdk-system-out
jdk-non-portable
check
testCheck
org.codehaus.mojo
cobertura-maven-plugin
2.7
xml
html
true
100
100
82
96
org.sonar.plugins.checkstyle.CheckstyleAuditListener
71
86
org.sonar.plugins.checkstyle.CheckstyleConfiguration
60
93
org.sonar.plugins.checkstyle.CheckstyleProfileExporter
87
97
org.sonar.plugins.checkstyle.CheckstyleProfileImporter
97
100
org.sonar.plugins.checkstyle.CheckstyleRulesDefinition
50
90
org.sonar.plugins.checkstyle.CheckstyleSensor
100
87
org.sonar.plugins.checkstyle.CheckstyleSeverityUtils
75
96
check
edu.illinois
nondex-maven-plugin
1.1.1
org.sonarsource.sonar-packaging-maven-plugin
sonar-packaging-maven-plugin
1.17
true
checkstyle
Checkstyle
org.sonar.plugins.checkstyle.CheckstylePlugin
Checkstyle.]]>
${buildNumber}
${timestamp}
org.apache.maven.plugins
maven-enforcer-plugin
1.4.1
enforce-plugin-size
enforce
verify
10000000
5000000
${project.build.directory}/${project.build.finalName}.jar
sevntu-maven
sevntu-maven
http://sevntu-checkstyle.github.io/sevntu.checkstyle/maven2