mirror of
https://gitea.invidious.io/iv-org/shard-ameba.git
synced 2024-08-15 00:53:29 +00:00
Merge pull request #282 from crystal-ameba/Sija/fix-issue-270
Populate `Rule::Base+.parsed_doc` on compile time
This commit is contained in:
commit
4700ae7649
2 changed files with 51 additions and 50 deletions
|
@ -138,57 +138,29 @@ module Ameba::Rule
|
|||
end
|
||||
end
|
||||
|
||||
private macro read_type_doc(filepath = __FILE__)
|
||||
{{ run("../../contrib/read_type_doc",
|
||||
@type.name.split("::").last,
|
||||
filepath
|
||||
).chomp.stringify }}.presence
|
||||
end
|
||||
|
||||
macro inherited
|
||||
protected def self.path_to_source_file
|
||||
__FILE__
|
||||
end
|
||||
end
|
||||
|
||||
# Returns documentation for this rule if any.
|
||||
#
|
||||
# ```
|
||||
# module Ameba
|
||||
# # This is a test rule.
|
||||
# # Does nothing.
|
||||
# class MyRule < Ameba::Rule::Base
|
||||
# def test(source)
|
||||
# end
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# MyRule.parsed_doc # => "This is a test rule.\nDoes nothing."
|
||||
# ```
|
||||
def self.parsed_doc
|
||||
source = File.read(path_to_source_file)
|
||||
nodes = Crystal::Parser.new(source)
|
||||
.tap(&.wants_doc = true)
|
||||
.parse
|
||||
type_name = rule_name.split('/').last?
|
||||
|
||||
DocFinder.new(nodes, type_name).doc
|
||||
end
|
||||
|
||||
# :nodoc:
|
||||
private class DocFinder < Crystal::Visitor
|
||||
getter doc : String?
|
||||
getter type_name : String?
|
||||
|
||||
def initialize(nodes, @type_name)
|
||||
self.accept(nodes)
|
||||
end
|
||||
|
||||
def visit(node : Crystal::ASTNode)
|
||||
return false if @doc
|
||||
|
||||
if node.responds_to?(:name) &&
|
||||
(name = node.name) &&
|
||||
name.is_a?(Crystal::Path) &&
|
||||
name.names.last? == @type_name
|
||||
@doc = node.doc
|
||||
end
|
||||
|
||||
true
|
||||
end
|
||||
# Returns documentation for this rule, if there is any.
|
||||
#
|
||||
# ```
|
||||
# module Ameba
|
||||
# # This is a test rule.
|
||||
# # Does nothing.
|
||||
# class MyRule < Ameba::Rule::Base
|
||||
# def test(source)
|
||||
# end
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# MyRule.parsed_doc # => "This is a test rule.\nDoes nothing."
|
||||
# ```
|
||||
class_getter parsed_doc : String? = read_type_doc
|
||||
end
|
||||
end
|
||||
|
||||
|
|
29
src/contrib/read_type_doc.cr
Normal file
29
src/contrib/read_type_doc.cr
Normal file
|
@ -0,0 +1,29 @@
|
|||
require "compiler/crystal/syntax/*"
|
||||
|
||||
private class DocFinder < Crystal::Visitor
|
||||
getter type_name : String
|
||||
getter doc : String?
|
||||
|
||||
def initialize(nodes, @type_name)
|
||||
self.accept(nodes)
|
||||
end
|
||||
|
||||
def visit(node : Crystal::ASTNode)
|
||||
return false if @doc
|
||||
|
||||
if node.responds_to?(:name) && (name = node.name).is_a?(Crystal::Path)
|
||||
@doc = node.doc if name.names.last? == @type_name
|
||||
end
|
||||
|
||||
true
|
||||
end
|
||||
end
|
||||
|
||||
type_name, path_to_source_file = ARGV
|
||||
|
||||
source = File.read(path_to_source_file)
|
||||
nodes = Crystal::Parser.new(source)
|
||||
.tap(&.wants_doc = true)
|
||||
.parse
|
||||
|
||||
puts DocFinder.new(nodes, type_name).doc
|
Loading…
Reference in a new issue