code wiki / (root) / nx_lsp.nx

nx_lsp.nx

buildroot/runtime/nx_lsp.nx

71816 B1756 linesdepth 5pulls 15 transitivereach 0 importersview sourcekind tool
docsdependenciesstructsconstsfunctions

about

============================================================================================ nx_lsp.nx -- LN11: THE NISHILANG LANGUAGE SERVER. LSP 3.17 over stdio, JSON-RPC 2.0, Content-Length framed. THE ARCHITECTURE BAR (lang.plan, rust-analyzer 2020 architecture note): the front end is ONE query surface serving the IDE, the CLI and agents -- a language server that ships a SECOND parser is a second source of truth that drifts from the compiler, and every drift is a diagnostic the editor shows and the build does not (or worse, the reverse). So this organ contains NO lexer, NO parser and NO diagnostic text of its own. It calls, verbatim: nx_import.nx expand_imports / expand_ctx_enable_linemap (the import closure + LineMap) nx_tokenizer.nx lex_source (the tokens) nx_parse.nx parse_module / nx_diag_set_source / nx_diag_set_linemap (the caret + did-you-mean diagnostics, live since 08-05) Every message a user sees in their editor is a byte the compiler wrote. WHY A FORK PER ANALYSIS. The compiler's diagnostic sites sys_exit(2) by design -- recovery stops at NX_DIAG_MAX_ERRS and every parser DESYNC site is fatal on purpose (past a desync each further diagnostic points at innocent code). Calling parse_module in-process would therefore let one bad keystroke KILL THE LANGUAGE SERVER. The analysis runs in a forked child with fd 2 redirected to a per-document artifact; the parent survives sys_exit, SIGSEGV and SIGALRM alike and reports WHICH. This is the same isolation rust-analyzer gives flycheck, reached for the same reason. WHY A SHADOW FILE. expand_imports resolves an import by walking UP from the IMPORTING file's own directory. An unsaved buffer analysed from anywhere else would resolve a DIFFERENT import set -- the measured-a-different-subject defect, and it would show up as a flood of phantom "I do not know the name" errors for every symbol the real build resolves fine. So the dirty buffer is written to <document-directory>/<shadow-dir-name>/<basename>: exactly one hop below the document, so the resolver walks the identical chain. When the directory cannot be created the server analyses the SAVED file and SAYS SO over window/logMessage rather than silently reporting stale diagnostics. TRUTHFUL CAPABILITIES. initialize advertises textDocumentSync=Full, definitionProvider and hoverProvider and NOTHING ELSE. A server that advertises a capability it does not serve is the stub-carrying-the-contract-name defect wearing an editor's clothes: the client greys out its own working fallback and the user gets silence instead of a feature. POSITIONS ARE UTF-16 CODE UNITS, as LSP requires by default. The compiler counts BYTES, so every column crosses lsp_u16_of_bytes / lsp_bytes_of_u16. Getting this wrong is invisible in ASCII and silently off-by-N in every file with an accent in a comment.

dependencies 10 imports · 0 importers

nx_syscalls.nx nx_types.nx nx_lex_kinds.nx nx_ir.nx nx_linemap.nx nx_tokenizer.nx nx_parse.nx nx_import.nx nx_json_lib.nx nx_lineconf_lib.nx nx_lsp.nx

imports: nx_syscalls.nxnx_types.nxnx_lex_kinds.nxnx_ir.nxnx_linemap.nxnx_tokenizer.nxnx_parse.nxnx_import.nxnx_json_lib.nxnx_lineconf_lib.nx

imported by: nobody (leaf or entry point)

call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown

main lsp_cfg_load lsp_conf_int lcf_int_of sys_mmap nxa_die sys_write sys_exit nxa_lock_take nxa_lock_addr sys_write ↻ nxa_lock_give nxa_lock_addr ↻ nxa_report_overrun sys_write ↻ nxa_dump_printable nxa_dump_sizes sys_read_file sys_openat_rd sys_lseek sys_mmap ↻ sys_read sys_munmap sys_close lcf_int lcf_find lsp_log lsp_write_all sys_write ↻ lsp_slen sys_exit ↻ lsp_conf_str sys_mmap ↻ lcf_str_of sys_mmap ↻ sys_read_file ↻ lcf_str lcf_find ↻ lsp_log ↻ sys_exit ↻

structs

none

consts

71const LSP_BS: i64 = 8
72const LSP_TAB: i64 = 9
73const LSP_LF: i64 = 10
74const LSP_FF: i64 = 12
75const LSP_CR: i64 = 13
76const LSP_SPACE: i64 = 32
77const LSP_QUOTE: i64 = 34
78const LSP_PCT: i64 = 37
79const LSP_COMMA: i64 = 44
80const LSP_MINUS: i64 = 45
81const LSP_DOT: i64 = 46
82const LSP_SLASH: i64 = 47
83const LSP_D0: i64 = 48
84const LSP_D9: i64 = 57
85const LSP_COLON: i64 = 58
86const LSP_UA: i64 = 65
87const LSP_UF: i64 = 70
88const LSP_UZ: i64 = 90
89const LSP_BSLASH: i64 = 92
90const LSP_CARET: i64 = 94
91const LSP_USCORE: i64 = 95
92const LSP_LA: i64 = 97
93const LSP_LF_HEX: i64 = 102
94const LSP_LZ: i64 = 122
95const LSP_RBRACE: i64 = 125
96const LSP_TILDE: i64 = 126
98const LSP_B10: i64 = 10
99const LSP_B16: i64 = 16
100const LSP_WORD: i64 = 8
101const LSP_NUMBUF: i64 = 32
104const LSP_U8_2: i64 = 192
105const LSP_U8_3: i64 = 224
106const LSP_U8_4: i64 = 240
109const LSP_SYNC_FULL: i64 = 1
110const LSP_SEV_ERROR: i64 = 1
111const LSP_SEV_WARN: i64 = 2
112const LSP_MSG_ERROR: i64 = 1
113const LSP_MSG_WARN: i64 = 2
114const LSP_MSG_INFO: i64 = 3
115const LSP_RPC_METHOD_NOT_FOUND: i64 = 0 - 32601
117const LSP_EXIT_OK: i64 = 0
118const LSP_EXIT_NO_SHUTDOWN: i64 = 1
119const LSP_EXIT_USAGE: i64 = 3
120const LSP_EXIT_CONF: i64 = 4
127const LSP_JSON_ESC_MAX: i64 = 6
128const LSP_SCAFFOLD_BYTES: i64 = 2048
129const LSP_PER_DIAG_BYTES: i64 = 256
130const LSP_URI_ESC_MAX: i64 = 3
132const LSP_OUTHDR_BYTES: i64 = 64
133const LSP_ID_BYTES: i64 = 256
134const LSP_SYMROW_BYTES: i64 = 192
135const LSP_KINDBUF: i64 = 32
136const LSP_NAMEBUF: i64 = 128

functions

