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…
	
	Add table
		Add a link
		
	
		Reference in a new issue