Refactor ExplainFormatter

This commit is contained in:
Sijawusz Pur Rahnama 2022-11-25 05:02:37 +01:00
parent f9b05a309e
commit 33ef9c6293
3 changed files with 41 additions and 22 deletions

View file

@ -59,7 +59,7 @@ module Ameba
source = Source.new "a = 42", "source.cr" source = Source.new "a = 42", "source.cr"
output = explanation(source) output = explanation(source)
output.should contain "DETAILED DESCRIPTION" output.should contain "DETAILED DESCRIPTION"
output.should contain "TO BE DONE..." output.should contain "Rule extended description"
end end
it "writes nothing if location not found" do it "writes nothing if location not found" do

View file

@ -24,6 +24,7 @@ module Ameba
end end
end end
# Rule extended description
class ErrorRule < Rule::Base class ErrorRule < Rule::Base
properties do properties do
description "Always adds an error at 1:1" description "Always adds an error at 1:1"

View file

@ -4,8 +4,7 @@ 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
HEADING = "## " HEADING_MARKER = "## "
PREFIX = " "
include Util include Util
@ -18,13 +17,18 @@ module Ameba::Formatter
# Second argument is *location* which indicates the location to explain. # Second argument is *location* which indicates the location to explain.
# #
# ``` # ```
# ExplainFormatter.new output, # ExplainFormatter.new output, {
# file: path, # file: path,
# line: line_number, # line: line_number,
# column: column_number # column: column_number,
# }
# ``` # ```
def initialize(@output, location) def initialize(@output, location)
@location = Crystal::Location.new(location[:file], location[:line], location[:column]) @location = Crystal::Location.new(
location[:file],
location[:line],
location[:column]
)
end end
# Reports the explanations at the *@location*. # Reports the explanations at the *@location*.
@ -39,42 +43,56 @@ module Ameba::Formatter
end end
private def explain(source, issue) private def explain(source, issue)
rule = issue.rule
return unless location = issue.location return unless location = issue.location
output_title "ISSUE INFO" output << '\n'
output_title "Issue info"
output_paragraph [ output_paragraph [
issue.message.colorize(:red).to_s, issue.message.colorize(:red),
location.to_s.colorize(:cyan).to_s, location.to_s.colorize(:cyan),
] ]
if affected_code = affected_code(issue, context_lines: 3) if affected_code = affected_code(issue, context_lines: 3)
output_title "AFFECTED CODE" output_title "Affected code"
output_paragraph affected_code output_paragraph affected_code
end end
rule = issue.rule
output_title "Rule info"
output_paragraph "%s of a %s severity" % {
rule.name.colorize(:magenta),
rule.severity.to_s.colorize(rule.severity.color),
}
if rule.responds_to?(:description) if rule.responds_to?(:description)
output_title "RULE INFO" output_paragraph rule.description
output_paragraph [rule.severity.to_s, rule.name, rule.description]
end end
output_title "DETAILED DESCRIPTION" rule_doc = colorize_code_blocks(rule.class.parsed_doc)
output_paragraph(rule.class.parsed_doc || "TO BE DONE...") return unless rule_doc
output_title "Detailed description"
output_paragraph rule_doc
end
private def colorize_code_blocks(string)
string.try &.gsub(/```(.+?)```/m, &.colorize(:dark_gray))
end end
private def output_title(title) private def output_title(title)
output << HEADING.colorize(:yellow) << title.colorize(:yellow) << '\n' output << HEADING_MARKER.colorize(:yellow)
output << '\n' output << title.upcase.colorize(:yellow)
output << "\n\n"
end end
private def output_paragraph(paragraph : String) private def output_paragraph(paragraph : String)
output_paragraph(paragraph.lines) output_paragraph(paragraph.lines)
end end
private def output_paragraph(paragraph : Array(String)) private def output_paragraph(paragraph : Array)
paragraph.each do |line| paragraph.each do |line|
output << PREFIX << line << '\n' output << ' ' << line << '\n'
end end
output << '\n' output << '\n'
end end