Class: FiberAudit::Suppressions::Parser

Inherits:
Object
  • Object
show all
Defined in:
lib/fiber_audit/suppressions/parser.rb

Class Method Summary collapse

Class Method Details

.parse_inline(path, content) ⇒ Object

Parses inline suppressions from a file's content using Prism for comment detection. Directives are recognized ONLY from actual Prism comments - never from raw text scans. This ensures directive text in strings, heredocs, and regex literals cannot start or end suppressions.



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
51
52
53
54
55
56
57
58
# File 'lib/fiber_audit/suppressions/parser.rb', line 22

def parse_inline(path, content)
  result = Prism.parse(content)
  return [] if result.errors.any?

  lines = content.lines
  disables = []
  enables = []

  # Only examine actual comments from Prism
  result.comments.each do |comment|
    text = comment.location.slice
    line_num = comment.location.start_line

    if (match = text.match(
      /fiber-audit:disable\s+(FA\d+)/
    ))
      rule_id = match[1]
      reason = extract_reason(text, path, line_num)
      is_block = block_comment?(comment, lines)
      disables << {
        rule_id: rule_id,
        reason: reason,
        line: line_num,
        block: is_block
      }
    elsif (match = text.match(
      /fiber-audit:enable\s+(FA\d+)/
    ))
      enables << {
        rule_id: match[1],
        line: line_num
      }
    end
  end

  build_suppressions(disables, enables, lines, path)
end

.parse_yaml(path) ⇒ Object

Parse YAML suppressions file



61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/fiber_audit/suppressions/parser.rb', line 61

def parse_yaml(path)
  return [] unless path && File.exist?(path)

  yaml = YAML.safe_load_file(path) || {}
  raw_suppressions = yaml['suppressions'] || []

  raw_suppressions.map do |entry|
    rule = entry['rule']
    reason = entry['reason']

    if reason.nil? || reason.strip.empty?
      raise FiberAudit::ConfigurationError,
            "YAML suppression for rule #{rule} at #{path} " \
            "missing 'reason'"
    end

    YamlSuppression.new(
      rule: rule,
      symbol: entry['symbol'],
      operation: entry['operation'],
      reason: reason.strip
    )
  end
end