Exception: Synthra::Errors::ParseError

Inherits:
Error
  • Object
show all
Defined in:
lib/synthra/errors.rb

Constant Summary collapse

ERROR_CODE =
"PARSE_ERROR"

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(message, line: nil, column: nil, source_line: nil, source_context: nil, suggestions: nil) ⇒ ParseError

Create a new ParseError with location information

Examples:

raise ParseError.new("Unexpected token", line: 5, column: 10, source_line: "  bad: ^invalid")

Parameters:

  • message (String)

    the error message describing the problem

  • line (Integer, nil) (defaults to: nil)

    line number where error occurred (1-based)

  • column (Integer, nil) (defaults to: nil)

    column number where error occurred (1-based)

  • source_line (String, nil) (defaults to: nil)

    the source line content for context

  • source_context (Array<String>, nil) (defaults to: nil)

    surrounding lines for context

  • suggestions (Array<String>, nil) (defaults to: nil)

    "did you mean" suggestions



142
143
144
145
146
147
148
149
150
151
# File 'lib/synthra/errors.rb', line 142

def initialize(message, line: nil, column: nil, source_line: nil, source_context: nil, suggestions: nil)
  @line = line
  @column = column
  @source_line = source_line
  @source_context = source_context
  @suggestions = suggestions

  full_message = build_message(message)
  super(full_message)
end

Instance Attribute Details

#columnObject (readonly)

Returns the value of attribute column.



126
127
128
# File 'lib/synthra/errors.rb', line 126

def column
  @column
end

#lineObject (readonly)

Returns the value of attribute line.



126
127
128
# File 'lib/synthra/errors.rb', line 126

def line
  @line
end

#source_contextObject (readonly)

Returns the value of attribute source_context.



126
127
128
# File 'lib/synthra/errors.rb', line 126

def source_context
  @source_context
end

#source_lineObject (readonly)

Returns the value of attribute source_line.



126
127
128
# File 'lib/synthra/errors.rb', line 126

def source_line
  @source_line
end

#suggestionsObject (readonly)

Returns the value of attribute suggestions.



126
127
128
# File 'lib/synthra/errors.rb', line 126

def suggestions
  @suggestions
end

Instance Method Details

#build_message(message) ⇒ String (private)

Build a formatted error message with location context

Creates a user-friendly error message that includes:

  • The base error message
  • Line and column numbers
  • Source context with line numbers and pointer
  • "Did you mean" suggestions

Parameters:

  • message (String)

    the base error message

Returns:

  • (String)

    the formatted message with location context



168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
# File 'lib/synthra/errors.rb', line 168

def build_message(message)
  parts = [message]
  parts << "at line #{line}" if line
  parts << "column #{column}" if column

  # Add source context if available
  if source_context&.any?
    parts << "\n\n#{format_source_context}"
  elsif source_line
    parts << "\n  #{source_line}"
    parts << "\n  #{" " * ([column.to_i - 1, 0].max)}^" if column
  end

  # Add suggestions if available
  if suggestions&.any?
    parts << "\n\n#{Utils::StringDistance.format_suggestions(suggestions)}"
  end

  parts.join(" ").strip
end

#format_source_contextString (private)

Format source context with line numbers

:nocov:

Returns:

  • (String)

    formatted source context



195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
# File 'lib/synthra/errors.rb', line 195

def format_source_context
  return "" unless source_context&.any?

  lines = []
  context_start_line = [line.to_i - source_context.length / 2, 1].max

  source_context.each_with_index do |content, idx|
    current_line = context_start_line + idx
    line_num = current_line.to_s.rjust(5)

    if current_line == line
      lines << "  > #{line_num} | #{content}"
      if column && column > 0
        pointer = " " * (10 + [column - 1, 0].max) + "^"
        lines << pointer
      end
    else
      lines << "    #{line_num} | #{content}"
    end
  end

  lines.join("\n")
end