Module: Ibex::ErrorMessages

Defined in:
lib/ibex/error_messages.rb,
lib/ibex/error_messages/parser.rb,
lib/ibex/error_messages/update.rb,
lib/ibex/error_messages/renderer.rb,
lib/ibex/error_messages/parser_v2.rb,
lib/ibex/error_messages/sentence_search.rb,
sig/ibex/error_messages.rbs,
sig/ibex/error_messages/parser.rbs,
sig/ibex/error_messages/update.rbs,
sig/ibex/error_messages/renderer.rbs,
sig/ibex/error_messages/parser_v2.rbs,
sig/ibex/error_messages/sentence_search.rbs

Overview

Parses, validates, and deterministically updates example-keyed syntax error messages.

Defined Under Namespace

Modules: ParserV2 Classes: Document, Entry, Parser, SentenceSearch, Update

Constant Summary collapse

HEADER_V1 =

Returns:

  • (::String)
"# ibex-messages v1"
HEADER =

Returns:

  • (::String)
"# ibex-messages v2"

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.add_uncovered_entries(entries, covered, witnesses, uncovered, next_id) ⇒ Object

RBS:

  • (Array[Entry] entries, Hash[Integer, bool] covered, Hash[Integer, SentenceSearch::Witness] witnesses, Array[String] uncovered, Integer next_id) -> void



44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/ibex/error_messages/update.rb', line 44

def add_uncovered_entries(entries, covered, witnesses, uncovered, next_id)
  witnesses.each do |state, witness|
    next if covered[state]

    error_id = format_error_id(next_id)
    next_id += 1
    entries << Entry.new(
      state: state, status: :active, message: nil, line: 1,
      sentence: witness.tokens, error_id: error_id, entry: witness.entry
    )
    uncovered << "#{error_id} state #{state}: #{witness.tokens.join(' ')}"
  end
end

.append_entry(lines, automaton, entry) ⇒ Object

RBS:

  • (Array[String] lines, IR::Automaton automaton, Entry entry) -> void



18
19
20
21
22
23
24
25
26
27
# File 'lib/ibex/error_messages/renderer.rb', line 18

def append_entry(lines, automaton, entry)
  lines << entry_heading(entry)
  lines << "## #{entry.error_id}"
  lines << "# entry: #{entry.entry}" if entry.entry
  lines << "# state: #{entry.state}" if entry.state
  append_expected_tokens(lines, automaton, entry)
  lines << "# Add one or more `| ` lines to customize this error." unless entry.message
  entry.message&.split("\n", -1)&.each { |line| lines << "| #{encode_line(line)}" }
  lines.push("end", "")
end

.append_expected_tokens(lines, automaton, entry) ⇒ Object

RBS:

  • (Array[String] lines, IR::Automaton automaton, Entry entry) -> void



38
39
40
41
42
43
# File 'lib/ibex/error_messages/renderer.rb', line 38

def append_expected_tokens(lines, automaton, entry)
  return unless entry.status == :active && entry.state

  expected = expected_tokens(automaton, automaton.states.fetch(entry.state))
  lines << "# expected: #{expected.empty? ? '(none)' : expected.join(', ')}"
end

.encode_line(line) ⇒ Object

RBS:

  • (String line) -> String



46
47
48
# File 'lib/ibex/error_messages/renderer.rb', line 46

def encode_line(line)
  line.gsub("\\", "\\\\").gsub("\t", "\\t").gsub("\r", "\\r")
end

.entry_heading(entry) ⇒ Object

RBS:

  • (Entry entry) -> String



30
31
32
33
34
35
# File 'lib/ibex/error_messages/renderer.rb', line 30

def entry_heading(entry)
  return "legacy-state: #{entry.state}" unless entry.sentence

  prefix = entry.status == :active ? "sentence" : "unreachable"
  "#{prefix}: #{entry.sentence.join(' ')}"
end

.entry_sort_key(entry) ⇒ Object

RBS:

  • (Entry entry) -> [Integer, Integer, String]



156
157
158
159
# File 'lib/ibex/error_messages/update.rb', line 156

def entry_sort_key(entry)
  rank = { active: 0, unreachable: 1, removed: 2 }.fetch(entry.status)
  [rank, entry.state || (1 << 62), entry.error_id || ""]
end

.error_action?(action) ⇒ Boolean

RBS:

  • (IR::parser_action? action) -> bool

Returns:

  • (Boolean)


