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

Usage of typescript-nx-imports-plugin outside of Nx Console (Neovim) #18

Open
AkisArou opened this issue May 13, 2023 · 10 comments
Open

Comments

@AkisArou
Copy link

Any ideas how can it be done? I've seen that you are using nvim and maybe you could figure it out! I tried with no luck! (newbie to nvim). Thanks!

@Cammisuli
Copy link
Owner

Hmm, we’d probably need to make some kind of plugin that configures the typescript language server.

Then the input for this need to be all the projects in the workspace with the full path to their tsconfig file.

@AkisArou
Copy link
Author

AkisArou commented May 17, 2023

Yeah I think this is the way.
Yesterday I implemented a dirty coc.nvim plugin.
I checked the nx-console code and saw that the interface that coc exposes, is like VSCode's.
I got it working!
You can check it out at https://github.com/AkisArou/coc-nx, and also read README for instructions.
I also have a repository that I am experimenting with nx & neovim, if you want to try out the coc implementation.
You can check the tsserver logs with :CocCommand tsserver.openTsServerLog, and the plugin logs with :CocOpenLog.

But I think the nvim lsp is the way to go, and not coc.
So if you are familiar with nvim lsp, we can try it out! I already started experimenting!

@Cammisuli
Copy link
Owner

Oh awesome! I wont have too much time to experiment with the nvim lsp, but I know it's possible 😄

@AkisArou
Copy link
Author

Oh ok! I will try to find time to implement it and I'll keep in touch!

@antoineviscardi
Copy link

antoineviscardi commented Sep 12, 2023

Hey guys, I'd love to pick that up and get something that works for neovim.

I have basically zero experience with Typescript lagage server plugins. That being said, at a high level, my plan would be to implement a language server plugin that wraps this one, populating the externalFiles config from the compilerOptions.paths in the tsconfig.base.json at the root of the Nx monorepo. From what I understand, this is basically what Nx Console does under the hood right?

Would that work? @Cammisuli, is that basically what you were saying above? Would it be simpler to write a plugin from scratch?

@Cammisuli
Copy link
Owner

Yup, thats exactly it @antoineviscardi. As long as you can configure the tsserver lsp to include plugins (which need to be installed in node_modules or somewhere where the language server can load it from), and then configure said plugin, it should work.

Here's where we do the configuration of the imports plugin in Nx Console: https://github.com/nrwl/nx-console/blob/f5ba74fc234d1787ad4f9d269d804b03eb6c0e45/libs/vscode/typescript-plugin/src/lib/typescript-plugin.ts#L108-L113

And here's where we configure the tsserver in VSCode to include the imports plugin:
https://github.com/nrwl/nx-console/blob/f5ba74fc234d1787ad4f9d269d804b03eb6c0e45/apps/vscode/package.json#L58-L63

@faileon
Copy link

faileon commented Jan 13, 2024

Hi folks, did anyone manage to make any progress with this? @antoineviscardi ? I've recently switched to neovim and I love it, but pretty much all my projects are managed with NX and Go To Reference is not working right with nvim-lsp - it only works If I have open buffer which contains the reference and it's driving me crazy :].

I could give this a try but I also have no experience with tsserver plugins and LSPs.

@Ajaymamtora
Copy link

Hi folks, did anyone manage to make any progress with this? @antoineviscardi ? I've recently switched to neovim and I love it, but pretty much all my projects are managed with NX and Go To Reference is not working right with nvim-lsp - it only works If I have open buffer which contains the reference and it's driving me crazy :].

I could give this a try but I also have no experience with tsserver plugins and LSPs.

Did you manage to get any further with this?

@faileon
Copy link

faileon commented Aug 13, 2024

@Ajaymamtora check out pmizio/typescript-tools.nvim#124

@Ajaymamtora
Copy link

Ajaymamtora commented Aug 13, 2024

@Ajaymamtora check out pmizio/typescript-tools.nvim#124

Thanks but it didn't work for me, I'm trying to use this plugin without nx cli which is why i came to this issue

This is my setup

