class RubyLsp::ERBDocument

: [ParseResultType = Prism::ParseLexResult]

def ast

: -> Prism::ProgramNode
def ast
  @parse_result.value.first
end

def initialize(source:, version:, uri:, global_state:)

: (source: String, version: Integer, uri: URI::Generic, global_state: GlobalState) -> void
def initialize(source:, version:, uri:, global_state:)
  # This has to be initialized before calling super because we call `parse` in the parent constructor, which
  # overrides this with the proper virtual host language source
  @host_language_source = "" #: String
  super
  @code_units_cache =
    @parse_result.code_units_cache(@encoding) #: (^(Integer arg0) -> Integer | Prism::CodeUnitsCache)
end

def inside_host_language?(char_position)

: (Integer char_position) -> bool?
def inside_host_language?(char_position)
  char = @host_language_source[char_position]
  char && char != " "
end

def language_id

: -> Symbol
@override
def language_id
  :erb
end

def locate_node(position, node_types: [])

: (Hash[Symbol, untyped] position, ?node_types: Array[singleton(Prism::Node)]) -> NodeContext
def locate_node(position, node_types: [])
  char_position, _ = find_index_by_position(position)
  RubyDocument.locate(
    ast,
    char_position,
    code_units_cache: @code_units_cache,
    node_types: node_types,
  )
end

def parse!

: -> bool
@override
def parse!
  return false unless @needs_parsing
  @needs_parsing = false
  scanner = ERBScanner.new(@source)
  scanner.scan
  @host_language_source = scanner.host_language
  # Use partial script to avoid syntax errors in ERB files where keywords may be used without the full context in
  # which they will be evaluated
  @parse_result = Prism.parse_lex(scanner.ruby, partial_script: true)
  @code_units_cache = @parse_result.code_units_cache(@encoding)
  true
end

def syntax_error?

: -> bool
@override
def syntax_error?
  @parse_result.failure?
end