rapydscript-ns 0.8.0

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 (144) hide show
  1. package/.agignore +1 -0
  2. package/.gitattributes +4 -0
  3. package/.github/workflows/ci.yml +38 -0
  4. package/.github/workflows/web-repl-page-deploy.yml +42 -0
  5. package/=template.pyj +5 -0
  6. package/CHANGELOG.md +456 -0
  7. package/CONTRIBUTORS +13 -0
  8. package/HACKING.md +103 -0
  9. package/LICENSE +24 -0
  10. package/README.md +2512 -0
  11. package/TODO.md +327 -0
  12. package/add-toc-to-readme +2 -0
  13. package/bin/export +75 -0
  14. package/bin/rapydscript +70 -0
  15. package/bin/web-repl-export +102 -0
  16. package/build +3 -0
  17. package/package.json +46 -0
  18. package/publish.py +37 -0
  19. package/release/baselib-plain-pretty.js +4370 -0
  20. package/release/baselib-plain-ugly.js +3 -0
  21. package/release/compiler.js +18394 -0
  22. package/release/signatures.json +31 -0
  23. package/session.vim +4 -0
  24. package/setup.cfg +2 -0
  25. package/src/ast.pyj +1356 -0
  26. package/src/baselib-builtins.pyj +279 -0
  27. package/src/baselib-containers.pyj +723 -0
  28. package/src/baselib-errors.pyj +37 -0
  29. package/src/baselib-internal.pyj +421 -0
  30. package/src/baselib-itertools.pyj +97 -0
  31. package/src/baselib-str.pyj +798 -0
  32. package/src/compiler.pyj +36 -0
  33. package/src/errors.pyj +30 -0
  34. package/src/lib/aes.pyj +646 -0
  35. package/src/lib/collections.pyj +695 -0
  36. package/src/lib/elementmaker.pyj +83 -0
  37. package/src/lib/encodings.pyj +126 -0
  38. package/src/lib/functools.pyj +148 -0
  39. package/src/lib/gettext.pyj +569 -0
  40. package/src/lib/itertools.pyj +580 -0
  41. package/src/lib/math.pyj +193 -0
  42. package/src/lib/numpy.pyj +2101 -0
  43. package/src/lib/operator.pyj +11 -0
  44. package/src/lib/pythonize.pyj +20 -0
  45. package/src/lib/random.pyj +118 -0
  46. package/src/lib/re.pyj +470 -0
  47. package/src/lib/traceback.pyj +63 -0
  48. package/src/lib/uuid.pyj +77 -0
  49. package/src/monaco-language-service/analyzer.js +526 -0
  50. package/src/monaco-language-service/builtins.js +543 -0
  51. package/src/monaco-language-service/completions.js +498 -0
  52. package/src/monaco-language-service/diagnostics.js +643 -0
  53. package/src/monaco-language-service/dts.js +550 -0
  54. package/src/monaco-language-service/hover.js +121 -0
  55. package/src/monaco-language-service/index.js +386 -0
  56. package/src/monaco-language-service/scope.js +162 -0
  57. package/src/monaco-language-service/signature.js +144 -0
  58. package/src/output/__init__.pyj +0 -0
  59. package/src/output/classes.pyj +296 -0
  60. package/src/output/codegen.pyj +492 -0
  61. package/src/output/comments.pyj +45 -0
  62. package/src/output/exceptions.pyj +105 -0
  63. package/src/output/functions.pyj +491 -0
  64. package/src/output/literals.pyj +109 -0
  65. package/src/output/loops.pyj +444 -0
  66. package/src/output/modules.pyj +329 -0
  67. package/src/output/operators.pyj +429 -0
  68. package/src/output/statements.pyj +463 -0
  69. package/src/output/stream.pyj +309 -0
  70. package/src/output/treeshake.pyj +182 -0
  71. package/src/output/utils.pyj +72 -0
  72. package/src/parse.pyj +3106 -0
  73. package/src/string_interpolation.pyj +72 -0
  74. package/src/tokenizer.pyj +702 -0
  75. package/src/unicode_aliases.pyj +576 -0
  76. package/src/utils.pyj +192 -0
  77. package/test/_import_one.pyj +37 -0
  78. package/test/_import_two/__init__.pyj +11 -0
  79. package/test/_import_two/level2/__init__.pyj +0 -0
  80. package/test/_import_two/level2/deep.pyj +4 -0
  81. package/test/_import_two/other.pyj +6 -0
  82. package/test/_import_two/sub.pyj +13 -0
  83. package/test/aes_vectors.pyj +421 -0
  84. package/test/annotations.pyj +80 -0
  85. package/test/baselib.pyj +319 -0
  86. package/test/classes.pyj +452 -0
  87. package/test/collections.pyj +152 -0
  88. package/test/decorators.pyj +77 -0
  89. package/test/dict_spread.pyj +76 -0
  90. package/test/docstrings.pyj +39 -0
  91. package/test/elementmaker_test.pyj +45 -0
  92. package/test/ellipsis.pyj +49 -0
  93. package/test/functions.pyj +151 -0
  94. package/test/generators.pyj +41 -0
  95. package/test/generic.pyj +370 -0
  96. package/test/imports.pyj +72 -0
  97. package/test/internationalization.pyj +73 -0
  98. package/test/lint.pyj +164 -0
  99. package/test/loops.pyj +85 -0
  100. package/test/numpy.pyj +734 -0
  101. package/test/omit_function_metadata.pyj +20 -0
  102. package/test/regexp.pyj +55 -0
  103. package/test/repl.pyj +121 -0
  104. package/test/scoped_flags.pyj +76 -0
  105. package/test/starargs.pyj +506 -0
  106. package/test/starred_assign.pyj +104 -0
  107. package/test/str.pyj +198 -0
  108. package/test/subscript_tuple.pyj +53 -0
  109. package/test/unit/fixtures/fibonacci_expected.js +46 -0
  110. package/test/unit/index.js +2989 -0
  111. package/test/unit/language-service-builtins.js +815 -0
  112. package/test/unit/language-service-completions.js +1067 -0
  113. package/test/unit/language-service-dts.js +543 -0
  114. package/test/unit/language-service-hover.js +455 -0
  115. package/test/unit/language-service-scope.js +833 -0
  116. package/test/unit/language-service-signature.js +458 -0
  117. package/test/unit/language-service.js +705 -0
  118. package/test/unit/run-language-service.js +41 -0
  119. package/test/unit/web-repl.js +484 -0
  120. package/tools/build-language-service.js +190 -0
  121. package/tools/cli.js +547 -0
  122. package/tools/compile.js +219 -0
  123. package/tools/compiler.js +108 -0
  124. package/tools/completer.js +131 -0
  125. package/tools/embedded_compiler.js +251 -0
  126. package/tools/export.js +316 -0
  127. package/tools/gettext.js +185 -0
  128. package/tools/ini.js +65 -0
  129. package/tools/lint.js +705 -0
  130. package/tools/msgfmt.js +187 -0
  131. package/tools/repl.js +223 -0
  132. package/tools/self.js +162 -0
  133. package/tools/test.js +118 -0
  134. package/tools/utils.js +128 -0
  135. package/tools/web_repl.js +95 -0
  136. package/try +41 -0
  137. package/web-repl/env.js +74 -0
  138. package/web-repl/index.html +163 -0
  139. package/web-repl/language-service.js +4084 -0
  140. package/web-repl/main.js +254 -0
  141. package/web-repl/prism.css +139 -0
  142. package/web-repl/prism.js +113 -0
  143. package/web-repl/rapydscript.js +435 -0
  144. package/web-repl/sha1.js +25 -0
