Willi Wonkainitial commit
cec60f05/10/2026, 1:03:59 PM
.cr
Crystal
(text/x-crystal)
require "tree-sitter"

type CodeSymbol = Hash(String, String | Array(Hash(String, String)))

# Define a RepositoryFile class for demonstration purposes
class RepositoryFile
  property name : String
  property content : String

  def initialize(@name, @content)
  end
end

# Define a function to get the file content
def get_file_content(file : RepositoryFile) : String
  file.content
end

# Define the extract_symbols method
def extract_symbols(parser : TreeSitter::Parser, node : TreeSitter::Node, file : RepositoryFile) : Array(CodeSymbol)
  symbols = [] of CodeSymbol

  case node.type
  when "function"
    args = [] of Hash(String, String)
    node.children.select { |child| child.type == "parameter" }.each do |child|
      args << {
        "type" => child.children.find { |grandchild| grandchild.type == "type" }.inspect,
        "name" => child.children.find { |grandchild| grandchild.type == "identifier" }.text,
      }
    end
    return_type = node.children.find { |child| child.type == "type" }.inspect
    symbols << {
      "type" => "function",
      "name" => node.children.find { |child| child.type == "identifier" }.text,
      "args" => args,
      "returnType" => return_type,
      "visibility" => "public",
    }
  when "class"
    properties = [] of Hash(String, String)
    methods = [] of CodeSymbol
    constants = [] of Hash(String, String)
    node.children.each do |child|
      case child.type
      when "property"
        properties << {
          "name" => child.children.find { |grandchild| grandchild.type == "identifier" }.text,
          "type" => child.children.find { |grandchild| grandchild.type == "type" }.inspect,
        }
      when "function"
        args = [] of Hash(String, String)
        child.children.select { |grandchild| grandchild.type == "parameter" }.each do |grandchild|
          args << {
            "type" => grandchild.children.find { |great_grandchild| great_grandchild.type == "type" }.inspect,
            "name" => grandchild.children.find { |great_grandchild| great_grandchild.type == "identifier" }.text,
          }
        end
        return_type = child.children.find { |grandchild| grandchild.type == "type" }.inspect
        methods << {
          "name" => child.children.find { |grandchild| grandchild.type == "identifier" }.text,
          "args" => args,
          "returnType" => return_type,
        }
      when "constant"
        constants << {
          "name" => child.children.find { |grandchild| grandchild.type == "identifier" }.text,
          "value" => child.children.find { |grandchild| grandchild.type == "type" }.inspect,
        }
      end
    end
    symbols << {
      "type" => "class",
      "name" => node.children.find { |child| child.type == "identifier" }.text,
      "properties" => properties,
      "methods" => methods,
      "constants" => constants,
    }
  when "constant"
    symbols << {
      "type" => "constant",
      "name" => node.children.find { |child| child.type == "identifier" }.text,
      "value" => node.children.find { |child| child.type == "type" }.inspect,
    }
  end

  # Recursively extract symbols from child nodes
  node.children.each do |child|
    symbols.concat(extract_symbols(parser, child, file))
  end

  symbols
end