# 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.
module Buildr
# Provides the checkstyle:html
and checkstyle:xml
tasks.
# Require explicitly using require "buildr/checkstyle"
.
module Checkstyle
class << self
# The specs for requirements
def dependencies
[
'com.puppycrawl.tools:checkstyle:jar:6.6',
'antlr:antlr:jar:2.7.7',
'org.antlr:antlr4-runtime:jar:4.5',
'com.google.guava:guava:jar:18.0',
'org.apache.commons:commons-lang3:jar:3.4',
'org.abego.treelayout:org.abego.treelayout.core:jar:1.0.1',
'commons-cli:commons-cli:jar:1.2',
'commons-beanutils:commons-beanutils-core:jar:1.8.3',
'commons-logging:commons-logging:jar:1.1.1'
]
end
def checkstyle(configuration_file, format, output_file, source_paths, options = {})
dependencies = self.dependencies + (options[:dependencies] || [])
cp = Buildr.artifacts(dependencies).each { |a| a.invoke() if a.respond_to?(:invoke) }.map(&:to_s)
args = []
if options[:properties_file]
args << '-p'
args << options[:properties_file]
end
args << '-c'
args << configuration_file
args << '-f'
args << format
args << '-o'
args << output_file
args += source_paths
begin
Java::Commands.java 'com.puppycrawl.tools.checkstyle.Main', *(args + [{:classpath => cp, :properties => options[:properties], :java_args => options[:java_args]}])
rescue => e
raise e if options[:fail_on_error]
end
end
end
class Config
def enabled?
File.exist?(self.configuration_file)
end
def html_enabled?
File.exist?(self.style_file)
end
attr_writer :config_directory
def config_directory
@config_directory || project._(:source, :main, :etc, :checkstyle)
end
attr_writer :report_dir
def report_dir
@report_dir || project._(:reports, :checkstyle)
end
attr_writer :configuration_file
def configuration_file=(configuration_file)
raise 'Configuration artifact already specified' if @configuration_artifact
@configuration_file = configuration_file
end
def configuration_file
if @configuration_file
return @configuration_file
elsif @configuration_artifact.nil?
"#{self.config_directory}/checks.xml"
else
a = Buildr.artifact(@configuration_artifact)
a.invoke
a.to_s
end
end
def configuration_artifact=(configuration_artifact)
raise 'Configuration file already specified' if @configuration_file
@configuration_artifact = configuration_artifact
end
def configuration_artifact
@configuration_artifact
end
attr_writer :fail_on_error
def fail_on_error?
@fail_on_error.nil? ? false : @fail_on_error
end
attr_writer :format
def format
@format || 'xml'
end
attr_writer :xml_output_file
def xml_output_file
@xml_output_file || "#{self.report_dir}/checkstyle.xml"
end
attr_writer :html_output_file
def html_output_file
@html_output_file || "#{self.report_dir}/checkstyle.html"
end
attr_writer :style_file
def style_file
unless @style_file
project_xsl = "#{self.config_directory}/checkstyle-report.xsl"
if File.exist?(project_xsl)
@style_file = project_xsl
else
@style_file = "#{File.dirname(__FILE__)}/checkstyle-report.xsl"
end
end
@style_file
end
attr_writer :suppressions_file
def suppressions_file
@suppressions_file || "#{self.config_directory}/suppressions.xml"
end
attr_writer :import_control_file
def import_control_file
@import_control_file || "#{self.config_directory}/import-control.xml"
end
def properties
unless @properties
@properties = {:basedir => self.project.base_dir}
@properties['checkstyle.config.dir'] = self.config_directory if File.directory?(self.config_directory)
@properties['checkstyle.suppressions.file'] = self.suppressions_file if File.exist?(self.suppressions_file)
@properties['checkstyle.import-control.file'] = self.import_control_file if File.exist?(self.import_control_file)
end
@properties
end
def source_paths
@source_paths ||= [self.project.compile.sources, self.project.test.compile.sources]
end
def extra_dependencies
@extra_dependencies ||= [self.project.compile.dependencies, self.project.test.compile.dependencies].flatten
end
protected
def initialize(project)
@project = project
end
attr_reader :project
end
module ProjectExtension
include Extension
def checkstyle
@checkstyle ||= Buildr::Checkstyle::Config.new(project)
end
after_define do |project|
if project.checkstyle.enabled?
desc 'Generate checkstyle xml report.'
project.task('checkstyle:xml') do
puts 'Checkstyle: Analyzing source code...'
mkdir_p File.dirname(project.checkstyle.xml_output_file)
Buildr::Checkstyle.checkstyle(project.checkstyle.configuration_file,
project.checkstyle.format,
project.checkstyle.xml_output_file,
project.checkstyle.source_paths.flatten.compact,
:properties => project.checkstyle.properties,
:fail_on_error => project.checkstyle.fail_on_error?,
:dependencies => project.checkstyle.extra_dependencies)
end
if project.checkstyle.html_enabled?
xml_task = project.task('checkstyle:xml')
desc 'Generate checkstyle html report.'
project.task('checkstyle:html' => xml_task) do
puts 'Checkstyle: Generating report'
mkdir_p File.dirname(project.checkstyle.html_output_file)
Buildr.ant 'checkstyle' do |ant|
ant.xslt :in => project.checkstyle.xml_output_file,
:out => project.checkstyle.html_output_file,
:style => project.checkstyle.style_file
end
end
end
end
end
end
end
end
class Buildr::Project
include Buildr::Checkstyle::ProjectExtension
end