function config.typescript_tools()
  local setup_diagnostics = require("languages.utils.setup_diagnostics")
  -- local util = require("lspconfig/util")
  local navic = require("nvim-navic")

  local tsserver_file_preferences = function()
    -- if ft == "javascript" then
    -- elseif ft == "typescript" then
    -- else
    -- end
    return {
      inlayHints = {
        includeCompletionsForModuleExports = true,
        quotePreference = "auto",
        includeInlayParameterNameHints = "all",
        includeInlayParameterNameHintsWhenArgumentMatchesName = false,
        includeInlayFunctionParameterTypeHints = true,
        includeInlayVariableTypeHints = true,
        includeInlayVariableTypeHintsWhenTypeMatchesName = false,
        includeInlayPropertyDeclarationTypeHints = true,
        includeInlayFunctionLikeReturnTypeHints = true,
        includeInlayEnumMemberValueHints = true,
      },
    }
  end

  local tsserver_format_options = function()
    return {
      allowIncompleteCompletions = true,
      allowRenameOfImportPath = true,
    }
  end

  -- local execute_command = function(command, callback)
  --   vim.lsp.buf_request(0, command, vim.lsp.util.make_position_params(0), callback)
  -- end
  --
  -- local is_in_angular_project = function(callback)
  --   execute_command("angular/isAngularCoreInOwningProject", callback)
  -- end
  --
  -- local function is_angular_project(bufnr)
  --   local clients = vim.lsp.get_active_clients({ bufnr = bufnr })
  --   for _, client in ipairs(clients) do
  --     if client.name == "angularls" then
  --       local params = vim.lsp.util.make_position_params(bufnr)
  --       local result = client.request_sync("angular/isAngularCoreInOwningProject", params, 1000, bufnr)
  --       print("RESPONSE IS AGN")
  --       print(vim.inspect(result))
  --       if result and result.result then
  --         return true
  --       end
  --     end
  --   end
  --   return false
  -- end
  --
  -- local function find_project_root(fname, root_files)
  --   local dir = vim.fs.dirname(fname)
  --   local cwd = vim.uv.cwd()
  --
  --   -- Use vim.fs.find() to search for root files
  --   local found = vim.fs.find(root_files, {
  --     path = dir,
  --     upward = true,
  --     stop = vim.fs.dirname(cwd), -- Stop at the parent of cwd to include cwd in the search
  --     type = "file",
  --     limit = 1,
  --   })
  --
  --   -- If a root file is found, return its directory
  --   if #found > 0 then
  --     return vim.fs.dirname(found[1])
  --   end
  --
  --   -- If no root file is found, return nil
  --   return nil
  -- end

  local on_attach = function(client, bufnr)
    local angular_clients = vim.lsp.get_clients({
      bufnr = bufnr,
      name = "angularls",
    })

    -- TODO: support individual ts files that arent part of angular but are a child of a folder that contains a file
    -- that matches an angular project marker
    -- local bufnr = vim.fn.bufnr(fname)
    -- if is_angular_project(bufnr) then
    --   vim.notify("Detached tsclient with ID")
    --   return nil
    -- end

    -- If angularls is active, detach tsserver from the buffer or disable some capabilities
    if #angular_clients > 0 then
      -- Angular can handle renames
      client.server_capabilities.renameProvider = false
      client.server_capabilities.rename = false
      -- client.server_capabilities.referencesProvider = false
      -- client.stop(true)

      -- Let angular handle references
      -- local angular_client = angular_clients and angular_clients[1]
      -- print(vim.inspect(angular_client.server_capabilities))
      -- print(vim.inspect(angular_client.dynamic_capabilities))
      return
    end

    setup_diagnostics.keymaps(client, bufnr)
    setup_diagnostics.omni(client, bufnr)
    setup_diagnostics.tag(client, bufnr)
    if client.server_capabilities.document_highlight then
      if client.server_capabilities.document_highlight then
        setup_diagnostics.document_highlight(client, bufnr)
      end
    end
    setup_diagnostics.document_formatting(client, bufnr)
    setup_diagnostics.inlay_hint(client, bufnr)
    if client.server_capabilities.documentSymbolProvider then
      navic.attach(client, bufnr)
    end

    local mods = {
...
    }
    local externalFiles = {
      {
        mainFile = vim.uv.cwd() .. "/<proj1>/src/app/main.ts",
        directory = vim.uv.cwd() .. "/<proj1>/src/app",
      },
    }
    for _, v in ipairs(mods) do
      table.insert(externalFiles, {
        mainFile = vim.uv.cwd() .. "/<proj>/modules/" .. v .. "/index.ts",
        directory = vim.uv.cwd() .. "/<proj>/modules/" .. v,
      })
    end

    -- configure plugin
    vim.schedule(function()
      local constants = require("typescript-tools.protocol.constants")
      local method = constants.CustomMethods.ConfigurePlugin
      local args = {
        pluginName = "@monodon/typescript-nx-imports-plugin",
        configuration = {
          externalFiles = externalFiles,
        },
      }
      client.request(method, args, function()
        print("tsserver handled configuration request", method)
      end)
    end)
  end

  local default_debounce_time = 150
  local opts = {
    on_attach = on_attach,
    root_dir = function()
      return tostring(vim.uv.cwd())
    end,
    -- root_dir = function()
    --   local fname = vim.api.nvim_buf_get_name(0)
    --   return find_project_root(fname, { "angular.json", "tsconfig.json" }) or tostring(vim.uv.cwd())
    -- end,
    filetypes = require("languages.base.ft").jsts,
    capabilities = setup_diagnostics.get_capabilities(),
    cmd_env = { NODE_OPTIONS = "--max-old-space-size=6144" }, -- Give 8gb of RAM to node
    flags = {
      debounce_text_changes = default_debounce_time,
    },
    -- handlers = { ... },
    settings = {
      -- spawn additional tsserver instance to calculate diagnostics on it
      separate_diagnostic_server = true,
      -- "change"|"insert_leave" determine when the client asks the server about diagnostic
      publish_diagnostic_on = "insert_leave",
      -- array of strings("fix_all"|"add_missing_imports"|"remove_unused"|
      -- "remove_unused_imports"|"organize_imports") -- or string "all"
      -- to include all supported code actions
      -- specify commands exposed as code_actions
      expose_as_code_action = {
        "add_missing_imports",
        "remove_unused_imports",
        "organize_imports",
        "fix_all",
        "remove_unused",
      },
      -- string|nil - specify a custom path to `tsserver.js` file, if this is nil or file under path
      -- not exists then standard path resolution strategy is applied
      tsserver_path = nil,
      -- this value is passed to: https://nodejs.org/api/cli.html#--max-old-space-sizesize-in-megabytes
      -- memory limit in megabytes or "auto"(basically no limit)
      tsserver_max_memory = "auto",
      -- described below
      -- locale of all tsserver messages, supported locales you can find here:
      -- https://github.com/microsoft/TypeScript/blob/3c221fc086be52b19801f6e8d82596d04607ede6/src/compiler/utilitiesPublic.ts#L620
      tsserver_locale = "en",
      -- mirror of VSCode's `typescript.suggest.completeFunctionCalls`
      complete_function_calls = false,
      include_completions_with_insert_text = true,
      -- CodeLens
      -- WARNING: Experimental feature also in VSCode, because it might hit performance of server.
      -- possible values: ("off"|"all"|"implementations_only"|"references_only")
      code_lens = "off",
      -- by default code lenses are displayed on all referenceable values and for some of you it can
      -- be too much this option reduce count of them by removing member references from lenses
      disable_member_code_lens = true,
      -- JSXCloseTag
      -- WARNING: it is disabled by default (maybe you configuration or distro already uses nvim-ts-autotag,
      -- that maybe have a conflict if enable this feature. )
      jsx_close_tag = {
        enable = false,
        filetypes = { "javascriptreact", "typescriptreact" },
      },
      init_options = {
        hostInfo = "neovim",
        maxTsServerMemory = 6144,
        plugins = {
          {
            name = "@monodon/typescript-nx-imports-plugin",
            location = _G.__os.home .. "/.npm/lib/node_modules/@monodon/typescript-nx-imports-plugin",
          },
        },
        preferences = {
          importModuleSpecifierPreference = "relative",
          importModuleSpecifierEnding = "minimal",
        },
        tsserver = {
          logVerbosity = "verbose",
        },
      },
      tsserver_file_preferences = tsserver_file_preferences,
      tsserver_format_options = tsserver_format_options,
      -- specify a list of plugins to load by tsserver, e.g., for support `styled-components`
      -- (see 💅 `styled-components` support section)
      tsserver_plugins = {
        "@monodon/typescript-nx-imports-plugin",
        -- for TypeScript v4.9+
        "@styled/typescript-styled-plugin",
        -- or for older TypeScript versions
        -- "typescript-styled-plugin",
      },
    },
  }
  require("typescript-tools").setup(opts)
end


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

5 participants