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,57 +138,29 @@ module Ameba::Rule
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private macro read_rule_doc(filepath = __FILE__)
 | 
				
			||||||
 | 
					      {{ run("../../read_rule_doc",
 | 
				
			||||||
 | 
					           @type.name.split("::").last,
 | 
				
			||||||
 | 
					           filepath
 | 
				
			||||||
 | 
					         ).chomp.stringify }}.presence
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    macro inherited
 | 
					    macro inherited
 | 
				
			||||||
      protected def self.path_to_source_file
 | 
					      # Returns documentation for this rule, if there is any.
 | 
				
			||||||
        __FILE__
 | 
					      #
 | 
				
			||||||
      end
 | 
					      # ```
 | 
				
			||||||
    end
 | 
					      # module Ameba
 | 
				
			||||||
 | 
					      #   # This is a test rule.
 | 
				
			||||||
    # Returns documentation for this rule if any.
 | 
					      #   # Does nothing.
 | 
				
			||||||
    #
 | 
					      #   class MyRule < Ameba::Rule::Base
 | 
				
			||||||
    # ```
 | 
					      #     def test(source)
 | 
				
			||||||
    # module Ameba
 | 
					      #     end
 | 
				
			||||||
    #   # This is a test rule.
 | 
					      #   end
 | 
				
			||||||
    #   # Does nothing.
 | 
					      # end
 | 
				
			||||||
    #   class MyRule < Ameba::Rule::Base
 | 
					      #
 | 
				
			||||||
    #     def test(source)
 | 
					      # MyRule.parsed_doc # => "This is a test rule.\nDoes nothing."
 | 
				
			||||||
    #     end
 | 
					      # ```
 | 
				
			||||||
    #   end
 | 
					      class_getter parsed_doc : String? = read_rule_doc
 | 
				
			||||||
    # 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
 | 
					 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
  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