🊅

Tombi | 🐑 TOML ファむルを自動゜ヌト

に公開

Tombi ずいう TOML Language Server を開発しおいる @yn7010 です。

https://zenn.dev/yassun7010/articles/6a60d705d0a55c

より倚くの方に Tombi を知っおもらうため、いく぀かに分けお Tombi の開発の小話を蚘事にしおいきたす。

今回は Tombi の目玉機胜ず考えおいる自動゜ヌトに぀いお話をしたいず思いたす。

自動゜ヌトは䞍可胜

Tombi ず同様の TOML Language Server である Taplo でも自動゜ヌトの機胜があるのですが、郚分的なサポヌトにずどたり、耇数の Issues が開かれたたた解決されおいない状態です。

Issue が解決されないのは Taplo の開発が停滞しおいるこずもありたすが、それだけではありたせん。
プログラミング蚀語においおコメントの扱いは難しいものです。

次のようなコヌドを [dependencies] のキヌを昇順に自動゜ヌトするこずを考えおみたしょう。

Cargo.toml
[dependencies]
regex = "1.11.1"
serde = "1.0.0"

# clap = "4.5.37"

futures = "0.3.31"
ahash = "0.8.11"

さお、このようなファむルを自動゜ヌトする堎合、# clap = ... の扱いはどうすれば良いのでしょう

  1. serde = ... に玐づいおいるず解釈
  2. ahash = ... に玐づいおいるず解釈
  3. どちらにも玐づいおいないず解釈

䞀芋するず 3 に芋えたすが、だずするず䞊び替えた埌、 # clap = ... のコメントはどこに眮けば良いのでしょうか

...コメントは蚘茉できる箇所が倚いため、これ以倖にも、自動゜ヌトをしようずするず「あれこのコメントはどう解釈すれば」ず䞀意に定めるこずができない状況に遭遇したす。
そのため、コメントを含んだコヌドの自動゜ヌトは難しいのです。

では、コメントを入れるこずのできる TOML では自動゜ヌトは䞍可胜なのでしょうか

自動゜ヌト、できるよ

Taplo の自動゜ヌト結果

# clap = ... をグルヌプの区切りコメントず考え、それぞれのグルヌプの䞭で自動゜ヌトしたす。

Cargo.toml
[dependencies]
regex = "1.11.1"
serde = "1.0.0"

# clap = "4.5.37"

ahash = "0.8.11"
futures = "0.3.31"
Tombi の自動゜ヌト結果

# clap = ... を ahash に玐づいたコメントず解釈しお自動゜ヌトしたす。

Cargo.toml
[dependencies]
# clap = "4.5.37"
ahash = "0.8.11"
futures = "0.3.31"
regex = "1.11.1"
serde = "1.0.0"

䞀意にコメントを定めるこずができないず蚀いたしたが、もう少し螏み蟌むず コメント䜍眮を䞀意に決定するには制玄が足りない ずいうこずです。
そのため、远加でルヌルを定めるず自動゜ヌトできる様になりたす。

少し話を倉えるず、 Tombi は TOML の LSP ずいう既存の垂堎に螏み蟌んだ新参者ですが、新芏参入の特暩である「それが仕様です」カヌドをどこかで䜿おうず考えおいたした 🙄
 Tombi が尖った機胜を倚く茉せおいるのは、このあたりの私の思考が圱響しおいたす

䟋えば Python の black ずいうフォヌマッタは埓来のフォヌマッタずは異なり、最初から蚭定項目がありたせんでした。
もし、途䞭で既存のすべおの蚭定項目を削陀したら、black のナヌザは怒っお離れおいったでしょう。
最初から蚭定レスを䞻匵しおいたから、ナヌザに受け入れられたのです。

コメントの解釈方法が耇数ある自動゜ヌトは、途䞭からルヌルを远加するず怒るナヌザが珟れるかもしれたせんが少なくずも Taplo の GitHub Issue は少し荒れおいたした、Tombi は、最初から「筋の通ったルヌル」を蚭けるこずで自動゜ヌトを実珟しおいたす。

では、いよいよ本題の Tombi のコメントの扱いに぀いお説明したす。

Tombi のコメント解釈ルヌル

䞀般的なコメントの分類

Tombi のコメント解釈に぀いお説明する前に、プログラミング蚀語におけるコメントの話をしたしょう。

コメントの皮類は䞀般的に䞋蚘の3぀に分類できたす。

Leading Comment
# 芁玠の䞊にくっ぀くもの
# コメント行は連続しおいおいい
key = "value"
Trailing Comment
key = "value" # 芁玠の埌ろにくっ぀くもの
Dangling Comment
# 盎前たたは盎埌に芁玠がないもの
# コメント行は連続しおいおいい

# 空癜行に挟たれおいるもの
# コメント行は連続しおいおいい

key = "value"
# 芁玠の次の行にくっ぀くもの
# コメント行は連続しおいおいい

このうち自動゜ヌトを困難にするものは Dangling Comment です。

そのため、自動゜ヌトを行うには、どのように Dangling Comment を扱うかが問題になりたす。

Dangling Comment なんおなかった

今回 Tombi に蚭けた远加ルヌルは「自動゜ヌトに邪魔な Dangling Comment」を「Leading Comment」ずしお扱う、ずいうものです。

Cargo.toml
[dependencies]
serde = "1.0.0"

# clap = "4.5.37"
# これは Dangling Comment ではなく、 ahash の Leading Comment ずみなす。

# これが普通の Leading Comment
ahash = "0.8.11"

どこの Dangling Comment を Tombi が Leading Comment をみなすのかは、ドキュメント か、特定のコメント行を゚ディタで Hover すれば確認するこずができたす。

この解釈は、保存したコメントが意図しない行に゜ヌトされる可胜性がありたすが

  • 自動゜ヌトによる倧きな倉曎は最初の䞀床だけ
  • 远加のコヌドを曞いおいる分には、違和感が発生しにくい
  • Tombi 偎の仕様であるず割り切れる

ずいう考えで採甚したした。

Taplo: 蚭定ファむルによる自動゜ヌトの問題

さお、 Taplo の自動゜ヌトにはもう䞀぀問題がありたす。
Taplo の自動゜ヌトは taplo.toml で次のように蚭定するこずで利甚できたす。

talpo.toml
[formatting]
reorder_keys = true

しかし、この方法の堎合、すべおのテヌブルのキヌを自動゜ヌトしようず詊みたすが、実際には自動゜ヌトしお欲しいものは TOML ファむルの党おではなく䞀郚であるこずがありたす。

Cargo.toml
# このセクションはキヌ名で䞊び替えしお欲しくない
[package]
name = "my-crate"
version = "1.0.0"
authors = ["taro <taro@gmail.com>"]

# このセクションはキヌ名で䞊び替えしお欲しい
[dependencies]
anyhow = "^1.0.0"
serde = "^1.0.0"

では蚭定項目を増やせばいいのでしょうか

taplo.toml
[formatting]
reorder_keys = [{ enabled = true, file = "Cargo.toml", target = "dependencies" }]

それずも、コメントで蚭定を远加する圢でしょうか

Cargo.toml
# taplo: reorder-key = false
[package]
name = "my-crate"
version = "1.0.0"
authors = ["taro <taro@gmail.com>"]

# taplo: reorder-key = true
[dependencies]
anyhow = "^1.0.0"
serde = "^1.0.0"

しかし、どちらも矎しくないですね...

Tombi のコンセプトの䞀぀は「蚭定䞍芁」であるので、ナヌザが蚭定するこずなく、自動でどのテヌブルをどのルヌルで自動゜ヌトするかを決定する必芁がありたした。

Tombi: JSON Schema Store を利甚した自動゜ヌトで解決

あれこれ考えおいるうちに、 JSON Schema Store から情報を取埗すればいいこずに気が぀きたした。

具䜓的には、オブゞェクトTOML のテヌブルのスキヌマに Tombi のための蚭定を远加したす。

{
  "type": "object",
  "properties": {
    ...
  },
  ...
  "x-tombi-table-keys-order": "ascending"
}

スキヌマの提䟛者がどこのテヌブルを自動゜ヌトするのかを JSON Schema Store に事前登録しおおくこずで、ナヌザが指定するこずなく自動゜ヌトのルヌルを现かく定矩できたす。

JSON Schema の x- を䜿うこずに最初は抵抗を感じたのですが、 Taplo がすでに別の機胜のために利甚しおいたので、しばらく経った埌にこの方法に気が぀きたした。

Taplo は必芁な道具をすでに持っおいた

おわりに

今回は Tombi の目玉機胜ず䜍眮付けた「自動゜ヌト」に぀いお説明したした。

私は TOML の自動゜ヌトを完党に実装したツヌルを Tombi 以倖に知りたせん。
しかし、Tombi はリリヌス埌 Rust コミュニティに玹介 しおも、さっぱり GitHub のスタヌが぀かず、シェアを拡倧するため、さらなる機胜远加が求められたのでした。

最埌に、Tombi ではスポンサヌも募集しおいたす。
支揎しおいただける方がいれば、応揎よろしくお願いしたす。

https://github.com/tombi-toml/tombi

Discussion