From cb0b24d47bdad053ff77881216eaa43cda2cbb9e Mon Sep 17 00:00:00 2001 From: Lazar Bulovan Date: Thu, 19 Feb 2026 14:10:14 +0100 Subject: [PATCH] feat(lsp): add references provider for goto references Add referencesProvider capability and handler to support LSP references (gr keybinding in LazyVim). Searches all occurrences of a symbol in the current document. --- src/main.lua | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/src/main.lua b/src/main.lua index 9fb8ecf..1f5bde7 100644 --- a/src/main.lua +++ b/src/main.lua @@ -61,6 +61,7 @@ local capabilities = { resolveProvider = false, }, definitionProvider = true, + referencesProvider = true, documentSymbolProvider = true, diagnosticProvider = { relatedDocuments = {} }, textDocumentSync = 1, @@ -456,6 +457,67 @@ function handlers.textDocument_definition(params) return nil end +function handlers.textDocument_references(params) + local uri = params.textDocument.uri + local doc = documents[uri] + if not doc then + return nil + end + + local lines = {} + for line in doc.content:gmatch("([^\n]*)\n") do + table.insert(lines, line) + end + if params.position.line + 1 > #lines then + return nil + end + + local line = lines[params.position.line + 1] + local col = params.position.character + 1 + + local word_start = col + while word_start > 1 and line:sub(word_start - 1, word_start - 1):match("[%w_]") do + word_start = word_start - 1 + end + + local word_end = col + while word_end <= #line and line:sub(word_end, word_end):match("[%w_]") do + word_end = word_end + 1 + end + + local word = line:sub(word_start, word_end - 1):gsub("^#", "") + if not word or word == "" then + return nil + end + + local references = {} + for line_num, line_content in ipairs(lines) do + local search_col = 1 + while search_col <= #line_content do + local match_start, match_end = line_content:find("[%w_]+", search_col) + if not match_start then + break + end + local matched_word = line_content:sub(match_start, match_end) + if matched_word == word then + table.insert(references, { + uri = uri, + range = { + start = { line = line_num - 1, character = match_start - 1 }, + ["end"] = { line = line_num - 1, character = match_end }, + }, + }) + end + search_col = match_end + 1 + end + end + + if #references > 0 then + return references + end + return nil +end + function handlers.textDocument_documentSymbol(params) local uri = params.textDocument.uri local doc = documents[uri]