.goファイル内のSQLを補完するLSPサーバを作った

pglsという.goファイル内のSQLを補完するLSPサーバをAIに作らせてみた。

github.com


先日、pistachioというPostgreSQL用の宣言的スキーマ管理ツールを作ったが、テーブル定義のSQLファイルを読ませればSQLの補完できるなぁ…となんとなく思いついて、mizzyさんがCarina用にLSPサーバを作っているのを見て、自分でもやってみた。

ワークスペースのルートに .pgls.json をおいて、スキーマファイルのディレクトリを指定。

{ "schemaDir": "schema" }

// language=sql とコメントを書く、またはdatabase/sqlの関数名でSQLと認識して補完できるようになる。

ツールチップでのテーブル定義の確認や、定義箇所へのジャンプもできる。

VS Codeとvimで動作確認済み。


vimはキーバインドの設定が必要だったので、以下のようにした。

if executable('pgls')
  augroup pgls_register
    autocmd!
    autocmd User lsp_setup call lsp#register_server({
      \ 'name': 'pgls',
      \ 'cmd': {server_info -> ['pgls']},
      \ 'allowlist': ['go', 'sql'],
      \ 'root_uri': {server_info -> lsp#utils#path_to_uri(
      \   lsp#utils#find_nearest_parent_file_directory(
      \     lsp#utils#get_buffer_path(), ['.git/', 'go.mod']))},
      \ })
  augroup END
endif

" vim-lsp 共通設定
let g:lsp_diagnostics_signs_enabled         = 1     " 行頭にエラーマーカー
let g:lsp_diagnostics_virtual_text_enabled  = 1     " 行末にインライン表示
let g:lsp_diagnostics_echo_cursor           = 1     " ステータスラインに表示
let g:lsp_document_highlight_enabled        = 0     " カーソル位置のシンボルハイライトは無効

" LSPがアタッチされたバッファだけにキーマップを設定
function! s:on_lsp_buffer_enabled() abort
  setlocal omnifunc=lsp#complete
  setlocal signcolumn=yes

  " ジャンプ
  nmap <buffer> gd <plug>(lsp-definition)
  nmap <buffer> gr <plug>(lsp-references)
  nmap <buffer> gi <plug>(lsp-implementation)
  nmap <buffer> gt <plug>(lsp-type-definition)

  " ホバー(K は man の上書き)
  nmap <buffer> K  <plug>(lsp-hover)

  " 診断
  nmap <buffer> ]d <plug>(lsp-next-diagnostic)
  nmap <buffer> [d <plug>(lsp-previous-diagnostic)

  " リネーム / コードアクション
  nmap <buffer> <leader>rn <plug>(lsp-rename)
  nmap <buffer> <leader>ca <plug>(lsp-code-action)

  " DocumentLink (Cmd+click相当 — pglsならスキーマファイルへ飛ぶ)
  nmap <buffer> gx <plug>(lsp-document-link)

  " 補完(asyncomplete 入れてないなら手動)
  inoremap <buffer> <C-Space> <C-x><C-o>
endfunction

augroup lsp_install
  autocmd!
  autocmd User lsp_buffer_enabled call s:on_lsp_buffer_enabled()
augroup END