149
150
151
# File 'lib/ibex/error_messages.rb', line 149

def error_action?(action)
  action.nil? || action[:type].to_sym == :error
end

.error_states(automaton) ⇒ Object

RBS:

  • (IR::Automaton automaton) -> Array[IR::AutomatonState]



83
84
85
86
87
88
# File 'lib/ibex/error_messages.rb', line 83

def error_states(automaton)
  terminals = ordinary_terminals(automaton)
  automaton.states.select do |state|
    terminals.any? { |terminal| error_action?(state.actions[terminal.id] || state.default_action) }
  end.sort_by(&:id)
end

.expected_tokens(automaton, state) ⇒ Object

RBS:

  • (IR::Automaton automaton, IR::AutomatonState state) -> Array[String]



51
52
53
54
55
56
# File 'lib/ibex/error_messages/renderer.rb', line 51

def expected_tokens(automaton, state)
  ordinary_terminals(automaton).filter_map do |terminal|
    action = state.actions[terminal.id] || state.default_action
    terminal.display_name || terminal.name unless error_action?(action)
  end
end

.fail_at(file, line, column, message) ⇒ Object

RBS:

  • (String file, Integer line, Integer column, String message) -> bot

Raises:



154
155
156
# File 'lib/ibex/error_messages.rb', line 154

def fail_at(file, line, column, message)
  raise Ibex::Error, "#{file}:#{line}:#{column}: #{message}"
end

.format_error_id(number) ⇒ Object

RBS:

  • (Integer number) -> String



151
152
153
# File 'lib/ibex/error_messages/update.rb', line 151

def format_error_id(number)
  format("E%04d", number)
end

.legacy_records_for(document, automaton, file:) ⇒ Object

RBS:

  • (Document document, IR::Automaton automaton, file: String) -> Hash[Integer, { id: String, message: String }]



127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# File 'lib/ibex/error_messages.rb', line 127

def legacy_records_for(document, automaton, file:)
  valid = error_states(automaton).to_h { |state| [state.id, true] }
  records = {} #: Hash[Integer, { id: String, message: String }]
  document.entries.each do |entry|
    next if entry.status == :removed || !entry.message

    state = entry.state || raise(Ibex::Error, "missing legacy error state")
    unless valid[state]
      fail_at(file, entry.line, 1,
              "unknown error state #{state} for current automaton; run `ibex errors --update`")
    end
    records[state] = { id: format_error_id(state + 1), message: entry.message }
  end
  records.sort.to_h.freeze
end

.load(path) ⇒ Object

RBS:

  • (String path) -> Document



77
78
79
# File 'lib/ibex/error_messages.rb', line 77

def load(path)
  parse(File.binread(path), file: path)
end

.messages_for(document, automaton, file:) ⇒ Object

RBS:

  • (Document document, IR::Automaton automaton, file: String) -> Hash[Integer, String]



92
93
94
# File 'lib/ibex/error_messages.rb', line 92

def messages_for(document, automaton, file:)
  records_for(document, automaton, file: file).transform_values { |record| record.fetch(:message) }.freeze
end

.migrate_legacy_entries(document, witnesses, classifications, next_id) ⇒ Object

RBS:

  • (Document document, Hash[Integer, SentenceSearch::Witness] witnesses, Hash[Symbol, Array[String]] classifications, Integer next_id) -> [Array[Entry], Hash[Integer, bool], Integer]



107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/ibex/error_messages/update.rb', line 107

def migrate_legacy_entries(document, witnesses, classifications, next_id)
  by_state = document.entries.to_h { |entry| [entry.state, entry] }
  entries = [] #: Array[Entry]
  covered = {} #: Hash[Integer, bool]
  witnesses.each do |state, witness|
    previous = by_state.delete(state)
    error_id = format_error_id(next_id)
    next_id += 1
    entries << Entry.new(
      state: state, status: :active, message: previous&.message, line: previous&.line || 1,
      sentence: witness.tokens, error_id: error_id, entry: witness.entry
    )
    covered[state] = true
    classifications[:uncovered] << "#{error_id} state #{state}: #{witness.tokens.join(' ')}" unless previous
  end
  by_state.values.sort_by { |entry| entry.state || -1 }.each do |entry|
    error_id = format_error_id(next_id)
    next_id += 1
    entries << Entry.new(
      state: entry.state, status: :removed, message: entry.message, line: entry.line, error_id: error_id
    )
    classifications[:unreachable] << "#{error_id}: legacy state #{entry.state}"
  end
  [entries, covered, next_id]
end

.next_error_id(document) ⇒ Object

RBS:

  • (Document document) -> Integer



142
143
144
145
146
147
148
# File 'lib/ibex/error_messages/update.rb', line 142

def next_error_id(document)
  maximum = document.entries.filter_map do |entry|
    match = entry.error_id&.match(/\AE([0-9]{4,})\z/)
    match && Integer(match[1] || "0", 10)
  end.max
  (maximum || 0) + 1
end

.ordinary_terminals(automaton) ⇒ Object

RBS:

  • (IR::Automaton automaton) -> Array[IR::GrammarSymbol]



144
145
146
# File 'lib/ibex/error_messages.rb', line 144

def ordinary_terminals(automaton)
  automaton.grammar.terminals.reject { |terminal| terminal.name == "error" }
end

.parse(source, file:) ⇒ Object

RBS:

  • (String source, file: String) -> Document



71
72
73
# File 'lib/ibex/error_messages.rb', line 71

def parse(source, file:)
  Parser.new(source, file: file).parse
end

.records_for(document, automaton, file:) ⇒ Object

RBS:

  • (Document document, IR::Automaton automaton, file: String) -> Hash[Integer, { id: String, message: String }]



99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/ibex/error_messages.rb', line 99

def records_for(document, automaton, file:)
  return legacy_records_for(document, automaton, file: file) if document.version == 1

  search = SentenceSearch.new(automaton)
  records = {} #: Hash[Integer, { id: String, message: String }]
  document.entries.each do |entry|
    next unless entry.status == :active && entry.message

    sentence = entry.sentence || raise(Ibex::Error, "missing active error sentence")
    state = search.state_for(sentence, entry: entry.entry)
    unless state
      fail_at(file, entry.line, 1,
              "error sentence no longer reaches a syntax error; run `ibex errors --update`")
    end
    if records[state]
      fail_at(file, entry.line, 1,
              "multiple messages reach error state #{state}; run `ibex errors --update`")
    end

    error_id = entry.error_id || raise(Ibex::Error, "missing error id")
    records[state] = { id: error_id, message: entry.message }
  end
  records.sort.to_h.freeze
end

.render(automaton, existing: nil, max_tokens: SentenceSearch::DEFAULT_MAX_TOKENS, max_configurations: SentenceSearch::DEFAULT_MAX_CONFIGURATIONS) ⇒ Object

RBS:

  • (IR::Automaton automaton, ?existing: Document?, ?max_tokens: Integer, ?max_configurations: Integer) -> String



9
10
11
12
13
14
# File 'lib/ibex/error_messages/update.rb', line 9

def render(automaton, existing: nil, max_tokens: SentenceSearch::DEFAULT_MAX_TOKENS,
           max_configurations: SentenceSearch::DEFAULT_MAX_CONFIGURATIONS)
  update(
    automaton, existing: existing, max_tokens: max_tokens, max_configurations: max_configurations
  ).source
end

.render_entries(automaton, entries) ⇒ Object

RBS:

  • (IR::Automaton automaton, Array[Entry] entries) -> String



6
7
8
9
10
11
12
13
14
15
# File 'lib/ibex/error_messages/renderer.rb', line 6

def render_entries(automaton, entries)
  lines = [
    HEADER,
    "# Generated by `ibex errors --update`; sentences and IDs are stable review keys.",
    "# Edit only `| ` message lines.",
    ""
  ]
  entries.each { |entry| append_entry(lines, automaton, entry) }
  "#{lines.join("\n").rstrip}\n"
end

.update(automaton, existing: nil, max_tokens: SentenceSearch::DEFAULT_MAX_TOKENS, max_configurations: SentenceSearch::DEFAULT_MAX_CONFIGURATIONS) ⇒ Object

RBS:

  • (IR::Automaton automaton, ?existing: Document?, ?max_tokens: Integer, ?max_configurations: Integer) -> Update



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/ibex/error_messages/update.rb', line 19

