mirror of
https://gitea.invidious.io/iv-org/shard-ameba.git
synced 2024-08-15 00:53:29 +00:00
Misc refactors (#180)
* Optimize Severity#symbol * Remove empty else branches * Optimize map+compact/flatten calls * Misc stylistic refactors
This commit is contained in:
parent
9d85e731f5
commit
19c370aee0
20 changed files with 87 additions and 98 deletions
|
@ -37,8 +37,7 @@ module Ameba::AST
|
||||||
|
|
||||||
# Returns true if this node or one of the parent branchables is a loop, false otherwise.
|
# Returns true if this node or one of the parent branchables is a loop, false otherwise.
|
||||||
def loop?
|
def loop?
|
||||||
return true if loop?(node)
|
loop?(node) || parent.try(&.loop?) || false
|
||||||
parent.try(&.loop?) || false
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -59,8 +59,6 @@ module Ameba::AST
|
||||||
end
|
end
|
||||||
when Crystal::BinaryOp
|
when Crystal::BinaryOp
|
||||||
unreachable_nodes << current_node.right if flow_expression?(current_node.left, in_loop?)
|
unreachable_nodes << current_node.right if flow_expression?(current_node.left, in_loop?)
|
||||||
else
|
|
||||||
# nop
|
|
||||||
end
|
end
|
||||||
|
|
||||||
unreachable_nodes
|
unreachable_nodes
|
||||||
|
|
|
@ -117,8 +117,8 @@ module Ameba::AST
|
||||||
|
|
||||||
# Returns true instance variable assinged in this scope.
|
# Returns true instance variable assinged in this scope.
|
||||||
def assigns_ivar?(name)
|
def assigns_ivar?(name)
|
||||||
arguments.find { |arg| arg.name == name } &&
|
arguments.find(&.name.== name) &&
|
||||||
ivariables.find { |var| var.name == "@#{name}" }
|
ivariables.find(&.name.== "@#{name}")
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns true if and only if current scope represents some
|
# Returns true if and only if current scope represents some
|
||||||
|
@ -137,13 +137,13 @@ module Ameba::AST
|
||||||
def references?(variable : Variable)
|
def references?(variable : Variable)
|
||||||
variable.references.any? do |reference|
|
variable.references.any? do |reference|
|
||||||
reference.scope == self ||
|
reference.scope == self ||
|
||||||
inner_scopes.any?(&.references? variable)
|
inner_scopes.any?(&.references?(variable))
|
||||||
end || variable.used_in_macro?
|
end || variable.used_in_macro?
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns true if current scope is a def, false if not.
|
# Returns true if current scope is a def, false if not.
|
||||||
def def?
|
def def?
|
||||||
node.is_a? Crystal::Def
|
node.is_a?(Crystal::Def)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns true if this scope is a top level scope, false if not.
|
# Returns true if this scope is a top level scope, false if not.
|
||||||
|
@ -173,7 +173,7 @@ module Ameba::AST
|
||||||
# the same Crystal node as `@node`.
|
# the same Crystal node as `@node`.
|
||||||
def eql?(node)
|
def eql?(node)
|
||||||
node == @node &&
|
node == @node &&
|
||||||
!node.location.nil? &&
|
node.location &&
|
||||||
node.location == @node.location
|
node.location == @node.location
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -72,12 +72,12 @@ module Ameba::Cli
|
||||||
|
|
||||||
parser.on("--only RULE1,RULE2,...",
|
parser.on("--only RULE1,RULE2,...",
|
||||||
"Run only given rules (or groups)") do |rules|
|
"Run only given rules (or groups)") do |rules|
|
||||||
opts.only = rules.split ","
|
opts.only = rules.split(',')
|
||||||
end
|
end
|
||||||
|
|
||||||
parser.on("--except RULE1,RULE2,...",
|
parser.on("--except RULE1,RULE2,...",
|
||||||
"Disable the given rules (or groups)") do |rules|
|
"Disable the given rules (or groups)") do |rules|
|
||||||
opts.except = rules.split ","
|
opts.except = rules.split(',')
|
||||||
end
|
end
|
||||||
|
|
||||||
parser.on("--all", "Enables all available rules") do
|
parser.on("--all", "Enables all available rules") do
|
||||||
|
@ -90,7 +90,8 @@ module Ameba::Cli
|
||||||
opts.config = ""
|
opts.config = ""
|
||||||
end
|
end
|
||||||
|
|
||||||
parser.on("--fail-level SEVERITY", "Change the level of failure to exit. Defaults to Convention") do |level|
|
parser.on("--fail-level SEVERITY",
|
||||||
|
"Change the level of failure to exit. Defaults to Convention") do |level|
|
||||||
opts.fail_level = Severity.parse(level)
|
opts.fail_level = Severity.parse(level)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -113,13 +114,13 @@ module Ameba::Cli
|
||||||
end
|
end
|
||||||
|
|
||||||
private def configure_rules(config, opts)
|
private def configure_rules(config, opts)
|
||||||
if only = opts.only
|
case
|
||||||
config.rules.map! { |r| r.enabled = false; r }
|
when only = opts.only
|
||||||
|
config.rules.map! &.tap(&.enabled = false)
|
||||||
config.update_rules(only, enabled: true)
|
config.update_rules(only, enabled: true)
|
||||||
elsif opts.all?
|
when opts.all?
|
||||||
config.rules.map! { |r| r.enabled = true; r }
|
config.rules.map! &.tap(&.enabled = true)
|
||||||
end
|
end
|
||||||
|
|
||||||
config.update_rules(opts.except, enabled: false)
|
config.update_rules(opts.except, enabled: false)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -127,7 +128,8 @@ module Ameba::Cli
|
||||||
if name = opts.formatter
|
if name = opts.formatter
|
||||||
config.formatter = name
|
config.formatter = name
|
||||||
end
|
end
|
||||||
config.formatter.config[:without_affected_code] = opts.without_affected_code?
|
config.formatter.config[:without_affected_code] =
|
||||||
|
opts.without_affected_code?
|
||||||
end
|
end
|
||||||
|
|
||||||
private def configure_explain_opts(loc, opts)
|
private def configure_explain_opts(loc, opts)
|
||||||
|
@ -138,10 +140,15 @@ module Ameba::Cli
|
||||||
end
|
end
|
||||||
|
|
||||||
private def parse_explain_location(arg)
|
private def parse_explain_location(arg)
|
||||||
location = arg.split(":", remove_empty: true).map &.strip
|
location = arg.split(':', remove_empty: true).map! &.strip
|
||||||
raise ArgumentError.new unless location.size === 3
|
raise ArgumentError.new unless location.size === 3
|
||||||
|
|
||||||
file, line, column = location
|
file, line, column = location
|
||||||
{file: file, line: line.to_i, column: column.to_i}
|
{
|
||||||
|
file: file,
|
||||||
|
line: line.to_i,
|
||||||
|
column: column.to_i,
|
||||||
|
}
|
||||||
rescue
|
rescue
|
||||||
raise "location should have PATH:line:column format"
|
raise "location should have PATH:line:column format"
|
||||||
end
|
end
|
||||||
|
|
|
@ -31,7 +31,6 @@ class Ameba::Config
|
||||||
!lib
|
!lib
|
||||||
)
|
)
|
||||||
|
|
||||||
setter formatter : Formatter::BaseFormatter?
|
|
||||||
getter rules : Array(Rule::Base)
|
getter rules : Array(Rule::Base)
|
||||||
property severity = Severity::Convention
|
property severity = Severity::Convention
|
||||||
|
|
||||||
|
@ -66,7 +65,9 @@ class Ameba::Config
|
||||||
@excluded = load_array_section(config, "Excluded")
|
@excluded = load_array_section(config, "Excluded")
|
||||||
@globs = load_array_section(config, "Globs", DEFAULT_GLOBS)
|
@globs = load_array_section(config, "Globs", DEFAULT_GLOBS)
|
||||||
|
|
||||||
self.formatter = load_formatter_name(config)
|
if formatter_name = load_formatter_name(config)
|
||||||
|
self.formatter = formatter_name
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Loads YAML configuration file by `path`.
|
# Loads YAML configuration file by `path`.
|
||||||
|
@ -84,7 +85,7 @@ class Ameba::Config
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.formatter_names
|
def self.formatter_names
|
||||||
AVAILABLE_FORMATTERS.keys.join("|")
|
AVAILABLE_FORMATTERS.keys.join('|')
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns a list of sources matching globs and excluded sections.
|
# Returns a list of sources matching globs and excluded sections.
|
||||||
|
@ -111,8 +112,8 @@ class Ameba::Config
|
||||||
# config.formatter
|
# config.formatter
|
||||||
# ```
|
# ```
|
||||||
#
|
#
|
||||||
def formatter
|
property formatter : Formatter::BaseFormatter do
|
||||||
@formatter ||= Formatter::DotFormatter.new
|
Formatter::DotFormatter.new
|
||||||
end
|
end
|
||||||
|
|
||||||
# Sets formatter by name.
|
# Sets formatter by name.
|
||||||
|
@ -138,7 +139,7 @@ class Ameba::Config
|
||||||
# ```
|
# ```
|
||||||
#
|
#
|
||||||
def update_rule(name, enabled = true, excluded = nil)
|
def update_rule(name, enabled = true, excluded = nil)
|
||||||
index = @rules.index { |r| r.name == name }
|
index = @rules.index { |rule| rule.name == name }
|
||||||
raise ArgumentError.new("Rule `#{name}` does not exist") unless index
|
raise ArgumentError.new("Rule `#{name}` does not exist") unless index
|
||||||
|
|
||||||
rule = @rules[index]
|
rule = @rules[index]
|
||||||
|
@ -172,7 +173,7 @@ class Ameba::Config
|
||||||
|
|
||||||
private def load_formatter_name(config)
|
private def load_formatter_name(config)
|
||||||
name = config["Formatter"]?.try &.["Name"]?
|
name = config["Formatter"]?.try &.["Name"]?
|
||||||
name ? name.to_s : nil
|
name.try(&.to_s)
|
||||||
end
|
end
|
||||||
|
|
||||||
private def load_array_section(config, section_name, default = [] of String)
|
private def load_array_section(config, section_name, default = [] of String)
|
||||||
|
|
|
@ -35,14 +35,17 @@ module Ameba::Formatter
|
||||||
next if issue.disabled?
|
next if issue.disabled?
|
||||||
next if (location = issue.location).nil?
|
next if (location = issue.location).nil?
|
||||||
|
|
||||||
output << "#{location}\n".colorize(:cyan)
|
output.puts location.colorize(:cyan)
|
||||||
output << "[#{issue.rule.severity.symbol}] #{issue.rule.name}: #{issue.message}\n".colorize(:red)
|
output.puts \
|
||||||
|
"[#{issue.rule.severity.symbol}] " \
|
||||||
|
"#{issue.rule.name}: " \
|
||||||
|
"#{issue.message}".colorize(:red)
|
||||||
|
|
||||||
if show_affected_code && (code = affected_code(source, location))
|
if show_affected_code && (code = affected_code(source, location))
|
||||||
output << code.colorize(:default)
|
output << code.colorize(:default)
|
||||||
end
|
end
|
||||||
|
|
||||||
output << "\n"
|
output << '\n'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -4,9 +4,8 @@ module Ameba::Formatter
|
||||||
# A formatter that shows the detailed explanation of the issue at
|
# A formatter that shows the detailed explanation of the issue at
|
||||||
# a specific location.
|
# a specific location.
|
||||||
class ExplainFormatter
|
class ExplainFormatter
|
||||||
LINE_BREAK = "\n"
|
HEADING = "## "
|
||||||
HEADING = "## "
|
PREFIX = " "
|
||||||
PREFIX = " "
|
|
||||||
|
|
||||||
include Util
|
include Util
|
||||||
|
|
||||||
|
@ -65,19 +64,19 @@ module Ameba::Formatter
|
||||||
end
|
end
|
||||||
|
|
||||||
private def output_title(title)
|
private def output_title(title)
|
||||||
output << HEADING.colorize(:yellow) << title.colorize(:yellow) << LINE_BREAK
|
output << HEADING.colorize(:yellow) << title.colorize(:yellow) << '\n'
|
||||||
output << LINE_BREAK
|
output << '\n'
|
||||||
end
|
end
|
||||||
|
|
||||||
private def output_paragraph(paragraph : String)
|
private def output_paragraph(paragraph : String)
|
||||||
output_paragraph(paragraph.split(LINE_BREAK))
|
output_paragraph(paragraph.split('\n'))
|
||||||
end
|
end
|
||||||
|
|
||||||
private def output_paragraph(paragraph : Array(String))
|
private def output_paragraph(paragraph : Array(String))
|
||||||
paragraph.each do |line|
|
paragraph.each do |line|
|
||||||
output << PREFIX << line << LINE_BREAK
|
output << PREFIX << line << '\n'
|
||||||
end
|
end
|
||||||
output << LINE_BREAK
|
output << '\n'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -9,7 +9,7 @@ module Ameba::Formatter
|
||||||
@mutex.synchronize do
|
@mutex.synchronize do
|
||||||
output.printf "%s:%d:%d: %s: [%s] %s\n",
|
output.printf "%s:%d:%d: %s: [%s] %s\n",
|
||||||
source.path, loc.line_number, loc.column_number, e.rule.severity.symbol,
|
source.path, loc.line_number, loc.column_number, e.rule.severity.symbol,
|
||||||
e.rule.name, e.message.gsub("\n", " ")
|
e.rule.name, e.message.gsub('\n', " ")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -8,19 +8,20 @@ module Ameba::Formatter
|
||||||
|
|
||||||
def finished(sources)
|
def finished(sources)
|
||||||
super
|
super
|
||||||
issues = sources.map(&.issues).flatten
|
|
||||||
|
issues = sources.flat_map(&.issues)
|
||||||
unless issues.any? { |issue| !issue.disabled? }
|
unless issues.any? { |issue| !issue.disabled? }
|
||||||
@output << "No issues found. File is not generated.\n"
|
@output.puts "No issues found. File is not generated."
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if issues.any? { |issue| issue.syntax? }
|
if issues.any?(&.syntax?)
|
||||||
@output << "Unable to generate TODO file. Please fix syntax issues.\n"
|
@output.puts "Unable to generate TODO file. Please fix syntax issues."
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
file = generate_todo_config issues
|
file = generate_todo_config issues
|
||||||
@output << "Created #{file.path}\n"
|
@output.puts "Created #{file.path}"
|
||||||
file
|
file
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -57,10 +58,9 @@ module Ameba::Formatter
|
||||||
end
|
end
|
||||||
|
|
||||||
private def rule_todo(rule, issues)
|
private def rule_todo(rule, issues)
|
||||||
rule.excluded =
|
rule.excluded = issues
|
||||||
issues.map(&.location.try &.filename.try &.to_s)
|
.compact_map(&.location.try &.filename.try &.to_s)
|
||||||
.compact
|
.uniq!
|
||||||
.uniq!
|
|
||||||
|
|
||||||
{rule.name => rule}.to_yaml
|
{rule.name => rule}.to_yaml
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,9 +2,9 @@ module Ameba::Formatter
|
||||||
module Util
|
module Util
|
||||||
def affected_code(source, location, max_length = 100, placeholder = " ...", prompt = "> ")
|
def affected_code(source, location, max_length = 100, placeholder = " ...", prompt = "> ")
|
||||||
line, column = location.line_number, location.column_number
|
line, column = location.line_number, location.column_number
|
||||||
affected_line = source.lines[line - 1]?
|
affected_line = source.lines[line - 1]?.presence
|
||||||
|
|
||||||
return if affected_line.nil? || affected_line.strip.empty?
|
return unless affected_line
|
||||||
|
|
||||||
if affected_line.size > max_length && column < max_length
|
if affected_line.size > max_length && column < max_length
|
||||||
affected_line = affected_line[0, max_length - placeholder.size - 1] + placeholder
|
affected_line = affected_line[0, max_length - placeholder.size - 1] + placeholder
|
||||||
|
@ -14,7 +14,7 @@ module Ameba::Formatter
|
||||||
position = column - (affected_line.size - stripped.size) + prompt.size
|
position = column - (affected_line.size - stripped.size) + prompt.size
|
||||||
|
|
||||||
String.build do |str|
|
String.build do |str|
|
||||||
str << prompt << stripped << "\n"
|
str << prompt << stripped << '\n'
|
||||||
str << " " * (position - 1)
|
str << " " * (position - 1)
|
||||||
str << "^".colorize(:yellow)
|
str << "^".colorize(:yellow)
|
||||||
end
|
end
|
||||||
|
|
|
@ -22,10 +22,10 @@ module Ameba
|
||||||
# ```
|
# ```
|
||||||
#
|
#
|
||||||
def expand(globs)
|
def expand(globs)
|
||||||
globs.map do |glob|
|
globs.flat_map do |glob|
|
||||||
glob += "/**/*.cr" if File.directory?(glob)
|
glob += "/**/*.cr" if File.directory?(glob)
|
||||||
Dir[glob]
|
Dir[glob]
|
||||||
end.flatten.uniq!
|
end.uniq!
|
||||||
end
|
end
|
||||||
|
|
||||||
private def rejected_globs(globs)
|
private def rejected_globs(globs)
|
||||||
|
|
|
@ -89,8 +89,10 @@ module Ameba
|
||||||
|
|
||||||
private def line_disabled?(line, rule)
|
private def line_disabled?(line, rule)
|
||||||
return false unless directive = parse_inline_directive(line)
|
return false unless directive = parse_inline_directive(line)
|
||||||
Action.parse?(directive[:action]).try(&.disable?) &&
|
return false unless Action.parse?(directive[:action]).try(&.disable?)
|
||||||
(directive[:rules].includes?(rule.name) || directive[:rules].includes?(rule.group))
|
|
||||||
|
directive[:rules].includes?(rule.name) ||
|
||||||
|
directive[:rules].includes?(rule.group)
|
||||||
end
|
end
|
||||||
|
|
||||||
private def commented_out?(line)
|
private def commented_out?(line)
|
||||||
|
|
|
@ -95,7 +95,7 @@ module Ameba::Rule
|
||||||
def excluded?(source)
|
def excluded?(source)
|
||||||
excluded.try &.any? do |path|
|
excluded.try &.any? do |path|
|
||||||
source.matches_path?(path) ||
|
source.matches_path?(path) ||
|
||||||
Dir.glob(path).any? { |glob| source.matches_path? glob }
|
Dir.glob(path).any? { |glob| source.matches_path?(glob) }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -123,11 +123,11 @@ module Ameba::Rule
|
||||||
end
|
end
|
||||||
|
|
||||||
protected def self.rule_name
|
protected def self.rule_name
|
||||||
name.gsub("Ameba::Rule::", "").gsub("::", "/")
|
name.gsub("Ameba::Rule::", "").gsub("::", '/')
|
||||||
end
|
end
|
||||||
|
|
||||||
protected def self.group_name
|
protected def self.group_name
|
||||||
rule_name.split("/")[0...-1].join("/")
|
rule_name.split('/')[0...-1].join('/')
|
||||||
end
|
end
|
||||||
|
|
||||||
protected def self.subclasses
|
protected def self.subclasses
|
||||||
|
@ -157,7 +157,7 @@ module Ameba::Rule
|
||||||
def self.parsed_doc
|
def self.parsed_doc
|
||||||
source = File.read(path_to_source_file)
|
source = File.read(path_to_source_file)
|
||||||
nodes = Crystal::Parser.new(source).tap(&.wants_doc = true).parse
|
nodes = Crystal::Parser.new(source).tap(&.wants_doc = true).parse
|
||||||
type_name = rule_name.split("/").last?
|
type_name = rule_name.split('/').last?
|
||||||
DocFinder.new(nodes, type_name).doc
|
DocFinder.new(nodes, type_name).doc
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -49,8 +49,6 @@ module Ameba::Rule::Lint
|
||||||
issue_for start_token.not_nil!, issue.not_nil!
|
issue_for start_token.not_nil!, issue.not_nil!
|
||||||
end
|
end
|
||||||
issue = start_token = nil
|
issue = start_token = nil
|
||||||
else
|
|
||||||
# nop
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -61,8 +59,6 @@ module Ameba::Rule::Lint
|
||||||
check_array_entry entry, string_array_unwanted_symbols, "%w"
|
check_array_entry entry, string_array_unwanted_symbols, "%w"
|
||||||
when .starts_with? "%i"
|
when .starts_with? "%i"
|
||||||
check_array_entry entry, symbol_array_unwanted_symbols, "%i"
|
check_array_entry entry, symbol_array_unwanted_symbols, "%i"
|
||||||
else
|
|
||||||
# nop
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -42,8 +42,6 @@ module Ameba::Rule::Lint
|
||||||
report source, node, "Remove redundant with_index"
|
report source, node, "Remove redundant with_index"
|
||||||
when "each_with_index"
|
when "each_with_index"
|
||||||
report source, node, "Use each instead of each_with_index"
|
report source, node, "Use each instead of each_with_index"
|
||||||
else
|
|
||||||
# nop
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -76,8 +76,6 @@ module Ameba::Rule::Style
|
||||||
redundant_begin_in_handler?(source, body, node)
|
redundant_begin_in_handler?(source, body, node)
|
||||||
when Crystal::Expressions
|
when Crystal::Expressions
|
||||||
redundant_begin_in_expressions?(body)
|
redundant_begin_in_expressions?(body)
|
||||||
else
|
|
||||||
# nop
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -88,7 +86,7 @@ module Ameba::Rule::Style
|
||||||
private def redundant_begin_in_handler?(source, handler, node)
|
private def redundant_begin_in_handler?(source, handler, node)
|
||||||
return false if begin_exprs_in_handler?(handler) || inner_handler?(handler)
|
return false if begin_exprs_in_handler?(handler) || inner_handler?(handler)
|
||||||
|
|
||||||
code = node_source(node, source.lines).try &.join("\n")
|
code = node_source(node, source.lines).try &.join('\n')
|
||||||
def_redundant_begin? code if code
|
def_redundant_begin? code if code
|
||||||
rescue
|
rescue
|
||||||
false
|
false
|
||||||
|
|
|
@ -50,7 +50,6 @@ module Ameba
|
||||||
.find &.name.==(Rule::Lint::UnneededDisableDirective.rule_name)
|
.find &.name.==(Rule::Lint::UnneededDisableDirective.rule_name)
|
||||||
end
|
end
|
||||||
|
|
||||||
# :nodoc:
|
|
||||||
protected def initialize(@rules, @sources, @formatter, @severity)
|
protected def initialize(@rules, @sources, @formatter, @severity)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -80,9 +79,8 @@ module Ameba
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
channels.each do |c|
|
channels.each do |chan|
|
||||||
e = c.receive
|
chan.receive.try { |e| raise e }
|
||||||
raise e unless e.nil?
|
|
||||||
end
|
end
|
||||||
|
|
||||||
self
|
self
|
||||||
|
|
|
@ -9,8 +9,12 @@ module Ameba
|
||||||
# ```
|
# ```
|
||||||
# Severity::Warning.symbol # => 'W'
|
# Severity::Warning.symbol # => 'W'
|
||||||
# ```
|
# ```
|
||||||
def symbol
|
def symbol : Char
|
||||||
to_s[0]
|
case self
|
||||||
|
in Error then 'E'
|
||||||
|
in Warning then 'W'
|
||||||
|
in Convention then 'C'
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Creates Severity by the name.
|
# Creates Severity by the name.
|
||||||
|
|
|
@ -11,10 +11,6 @@ module Ameba
|
||||||
# Crystal code (content of a source file).
|
# Crystal code (content of a source file).
|
||||||
getter code : String
|
getter code : String
|
||||||
|
|
||||||
@lines : Array(String)?
|
|
||||||
@ast : Crystal::ASTNode?
|
|
||||||
@fullpath : String?
|
|
||||||
|
|
||||||
# Creates a new source by `code` and `path`.
|
# Creates a new source by `code` and `path`.
|
||||||
#
|
#
|
||||||
# For example:
|
# For example:
|
||||||
|
@ -24,7 +20,7 @@ module Ameba
|
||||||
# Ameba::Source.new File.read(path), path
|
# Ameba::Source.new File.read(path), path
|
||||||
# ```
|
# ```
|
||||||
#
|
#
|
||||||
def initialize(@code : String, @path = "")
|
def initialize(@code, @path = "")
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns lines of code splitted by new line character.
|
# Returns lines of code splitted by new line character.
|
||||||
|
@ -38,9 +34,7 @@ module Ameba
|
||||||
# source.lines # => ["a = 1", "b = 2"]
|
# source.lines # => ["a = 1", "b = 2"]
|
||||||
# ```
|
# ```
|
||||||
#
|
#
|
||||||
def lines
|
getter lines : Array(String) { code.split('\n') }
|
||||||
@lines ||= @code.split("\n")
|
|
||||||
end
|
|
||||||
|
|
||||||
# Returns AST nodes constructed by `Crystal::Parser`.
|
# Returns AST nodes constructed by `Crystal::Parser`.
|
||||||
#
|
#
|
||||||
|
@ -49,16 +43,15 @@ module Ameba
|
||||||
# source.ast
|
# source.ast
|
||||||
# ```
|
# ```
|
||||||
#
|
#
|
||||||
def ast
|
getter ast : Crystal::ASTNode do
|
||||||
@ast ||=
|
Crystal::Parser.new(code)
|
||||||
Crystal::Parser.new(code)
|
.tap(&.wants_doc = true)
|
||||||
.tap { |parser| parser.wants_doc = true }
|
.tap(&.filename = path)
|
||||||
.tap { |parser| parser.filename = @path }
|
.parse
|
||||||
.parse
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def fullpath
|
getter fullpath : String do
|
||||||
@fullpath ||= File.expand_path @path
|
File.expand_path(path)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns true if *filepath* matches the source's path, false if it does not.
|
# Returns true if *filepath* matches the source's path, false if it does not.
|
||||||
|
|
|
@ -53,8 +53,7 @@ module Ameba
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
|
|
||||||
private def run_normal_state(lexer, break_on_rcurly = false,
|
private def run_normal_state(lexer, break_on_rcurly = false, &block : Crystal::Token -> _)
|
||||||
&block : Crystal::Token -> _)
|
|
||||||
loop do
|
loop do
|
||||||
token = @lexer.next_token
|
token = @lexer.next_token
|
||||||
block.call token
|
block.call token
|
||||||
|
@ -68,8 +67,6 @@ module Ameba
|
||||||
break
|
break
|
||||||
when :"}"
|
when :"}"
|
||||||
break if break_on_rcurly
|
break if break_on_rcurly
|
||||||
else
|
|
||||||
# go on
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -86,8 +83,6 @@ module Ameba
|
||||||
run_normal_state lexer, break_on_rcurly: true, &block
|
run_normal_state lexer, break_on_rcurly: true, &block
|
||||||
when :EOF
|
when :EOF
|
||||||
break
|
break
|
||||||
else
|
|
||||||
# go on
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -102,8 +97,6 @@ module Ameba
|
||||||
break
|
break
|
||||||
when :EOF
|
when :EOF
|
||||||
break
|
break
|
||||||
else
|
|
||||||
# go on
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue