Class: Ibex::Coverage::Collector
- Inherits:
-
Object
- Object
- Ibex::Coverage::Collector
- Defined in:
- lib/ibex/coverage/collector.rb,
sig/ibex/coverage/collector.rbs
Overview
Strictly turns one or more complete parse sessions into a coverage report.
Class Method Summary collapse
Instance Method Summary collapse
- #consume(document, source:, line:) ⇒ void
- #consume_session_event(event, data, sequence, source, line) ⇒ void
- #establish_metadata(metadata, source, line) ⇒ void
- #finish(source:) ⇒ Report
- #hit_production(id, source, line) ⇒ void
- #hit_state(id, source, line) ⇒ void
- #increment(hits, id, kind, source, line) ⇒ void
-
#initialize ⇒ Collector
constructor
A new instance of Collector.
- #invalid(source, line, message) ⇒ bot
- #required_metadata(value) ⇒ void
- #session_metadata(data, source, line) ⇒ [ [ String, Integer, Integer, Integer ], Integer ]
- #start_session(data, sequence, source, line) ⇒ void
- #valid_id?(id, total) ⇒ Boolean
- #validate_metadata!(source, line) ⇒ void
Constructor Details
#initialize ⇒ Collector
Returns a new instance of Collector.
20 21 22 23 24 25 26 27 28 29 30 31 |
# File 'lib/ibex/coverage/collector.rb', line 20 def initialize @grammar_digest = nil @table_format_version = nil @state_count = nil @production_count = nil @sessions = 0 @event_count = 0 @state_hits = Hash.new(0) @production_hits = Hash.new(0) @in_session = false @expected_sequence = 1 end |
Class Method Details
.collect_file(path) ⇒ Report
34 35 36 37 38 39 40 |
# File 'lib/ibex/coverage/collector.rb', line 34 def self.collect_file(path) collector = new EventStream.each_file(path) do |document, line| collector.consume(document, source: path, line: line) end collector.finish(source: path) end |
Instance Method Details
#consume(document, source:, line:) ⇒ void
This method returns an undefined value.
43 44 45 46 47 48 49 50 51 52 |
# File 'lib/ibex/coverage/collector.rb', line 43 def consume(document, source:, line:) event = document.fetch("event") sequence = document.fetch("sequence") if event == "start" start_session(document.fetch("data"), sequence, source, line) else consume_session_event(event, document.fetch("data"), sequence, source, line) end @event_count += 1 end |
#consume_session_event(event, data, sequence, source, line) ⇒ void
This method returns an undefined value.
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/ibex/coverage/collector.rb', line 89 def consume_session_event(event, data, sequence, source, line) invalid(source, line, "event appears outside a parse session") unless @in_session unless sequence == @expected_sequence invalid(source, line, "expected event sequence #{@expected_sequence}, got #{sequence.inspect}") end case event when "shift", "recover" then hit_state(data["state"], source, line) when "reduce" hit_production(data["production_id"], source, line) hit_state(data["goto_state"], source, line) end if %w[accept reject].include?(event) @in_session = false @expected_sequence = 1 else @expected_sequence += 1 end end |
#establish_metadata(metadata, source, line) ⇒ void
This method returns an undefined value.
125 126 127 128 129 130 131 132 133 |
# File 'lib/ibex/coverage/collector.rb', line 125 def (, source, line) unless @grammar_digest @grammar_digest, @table_format_version, @state_count, @production_count = return end expected = [@grammar_digest, @table_format_version, @state_count, @production_count] invalid(source, line, "parse sessions use different parser metadata") unless == expected end |
#finish(source:) ⇒ Report
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/ibex/coverage/collector.rb', line 55 def finish(source:) invalid(source, 1, "event stream ended before accept or reject") if @in_session invalid(source, 1, "event stream does not contain a parse session") if @sessions.zero? Report.new( grammar_digest: (@grammar_digest), table_format_version: (@table_format_version), state_count: (@state_count), production_count: (@production_count), sessions: @sessions, event_count: @event_count, state_hits: @state_hits, production_hits: @production_hits ) rescue ArgumentError => e raise Ibex::Error, "#{source}:1:1: #{e.}" end |
#hit_production(id, source, line) ⇒ void
This method returns an undefined value.
159 160 161 162 163 |
# File 'lib/ibex/coverage/collector.rb', line 159 def hit_production(id, source, line) total = (@production_count) invalid(source, line, "production id #{id.inspect} is outside 0...#{total}") unless valid_id?(id, total) increment(@production_hits, id, "production", source, line) end |
#hit_state(id, source, line) ⇒ void
This method returns an undefined value.
152 153 154 155 156 |
# File 'lib/ibex/coverage/collector.rb', line 152 def hit_state(id, source, line) total = (@state_count) invalid(source, line, "state id #{id.inspect} is outside 0...#{total}") unless valid_id?(id, total) increment(@state_hits, id, "state", source, line) end |
#increment(hits, id, kind, source, line) ⇒ void
This method returns an undefined value.
171 172 173 174 175 |
# File 'lib/ibex/coverage/collector.rb', line 171 def increment(hits, id, kind, source, line) count = hits[id] + 1 invalid(source, line, "#{kind} hit count exceeds the supported count") if count > Report::MAX_COUNT hits[id] = count end |
#invalid(source, line, message) ⇒ bot
183 184 185 |
# File 'lib/ibex/coverage/collector.rb', line 183 def invalid(source, line, ) raise Ibex::Error, "#{source}:#{line}:1: #{}" end |
#required_metadata(value) ⇒ void
This method returns an undefined value.
178 179 180 |
# File 'lib/ibex/coverage/collector.rb', line 178 def (value) value || raise(ArgumentError, "coverage metadata is unavailable") end |
#session_metadata(data, source, line) ⇒ [ [ String, Integer, Integer, Integer ], Integer ]
111 112 113 114 115 116 117 118 119 120 121 122 |
# File 'lib/ibex/coverage/collector.rb', line 111 def (data, source, line) digest = data["grammar_digest"] format = data["table_format_version"] states = data["state_count"] productions = data["production_count"] initial_state = data["initial_state"] unless digest.is_a?(String) && format.is_a?(Integer) && states.is_a?(Integer) && productions.is_a?(Integer) && initial_state.is_a?(Integer) invalid(source, line, "start event lacks generated parser coverage metadata") end [[digest, format, states, productions], initial_state] end |
#start_session(data, sequence, source, line) ⇒ void
This method returns an undefined value.
75 76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/ibex/coverage/collector.rb', line 75 def start_session(data, sequence, source, line) invalid(source, line, "new start event before prior session ended") if @in_session invalid(source, line, "start event sequence must be 1") unless sequence == 1 , initial_state = (data, source, line) (, source, line) (source, line) hit_state(initial_state, source, line) @sessions += 1 @in_session = true @expected_sequence = 2 end |
#valid_id?(id, total) ⇒ Boolean
166 167 168 |
# File 'lib/ibex/coverage/collector.rb', line 166 def valid_id?(id, total) id.is_a?(Integer) && id >= 0 && id < total end |
#validate_metadata!(source, line) ⇒ void
This method returns an undefined value.
136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
# File 'lib/ibex/coverage/collector.rb', line 136 def (source, line) Report.new( grammar_digest: (@grammar_digest), table_format_version: (@table_format_version), state_count: (@state_count), production_count: (@production_count), sessions: 1, event_count: 1, state_hits: {}, production_hits: {} ) rescue ArgumentError => e invalid(source, line, e.) end |