def update(automaton, existing: nil, max_tokens: SentenceSearch::DEFAULT_MAX_TOKENS,
           max_configurations: SentenceSearch::DEFAULT_MAX_CONFIGURATIONS)
  document = existing || Document.new(entries: [])
  search = SentenceSearch.new(
    automaton, max_tokens: max_tokens, max_configurations: max_configurations
  )
  witnesses = search.all
  classifications = { uncovered: [], unreachable: [], moved: [] } #: Hash[Symbol, Array[String]]
  next_id = next_error_id(document)
  entries, covered, next_id = update_existing_entries(
    document, search, witnesses, classifications, next_id
  )
  add_uncovered_entries(entries, covered, witnesses, classifications[:uncovered], next_id)
  entries.sort_by! { |entry| entry_sort_key(entry) }
  Update.new(
    source: render_entries(automaton, entries),
    uncovered: classifications[:uncovered],
    unreachable: classifications[:unreachable],
    moved: classifications[:moved]
  )
end

.update_existing_entries(document, search, witnesses, classifications, next_id) ⇒ Object

RBS:

  • (Document document, SentenceSearch search, Hash[Integer, SentenceSearch::Witness] witnesses, Hash[Symbol, Array[String]] classifications, Integer next_id) -> [Array[Entry], Hash[Integer, bool], Integer]



61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/ibex/error_messages/update.rb', line 61

def update_existing_entries(document, search, witnesses, classifications, next_id)
  return migrate_legacy_entries(document, witnesses, classifications, next_id) if document.version == 1

  entries = [] #: Array[Entry]
  covered = {} #: Hash[Integer, bool]
  document.entries.each do |entry|
    if entry.sentence
      next_id = update_sentence_entry(
        entry, search, entries, covered, classifications, next_id
      )
    else
      entries << with_error_id(entry, next_id)
      next_id += 1 unless entry.error_id
    end
  end
  [entries, covered, next_id]
end

.update_sentence_entry(entry, search, entries, covered, classifications, next_id) ⇒ Object

RBS:

  • (Entry entry, SentenceSearch search, Array[Entry] entries, Hash[Integer, bool] covered, Hash[Symbol, Array[String]] classifications, Integer next_id) -> Integer



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/ibex/error_messages/update.rb', line 81

def update_sentence_entry(entry, search, entries, covered, classifications, next_id)
  error_id = entry.error_id || format_error_id(next_id)
  next_id += 1 unless entry.error_id
  sentence = entry.sentence || raise(Ibex::Error, "missing error sentence")
  state = search.state_for(sentence, entry: entry.entry)
  unless state
    entries << Entry.new(
      state: entry.state, status: :unreachable, message: entry.message, line: entry.line,
      sentence: sentence, error_id: error_id, entry: entry.entry
    )
    classifications[:unreachable] << "#{error_id}: #{sentence.join(' ')}"
    return next_id
  end

  classifications[:moved] << "#{error_id}: state #{entry.state} -> #{state}" if entry.state && entry.state != state
  covered[state] = true
  entries << Entry.new(
    state: state, status: :active, message: entry.message, line: entry.line,
    sentence: sentence, error_id: error_id, entry: entry.entry
  )
  next_id
end

.with_error_id(entry, next_id) ⇒ Object

RBS:

  • (Entry entry, Integer next_id) -> Entry



134
135
136
137
138
139
# File 'lib/ibex/error_messages/update.rb', line 134

def with_error_id(entry, next_id)
  Entry.new(
    state: entry.state, status: entry.status, message: entry.message, line: entry.line,
    sentence: entry.sentence, error_id: entry.error_id || format_error_id(next_id), entry: entry.entry
  )
end

Instance Method Details

#append_entry(lines, automaton, entry) ⇒ void

This method returns an undefined value.

RBS:

  • (Array[String] lines, IR::Automaton automaton, Entry entry) -> void

Parameters:



18
19
20
21
22
23
24
25
26
27
# File 'lib/ibex/error_messages/renderer.rb', line 18

def append_entry(lines, automaton, entry)
  lines << entry_heading(entry)
  lines << "## #{entry.error_id}"
  lines << "# entry: #{entry.entry}" if entry.entry
  lines << "# state: #{entry.state}" if entry.state
  append_expected_tokens(lines, automaton, entry)
  lines << "# Add one or more `| ` lines to customize this error." unless entry.message
  entry.message&.split("\n", -1)&.each { |line| lines << "| #{encode_line(line)}" }
  lines.push("end", "")
end

#append_expected_tokens(lines, automaton, entry) ⇒ void

This method returns an undefined value.

RBS:

  • (Array[String] lines, IR::Automaton automaton, Entry entry) -> void

Parameters:



38
39
40
41
42
43
# File 'lib/ibex/error_messages/renderer.rb', line 38

