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

[Help] Trying to load schema for LSP to use with neoconf #42

Open
Ajaymamtora opened this issue Aug 24, 2024 · 9 comments
Open

[Help] Trying to load schema for LSP to use with neoconf #42

Ajaymamtora opened this issue Aug 24, 2024 · 9 comments

Comments

@Ajaymamtora
Copy link

Ajaymamtora commented Aug 24, 2024

Hi I can't get this plugin to suggest anything from local schema files in jsonls.

I'm loading the local schemas (1 of my own, the rest being these https://github.com/folke/neoconf.nvim/blob/main/schemas) via my setup:

modules["b0o/schemastore.nvim"] = {
  version = false,
  lazy = false,
  config = function()
    local schemastore_status_ok, _ = pcall(require, "schemastore")
    if not schemastore_status_ok then
      return
    end

    local extra_schemas = {
      {
        description = "Schema for nvim project config",
        fileMatch = { "nvim.json", ".nvim.json" },
        name = "nvim.json",
        url = "file://" .. _G.__os.home .. "/.config/json_schema/nvim.json",
      },
    }

    local schema_path = _G.__os.home .. "/.local/share/nvim/lazy/neoconf.nvim/schemas"

    local function add_schema(file)
      local name = file:match("(.+)%.json$")
      if name then
        table.insert(extra_schemas, {
          description = "Schema for " .. name,
          fileMatch = { "nvim.json", ".nvim.json" },
          name = "nvim.json",
          url = "file://" .. schema_path .. "/" .. file,
        })
      end
    end

    local handle = vim.loop.fs_scandir(schema_path)
    if handle then
      local name, type
      while true do
        name, type = vim.loop.fs_scandir_next(handle)
        if not name then
          break
        end
        if type == "file" and name:match("%.json$") then
          add_schema(name)
        end
      end
    end

    require("schemastore").json.schemas({
      extra = extra_schemas,
    })
  end,
}



-- LSP Setup:
M.jsonls_config = function(file_types)
  return {
    flags = {
      debounce_text_changes = default_debounce_time,
    },
    autostart = true,
    filetypes = file_types,
    on_attach = function(client, bufnr)
      setup_diagnostics.keymaps(client, bufnr)
      setup_diagnostics.omni(client, bufnr)
      setup_diagnostics.tag(client, bufnr)
      if client.server_capabilities.document_highlight then
        setup_diagnostics.document_highlight(client, bufnr)
      end
      setup_diagnostics.document_formatting(client, bufnr)
      setup_diagnostics.inlay_hint(client, bufnr)
      if client.server_capabilities.documentSymbolProvider then
        navic.attach(client, bufnr)
      end
    end,
    capabilities = setup_diagnostics.get_capabilities(),
    root_dir = function(fname)
      return util.find_git_ancestor(fname) or vim.fn.getcwd()
    end,
    settings = {
      json = {
        validate = { enable = true },
        schemas = require("schemastore").json.schemas({
          extra = {
            {
              description = "Schema for nvim project config",
              fileMatch = { "nvim.json", ".nvim.json" },
              name = "nvim.json",
              url = "file://" .. _G.__os.home .. "/.config/json_schema/nvim.json",
            },
          },
        }),
      },
    },
  }
end

It successfully adds to extras but nothing is suggested by the LSP at all.

I'm triggering nvim cmp in files named nvim.json and .nvim.json and neither works

Please can I have some help?

@Ajaymamtora Ajaymamtora changed the title [Help] Trying to load schema for LSP to use in neoconf [Help] Trying to load schema for LSP to use with neoconf Aug 24, 2024
@Ajaymamtora
Copy link
Author

Ajaymamtora commented Aug 24, 2024

In json files that don't match my patterns, the LSP suggests $schema and then a bunch of nonsense - not sure what happened here?

image

None of these exist in my local schemas

@b0o
Copy link
Owner

b0o commented Aug 28, 2024

Calling schemastore.json.schemas() does not mutate the underlying catalog, it returns a deep copy of the catalog with the extra schemas added. Therefore, this will have no effect:

modules["b0o/schemastore.nvim"] = {
  version = false,
  lazy = false,
  config = function()
    -- ...
    require("schemastore").json.schemas({
      extra = extra_schemas,
    })
  end,
}

You will need to modify your config to pass extra_schemas here:

