Skip to content

Commit

Permalink
Add Lint/Typos rule
Browse files Browse the repository at this point in the history
  • Loading branch information
Sija committed Jun 15, 2023
1 parent e1f5c81 commit 97a8e11
Showing 1 changed file with 87 additions and 0 deletions.
87 changes: 87 additions & 0 deletions src/ameba/rule/lint/typos.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
module Ameba::Rule::Lint
# A rule that reports typos found in source files.
#
# NOTE: Needs [typos](https://github.com/crate-ci/typos) CLI tool.
# NOTE: See the chapter on [false positives](https://github.com/crate-ci/typos#false-positives).
#
# YAML configuration example:
#
# ```
# Lint/Typos:
# Enabled: true
# BinPath: ~
# FailOnError: false
# ```
class Typos < Base
properties do
description "Reports typos found in source files"
fail_on_error false
bin_path nil.as(String?)
end

record Typo,
typo : String,
corrections : Array(String),
location : {Int32, Int32},
end_location : {Int32, Int32} do
def self.parse(str)
issue = JSON.parse(str)

return unless issue["type"] == "typo"

typo = issue["typo"].as_s
corrections = issue["corrections"].as_a.map(&.as_s)

return if typo.empty? || corrections.empty?

line_no = issue["line_num"].as_i
col_no = issue["byte_offset"].as_i + 1
end_col_no = col_no + typo.size - 1

new(typo, corrections,
{line_no, col_no}, {line_no, end_col_no})
end
end

MSG = "Typo found: %s -> %s"

protected class_getter bin_path : String? {
Process.find_executable("typos")
}

@[YAML::Field(ignore: true)]
protected getter bin_path : String {
@bin_path ||
self.class.bin_path ||
raise RuntimeError.new "Could not find `typos` executable"
}

def test(source : Source)
status = Process.run(bin_path, args: ["--format", "json", source.path],
output: output = IO::Memory.new,
)
return if status.success?

output.to_s.lines.each do |line|
next unless typo = Typo.parse(line)

message = MSG % {
typo.typo, typo.corrections.join(" / "),
}

# FIXME
# if typo.corrections.size == 1
# issue_for typo.location, typo.end_location, message do |corrector|
# corrector.replace(typo.location, typo.end_location, typo.corrections.first)
# end
# else
# issue_for typo.location, typo.end_location, message
# end

issue_for typo.location, typo.end_location, message
end
rescue ex
raise ex if fail_on_error?
end
end
end

0 comments on commit 97a8e11

Please sign in to comment.