def append_expected_tokens(lines, automaton, entry)
  return unless entry.status == :active && entry.state

  expected = expected_tokens(automaton, automaton.states.fetch(entry.state))
  lines << "# expected: #{expected.empty? ? '(none)' : expected.join(', ')}"
end

#encode_line(line) ⇒ String

RBS:

  • (String line) -> String

Parameters:

  • line (String)

Returns:

  • (String)


46
47
48
# File 'lib/ibex/error_messages/renderer.rb', line 46

def encode_line(line)
  line.gsub("\\", "\\\\").gsub("\t", "\\t").gsub("\r", "\\r")
end

#entry_heading(entry) ⇒ String

RBS:

  • (Entry entry) -> String

Parameters:

Returns:

  • (String)


30
31
32
33
34
35
# File 'lib/ibex/error_messages/renderer.rb', line 30

def entry_heading(entry)
  return "legacy-state: #{entry.state}" unless entry.sentence

  prefix = entry.status == :active ? "sentence" : "unreachable"
  "#{prefix}: #{entry.sentence.join(' ')}"
end

#entry_sort_key(entry) ⇒ [ Integer, Integer, String ]

RBS:

  • (Entry entry) -> [Integer, Integer, String]

Parameters:

Returns:

  • ([ Integer, Integer, String ])


156
157
158
159
# File 'lib/ibex/error_messages/update.rb', line 156

def entry_sort_key(entry)
  rank = { active: 0, unreachable: 1, removed: 2 }.fetch(entry.status)
  [rank, entry.state || (1 << 62), entry.error_id || ""]
end

#error_action?(action) ⇒ Boolean

RBS:

  • (IR::parser_action? action) -> bool

Parameters:

  • action (IR::parser_action, nil)

Returns:

  • (Boolean)


149
150
151
# File 'lib/ibex/error_messages.rb', line 149

def error_action?(action)
  action.nil? || action[:type].to_sym == :error
end

#expected_tokens(automaton, state) ⇒ Array[String]

RBS:

  • (IR::Automaton automaton, IR::AutomatonState state) -> Array[String]

Parameters:

Returns:

  • (Array[String])


51
52
53
54
55
56
# File 'lib/ibex/error_messages/renderer.rb', line 51

def expected_tokens(automaton, state)
  ordinary_terminals(automaton).filter_map do |terminal|
    action = state.actions[terminal.id] || state.default_action
    terminal.display_name || terminal.name unless error_action?(action)
  end
end

#fail_at(file, line, column, message) ⇒ bot

RBS:

  • (String file, Integer line, Integer column, String message) -> bot

Parameters:

  • file (String)
  • line (Integer)
  • column (Integer)
  • message (String)

Returns:

  • (bot)


154
155
156
# File 'lib/ibex/error_messages.rb', line 154

def fail_at(file, line, column, message)
  raise Ibex::Error, "#{file}:#{line}:#{column}: #{message}"
end

#format_error_id(number) ⇒ String

RBS:

  • (Integer number) -> String

Parameters:

  • number (Integer)

Returns:

  • (String)


151
152
153
# File 'lib/ibex/error_messages/update.rb', line 151

def format_error_id(number)
  format("E%04d", number)
end

#migrate_legacy_entries(document, witnesses, classifications, next_id) ⇒ [ Array[Entry], Hash[Integer, bool], Integer ]

RBS:

  • (Document document, Hash[Integer, SentenceSearch::Witness] witnesses, Hash[Symbol, Array[String]] classifications, Integer next_id) -> [Array[Entry], Hash[Integer, bool], Integer]

Parameters:

Returns:

  • ([ Array[Entry], Hash[Integer, bool], Integer ])


107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/ibex/error_messages/update.rb', line 107

def migrate_legacy_entries(document, witnesses, classifications, next_id)
  by_state = document.entries.to_h { |entry| [entry.state, entry] }
  entries = [] #: Array[Entry]
  covered = {} #: Hash[Integer, bool]
  witnesses.each do |state, witness|
    previous = by_state.delete(state)
    error_id = format_error_id(next_id)
    next_id += 1
    entries << Entry.new(
      state: state, status: :active, message: previous&.message, line: previous&.line || 1,
      sentence: witness.tokens, error_id: error_id, entry: witness.entry
    )
    covered[state] = true
    classifications[:uncovered] << "#{error_id} state #{state}: #{witness.tokens.join(' ')}" unless previous
  end
  by_state.values.sort_by { |entry| entry.state || -1 }.each do |entry|
    error_id = format_error_id(next_id)
    next_id += 1
    entries << Entry.new(
      state: entry.state, status: :removed, message: entry.message, line: entry.line, error_id: error_id
    )
    classifications[:unreachable] << "#{error_id}: legacy state #{entry.state}"
  end
  [entries, covered, next_id]
