mirror of
				https://gitea.invidious.io/iv-org/shard-ameba.git
				synced 2024-08-15 00:53:29 +00:00 
			
		
		
		
	Populate Rule::Base+.parsed_doc on compile time
				
					
				
			This commit is contained in:
		
							parent
							
								
									cac1ce4138
								
							
						
					
					
						commit
						3d61254739
					
				
					 2 changed files with 54 additions and 50 deletions
				
			
		| 
						 | 
				
			
			@ -138,13 +138,15 @@ module Ameba::Rule
 | 
			
		|||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    macro inherited
 | 
			
		||||
      protected def self.path_to_source_file
 | 
			
		||||
        __FILE__
 | 
			
		||||
      end
 | 
			
		||||
    private macro read_rule_doc(filepath = __FILE__)
 | 
			
		||||
      {{ run("../../read_rule_doc",
 | 
			
		||||
           @type.name.split("::").last,
 | 
			
		||||
           filepath
 | 
			
		||||
         ).chomp.stringify }}.presence
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns documentation for this rule if any.
 | 
			
		||||
    macro inherited
 | 
			
		||||
      # Returns documentation for this rule, if there is any.
 | 
			
		||||
      #
 | 
			
		||||
      # ```
 | 
			
		||||
      # module Ameba
 | 
			
		||||
| 
						 | 
				
			
			@ -158,37 +160,7 @@ module Ameba::Rule
 | 
			
		|||
      #
 | 
			
		||||
      # 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
 | 
			
		||||
      class_getter parsed_doc : String? = read_rule_doc
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										32
									
								
								src/read_rule_doc.cr
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								src/read_rule_doc.cr
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,32 @@
 | 
			
		|||
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) &&
 | 
			
		||||
       name.is_a?(Crystal::Path) &&
 | 
			
		||||
       name.names.last? == @type_name
 | 
			
		||||
      @doc = node.doc
 | 
			
		||||
    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…
	
	Add table
		Add a link
		
	
		Reference in a new issue