@@ -0,0 +1,815 @@
1
+ /*
2
+ * test/unit/language-service-builtins.js
3
+ *
4
+ * Unit tests for src/monaco-language-service/builtins.js (Phase 7).
5
+ * Also tests the integration of BuiltinsRegistry into HoverEngine,
6
+ * SignatureHelpEngine, and CompletionEngine.
7
+ *
8
+ * Usage:
9
+ * node test/unit/language-service-builtins.js # run all tests
10
+ * node test/unit/language-service-builtins.js <test-name> # run single test
11
+ */
12
+ "use strict";
13
+
14
+ var assert = require("assert");
15
+ var path = require("path");
16
+ var url = require("url");
17
+ var compiler_module = require("../../tools/compiler");
18
+ var utils = require("../../tools/utils");
19
+ var colored = utils.safe_colored;
20
+
21
+ // ---------------------------------------------------------------------------
22
+ // Mock Monaco CompletionItemKind
23
+ // ---------------------------------------------------------------------------
24
+
25
+ var MockKind = {
26
+ Method: 0,
27
+ Function: 1,
28
+ Class: 5,
29
+ Variable: 6,
30
+ Module: 8,
31
+ Property: 9,
32
+ };
33
+
34
+ function pos(line, col) { return { lineNumber: line, column: col }; }
35
+
36
+ // ---------------------------------------------------------------------------
37
+ // Test definitions
38
+ // ---------------------------------------------------------------------------
39
+
40
+ function make_tests(BuiltinsRegistry, BuiltinInfo, HoverEngine, SignatureHelpEngine,
41
+ CompletionEngine, detect_call_context, SourceAnalyzer, RS) {
42
+
43
+ var TESTS = [
44
+
45
+ // ── BuiltinsRegistry: get ─────────────────────────────────────────
46
+
47
+ {
48
+ name: "get_known_builtin",
49
+ description: "get() returns a BuiltinInfo for a known built-in",
50
+ run: function () {
51
+ var reg = new BuiltinsRegistry();
52
+ var bi = reg.get('len');
53
+ assert.ok(bi, 'len should be registered');
54
+ assert.strictEqual(bi.name, 'len');
55
+ assert.strictEqual(bi.kind, 'function');
56
+ assert.ok(Array.isArray(bi.params));
57
+ assert.strictEqual(bi.params.length, 1);
58
+ assert.strictEqual(bi.params[0].label, 's');
59
+ assert.ok(bi.doc && bi.doc.length > 0, 'len should have a docstring');
60
+ },
61
+ },
62
+
63
+ {
64
+ name: "get_class_builtin",
65
+ description: "get() returns kind='class' for type constructors",
66
+ run: function () {
67
+ var reg = new BuiltinsRegistry();
68
+ assert.strictEqual(reg.get('int').kind, 'class');
69
+ assert.strictEqual(reg.get('str').kind, 'class');
70
+ assert.strictEqual(reg.get('list').kind, 'class');
71
+ assert.strictEqual(reg.get('set').kind, 'class');
72
+ assert.strictEqual(reg.get('dict').kind, 'class');
73
+ assert.strictEqual(reg.get('bool').kind, 'class');
74
+ assert.strictEqual(reg.get('float').kind,'class');
75
+ },
76
+ },
77
+
78
+ {
79
+ name: "get_unknown_returns_null",
80
+ description: "get() returns null for an unknown name",
81
+ run: function () {
82
+ var reg = new BuiltinsRegistry();
83
+ assert.strictEqual(reg.get('__totally_unknown__'), null);
84
+ },
85
+ },
86
+
87
+ // ── BuiltinsRegistry: getNames ────────────────────────────────────
88
+
89
+ {
90
+ name: "getNames_includes_core",
91
+ description: "getNames() includes the core Python built-ins",
92
+ run: function () {
93
+ var reg = new BuiltinsRegistry();
94
+ var names = reg.getNames();
95
+ var core = ['len', 'range', 'print', 'type', 'str', 'int', 'list',
96
+ 'dict', 'set', 'abs', 'min', 'max', 'sum', 'sorted',
97
+ 'enumerate', 'zip', 'map', 'filter', 'any', 'all'];
98
+ core.forEach(function (n) {
99
+ assert.ok(names.indexOf(n) !== -1, n + ' should be in getNames()');
100
+ });
101
+ },
102
+ },
103
+
104
+ {
105
+ name: "getNames_includes_js_globals",
106
+ description: "getNames() includes JS built-ins (parseInt, setTimeout, etc.)",
107
+ run: function () {
108
+ var reg = new BuiltinsRegistry();
109
+ var names = reg.getNames();
110
+ ['parseInt', 'parseFloat', 'isNaN', 'isFinite',
111
+ 'setTimeout', 'setInterval', 'clearTimeout', 'clearInterval',
112
+ 'encodeURIComponent', 'decodeURIComponent'
113
+ ].forEach(function (n) {
114
+ assert.ok(names.indexOf(n) !== -1, n + ' should be in getNames()');
115
+ });
116
+ },
117
+ },
118
+
119
+ // ── BuiltinsRegistry: getHoverMarkdown ────────────────────────────
120
+
121
+ {
122
+ name: "hover_len_contains_sig",
123
+ description: "getHoverMarkdown('len') contains a signature and docstring",
124
+ run: function () {
125
+ var reg = new BuiltinsRegistry();
126
+ var md = reg.getHoverMarkdown('len');
127
+ assert.ok(md, 'hover markdown should not be null');
128
+ assert.ok(md.indexOf('len(s)') !== -1, 'should contain len(s)');
129
+ assert.ok(md.indexOf('```') !== -1, 'should be in a code fence');
130
+ assert.ok(md.indexOf('Return the number') !== -1, 'should contain doc text');
131
+ },
132
+ },
133
+
134
+ {
135
+ name: "hover_print_contains_sig",
136
+ description: "getHoverMarkdown('print') contains the *args param",
137
+ run: function () {
138
+ var reg = new BuiltinsRegistry();
139
+ var md = reg.getHoverMarkdown('print');
140
+ assert.ok(md, 'hover for print should not be null');
141
+ assert.ok(md.indexOf('print') !== -1, 'should mention print');
142
+ assert.ok(md.indexOf('*args') !== -1, 'should show *args param');
143
+ },
144
+ },
145
+
146
+ {
147
+ name: "hover_range_shows_return_type",
148
+ description: "getHoverMarkdown('range') shows the return type in the signature",
149
+ run: function () {
150
+ var reg = new BuiltinsRegistry();
151
+ var md = reg.getHoverMarkdown('range');
152
+ assert.ok(md, 'hover for range should not be null');
153
+ assert.ok(md.indexOf('range') !== -1);
154
+ assert.ok(md.indexOf('→') !== -1, 'should show arrow return type');
155
+ },
156
+ },
157
+
158
+ {
159
+ name: "hover_unknown_returns_null",
160
+ description: "getHoverMarkdown returns null for unknown names",
161
+ run: function () {
162
+ var reg = new BuiltinsRegistry();
163
+ assert.strictEqual(reg.getHoverMarkdown('__unknown__'), null);
164
+ },
165
+ },
166
+
167
+ {
168
+ name: "hover_none_return_omitted",
169
+ description: "getHoverMarkdown omits '→ None' from the signature (void functions)",
170
+ run: function () {
171
+ var reg = new BuiltinsRegistry();
172
+ var md = reg.getHoverMarkdown('print');
173
+ // Should not show "→ None"
174
+ assert.ok(md.indexOf('→ None') === -1, 'None return type should be omitted');
175
+ },
176
+ },
177
+
178
+ // ── BuiltinsRegistry: getTypeMembers ─────────────────────────────
179
+
180
+ {
181
+ name: "getTypeMembers_list_returns_map",
182
+ description: "getTypeMembers('list') returns a Map with list members",
183
+ run: function () {
184
+ var reg = new BuiltinsRegistry();
185
+ var members = reg.getTypeMembers('list');
186
+ assert.ok(members, 'getTypeMembers(list) should not return null');
187
+ assert.ok(typeof members.get === 'function', 'should be a Map');
188
+ assert.ok(members.has('length'), 'list should have length');
189
+ assert.ok(members.has('append'), 'list should have append');
190
+ assert.ok(members.has('push'), 'list should have push');
191
+ assert.ok(members.has('map'), 'list should have map');
192
+ assert.ok(members.has('filter'), 'list should have filter');
193
+ assert.ok(members.has('slice'), 'list should have slice');
194
+ },
195
+ },
196
+
197
+ {
198
+ name: "getTypeMembers_list_length_is_property",
199
+ description: "list.length is a 'property' member, not a method",
200
+ run: function () {
201
+ var reg = new BuiltinsRegistry();
202
+ var members = reg.getTypeMembers('list');
203
+ var length_member = members.get('length');
204
+ assert.ok(length_member, 'length member should exist');
205
+ assert.strictEqual(length_member.kind, 'property');
206
+ assert.strictEqual(length_member.return_type, 'int');
207
+ },
208
+ },
209
+
210
+ {
211
+ name: "getTypeMembers_list_append_is_method",
212
+ description: "list.append is a 'method' member with a param",
213
+ run: function () {
214
+ var reg = new BuiltinsRegistry();
215
+ var members = reg.getTypeMembers('list');
216
+ var append = members.get('append');
217
+ assert.ok(append, 'append member should exist');
218
+ assert.strictEqual(append.kind, 'method');
219
+ assert.ok(Array.isArray(append.params) && append.params.length >= 1,
220
+ 'append should have at least one param');
221
+ },
222
+ },
223
+
224
+ {
225
+ name: "getTypeMembers_str_returns_map",
226
+ description: "getTypeMembers('str') returns a Map with string members",
227
+ run: function () {
228
+ var reg = new BuiltinsRegistry();
229
+ var members = reg.getTypeMembers('str');
230
+ assert.ok(members, 'getTypeMembers(str) should not return null');
231
+ assert.ok(members.has('length'), 'str should have length');
232
+ assert.ok(members.has('upper'), 'str should have upper');
233
+ assert.ok(members.has('lower'), 'str should have lower');
234
+ assert.ok(members.has('split'), 'str should have split');
235
+ assert.ok(members.has('strip'), 'str should have strip');
236
+ assert.ok(members.has('startswith'), 'str should have startswith');
237
+ assert.ok(members.has('endswith'), 'str should have endswith');
238
+ },
239
+ },
240
+
241
+ {
242
+ name: "getTypeMembers_dict_returns_map",
243
+ description: "getTypeMembers('dict') returns a Map with dict members",
244
+ run: function () {
245
+ var reg = new BuiltinsRegistry();
246
+ var members = reg.getTypeMembers('dict');
247
+ assert.ok(members, 'getTypeMembers(dict) should not return null');
248
+ assert.ok(members.has('keys'), 'dict should have keys');
249
+ assert.ok(members.has('values'), 'dict should have values');
250
+ assert.ok(members.has('items'), 'dict should have items');
251
+ assert.ok(members.has('get'), 'dict should have get');
252
+ assert.ok(members.has('update'), 'dict should have update');
253
+ assert.ok(members.has('pop'), 'dict should have pop');
254
+ },
255
+ },
256
+
257
+ {
258
+ name: "getTypeMembers_number_returns_map",
259
+ description: "getTypeMembers('number') returns a Map with number members",
260
+ run: function () {
261
+ var reg = new BuiltinsRegistry();
262
+ var members = reg.getTypeMembers('number');
263
+ assert.ok(members, 'getTypeMembers(number) should not return null');
264
+ assert.ok(members.has('toFixed'), 'number should have toFixed');
265
+ assert.ok(members.has('toString'), 'number should have toString');
266
+ assert.ok(members.has('toPrecision'), 'number should have toPrecision');
267
+ },
268
+ },
269
+
270
+ {
271
+ name: "getTypeMembers_unknown_returns_null",
272
+ description: "getTypeMembers() returns null for an unknown type name",
273
+ run: function () {
274
+ var reg = new BuiltinsRegistry();
275
+ assert.strictEqual(reg.getTypeMembers('totally_unknown'), null);
276
+ assert.strictEqual(reg.getTypeMembers(''), null);
277
+ },
278
+ },
279
+
280
+ // ── BuiltinsRegistry: getSignatureInfo ────────────────────────────
281
+
282
+ {
283
+ name: "sig_info_len",
284
+ description: "getSignatureInfo('len') returns correct label and params",
285
+ run: function () {
286
+ var reg = new BuiltinsRegistry();
287
+ var info = reg.getSignatureInfo('len');
288
+ assert.ok(info, 'should return info for len');
289
+ assert.ok(info.label.indexOf('len(') === 0, 'label should start with len(');
290
+ assert.ok(Array.isArray(info.params), 'params should be an array');
291
+ assert.strictEqual(info.params.length, 1);
292
+ assert.ok(info.params[0].label, 'param should have a label');
293
+ assert.ok(info.doc, 'should have doc');
294
+ },
295
+ },
296
+
297
+ {
298
+ name: "sig_info_range_has_three_params",
299
+ description: "getSignatureInfo('range') has three parameters",
300
+ run: function () {
301
+ var reg = new BuiltinsRegistry();
302
+ var info = reg.getSignatureInfo('range');
303
+ assert.ok(info);
304
+ assert.strictEqual(info.params.length, 3);
305
+ assert.ok(info.params[1].label.indexOf('?') !== -1,
306
+ 'stop param should be marked optional');
307
+ },
308
+ },
309
+
310
+ {
311
+ name: "sig_info_unknown_returns_null",
312
+ description: "getSignatureInfo returns null for unknown name",
313
+ run: function () {
314
+ var reg = new BuiltinsRegistry();
315
+ assert.strictEqual(reg.getSignatureInfo('__unknown__'), null);
316
+ },
317
+ },
318
+
319
+ {
320
+ name: "sig_info_var_returns_null",
321
+ description: "getSignatureInfo returns null for var-kind stubs (no params)",
322
+ run: function () {
323
+ // jstype is a function, but we can test that any stub without
324
+ // params returns null by checking a hypothetical var
325
+ // (No var stubs are currently defined in builtins, so we verify
326
+ // that a stub with params always returns a non-null info)
327
+ var reg = new BuiltinsRegistry();
328
+ // All function stubs should return non-null
329
+ assert.ok(reg.getSignatureInfo('abs') !== null, 'abs should have sig info');
330
+ },
331
+ },
332
+
333
+ // ── HoverEngine integration ───────────────────────────────────────
334
+
335
+ {
336
+ name: "hover_builtin_fallback_works",
337
+ description: "HoverEngine falls back to BuiltinsRegistry when word not in ScopeMap or DTS",
338
+ run: function () {
339
+ var reg = new BuiltinsRegistry();
340
+ var engine = new HoverEngine(null, reg);
341
+ var hover = engine.getHover(null, pos(1, 1), 'len');
342
+ assert.ok(hover, 'should return a hover object');
343
+ assert.ok(Array.isArray(hover.contents), 'contents should be an array');
344
+ assert.ok(hover.contents[0].value.indexOf('len') !== -1);
345
+ },
346
+ },
347
+
348
+ {
349
+ name: "hover_null_word_returns_null",
350
+ description: "HoverEngine returns null for a null word with builtins registry",
351
+ run: function () {
352
+ var reg = new BuiltinsRegistry();
353
+ var engine = new HoverEngine(null, reg);
354
+ assert.strictEqual(engine.getHover(null, pos(1, 1), null), null);
355
+ },
356
+ },
357
+
358
+ {
359
+ name: "hover_unknown_word_returns_null",
360
+ description: "HoverEngine returns null for a word not in builtins",
361
+ run: function () {
362
+ var reg = new BuiltinsRegistry();
363
+ var engine = new HoverEngine(null, reg);
364
+ assert.strictEqual(engine.getHover(null, pos(1, 1), '__totally_unknown__'), null);
365
+ },
366
+ },
367
+
368
+ {
369
+ name: "hover_no_registry_returns_null",
370
+ description: "HoverEngine with no registries returns null for a builtin name",
371
+ run: function () {
372
+ var engine = new HoverEngine(null, null);
373
+ assert.strictEqual(engine.getHover(null, pos(1, 1), 'len'), null);
374
+ },
375
+ },
376
+
377
+ // ── SignatureHelpEngine integration ───────────────────────────────
378
+
379
+ {
380
+ name: "sig_builtin_fallback_works",
381
+ description: "SignatureHelpEngine uses builtins when no ScopeMap",
382
+ run: function () {
383
+ var reg = new BuiltinsRegistry();
384
+ var engine = new SignatureHelpEngine(reg);
385
+ var help = engine.getSignatureHelp(null, pos(1, 5), 'len(');
386
+ assert.ok(help, 'should return signature help');
387
+ var sig = help.value.signatures[0];
388
+ assert.ok(sig.label.indexOf('len(') === 0, 'label should start with len(');
389
+ assert.ok(Array.isArray(sig.parameters));
390
+ assert.strictEqual(sig.parameters.length, 1);
391
+ },
392
+ },
393
+
394
+ {
395
+ name: "sig_builtin_active_param",
396
+ description: "Active parameter index advances with commas",
397
+ run: function () {
398
+ var reg = new BuiltinsRegistry();
399
+ var engine = new SignatureHelpEngine(reg);
400
+
401
+ // range(start_or_stop, stop?, step?)
402
+ var h0 = engine.getSignatureHelp(null, pos(1, 7), 'range(');
403
+ var h1 = engine.getSignatureHelp(null, pos(1, 9), 'range(1,');
404
+ var h2 = engine.getSignatureHelp(null, pos(1, 12), 'range(1, 5,');
405
+
406
+ assert.ok(h0, 'cursor after ( should give help');
407
+ assert.ok(h1, 'cursor after first , should give help');
408
+ assert.ok(h2, 'cursor after second , should give help');
409
+
410
+ assert.strictEqual(h0.value.activeParameter, 0, 'first param active');
411
+ assert.strictEqual(h1.value.activeParameter, 1, 'second param active');
412
+ assert.strictEqual(h2.value.activeParameter, 2, 'third param active');
413
+ },
414
+ },
415
+
416
+ {
417
+ name: "sig_builtin_clamps_active_param",
418
+ description: "Active parameter is clamped to last param index",
419
+ run: function () {
420
+ var reg = new BuiltinsRegistry();
421
+ var engine = new SignatureHelpEngine(reg);
422
+ // abs only has one param; cursor past many commas should clamp to 0
423
+ var help = engine.getSignatureHelp(null, pos(1, 10), 'abs(1, 2,');
424
+ assert.ok(help);
425
+ assert.strictEqual(help.value.activeParameter, 0);
426
+ },
427
+ },
428
+
429
+ {
430
+ name: "sig_unknown_callee_returns_null",
431
+ description: "SignatureHelpEngine returns null for unknown function name",
432
+ run: function () {
433
+ var reg = new BuiltinsRegistry();
434
+ var engine = new SignatureHelpEngine(reg);
435
+ assert.strictEqual(
436
+ engine.getSignatureHelp(null, pos(1, 10), '__totally_unknown__('),
437
+ null
438
+ );
439
+ },
440
+ },
441
+
442
+ {
443
+ name: "sig_no_registry_still_works_for_scope",
444
+ description: "SignatureHelpEngine without registry still resolves user-defined functions",
445
+ run: function () {
446
+ var engine = new SignatureHelpEngine(null);
447
+ var analyzer = new SourceAnalyzer(RS);
448
+ var scopeMap = analyzer.analyze([
449
+ "def greet(name, msg):",
450
+ " return name",
451
+ "pass",
452
+ ].join("\n"), {});
453
+ var help = engine.getSignatureHelp(scopeMap, pos(3, 1), 'greet(');
454
+ assert.ok(help, 'should resolve user-defined greet');
455
+ assert.ok(help.value.signatures[0].label.indexOf('greet(') === 0);
456
+ },
457
+ },
458
+
459
+ {
460
+ name: "sig_scopemap_wins_over_builtin",
461
+ description: "User-defined function in ScopeMap wins over built-in with same name",
462
+ run: function () {
463
+ var reg = new BuiltinsRegistry();
464
+ var engine = new SignatureHelpEngine(reg);
465
+ var analyzer = new SourceAnalyzer(RS);
466
+ // Shadow 'len' with a user-defined function that takes 2 params
467
+ var scopeMap = analyzer.analyze([
468
+ "def len(a, b):",
469
+ " return a",
470
+ "pass",
471
+ ].join("\n"), {});
472
+ var help = engine.getSignatureHelp(scopeMap, pos(3, 1), 'len(');
473
+ assert.ok(help);
474
+ // user-defined len has 2 params; builtin has 1
475
+ assert.strictEqual(help.value.signatures[0].parameters.length, 2,
476
+ 'user-defined len (2 params) should win over builtin (1 param)');
477
+ },
478
+ },
479
+
480
+ // ── CompletionEngine integration ──────────────────────────────────
481
+
482
+ {
483
+ name: "completion_builtin_rich_detail",
484
+ description: "Builtin completion items show param list in detail when registry present",
485
+ run: function () {
486
+ var reg = new BuiltinsRegistry();
487
+ var analyzer = new SourceAnalyzer(RS);
488
+ var engine = new CompletionEngine(analyzer, {
489
+ virtualFiles: {},
490
+ builtinNames: ['len', 'range', 'print'],
491
+ builtinsRegistry: reg,
492
+ });
493
+ var list = engine.getCompletions(null, pos(1, 4), 'len', MockKind);
494
+ var item = list.suggestions.find(function (s) { return s.label === 'len'; });
495
+ assert.ok(item, 'len should be in completions');
496
+ assert.ok(item.detail && item.detail.indexOf('(s)') !== -1,
497
+ 'detail should show param list: ' + item.detail);
498
+ assert.ok(item.documentation, 'should have documentation');
499
+ },
500
+ },
501
+
502
+ {
503
+ name: "completion_builtin_class_kind",
504
+ description: "Type constructor built-ins have Class kind in completions",
505
+ run: function () {
506
+ var reg = new BuiltinsRegistry();
507
+ var analyzer = new SourceAnalyzer(RS);
508
+ var engine = new CompletionEngine(analyzer, {
509
+ virtualFiles: {},
510
+ builtinNames: ['int', 'str', 'list'],
511
+ builtinsRegistry: reg,
512
+ });
513
+ var list = engine.getCompletions(null, pos(1, 1), '', MockKind);
514
+ ['int', 'str', 'list'].forEach(function (name) {
515
+ var item = list.suggestions.find(function (s) { return s.label === name; });
516
+ assert.ok(item, name + ' should be in completions');
517
+ assert.strictEqual(item.kind, MockKind.Class,
518
+ name + ' should have Class kind');
519
+ });
520
+ },
521
+ },
522
+
523
+ {
524
+ name: "completion_builtin_function_kind",
525
+ description: "Function built-ins have Function kind in completions",
526
+ run: function () {
527
+ var reg = new BuiltinsRegistry();
528
+ var analyzer = new SourceAnalyzer(RS);
529
+ var engine = new CompletionEngine(analyzer, {
530
+ virtualFiles: {},
531
+ builtinNames: ['len', 'abs', 'sorted'],
532
+ builtinsRegistry: reg,
533
+ });
534
+ var list = engine.getCompletions(null, pos(1, 1), '', MockKind);
535
+ ['len', 'abs', 'sorted'].forEach(function (name) {
536
+ var item = list.suggestions.find(function (s) { return s.label === name; });
537
+ assert.ok(item, name + ' should be in completions');
538
+ assert.strictEqual(item.kind, MockKind.Function,
539
+ name + ' should have Function kind');
540
+ });
541
+ },
542
+ },
543
+
544
+ {
545
+ name: "completion_builtin_no_registry_still_works",
546
+ description: "CompletionEngine works without builtinsRegistry (plain items)",
547
+ run: function () {
548
+ var analyzer = new SourceAnalyzer(RS);
549
+ var engine = new CompletionEngine(analyzer, {
550
+ virtualFiles: {},
551
+ builtinNames: ['len', 'range'],
552
+ // no builtinsRegistry
553
+ });
554
+ var list = engine.getCompletions(null, pos(1, 4), 'len', MockKind);
555
+ var item = list.suggestions.find(function (s) { return s.label === 'len'; });
556
+ assert.ok(item, 'len should appear even without stubs');
557
+ // Without stubs, detail is undefined (plain name_to_item)
558
+ assert.ok(!item.detail, 'no detail without stubs');
559
+ },
560
+ },
561
+
562
+ // ── super() ───────────────────────────────────────────────────────
563
+
564
+ {
565
+ name: "super_in_registry",
566
+ description: "BuiltinsRegistry has an entry for super()",
567
+ run: function () {
568
+ var reg = new BuiltinsRegistry();
569
+ var info = reg.get('super');
570
+ assert.ok(info, 'super should be in the registry');
571
+ assert.strictEqual(info.name, 'super');
572
+ assert.strictEqual(info.kind, 'function');
573
+ assert.ok(info.doc && info.doc.length > 0, 'super should have a doc string');
574
+ },
575
+ },
576
+
577
+ {
578
+ name: "super_hover",
579
+ description: "HoverEngine provides hover docs for super()",
580
+ run: function () {
581
+ var reg = new BuiltinsRegistry();
582
+ var md = reg.getHoverMarkdown('super');
583
+ assert.ok(md && md.indexOf('super') !== -1, 'hover markdown should mention super');
584
+ },
585
+ },
586
+
587
+ {
588
+ name: "super_in_completions",
589
+ description: "super appears in completion list as a built-in function",
590
+ run: function () {
591
+ var reg = new BuiltinsRegistry();
592
+ var analyzer = new SourceAnalyzer(RS);
593
+ var engine = new CompletionEngine(analyzer, {
594
+ virtualFiles: {},
595
+ builtinNames: ['super'],
596
+ builtinsRegistry: reg,
597
+ });
598
+ var list = engine.getCompletions(null, pos(1, 5), 'super', MockKind);
599
+ var item = list.suggestions.find(function (s) { return s.label === 'super'; });
600
+ assert.ok(item, 'super should appear in completions');
601
+ assert.strictEqual(item.kind, MockKind.Function, 'super should have Function kind');
602
+ },
603
+ },
604
+
605
+ // ── any() ─────────────────────────────────────────────────────────
606
+
607
+ {
608
+ name: "any_in_registry",
609
+ description: "BuiltinsRegistry has an entry for any()",
610
+ run: function () {
611
+ var reg = new BuiltinsRegistry();
612
+ var bi = reg.get('any');
613
+ assert.ok(bi, 'any should be registered');
614
+ assert.strictEqual(bi.name, 'any');
615
+ assert.strictEqual(bi.kind, 'function');
616
+ assert.ok(Array.isArray(bi.params) && bi.params.length === 1, 'any should have one param');
617
+ assert.strictEqual(bi.params[0].label, 'iterable');
618
+ assert.strictEqual(bi.return_type, 'bool');
619
+ assert.ok(bi.doc && bi.doc.length > 0, 'any should have a docstring');
620
+ },
621
+ },
622
+
623
+ {
624
+ name: "any_hover_markdown",
625
+ description: "getHoverMarkdown('any') contains signature and docstring",
626
+ run: function () {
627
+ var reg = new BuiltinsRegistry();
628
+ var md = reg.getHoverMarkdown('any');
629
+ assert.ok(md, 'hover markdown should not be null');
630
+ assert.ok(md.indexOf('any(iterable)') !== -1, 'should contain any(iterable)');
631
+ assert.ok(md.indexOf('```') !== -1, 'should be in a code fence');
632
+ assert.ok(md.indexOf('→ bool') !== -1, 'should show return type bool');
633
+ assert.ok(md.indexOf('true') !== -1 || md.indexOf('True') !== -1,
634
+ 'docstring should mention true');
635
+ },
636
+ },
637
+
638
+ {
639
+ name: "any_signature_info",
640
+ description: "getSignatureInfo('any') returns correct label and param",
641
+ run: function () {
642
+ var reg = new BuiltinsRegistry();
643
+ var info = reg.getSignatureInfo('any');
644
+ assert.ok(info, 'should return info for any');
645
+ assert.ok(info.label.indexOf('any(') === 0, 'label should start with any(');
646
+ assert.strictEqual(info.params.length, 1);
647
+ assert.ok(info.params[0].label.indexOf('iterable') !== -1);
648
+ assert.ok(info.doc, 'should have doc');
649
+ },
650
+ },
651
+
652
+ {
653
+ name: "any_in_completions",
654
+ description: "any appears in completion list as a built-in function",
655
+ run: function () {
656
+ var reg = new BuiltinsRegistry();
657
+ var analyzer = new SourceAnalyzer(RS);
658
+ var engine = new CompletionEngine(analyzer, {
659
+ virtualFiles: {},
660
+ builtinNames: ['any'],
661
+ builtinsRegistry: reg,
662
+ });
663
+ var list = engine.getCompletions(null, pos(1, 3), 'any', MockKind);
664
+ var item = list.suggestions.find(function (s) { return s.label === 'any'; });
665
+ assert.ok(item, 'any should appear in completions');
666
+ assert.strictEqual(item.kind, MockKind.Function, 'any should have Function kind');
667
+ assert.ok(item.detail && item.detail.indexOf('(iterable)') !== -1,
668
+ 'detail should show param list: ' + item.detail);
669
+ },
670
+ },
671
+
672
+ // ── all() ─────────────────────────────────────────────────────────
673
+
674
+ {
675
+ name: "all_in_registry",
676
+ description: "BuiltinsRegistry has an entry for all()",
677
+ run: function () {
678
+ var reg = new BuiltinsRegistry();
679
+ var bi = reg.get('all');
680
+ assert.ok(bi, 'all should be registered');
681
+ assert.strictEqual(bi.name, 'all');
682
+ assert.strictEqual(bi.kind, 'function');
683
+ assert.ok(Array.isArray(bi.params) && bi.params.length === 1, 'all should have one param');
684
+ assert.strictEqual(bi.params[0].label, 'iterable');
685
+ assert.strictEqual(bi.return_type, 'bool');
686
+ assert.ok(bi.doc && bi.doc.length > 0, 'all should have a docstring');
687
+ },
688
+ },
689
+
690
+ {
691
+ name: "all_hover_markdown",
692
+ description: "getHoverMarkdown('all') contains signature and docstring",
693
+ run: function () {
694
+ var reg = new BuiltinsRegistry();
695
+ var md = reg.getHoverMarkdown('all');
696
+ assert.ok(md, 'hover markdown should not be null');
697
+ assert.ok(md.indexOf('all(iterable)') !== -1, 'should contain all(iterable)');
698
+ assert.ok(md.indexOf('```') !== -1, 'should be in a code fence');
699
+ assert.ok(md.indexOf('→ bool') !== -1, 'should show return type bool');
700
+ },
701
+ },
702
+
703
+ {
704
+ name: "all_signature_info",
705
+ description: "getSignatureInfo('all') returns correct label and param",
706
+ run: function () {
707
+ var reg = new BuiltinsRegistry();
708
+ var info = reg.getSignatureInfo('all');
709
+ assert.ok(info, 'should return info for all');
710
+ assert.ok(info.label.indexOf('all(') === 0, 'label should start with all(');
711
+ assert.strictEqual(info.params.length, 1);
712
+ assert.ok(info.params[0].label.indexOf('iterable') !== -1);
713
+ assert.ok(info.doc, 'should have doc');
714
+ },
715
+ },
716
+
717
+ {
718
+ name: "all_in_completions",
719
+ description: "all appears in completion list as a built-in function",
720
+ run: function () {
721
+ var reg = new BuiltinsRegistry();
722
+ var analyzer = new SourceAnalyzer(RS);
723
+ var engine = new CompletionEngine(analyzer, {
724
+ virtualFiles: {},
725
+ builtinNames: ['all'],
726
+ builtinsRegistry: reg,
727
+ });
728
+ var list = engine.getCompletions(null, pos(1, 3), 'all', MockKind);
729
+ var item = list.suggestions.find(function (s) { return s.label === 'all'; });
730
+ assert.ok(item, 'all should appear in completions');
731
+ assert.strictEqual(item.kind, MockKind.Function, 'all should have Function kind');
732
+ assert.ok(item.detail && item.detail.indexOf('(iterable)') !== -1,
733
+ 'detail should show param list: ' + item.detail);
734
+ },
735
+ },
736
+
737
+ ];
738
+
739
+ return TESTS;
740
+ }
741
+
742
+ // ---------------------------------------------------------------------------
743
+ // Runner
744
+ // ---------------------------------------------------------------------------
745
+
746
+ function run_tests(TESTS, filter) {
747
+ var tests = filter
748
+ ? TESTS.filter(function (t) { return t.name === filter; })
749
+ : TESTS;
750
+
751
+ if (tests.length === 0) {
752
+ console.error(colored("No test found: " + filter, "red"));
753
+ process.exit(1);
754
+ }
755
+
756
+ var failures = [];
757
+ tests.forEach(function (test) {
758
+ try {
759
+ test.run();
760
+ console.log(colored("PASS " + test.name, "green") + " – " + test.description);
761
+ } catch (e) {
762
+ failures.push(test.name);
763
+ console.log(colored("FAIL " + test.name, "red") +
764
+ "\n " + (e.message || String(e)) + "\n");
765
+ }
766
+ });
767
+
768
+ console.log("");
769
+ if (failures.length) {
770
+ console.log(colored(failures.length + " test(s) failed.", "red"));
771
+ } else {
772
+ console.log(colored("All " + tests.length + " language-service-builtins tests passed!", "green"));
773
+ }
774
+ process.exit(failures.length ? 1 : 0);
775
+ }
776
+
777
+ // ---------------------------------------------------------------------------
778
+ // Entry point
779
+ // ---------------------------------------------------------------------------
780
+
781
+ var builtins_path = url.pathToFileURL(path.join(__dirname, "../../src/monaco-language-service/builtins.js")).href;
782
+ var hover_path = url.pathToFileURL(path.join(__dirname, "../../src/monaco-language-service/hover.js")).href;
783
+ var signature_path = url.pathToFileURL(path.join(__dirname, "../../src/monaco-language-service/signature.js")).href;
784
+ var completions_path = url.pathToFileURL(path.join(__dirname, "../../src/monaco-language-service/completions.js")).href;
785
+ var analyzer_path = url.pathToFileURL(path.join(__dirname, "../../src/monaco-language-service/analyzer.js")).href;
786
+
787
+ var filter = process.argv[2] || null;
788
+
789
+ Promise.all([
790
+ import(builtins_path),
791
+ import(hover_path),
792
+ import(signature_path),
793
+ import(completions_path),
794
+ import(analyzer_path),
795
+ ]).then(function (mods) {
796
+ var BuiltinsRegistry = mods[0].BuiltinsRegistry;
797
+ var BuiltinInfo = mods[0].BuiltinInfo;
798
+ var HoverEngine = mods[1].HoverEngine;
799
+ var SignatureHelpEngine = mods[2].SignatureHelpEngine;
800
+ var detect_call_context = mods[2].detect_call_context;
801
+ var CompletionEngine = mods[3].CompletionEngine;
802
+ var SourceAnalyzer = mods[4].SourceAnalyzer;
803
+ var RS = compiler_module.create_compiler();
804
+
805
+ var TESTS = make_tests(
806
+ BuiltinsRegistry, BuiltinInfo,
807
+ HoverEngine, SignatureHelpEngine,
808
+ CompletionEngine, detect_call_context,
809
+ SourceAnalyzer, RS
810
+ );
811
+ run_tests(TESTS, filter);
812
+ }).catch(function (e) {
813
+ console.error(colored("Failed to load modules:", "red"), e);
814
+ process.exit(1);
815
+ });