mirror of
https://github.com/neovim/nvim-lspconfig.git
synced 2026-05-05 08:36:09 +02:00
fix(angularls): improve root path resolution #4083
Problem: The current config for Angular LS make strong assumptions when trying to find the root dir, which can lead to unexpected LSP crashes. Solution: By defining the 'cmd' field as a function, the config employs Neovim's LSP root resolution to identify the correct path and find the relevant node_modules folder. Co-authored-by: Erikson Kaszubowski <erikson.kaszubowski@serpro.gov.br>
This commit is contained in:
parent
c8c9420b76
commit
7580edb811
@ -14,72 +14,84 @@
|
||||
|
||||
-- Angular requires a node_modules directory to probe for @angular/language-service and typescript
|
||||
-- in order to use your projects configured versions.
|
||||
local root_dir = vim.fn.getcwd()
|
||||
local node_modules_dir = vim.fs.find('node_modules', { path = root_dir, upward = true })[1]
|
||||
local project_root = node_modules_dir and vim.fs.dirname(node_modules_dir) or '?'
|
||||
local fs, fn, uv = vim.fs, vim.fn, vim.uv
|
||||
|
||||
local function get_probe_dir()
|
||||
return project_root and (project_root .. '/node_modules') or ''
|
||||
local function collect_node_modules(root_dir)
|
||||
local results = {}
|
||||
|
||||
local project_node = fs.joinpath(root_dir, 'node_modules')
|
||||
if uv.fs_stat(project_node) then
|
||||
table.insert(results, project_node)
|
||||
end
|
||||
|
||||
local ngserver_exe = fn.exepath('ngserver')
|
||||
if ngserver_exe and #ngserver_exe > 0 then
|
||||
local realpath = uv.fs_realpath(ngserver_exe) or ngserver_exe
|
||||
local candidate = fs.normalize(fs.joinpath(fs.dirname(realpath), '../../node_modules'))
|
||||
if uv.fs_stat(candidate) then
|
||||
table.insert(results, candidate)
|
||||
end
|
||||
end
|
||||
|
||||
local internal_servers = fn.globpath(fn.stdpath('data'), '**/node_modules/.bin/ngserver', true, true)
|
||||
for _, exe in ipairs(internal_servers) do
|
||||
local realpath = uv.fs_realpath(exe) or exe
|
||||
local candidate = fs.normalize(fs.joinpath(fs.dirname(realpath), '../../node_modules'))
|
||||
if uv.fs_stat(candidate) then
|
||||
table.insert(results, candidate)
|
||||
end
|
||||
end
|
||||
|
||||
return results
|
||||
end
|
||||
|
||||
local function get_angular_core_version()
|
||||
if not project_root then
|
||||
local function get_angular_core_version(root_dir)
|
||||
local package_json = fs.joinpath(root_dir, 'package.json')
|
||||
if not uv.fs_stat(package_json) then
|
||||
return ''
|
||||
end
|
||||
|
||||
local package_json = project_root .. '/package.json'
|
||||
if not vim.uv.fs_stat(package_json) then
|
||||
local ok, f = pcall(io.open, package_json, 'r')
|
||||
if not ok or not f then
|
||||
return ''
|
||||
end
|
||||
|
||||
local contents = io.open(package_json):read '*a'
|
||||
local json = vim.json.decode(contents)
|
||||
if not json.dependencies then
|
||||
return ''
|
||||
end
|
||||
local json = vim.json.decode(f:read('*a')) or {}
|
||||
f:close()
|
||||
|
||||
local angular_core_version = json.dependencies['@angular/core']
|
||||
|
||||
angular_core_version = angular_core_version and angular_core_version:match('%d+%.%d+%.%d+')
|
||||
|
||||
return angular_core_version
|
||||
local version = (json.dependencies or {})['@angular/core'] or ''
|
||||
return version:match('%d+%.%d+%.%d+') or ''
|
||||
end
|
||||
|
||||
local default_probe_dir = get_probe_dir()
|
||||
local default_angular_core_version = get_angular_core_version()
|
||||
|
||||
-- structure should be like
|
||||
-- - $EXTENSION_PATH
|
||||
-- - @angular
|
||||
-- - language-server
|
||||
-- - bin
|
||||
-- - ngserver
|
||||
-- - typescript
|
||||
local ngserver_exe = vim.fn.exepath('ngserver')
|
||||
local ngserver_path = #(ngserver_exe or '') > 0 and vim.fs.dirname(vim.uv.fs_realpath(ngserver_exe)) or '?'
|
||||
local extension_path = vim.fs.normalize(vim.fs.joinpath(ngserver_path, '../../../'))
|
||||
|
||||
-- angularls will get module by `require.resolve(PROBE_PATH, MODULE_NAME)` of nodejs
|
||||
local ts_probe_dirs = vim.iter({ extension_path, default_probe_dir }):join(',')
|
||||
local ng_probe_dirs = vim
|
||||
.iter({ extension_path, default_probe_dir })
|
||||
:map(function(p)
|
||||
return vim.fs.joinpath(p, '/@angular/language-server/node_modules')
|
||||
end)
|
||||
:join(',')
|
||||
|
||||
---@type vim.lsp.Config
|
||||
return {
|
||||
cmd = {
|
||||
'ngserver',
|
||||
'--stdio',
|
||||
'--tsProbeLocations',
|
||||
ts_probe_dirs,
|
||||
'--ngProbeLocations',
|
||||
ng_probe_dirs,
|
||||
'--angularCoreVersion',
|
||||
default_angular_core_version,
|
||||
},
|
||||
cmd = function(dispatchers, config)
|
||||
local root_dir = config.root or fn.getcwd()
|
||||
local node_paths = collect_node_modules(root_dir)
|
||||
|
||||
local ts_probe = table.concat(node_paths, ',')
|
||||
local ng_probe = table.concat(
|
||||
vim
|
||||
.iter(node_paths)
|
||||
:map(function(p)
|
||||
return fs.joinpath(p, '@angular/language-server/node_modules')
|
||||
end)
|
||||
:totable(),
|
||||
','
|
||||
)
|
||||
local cmd = {
|
||||
'ngserver',
|
||||
'--stdio',
|
||||
'--tsProbeLocations',
|
||||
ts_probe,
|
||||
'--ngProbeLocations',
|
||||
ng_probe,
|
||||
'--angularCoreVersion',
|
||||
get_angular_core_version(root_dir),
|
||||
}
|
||||
return vim.lsp.rpc.start(cmd, dispatchers)
|
||||
end,
|
||||
|
||||
filetypes = { 'typescript', 'html', 'typescriptreact', 'typescript.tsx', 'htmlangular' },
|
||||
root_markers = { 'angular.json', 'nx.json' },
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user