From dceafd26e5c09213cee1595da85e6a838d314461 Mon Sep 17 00:00:00 2001 From: Vitalii Elenhaupt Date: Thu, 23 Nov 2017 19:49:45 +0200 Subject: [PATCH] Except & only cli flags --- spec/ameba/config_spec.cr | 8 ----- spec/ameba/runner_spec.cr | 3 +- src/ameba/cli/cmd.cr | 76 +++++++++++++++++++++++++++++++++++++++ src/ameba/config.cr | 24 ++++++++----- src/ameba/rule/base.cr | 2 +- src/ameba/runner.cr | 16 ++------- src/cli.cr | 40 ++------------------- 7 files changed, 99 insertions(+), 70 deletions(-) create mode 100644 src/ameba/cli/cmd.cr diff --git a/spec/ameba/config_spec.cr b/spec/ameba/config_spec.cr index dab2b191..75a199bb 100644 --- a/spec/ameba/config_spec.cr +++ b/spec/ameba/config_spec.cr @@ -46,13 +46,5 @@ module Ameba config.formatter.should eq formatter end end - - describe "#subconfig" do - it "returns a specific subconfig" do - config = Config.load config_sample - config.subconfig("NoSuchConfig").should be_nil - config.subconfig(Rule::LineLength.new.name).should_not be_nil - end - end end end diff --git a/spec/ameba/runner_spec.cr b/spec/ameba/runner_spec.cr index 53b2a102..fb8237c4 100644 --- a/spec/ameba/runner_spec.cr +++ b/spec/ameba/runner_spec.cr @@ -48,10 +48,11 @@ module Ameba end it "returns false if there are invalid sources" do + rules = Rule.rules.map &.new s = Source.new %q( WrongConstant = 5 ) - Runner.new([s], formatter).run.success?.should be_false + Runner.new(rules, [s], formatter).run.success?.should be_false end end end diff --git a/src/ameba/cli/cmd.cr b/src/ameba/cli/cmd.cr new file mode 100644 index 00000000..fc48e8f5 --- /dev/null +++ b/src/ameba/cli/cmd.cr @@ -0,0 +1,76 @@ +require "../../ameba" +require "option_parser" + +# :nodoc: +module Ameba::Cli + extend self + + private class Opts + property config : String? + property silent : Bool = false + property files : Array(String)? + property only : Array(String)? + property except : Array(String)? + end + + def run(args, opts = Opts.new) + OptionParser.parse(args) do |parser| + parser.banner = "Usage: ameba [options] [file1 file2 ...]" + + parser.on("-v", "--version", "Print version") { print_version } + parser.on("-h", "--help", "Show this help") { show_help parser } + parser.on("-s", "--silent", "Disable output") { opts.silent = true } + parser.unknown_args { |f| files = f if f.any? } + + parser.on("-c PATH", "--config PATH", "Specify configuration file") do |f| + opts.config = f + end + + parser.on("--only RULE1,RULE2,...", "Specify a list of rules") do |rules| + opts.only = rules.split "," + end + + parser.on("--except RULE1,RULE2,...", "Disable the given rules") do |rules| + opts.except = rules.split "," + end + end + + run_ameba opts + end + + def run_ameba(opts) + config = Ameba::Config.load opts.config + config.files = opts.files + config.formatter = Ameba::Formatter::BaseFormatter.new if opts.silent + + configure_rules(config, opts) + + exit 1 unless Ameba.run(config).success? + rescue e + puts "Error: #{e.message}" + exit 255 + end + + private def configure_rules(config, opts) + if only = opts.only + config.rules.map! { |r| r.enabled = false; r } + only.each do |rule_name| + config.update_rule(rule_name, enabled: true) + end + end + + opts.except.try &.each do |rule_name| + config.update_rule(rule_name, enabled: false) + end + end + + private def print_version + puts Ameba::VERSION + exit 0 + end + + private def show_help(parser) + puts parser + exit 0 + end +end diff --git a/src/ameba/config.cr b/src/ameba/config.cr index cbb9d016..dd5a6a49 100644 --- a/src/ameba/config.cr +++ b/src/ameba/config.cr @@ -14,11 +14,13 @@ require "yaml" class Ameba::Config setter formatter : Formatter::BaseFormatter? setter files : Array(String)? + getter rules : Array(Rule::Base) # Creates a new instance of `Ameba::Config` based on YAML parameters. # # `Config.load` uses this constructor to instantiate new config by YAML file. - protected def initialize(@config : YAML::Any) + protected def initialize(config : YAML::Any) + @rules = Rule.rules.map &.new(config) end # Loads YAML configuration file by `path`. @@ -60,16 +62,20 @@ class Ameba::Config @formatter ||= default_formatter end - # Returns a subconfig of a fully loaded configuration. - # This is used to get a config for a specific rule. + # Updates rule properties. # # ``` # config = Ameba::Config.load - # config.subconfig "LineLength" + # config.update_rule "MyRuleName", enabled: false # ``` # - def subconfig(name) - @config[name]? + def update_rule(name, enabled = true) + index = @rules.index { |r| r.name == name } + raise ArgumentError.new("Rule `#{name}` does not exist") unless index + + rule = @rules[index] + rule.enabled = enabled + @rules[index] = rule end private def default_files @@ -81,7 +87,7 @@ class Ameba::Config end # :nodoc: - module Rule + module RuleConfig macro properties(&block) {% definitions = [] of NamedTuple %} {% if block.body.is_a? Assign %} @@ -140,8 +146,8 @@ class Ameba::Config # allow creating rules without properties properties {} - def self.new(config : Ameba::Config? = nil) - yaml = config.try &.subconfig(class_name).try &.to_yaml || "{}" + def self.new(config = nil) + yaml = config.try &.[class_name]?.try &.to_yaml || "{}" from_yaml yaml end end diff --git a/src/ameba/rule/base.cr b/src/ameba/rule/base.cr index 5b2fdc55..dbb7e776 100644 --- a/src/ameba/rule/base.cr +++ b/src/ameba/rule/base.cr @@ -21,7 +21,7 @@ module Ameba::Rule # that are tested by this rule, it should add an error. # abstract struct Base - include Config::Rule + include Config::RuleConfig # This method is designed to test the source passed in. If source has issues # that are tested by this rule, it should add an error. diff --git a/src/ameba/runner.cr b/src/ameba/runner.cr index 246e1eea..1293c2cf 100644 --- a/src/ameba/runner.cr +++ b/src/ameba/runner.cr @@ -31,19 +31,13 @@ module Ameba # ``` # def initialize(config : Config) - @rules = load_rules(config) @sources = load_sources(config) @formatter = config.formatter + @rules = config.rules.select &.enabled end - # Instantiates a runner using a list of sources and a formatter. - # - # ``` - # runner = Ameba::Runner.new sources, formatter - # ``` - # - def initialize(@sources, @formatter) - @rules = load_rules nil + # :nodoc: + protected def initialize(@rules, @sources, @formatter) end # Performs the inspection. Iterates through all sources and test it using @@ -91,9 +85,5 @@ module Ameba .flatten .map { |path| Source.new File.read(path), path } end - - private def load_rules(config) - Rule.rules.map { |r| r.new config }.select &.enabled - end end end diff --git a/src/cli.cr b/src/cli.cr index 544c8581..f33c7fa1 100644 --- a/src/cli.cr +++ b/src/cli.cr @@ -1,39 +1,3 @@ -require "option_parser" -require "./ameba" +require "./ameba/cli/cmd" -files, formatter, config_path = nil, nil, nil - -OptionParser.parse(ARGV) do |parser| - parser.banner = "Usage: ameba [options] [file1 file2 ...]" - - parser.on("-v", "--version", "Print version") do - puts Ameba::VERSION - exit 0 - end - - parser.on("-h", "--help", "Show this help") do - puts parser - exit 0 - end - - parser.on("-s", "--silent", "Disable output") do - formatter = Ameba::Formatter::BaseFormatter.new - end - - # parser.on("-f FORMATTER", "--format FORMATTER", "Specify formatter") do |f| - # end - - parser.on("-c PATH", "--config PATH", "Specify configuration file") do |f| - config_path = f - end - - parser.unknown_args do |f| - files = f if f.any? - end -end - -config = Ameba::Config.load config_path -config.formatter = formatter -config.files = files - -exit(1) unless Ameba.run(config).success? +Ameba::Cli.run(ARGV)