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

Injected formatter skips formatting if injected region at end of file #452

Open
1 task done
GerbenWelter opened this issue Jun 9, 2024 · 1 comment
Open
1 task done
Labels
bug Something isn't working P0 Highest priority, will receive attention

Comments

@GerbenWelter
Copy link

Neovim version (nvim -v)

NVIM v0.10.0 Build type: RelWithDebInfo LuaJIT 2.1.1713773202

Operating system/version

Fedora 40

Add the debug logs

  • I have set log_level = vim.log.levels.DEBUG and pasted the log contents below.

Log file

log_level was set to 'TRACE' to show injected formatter regions:

17:03:24[DEBUG] Running formatters on /home/gerben/repro/test.yaml: { "prettier", "injected" }
17:03:24[INFO] Run prettier on /home/gerben/repro/test.yaml
17:03:24[TRACE] Input lines: { "kind: ConfigMap", "apiVersion: v1", "metadata:", "  name: injected-repro", "  namespace: test", "data:", "  config.json: |-", "    {", '      "foo":   [', '              "bar",', '        "baz"', "      ]", "    }" }
17:03:24[DEBUG] Run command: { "prettier", "--stdin-filepath", "/home/gerben/repro/test.yaml" }
17:03:24[DEBUG] Run default CWD: /home/gerben/repro
17:03:24[DEBUG] prettier exited with code 0
17:03:24[TRACE] Output lines: { "kind: ConfigMap", "apiVersion: v1", "metadata:", "  name: injected-repro", "  namespace: test", "data:", "  config.json: |-", "    {", '      "foo":   [', '              "bar",', '        "baz"', "      ]", "    }" }
17:03:24[TRACE] prettier stderr: { "" }
17:03:24[INFO] Run injected on /home/gerben/repro/test.yaml
17:03:24[TRACE] Input lines: { "kind: ConfigMap", "apiVersion: v1", "metadata:", "  name: injected-repro", "  namespace: test", "data:", "  config.json: |-", "    {", '      "foo":   [', '              "bar",', '        "baz"', "      ]", "    }" }
17:03:24[TRACE] Injected formatter regions { { "json", 8, 1, 14, 0 } }
17:03:24[TRACE] Applying formatting to /home/gerben/repro/test.yaml
17:03:24[TRACE] Comparing lines { "kind: ConfigMap", "apiVersion: v1", "metadata:", "  name: injected-repro", "  namespace: test", "data:", "  config.json: |-", "    {", '      "foo":   [', '              "bar",', '        "baz"', "      ]", "    }" } and { "kind: ConfigMap", "apiVersion: v1", "metadata:", "  name: injected-repro", "  namespace: test", "data:", "  config.json: |-", "    {", '      "foo":   [', '              "bar",', '        "baz"', "      ]", "    }" }
17:03:24[TRACE] Diff indices {}
17:03:24[TRACE] Applying text edits: {}
17:03:24[TRACE] Done formatting /home/gerben/repro/test.yaml

Describe the bug

When saving the file Neovim should format both the yaml and the embedded json. But nothing what I tried would make conform.nvim format the json part. While troubleshooting (and fixing some of my own config bugs) I realized I had the misfortune of testing with a yaml file where the injection region was at at the end of the file. When adding another yaml key at the end of the file the json started formatting.

What is the severity of this bug?

breaking (some functionality is broken)

Steps To Reproduce

  1. nvim -u repro.lua /path/to/test.yaml
  2. Save the file.

Expected Behavior

Neovim will format both the yaml and the json file under "data/config.yaml".

Minimal example file

kind: ConfigMap
apiVersion: v1
metadata:
  name: injected-repro
  namespace: test
data:
  config.json: |-
    {
      "foo":   [
              "bar",
        "baz"
      ]
    }

Minimal init.lua

-- DO NOT change the paths and don't remove the colorscheme
local root = vim.fn.fnamemodify("./.repro", ":p")

-- set stdpaths to use .repro
for _, name in ipairs({ "config", "data", "state", "cache" }) do
	vim.env[("XDG_%s_HOME"):format(name:upper())] = root .. "/" .. name
end

-- bootstrap lazy
local lazypath = root .. "/plugins/lazy.nvim"
if not vim.loop.fs_stat(lazypath) then
	vim.fn.system({
		"git",
		"clone",
		"--filter=blob:none",
		"--single-branch",
		"https://github.com/folke/lazy.nvim.git",
		lazypath,
	})
end
vim.opt.runtimepath:prepend(lazypath)

-- install plugins
local plugins = {
	"folke/tokyonight.nvim",
	{
		"stevearc/conform.nvim",
		config = function()
			require("conform").setup({
				log_level = vim.log.levels.TRACE,
				-- add your config here
				formatters_by_ft = {
					json = { "prettier" },
					yaml = { "prettier", "injected" },
				},
				formatters = {
					injected = {
						options = {
							ignore_errors = false,
							lang_to_ext = {
								json = "json",
								yaml = "yaml",
							},
						},
					},
				},
				-- Set up format-on-save
				format_on_save = { timeout_ms = 5000, lsp_fallback = true },
			})
		end,
		init = function()
			-- If you want the formatexpr, here is the place to set it
			vim.o.formatexpr = "v:lua.require'conform'.formatexpr()"
		end,
	},
	-- add any other plugins here
	{
		"nvim-treesitter/nvim-treesitter",
		event = { "BufReadPre", "BufNewFile" },
		build = ":TSUpdate",
		config = function()
			-- import nvim-treesitter plugin
			local treesitter = require("nvim-treesitter.configs")

			-- configure treesitter
			treesitter.setup({ -- enable syntax highlighting
				highlight = {
					enable = true,
				},
				-- enable indentation
				indent = { enable = true },
				-- enable autotagging (w/ nvim-ts-autotag plugin)
				autotag = { enable = true },
				-- ensure these language parsers are installed
				ensure_installed = {
					"json",
					"lua",
					"query",
					"yaml",
				},
				-- auto install above language parsers
				auto_install = true,
				-- activate linter in query editor
			})
		end,
	},
	{
		"nvim-treesitter/playground",
	},
	{
		"williamboman/mason.nvim",
		dependencies = {
			"williamboman/mason-lspconfig.nvim",
			"WhoIsSethDaniel/mason-tool-installer.nvim",
		},
		config = function()
			-- import mason plugin safely
			local mason = require("mason")

			-- import mason-lspconfig plugin safely
			local mason_lspconfig = require("mason-lspconfig")

			-- automatically install tools
			local mason_tool_installer = require("mason-tool-installer")

			-- enable mason
			mason.setup({
				ui = {
					icons = {
						package_installed = "",
						package_pending = "",
						package_uninstalled = "",
					},
				},
			})

			mason_lspconfig.setup({
				ensure_installed = { "lua_ls" },
				-- auto-install configured servers (with lspconfig)
				automatic_installation = true, -- not the same as ensure_installed
			})

			mason_tool_installer.setup({
				ensure_installed = { "prettier", "stylua" },
			})
		end,
	},
}
require("lazy").setup(plugins, {
	root = root .. "/plugins",
})

vim.cmd.colorscheme("tokyonight")
-- add anything else here

Additional context

Treesitter file to inject json:
(put it in .repro/config/nvim/queries/yaml/injections.scm)

(document
  (block_node
	(block_mapping
	  (block_mapping_pair
		key: (flow_node) @_data (#eq? @_data "data")
		value: (block_node
				 (block_mapping
				   (block_mapping_pair
					 key: (flow_node) @_json_file
					 (#eq? @_json_file "config.json")
					 value: (block_node
							  (block_scalar) @injection.content
							  (#set! injection.language "json")
							  ; block_scalar must use offset which is relative to the '|'
							  (#offset! @injection.content 1 -14 0 0)
					 ))))))))
@GerbenWelter GerbenWelter added the bug Something isn't working label Jun 9, 2024
@stevearc stevearc added the P0 Highest priority, will receive attention label Jun 9, 2024
@GerbenWelter
Copy link
Author

GerbenWelter commented Jun 14, 2024

I spent some debugging this again and made the following observation. When adding an extra yaml key at the end of the file and the json is formatted, the conform trace log will report:

Injected formatter regions { { "json", 8, 1, 13, 5 } }

But with the json at the end of the file the log show:

Injected formatter regions { { "json", 8, 1, 14, 0 } }

Debugging the code this region table seems to come from parsing the treesitter output.

It looks like treesitter expands the region to the end of the file if the regions is at the end of the file. Could this be a treesitter bug?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working P0 Highest priority, will receive attention
Projects
None yet
Development

No branches or pull requests

2 participants