someone-stole-my-name / yaml-companion.nvim

Get, set and autodetect YAML schemas in your buffers.
MIT License
203 stars 18 forks source link

Can't register new Kubernetes schemas #12

Open joshfrench opened 1 year ago

joshfrench commented 1 year ago

When I use the default k8s detection, diagnostics work as expected:

Screen Shot 2022-08-23 at 16 58 30

However, when I try to use a custom schema I do not get any diagnostics. I am able to select a custom schema via :Telescope yaml_schema but once attached, any existing diagnostics disappear and I can't seem to trigger them again.

Here's my minimalized setup:

Env
Nvim 0.7.2
yaml-companion 0.1.1
-- init.lua
return require('packer').startup(function()
  use 'wbthomason/packer.nvim'

  use {
    "someone-stole-my-name/yaml-companion.nvim",
    requires = {
      { "neovim/nvim-lspconfig" },
      { "nvim-lua/plenary.nvim" },
      { "nvim-telescope/telescope.nvim" },
    },
    config = function()
      require("telescope").load_extension("yaml_schema")
      local cfg = require("yaml-companion").setup({
        schemas = {
          result = {
            {
              name = "Kubernetes 1.22.5",
              uri = "https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/v1.22.5-standalone-strict/all.json",
            },
          },
        },
      })
      require("lspconfig")["yamlls"].setup(cfg)
    end,
  }
end)
# ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
foo: bar

Output of :lua =require("yaml-companion.config").options:

{
  builtin_matchers = {
    kubernetes = {
      enabled = true
    }
  },
  lspconfig = {
    flags = {
      debounce_text_changes = 150
    },
    on_attach = <function 1>,
    settings = {
      redhat = {
        telemetry = {
          enabled = false
        }
      },
      yaml = {
        format = {
          enable = true
        },
        hover = true,
        schemaDownload = {
          enable = true
        },
        schemaStore = {
          enable = true,
          url = "https://www.schemastore.org/api/json/catalog.json"
        },
        schemas = {
          result = {}
        },
        trace = {
          server = "debug"
        },
        validate = true
      }
    },
    single_file_support = true
  },
  schemas = {
    result = { {
        name = "Kubernetes 1.22.5",
        uri = "https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/v1.22.5-standalone-strict/all.json"
      } }
  }
}

After running :Telescope yaml_schema and selecting Kubernetes 1.22.5, output of :lua =require("yaml-companion").get_buf_schema(0):

{
  result = { {
      name = "Kubernetes 1.22.5",
      uri = "https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/v1.22.5-standalone-strict/all.json"
    } }
}

I've also tried cloning the kubernetes-json-schema repo and pointing at a local path, but that didn't change anything.

One slightly weird wrinkle: if I set up a custom schema pointing at v1.22.4 to match the builtin, diagnostics work. Downgrading past that breaks them again though, so this may be a cached artifact? ¯\_(ツ)_/¯

joshfrench commented 1 year ago

Updating this to add some LSP logs. This is what follows after selecting the custom schema with :Telescope yaml_schemas.

"rpc.send"
{ jsonrpc = "2.0", method = "workspace/didChangeConfiguration",
    params = { settings = { redhat = { telemetry = { enabled = false } },
      yaml = { format = { enable = true }, hover = true, schemaDownload = { enable = true },
        schemaStore = { enable = true, url = "https://www.schemastore.org/api/json/catalog.json" },
        schemas = { ["https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/v1.22.5-standalone-strict/all.json"] = "file:///Users/josh/src/joshfrench/yaml-companion.nvim/ingress.yaml",
          result = {} }, trace = { server = "debug" }, validate = true } } } }

"rpc.receive"
{ id = 4, jsonrpc = "2.0", method = "workspace/configuration",
    params = { items = { { section = "yaml" }, { section = "http" }, { section = "[yaml]" },
      { section = "editor" }, { section = "files" } } } }

"server_request: callback result"
{ result = { { format = { enable = true }, hover = true, schemaDownload = { enable = true },
    schemaStore = { enable = true, url = "https://www.schemastore.org/api/json/catalog.json" },
    schemas = { ["https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/v1.22.5-standalone-strict/all.json"] = "file:///Users/josh/src/joshfrench/yaml-companion.nvim/ingress.yaml",
      result = {} }, trace = { server = "debug" }, validate = true }, vim.NIL, vim.NIL, vim.NIL, vim.NIL }, status = true }

"rpc.send"
{ id = 4, jsonrpc = "2.0",
    result = { { format = { enable = true }, hover = true, schemaDownload = { enable = true },
      schemaStore = { enable = true, url = "https://www.schemastore.org/api/json/catalog.json" },
      schemas = { ["https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/v1.22.5-standalone-strict/all.json"] = "file:///Users/josh/src/joshfrench/yaml-companion.nvim/ingress.yaml",
        result = {} }, trace = { server = "debug" }, validate = true }, vim.NIL, vim.NIL, vim.NIL, vim.NIL } }