164func lsp_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
169func lsp_dec_at(b: *u8, s: i64, e: i64) -> i64;
called by 1: lsp_sym_find
170func lsp_slen_bounded(b: *u8, cap: i64) -> i64;
172func lsp_streq(a: *u8, b: *u8) -> i64
183func lsp_write_all(fd: i64, buf: *u8, n: i64) -> i64
195func lsp_log(s: *u8) -> i64 { lsp_write_all(2, s, lsp_slen(s)); return 0 }
197func lsp_lognum(v: i64) -> i64
215func lsp_put(d: *u8, o: i64, cap: i64, c: i64) -> i64
221func lsp_str_into(d: *u8, o: i64, cap: i64, s: *u8) -> i64
228func lsp_bytes_into(d: *u8, o: i64, cap: i64, s: *u8, n: i64) -> i64
calls 1: lsp_put
235func lsp_num_into(d: *u8, o: i64, cap: i64, v: i64) -> i64
248func lsp_hexdig(v: i64) -> i64
255func lsp_jstr_into(d: *u8, o: i64, cap: i64, s: *u8, n: i64) -> i64
277func lsp_jstrz_into(d: *u8, o: i64, cap: i64, s: *u8) -> i64
285func lsp_conf_int(key: *u8) -> i64
296func lsp_conf_str(key: *u8) -> *u8
308func lsp_cfg_load() -> i64
334func lsp_line_start(t: *u8, n: i64, line0: i64) -> i64
352func lsp_line_end(t: *u8, n: i64, start: i64) -> i64
364func lsp_u16_of_bytes(lp: *u8, n: i64, byte_off: i64) -> i64
385func lsp_bytes_of_u16(lp: *u8, n: i64, u16col: i64) -> i64
called by 1: lsp_resolve
406func lsp_is_word(c: i64) -> i64
called by 1: lsp_word_at
415func lsp_word_at(t: *u8, n: i64, off: i64, s_out: *i64, e_out: *i64) -> i64
450func lsp_hexval(c: i64) -> i64
459func lsp_uri_to_path(uri: *u8, out: *u8, cap: i64) -> i64
488func lsp_uri_unreserved(c: i64) -> i64
499func lsp_path_to_uri(path: *u8, out: *u8, cap: i64) -> i64
526func lsp_basename(path: *u8) -> *u8
541func lsp_uri_slot(i: i64) -> *u8 { return ((g_doc_uri as i64) + i * g_uri_bytes) as *u8 }
542func lsp_path_slot(i: i64) -> *u8 { return ((g_doc_path as i64) + i * SYS_PATH_MAX) as *u8 }
543func lsp_shadow_slot(i: i64) -> *u8 { return ((g_doc_shadow as i64) + i * SYS_PATH_MAX) as *u8 }
545func lsp_doc_find(uri: *u8) -> i64
559func lsp_doc_put(uri: *u8, txt: *u8, n: i64) -> i64
589func lsp_scratch_path(slot: i64, ext: *u8, out: *u8, cap: i64) -> i64
598func lsp_write_file(path: *u8, buf: *u8, n: i64) -> i64
607func lsp_truncate_file(path: *u8) -> i64
615func lsp_shadow_make(path: *u8, txt: *u8, n: i64, out: *u8, cap: i64) -> i64
638func lsp_child_analyze(path: *u8, symp: *u8) -> i64
757func lsp_analyze(slot: i64, sig_out: *i64) -> i64
799func lsp_starts(b: *u8, n: i64, at: i64, s: *u8) -> i64
813func lsp_caret_col(b: *u8, ls: i64, le: i64) -> i64
840func lsp_next_marker(b: *u8, n: i64, from: i64, kind_out: *i64) -> i64
860func lsp_parse_diags(b: *u8, n: i64, base: *u8, cap: i64,
972func lsp_sym_find(slot: i64, name: *u8, kind_out: *u8, kcap: i64,
1060func lsp_dec_at(b: *u8, s: i64, e: i64) -> i64
1075func lsp_send(body: *u8, n: i64) -> i64
1094func lsp_window_log(kind: i64, msg: *u8) -> i64
1107func lsp_reply_initialize(id: *u8) -> i64
1119func lsp_reply_null(id: *u8) -> i64
1128func lsp_reply_error(id: *u8, code: i64, msg: *u8) -> i64
1143func lsp_build_diags(slot: i64, out_cap_out: *i64, nd_out: *i64) -> *u8
1248func lsp_publish(slot: i64) -> i64
1257func lsp_slen_bounded(b: *u8, cap: i64) -> i64
1268func lsp_resolve(slot: i64, line0: i64, char0: i64,
1307func lsp_decl_line(slot: i64, path: *u8, line: i64, out: *u8, cap: i64, trim: i64) -> i64
1341func lsp_handle_definition(id: *u8, slot: i64, line0: i64, char0: i64) -> i64
1390func lsp_handle_hover(id: *u8, slot: i64, line0: i64, char0: i64) -> i64
1444func lsp_get_id_raw(b: *u8, n: i64, out: *u8, cap: i64) -> i64
1487func lsp_read_header(clen_out: *i64) -> i64
1539func lsp_read_body(n: i64) -> *u8
1554func lsp_params_pos(b: *u8, n: i64, l_out: *i64, c_out: *i64) -> i64
1568func lsp_dispatch(b: *u8, n: i64) -> i64
1656func lsp_serve() -> i64
1683func lsp_oneshot_load(path: *u8) -> i64
1696func lsp_mode_diag(path: *u8) -> i64
1710func lsp_mode_symbols(path: *u8) -> i64
1731func lsp_usage() -> i64
1742func main(argc: i64, argv: *i64) -> i64