Class: PinkSpoon::DocExtractor
- Inherits:
-
Object
- Object
- PinkSpoon::DocExtractor
- Defined in:
- lib/pink_spoon/doc_extractor.rb
Overview
Fetches YARD/RDoc comments from installed gem source files for a given type + method. Handles both regular ‘def` and DSL-style definitions like `define_example_method :it` or `define_example_group_method :describe`.
Gem lookup uses the downcased first namespace component so that ‘RSpec::Core::ExampleGroup` correctly finds the `rspec-core` gem rather than trying the broken underscore form `r_spec`.
Defined Under Namespace
Classes: ConstantDefinitionFinder
Instance Method Summary collapse
-
#extract(type, method_name) ⇒ Object
Returns a markdown string with the doc comment, or nil.
-
#extract_for_constant(type) ⇒ Object
Returns markdown docs for a class/module/constant.
-
#extract_for_location(loc) ⇒ Object
Returns hover markdown for a known file+line (used as fallback when find_constant_location cannot locate the constant via gem-hint scanning).
-
#find_constant_source(type) ⇒ Object
Returns { file: absolute_path, line: integer } for a class/module definition.
-
#find_ivar_in_type(type, ivar_name) ⇒ Object
Returns { file:, line: } for the first assignment of ivar_name (@foo = …) in any source file belonging to the given type’s gem or project.
-
#find_source(type, method_name) ⇒ Object
Returns { file: absolute_path, line: integer } or nil.
-
#initialize(root_path) ⇒ DocExtractor
constructor
A new instance of DocExtractor.
Constructor Details
#initialize(root_path) ⇒ DocExtractor
Returns a new instance of DocExtractor.
14 15 16 17 |
# File 'lib/pink_spoon/doc_extractor.rb', line 14 def initialize(root_path) @root_path = root_path @cache = {} end |
Instance Method Details
#extract(type, method_name) ⇒ Object
Returns a markdown string with the doc comment, or nil.
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
# File 'lib/pink_spoon/doc_extractor.rb', line 113 def extract(type, method_name) cache_key = "doc:#{type}##{method_name}" return @cache[cache_key] if @cache.key?(cache_key) @cache[cache_key] = begin loc = find_location(type, method_name) if loc raw = read_comments(loc[:file], loc[:line]) raw.empty? ? nil : render(raw) else extract_via_ri(type, method_name) end end rescue nil end |
#extract_for_constant(type) ⇒ Object
Returns markdown docs for a class/module/constant. When there is a YARD comment above the definition, renders it. When there is no comment, falls back to showing the declaration line itself.
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/pink_spoon/doc_extractor.rb', line 65 def extract_for_constant(type) cache_key = "const_doc:#{type}" return @cache[cache_key] if @cache.key?(cache_key) @cache[cache_key] = begin loc = find_constant_location(type) if loc raw = read_comments(loc[:file], loc[:line]) if raw.empty? decl = declaration_line(loc[:file], loc[:line]) decl ? "```ruby\n#{decl}\n```" : nil else render(raw) end end end rescue nil end |
#extract_for_location(loc) ⇒ Object
Returns hover markdown for a known file+line (used as fallback when find_constant_location cannot locate the constant via gem-hint scanning).
88 89 90 91 92 93 94 95 96 97 98 99 100 |
# File 'lib/pink_spoon/doc_extractor.rb', line 88 def extract_for_location(loc) return nil unless loc raw = read_comments(loc[:file], loc[:line]) if raw.empty? decl = declaration_line(loc[:file], loc[:line]) decl ? "```ruby\n#{decl}\n```" : nil else render(raw) end rescue nil end |
#find_constant_source(type) ⇒ Object
Returns { file: absolute_path, line: integer } for a class/module definition.
53 54 55 56 57 58 59 60 |
# File 'lib/pink_spoon/doc_extractor.rb', line 53 def find_constant_source(type) cache_key = "const_loc:#{type}" return @cache[cache_key] if @cache.key?(cache_key) @cache[cache_key] = find_constant_location(type) rescue nil end |
#find_ivar_in_type(type, ivar_name) ⇒ Object
Returns { file:, line: } for the first assignment of ivar_name (@foo = …) in any source file belonging to the given type’s gem or project.
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
# File 'lib/pink_spoon/doc_extractor.rb', line 21 def find_ivar_in_type(type, ivar_name) cache_key = "ivar:#{type}##{ivar_name}" return @cache[cache_key] if @cache.key?(cache_key) @cache[cache_key] = begin escaped = Regexp.escape(ivar_name) pattern = /#{escaped}\s*=/ hint = type.split("::").first.to_s.downcase gem_dirs_for(hint).each do |gem_dir| Dir.glob("#{gem_dir}/lib/**/*.rb").sort.each do |file| line = first_line_matching(file, pattern) return { file: file, line: line } if line end end %w[lib app spec test].each do |subdir| dir = File.join(@root_path, subdir) next unless File.directory?(dir) Dir.glob("#{dir}/**/*.rb").sort.each do |file| line = first_line_matching(file, pattern) return { file: file, line: line } if line end end nil end rescue nil end |
#find_source(type, method_name) ⇒ Object
Returns { file: absolute_path, line: integer } or nil.
103 104 105 106 107 108 109 110 |
# File 'lib/pink_spoon/doc_extractor.rb', line 103 def find_source(type, method_name) cache_key = "loc:#{type}##{method_name}" return @cache[cache_key] if @cache.key?(cache_key) @cache[cache_key] = find_location(type, method_name) rescue nil end |