#!/usr/bin/env bash
set -eo pipefail
if [[ -n "$1" ]]; then
  cat "$1"
else
  curl --fail -L 'https://github.com/microsoft/language-server-protocol/raw/38c3746bc86c8ae7bc74f49afbd398b132bc627e/_specifications/lsp/3.17/metaModel/metaModel.json' |
    tee ./metaModel.json
fi | jq -r '
  def is_excluded:
    .method |
    # Notebook protocols are not supported.
    test("^notebookDocument/")
    # Lifecycle methods are handled specially outside.
    or test("^(initialized?|shutdown|exit)$");

  def to_snake:
    # Keep the prefix for `*/diagnostic` since both for workspace and document exist.
    sub("textDocument/diagnostic"; "document_diagnostic") |
    sub("workspace/diagnostic"; "workspace_diagnostic") |
    sub("^(workspace|textDocument|callHierarchy|typeHierarchy|window|client|\\$)/"; "") |
    sub("/"; "_"; "g") | sub("(?<x>[A-Z])"; "_\(.x | ascii_downcase)"; "g");

  def extract(dir_pat):
    .[] |
    select((.messageDirection | test(dir_pat)) and (is_excluded | not)) |
      "        \"\(.method)\", \(.method | to_snake);";

  "// This file is automatically @generated by update_omni_trait.sh",
  "// It is not intended for manual editing.",
  "#[rustfmt::ignore]",
  "define! {",
  "    // Client -> Server requests.",
  "    {",
  (.requests | extract("clientToServer|both")),
  "    }",
  "    // Client -> Server notifications.",
  "    {",
  (.notifications | extract("clientToServer|both")),
  "    }",
  "    // Server -> Client requests.",
  "    {",
  (.requests | extract("serverToClient|both")),
  "    }",
  "    // Server -> Client notifications.",
  "    {",
  (.notifications | extract("serverToClient|both")),
  "    }",
  "}"
' >./src/omni_trait_generated.rs
