Class: Ibex::Frontend::RuleDocumentation
- Inherits:
-
Object
- Object
- Ibex::Frontend::RuleDocumentation
- Defined in:
- lib/ibex/frontend/rule_documentation.rb,
sig/ibex/frontend/rule_documentation.rbs
Overview
Attaches immediately preceding lossless line-comment blocks to parsed rules.
Constant Summary collapse
- EMPTY_SEGMENTS =
Array.new(0).freeze
Class Method Summary collapse
Instance Method Summary collapse
- #covered_lines(segment) ⇒ Array[Integer]
- #documentation_anchor(rule) ⇒ Integer
- #documentation_before(rule_line) ⇒ String?
- #documentation_line(line) ⇒ String?
- #documentation_line_segment?(segment, comment) ⇒ Boolean
- #documented_rule(rule) ⇒ AST::Rule
- #enrich(node) ⇒ AST::Root, AST::Fragment
- #index_segments(document) ⇒ Hash[Integer, Array[Segment]]
-
#initialize(document) ⇒ RuleDocumentation
constructor
A new instance of RuleDocumentation.
Constructor Details
#initialize(document) ⇒ RuleDocumentation
Returns a new instance of RuleDocumentation.
16 17 18 19 20 21 |
# File 'lib/ibex/frontend/rule_documentation.rb', line 16 def initialize(document) @segments_by_line = index_segments(document) #: Hash[Integer, Array[Segment]] @inline_lines = document.tokens.filter_map do |token| token.location.line if token.type == :inline end #: Array[Integer] end |
Class Method Details
.enrich(node, document) ⇒ AST::Root, AST::Fragment
11 12 13 |
# File 'lib/ibex/frontend/rule_documentation.rb', line 11 def self.enrich(node, document) new(document).enrich(node) end |
Instance Method Details
#covered_lines(segment) ⇒ Array[Integer]
95 96 97 98 99 100 |
# File 'lib/ibex/frontend/rule_documentation.rb', line 95 def covered_lines(segment) first = segment.span.start.line return [first] if segment.kind == :newline (first..segment.span.finish.line).to_a end |
#documentation_anchor(rule) ⇒ Integer
47 48 49 50 51 |
# File 'lib/ibex/frontend/rule_documentation.rb', line 47 def documentation_anchor(rule) return rule.loc.line unless rule.inline @inline_lines.reverse_each.find { |line| line <= rule.loc.line } || rule.loc.line end |
#documentation_before(rule_line) ⇒ String?
54 55 56 57 58 59 60 61 62 63 64 65 |
# File 'lib/ibex/frontend/rule_documentation.rb', line 54 def documentation_before(rule_line) lines = [] #: Array[String] line = rule_line - 1 while line.positive? content = documentation_line(line) break unless content lines.unshift(content) line -= 1 end lines.empty? ? nil : lines.join("\n").freeze end |
#documentation_line(line) ⇒ String?
68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/ibex/frontend/rule_documentation.rb', line 68 def documentation_line(line) segments = @segments_by_line.fetch(line, EMPTY_SEGMENTS) comments = segments.select { |segment| segment.kind == :line_comment } return unless comments.length == 1 comment = comments.fetch(0) return unless comment.text.start_with?("##") return unless segments.all? { |segment| documentation_line_segment?(segment, comment) } comment.text.delete_prefix("##").delete_prefix(" ") end |
#documentation_line_segment?(segment, comment) ⇒ Boolean
81 82 83 |
# File 'lib/ibex/frontend/rule_documentation.rb', line 81 def documentation_line_segment?(segment, comment) segment.equal?(comment) || %i[whitespace newline].include?(segment.kind) end |
#documented_rule(rule) ⇒ AST::Rule
39 40 41 42 43 44 |
# File 'lib/ibex/frontend/rule_documentation.rb', line 39 def documented_rule(rule) AST::Rule.new( lhs: rule.lhs, parameters: rule.parameters, alternatives: rule.alternatives, loc: rule.loc, documentation: documentation_before(documentation_anchor(rule)), inline: rule.inline ) end |
#enrich(node) ⇒ AST::Root, AST::Fragment
24 25 26 27 28 29 30 31 32 33 34 |
# File 'lib/ibex/frontend/rule_documentation.rb', line 24 def enrich(node) rules = node.rules.map { |rule| documented_rule(rule) } if node.is_a?(AST::Root) AST::Root.new( class_name: node.class_name, superclass: node.superclass, declarations: node.declarations, rules: rules, user_code: node.user_code, loc: node.loc, extended: node.extended, cst: node.cst ) else AST::Fragment.new(declarations: node.declarations, rules: rules, loc: node.loc) end end |
#index_segments(document) ⇒ Hash[Integer, Array[Segment]]
86 87 88 89 90 91 92 |
# File 'lib/ibex/frontend/rule_documentation.rb', line 86 def index_segments(document) indexed = Hash.new { |hash, line| hash[line] = [] } #: Hash[Integer, Array[Segment]] document.cst.each do |segment| covered_lines(segment).each { |line| indexed[line] << segment } end indexed end |