"rpc.receive"
{ jsonrpc = "2.0", method = "yaml/schema/store/initialized", params = vim.empty_dict() }

"rpc.receive"
{ jsonrpc = "2.0", method = "textDocument/publishDiagnostics",
    params = { diagnostics = {}, uri = "file:///Users/josh/src/joshfrench/yaml-companion.nvim/ingress.yaml" } }

It looks like the client is correctly sending workspace/didChangeConfiguration, but the server doesn't think there are any diagnostics to report (and never does, no matter what I do to the file.) If I choose a built-in schema instead, things work as expected.

At this point I'm not sure if the issue is here or in yaml-language-server.

someone-stole-my-name commented 1 year ago

This is most likely an issue in yaml-language-server as you say, let's try to isolate the issue and report the bug upstream 🙏

joshfrench commented 1 year ago

Possibly related? https://github.com/redhat-developer/yaml-language-server/issues/60

someone-stole-my-name commented 1 year ago

Diagnostics break even just changing the default version in version.lua from 1.22.4 to 1.22.5. Oddly enough, all schema files are the same if you remove the version from the files (sed -i 's/v1.22.X//g' *).

Shinzu commented 1 year ago

I have the same problem,after some digging i believe this is due to a hard coded version in yaml-language-server itself:

https://github.com/redhat-developer/yaml-language-server/blob/main/src/languageservice/utils/schemaUrls.ts#L8

as workaround i "patched" the node files in the location where mason install the server:

cd ~/.local/share/nvim/mason/packages/yaml-language-server/node_modules/yaml-language-server
grep -r -l 1.22.4 | xargs sed -i 's/1.22.4/1.22.17/g'

you have to add the schema then in the config:

...
  schemas = {
    result = {
      {
        name = "Kubernetes 1.22.17",
        uri = "https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/v1.22.17-standalone-strict/all.json",
      },
    },
  },
...

afterwards the validation and completion works for me, if i choose the added schema with Telescope yaml_schema

image

someone-stole-my-name commented 1 year ago

The hack seems to work, thanks for looking into it.

For a more future-proof hack that works with any version, you can change the conditions on line 339 and 343 of src/languageserver/handlers/settingsHandlers.ts to something like:

        if (fileMatch.constructor === Array && uri.search(/kubernetes-json-schema/)) {
            fileMatch.forEach((url) => {
                this.yamlSettings.specificValidatorPaths.push(url);
            });
        }
        else if (uri.search(/kubernetes-json-schema/)) {
            this.yamlSettings.specificValidatorPaths.push(fileMatch);
        }

I haven't looked into why they have those conditions just for Kubernetes, but it works.

mosheavni commented 2 months ago

The hack seems to work, thanks for looking into it.

For a more future-proof hack that works with any version, you can change the conditions on line 339 and 343 of src/languageserver/handlers/settingsHandlers.ts to something like:

        if (fileMatch.constructor === Array && uri.search(/kubernetes-json-schema/)) {
            fileMatch.forEach((url) => {
                this.yamlSettings.specificValidatorPaths.push(url);
            });
        }
        else if (uri.search(/kubernetes-json-schema/)) {
            this.yamlSettings.specificValidatorPaths.push(fileMatch);
        }

~I haven't looked into why they have those conditions just for Kubernetes~, but it works.

hey @someone-stole-my-name I patched yaml-language-server with your changes but it seems that specifically on Kubernetes, there are no completions if you did not configure kubernetes = '/*.yaml' on your lsp config:

  local yaml_cfg = require('yaml-companion').setup {
    builtin_matchers = {
      -- Detects Kubernetes files based on content
      kubernetes = { enabled = true },
    },
    schemas = {
      {
        name = 'Kubernetes 1.27.12',
        uri = 'https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/v1.27.12-standalone-strict/all.json',
      },
      {
        name = 'Kubernetes 1.26.14',
        uri = 'https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/v1.26.14-standalone-strict/all.json',
      },
    },
    lspconfig = {
      on_attach = default_on_attach,
      capabilities = capabilities,
      cmd = { 'node', vim.fn.expand '~/Repos/yaml-language-server/out/server/src/server.js', '--stdio' },
      settings = {
        yaml = {
          -- if these lines are commented out, there are no completions
          -- schemas = {
          --   kubernetes = '/*',
          -- },
        },
      },
    },
  }
  require('lspconfig')['yamlls'].setup(yaml_cfg)

however, if I comment in those lines, I cannot get completion on any other schema since it's recognized as kubernetes. what am I doing wrong?