Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for opening source generated documents #115

Merged
merged 5 commits into from
Dec 13, 2024
Merged

Conversation

zickb
Copy link

@zickb zickb commented Dec 13, 2024

This PR adds support for opening and handling source generated documents. The reloading of open source generated documents is currently not implement, but should not be to hard to add.

The "BufReadCmd" callback is inspired by https://github.com/mfussenegger/nvim-jdtls/blob/master/lua/jdtls.lua#L1186 (including the vim.wait call).

The VsCode extension has also added support for source generated documents. (initial: dotnet/vscode-csharp#7581, refresh support: dotnet/vscode-csharp#7791, src location: `https://github.com/dotnet/vscode-csharp/blob/main/src/lsptoolshost/sourceGeneratedFilesContentProvider.ts)

Notes from manual testing:
The VsCode extension and this extension returns some times different results when executing the "go to reference" command.
E.g. In VsCode 3 references are found (t.Print(), public partial Regex Print(); and public partial global::System.Text.RegularExpressions.Regex Print() => global::System.Text.RegularExpressions.Generated.Print_0.Instance;)
while this extension only returns 2 references (public partial Regex Print(); and public partial global::System.Text.RegularExpressions.Regex Print() => global::System.Text.RegularExpressions.Generated.Print_0.Instance;).
But if the cursor is at the source generate method name, VsCode and this extension returns both 3 references.

I guess that this is not a direct problem with this PR, but rather some difference in the lsp client setup/lsp client implementation that lead to this behavior.

var t = new Test2();
t.Print();
//  ^ place cursor here

public partial class Test2
{
	[GeneratedRegex("test")]
	public partial Regex Print();

	[GeneratedRegex("test2")]
	public partial Regex Print2();
}

For a better telescope support two thinks must be done:

  1. register an autocmd handler:
vim.api.nvim_create_autocmd({ "User" }, {
	pattern = "TelescopePreviewerLoaded",
	callback = function(args)
		local putils = require("telescope.previewers.utils")
		if args.data ~= nil and args.data.bufname ~= nil and args.data.bufname:match("^roslyn%-source%-generated://") then
			putils.highlighter(args.buf, 'cs', {})
		end
	end
  1. a slightly customized entry_maker function have to be provided:
local get_filename_fn = function()
	local bufnr_name_cache = {}
	return function(bufnr)
		bufnr = vim.F.if_nil(bufnr, 0)
		local c = bufnr_name_cache[bufnr]
		if c then
			return c
		end

		local n = vim.api.nvim_buf_get_name(bufnr)
		bufnr_name_cache[bufnr] = n
		return n
	end
end

local gen_from_quickfix_with_remotefile_support = function(opts)
	opts = opts or {}
	local show_line = vim.F.if_nil(opts.show_line, true)

	local utils = require("telescope.utils")
	local make_entry = require("telescope.make_entry")
	local hidden = utils.is_path_hidden(opts)

	local make_display = function(entry)
		-- optional customization
		local filename = entry.filename:match("^roslyn%-source%-generated://(.+)%?")
		if filename == nil then
			filename = entry.filename
		end

		local display_filename, path_style = utils.transform_path(opts, filename)

		local display_string = string.format("%s:%d:%d", display_filename, entry.lnum, entry.col)
		if hidden then
			display_string = string.format("%4d:%2d", entry.lnum, entry.col)
		end

		if show_line then
			local text = entry.text
			if opts.trim_text then
				text = vim.trim(text)
			end
			text = text:gsub(".* | ", "")
			display_string = display_string .. ":" .. text
		end

		return display_string, path_style
	end

	local get_filename = get_filename_fn()

	return function(entry)
		local filename = vim.F.if_nil(entry.filename, get_filename(entry.bufnr))

		-- required: Custom language server protocol extensions can result in servers sending URIs with custom schemes.
		-- These files are not stored on disk and we need to set the buffer number to show a preview for the buffer content.
		local bufnr = entry.bufnr
		if filename:match("^roslyn%-source%-generated://") then
			bufnr = vim.fn.bufnr(filename)
		end

		return make_entry.set_default_entry_mt({
			value = entry,
			ordinal = (not hidden and filename or "") .. " " .. entry.text,
			display = make_display,
			bufnr = bufnr,
			filename = filename,
			lnum = entry.lnum,
			col = entry.col,
			text = entry.text,
			start = entry.start,
			finish = entry.finish,
		}, opts)
	end
end

local opts = {
       entry_maker = gen_from_quickfix_with_remotefile_support()
}

require("telescope.builtin").lsp_references(opts)

Copy link
Owner

@seblj seblj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow this looks great! Thank you very much!

I just had one question, and otherwise I just want to test it a little bit first.

The code looks very simple and is easily understandable🙌

callback = function()
local uri = vim.fn.expand('<amatch>')
local buf = vim.api.nvim_get_current_buf()
vim.bo[buf].modifiable = true
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understand it correctly, we only set modified here to be able to set the lines in the handler, and then immediately set it to nomodifiable again after that?

Is it possible to set it to modifiable just before setting the lines inside the handler or doesn't that work?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see that this is also done for the jdtls, so it is probably fine🤷‍♂️ I was just curious

@seblj
Copy link
Owner

seblj commented Dec 13, 2024

I just tried it a bit, and seems good👍 I just added a commit to format the code while I was already having it open and format on save is turned on for me

@seblj
Copy link
Owner

seblj commented Dec 13, 2024

Thanks!

@seblj seblj merged commit 6d591af into seblj:main Dec 13, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants