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.
- package/.agignore +1 -0
- package/.gitattributes +4 -0
- package/.github/workflows/ci.yml +38 -0
- package/.github/workflows/web-repl-page-deploy.yml +42 -0
- package/=template.pyj +5 -0
- package/CHANGELOG.md +456 -0
- package/CONTRIBUTORS +13 -0
- package/HACKING.md +103 -0
- package/LICENSE +24 -0
- package/README.md +2512 -0
- package/TODO.md +327 -0
- package/add-toc-to-readme +2 -0
- package/bin/export +75 -0
- package/bin/rapydscript +70 -0
- package/bin/web-repl-export +102 -0
- package/build +3 -0
- package/package.json +46 -0
- package/publish.py +37 -0
- package/release/baselib-plain-pretty.js +4370 -0
- package/release/baselib-plain-ugly.js +3 -0
- package/release/compiler.js +18394 -0
- package/release/signatures.json +31 -0
- package/session.vim +4 -0
- package/setup.cfg +2 -0
- package/src/ast.pyj +1356 -0
- package/src/baselib-builtins.pyj +279 -0
- package/src/baselib-containers.pyj +723 -0
- package/src/baselib-errors.pyj +37 -0
- package/src/baselib-internal.pyj +421 -0
- package/src/baselib-itertools.pyj +97 -0
- package/src/baselib-str.pyj +798 -0
- package/src/compiler.pyj +36 -0
- package/src/errors.pyj +30 -0
- package/src/lib/aes.pyj +646 -0
- package/src/lib/collections.pyj +695 -0
- package/src/lib/elementmaker.pyj +83 -0
- package/src/lib/encodings.pyj +126 -0
- package/src/lib/functools.pyj +148 -0
- package/src/lib/gettext.pyj +569 -0
- package/src/lib/itertools.pyj +580 -0
- package/src/lib/math.pyj +193 -0
- package/src/lib/numpy.pyj +2101 -0
- package/src/lib/operator.pyj +11 -0
- package/src/lib/pythonize.pyj +20 -0
- package/src/lib/random.pyj +118 -0
- package/src/lib/re.pyj +470 -0
- package/src/lib/traceback.pyj +63 -0
- package/src/lib/uuid.pyj +77 -0
- package/src/monaco-language-service/analyzer.js +526 -0
- package/src/monaco-language-service/builtins.js +543 -0
- package/src/monaco-language-service/completions.js +498 -0
- package/src/monaco-language-service/diagnostics.js +643 -0
- package/src/monaco-language-service/dts.js +550 -0
- package/src/monaco-language-service/hover.js +121 -0
- package/src/monaco-language-service/index.js +386 -0
- package/src/monaco-language-service/scope.js +162 -0
- package/src/monaco-language-service/signature.js +144 -0
- package/src/output/__init__.pyj +0 -0
- package/src/output/classes.pyj +296 -0
- package/src/output/codegen.pyj +492 -0
- package/src/output/comments.pyj +45 -0
- package/src/output/exceptions.pyj +105 -0
- package/src/output/functions.pyj +491 -0
- package/src/output/literals.pyj +109 -0
- package/src/output/loops.pyj +444 -0
- package/src/output/modules.pyj +329 -0
- package/src/output/operators.pyj +429 -0
- package/src/output/statements.pyj +463 -0
- package/src/output/stream.pyj +309 -0
- package/src/output/treeshake.pyj +182 -0
- package/src/output/utils.pyj +72 -0
- package/src/parse.pyj +3106 -0
- package/src/string_interpolation.pyj +72 -0
- package/src/tokenizer.pyj +702 -0
- package/src/unicode_aliases.pyj +576 -0
- package/src/utils.pyj +192 -0
- package/test/_import_one.pyj +37 -0
- package/test/_import_two/__init__.pyj +11 -0
- package/test/_import_two/level2/__init__.pyj +0 -0
- package/test/_import_two/level2/deep.pyj +4 -0
- package/test/_import_two/other.pyj +6 -0
- package/test/_import_two/sub.pyj +13 -0
- package/test/aes_vectors.pyj +421 -0
- package/test/annotations.pyj +80 -0
- package/test/baselib.pyj +319 -0
- package/test/classes.pyj +452 -0
- package/test/collections.pyj +152 -0
- package/test/decorators.pyj +77 -0
- package/test/dict_spread.pyj +76 -0
- package/test/docstrings.pyj +39 -0
- package/test/elementmaker_test.pyj +45 -0
- package/test/ellipsis.pyj +49 -0
- package/test/functions.pyj +151 -0
- package/test/generators.pyj +41 -0
- package/test/generic.pyj +370 -0
- package/test/imports.pyj +72 -0
- package/test/internationalization.pyj +73 -0
- package/test/lint.pyj +164 -0
- package/test/loops.pyj +85 -0
- package/test/numpy.pyj +734 -0
- package/test/omit_function_metadata.pyj +20 -0
- package/test/regexp.pyj +55 -0
- package/test/repl.pyj +121 -0
- package/test/scoped_flags.pyj +76 -0
- package/test/starargs.pyj +506 -0
- package/test/starred_assign.pyj +104 -0
- package/test/str.pyj +198 -0
- package/test/subscript_tuple.pyj +53 -0
- package/test/unit/fixtures/fibonacci_expected.js +46 -0
- package/test/unit/index.js +2989 -0
- package/test/unit/language-service-builtins.js +815 -0
- package/test/unit/language-service-completions.js +1067 -0
- package/test/unit/language-service-dts.js +543 -0
- package/test/unit/language-service-hover.js +455 -0
- package/test/unit/language-service-scope.js +833 -0
- package/test/unit/language-service-signature.js +458 -0
- package/test/unit/language-service.js +705 -0
- package/test/unit/run-language-service.js +41 -0
- package/test/unit/web-repl.js +484 -0
- package/tools/build-language-service.js +190 -0
- package/tools/cli.js +547 -0
- package/tools/compile.js +219 -0
- package/tools/compiler.js +108 -0
- package/tools/completer.js +131 -0
- package/tools/embedded_compiler.js +251 -0
- package/tools/export.js +316 -0
- package/tools/gettext.js +185 -0
- package/tools/ini.js +65 -0
- package/tools/lint.js +705 -0
- package/tools/msgfmt.js +187 -0
- package/tools/repl.js +223 -0
- package/tools/self.js +162 -0
- package/tools/test.js +118 -0
- package/tools/utils.js +128 -0
- package/tools/web_repl.js +95 -0
- package/try +41 -0
- package/web-repl/env.js +74 -0
- package/web-repl/index.html +163 -0
- package/web-repl/language-service.js +4084 -0
- package/web-repl/main.js +254 -0
- package/web-repl/prism.css +139 -0
- package/web-repl/prism.js +113 -0
- package/web-repl/rapydscript.js +435 -0
- package/web-repl/sha1.js +25 -0
|
@@ -0,0 +1,833 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* test/unit/language-service-scope.js
|
|
3
|
+
*
|
|
4
|
+
* Unit tests for Phase 2: src/monaco-language-service/analyzer.js
|
|
5
|
+
* (ScopeBuilder + SourceAnalyzer + ScopeMap queries)
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* node test/unit/language-service-scope.js # all tests
|
|
9
|
+
* node test/unit/language-service-scope.js <test-name> # single test
|
|
10
|
+
*/
|
|
11
|
+
"use strict";
|
|
12
|
+
|
|
13
|
+
var assert = require("assert");
|
|
14
|
+
var path = require("path");
|
|
15
|
+
var url = require("url");
|
|
16
|
+
var compiler_module = require("../../tools/compiler");
|
|
17
|
+
var utils = require("../../tools/utils");
|
|
18
|
+
var colored = utils.safe_colored;
|
|
19
|
+
|
|
20
|
+
// ---------------------------------------------------------------------------
|
|
21
|
+
// Helpers
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
|
|
24
|
+
function names_of(symbols) {
|
|
25
|
+
return symbols.map(function (s) { return s.name; }).sort();
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function find(symbols, name) {
|
|
29
|
+
return symbols.find(function (s) { return s.name === name; }) || null;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function assert_has(symbols, name, label) {
|
|
33
|
+
assert.ok(
|
|
34
|
+
symbols.some(function (s) { return s.name === name; }),
|
|
35
|
+
(label || "") + ": expected symbol '" + name + "' in [" + names_of(symbols).join(", ") + "]"
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function assert_not_has(symbols, name, label) {
|
|
40
|
+
assert.ok(
|
|
41
|
+
!symbols.some(function (s) { return s.name === name; }),
|
|
42
|
+
(label || "") + ": symbol '" + name + "' should NOT appear in [" + names_of(symbols).join(", ") + "]"
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// ---------------------------------------------------------------------------
|
|
47
|
+
// Test definitions
|
|
48
|
+
// ---------------------------------------------------------------------------
|
|
49
|
+
|
|
50
|
+
function make_tests(SourceAnalyzer, RS) {
|
|
51
|
+
|
|
52
|
+
function analyze(code, opts) {
|
|
53
|
+
var a = new SourceAnalyzer(RS);
|
|
54
|
+
return a.analyze(code, opts || {});
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
var TESTS = [
|
|
58
|
+
|
|
59
|
+
// ── Basic structure ───────────────────────────────────────────────
|
|
60
|
+
|
|
61
|
+
{
|
|
62
|
+
name: "returns_scopemap",
|
|
63
|
+
description: "analyze() always returns a ScopeMap object",
|
|
64
|
+
run: function () {
|
|
65
|
+
var m = analyze("x = 1");
|
|
66
|
+
assert.ok(m, "ScopeMap should be truthy");
|
|
67
|
+
assert.ok(Array.isArray(m.frames), "ScopeMap.frames should be an array");
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
|
|
71
|
+
{
|
|
72
|
+
name: "empty_source_gives_module_frame",
|
|
73
|
+
description: "Empty source produces a single module-scoped frame",
|
|
74
|
+
run: function () {
|
|
75
|
+
var m = analyze("");
|
|
76
|
+
assert.ok(m.frames.length >= 1, "Expected at least the module frame");
|
|
77
|
+
var mod = m.frames.find(function (f) { return f.kind === "module"; });
|
|
78
|
+
assert.ok(mod, "Expected a 'module' frame");
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
|
|
82
|
+
{
|
|
83
|
+
name: "syntax_error_returns_empty_map",
|
|
84
|
+
description: "A parse error returns an empty (0-frame) ScopeMap without throwing",
|
|
85
|
+
run: function () {
|
|
86
|
+
var m = analyze("def foo(");
|
|
87
|
+
// No frames, no throw
|
|
88
|
+
assert.ok(m.frames.length === 0, "Expected 0 frames on parse error");
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
|
|
92
|
+
// ── Module-level symbols ──────────────────────────────────────────
|
|
93
|
+
|
|
94
|
+
{
|
|
95
|
+
name: "module_variable",
|
|
96
|
+
description: "A top-level assignment appears as a variable in the module frame",
|
|
97
|
+
run: function () {
|
|
98
|
+
var m = analyze("x = 42");
|
|
99
|
+
var syms = m.getAllSymbols();
|
|
100
|
+
assert_has(syms, "x", "module_variable");
|
|
101
|
+
var sym = find(syms, "x");
|
|
102
|
+
assert.strictEqual(sym.kind, "variable");
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
|
|
106
|
+
{
|
|
107
|
+
name: "module_function",
|
|
108
|
+
description: "A top-level def appears as a function symbol in the module frame",
|
|
109
|
+
run: function () {
|
|
110
|
+
var m = analyze("def greet(name):\n return name");
|
|
111
|
+
var syms = m.getAllSymbols();
|
|
112
|
+
assert_has(syms, "greet", "module_function");
|
|
113
|
+
var sym = find(syms, "greet");
|
|
114
|
+
assert.strictEqual(sym.kind, "function");
|
|
115
|
+
},
|
|
116
|
+
},
|
|
117
|
+
|
|
118
|
+
{
|
|
119
|
+
name: "module_class",
|
|
120
|
+
description: "A top-level class appears as a class symbol in the module frame",
|
|
121
|
+
run: function () {
|
|
122
|
+
var m = analyze("class Foo:\n pass");
|
|
123
|
+
var syms = m.getAllSymbols();
|
|
124
|
+
assert_has(syms, "Foo", "module_class");
|
|
125
|
+
var sym = find(syms, "Foo");
|
|
126
|
+
assert.strictEqual(sym.kind, "class");
|
|
127
|
+
},
|
|
128
|
+
},
|
|
129
|
+
|
|
130
|
+
// ── Function scope ────────────────────────────────────────────────
|
|
131
|
+
|
|
132
|
+
{
|
|
133
|
+
name: "function_params_in_function_scope",
|
|
134
|
+
description: "Function parameters appear with kind='parameter' inside the function frame",
|
|
135
|
+
run: function () {
|
|
136
|
+
var m = analyze([
|
|
137
|
+
"def add(a, b):",
|
|
138
|
+
" return a + b",
|
|
139
|
+
].join("\n"));
|
|
140
|
+
var syms = m.getAllSymbols();
|
|
141
|
+
assert_has(syms, "a");
|
|
142
|
+
assert_has(syms, "b");
|
|
143
|
+
var a_sym = find(syms, "a");
|
|
144
|
+
assert.strictEqual(a_sym.kind, "parameter");
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
|
|
148
|
+
{
|
|
149
|
+
name: "local_variable_in_function_scope",
|
|
150
|
+
description: "Assignments inside a function appear in the function frame",
|
|
151
|
+
run: function () {
|
|
152
|
+
var m = analyze([
|
|
153
|
+
"def foo():",
|
|
154
|
+
" result = 42",
|
|
155
|
+
" return result",
|
|
156
|
+
].join("\n"));
|
|
157
|
+
var syms = m.getAllSymbols();
|
|
158
|
+
assert_has(syms, "result");
|
|
159
|
+
var sym = find(syms, "result");
|
|
160
|
+
assert.strictEqual(sym.kind, "variable");
|
|
161
|
+
},
|
|
162
|
+
},
|
|
163
|
+
|
|
164
|
+
{
|
|
165
|
+
name: "function_frame_created",
|
|
166
|
+
description: "A def creates a frame with kind='function'",
|
|
167
|
+
run: function () {
|
|
168
|
+
var m = analyze("def bar():\n pass");
|
|
169
|
+
var fn_frame = m.frames.find(function (f) { return f.kind === "function"; });
|
|
170
|
+
assert.ok(fn_frame, "Expected a 'function' frame");
|
|
171
|
+
},
|
|
172
|
+
},
|
|
173
|
+
|
|
174
|
+
// ── Class scope ───────────────────────────────────────────────────
|
|
175
|
+
|
|
176
|
+
{
|
|
177
|
+
name: "class_frame_created",
|
|
178
|
+
description: "A class creates a frame with kind='class'",
|
|
179
|
+
run: function () {
|
|
180
|
+
var m = analyze("class MyClass:\n def method(self):\n return self");
|
|
181
|
+
var cls_frame = m.frames.find(function (f) { return f.kind === "class"; });
|
|
182
|
+
assert.ok(cls_frame, "Expected a 'class' frame");
|
|
183
|
+
assert.strictEqual(cls_frame.name, "MyClass");
|
|
184
|
+
},
|
|
185
|
+
},
|
|
186
|
+
|
|
187
|
+
{
|
|
188
|
+
name: "method_appears_in_class_scope",
|
|
189
|
+
description: "A method appears with kind='method' in the class frame",
|
|
190
|
+
run: function () {
|
|
191
|
+
var m = analyze([
|
|
192
|
+
"class Dog:",
|
|
193
|
+
" def bark(self):",
|
|
194
|
+
" return 'woof'",
|
|
195
|
+
].join("\n"));
|
|
196
|
+
var cls_frame = m.frames.find(function (f) { return f.kind === "class"; });
|
|
197
|
+
assert.ok(cls_frame, "Expected a class frame");
|
|
198
|
+
var method_sym = cls_frame.getSymbol("bark");
|
|
199
|
+
assert.ok(method_sym, "Expected 'bark' in class frame");
|
|
200
|
+
assert.strictEqual(method_sym.kind, "method");
|
|
201
|
+
},
|
|
202
|
+
},
|
|
203
|
+
|
|
204
|
+
{
|
|
205
|
+
name: "self_param_in_method_scope",
|
|
206
|
+
description: "'self' appears as a parameter inside a method frame",
|
|
207
|
+
run: function () {
|
|
208
|
+
var m = analyze([
|
|
209
|
+
"class Foo:",
|
|
210
|
+
" def do_thing(self, x):",
|
|
211
|
+
" return x",
|
|
212
|
+
].join("\n"));
|
|
213
|
+
var syms = m.getAllSymbols();
|
|
214
|
+
assert_has(syms, "self");
|
|
215
|
+
assert_has(syms, "x");
|
|
216
|
+
var self_sym = find(syms, "self");
|
|
217
|
+
assert.strictEqual(self_sym.kind, "parameter");
|
|
218
|
+
},
|
|
219
|
+
},
|
|
220
|
+
|
|
221
|
+
// ── Imports ───────────────────────────────────────────────────────
|
|
222
|
+
|
|
223
|
+
{
|
|
224
|
+
name: "from_import_symbol",
|
|
225
|
+
description: "'from mod import name' produces an import symbol",
|
|
226
|
+
run: function () {
|
|
227
|
+
var m = analyze("from mymod import foo\nfoo()", {
|
|
228
|
+
virtualFiles: { mymod: "def foo(): pass" },
|
|
229
|
+
});
|
|
230
|
+
var syms = m.getAllSymbols();
|
|
231
|
+
assert_has(syms, "foo");
|
|
232
|
+
var sym = find(syms, "foo");
|
|
233
|
+
assert.strictEqual(sym.kind, "import");
|
|
234
|
+
},
|
|
235
|
+
},
|
|
236
|
+
|
|
237
|
+
{
|
|
238
|
+
name: "from_import_alias",
|
|
239
|
+
description: "'from mod import name as alias' records the alias",
|
|
240
|
+
run: function () {
|
|
241
|
+
var m = analyze("from mymod import foo as bar\nbar()", {
|
|
242
|
+
virtualFiles: { mymod: "def foo(): pass" },
|
|
243
|
+
});
|
|
244
|
+
var syms = m.getAllSymbols();
|
|
245
|
+
assert_has(syms, "bar");
|
|
246
|
+
assert_not_has(syms, "foo", "from_import_alias: original name should not appear");
|
|
247
|
+
},
|
|
248
|
+
},
|
|
249
|
+
|
|
250
|
+
// ── For-loop variable ─────────────────────────────────────────────
|
|
251
|
+
|
|
252
|
+
{
|
|
253
|
+
name: "for_loop_variable",
|
|
254
|
+
description: "Loop variable from a for-in loop appears as a variable symbol",
|
|
255
|
+
run: function () {
|
|
256
|
+
var m = analyze([
|
|
257
|
+
"for item in [1, 2, 3]:",
|
|
258
|
+
" print(item)",
|
|
259
|
+
].join("\n"));
|
|
260
|
+
var syms = m.getAllSymbols();
|
|
261
|
+
assert_has(syms, "item");
|
|
262
|
+
var sym = find(syms, "item");
|
|
263
|
+
assert.strictEqual(sym.kind, "variable");
|
|
264
|
+
},
|
|
265
|
+
},
|
|
266
|
+
|
|
267
|
+
// ── *args and **kwargs ────────────────────────────────────────────
|
|
268
|
+
|
|
269
|
+
{
|
|
270
|
+
name: "star_args_captured",
|
|
271
|
+
description: "*args appears as a parameter in the function frame",
|
|
272
|
+
run: function () {
|
|
273
|
+
var m = analyze("def f(*args):\n return args");
|
|
274
|
+
var syms = m.getAllSymbols();
|
|
275
|
+
assert_has(syms, "args");
|
|
276
|
+
var sym = find(syms, "args");
|
|
277
|
+
assert.strictEqual(sym.kind, "parameter");
|
|
278
|
+
},
|
|
279
|
+
},
|
|
280
|
+
|
|
281
|
+
// ── params metadata on function SymbolInfo ────────────────────────
|
|
282
|
+
|
|
283
|
+
{
|
|
284
|
+
name: "function_params_metadata",
|
|
285
|
+
description: "A function SymbolInfo carries its parameter list",
|
|
286
|
+
run: function () {
|
|
287
|
+
var m = analyze("def greet(name, greeting):\n return greeting + name");
|
|
288
|
+
var sym = find(m.getAllSymbols(), "greet");
|
|
289
|
+
assert.ok(sym, "Expected 'greet' symbol");
|
|
290
|
+
assert.ok(Array.isArray(sym.params), "Expected params to be an array");
|
|
291
|
+
var param_names = sym.params.map(function (p) { return p.name; });
|
|
292
|
+
assert.ok(param_names.indexOf("name") >= 0, "Expected param 'name'");
|
|
293
|
+
assert.ok(param_names.indexOf("greeting") >= 0, "Expected param 'greeting'");
|
|
294
|
+
},
|
|
295
|
+
},
|
|
296
|
+
|
|
297
|
+
// ── Position queries ──────────────────────────────────────────────
|
|
298
|
+
|
|
299
|
+
{
|
|
300
|
+
name: "getScopesAtPosition_module",
|
|
301
|
+
description: "A position in module scope returns a module frame",
|
|
302
|
+
run: function () {
|
|
303
|
+
var m = analyze("x = 1\ny = 2");
|
|
304
|
+
var scopes = m.getScopesAtPosition(1, 1);
|
|
305
|
+
assert.ok(scopes.length >= 1);
|
|
306
|
+
var kinds = scopes.map(function (s) { return s.kind; });
|
|
307
|
+
assert.ok(kinds.indexOf("module") >= 0, "Expected 'module' in scopes");
|
|
308
|
+
},
|
|
309
|
+
},
|
|
310
|
+
|
|
311
|
+
{
|
|
312
|
+
name: "getScopesAtPosition_inside_function",
|
|
313
|
+
description: "A position inside a function body returns both function and module frames",
|
|
314
|
+
run: function () {
|
|
315
|
+
// line 1: def foo():
|
|
316
|
+
// line 2: x = 1
|
|
317
|
+
var m = analyze("def foo():\n x = 1");
|
|
318
|
+
// Position on line 2 is inside the function
|
|
319
|
+
var scopes = m.getScopesAtPosition(2, 5);
|
|
320
|
+
var kinds = scopes.map(function (s) { return s.kind; });
|
|
321
|
+
assert.ok(kinds.indexOf("function") >= 0, "Expected 'function' frame at line 2");
|
|
322
|
+
assert.ok(kinds.indexOf("module") >= 0, "Expected 'module' frame at line 2");
|
|
323
|
+
},
|
|
324
|
+
},
|
|
325
|
+
|
|
326
|
+
{
|
|
327
|
+
name: "getSymbolsAtPosition_module_visible_in_function",
|
|
328
|
+
description: "Module-level symbols are visible inside a function",
|
|
329
|
+
run: function () {
|
|
330
|
+
// line 1: CONST = 99
|
|
331
|
+
// line 2: def foo():
|
|
332
|
+
// line 3: return CONST
|
|
333
|
+
var m = analyze("CONST = 99\ndef foo():\n return CONST");
|
|
334
|
+
// Query inside foo's body
|
|
335
|
+
var syms = m.getSymbolsAtPosition(3, 5);
|
|
336
|
+
assert_has(syms, "CONST", "getSymbolsAtPosition_module_visible");
|
|
337
|
+
assert_has(syms, "foo", "getSymbolsAtPosition_module_visible");
|
|
338
|
+
},
|
|
339
|
+
},
|
|
340
|
+
|
|
341
|
+
{
|
|
342
|
+
name: "getSymbolsAtPosition_inner_shadows_outer",
|
|
343
|
+
description: "An inner-scope definition of the same name shadows the outer one",
|
|
344
|
+
run: function () {
|
|
345
|
+
// line 1: x = "outer"
|
|
346
|
+
// line 2: def foo():
|
|
347
|
+
// line 3: x = "inner"
|
|
348
|
+
// line 4: return x
|
|
349
|
+
var m = analyze("x = 'outer'\ndef foo():\n x = 'inner'\n return x");
|
|
350
|
+
var syms = m.getSymbolsAtPosition(4, 5); // inside foo
|
|
351
|
+
// getSymbolsAtPosition deduplicates: inner x wins
|
|
352
|
+
var x_matches = syms.filter(function (s) { return s.name === "x"; });
|
|
353
|
+
assert.strictEqual(x_matches.length, 1, "Expected exactly one 'x' (inner shadows outer)");
|
|
354
|
+
// The inner x's scope_depth should be greater than 0 (module depth)
|
|
355
|
+
assert.ok(x_matches[0].scope_depth > 0, "Expected inner 'x' to have scope_depth > 0");
|
|
356
|
+
},
|
|
357
|
+
},
|
|
358
|
+
|
|
359
|
+
{
|
|
360
|
+
name: "getSymbol_lookup",
|
|
361
|
+
description: "getSymbol() returns the correct SymbolInfo for a name at a position",
|
|
362
|
+
run: function () {
|
|
363
|
+
// line 1: def calculate(a, b):
|
|
364
|
+
// line 2: total = a + b
|
|
365
|
+
// line 3: return total
|
|
366
|
+
var m = analyze("def calculate(a, b):\n total = a + b\n return total");
|
|
367
|
+
var sym = m.getSymbol("a", 2, 5);
|
|
368
|
+
assert.ok(sym, "Expected to find 'a'");
|
|
369
|
+
assert.strictEqual(sym.kind, "parameter");
|
|
370
|
+
|
|
371
|
+
var total = m.getSymbol("total", 3, 5);
|
|
372
|
+
assert.ok(total, "Expected to find 'total'");
|
|
373
|
+
assert.strictEqual(total.kind, "variable");
|
|
374
|
+
},
|
|
375
|
+
},
|
|
376
|
+
|
|
377
|
+
{
|
|
378
|
+
name: "getSymbol_not_visible_outside_function",
|
|
379
|
+
description: "A function-local symbol is not visible from module scope",
|
|
380
|
+
run: function () {
|
|
381
|
+
// line 1: def foo():
|
|
382
|
+
// line 2: local_var = 1
|
|
383
|
+
// line 3: x = 2
|
|
384
|
+
var m = analyze("def foo():\n local_var = 1\n\nx = 2");
|
|
385
|
+
// Query from module scope (line 4 = after foo's body)
|
|
386
|
+
var sym = m.getSymbol("local_var", 4, 1);
|
|
387
|
+
assert.ok(!sym, "Expected 'local_var' to be invisible at module scope");
|
|
388
|
+
},
|
|
389
|
+
},
|
|
390
|
+
|
|
391
|
+
{
|
|
392
|
+
name: "getSymbol_returns_null_for_unknown",
|
|
393
|
+
description: "getSymbol() returns null for a name not in any visible scope",
|
|
394
|
+
run: function () {
|
|
395
|
+
var m = analyze("x = 1");
|
|
396
|
+
var sym = m.getSymbol("totally_unknown", 1, 1);
|
|
397
|
+
assert.strictEqual(sym, null);
|
|
398
|
+
},
|
|
399
|
+
},
|
|
400
|
+
|
|
401
|
+
// ── Defined-at positions ──────────────────────────────────────────
|
|
402
|
+
|
|
403
|
+
{
|
|
404
|
+
name: "defined_at_line_number",
|
|
405
|
+
description: "defined_at.line matches the 1-indexed line of the definition",
|
|
406
|
+
run: function () {
|
|
407
|
+
// line 1: x = 1 ← defined at line 1
|
|
408
|
+
// line 2: y = 2 ← defined at line 2
|
|
409
|
+
var m = analyze("x = 1\ny = 2");
|
|
410
|
+
var syms = m.getAllSymbols();
|
|
411
|
+
var x_sym = find(syms, "x");
|
|
412
|
+
var y_sym = find(syms, "y");
|
|
413
|
+
assert.ok(x_sym && x_sym.defined_at, "Expected defined_at on x");
|
|
414
|
+
assert.ok(y_sym && y_sym.defined_at, "Expected defined_at on y");
|
|
415
|
+
assert.strictEqual(x_sym.defined_at.line, 1, "x should be on line 1");
|
|
416
|
+
assert.strictEqual(y_sym.defined_at.line, 2, "y should be on line 2");
|
|
417
|
+
},
|
|
418
|
+
},
|
|
419
|
+
|
|
420
|
+
// ── Docstrings ────────────────────────────────────────────────────
|
|
421
|
+
|
|
422
|
+
{
|
|
423
|
+
name: "function_docstring_captured",
|
|
424
|
+
description: "A function docstring is captured in SymbolInfo.doc",
|
|
425
|
+
run: function () {
|
|
426
|
+
var m = analyze([
|
|
427
|
+
'def described():',
|
|
428
|
+
' "This function does something"',
|
|
429
|
+
' return 1',
|
|
430
|
+
].join("\n"));
|
|
431
|
+
var sym = find(m.getAllSymbols(), "described");
|
|
432
|
+
assert.ok(sym, "Expected 'described' symbol");
|
|
433
|
+
assert.ok(sym.doc && sym.doc.indexOf("does something") >= 0,
|
|
434
|
+
"Expected docstring to be captured, got: " + JSON.stringify(sym.doc));
|
|
435
|
+
},
|
|
436
|
+
},
|
|
437
|
+
|
|
438
|
+
// ── Nested functions ──────────────────────────────────────────────
|
|
439
|
+
|
|
440
|
+
{
|
|
441
|
+
name: "nested_function_scope",
|
|
442
|
+
description: "A function nested inside another creates its own inner frame",
|
|
443
|
+
run: function () {
|
|
444
|
+
var m = analyze([
|
|
445
|
+
"def outer():",
|
|
446
|
+
" def inner():",
|
|
447
|
+
" return 1",
|
|
448
|
+
" return inner()",
|
|
449
|
+
].join("\n"));
|
|
450
|
+
var fn_frames = m.frames.filter(function (f) { return f.kind === "function"; });
|
|
451
|
+
assert.ok(fn_frames.length >= 2, "Expected at least 2 function frames (outer + inner)");
|
|
452
|
+
var depths = fn_frames.map(function (f) { return f.depth; });
|
|
453
|
+
assert.ok(Math.max.apply(null, depths) >= 2,
|
|
454
|
+
"Expected at least one nested frame at depth >= 2");
|
|
455
|
+
},
|
|
456
|
+
},
|
|
457
|
+
|
|
458
|
+
// ── Exception variable ────────────────────────────────────────────
|
|
459
|
+
|
|
460
|
+
{
|
|
461
|
+
name: "except_variable_captured",
|
|
462
|
+
description: "The variable in an except clause appears as a symbol",
|
|
463
|
+
run: function () {
|
|
464
|
+
var m = analyze([
|
|
465
|
+
"try:",
|
|
466
|
+
" x = 1",
|
|
467
|
+
"except Exception as e:",
|
|
468
|
+
" print(e)",
|
|
469
|
+
].join("\n"));
|
|
470
|
+
var syms = m.getAllSymbols();
|
|
471
|
+
assert_has(syms, "e", "except_variable_captured");
|
|
472
|
+
var sym = find(syms, "e");
|
|
473
|
+
assert.strictEqual(sym.kind, "variable");
|
|
474
|
+
},
|
|
475
|
+
},
|
|
476
|
+
|
|
477
|
+
// ── getAllSymbols ─────────────────────────────────────────────────
|
|
478
|
+
|
|
479
|
+
{
|
|
480
|
+
name: "getAllSymbols_returns_all",
|
|
481
|
+
description: "getAllSymbols() includes symbols from all frames",
|
|
482
|
+
run: function () {
|
|
483
|
+
var m = analyze([
|
|
484
|
+
"module_var = 1",
|
|
485
|
+
"def fn(param):",
|
|
486
|
+
" local = 2",
|
|
487
|
+
"class Cls:",
|
|
488
|
+
" def method(self):",
|
|
489
|
+
" return self",
|
|
490
|
+
].join("\n"));
|
|
491
|
+
var names = names_of(m.getAllSymbols());
|
|
492
|
+
["module_var", "fn", "param", "local", "Cls", "method", "self"].forEach(function (n) {
|
|
493
|
+
assert.ok(names.indexOf(n) >= 0, "Expected '" + n + "' in getAllSymbols");
|
|
494
|
+
});
|
|
495
|
+
},
|
|
496
|
+
},
|
|
497
|
+
|
|
498
|
+
// ── inferred_class from literal assignments ───────────────────────
|
|
499
|
+
|
|
500
|
+
{
|
|
501
|
+
name: "inferred_class_list_literal",
|
|
502
|
+
description: "myArr = [] sets inferred_class to 'list'",
|
|
503
|
+
run: function () {
|
|
504
|
+
var m = analyze("myArr = []\npass");
|
|
505
|
+
var sym = find(m.getAllSymbols(), "myArr");
|
|
506
|
+
assert.ok(sym, "Expected 'myArr' symbol");
|
|
507
|
+
assert.strictEqual(sym.inferred_class, "list");
|
|
508
|
+
},
|
|
509
|
+
},
|
|
510
|
+
|
|
511
|
+
{
|
|
512
|
+
name: "inferred_class_dict_literal",
|
|
513
|
+
description: "myObj = {} sets inferred_class to 'dict'",
|
|
514
|
+
run: function () {
|
|
515
|
+
var m = analyze("myObj = {}\npass");
|
|
516
|
+
var sym = find(m.getAllSymbols(), "myObj");
|
|
517
|
+
assert.ok(sym, "Expected 'myObj' symbol");
|
|
518
|
+
assert.strictEqual(sym.inferred_class, "dict");
|
|
519
|
+
},
|
|
520
|
+
},
|
|
521
|
+
|
|
522
|
+
{
|
|
523
|
+
name: "inferred_class_str_literal",
|
|
524
|
+
description: "myStr = 'hello' sets inferred_class to 'str'",
|
|
525
|
+
run: function () {
|
|
526
|
+
var m = analyze("myStr = 'hello'\npass");
|
|
527
|
+
var sym = find(m.getAllSymbols(), "myStr");
|
|
528
|
+
assert.ok(sym, "Expected 'myStr' symbol");
|
|
529
|
+
assert.strictEqual(sym.inferred_class, "str");
|
|
530
|
+
},
|
|
531
|
+
},
|
|
532
|
+
|
|
533
|
+
{
|
|
534
|
+
name: "inferred_class_number_literal",
|
|
535
|
+
description: "myNum = 42 sets inferred_class to 'number'",
|
|
536
|
+
run: function () {
|
|
537
|
+
var m = analyze("myNum = 42\npass");
|
|
538
|
+
var sym = find(m.getAllSymbols(), "myNum");
|
|
539
|
+
assert.ok(sym, "Expected 'myNum' symbol");
|
|
540
|
+
assert.strictEqual(sym.inferred_class, "number");
|
|
541
|
+
},
|
|
542
|
+
},
|
|
543
|
+
|
|
544
|
+
{
|
|
545
|
+
name: "inferred_class_constructor_call",
|
|
546
|
+
description: "x = Foo() sets inferred_class to 'Foo'",
|
|
547
|
+
run: function () {
|
|
548
|
+
var m = analyze("class Foo:\n pass\nx = Foo()\npass");
|
|
549
|
+
var sym = find(m.getAllSymbols(), "x");
|
|
550
|
+
assert.ok(sym, "Expected 'x' symbol");
|
|
551
|
+
assert.strictEqual(sym.inferred_class, "Foo");
|
|
552
|
+
},
|
|
553
|
+
},
|
|
554
|
+
|
|
555
|
+
{
|
|
556
|
+
name: "inferred_class_function_local_list",
|
|
557
|
+
description: "Inside a function, myArr = [] sets inferred_class to 'list'",
|
|
558
|
+
run: function () {
|
|
559
|
+
var m = analyze([
|
|
560
|
+
"def main():",
|
|
561
|
+
" myArr = []",
|
|
562
|
+
" return myArr",
|
|
563
|
+
].join("\n"));
|
|
564
|
+
var sym = find(m.getAllSymbols(), "myArr");
|
|
565
|
+
assert.ok(sym, "Expected 'myArr' symbol in function scope");
|
|
566
|
+
assert.strictEqual(sym.inferred_class, "list",
|
|
567
|
+
"Expected inferred_class='list', got: " + sym.inferred_class);
|
|
568
|
+
},
|
|
569
|
+
},
|
|
570
|
+
|
|
571
|
+
{
|
|
572
|
+
name: "inferred_class_function_local_dict",
|
|
573
|
+
description: "Inside a function, myObj = {} sets inferred_class to 'dict'",
|
|
574
|
+
run: function () {
|
|
575
|
+
var m = analyze([
|
|
576
|
+
"def main():",
|
|
577
|
+
" myObj = {}",
|
|
578
|
+
" return myObj",
|
|
579
|
+
].join("\n"));
|
|
580
|
+
var sym = find(m.getAllSymbols(), "myObj");
|
|
581
|
+
assert.ok(sym, "Expected 'myObj' symbol in function scope");
|
|
582
|
+
assert.strictEqual(sym.inferred_class, "dict");
|
|
583
|
+
},
|
|
584
|
+
},
|
|
585
|
+
|
|
586
|
+
{
|
|
587
|
+
name: "inferred_class_function_local_str",
|
|
588
|
+
description: "Inside a function, myStr = 'x' sets inferred_class to 'str'",
|
|
589
|
+
run: function () {
|
|
590
|
+
var m = analyze([
|
|
591
|
+
"def main():",
|
|
592
|
+
" myStr = 'hello'",
|
|
593
|
+
" return myStr",
|
|
594
|
+
].join("\n"));
|
|
595
|
+
var sym = find(m.getAllSymbols(), "myStr");
|
|
596
|
+
assert.ok(sym, "Expected 'myStr' symbol in function scope");
|
|
597
|
+
assert.strictEqual(sym.inferred_class, "str");
|
|
598
|
+
},
|
|
599
|
+
},
|
|
600
|
+
|
|
601
|
+
{
|
|
602
|
+
name: "inferred_class_async_function_local",
|
|
603
|
+
description: "Inside async def, list literal sets inferred_class to 'list'",
|
|
604
|
+
run: function () {
|
|
605
|
+
var m = analyze([
|
|
606
|
+
"async def main():",
|
|
607
|
+
" myArr = []",
|
|
608
|
+
" return myArr",
|
|
609
|
+
].join("\n"));
|
|
610
|
+
var sym = find(m.getAllSymbols(), "myArr");
|
|
611
|
+
assert.ok(sym, "Expected 'myArr' symbol in async function scope");
|
|
612
|
+
assert.strictEqual(sym.inferred_class, "list");
|
|
613
|
+
},
|
|
614
|
+
},
|
|
615
|
+
|
|
616
|
+
{
|
|
617
|
+
name: "inferred_class_no_inference_for_variable_rhs",
|
|
618
|
+
description: "x = some_var does not set inferred_class (unknown rhs)",
|
|
619
|
+
run: function () {
|
|
620
|
+
var m = analyze("some_var = 1\nx = some_var\npass");
|
|
621
|
+
var sym = find(m.getAllSymbols(), "x");
|
|
622
|
+
assert.ok(sym, "Expected 'x' symbol");
|
|
623
|
+
assert.ok(!sym.inferred_class,
|
|
624
|
+
"Expected no inferred_class for variable assignment, got: " + sym.inferred_class);
|
|
625
|
+
},
|
|
626
|
+
},
|
|
627
|
+
|
|
628
|
+
// ── Walrus operator (:=) ─────────────────────────────────────────────
|
|
629
|
+
|
|
630
|
+
{
|
|
631
|
+
name: "walrus_registers_symbol_in_scope",
|
|
632
|
+
description: "name := expr registers name as a variable in the enclosing scope",
|
|
633
|
+
run: function () {
|
|
634
|
+
var m = analyze([
|
|
635
|
+
"if (n := 42) > 0:",
|
|
636
|
+
" pass",
|
|
637
|
+
].join("\n"));
|
|
638
|
+
var syms = m.getAllSymbols();
|
|
639
|
+
assert_has(syms, "n", "walrus LHS should be registered");
|
|
640
|
+
var sym = find(syms, "n");
|
|
641
|
+
assert.strictEqual(sym.kind, "variable");
|
|
642
|
+
},
|
|
643
|
+
},
|
|
644
|
+
|
|
645
|
+
{
|
|
646
|
+
name: "walrus_in_function_scope",
|
|
647
|
+
description: "walrus inside a function registers name in the function scope",
|
|
648
|
+
run: function () {
|
|
649
|
+
var m = analyze([
|
|
650
|
+
"def check(data):",
|
|
651
|
+
" if (result := len(data)) > 0:",
|
|
652
|
+
" return result",
|
|
653
|
+
" return 0",
|
|
654
|
+
].join("\n"));
|
|
655
|
+
var syms = m.getAllSymbols();
|
|
656
|
+
assert_has(syms, "result", "walrus LHS in function should be registered");
|
|
657
|
+
var sym = find(syms, "result");
|
|
658
|
+
assert.strictEqual(sym.kind, "variable");
|
|
659
|
+
},
|
|
660
|
+
},
|
|
661
|
+
|
|
662
|
+
// ── Lambda ────────────────────────────────────────────────────────
|
|
663
|
+
|
|
664
|
+
{
|
|
665
|
+
name: "lambda_parameter_in_scope",
|
|
666
|
+
description: "lambda parameters are registered as 'parameter' symbols inside the lambda scope",
|
|
667
|
+
run: function () {
|
|
668
|
+
var m = analyze([
|
|
669
|
+
"add = lambda x, y: x + y",
|
|
670
|
+
].join("\n"));
|
|
671
|
+
var syms = m.getAllSymbols();
|
|
672
|
+
assert_has(syms, "x", "lambda param x should be in scope");
|
|
673
|
+
assert_has(syms, "y", "lambda param y should be in scope");
|
|
674
|
+
var sx = find(syms, "x");
|
|
675
|
+
assert.strictEqual(sx.kind, "parameter");
|
|
676
|
+
},
|
|
677
|
+
},
|
|
678
|
+
|
|
679
|
+
{
|
|
680
|
+
name: "lambda_creates_function_scope",
|
|
681
|
+
description: "lambda body creates a new function scope frame",
|
|
682
|
+
run: function () {
|
|
683
|
+
var m = analyze([
|
|
684
|
+
"fn = lambda x: x * 2",
|
|
685
|
+
].join("\n"));
|
|
686
|
+
var function_frames = m.frames.filter(function (f) { return f.kind === "function"; });
|
|
687
|
+
assert.ok(function_frames.length >= 1, "Expected at least one function frame for the lambda");
|
|
688
|
+
},
|
|
689
|
+
},
|
|
690
|
+
|
|
691
|
+
{
|
|
692
|
+
name: "lambda_closure_outer_symbol_accessible",
|
|
693
|
+
description: "symbols assigned in outer scope are visible when lambda is assigned to them",
|
|
694
|
+
run: function () {
|
|
695
|
+
var m = analyze([
|
|
696
|
+
"def make_adder(n):",
|
|
697
|
+
" return lambda x: x + n",
|
|
698
|
+
].join("\n"));
|
|
699
|
+
var syms = m.getAllSymbols();
|
|
700
|
+
assert_has(syms, "n", "outer parameter n should be in scope");
|
|
701
|
+
assert_has(syms, "x", "lambda parameter x should be in scope");
|
|
702
|
+
},
|
|
703
|
+
},
|
|
704
|
+
|
|
705
|
+
// ── Virtual file imports ──────────────────────────────────────────
|
|
706
|
+
|
|
707
|
+
{
|
|
708
|
+
name: "virtual_import_creates_symbol",
|
|
709
|
+
description: "Importing from a virtual file produces an import symbol",
|
|
710
|
+
run: function () {
|
|
711
|
+
var m = analyze("from helper import square\nprint(square(4))", {
|
|
712
|
+
virtualFiles: { helper: "def square(n): return n * n" },
|
|
713
|
+
});
|
|
714
|
+
var syms = m.getAllSymbols();
|
|
715
|
+
assert_has(syms, "square");
|
|
716
|
+
var sym = find(syms, "square");
|
|
717
|
+
assert.strictEqual(sym.kind, "import");
|
|
718
|
+
},
|
|
719
|
+
},
|
|
720
|
+
|
|
721
|
+
// ── Variable type annotations ──────────────────────────────────────
|
|
722
|
+
|
|
723
|
+
{
|
|
724
|
+
name: "annotated_assign_registers_symbol",
|
|
725
|
+
description: "x: int = 1 registers x as a variable symbol",
|
|
726
|
+
run: function () {
|
|
727
|
+
var m = analyze("x: int = 1");
|
|
728
|
+
var syms = m.getAllSymbols();
|
|
729
|
+
assert_has(syms, "x");
|
|
730
|
+
var sym = find(syms, "x");
|
|
731
|
+
assert.strictEqual(sym.kind, "variable");
|
|
732
|
+
},
|
|
733
|
+
},
|
|
734
|
+
|
|
735
|
+
{
|
|
736
|
+
name: "annotated_assign_inferred_class",
|
|
737
|
+
description: "x: MyType = val sets inferred_class to 'MyType'",
|
|
738
|
+
run: function () {
|
|
739
|
+
var m = analyze("x: MyType = MyType()");
|
|
740
|
+
var syms = m.getAllSymbols();
|
|
741
|
+
var sym = find(syms, "x");
|
|
742
|
+
assert.ok(sym, "symbol x should exist");
|
|
743
|
+
assert.strictEqual(sym.inferred_class, "MyType");
|
|
744
|
+
},
|
|
745
|
+
},
|
|
746
|
+
|
|
747
|
+
{
|
|
748
|
+
name: "annotated_assign_only_registers_symbol",
|
|
749
|
+
description: "x: int (no value) still registers x as a variable",
|
|
750
|
+
run: function () {
|
|
751
|
+
var m = analyze("x: int");
|
|
752
|
+
var syms = m.getAllSymbols();
|
|
753
|
+
assert_has(syms, "x");
|
|
754
|
+
var sym = find(syms, "x");
|
|
755
|
+
assert.strictEqual(sym.kind, "variable");
|
|
756
|
+
},
|
|
757
|
+
},
|
|
758
|
+
|
|
759
|
+
{
|
|
760
|
+
name: "annotated_assign_in_function",
|
|
761
|
+
description: "x: int = 1 inside a function registers x in function scope",
|
|
762
|
+
run: function () {
|
|
763
|
+
var m = analyze("def f():\n x: int = 10\n return x");
|
|
764
|
+
var all = m.getAllSymbols();
|
|
765
|
+
assert_has(all, "x");
|
|
766
|
+
var xsym = find(all, "x");
|
|
767
|
+
assert.strictEqual(xsym.kind, "variable");
|
|
768
|
+
// x should be in function scope (depth 1), not module scope (depth 0)
|
|
769
|
+
assert.ok(xsym.scope_depth > 0, "x should be in a nested scope");
|
|
770
|
+
},
|
|
771
|
+
},
|
|
772
|
+
|
|
773
|
+
];
|
|
774
|
+
|
|
775
|
+
return TESTS;
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
// ---------------------------------------------------------------------------
|
|
779
|
+
// Runner
|
|
780
|
+
// ---------------------------------------------------------------------------
|
|
781
|
+
|
|
782
|
+
function run_tests(TESTS, filter) {
|
|
783
|
+
var tests = filter
|
|
784
|
+
? TESTS.filter(function (t) { return t.name === filter; })
|
|
785
|
+
: TESTS;
|
|
786
|
+
|
|
787
|
+
if (tests.length === 0) {
|
|
788
|
+
console.error(colored("No test found: " + filter, "red"));
|
|
789
|
+
process.exit(1);
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
var failures = [];
|
|
793
|
+
|
|
794
|
+
tests.forEach(function (test) {
|
|
795
|
+
try {
|
|
796
|
+
test.run();
|
|
797
|
+
console.log(colored("PASS " + test.name, "green") +
|
|
798
|
+
" – " + test.description);
|
|
799
|
+
} catch (e) {
|
|
800
|
+
failures.push(test.name);
|
|
801
|
+
console.log(colored("FAIL " + test.name, "red") +
|
|
802
|
+
"\n " + (e.message || String(e)) + "\n");
|
|
803
|
+
}
|
|
804
|
+
});
|
|
805
|
+
|
|
806
|
+
console.log("");
|
|
807
|
+
if (failures.length) {
|
|
808
|
+
console.log(colored(failures.length + " test(s) failed.", "red"));
|
|
809
|
+
} else {
|
|
810
|
+
console.log(colored("All " + tests.length + " scope-analysis tests passed!", "green"));
|
|
811
|
+
}
|
|
812
|
+
process.exit(failures.length ? 1 : 0);
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
// ---------------------------------------------------------------------------
|
|
816
|
+
// Entry point
|
|
817
|
+
// ---------------------------------------------------------------------------
|
|
818
|
+
|
|
819
|
+
var analyzer_path = url.pathToFileURL(
|
|
820
|
+
path.join(__dirname, "../../src/monaco-language-service/analyzer.js")
|
|
821
|
+
).href;
|
|
822
|
+
|
|
823
|
+
var filter = process.argv[2] || null;
|
|
824
|
+
|
|
825
|
+
import(analyzer_path).then(function (mod) {
|
|
826
|
+
var SourceAnalyzer = mod.SourceAnalyzer;
|
|
827
|
+
var RS = compiler_module.create_compiler();
|
|
828
|
+
var TESTS = make_tests(SourceAnalyzer, RS);
|
|
829
|
+
run_tests(TESTS, filter);
|
|
830
|
+
}).catch(function (e) {
|
|
831
|
+
console.error(colored("Failed to load analyzer module:", "red"), e);
|
|
832
|
+
process.exit(1);
|
|
833
|
+
});
|