end

#next_error_id(document) ⇒ Integer

RBS:

  • (Document document) -> Integer

Parameters:

Returns:

  • (Integer)


142
143
144
145
146
147
148
# File 'lib/ibex/error_messages/update.rb', line 142

def next_error_id(document)
  maximum = document.entries.filter_map do |entry|
    match = entry.error_id&.match(/\AE([0-9]{4,})\z/)
    match && Integer(match[1] || "0", 10)
  end.max
  (maximum || 0) + 1
end

#ordinary_terminals(automaton) ⇒ Array[IR::GrammarSymbol]

RBS:

  • (IR::Automaton automaton) -> Array[IR::GrammarSymbol]

Parameters:

Returns:



144
145
146
# File 'lib/ibex/error_messages.rb', line 144

def ordinary_terminals(automaton)
  automaton.grammar.terminals.reject { |terminal| terminal.name == "error" }
end

#self?.add_uncovered_entriesvoid

This method returns an undefined value.

RBS:

  • (Array[Entry] entries, Hash[Integer, bool] covered, Hash[Integer, SentenceSearch::Witness] witnesses, Array[String] uncovered, Integer next_id) -> void

Parameters:

  • entries (Array[Entry])
  • covered (Hash[Integer, bool])
  • witnesses (Hash[Integer, SentenceSearch::Witness])
  • uncovered (Array[String])
  • next_id (Integer)


15
# File 'sig/ibex/error_messages/update.rbs', line 15

def self?.add_uncovered_entries: (Array[Entry] entries, Hash[Integer, bool] covered, Hash[Integer, SentenceSearch::Witness] witnesses, Array[String] uncovered, Integer next_id) -> void

#self?.error_statesArray[IR::AutomatonState]

RBS:

  • (IR::Automaton automaton) -> Array[IR::AutomatonState]

Parameters:

Returns:



63
# File 'sig/ibex/error_messages.rbs', line 63

def self?.error_states: (IR::Automaton automaton) -> Array[IR::AutomatonState]

#self?.legacy_records_forHash[Integer, { id: String, message: String }]

RBS:

  • (Document document, IR::Automaton automaton, file: String) -> Hash[Integer, { id: String, message: String }]

Parameters:

Returns:

  • (Hash[Integer, { id: String, message: String }])


74
# File 'sig/ibex/error_messages.rbs', line 74

def self?.legacy_records_for: (Document document, IR::Automaton automaton, file: String) -> Hash[Integer, { id: String, message: String }]

#self?.loadDocument

RBS:

  • (String path) -> Document

Parameters:

  • path (String)

Returns:



60
# File 'sig/ibex/error_messages.rbs', line 60

def self?.load: (String path) -> Document

#self?.messages_forHash[Integer, String]

RBS:

  • (Document document, IR::Automaton automaton, file: String) -> Hash[Integer, String]

Parameters:

Returns:

  • (Hash[Integer, String])


66
# File 'sig/ibex/error_messages.rbs', line 66

def self?.messages_for: (Document document, IR::Automaton automaton, file: String) -> Hash[Integer, String]

#self?.parseDocument

RBS:

  • (String source, file: String) -> Document

Parameters:

  • source (String)
  • file: (String)

Returns:



57
# File 'sig/ibex/error_messages.rbs', line 57

def self?.parse: (String source, file: String) -> Document

#self?.records_forHash[Integer, { id: String, message: String }]

RBS:

  • (Document document, IR::Automaton automaton, file: String) -> Hash[Integer, { id: String, message: String }]

Parameters:

Returns:

  • (Hash[Integer, { id: String, message: String }])


70
# File 'sig/ibex/error_messages.rbs', line 70

def self?.records_for: (Document document, IR::Automaton automaton, file: String) -> Hash[Integer, { id: String, message: String }]

#self?.renderString

RBS:

  • (IR::Automaton automaton, ?existing: Document?, ?max_tokens: Integer, ?max_configurations: Integer) -> String