-- LSP Setup:
M.jsonls_config = function(file_types)
  return {
    -- ...
    settings = {
      json = {
        validate = { enable = true },
        schemas = require("schemastore").json.schemas({ -- pass extra_schemas to this call
          extra = {
            {
              description = "Schema for nvim project config",
              fileMatch = { "nvim.json", ".nvim.json" },
              name = "nvim.json",
              url = "file://" .. _G.__os.home .. "/.config/json_schema/nvim.json",
            },
          },
        }),
      },
    },
  }
end

@Ajaymamtora
Copy link
Author

Thanks, I've updated it as you suggested and temporarily simplified it like so:

  local extra_schemas = {
    {
      description = "ASTRO",
      fileMatch = { "nvim.json", ".nvim.json" },
      name = "nvim.json",
      url = "/Users/ajay.mamtora/.local/share/nvim/lazy/neoconf.nvim/schemas/astro.json",
    },
  }
...
    settings = {
      json = {
        validate = { enable = true },
        schemas = require("schemastore").json.schemas({
          extra = extra_schemas,
        }),
      },
    },

And the jsonls lsp isn't suggesting properties defined in "https://github.com/folke/neoconf.nvim/blob/main/schemas/astro.json" -- am I misunderstanding something?

All I see is this:
image

image

@Hdoc1509
Copy link

Hi, @Ajaymamtora , you also need to add nvim.json to select option. Like this:

local extra_schemas = {
  {
    description = "ASTRO",
    fileMatch = { "nvim.json", ".nvim.json" },
    name = "nvim.json",
    url = "/Users/ajay.mamtora/.local/share/nvim/lazy/neoconf.nvim/schemas/astro.json",
  },
}
...
  settings = {
    json = {
      validate = { enable = true },
      schemas = require("schemastore").json.schemas({
        select = { ...other_schemas, 'nvim.json' },
        extra = extra_schemas,
      }),
    },
  },

Warning

Use the name field of your custom schema in select option.

Recommendation

I suggest you to use vim.fn.expand() to get the path of the local schema:

url = vim.fn.expand('~/.local/share/nvim/lazy/neoconf.nvim/schemas/astro.json')

This way you will retrieve the file if you use your neovim config in another machine where username or $HOME is different.


Have a good day n_n7

@Ajaymamtora
Copy link
Author

Hi, @Ajaymamtora , you also need to add nvim.json to select option. Like this:

local extra_schemas = {
  {
    description = "ASTRO",
    fileMatch = { "nvim.json", ".nvim.json" },
    name = "nvim.json",
    url = "/Users/ajay.mamtora/.local/share/nvim/lazy/neoconf.nvim/schemas/astro.json",
  },
}
...
  settings = {
    json = {
      validate = { enable = true },
      schemas = require("schemastore").json.schemas({
        select = { ...other_schemas, 'nvim.json' },
        extra = extra_schemas,
      }),
    },
  },

Warning

Use the name field of your custom schema in select option.

Recommendation

I suggest you to use vim.fn.expand() to get the path of the local schema:

url = vim.fn.expand('~/.local/share/nvim/lazy/neoconf.nvim/schemas/astro.json')

This way you will retrieve the file if you use your neovim config in another machine where username or $HOME is different.

Have a good day n_n7

Hi I'm not sure what you mean by ...other_schemas,, ive looped through the folder that contains all the schema json files, and added that to a table.

Heres what ive currently got:

  handlers["jsonls"] = function()
    local extra_schemas = {
      {
        description = "Schema for nvim project config",
        fileMatch = { "nvim.json", ".nvim.json" },
        name = "nvim.json",
        url = vim.fn.expand("~/.config/json_schema/nvim.json"),
      },
    }

    local schema_path = vim.fn.expand("~/.local/share/nvim/lazy/neoconf.nvim/schemas")

    local function add_schema(file)
      local name = file:match("(.+)%.json$")
      if name then
        table.insert(extra_schemas, {
          description = "Schema for " .. name,
          fileMatch = { "nvim.json", ".nvim.json" },
          name = "nvim.json",
          url = schema_path .. "/" .. file,
        })
      end
    end

    local handle = vim.uv.fs_scandir(schema_path)
    if handle then
      local name, type
      while true do
        name, type = vim.uv.fs_scandir_next(handle)
        if not name then
          break
        end
        if type == "file" and name:match("%.json$") then
          add_schema(name)
        end
      end
    end

    require("lspconfig").jsonls.setup({
      flags = {
        debounce_text_changes = default_debounce_time,
      },
      autostart = true,
      filetypes = { "json" },
      on_attach = function(client, bufnr)
        M.omni(client, bufnr)
        M.tag(client, bufnr)
        M.document_highlight(client, bufnr)
        M.inlay_hint(client, bufnr)
      end,
      capabilities = M.get_capabilities(),
      settings = {
        json = {
          schemas = require("schemastore").json.schemas({
            extra = extra_schemas,
          }),
          validate = { enable = true },
        },
      },
      setup = {
        commands = {
          Format = {
            function()
              vim.lsp.buf.range_formatting({}, { 0, 0 }, { vim.fn.line("$"), 0 })
            end,
          },
        },
      },
    })
  end

