rapydscript-ns 0.9.1 → 0.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/.agignore +1 -1
  2. package/.github/workflows/ci.yml +38 -38
  3. package/=template.pyj +5 -5
  4. package/CHANGELOG.md +3 -1
  5. package/HACKING.md +103 -103
  6. package/LICENSE +24 -24
  7. package/README.md +1 -1
  8. package/TODO.md +117 -0
  9. package/add-toc-to-readme +2 -2
  10. package/bin/export +75 -75
  11. package/bin/rapydscript +70 -70
  12. package/bin/web-repl-export +102 -102
  13. package/build +2 -2
  14. package/language-service/index.js +7 -7
  15. package/language-service/language-service.d.ts +1 -1
  16. package/package.json +6 -2
  17. package/publish.py +37 -37
  18. package/release/compiler.js +245 -230
  19. package/release/signatures.json +22 -22
  20. package/session.vim +4 -4
  21. package/setup.cfg +2 -2
  22. package/src/compiler.pyj +36 -36
  23. package/src/errors.pyj +30 -30
  24. package/src/lib/aes.pyj +646 -646
  25. package/src/lib/copy.pyj +120 -120
  26. package/src/lib/elementmaker.pyj +83 -83
  27. package/src/lib/encodings.pyj +126 -126
  28. package/src/lib/gettext.pyj +569 -569
  29. package/src/lib/itertools.pyj +580 -580
  30. package/src/lib/math.pyj +193 -193
  31. package/src/lib/operator.pyj +11 -11
  32. package/src/lib/pythonize.pyj +20 -20
  33. package/src/lib/random.pyj +118 -118
  34. package/src/lib/react.pyj +74 -74
  35. package/src/lib/traceback.pyj +63 -63
  36. package/src/lib/uuid.pyj +77 -77
  37. package/src/monaco-language-service/diagnostics.js +2 -2
  38. package/src/monaco-language-service/dts.js +550 -550
  39. package/src/monaco-language-service/index.js +2 -2
  40. package/src/output/comments.pyj +45 -45
  41. package/src/output/exceptions.pyj +201 -201
  42. package/src/output/jsx.pyj +164 -164
  43. package/src/output/loops.pyj +9 -0
  44. package/src/output/treeshake.pyj +182 -182
  45. package/src/output/utils.pyj +72 -72
  46. package/src/string_interpolation.pyj +72 -72
  47. package/src/unicode_aliases.pyj +576 -576
  48. package/src/utils.pyj +192 -192
  49. package/test/_import_one.pyj +37 -37
  50. package/test/_import_two/__init__.pyj +11 -11
  51. package/test/_import_two/level2/deep.pyj +4 -4
  52. package/test/_import_two/other.pyj +6 -6
  53. package/test/_import_two/sub.pyj +13 -13
  54. package/test/aes_vectors.pyj +421 -421
  55. package/test/annotations.pyj +80 -80
  56. package/test/decorators.pyj +77 -77
  57. package/test/docstrings.pyj +39 -39
  58. package/test/elementmaker_test.pyj +45 -45
  59. package/test/functions.pyj +151 -151
  60. package/test/generators.pyj +41 -41
  61. package/test/generic.pyj +370 -370
  62. package/test/imports.pyj +72 -72
  63. package/test/internationalization.pyj +73 -73
  64. package/test/lint.pyj +164 -164
  65. package/test/loops.pyj +85 -85
  66. package/test/numpy.pyj +734 -734
  67. package/test/omit_function_metadata.pyj +20 -20
  68. package/test/repl.pyj +121 -121
  69. package/test/scoped_flags.pyj +76 -76
  70. package/test/unit/index.js +66 -0
  71. package/test/unit/language-service-dts.js +543 -543
  72. package/test/unit/language-service-hover.js +455 -455
  73. package/test/unit/language-service.js +1 -1
  74. package/tools/compiler.d.ts +367 -0
  75. package/tools/completer.js +131 -131
  76. package/tools/gettext.js +185 -185
  77. package/tools/ini.js +65 -65
  78. package/tools/msgfmt.js +187 -187
  79. package/tools/repl.js +223 -223
  80. package/tools/test.js +118 -118
  81. package/tools/utils.js +128 -128
  82. package/tools/web_repl.js +95 -95
  83. package/try +41 -41
  84. package/web-repl/env.js +196 -196
  85. package/web-repl/index.html +163 -163
  86. package/web-repl/prism.css +139 -139
  87. package/web-repl/prism.js +113 -113
  88. package/web-repl/rapydscript.js +224 -224
  89. package/web-repl/sha1.js +25 -25
