mirror of
https://gitea.invidious.io/iv-org/shard-ameba.git
synced 2024-08-15 00:53:29 +00:00
Base YAML config loader & Ameba runner
This commit is contained in:
parent
80e2ab4f55
commit
822a69b81c
7 changed files with 158 additions and 32 deletions
|
@ -1,7 +1,7 @@
|
||||||
require "../src/ameba"
|
require "../src/ameba"
|
||||||
require "benchmark"
|
require "benchmark"
|
||||||
|
|
||||||
private def get_sources(n)
|
private def get_files(n)
|
||||||
Dir["src/**/*.cr"].first(n)
|
Dir["src/**/*.cr"].first(n)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -16,10 +16,11 @@ Benchmark.ips do |x|
|
||||||
30,
|
30,
|
||||||
40,
|
40,
|
||||||
].each do |n|
|
].each do |n|
|
||||||
sources = get_sources(n)
|
config = Ameba::Config.load
|
||||||
formatter = Ameba::Formatter::BaseFormatter.new
|
config.formatter = Ameba::Formatter::BaseFormatter.new
|
||||||
|
config.files = get_files(n)
|
||||||
s = n == 1 ? "" : "s"
|
s = n == 1 ? "" : "s"
|
||||||
x.report("#{n} source#{s}") { Ameba.run sources, formatter }
|
x.report("#{n} source#{s}") { Ameba.run config }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
23
src/ameba.cr
23
src/ameba.cr
|
@ -6,26 +6,7 @@ require "./ameba/formatter/*"
|
||||||
module Ameba
|
module Ameba
|
||||||
extend self
|
extend self
|
||||||
|
|
||||||
def run(formatter = Formatter::BaseFormatter.new)
|
def run(config = Config.load)
|
||||||
run Dir["**/*.cr"].reject(&.starts_with? "lib/"), formatter
|
Runner.new(config).run
|
||||||
end
|
|
||||||
|
|
||||||
def run(files, formatter : Formatter::BaseFormatter)
|
|
||||||
sources = files.map { |path| Source.new(File.read(path), path) }
|
|
||||||
|
|
||||||
formatter.started sources
|
|
||||||
sources.each do |source|
|
|
||||||
formatter.source_started source
|
|
||||||
catch(source)
|
|
||||||
formatter.source_finished source
|
|
||||||
end
|
|
||||||
formatter.finished sources
|
|
||||||
sources
|
|
||||||
end
|
|
||||||
|
|
||||||
def catch(source : Source)
|
|
||||||
Rule.rules.each do |rule|
|
|
||||||
rule.new.test(source)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
69
src/ameba/config.cr
Normal file
69
src/ameba/config.cr
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
require "yaml"
|
||||||
|
|
||||||
|
class Ameba::Config
|
||||||
|
setter formatter : Formatter::BaseFormatter?
|
||||||
|
setter files : Array(String)?
|
||||||
|
|
||||||
|
def initialize(@config : YAML::Any)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.load(path = ".ameba.yml")
|
||||||
|
content = (path && File.exists? path) ? File.read path : "{}"
|
||||||
|
Config.new YAML.parse(content)
|
||||||
|
end
|
||||||
|
|
||||||
|
def files
|
||||||
|
@files ||= default_files
|
||||||
|
end
|
||||||
|
|
||||||
|
def formatter
|
||||||
|
@formatter ||= default_formatter
|
||||||
|
end
|
||||||
|
|
||||||
|
def subconfig(name)
|
||||||
|
@config[name]?
|
||||||
|
end
|
||||||
|
|
||||||
|
private def default_files
|
||||||
|
Dir["**/*.cr"].reject(&.starts_with? "lib/")
|
||||||
|
end
|
||||||
|
|
||||||
|
private def default_formatter
|
||||||
|
Formatter::DotFormatter.new
|
||||||
|
end
|
||||||
|
|
||||||
|
module Rule
|
||||||
|
getter config : YAML::Any?
|
||||||
|
|
||||||
|
macro prop(assign)
|
||||||
|
# Rule configuration property.
|
||||||
|
def {{assign.target}}
|
||||||
|
{% prop_name = assign.target.id.camelcase.gsub(/\?/, "") %}
|
||||||
|
|
||||||
|
{% if assign.value.is_a? NumberLiteral %}
|
||||||
|
int_prop "{{prop_name}}", {{assign.value}}
|
||||||
|
{% elsif assign.value.is_a? BoolLiteral %}
|
||||||
|
bool_prop "{{prop_name}}", {{assign.value}}
|
||||||
|
{% elsif assign.value.is_a? StringLiteral %}
|
||||||
|
str_prop "{{prop_name}}", {{assign.value}}
|
||||||
|
{% end %}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def initialize(config = nil)
|
||||||
|
@config = config.try &.subconfig(name)
|
||||||
|
end
|
||||||
|
|
||||||
|
protected def int_prop(name, default : Number)
|
||||||
|
str_prop(name, default).to_i
|
||||||
|
end
|
||||||
|
|
||||||
|
protected def bool_prop(name, default : Bool)
|
||||||
|
str_prop(name, default.to_s) == "true"
|
||||||
|
end
|
||||||
|
|
||||||
|
protected def str_prop(name, default)
|
||||||
|
config.try &.[name]?.try &.as_s || default
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,7 +1,11 @@
|
||||||
module Ameba::Rule
|
module Ameba::Rule
|
||||||
abstract struct Base
|
abstract struct Base
|
||||||
|
include Config::Rule
|
||||||
|
|
||||||
abstract def test(source : Source)
|
abstract def test(source : Source)
|
||||||
|
|
||||||
|
prop enabled? = true
|
||||||
|
|
||||||
def test(source : Source, node : Crystal::ASTNode)
|
def test(source : Source, node : Crystal::ASTNode)
|
||||||
# can't be abstract
|
# can't be abstract
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,10 +1,19 @@
|
||||||
module Ameba::Rule
|
module Ameba::Rule
|
||||||
# A rule that disallows lines longer than 80 symbols.
|
# A rule that disallows lines longer than `max_length` number of symbols.
|
||||||
#
|
#
|
||||||
|
# YAML configuration example:
|
||||||
|
#
|
||||||
|
# ```
|
||||||
|
# LineLength:
|
||||||
|
# Enabled: true
|
||||||
|
# MaxLength: 100
|
||||||
|
# ```
|
||||||
struct LineLength < Base
|
struct LineLength < Base
|
||||||
|
prop max_length = 80
|
||||||
|
|
||||||
def test(source)
|
def test(source)
|
||||||
source.lines.each_with_index do |line, index|
|
source.lines.each_with_index do |line, index|
|
||||||
next unless line.size > 80
|
next unless line.size > max_length
|
||||||
|
|
||||||
source.error self, source.location(index + 1, line.size),
|
source.error self, source.location(index + 1, line.size),
|
||||||
"Line too long"
|
"Line too long"
|
||||||
|
|
49
src/ameba/runner.cr
Normal file
49
src/ameba/runner.cr
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
module Ameba
|
||||||
|
class Runner
|
||||||
|
@rules : Array(Rule::Base)
|
||||||
|
@sources : Array(Source)
|
||||||
|
@formatter : Formatter::BaseFormatter
|
||||||
|
|
||||||
|
def initialize(config : Config)
|
||||||
|
@rules = load_rules(config)
|
||||||
|
@sources = load_sources(config)
|
||||||
|
@formatter = config.formatter
|
||||||
|
end
|
||||||
|
|
||||||
|
def run
|
||||||
|
@formatter.started @sources
|
||||||
|
@sources.each do |source|
|
||||||
|
@formatter.source_started source
|
||||||
|
|
||||||
|
@rules.each &.test(source)
|
||||||
|
|
||||||
|
@formatter.source_finished source
|
||||||
|
end
|
||||||
|
self
|
||||||
|
ensure
|
||||||
|
@formatter.finished @sources
|
||||||
|
end
|
||||||
|
|
||||||
|
def success?
|
||||||
|
@sources.all? &.valid?
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_source(source)
|
||||||
|
@formatter.source_started source
|
||||||
|
@rules.each &.test(source)
|
||||||
|
ensure
|
||||||
|
@formatter.source_finished source
|
||||||
|
end
|
||||||
|
|
||||||
|
private def load_sources(config)
|
||||||
|
config.files
|
||||||
|
.map { |wildcard| Dir[wildcard] }
|
||||||
|
.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
|
23
src/cli.cr
23
src/cli.cr
|
@ -1,10 +1,10 @@
|
||||||
require "option_parser"
|
require "option_parser"
|
||||||
require "./ameba"
|
require "./ameba"
|
||||||
|
|
||||||
formatter = Ameba::Formatter::DotFormatter
|
files, formatter, config_path = nil, nil, nil
|
||||||
|
|
||||||
OptionParser.parse(ARGV) do |parser|
|
OptionParser.parse(ARGV) do |parser|
|
||||||
parser.banner = "Usage: ameba [options]"
|
parser.banner = "Usage: ameba [options] [file1 file2 ...]"
|
||||||
|
|
||||||
parser.on("-v", "--version", "Print version") do
|
parser.on("-v", "--version", "Print version") do
|
||||||
puts Ameba::VERSION
|
puts Ameba::VERSION
|
||||||
|
@ -17,10 +17,23 @@ OptionParser.parse(ARGV) do |parser|
|
||||||
end
|
end
|
||||||
|
|
||||||
parser.on("-s", "--silent", "Disable output") do
|
parser.on("-s", "--silent", "Disable output") do
|
||||||
formatter = Ameba::Formatter::BaseFormatter
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
files = Dir["**/*.cr"]
|
config = Ameba::Config.load config_path
|
||||||
|
config.formatter = formatter
|
||||||
|
config.files = files
|
||||||
|
|
||||||
exit(1) unless Ameba.run(files, formatter.new).all? &.valid?
|
exit(1) unless Ameba.run(config).success?
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue