b0o / SchemaStore.nvim

🛍 JSON schemas for Neovim
https://schemastore.org
Apache License 2.0
726 stars 18 forks source link

Using json schemas with jsonls and lspconfig breaks diagnostics #8

Closed mcritchlow closed 2 years ago

mcritchlow commented 2 years ago

Hi,

Apologies if this is the wrong repo to report this too, but I've narrowed down nvim not showing diagnostics for json files to the configuration used to reference the schemastore json schemas.

Specifically, adding this to the lsp setup stops diagnostics from rendering in nvim (though I do see them in the LSP log if I use debug)

settings = {
    json = {
      schemas = require('schemastore').json.schemas(),
    },
  },

lsp log:

[DEBUG][2022-05-17 11:23:58] .../vim/lsp/rpc.lua:454    "rpc.receive"   {  jsonrpc = "2.0",  method = "textDocument/publishDiagnostics",  params = {    diagnostics = {},    uri = "file:///home/mcritchlow/projects/ucsd/highfive/renovate.json"  }}
[DEBUG][2022-05-17 11:24:27] .../vim/lsp/rpc.lua:347    "rpc.send"  {  jsonrpc = "2.0",  method = "textDocument/didChange",  params = {    contentChanges = { {        range = {          end = {            character = 11,            line = 1          },          start = {            character = 10,            line = 1          }        },        rangeLength = 1,        text = "'"      } },    textDocument = {      uri = "file:///home/mcritchlow/projects/ucsd/highfive/renovate.json",      version = 4    }  }}
[DEBUG][2022-05-17 11:24:27] .../vim/lsp/rpc.lua:454    "rpc.receive"   {  jsonrpc = "2.0",  method = "textDocument/publishDiagnostics",  params = {    diagnostics = {},    uri = "file:///home/mcritchlow/projects/ucsd/highfive/renovate.json"  }}

minimal init.lua (borrowed from lspconfig and modified for this issue)

local on_windows = vim.loop.os_uname().version:match 'Windows'

local function join_paths(...)
  local path_sep = on_windows and '\\' or '/'
  local result = table.concat({ ... }, path_sep)
  return result
end

vim.cmd [[set runtimepath=$VIMRUNTIME]]

local temp_dir = vim.loop.os_getenv 'TEMP' or '/tmp'

vim.cmd('set packpath=' .. join_paths(temp_dir, 'nvim', 'site'))

local package_root = join_paths(temp_dir, 'nvim', 'site', 'pack')
local install_path = join_paths(package_root, 'packer', 'start', 'packer.nvim')
local compile_path = join_paths(install_path, 'plugin', 'packer_compiled.lua')

local function load_plugins()
  require('packer').startup {
    {
      'wbthomason/packer.nvim',
      'b0o/schemastore.nvim',
      'williamboman/nvim-lsp-installer', {
        'neovim/nvim-lspconfig',
      }
    },
    config = {
      package_root = package_root,
      compile_path = compile_path,
    },
  }
end

_G.load_config = function()
  vim.lsp.set_log_level 'trace'
  if vim.fn.has 'nvim-0.5.1' == 1 then
    require('vim.lsp.log').set_format_func(vim.inspect)
  end
  local nvim_lsp = require 'lspconfig'
  local lsp_installer = require("nvim-lsp-installer")
  local on_attach = function(_, bufnr)
    local function buf_set_keymap(...)
      vim.api.nvim_buf_set_keymap(bufnr, ...)
    end

    local function buf_set_option(...)
      vim.api.nvim_buf_set_option(bufnr, ...)
    end

    buf_set_option('omnifunc', 'v:lua.vim.lsp.omnifunc')

    -- Mappings.
    local opts = { noremap = true, silent = true }
    buf_set_keymap('n', 'gD', '<Cmd>lua vim.lsp.buf.declaration()<CR>', opts)
    buf_set_keymap('n', 'gd', '<Cmd>lua vim.lsp.buf.definition()<CR>', opts)
    buf_set_keymap('n', 'K', '<Cmd>lua vim.lsp.buf.hover()<CR>', opts)
    buf_set_keymap('n', 'gi', '<cmd>lua vim.lsp.buf.implementation()<CR>', opts)
    buf_set_keymap('n', '<C-k>', '<cmd>lua vim.lsp.buf.signature_help()<CR>', opts)
    buf_set_keymap('n', '<space>wa', '<cmd>lua vim.lsp.buf.add_workspace_folder()<CR>', opts)
    buf_set_keymap('n', '<space>wr', '<cmd>lua vim.lsp.buf.remove_workspace_folder()<CR>', opts)
    buf_set_keymap('n', '<space>wl', '<cmd>lua print(vim.inspect(vim.lsp.buf.list_workspace_folders()))<CR>', opts)
    buf_set_keymap('n', '<space>D', '<cmd>lua vim.lsp.buf.type_definition()<CR>', opts)
    buf_set_keymap('n', '<space>rn', '<cmd>lua vim.lsp.buf.rename()<CR>', opts)
    buf_set_keymap('n', 'gr', '<cmd>lua vim.lsp.buf.references()<CR>', opts)
    buf_set_keymap('n', '<space>e', '<cmd>lua vim.diagnostic.open_float()<CR>', opts)
    buf_set_keymap('n', '[d', '<cmd>lua vim.diagnostic.goto_prev()<CR>', opts)
    buf_set_keymap('n', ']d', '<cmd>lua vim.diagnostic.goto_next()<CR>', opts)
    buf_set_keymap('n', '<space>q', '<cmd>lua vim.diagnostic.setloclist()<CR>', opts)
  end

  local name = 'jsonls'
  local capabilities = vim.lsp.protocol.make_client_capabilities()

  lsp_installer.setup {
    ensure_installed = name,
    automatic_installation = true,
  }

  nvim_lsp[name].setup {
    on_attach = on_attach,
    capabilities = capabilities,
    settings = {
      json = {
        schemas = require('schemastore').json.schemas(),
      },
    },
  }

  print [[You can find your log at $HOME/.cache/nvim/lsp.log. Please paste in a github issue under a details tag as described in the issue template.]]
end

if vim.fn.isdirectory(install_path) == 0 then
  vim.fn.system { 'git', 'clone', 'https://github.com/wbthomason/packer.nvim', install_path }
  load_plugins()
  require('packer').sync()
  vim.cmd [[autocmd User PackerComplete ++once lua load_config()]]
else
  load_plugins()
  require('packer').sync()
  _G.load_config()
end
b0o commented 2 years ago

Thanks for reporting! This isn't an issue with SchemaStore.nvim, but it is an important behavior that I should describe in the documentation.

This is due to the way jsonls handles its configuration, which is a bit counter-intuitive IMO. It seems that if you pass settings = { json = { ... } }, jsonls treats any unspecified option as false, rather than using the default value that would be used if you didn't pass any settings. The option that is causing your issue is validate.enable. To fix this, you can explicitly enable the validate option:

nvim_lsp.jsonls.setup({
  on_attach = on_attach,
  capabilities = capabilities,
  settings = {
    json = {
      validate = { enable = true },
      schemas = require("schemastore").json.schemas(),
    },
  },
})
b0o commented 2 years ago

For reference, here is the jsonls code causing this issue: https://github.com/microsoft/vscode/blob/6fef251f8f0e9f74b7adb4ed310e35eabb97afdf/extensions/json-language-features/server/src/jsonServer.ts#L230-L239

validateEnabled is true by default, but if any of the settings are changed, it defaults to false.

If you wanted, you could open an issue there and suggest that the default values should be kept if the settings doesn't include a certain key. They have over 6k open issues, though, so I have my doubts that it would be fixed any time soon.

mcritchlow commented 2 years ago

Ah, that's so helpful, thank you! I definitely agree that it's counter-intuitive to flip default settings when another setting is changed.. But that definitely addresses the issue on my end. Again, much appreciated :)