コードレビューのためのコメント評価機能の作成
この記事はMisskey.devアドベントカレンダー1日目、Vim駅伝2025年12月01日分の記事です。
NeoVim上でソースコードのコメントを評価できる機能を作成してみました。
完成したプラグイン、ソースコードはGitHubにあります。
思いつきで作ってみたものですので粗があるかと思います。
はじめに
昨今、コーディング補助AIの発展は目覚ましく、コードレビューの依頼から部分的なコーディング作業の置き換え、Vibe Codingによるコーディングの自動化まで、様々な場面で使われています。
しかし、AIにコードを書かせると、不要なコード、コメントを大量に書き込まれることがよくあります。特にコメントはかなり細かく挿入されるため、かえってコードが読みづらくなってしまい、人間が一つ一つチェックして削除、書き直しを行うという事態になりがちです。
そこで、コードリーディング中にコメントに対して評価を行い、後で評価状況を確認できるような機能を作成しました。
イメージとしてはダークソウルのメッセージ評価です。
要件
- コメント行でポジティブ/ネガティブ評価ができる
- コメントにカーソル合わせると、ポップアップで評価が表示される
- バッファ中のコメントの評価の一覧を表示できる
実現方法
今回はNeoVimのプラグインをLuaで作成します。
コメント行でポジティブ/ネガティブ評価をする
コメント上にカーソルがある状態で<Leader>bでポジティブ評価、<Leader>qでネガティブ評価をすることができます。
キーマップはいつもの通りに登録しています。
-- Key mappings
-- <Leader>b for positive rating
vim.keymap.set('n', '<Leader>b', function()
comment_bp.add_rating('b')
end, { silent = true, desc = 'Add positive rating to comment' })
-- <Leader>q for negative rating
vim.keymap.set('n', '<Leader>q', function()
comment_bp.add_rating('p')
end, { silent = true, desc = 'Add negative rating to comment' })
マップにb, qを割り当てているのは、サムズアップとサムズダウンを意識してのものです。
ネガティブ評価はpに割り当てたかったのですが、ペーストと重複するためqにしています。
コメントは正規表現で抽出しています。ファイル形式を見てどの正規表現を用いるか判断しています。
-- Get comment patterns based on filetype
local function get_comment_patterns()
local ft = vim.bo.filetype
local patterns = {}
if ft == 'c' or ft == 'cpp' or ft == 'java' or ft == 'javascript' or ft == 'typescript' then
patterns = {
'^%s*//(.*)$',
'^%s*/%*(.*)%*/$'
}
elseif ft == 'python' or ft == 'sh' or ft == 'bash' or ft == 'ruby' then
patterns = { '^%s*#(.*)$' }
elseif ft == 'vim' then
patterns = { '^%s*"(.*)$' }
elseif ft == 'lua' then
patterns = { '^%s*%-%-(.*)$' }
else
patterns = {
'^%s*//(.*)$',
'^%s*/%*(.*)%*/$',
'^%s*#(.*)$',
'^%s*"(.*)$',
'^%s*%-%-(.*)$'
}
end
return patterns
end
評価集計は別ファイルに持つのではなく、コメント末尾に直接埋め込むようにします。コメント末尾にb:3, p:0という形で挿入されます。
local new_rating = ' ' .. format_rating(rating.b, rating.p)
if rating.found then
local replaced = false
if line:match(patterns.emoji) then
line = line:gsub(patterns.emoji, new_rating)
replaced = true
end
if not replaced and line:match(patterns.simple) then
line = line:gsub(patterns.simple, new_rating)
replaced = true
end
else
line = line:gsub('%s*$', '')
if line:match('%*/$') then
line = line:gsub('%s*%*/$', new_rating .. ' */')
else
line = line .. new_rating
end
end
なお、コメントに埋め込まれた方の評価集計はconceal機能で見えなくしています。
local function setup_conceal()
local bufnr = vim.api.nvim_get_current_buf()
local ft = vim.bo.filetype
local supported = vim.tbl_contains(
{'python', 'c', 'cpp', 'vim', 'lua', 'sh', 'bash', 'ruby', 'java', 'javascript', 'typescript'}, ft)
if not supported then
return
end
if conceal_matches[bufnr] then
for _, match_id in ipairs(conceal_matches[bufnr]) do
pcall(vim.fn.matchdelete, match_id)
end
end
conceal_matches[bufnr] = {}
-- matchaddのConcealを正規表現で指定する
local match_id = vim.fn.matchadd('Conceal', [[\s\+b:\d\+,\s*p:\d\+]], 10, -1, {conceal = ''})
table.insert(conceal_matches[bufnr], match_id)
if vim.wo.conceallevel == 0 then
vim.wo.conceallevel = 2
end
if vim.wo.concealcursor == '' then
vim.wo.concealcursor = 'nc'
end
end
ポップアップで評価を表示する
ポップアップで評価を表示する際は自作のNeoVimのFloating WindowでPopup Menuを作ってみたからポップアップ表示部分を抜き出し、popup_infoとして使用しています。
popup_info.popup_info(text, {
relative = 'editor',
row = row,
col = col,
width = width,
height = 1,
border = 'rounded',
title = 'Rating',
zindex = 200,
timeout = 3000
})
表示は以下のようになります。

評価の一覧を表示する
現在のバッファ中のコメントの評価について一覧を表記します。
function M.show_rating_list()
local qf_list = {}
local lines = vim.api.nvim_buf_get_lines(0, 0, -1, false)
for line_num, line in ipairs(lines) do
if is_comment_line(line) then
local rating = extract_rating(line)
local text
if rating.found then
text = string.format('%s | %s', format_rating(rating.b, rating.p), line)
else
text = string.format('No rating | %s', line)
end
table.insert(qf_list, {
lnum = line_num,
text = text
})
end
end
vim.fn.setqflist(qf_list)
if #qf_list == 0 then
print('No comments found')
else
vim.cmd('copen')
print(string.format('Found %d comments', #qf_list))
end
end
一覧はQuickFixを使用して表示しています。
:CommentBPListコマンドを実行することで以下のように表示されます。

使い方
アイデア先行でなんとなく作ってみたものなのですが、この機能はコードレビューの簡易化で使えるかと思います。
ユースケース
- AIにソースコードを生成させる
- コードレビューでコードを読む
- 必要なコメントは
<Leader> + b, 不要なコメントは<Leader> + q - :CommentBPListで一覧表示
- QuickFixからBad評価のコメントを削除
AIの書いたコードをレビューするときだけでなく、複数人で運用する大規模コードについても一定期間で評価集計を確認し、不要なものは削除するなどの使い方ができます。
課題
やっつけで作ったのでイマイチなところがあります。ブラッシュアップしていきたいです。
- 複数行コメントに対応していない
- 評価の取り消しができない
- 評価した後に基準値を上回るものは全部削除ができた方が便利
- 今はバッファ単位で管理しているが、プロジェクト全体で傾向などを表示できるといいかも
- コメントだけでなくコード行にも評価できた方がいいかも
まとめ
AIコーディングが登場してからというもの、AIが生成した膨大なコードをいかに効率よく処理していくか、が人間の役目になりつつあります。
それに伴いエディタの役割も変わりつつあります。コードをより速く正確に書くためのツールから、AIが書いたコードを読む、評価するツールになっていくでしょう。今回作成したコメント評価プラグインもそこを意識しています。やっつけで作ったものではありますが、叩き台程度にはなるのではないでしょうか。
Discussion