Skip to main content

nodejs/
lsp.rs

1//! Builtin / keyword / method corpus for offline documentation.
2//!
3//! Single source of truth for the reference manual (`gen-docs` → `docs/reference.html`).
4//! Every entry mirrors something the runtime actually recognizes:
5//!   * "Keyword"      → the `KEYWORDS` set in `parser.rs` (plus the operator
6//!     keywords `typeof`/`void`/`delete`/`instanceof`/`in`/`new`/`this`).
7//!   * "Global"       → the global identifiers resolved in `builtins.rs`
8//!     (`undefined`/`NaN`/`Infinity`/`globalThis`) and the free functions /
9//!     constructors in its dispatch table (`parseInt`, `parseFloat`, `isNaN`,
10//!     `isFinite`, `String`, `Number`, `Boolean`, `Array`, `Error`, …).
11//!   * "console"      → `console.log`/`error`/`warn`/`info`/`debug`.
12//!   * "Math"/"JSON"/"Object"/"Number"/"String static"/"Array static" → the
13//!     namespace dispatch arms in `builtins.rs` (`call_builtin`, `call_math`,
14//!     the `Math.*` const table, `Object.*`, `Number.*`, `Array.*`).
15//!   * "Array method"/"String method"/"Number method" → the per-type dispatch
16//!     tables (`array_method`, `string_method`, and the number-method arms).
17//!
18//! Only names the crate implements appear here — no classes, regex, Map/Set,
19//! generators, or modules, none of which the lexer/parser/builtins support.
20
21/// The builtin corpus: (name, chapter, one-line doc, runnable example).
22const CORPUS: &[(&str, &str, &str, &str)] = &[
23    // ── Keyword ──
24    (
25        "var",
26        "Keyword",
27        "declare a function-scoped (hoisted) variable",
28        "var x = 1; x   // => 1",
29    ),
30    (
31        "let",
32        "Keyword",
33        "declare a block-scoped variable",
34        "let x = 2; x   // => 2",
35    ),
36    (
37        "const",
38        "Keyword",
39        "declare a block-scoped binding that cannot be reassigned",
40        "const x = 3; x   // => 3",
41    ),
42    (
43        "function",
44        "Keyword",
45        "define a function (declaration or expression)",
46        "function f() { return 9; } f()   // => 9",
47    ),
48    (
49        "return",
50        "Keyword",
51        "return a value from the current function (undefined if omitted)",
52        "(function () { return 7; })()   // => 7",
53    ),
54    (
55        "if",
56        "Keyword",
57        "conditional branch on a truthy test",
58        "let x; if (true) x = 1; x   // => 1",
59    ),
60    (
61        "else",
62        "Keyword",
63        "fallback branch of an if",
64        "let x; if (false) x = 1; else x = 2; x   // => 2",
65    ),
66    (
67        "while",
68        "Keyword",
69        "loop while the condition is truthy",
70        "let i = 0; while (i < 3) i++; i   // => 3",
71    ),
72    (
73        "do",
74        "Keyword",
75        "do/while loop: run the body once, then repeat while truthy",
76        "let i = 0; do { i++; } while (i < 3); i   // => 3",
77    ),
78    (
79        "for",
80        "Keyword",
81        "C-style loop, or for/of and for/in iteration",
82        "let s = 0; for (let i = 0; i < 3; i++) s += i; s   // => 3",
83    ),
84    (
85        "of",
86        "Keyword",
87        "iterate values of an iterable: `for (x of iterable)`",
88        "let s = 0; for (const n of [1, 2, 3]) s += n; s   // => 6",
89    ),
90    (
91        "in",
92        "Keyword",
93        "for/in key iteration, and the property-membership operator",
94        "\"a\" in { a: 1 }   // => true",
95    ),
96    (
97        "switch",
98        "Keyword",
99        "multi-way branch on a discriminant with case labels",
100        "let x; switch (2) { case 2: x = \"b\"; break; } x   // => 'b'",
101    ),
102    (
103        "case",
104        "Keyword",
105        "a labeled branch inside a switch",
106        "let x; switch (1) { case 1: x = \"a\"; } x   // => 'a'",
107    ),
108    (
109        "default",
110        "Keyword",
111        "the fallback branch of a switch",
112        "let x; switch (9) { default: x = \"d\"; } x   // => 'd'",
113    ),
114    (
115        "break",
116        "Keyword",
117        "exit the nearest enclosing loop or switch",
118        "let x; for (const n of [1, 2, 3]) { if (n === 2) break; x = n; } x   // => 1",
119    ),
120    (
121        "continue",
122        "Keyword",
123        "skip to the next iteration of the nearest loop",
124        "let s = 0; for (const n of [1, 2, 3]) { if (n === 2) continue; s += n; } s   // => 4",
125    ),
126    (
127        "new",
128        "Keyword",
129        "construct an instance: `new Ctor(args)`",
130        "new Error(\"boom\").message   // => 'boom'",
131    ),
132    (
133        "this",
134        "Keyword",
135        "the receiver of the current call",
136        "({ n: 5, get() { return this.n; } }).get()   // => 5",
137    ),
138    (
139        "typeof",
140        "Keyword",
141        "the type tag of a value as a string",
142        "typeof 3   // => 'number'",
143    ),
144    (
145        "void",
146        "Keyword",
147        "evaluate an expression and yield undefined",
148        "void 0   // => undefined",
149    ),
150    (
151        "delete",
152        "Keyword",
153        "remove a property from an object",
154        "const o = { a: 1 }; delete o.a; o.a   // => undefined",
155    ),
156    (
157        "instanceof",
158        "Keyword",
159        "test whether an object was built by a constructor",
160        "new Error(\"e\") instanceof Error   // => true",
161    ),
162    (
163        "throw",
164        "Keyword",
165        "raise an exception value",
166        "try { throw \"x\"; } catch (e) { e }   // => 'x'",
167    ),
168    (
169        "try",
170        "Keyword",
171        "run a block, routing exceptions to catch/finally",
172        "let x; try { x = 1; } finally { x = 2; } x   // => 2",
173    ),
174    (
175        "catch",
176        "Keyword",
177        "handle an exception thrown in the try block",
178        "try { null.x; } catch (e) { \"caught\" }   // => 'caught'",
179    ),
180    (
181        "finally",
182        "Keyword",
183        "block that always runs after try/catch",
184        "let x; try { x = 1; } finally { x = 3; } x   // => 3",
185    ),
186    (
187        "true",
188        "Keyword",
189        "the boolean true literal",
190        "true && 1   // => 1",
191    ),
192    (
193        "false",
194        "Keyword",
195        "the boolean false literal",
196        "false || 2   // => 2",
197    ),
198    (
199        "null",
200        "Keyword",
201        "the intentional-absence value",
202        "null ?? 5   // => 5",
203    ),
204    // ── Global ──
205    (
206        "undefined",
207        "Global",
208        "the value of an unassigned binding or missing property",
209        "typeof undefined   // => 'undefined'",
210    ),
211    (
212        "NaN",
213        "Global",
214        "the not-a-number float; unequal to itself",
215        "NaN === NaN   // => false",
216    ),
217    (
218        "Infinity",
219        "Global",
220        "the positive-infinity float",
221        "1 / 0 === Infinity   // => true",
222    ),
223    (
224        "globalThis",
225        "Global",
226        "the global object",
227        "typeof globalThis   // => 'object'",
228    ),
229    (
230        "parseInt",
231        "Global",
232        "parse the leading integer of a string (optional radix)",
233        "parseInt(\"42px\")   // => 42",
234    ),
235    (
236        "parseFloat",
237        "Global",
238        "parse the leading floating-point number of a string",
239        "parseFloat(\"3.14abc\")   // => 3.14",
240    ),
241    (
242        "isNaN",
243        "Global",
244        "true if the coerced number is NaN",
245        "isNaN(\"x\")   // => true",
246    ),
247    (
248        "isFinite",
249        "Global",
250        "true if the coerced number is finite",
251        "isFinite(10)   // => true",
252    ),
253    (
254        "String",
255        "Global",
256        "convert a value to its string form",
257        "String(123)   // => '123'",
258    ),
259    (
260        "Number",
261        "Global",
262        "convert a value to a number",
263        "Number(\"3.5\")   // => 3.5",
264    ),
265    (
266        "Boolean",
267        "Global",
268        "convert a value to its truthiness",
269        "Boolean(\"\")   // => false",
270    ),
271    (
272        "Array",
273        "Global",
274        "build an array from the given elements",
275        "Array(1, 2, 3)   // => [ 1, 2, 3 ]",
276    ),
277    (
278        "Error",
279        "Global",
280        "construct a generic error with a message",
281        "new Error(\"boom\").message   // => 'boom'",
282    ),
283    (
284        "TypeError",
285        "Global",
286        "construct a type error (name is 'TypeError')",
287        "new TypeError(\"bad\").name   // => 'TypeError'",
288    ),
289    (
290        "RangeError",
291        "Global",
292        "construct a range error (name is 'RangeError')",
293        "new RangeError(\"oob\").name   // => 'RangeError'",
294    ),
295    // ── console ──
296    (
297        "console.log",
298        "console",
299        "write args to stdout, space-separated, ending in a newline",
300        "console.log(\"hi\", 1)   // prints: hi 1",
301    ),
302    (
303        "console.error",
304        "console",
305        "write args to stderr",
306        "console.error(\"oops\")   // prints oops to stderr",
307    ),
308    (
309        "console.warn",
310        "console",
311        "write args to stderr (warning channel)",
312        "console.warn(\"careful\")   // prints careful to stderr",
313    ),
314    (
315        "console.info",
316        "console",
317        "write args to stdout (info channel)",
318        "console.info(\"note\")   // prints note",
319    ),
320    (
321        "console.debug",
322        "console",
323        "write args to stdout (debug channel)",
324        "console.debug(\"dbg\")   // prints dbg",
325    ),
326    // ── Math ──
327    (
328        "Math.PI",
329        "Math",
330        "the ratio of a circle's circumference to its diameter",
331        "Math.PI   // => 3.141592653589793",
332    ),
333    (
334        "Math.abs",
335        "Math",
336        "absolute value of a number",
337        "Math.abs(-5)   // => 5",
338    ),
339    (
340        "Math.floor",
341        "Math",
342        "largest integer <= x",
343        "Math.floor(3.7)   // => 3",
344    ),
345    (
346        "Math.ceil",
347        "Math",
348        "smallest integer >= x",
349        "Math.ceil(3.2)   // => 4",
350    ),
351    (
352        "Math.round",
353        "Math",
354        "round to the nearest integer (ties toward +Infinity)",
355        "Math.round(2.5)   // => 3",
356    ),
357    (
358        "Math.trunc",
359        "Math",
360        "the integer part of x, dropping any fraction",
361        "Math.trunc(-4.7)   // => -4",
362    ),
363    (
364        "Math.sign",
365        "Math",
366        "the sign of x as -1, 0, or 1",
367        "Math.sign(-8)   // => -1",
368    ),
369    (
370        "Math.sqrt",
371        "Math",
372        "square root of x",
373        "Math.sqrt(16)   // => 4",
374    ),
375    (
376        "Math.cbrt",
377        "Math",
378        "cube root of x",
379        "Math.cbrt(27)   // => 3",
380    ),
381    (
382        "Math.pow",
383        "Math",
384        "x raised to the power y",
385        "Math.pow(2, 10)   // => 1024",
386    ),
387    (
388        "Math.exp",
389        "Math",
390        "e raised to the power x",
391        "Math.exp(0)   // => 1",
392    ),
393    (
394        "Math.log",
395        "Math",
396        "natural logarithm of x",
397        "Math.log(1)   // => 0",
398    ),
399    (
400        "Math.max",
401        "Math",
402        "largest of the arguments",
403        "Math.max(3, 1, 2)   // => 3",
404    ),
405    (
406        "Math.min",
407        "Math",
408        "smallest of the arguments",
409        "Math.min(3, 1, 2)   // => 1",
410    ),
411    (
412        "Math.hypot",
413        "Math",
414        "the square root of the sum of squares of the arguments",
415        "Math.hypot(3, 4)   // => 5",
416    ),
417    (
418        "Math.sin",
419        "Math",
420        "sine of x (radians)",
421        "Math.sin(0)   // => 0",
422    ),
423    (
424        "Math.cos",
425        "Math",
426        "cosine of x (radians)",
427        "Math.cos(0)   // => 1",
428    ),
429    (
430        "Math.tan",
431        "Math",
432        "tangent of x (radians)",
433        "Math.tan(0)   // => 0",
434    ),
435    (
436        "Math.random",
437        "Math",
438        "a pseudo-random float in [0, 1)",
439        "Math.random() < 1   // => true",
440    ),
441    // ── JSON ──
442    (
443        "JSON.stringify",
444        "JSON",
445        "serialize a value to a JSON string",
446        "JSON.stringify({ a: 1 })   // => '{\"a\":1}'",
447    ),
448    (
449        "JSON.parse",
450        "JSON",
451        "parse a JSON string into a value",
452        "JSON.parse(\"[1,2]\")   // => [ 1, 2 ]",
453    ),
454    // ── Object ──
455    (
456        "Object.keys",
457        "Object",
458        "an array of an object's own enumerable keys",
459        "Object.keys({ a: 1, b: 2 })   // => [ 'a', 'b' ]",
460    ),
461    (
462        "Object.values",
463        "Object",
464        "an array of an object's own enumerable values",
465        "Object.values({ a: 1, b: 2 })   // => [ 1, 2 ]",
466    ),
467    (
468        "Object.entries",
469        "Object",
470        "an array of [key, value] pairs",
471        "Object.entries({ a: 1 })   // => [ [ 'a', 1 ] ]",
472    ),
473    (
474        "Object.assign",
475        "Object",
476        "copy source properties onto a target object (in place)",
477        "Object.assign({ a: 1 }, { b: 2 })   // => { a: 1, b: 2 }",
478    ),
479    (
480        "Object.fromEntries",
481        "Object",
482        "build an object from [key, value] pairs",
483        "Object.fromEntries([[\"a\", 1]])   // => { a: 1 }",
484    ),
485    (
486        "Object.freeze",
487        "Object",
488        "make an object immutable and return it",
489        "Object.freeze({ a: 1 }).a   // => 1",
490    ),
491    // ── Number ──
492    (
493        "Number.isInteger",
494        "Number",
495        "true if the value is an integer number",
496        "Number.isInteger(3)   // => true",
497    ),
498    (
499        "Number.isNaN",
500        "Number",
501        "true only if the value is exactly NaN (no coercion)",
502        "Number.isNaN(NaN)   // => true",
503    ),
504    (
505        "Number.isFinite",
506        "Number",
507        "true if the value is a finite number (no coercion)",
508        "Number.isFinite(10)   // => true",
509    ),
510    (
511        "Number.isSafeInteger",
512        "Number",
513        "true if the value is an integer within +/-2^53-1",
514        "Number.isSafeInteger(2 ** 53)   // => false",
515    ),
516    (
517        "Number.parseInt",
518        "Number",
519        "same as the global parseInt",
520        "Number.parseInt(\"20\", 10)   // => 20",
521    ),
522    (
523        "Number.parseFloat",
524        "Number",
525        "same as the global parseFloat",
526        "Number.parseFloat(\"1.5\")   // => 1.5",
527    ),
528    // ── String static ──
529    (
530        "String.fromCharCode",
531        "String static",
532        "a string built from the given UTF-16 code units",
533        "String.fromCharCode(65, 66)   // => 'AB'",
534    ),
535    // ── Array static ──
536    (
537        "Array.isArray",
538        "Array static",
539        "true if the value is an array",
540        "Array.isArray([1, 2])   // => true",
541    ),
542    (
543        "Array.from",
544        "Array static",
545        "build an array from an iterable or array-like",
546        "Array.from(\"ab\")   // => [ 'a', 'b' ]",
547    ),
548    (
549        "Array.of",
550        "Array static",
551        "build an array from the given arguments",
552        "Array.of(1, 2, 3)   // => [ 1, 2, 3 ]",
553    ),
554    // ── Array method ──
555    (
556        "push",
557        "Array method",
558        "append items to the end; returns the new length",
559        "const a = [1]; a.push(2); a   // => [ 1, 2 ]",
560    ),
561    (
562        "pop",
563        "Array method",
564        "remove and return the last item",
565        "[1, 2, 3].pop()   // => 3",
566    ),
567    (
568        "shift",
569        "Array method",
570        "remove and return the first item",
571        "[1, 2, 3].shift()   // => 1",
572    ),
573    (
574        "unshift",
575        "Array method",
576        "prepend items; returns the new length",
577        "const a = [2]; a.unshift(1); a   // => [ 1, 2 ]",
578    ),
579    (
580        "map",
581        "Array method",
582        "a new array of the results of calling fn on each item",
583        "[1, 2, 3].map(x => x * 2)   // => [ 2, 4, 6 ]",
584    ),
585    (
586        "filter",
587        "Array method",
588        "a new array of the items for which fn is truthy",
589        "[1, 2, 3, 4].filter(x => x % 2 === 0)   // => [ 2, 4 ]",
590    ),
591    (
592        "forEach",
593        "Array method",
594        "call fn on each item for effect; returns undefined",
595        "let s = 0; [1, 2, 3].forEach(x => s += x); s   // => 6",
596    ),
597    (
598        "reduce",
599        "Array method",
600        "fold the array to a single value with an accumulator",
601        "[1, 2, 3].reduce((a, b) => a + b, 0)   // => 6",
602    ),
603    (
604        "join",
605        "Array method",
606        "concatenate items into a string with a separator",
607        "[1, 2, 3].join(\"-\")   // => '1-2-3'",
608    ),
609    (
610        "slice",
611        "Array method",
612        "a shallow copy of a [start, end) sub-range",
613        "[1, 2, 3, 4].slice(1, 3)   // => [ 2, 3 ]",
614    ),
615    (
616        "splice",
617        "Array method",
618        "remove/insert items in place; returns the removed items",
619        "const a = [1, 2, 3]; a.splice(1, 1); a   // => [ 1, 3 ]",
620    ),
621    (
622        "concat",
623        "Array method",
624        "a new array joining this array with more arrays/values",
625        "[1].concat([2, 3])   // => [ 1, 2, 3 ]",
626    ),
627    (
628        "indexOf",
629        "Array method",
630        "index of the first matching item, or -1",
631        "[1, 2, 3].indexOf(2)   // => 1",
632    ),
633    (
634        "lastIndexOf",
635        "Array method",
636        "index of the last matching item, or -1",
637        "[1, 2, 1].lastIndexOf(1)   // => 2",
638    ),
639    (
640        "includes",
641        "Array method",
642        "true if the array contains the value",
643        "[1, 2, 3].includes(2)   // => true",
644    ),
645    (
646        "find",
647        "Array method",
648        "the first item for which fn is truthy, else undefined",
649        "[1, 2, 3].find(x => x > 1)   // => 2",
650    ),
651    (
652        "findIndex",
653        "Array method",
654        "the index of the first item for which fn is truthy, else -1",
655        "[1, 2, 3].findIndex(x => x > 1)   // => 1",
656    ),
657    (
658        "some",
659        "Array method",
660        "true if fn is truthy for any item",
661        "[1, 2, 3].some(x => x > 2)   // => true",
662    ),
663    (
664        "every",
665        "Array method",
666        "true if fn is truthy for every item",
667        "[1, 2, 3].every(x => x > 0)   // => true",
668    ),
669    (
670        "reverse",
671        "Array method",
672        "reverse the array in place",
673        "[1, 2, 3].reverse()   // => [ 3, 2, 1 ]",
674    ),
675    (
676        "sort",
677        "Array method",
678        "sort in place (default: by string order)",
679        "[3, 1, 2].sort()   // => [ 1, 2, 3 ]",
680    ),
681    (
682        "flat",
683        "Array method",
684        "a new array with sub-arrays flattened one level (or by depth)",
685        "[1, [2, [3]]].flat()   // => [ 1, 2, [ 3 ] ]",
686    ),
687    (
688        "flatMap",
689        "Array method",
690        "map each item then flatten the result one level",
691        "[1, 2].flatMap(x => [x, x])   // => [ 1, 1, 2, 2 ]",
692    ),
693    (
694        "fill",
695        "Array method",
696        "overwrite a range with a value in place",
697        "[1, 2, 3].fill(0)   // => [ 0, 0, 0 ]",
698    ),
699    (
700        "at",
701        "Array method",
702        "the item at an index, allowing negative indexing",
703        "[1, 2, 3].at(-1)   // => 3",
704    ),
705    // ── String method ──
706    (
707        "toUpperCase",
708        "String method",
709        "a copy with all cased characters uppercased",
710        "\"abc\".toUpperCase()   // => 'ABC'",
711    ),
712    (
713        "toLowerCase",
714        "String method",
715        "a copy with all cased characters lowercased",
716        "\"ABC\".toLowerCase()   // => 'abc'",
717    ),
718    (
719        "charAt",
720        "String method",
721        "the character at an index",
722        "\"hi\".charAt(1)   // => 'i'",
723    ),
724    (
725        "charCodeAt",
726        "String method",
727        "the UTF-16 code unit at an index",
728        "\"A\".charCodeAt(0)   // => 65",
729    ),
730    (
731        "codePointAt",
732        "String method",
733        "the Unicode code point at an index",
734        "\"A\".codePointAt(0)   // => 65",
735    ),
736    (
737        "slice",
738        "String method",
739        "a substring over a [start, end) range (negatives allowed)",
740        "\"hello\".slice(1, 3)   // => 'el'",
741    ),
742    (
743        "substring",
744        "String method",
745        "a substring over a [start, end) range (no negatives)",
746        "\"hello\".substring(0, 2)   // => 'he'",
747    ),
748    (
749        "split",
750        "String method",
751        "an array of substrings split on a separator",
752        "\"a,b,c\".split(\",\")   // => [ 'a', 'b', 'c' ]",
753    ),
754    (
755        "trim",
756        "String method",
757        "a copy with leading and trailing whitespace removed",
758        "\"  hi  \".trim()   // => 'hi'",
759    ),
760    (
761        "trimStart",
762        "String method",
763        "a copy with leading whitespace removed",
764        "\"  hi\".trimStart()   // => 'hi'",
765    ),
766    (
767        "trimEnd",
768        "String method",
769        "a copy with trailing whitespace removed",
770        "\"hi  \".trimEnd()   // => 'hi'",
771    ),
772    (
773        "replace",
774        "String method",
775        "a copy with the first match of a substring replaced",
776        "\"aaa\".replace(\"a\", \"b\")   // => 'baa'",
777    ),
778    (
779        "replaceAll",
780        "String method",
781        "a copy with every match of a substring replaced",
782        "\"aaa\".replaceAll(\"a\", \"b\")   // => 'bbb'",
783    ),
784    (
785        "repeat",
786        "String method",
787        "the string repeated n times",
788        "\"ab\".repeat(3)   // => 'ababab'",
789    ),
790    (
791        "startsWith",
792        "String method",
793        "true if the string starts with the prefix",
794        "\"hello\".startsWith(\"he\")   // => true",
795    ),
796    (
797        "endsWith",
798        "String method",
799        "true if the string ends with the suffix",
800        "\"hello\".endsWith(\"lo\")   // => true",
801    ),
802    (
803        "padStart",
804        "String method",
805        "pad on the left to a target length",
806        "\"5\".padStart(3, \"0\")   // => '005'",
807    ),
808    (
809        "padEnd",
810        "String method",
811        "pad on the right to a target length",
812        "\"5\".padEnd(3, \"0\")   // => '500'",
813    ),
814    // ── Number method ──
815    (
816        "toFixed",
817        "Number method",
818        "a fixed-point string with n digits after the decimal point",
819        "(3.14159).toFixed(2)   // => '3.14'",
820    ),
821    (
822        "toPrecision",
823        "Number method",
824        "a string with n significant digits",
825        "(123.456).toPrecision(4)   // => '123.5'",
826    ),
827    (
828        "toString",
829        "Number method",
830        "the string form of a number in an optional radix",
831        "(255).toString(16)   // => 'ff'",
832    ),
833];
834
835/// The builtin corpus, exposed for offline doc generation (`gen-docs`) and any
836/// editor tooling that wants the same (name, chapter, doc, example) rows.
837pub fn corpus() -> &'static [(&'static str, &'static str, &'static str, &'static str)] {
838    CORPUS
839}