Parameters:

  • automaton (IR::Automaton)
  • existing: (Document, nil)
  • max_tokens: (Integer)
  • max_configurations: (Integer)

Returns:

  • (String)


7
# File 'sig/ibex/error_messages/update.rbs', line 7

def self?.render: (IR::Automaton automaton, ?existing: Document?, ?max_tokens: Integer, ?max_configurations: Integer) -> String

#self?.render_entriesString

RBS:

  • (IR::Automaton automaton, Array[Entry] entries) -> String

Parameters:

Returns:

  • (String)


6
# File 'sig/ibex/error_messages/renderer.rbs', line 6

def self?.render_entries: (IR::Automaton automaton, Array[Entry] entries) -> String

#self?.updateUpdate

RBS:

  • (IR::Automaton automaton, ?existing: Document?, ?max_tokens: Integer, ?max_configurations: Integer) -> Update

Parameters:

  • automaton (IR::Automaton)
  • existing: (Document, nil)
  • max_tokens: (Integer)
  • max_configurations: (Integer)

Returns:



11
# File 'sig/ibex/error_messages/update.rbs', line 11

def self?.update: (IR::Automaton automaton, ?existing: Document?, ?max_tokens: Integer, ?max_configurations: Integer) -> Update

#update_existing_entries(document, search, witnesses, classifications, next_id) ⇒ [ Array[Entry], Hash[Integer, bool], Integer ]

RBS:

  • (Document document, SentenceSearch search, Hash[Integer, SentenceSearch::Witness] witnesses, Hash[Symbol, Array[String]] classifications, Integer next_id) -> [Array[Entry], Hash[Integer, bool], Integer]

Parameters:

Returns:

  • ([ Array[Entry], Hash[Integer, bool], Integer ])


61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/ibex/error_messages/update.rb', line 61

def update_existing_entries(document, search, witnesses, classifications, next_id)
  return migrate_legacy_entries(document, witnesses, classifications, next_id) if document.version == 1

  entries = [] #: Array[Entry]
  covered = {} #: Hash[Integer, bool]
  document.entries.each do |entry|
    if entry.sentence
      next_id = update_sentence_entry(
        entry, search, entries, covered, classifications, next_id
      )
    else
      entries << with_error_id(entry, next_id)
      next_id += 1 unless entry.error_id
    end
  end
  [entries, covered, next_id]
end

#update_sentence_entry(entry, search, entries, covered, classifications, next_id) ⇒ Integer

RBS:

  • (Entry entry, SentenceSearch search, Array[Entry] entries, Hash[Integer, bool] covered, Hash[Symbol, Array[String]] classifications, Integer next_id) -> Integer

Parameters:

  • entry (Entry)
  • search (SentenceSearch)
  • entries (Array[Entry])
  • covered (Hash[Integer, bool])
  • classifications (Hash[Symbol, Array[String]])
  • next_id (Integer)

Returns:

  • (Integer)


81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/ibex/error_messages/update.rb', line 81

def update_sentence_entry(entry, search, entries, covered, classifications, next_id)
  error_id = entry.error_id || format_error_id(next_id)
  next_id += 1 unless entry.error_id
  sentence = entry.sentence || raise(Ibex::Error, "missing error sentence")
  state = search.state_for(sentence, entry: entry.entry)
  unless state
    entries << Entry.new(
      state: entry.state, status: :unreachable, message: entry.message, line: entry.line,
      sentence: sentence, error_id: error_id, entry: entry.entry
    )
    classifications[:unreachable] << "#{error_id}: #{sentence.join(' ')}"
    return next_id
  end

  classifications[:moved] << "#{error_id}: state #{entry.state} -> #{state}" if entry.state && entry.state != state
  covered[state] = true
  entries << Entry.new(
    state: state, status: :active, message: entry.message, line: entry.line,
    sentence: sentence, error_id: error_id, entry: entry.entry
  )
  next_id
end

#with_error_id(entry, next_id) ⇒ Entry

RBS:

  • (Entry entry, Integer next_id) -> Entry

Parameters:

  • entry (Entry)
  • next_id (Integer)

Returns:



134
135
136
137
138
139
# File 'lib/ibex/error_messages/update.rb', line 134

def with_error_id(entry, next_id)
  Entry.new(
    state: entry.state, status: entry.status, message: entry.message, line: entry.line,
    sentence: entry.sentence, error_id: entry.error_id || format_error_id(next_id), entry: entry.entry
  )
end