@@ -1,455 +1,455 @@
1
- /*
2
- * test/unit/language-service-hover.js
3
- *
4
- * Unit tests for src/monaco-language-service/hover.js (Phase 5).
5
- *
6
- * Usage:
7
- * node test/unit/language-service-hover.js # run all tests
8
- * node test/unit/language-service-hover.js <test-name> # run a single test by name
9
- */
10
- "use strict";
11
-
12
- var assert = require("assert");
13
- var path = require("path");
14
- var url = require("url");
15
- var compiler_module = require("../../tools/compiler");
16
- var utils = require("../../tools/utils");
17
- var colored = utils.safe_colored;
18
-
19
- // ---------------------------------------------------------------------------
20
- // Helpers
21
- // ---------------------------------------------------------------------------
22
-
23
- function pos(line, col) { return { lineNumber: line, column: col }; }
24
-
25
- /** Return the first contents value string from a hover result. */
26
- function hover_text(result) {
27
- return result && result.contents && result.contents[0]
28
- ? result.contents[0].value
29
- : null;
30
- }
31
-
32
- // ---------------------------------------------------------------------------
33
- // Test definitions
34
- // ---------------------------------------------------------------------------
35
-
36
- function make_tests(HoverEngine, SourceAnalyzer, DtsRegistry, RS) {
37
-
38
- function make_engine(dts_registry) {
39
- return new HoverEngine(dts_registry || null, null);
40
- }
41
-
42
- function analyze(src) {
43
- return new SourceAnalyzer(RS).analyze(src, {});
44
- }
45
-
46
- var TESTS = [
47
-
48
- // ── Basic symbol lookup ───────────────────────────────────────────
49
-
50
- {
51
- name: "hover_function",
52
- description: "Hovering over a function name shows its signature",
53
- run: function () {
54
- var engine = make_engine();
55
- var scopeMap = analyze([
56
- "def add(x, y):",
57
- " return x + y",
58
- "z = add(1, 2)",
59
- "pass",
60
- ].join("\n"));
61
-
62
- var result = engine.getHover(scopeMap, pos(4, 1), "add");
63
- assert.ok(result, "expected hover result");
64
- var text = hover_text(result);
65
- assert.ok(text.indexOf("function") !== -1, "should mention 'function'");
66
- assert.ok(text.indexOf("add") !== -1, "should include function name");
67
- assert.ok(text.indexOf("x") !== -1, "should include param x");
68
- assert.ok(text.indexOf("y") !== -1, "should include param y");
69
- },
70
- },
71
-
72
- {
73
- name: "hover_class",
74
- description: "Hovering over a class name shows its kind",
75
- run: function () {
76
- var engine = make_engine();
77
- var scopeMap = analyze([
78
- "class Dog:",
79
- " def bark(self):",
80
- " return 'woof'",
81
- "d = Dog()",
82
- "pass",
83
- ].join("\n"));
84
-
85
- var result = engine.getHover(scopeMap, pos(5, 1), "Dog");
86
- assert.ok(result, "expected hover result");
87
- var text = hover_text(result);
88
- assert.ok(text.indexOf("class") !== -1, "should mention 'class'");
89
- assert.ok(text.indexOf("Dog") !== -1, "should include class name");
90
- },
91
- },
92
-
93
- {
94
- name: "hover_variable",
95
- description: "Hovering over a variable shows its kind",
96
- run: function () {
97
- var engine = make_engine();
98
- var scopeMap = analyze("my_var = 42\npass");
99
-
100
- var result = engine.getHover(scopeMap, pos(1, 1), "my_var");
101
- assert.ok(result, "expected hover result");
102
- var text = hover_text(result);
103
- assert.ok(text.indexOf("variable") !== -1, "should mention 'variable'");
104
- assert.ok(text.indexOf("my_var") !== -1, "should include var name");
105
- },
106
- },
107
-
108
- {
109
- name: "hover_import",
110
- description: "Hovering over an import name shows its kind",
111
- run: function () {
112
- var engine = make_engine();
113
- var scopeMap = analyze([
114
- "from math import sqrt",
115
- "x = sqrt(4)",
116
- "pass",
117
- ].join("\n"), {});
118
-
119
- var result = engine.getHover(scopeMap, pos(3, 1), "sqrt");
120
- assert.ok(result, "expected hover result");
121
- var text = hover_text(result);
122
- assert.ok(text.indexOf("import") !== -1, "should mention 'import'");
123
- assert.ok(text.indexOf("sqrt") !== -1, "should include symbol name");
124
- },
125
- },
126
-
127
- // ── Docstring in hover ────────────────────────────────────────────
128
-
129
- {
130
- name: "hover_with_docstring",
131
- description: "Hover includes the docstring when present",
132
- run: function () {
133
- var engine = make_engine();
134
- var scopeMap = analyze([
135
- "def greet(name):",
136
- ' """Say hello to someone."""',
137
- " return name",
138
- "x = greet('world')",
139
- "pass",
140
- ].join("\n"));
141
-
142
- var result = engine.getHover(scopeMap, pos(5, 1), "greet");
143
- assert.ok(result, "expected hover result");
144
- var text = hover_text(result);
145
- assert.ok(text.indexOf("Say hello") !== -1,
146
- "hover should include docstring: " + text);
147
- },
148
- },
149
-
150
- {
151
- name: "hover_no_docstring",
152
- description: "Hover works cleanly when no docstring is present",
153
- run: function () {
154
- var engine = make_engine();
155
- var scopeMap = analyze([
156
- "def plain(a):",
157
- " return a",
158
- "x = plain(1)",
159
- "pass",
160
- ].join("\n"));
161
-
162
- var result = engine.getHover(scopeMap, pos(4, 1), "plain");
163
- assert.ok(result, "expected hover result");
164
- var text = hover_text(result);
165
- assert.ok(text.indexOf("plain") !== -1, "should include function name");
166
- },
167
- },
168
-
169
- // ── Parameter display ─────────────────────────────────────────────
170
-
171
- {
172
- name: "hover_star_args",
173
- description: "Hover shows *args with asterisk in signature",
174
- run: function () {
175
- var engine = make_engine();
176
- var scopeMap = analyze([
177
- "def variadic(first, *rest):",
178
- " return first",
179
- "x = variadic(1)",
180
- "pass",
181
- ].join("\n"));
182
-
183
- var result = engine.getHover(scopeMap, pos(4, 1), "variadic");
184
- var text = hover_text(result);
185
- assert.ok(text.indexOf("*rest") !== -1, "should show *rest");
186
- },
187
- },
188
-
189
- {
190
- name: "hover_kwargs",
191
- description: "Hover shows **kwargs with double asterisk in signature",
192
- run: function () {
193
- var engine = make_engine();
194
- var scopeMap = analyze([
195
- "def configure(host, **opts):",
196
- " return host",
197
- "x = configure('localhost')",
198
- "pass",
199
- ].join("\n"));
200
-
201
- var result = engine.getHover(scopeMap, pos(4, 1), "configure");
202
- var text = hover_text(result);
203
- assert.ok(text.indexOf("**opts") !== -1, "should show **opts");
204
- },
205
- },
206
-
207
- // ── Null / unknown symbol cases ───────────────────────────────────
208
-
209
- {
210
- name: "hover_unknown_word",
211
- description: "Hover returns null for a word not in the ScopeMap",
212
- run: function () {
213
- var engine = make_engine();
214
- var scopeMap = analyze("x = 1\npass");
215
-
216
- var result = engine.getHover(scopeMap, pos(2, 1), "unknown_sym");
217
- assert.strictEqual(result, null, "unknown symbol → null");
218
- },
219
- },
220
-
221
- {
222
- name: "hover_null_scopemap",
223
- description: "Hover returns null when scopeMap is null",
224
- run: function () {
225
- var engine = make_engine();
226
- var result = engine.getHover(null, pos(1, 1), "foo");
227
- assert.strictEqual(result, null, "null scopeMap → null");
228
- },
229
- },
230
-
231
- {
232
- name: "hover_null_word",
233
- description: "Hover returns null when word is null",
234
- run: function () {
235
- var engine = make_engine();
236
- var scopeMap = analyze("x = 1\npass");
237
- var result = engine.getHover(scopeMap, pos(1, 1), null);
238
- assert.strictEqual(result, null, "null word → null");
239
- },
240
- },
241
-
242
- // ── Contents structure ────────────────────────────────────────────
243
-
244
- {
245
- name: "hover_contents_structure",
246
- description: "Hover result has a contents array with value strings",
247
- run: function () {
248
- var engine = make_engine();
249
- var scopeMap = analyze("my_val = 99\npass");
250
-
251
- var result = engine.getHover(scopeMap, pos(1, 1), "my_val");
252
- assert.ok(result, "expected hover result");
253
- assert.ok(Array.isArray(result.contents), "contents should be an array");
254
- assert.ok(result.contents.length > 0, "contents should not be empty");
255
- assert.strictEqual(typeof result.contents[0].value, "string",
256
- "contents[0].value should be a string");
257
- },
258
- },
259
-
260
- {
261
- name: "hover_code_block",
262
- description: "Hover signature is wrapped in a code block",
263
- run: function () {
264
- var engine = make_engine();
265
- var scopeMap = analyze([
266
- "def f(a):",
267
- " return a",
268
- "x = f(1)",
269
- "pass",
270
- ].join("\n"));
271
-
272
- var result = engine.getHover(scopeMap, pos(4, 1), "f");
273
- var text = hover_text(result);
274
- assert.ok(text.indexOf("```") !== -1, "signature should be in a code block");
275
- },
276
- },
277
-
278
- // ── DTS member hover via dot-chain ────────────────────────────────
279
-
280
- {
281
- name: "hover_dts_member_single_level",
282
- description: "Hovering 'hack' with line_before_word='ns.' shows NS.hack doc",
283
- run: function () {
284
- var reg = new DtsRegistry();
285
- reg.addDts("lib", [
286
- "interface NS {",
287
- " /** Hack a server to steal money. */",
288
- " hack(host: string): Promise<number>;",
289
- "}",
290
- "declare var ns: NS;",
291
- ].join("\n"));
292
- var engine = make_engine(reg);
293
- var result = engine.getHover(null, pos(1, 4), "hack", "ns.");
294
- assert.ok(result, "expected hover result");
295
- var text = hover_text(result);
296
- assert.ok(text.indexOf("hack") !== -1, "should include method name");
297
- assert.ok(text.indexOf("host") !== -1, "should include param");
298
- assert.ok(text.indexOf("Hack a server") !== -1, "should include JSDoc");
299
- },
300
- },
301
-
302
- {
303
- name: "hover_dts_member_multi_level",
304
- description: "Hovering 'purchaseNode' with 'ns.hacknet.' shows Hacknet.purchaseNode doc",
305
- run: function () {
306
- var reg = new DtsRegistry();
307
- reg.addDts("lib", [
308
- "interface Hacknet {",
309
- " /** Buy a new hacknet node. */",
310
- " purchaseNode(): number;",
311
- "}",
312
- "interface NS {",
313
- " readonly hacknet: Hacknet;",
314
- "}",
315
- "declare var ns: NS;",
316
- ].join("\n"));
317
- var engine = make_engine(reg);
318
- var result = engine.getHover(null, pos(1, 16), "purchaseNode", "ns.hacknet.");
319
- assert.ok(result, "expected hover result");
320
- var text = hover_text(result);
321
- assert.ok(text.indexOf("purchaseNode") !== -1, "should include method name");
322
- assert.ok(text.indexOf("Buy a new hacknet node") !== -1, "should include JSDoc");
323
- },
324
- },
325
-
326
- {
327
- name: "hover_dts_member_no_dot_falls_through",
328
- description: "No dot before word → falls through to global DTS lookup",
329
- run: function () {
330
- var reg = new DtsRegistry();
331
- reg.addDts("lib", "declare var ns: NS;");
332
- var engine = make_engine(reg);
333
- // 'ns' is a top-level global; no dot before it
334
- var result = engine.getHover(null, pos(1, 1), "ns", "");
335
- assert.ok(result, "expected hover for top-level 'ns'");
336
- var text = hover_text(result);
337
- assert.ok(text.indexOf("ns") !== -1, "should mention ns");
338
- },
339
- },
340
-
341
- {
342
- name: "hover_dts_member_unknown_path_returns_null",
343
- description: "Dot-chain hover on unknown path returns null",
344
- run: function () {
345
- var reg = new DtsRegistry();
346
- reg.addDts("lib", "declare var ns: NS;");
347
- var engine = make_engine(reg);
348
- // 'unknown.' is not a registered type
349
- var result = engine.getHover(null, pos(1, 9), "hack", "unknown.");
350
- assert.strictEqual(result, null, "unknown dot-chain path → null");
351
- },
352
- },
353
-
354
- // ── Method hover ──────────────────────────────────────────────────
355
-
356
- {
357
- name: "hover_method",
358
- description: "Hovering over a method inside a class shows method kind",
359
- run: function () {
360
- var engine = make_engine();
361
- var scopeMap = analyze([
362
- "class Calc:",
363
- " def square(self, n):",
364
- " return n * n",
365
- "c = Calc()",
366
- "pass",
367
- ].join("\n"));
368
-
369
- // 'square' is in the class frame; query inside the class range (line 2)
370
- var result = engine.getHover(scopeMap, pos(2, 5), "square");
371
- assert.ok(result, "expected hover result");
372
- var text = hover_text(result);
373
- assert.ok(text.indexOf("method") !== -1, "should mention 'method'");
374
- assert.ok(text.indexOf("square") !== -1, "should include method name");
375
- assert.ok(text.indexOf("self") !== -1, "should include self param");
376
- assert.ok(text.indexOf("n") !== -1, "should include n param");
377
- },
378
- },
379
-
380
- ];
381
-
382
- return TESTS;
383
- }
384
-
385
- // ---------------------------------------------------------------------------
386
- // Runner
387
- // ---------------------------------------------------------------------------
388
-
389
- function run_tests(TESTS, filter) {
390
- var tests = filter
391
- ? TESTS.filter(function (t) { return t.name === filter; })
392
- : TESTS;
393
-
394
- if (tests.length === 0) {
395
- console.error(colored("No test found: " + filter, "red"));
396
- process.exit(1);
397
- }
398
-
399
- var failures = [];
400
-
401
- tests.forEach(function (test) {
402
- try {
403
- test.run();
404
- console.log(colored("PASS " + test.name, "green") +
405
- " – " + test.description);
406
- } catch (e) {
407
- failures.push(test.name);
408
- var msg = e.message || String(e);
409
- console.log(colored("FAIL " + test.name, "red") +
410
- "\n " + msg + "\n");
411
- }
412
- });
413
-
414
- console.log("");
415
- if (failures.length) {
416
- console.log(colored(failures.length + " test(s) failed.", "red"));
417
- } else {
418
- console.log(colored("All " + tests.length + " language-service-hover tests passed!", "green"));
419
- }
420
- process.exit(failures.length ? 1 : 0);
421
- }
422
-
423
- // ---------------------------------------------------------------------------
424
- // Entry point
425
- // ---------------------------------------------------------------------------
426
-
427
- var hover_path = url.pathToFileURL(
428
- path.join(__dirname, "../../src/monaco-language-service/hover.js")
429
- ).href;
430
-
431
- var analyzer_path = url.pathToFileURL(
432
- path.join(__dirname, "../../src/monaco-language-service/analyzer.js")
433
- ).href;
434
-
435
- var dts_path = url.pathToFileURL(
436
- path.join(__dirname, "../../src/monaco-language-service/dts.js")
437
- ).href;
438
-
439
- var filter = process.argv[2] || null;
440
-
441
- Promise.all([
442
- import(hover_path),
443
- import(analyzer_path),
444
- import(dts_path),
445
- ]).then(function (mods) {
446
- var HoverEngine = mods[0].HoverEngine;
447
- var SourceAnalyzer = mods[1].SourceAnalyzer;
448
- var DtsRegistry = mods[2].DtsRegistry;
449
- var RS = compiler_module.create_compiler();
450
- var TESTS = make_tests(HoverEngine, SourceAnalyzer, DtsRegistry, RS);
451
- run_tests(TESTS, filter);
452
- }).catch(function (e) {
453
- console.error(colored("Failed to load hover module:", "red"), e);
454
- process.exit(1);
455
- });
1
+ /*
2
+ * test/unit/language-service-hover.js
3
+ *
4
+ * Unit tests for src/monaco-language-service/hover.js (Phase 5).
5
+ *
6
+ * Usage:
7
+ * node test/unit/language-service-hover.js # run all tests
8
+ * node test/unit/language-service-hover.js <test-name> # run a single test by name
9
+ */
10
+ "use strict";
11
+
12
+ var assert = require("assert");
13
+ var path = require("path");
14
+ var url = require("url");
15
+ var compiler_module = require("../../tools/compiler");
16
+ var utils = require("../../tools/utils");
17
+ var colored = utils.safe_colored;
18
+
19
+ // ---------------------------------------------------------------------------
20
+ // Helpers
21
+ // ---------------------------------------------------------------------------
22
+
23
+ function pos(line, col) { return { lineNumber: line, column: col }; }
24
+
25
+ /** Return the first contents value string from a hover result. */
26
+ function hover_text(result) {
27
+ return result && result.contents && result.contents[0]
28
+ ? result.contents[0].value
29
+ : null;
30
+ }
31
+
32
+ // ---------------------------------------------------------------------------
33
+ // Test definitions
34
+ // ---------------------------------------------------------------------------
35
+
36
+ function make_tests(HoverEngine, SourceAnalyzer, DtsRegistry, RS) {
37
+
38
+ function make_engine(dts_registry) {
39
+ return new HoverEngine(dts_registry || null, null);
40
+ }
41
+
42
+ function analyze(src) {
43
+ return new SourceAnalyzer(RS).analyze(src, {});
44
+ }
45
+
46
+ var TESTS = [
47
+
48
+ // ── Basic symbol lookup ───────────────────────────────────────────
49
+
50
+ {
51
+ name: "hover_function",
52
+ description: "Hovering over a function name shows its signature",
53
+ run: function () {
54
+ var engine = make_engine();
55
+ var scopeMap = analyze([
56
+ "def add(x, y):",
57
+ " return x + y",
58
+ "z = add(1, 2)",
59
+ "pass",
60
+ ].join("\n"));
61
+
62
+ var result = engine.getHover(scopeMap, pos(4, 1), "add");
63
+ assert.ok(result, "expected hover result");
64
+ var text = hover_text(result);
65
+ assert.ok(text.indexOf("function") !== -1, "should mention 'function'");
66
+ assert.ok(text.indexOf("add") !== -1, "should include function name");
67
+ assert.ok(text.indexOf("x") !== -1, "should include param x");
68
+ assert.ok(text.indexOf("y") !== -1, "should include param y");
69
+ },
70
+ },
71
+
72
+ {
73
+ name: "hover_class",
74
+ description: "Hovering over a class name shows its kind",
75
+ run: function () {
76
+ var engine = make_engine();
77
+ var scopeMap = analyze([
78
+ "class Dog:",
79
+ " def bark(self):",
80
+ " return 'woof'",
81
+ "d = Dog()",
82
+ "pass",
83
+ ].join("\n"));
84
+
85
+ var result = engine.getHover(scopeMap, pos(5, 1), "Dog");
86
+ assert.ok(result, "expected hover result");
87
+ var text = hover_text(result);
88
+ assert.ok(text.indexOf("class") !== -1, "should mention 'class'");
89
+ assert.ok(text.indexOf("Dog") !== -1, "should include class name");
90
+ },
91
+ },
92
+
93
+ {
94
+ name: "hover_variable",
95
+ description: "Hovering over a variable shows its kind",
96
+ run: function () {
97
+ var engine = make_engine();
98
+ var scopeMap = analyze("my_var = 42\npass");
99
+
100
+ var result = engine.getHover(scopeMap, pos(1, 1), "my_var");
101
+ assert.ok(result, "expected hover result");
102
+ var text = hover_text(result);
103
+ assert.ok(text.indexOf("variable") !== -1, "should mention 'variable'");
104
+ assert.ok(text.indexOf("my_var") !== -1, "should include var name");
105
+ },
106
+ },
107
+
108
+ {
109
+ name: "hover_import",
110
+ description: "Hovering over an import name shows its kind",
111
+ run: function () {
112
+ var engine = make_engine();
113
+ var scopeMap = analyze([
114
+ "from math import sqrt",
115
+ "x = sqrt(4)",
116
+ "pass",
117
+ ].join("\n"), {});
118
+
119
+ var result = engine.getHover(scopeMap, pos(3, 1), "sqrt");
120
+ assert.ok(result, "expected hover result");
121
+ var text = hover_text(result);
122
+ assert.ok(text.indexOf("import") !== -1, "should mention 'import'");
123
+ assert.ok(text.indexOf("sqrt") !== -1, "should include symbol name");
124
+ },
125
+ },
126
+
127
+ // ── Docstring in hover ────────────────────────────────────────────
128
+
129
+ {
130
+ name: "hover_with_docstring",
131
+ description: "Hover includes the docstring when present",
132
+ run: function () {
133
+ var engine = make_engine();
134
+ var scopeMap = analyze([
135
+ "def greet(name):",
136
+ ' """Say hello to someone."""',
137
+ " return name",
138
+ "x = greet('world')",
139
+ "pass",
140
+ ].join("\n"));
141
+
142
+ var result = engine.getHover(scopeMap, pos(5, 1), "greet");
143
+ assert.ok(result, "expected hover result");
144
+ var text = hover_text(result);
145
+ assert.ok(text.indexOf("Say hello") !== -1,
146
+ "hover should include docstring: " + text);
147
+ },
148
+ },
149
+
150
+ {
151
+ name: "hover_no_docstring",
152
+ description: "Hover works cleanly when no docstring is present",
153
+ run: function () {
154
+ var engine = make_engine();
155
+ var scopeMap = analyze([
156
+ "def plain(a):",
157
+ " return a",
158
+ "x = plain(1)",
159
+ "pass",
160
+ ].join("\n"));
161
+
162
+ var result = engine.getHover(scopeMap, pos(4, 1), "plain");
163
+ assert.ok(result, "expected hover result");
164
+ var text = hover_text(result);
165
+ assert.ok(text.indexOf("plain") !== -1, "should include function name");
166
+ },
167
+ },
168
+
169
+ // ── Parameter display ─────────────────────────────────────────────
170
+
171
+ {
172
+ name: "hover_star_args",
173
+ description: "Hover shows *args with asterisk in signature",
174
+ run: function () {
175
+ var engine = make_engine();
176
+ var scopeMap = analyze([
177
+ "def variadic(first, *rest):",
178
+ " return first",
179
+ "x = variadic(1)",
180
+ "pass",
181
+ ].join("\n"));
182
+
183
+ var result = engine.getHover(scopeMap, pos(4, 1), "variadic");
184
+ var text = hover_text(result);
185
+ assert.ok(text.indexOf("*rest") !== -1, "should show *rest");
186
+ },
187
+ },
188
+
189
+ {
190
+ name: "hover_kwargs",
191
+ description: "Hover shows **kwargs with double asterisk in signature",
192
+ run: function () {
193
+ var engine = make_engine();
194
+ var scopeMap = analyze([
195
+ "def configure(host, **opts):",
196
+ " return host",
197
+ "x = configure('localhost')",
198
+ "pass",
199
+ ].join("\n"));
200
+
201
+ var result = engine.getHover(scopeMap, pos(4, 1), "configure");
202
+ var text = hover_text(result);
203
+ assert.ok(text.indexOf("**opts") !== -1, "should show **opts");
204
+ },
205
+ },
206
+
207
+ // ── Null / unknown symbol cases ───────────────────────────────────
208
+
209
+ {
210
+ name: "hover_unknown_word",
211
+ description: "Hover returns null for a word not in the ScopeMap",
212
+ run: function () {
213
+ var engine = make_engine();
214
+ var scopeMap = analyze("x = 1\npass");
215
+
216
+ var result = engine.getHover(scopeMap, pos(2, 1), "unknown_sym");
217
+ assert.strictEqual(result, null, "unknown symbol → null");
218
+ },
219
+ },
220
+
221
+ {
222
+ name: "hover_null_scopemap",
223
+ description: "Hover returns null when scopeMap is null",
224
+ run: function () {
225
+ var engine = make_engine();
226
+ var result = engine.getHover(null, pos(1, 1), "foo");
227
+ assert.strictEqual(result, null, "null scopeMap → null");
228
+ },
229
+ },
230
+
231
+ {
232
+ name: "hover_null_word",
233
+ description: "Hover returns null when word is null",
234
+ run: function () {
235
+ var engine = make_engine();
236
+ var scopeMap = analyze("x = 1\npass");
237
+ var result = engine.getHover(scopeMap, pos(1, 1), null);
238
+ assert.strictEqual(result, null, "null word → null");
239
+ },
240
+ },
241
+
242
+ // ── Contents structure ────────────────────────────────────────────
243
+
244
+ {
245
+ name: "hover_contents_structure",
246
+ description: "Hover result has a contents array with value strings",
247
+ run: function () {
248
+ var engine = make_engine();
249
+ var scopeMap = analyze("my_val = 99\npass");
250
+
251
+ var result = engine.getHover(scopeMap, pos(1, 1), "my_val");
252
+ assert.ok(result, "expected hover result");
253
+ assert.ok(Array.isArray(result.contents), "contents should be an array");
254
+ assert.ok(result.contents.length > 0, "contents should not be empty");
255
+ assert.strictEqual(typeof result.contents[0].value, "string",
256
+ "contents[0].value should be a string");
257
+ },
258
+ },
259
+
260
+ {
261
+ name: "hover_code_block",
262
+ description: "Hover signature is wrapped in a code block",
263
+ run: function () {
264
+ var engine = make_engine();
265
+ var scopeMap = analyze([
266
+ "def f(a):",
267
+ " return a",
268
+ "x = f(1)",
269
+ "pass",
270
+ ].join("\n"));
271
+
272
+ var result = engine.getHover(scopeMap, pos(4, 1), "f");
273
+ var text = hover_text(result);
274
+ assert.ok(text.indexOf("```") !== -1, "signature should be in a code block");
275
+ },
276
+ },
277
+
278
+ // ── DTS member hover via dot-chain ────────────────────────────────
279
+
280
+ {
281
+ name: "hover_dts_member_single_level",
282
+ description: "Hovering 'hack' with line_before_word='ns.' shows NS.hack doc",
283
+ run: function () {
284
+ var reg = new DtsRegistry();
285
+ reg.addDts("lib", [
286
+ "interface NS {",
287
+ " /** Hack a server to steal money. */",
288
+ " hack(host: string): Promise<number>;",
289
+ "}",
290
+ "declare var ns: NS;",
291
+ ].join("\n"));
292
+ var engine = make_engine(reg);
293
+ var result = engine.getHover(null, pos(1, 4), "hack", "ns.");
294
+ assert.ok(result, "expected hover result");
295
+ var text = hover_text(result);
296
+ assert.ok(text.indexOf("hack") !== -1, "should include method name");
297
+ assert.ok(text.indexOf("host") !== -1, "should include param");
298
+ assert.ok(text.indexOf("Hack a server") !== -1, "should include JSDoc");
299
+ },
300
+ },
301
+
302
+ {
303
+ name: "hover_dts_member_multi_level",
304
+ description: "Hovering 'purchaseNode' with 'ns.hacknet.' shows Hacknet.purchaseNode doc",
305
+ run: function () {
306
+ var reg = new DtsRegistry();
307
+ reg.addDts("lib", [
308
+ "interface Hacknet {",
309
+ " /** Buy a new hacknet node. */",
310
+ " purchaseNode(): number;",
311
+ "}",
312
+ "interface NS {",
313
+ " readonly hacknet: Hacknet;",
314
+ "}",
315
+ "declare var ns: NS;",
316
+ ].join("\n"));
317
+ var engine = make_engine(reg);
318
+ var result = engine.getHover(null, pos(1, 16), "purchaseNode", "ns.hacknet.");
319
+ assert.ok(result, "expected hover result");
320
+ var text = hover_text(result);
321
+ assert.ok(text.indexOf("purchaseNode") !== -1, "should include method name");
322
+ assert.ok(text.indexOf("Buy a new hacknet node") !== -1, "should include JSDoc");
323
+ },
324
+ },
325
+
326
+ {
327
+ name: "hover_dts_member_no_dot_falls_through",
328
+ description: "No dot before word → falls through to global DTS lookup",
329
+ run: function () {
330
+ var reg = new DtsRegistry();
331
+ reg.addDts("lib", "declare var ns: NS;");
332
+ var engine = make_engine(reg);
333
+ // 'ns' is a top-level global; no dot before it
334
+ var result = engine.getHover(null, pos(1, 1), "ns", "");
335
+ assert.ok(result, "expected hover for top-level 'ns'");
336
+ var text = hover_text(result);
337
+ assert.ok(text.indexOf("ns") !== -1, "should mention ns");
338
+ },
339
+ },
340
+
341
+ {
342
+ name: "hover_dts_member_unknown_path_returns_null",
343
+ description: "Dot-chain hover on unknown path returns null",
344
+ run: function () {
345
+ var reg = new DtsRegistry();
346
+ reg.addDts("lib", "declare var ns: NS;");
347
+ var engine = make_engine(reg);
348
+ // 'unknown.' is not a registered type
349
+ var result = engine.getHover(null, pos(1, 9), "hack", "unknown.");
350
+ assert.strictEqual(result, null, "unknown dot-chain path → null");
351
+ },
352
+ },
353
+
354
+ // ── Method hover ──────────────────────────────────────────────────
355
+
356
+ {
357
+ name: "hover_method",
358
+ description: "Hovering over a method inside a class shows method kind",
359
+ run: function () {
360
+ var engine = make_engine();
361
+ var scopeMap = analyze([
362
+ "class Calc:",
363
+ " def square(self, n):",
364
+ " return n * n",
365
+ "c = Calc()",
366
+ "pass",
367
+ ].join("\n"));
368
+
369
+ // 'square' is in the class frame; query inside the class range (line 2)
370
+ var result = engine.getHover(scopeMap, pos(2, 5), "square");
371
+ assert.ok(result, "expected hover result");
372
+ var text = hover_text(result);
373
+ assert.ok(text.indexOf("method") !== -1, "should mention 'method'");
374
+ assert.ok(text.indexOf("square") !== -1, "should include method name");
375
+ assert.ok(text.indexOf("self") !== -1, "should include self param");
376
+ assert.ok(text.indexOf("n") !== -1, "should include n param");
377
+ },
378
+ },
379
+
380
+ ];
381
+
382
+ return TESTS;
383
+ }
384
+
385
+ // ---------------------------------------------------------------------------
386
+ // Runner
387
+ // ---------------------------------------------------------------------------
388
+
389
+ function run_tests(TESTS, filter) {
390
+ var tests = filter
391
+ ? TESTS.filter(function (t) { return t.name === filter; })
392
+ : TESTS;
393
+
394
+ if (tests.length === 0) {
395
+ console.error(colored("No test found: " + filter, "red"));
396
+ process.exit(1);
397
+ }
398
+
399
+ var failures = [];
400
+
401
+ tests.forEach(function (test) {
402
+ try {
403
+ test.run();
404
+ console.log(colored("PASS " + test.name, "green") +
405
+ " – " + test.description);
406
+ } catch (e) {
407
+ failures.push(test.name);
408
+ var msg = e.message || String(e);
409
+ console.log(colored("FAIL " + test.name, "red") +
410
+ "\n " + msg + "\n");
411
+ }
412
+ });
413
+
414
+ console.log("");
415
+ if (failures.length) {
416
+ console.log(colored(failures.length + " test(s) failed.", "red"));
417
+ } else {
418
+ console.log(colored("All " + tests.length + " language-service-hover tests passed!", "green"));
419
+ }
420
+ process.exit(failures.length ? 1 : 0);
421
+ }
422
+
423
+ // ---------------------------------------------------------------------------
424
+ // Entry point
425
+ // ---------------------------------------------------------------------------
426
+
427
+ var hover_path = url.pathToFileURL(
428
+ path.join(__dirname, "../../src/monaco-language-service/hover.js")
429
+ ).href;
430
+
431
+ var analyzer_path = url.pathToFileURL(
432
+ path.join(__dirname, "../../src/monaco-language-service/analyzer.js")
433
+ ).href;
434
+
435
+ var dts_path = url.pathToFileURL(
436
+ path.join(__dirname, "../../src/monaco-language-service/dts.js")
437
+ ).href;
438
+
439
+ var filter = process.argv[2] || null;
440
+
441
+ Promise.all([
442
+ import(hover_path),
443
+ import(analyzer_path),
444
+ import(dts_path),
445
+ ]).then(function (mods) {
446
+ var HoverEngine = mods[0].HoverEngine;
447
+ var SourceAnalyzer = mods[1].SourceAnalyzer;
448
+ var DtsRegistry = mods[2].DtsRegistry;
449
+ var RS = compiler_module.create_compiler();
450
+ var TESTS = make_tests(HoverEngine, SourceAnalyzer, DtsRegistry, RS);
451
+ run_tests(TESTS, filter);
452
+ }).catch(function (e) {
453
+ console.error(colored("Failed to load hover module:", "red"), e);
454
+ process.exit(1);
455
+ });