mruby用のLanguage ServerをGo言語で作ってみた💎
こんにちは!🤖
都内でエンジニアをしているhamachangです!
前回投稿した「Go言語でmrubyの静的型検査器を作ってみた💎」
の続きとはなりますが、
今回は mruby用のLanguage ServerをGo言語で作ってみました✨
今回作ったやつ「ruby-ti-lsp」の紹介
「Ruby-TI」とは、自分が作成したmruby用の静的型検査器なんですが、
ruby-ti-lspはRuby-TIの型検査をエディタから利用するやつですね。
ソースコードはこんな感じになりました🗒️
スクリーンショットはこんな感じですね。

機能としては、
- 型注釈(Code Lens)
- 補完 (Completion)
- メソッドジャンプ(Definition)
- 型検査(Diagnostics)
を実装しています🔧
なぜ作ったのか🤔
RubyTI本体に同じ様な機能を持つVim拡張(VimScript製)を同梱してたのですが、あくまでVim専用となっていました。
やっぱ作ったからには色んな人に使って欲しい。。。
きっと流行ってないのはVSCodeで使えないからだ!
よしVSCode対応(Language Serverを実装)だ!
と言う短絡的な動機です☝
Go言語で簡単にLanguage Serverが実装出来る「glsp」の紹介
そしてGo言語でLanguage Serverを実装しようとして色々調べてたら、見つけちゃったんですね。素敵なライブラリ。
それが「glsp」です。
本当に上手いことLSPを抽象化してくれていて、
めちゃくちゃ実装しやすかったです。
多分Language Serverを実装するぞ!ってなってから、1週間前後くらいで実装したんですが、全部このglspのお陰ですね!
func textDocumentCompletion(
ctx *glsp.Context,
params *protocol.CompletionParams,
) (any, error) {
var items []protocol.CompletionItem
content, ok := documentContents[params.TextDocument.URI]
if !ok {
return nil, nil
}
signatures :=
findComplection(content, params.Position.Line, params.Position.Character)
for _, sig := range signatures {
items =
append(items, protocol.CompletionItem{
Label: sig.Method,
Detail: &sig.Detail,
})
}
return items, nil
}
これは、補完の実装になるのですが、
こんな感じのメソッドを作って、
func NewServer() *server.Server {
handler = protocol.Handler{
Initialize: initialize,
TextDocumentDidOpen: textDocumentDidOpen,
TextDocumentCompletion: textDocumentCompletion,
TextDocumentDidChange: textDocumentDidChange,
TextDocumentDidSave: textDocumentDidSave,
TextDocumentDefinition: textDocumentDefinition,
TextDocumentCodeLens: textDocumentCodeLens,
}
server := server.NewServer(&handler, "ruby-ti", false)
return server
}
こんな感じでhandlerに登録すると実装が終わって、
Language Serverで補完機能を提供する事ができます(超絶便利ですね!)
あとLSPの仕組みを理解する目的としても、個人的にはおすすめのライブラリで、
LSPの仕組みを知りたい!って方にも是非使ってみて欲しいです🪛
やっぱり実装してみると理解は深まりますし💡
そしてリリースへ📅
VSCodeに対応したと言う事で、早速ウキウキでruby-ti-lspをリリースしてみたのですが、
RubyTIが流行って無い理由とVSCode対応は全然関係が無かった
と言う所までは解りました🙆
RubyTIの今後🚀
やっぱり使ってくれる人を増やすには、普段の仕事でもある程度使えないと行けないのかなーとか、
LSPをリリースして感じたので、今はそんな事を考えながら実装を進めています。
もう少し具体的的な話だと、
Ruby-TIはmruby用途のものではありますが、
設定をちゃんとすればCRubyやRailsでも使おうと思えば使えるので、
PR的に「Railsで使用してみた!」とか出来たら、少し使ってみよう!ってなる人が増える気がしています💡
(ただmruby用途に拘りたい理由もあるので、引き続きmruby用として提供すると思います)
なので、そこに向けて設定を簡略化する機能を作ったり、ドキュメントの整備を進めて行くつもりです✌
まあ上手く行っても行かなくても、物を作るって本当に楽しいですよね!😎
そもそも現状の試行錯誤がもう楽しいです✨
話が少し逸れた気がしますが、
「glsp」
おすすめです⭐⭐⭐
Discussion