aboutsummaryrefslogtreecommitdiff
path: root/src/lsp
diff options
context:
space:
mode:
authorGravatar zinc <zinc@downsta.ir> 2026-10-14 10:42:28 +0000
committerGravatar zinc <zinc@downsta.ir> 2026-10-14 10:42:28 +0000
commitea052eab91b304459ddf64281fc93fc152597412 (patch)
tree8dcd378d6634626dd2529c2aef684890999de963 /src/lsp
parenttodo: the spec verifier restarted from the first agent's partial work (diff)
parentfix std hover, full capture terminator, bare static calls, void main in run-o... (diff)
Merge four small fixes: std hovers, capture terminator, bare static calls, void main; todo updated
Diffstat (limited to 'src/lsp')
-rw-r--r--src/lsp/server.zc40
1 files changed, 34 insertions, 6 deletions
diff --git a/src/lsp/server.zc b/src/lsp/server.zc
index afa8de4..a43f910 100644
--- a/src/lsp/server.zc
+++ b/src/lsp/server.zc
@@ -1761,6 +1761,12 @@ int hover_method(int i) {
if (!found) ls = le + 1;
}
if (!found) return 0;
+ return hover_method_at(i, sg);
+}
+// the markdown of the method whose signature starts at byte sg of document i: the
+// signature up to the body, a ; or the end of the line, then the docs above it
+int hover_method_at(int i, int sg) {
+ int base = doff[i], size = dsize[i], k, se;
// the signature: up to the body, a ; or the end of the line
se = sg;
while (se < size && dc(base, se) != 10 && dc(base, se) != '{' && dc(base, se) != ';') se++;
@@ -1919,17 +1925,24 @@ int hover_global(int i, int kind) {
r = rs_find(hoff);
if (r >= 0 && run.rsrec[r * run.RS_W + 1] == run.RS_SYM && run.rsrec[r * run.RS_W + 3] >= 0 && kind != 2) {
s = run.rsrec[r * run.RS_W + 3];
- if (run.skind[s] != run.K_KW && bs_find(run.sname[s])) { hover_fill(bs_load(bs_k)); return hn; }
+ if (run.skind[s] != run.K_KW && bs_find(run.sname[s])) { bs_hover(); return hn; }
}
if (kind != 2) { kt = kwtext(); if (kt) return kw_put(kt); }
- if (kind == 1) { if (bs_find(hname)) { hover_fill(bs_load(bs_k)); return hn; } hover_blob(i); return hn; }
+ if (kind == 1) { if (bs_find(hname)) { bs_hover(); return hn; } hover_blob(i); return hn; }
if (hover_scan(i)) { hover_fill(i); return hn; }
if (hover_method(i)) return hn;
if (kind == 0 && hover_local(i)) return hn;
- if (kind != 2 && bs_find(hname)) { hover_fill(bs_load(bs_k)); return hn; }
+ if (kind != 2 && bs_find(hname)) { bs_hover(); return hn; }
hover_blob(i);
return hn;
}
+// is symbol s declared in an embedded library source (the text of std or icon, included
+// from tinyvm:std.zc and tinyvm:icon.zc)? such a symbol is a user symbol to the compiler
+// (rs_sym sets 16 for it) but its text is not in the document, so hover looks it up by
+// its qualified name in the library source, as it does for the runtime.
+int hover_embedded_sym(int s) {
+ return s >= 0 && run.sdsrc && run.sdsrc[s] && bs_name(run.sdsrc[s]) && bs_source(run.sdsrc[s]) >= 0;
+}
// the hover at the cursor. the compiler's record of the name decides what it
// is: a local is its declaration, a parameter the header that names it, and a
// symbol is looked up as that kind of symbol. a name with no record is found by
@@ -1950,7 +1963,9 @@ int do_hover(int i) {
else if (k == run.RS_FIELD && v >= 0) hover_named(i, v, 4);
else if (k == run.RS_LOCAL) hover_local(i);
else if (k == run.RS_SYM) {
- if ((v & 15) == run.K_GVAR || (v & 15) == run.K_GARR) {
+ // a symbol from an embedded library source (std, icon) is above the user's symbols but is not in the document: its declaration is found in that source by its qualified name
+ if ((v & 16) && hover_embedded_sym(run.rsrec[r * run.RS_W + 3])) hover_global(i, 1);
+ else if ((v & 15) == run.K_GVAR || (v & 15) == run.K_GARR) {
s = run.rsrec[r * run.RS_W + 3]; q = 0; o = 0 - 1;
while (q < run.rsn) { if (run.rsrec[q * run.RS_W + 3] == s && lt_find(run.rsrec[q * run.RS_W]) >= 0) { o = run.rsrec[q * run.RS_W]; break; } q++; }
if (o >= 0) hover_named(i, o, 3); else if (v & 16) hover_global(i, 2); else hover_global(i, 1);
@@ -2261,16 +2276,29 @@ int bs_method(int dd, char* name, int dot) {
}
return 0 - 1;
}
+// did the last bs_find_in hit find a method of a struct (bs_off is its name), not a top-level declaration
+int bs_meth;
+// the hover of the declaration the last successful bs_find found: a method by its line, anything else
+// by the scan that found it
+int bs_hover() {
+ int dd = bs_load(bs_k), q;
+ if (!bs_meth) return hover_fill(dd);
+ q = bs_off;
+ while (q > 0 && dc(doff[dd], q - 1) != 10) q--;
+ while (q < bs_off && (dc(doff[dd], q) == 32 || dc(doff[dd], q) == 9)) q++;
+ hn = 0; hover_method_at(dd, q);
+ return hn;
+}
// locate a declaration inside one source, after removing its module prefix.
int bs_find_in(int k, char* name) {
int n = 0, dot = -1, o, dd = bs_load(k);
while (name[n]) { if (name[n] == '.' && dot < 0) dot = n; n++; }
if (dot > 0 && name[dot + 1]) {
o = bs_method(dd, name, dot);
- if (o >= 0) { bs_k = k; bs_off = o; return 1; }
+ if (o >= 0) { bs_k = k; bs_off = o; bs_meth = 1; return 1; }
} else if (dot < 0) {
set_hname(name);
- if (hover_scan(dd)) { bs_k = k; bs_off = decl_off(doff[dd], hdl, hdle); return 1; }
+ if (hover_scan(dd)) { bs_k = k; bs_off = decl_off(doff[dd], hdl, hdle); bs_meth = 0; return 1; }
}
return 0;
}