|
14 | 14 |
|
15 | 15 | -- Angular requires a node_modules directory to probe for @angular/language-service and typescript
|
16 | 16 | -- in order to use your projects configured versions.
|
17 |
| -local root_dir = vim.fn.getcwd() |
18 |
| -local node_modules_dir = vim.fs.find('node_modules', { path = root_dir, upward = true })[1] |
19 |
| -local project_root = node_modules_dir and vim.fs.dirname(node_modules_dir) or '?' |
| 17 | +local fs, fn, uv = vim.fs, vim.fn, vim.uv |
20 | 18 |
|
21 |
| -local function get_probe_dir() |
22 |
| - return project_root and (project_root .. '/node_modules') or '' |
23 |
| -end |
| 19 | +local function collect_node_modules(root_dir) |
| 20 | + local results = {} |
24 | 21 |
|
25 |
| -local function get_angular_core_version() |
26 |
| - if not project_root then |
27 |
| - return '' |
| 22 | + local project_node = fs.joinpath(root_dir, 'node_modules') |
| 23 | + if uv.fs_stat(project_node) then |
| 24 | + table.insert(results, project_node) |
28 | 25 | end
|
29 | 26 |
|
30 |
| - local package_json = project_root .. '/package.json' |
31 |
| - if not vim.uv.fs_stat(package_json) then |
32 |
| - return '' |
| 27 | + local ngserver_exe = fn.exepath('ngserver') |
| 28 | + if ngserver_exe and #ngserver_exe > 0 then |
| 29 | + local realpath = uv.fs_realpath(ngserver_exe) or ngserver_exe |
| 30 | + local candidate = fs.normalize(fs.joinpath(fs.dirname(realpath), '../../node_modules')) |
| 31 | + if uv.fs_stat(candidate) then |
| 32 | + table.insert(results, candidate) |
| 33 | + end |
33 | 34 | end
|
34 | 35 |
|
35 |
| - local contents = io.open(package_json):read '*a' |
36 |
| - local json = vim.json.decode(contents) |
37 |
| - if not json.dependencies then |
38 |
| - return '' |
| 36 | + local internal_servers = fn.globpath(fn.stdpath('data'), '**/node_modules/.bin/ngserver', true, true) |
| 37 | + for _, exe in ipairs(internal_servers) do |
| 38 | + local realpath = uv.fs_realpath(exe) or exe |
| 39 | + local candidate = fs.normalize(fs.joinpath(fs.dirname(realpath), '../../node_modules')) |
| 40 | + if uv.fs_stat(candidate) then |
| 41 | + table.insert(results, candidate) |
| 42 | + end |
39 | 43 | end
|
40 | 44 |
|
41 |
| - local angular_core_version = json.dependencies['@angular/core'] |
42 |
| - |
43 |
| - angular_core_version = angular_core_version and angular_core_version:match('%d+%.%d+%.%d+') |
44 |
| - |
45 |
| - return angular_core_version |
| 45 | + return results |
46 | 46 | end
|
47 | 47 |
|
48 |
| -local default_probe_dir = get_probe_dir() |
49 |
| -local default_angular_core_version = get_angular_core_version() |
| 48 | +local function get_angular_core_version(root_dir) |
| 49 | + local package_json = fs.joinpath(root_dir, 'package.json') |
| 50 | + if not uv.fs_stat(package_json) then |
| 51 | + return '' |
| 52 | + end |
| 53 | + |
| 54 | + local ok, f = pcall(io.open, package_json, 'r') |
| 55 | + if not ok or not f then |
| 56 | + return '' |
| 57 | + end |
50 | 58 |
|
51 |
| --- structure should be like |
52 |
| --- - $EXTENSION_PATH |
53 |
| --- - @angular |
54 |
| --- - language-server |
55 |
| --- - bin |
56 |
| --- - ngserver |
57 |
| --- - typescript |
58 |
| -local ngserver_exe = vim.fn.exepath('ngserver') |
59 |
| -local ngserver_path = #(ngserver_exe or '') > 0 and vim.fs.dirname(vim.uv.fs_realpath(ngserver_exe)) or '?' |
60 |
| -local extension_path = vim.fs.normalize(vim.fs.joinpath(ngserver_path, '../../../')) |
| 59 | + local json = vim.json.decode(f:read('*a')) or {} |
| 60 | + f:close() |
61 | 61 |
|
62 |
| --- angularls will get module by `require.resolve(PROBE_PATH, MODULE_NAME)` of nodejs |
63 |
| -local ts_probe_dirs = vim.iter({ extension_path, default_probe_dir }):join(',') |
64 |
| -local ng_probe_dirs = vim |
65 |
| - .iter({ extension_path, default_probe_dir }) |
66 |
| - :map(function(p) |
67 |
| - return vim.fs.joinpath(p, '/@angular/language-server/node_modules') |
68 |
| - end) |
69 |
| - :join(',') |
| 62 | + local version = (json.dependencies or {})['@angular/core'] or '' |
| 63 | + return version:match('%d+%.%d+%.%d+') or '' |
| 64 | +end |
70 | 65 |
|
71 | 66 | ---@type vim.lsp.Config
|
72 | 67 | return {
|
73 |
| - cmd = { |
74 |
| - 'ngserver', |
75 |
| - '--stdio', |
76 |
| - '--tsProbeLocations', |
77 |
| - ts_probe_dirs, |
78 |
| - '--ngProbeLocations', |
79 |
| - ng_probe_dirs, |
80 |
| - '--angularCoreVersion', |
81 |
| - default_angular_core_version, |
82 |
| - }, |
| 68 | + cmd = function(dispatchers, config) |
| 69 | + local root_dir = config.root or fn.getcwd() |
| 70 | + local node_paths = collect_node_modules(root_dir) |
| 71 | + |
| 72 | + local ts_probe = table.concat(node_paths, ',') |
| 73 | + local ng_probe = table.concat( |
| 74 | + vim |
| 75 | + .iter(node_paths) |
| 76 | + :map(function(p) |
| 77 | + return fs.joinpath(p, '@angular/language-server/node_modules') |
| 78 | + end) |
| 79 | + :totable(), |
| 80 | + ',' |
| 81 | + ) |
| 82 | + local cmd = { |
| 83 | + 'ngserver', |
| 84 | + '--stdio', |
| 85 | + '--tsProbeLocations', |
| 86 | + ts_probe, |
| 87 | + '--ngProbeLocations', |
| 88 | + ng_probe, |
| 89 | + '--angularCoreVersion', |
| 90 | + get_angular_core_version(root_dir), |
| 91 | + } |
| 92 | + return vim.lsp.rpc.start(cmd, dispatchers) |
| 93 | + end, |
| 94 | + |
83 | 95 | filetypes = { 'typescript', 'html', 'typescriptreact', 'typescript.tsx', 'htmlangular' },
|
84 |
| - root_markers = { 'angular.json', 'nx.json' }, |
| 96 | + root_markers = { 'angular.json', 'nx.json', 'package.json' }, |
85 | 97 | }
|
0 commit comments