Now my LSP is suggesting the $schema variable at the top level, then the url as its value. I want jsonls to suggest the content described by the schema, not text of the literal JSON files that describe the schema in the neoconf repo

@Hdoc1509
Copy link

Hdoc1509 commented Dec 27, 2024

In ...other_schemas, I mean other config objects in the list.

If I'm not wrong, the following should be enough:

handlers["jsonls"] = function()
  local selected_schemas = {
   "nvim.json", -- <-- `name` field
  }

  local extra_schemas = {
    {
      description = "Schema for nvim project config",
      fileMatch = { "nvim.json", ".nvim.json" },
      name = "nvim.json",
      url = vim.fn.expand("~/.config/json_schema/nvim.json"),
    },
  }

  local schema_path =
    vim.fn.expand("~/.local/share/nvim/lazy/neoconf.nvim/schemas")

  local function add_schema(file)
    local name = file:match("(.+)%.json$")
    if name then
      table.insert(extra_schemas, {
        description = "Schema for " .. name,
        -- NOTE: `fileMatch` should match the filename(s) you expect to be used
        -- it should be generated dynamically based on `name` local variable
        -- see https://github.com/SchemaStore/schemastore/blob/master/src/api/json/catalog.json for references
        fileMatch = { "nvim.json", ".nvim.json" },
        name = name, -- NOTE: `name` field should be unique
        url = schema_path .. "/" .. file,
      })

      -- add to selected schemas
      table.insert(selected_schemas, name)
    end
  end

  local handle = vim.uv.fs_scandir(schema_path)
  if handle then
    local name, type
    while true do
      name, type = vim.uv.fs_scandir_next(handle)
      if not name then
        break
      end
      if type == "file" and name:match("%.json$") then
        add_schema(name)
      end
    end
  end

  require("lspconfig").jsonls.setup({
    flags = {
      debounce_text_changes = default_debounce_time,
    },
    autostart = true,
    filetypes = { "json" },
    on_attach = function(client, bufnr)
      M.omni(client, bufnr)
      M.tag(client, bufnr)
      M.document_highlight(client, bufnr)
      M.inlay_hint(client, bufnr)
    end,
    capabilities = M.get_capabilities(),
    settings = {
      json = {
        schemas = require("schemastore").json.schemas({
          -- DO NOT FORGET the `select` option!
          select = selected_schemas,
          extra = extra_schemas,
        }),
        validate = { enable = true },
      },
    },
    setup = {
      commands = {
        Format = {
          function()
            vim.lsp.buf.range_formatting({}, { 0, 0 }, { vim.fn.line("$"), 0 })
          end,
        },
      },
    },
  })
end

@Ajaymamtora
Copy link
Author

Thanks for the help, unfortunately thats made it suggest less stuff, i only see 2 schema values listed here:
image

image

And before it used to list all the URLs defined inside each schema file with the last iteration i provided you. Either way, its still only suggesting $schema at the top level, rather than the actual JSON stucture defined by the json schema files.

Not sure how to proceed from here :(

@Hdoc1509
Copy link

Hdoc1509 commented Dec 27, 2024

Oh. I think I misunderstood.

You want suggestions for $schema-like fields, right?
I don't know how to do that.
Maybe by touching completion engine plugins (?).

My approuch enable suggestions of available fields for specific files (this is how schemastore.nvim works), i.e.:

  • compilerOptions for tsconfig.json
  • runtime.version for .luarc.json
  • env for .eslintc.json

@Ajaymamtora
Copy link
Author

Ajaymamtora commented Dec 29, 2024

Reference
I want everything under the 'properties' object to be suggested, is this possible using schemastore.nvim? Maybe I misunderstood as well

Thanks for the response, for example, all the schema files in the neoconf repo:
https://github.com/folke/neoconf.nvim/blob/main/schemas/eslint.json
are structured like this with the available LSP options, and I want all of them in every schema to be suggested in my nvim.json file, I dont want some to be suggested in tsconfig.json and some in env if that makes sense. This is because the nvim.json file will set global LSP config options for all LSPs

https://github.com/folke/neoconf.nvim

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

No branches or pull requests

3 participants