detached 922360b

test(expr): add the languageservices cross-language expression fixtures

commit
922360bcd924d9eaebb285b0137b44a90217f505
author
brice · · 2026-10-12 17:09 UTC
parent
b6c4c3a
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
30 files · +5785 -0
M THIRD_PARTY.md +2 -0
@@ -6,6 +6,8 @@ Test fixtures and schemas under `testdata/`, `workflow/testdata/` and `template/
66
77 https://github.com/actions/languageservices
88
9+Used: `expr/testdata/languageservices/*.json` (the cross-language expression fixtures, commit 4043eda158e16579cc5fb1b0b07a4bce2a76f0b5) and the `@actions/expressions` package that the other `expr` oracle files were generated from.
10+
911 ```
1012 MIT License
1113
A expr/testdata/languageservices/SOURCE +6 -0
@@ -0,0 +1,6 @@
1+The *.json files in this directory are copied unmodified from
2+https://github.com/actions/languageservices, directory expressions/testdata,
3+commit 4043eda158e16579cc5fb1b0b07a4bce2a76f0b5 (MIT, Copyright GitHub, Inc.;
4+see ../../../THIRD_PARTY.md). They are shared by the TypeScript and the C#
5+implementations of GitHub Actions expressions. ../../xlang_test.go replays
6+them the way expressions/src/xlang.test.ts of that repository does.
A expr/testdata/languageservices/basic.json +64 -0
@@ -0,0 +1,64 @@
1+{
2+ "empty_expression": [{
3+ "expr": "",
4+ "result": {
5+ "kind": "Null",
6+ "value": null
7+ }
8+ }],
9+ "equal_simple": [{
10+ "expr": "1 == 2",
11+ "result": {
12+ "kind": "Boolean",
13+ "value": false
14+ }
15+ }],
16+ "context_simple_access": [{
17+ "expr": "simple",
18+ "result": {
19+ "kind": "String",
20+ "value": "foo"
21+ },
22+ "contexts": {
23+ "simple": "foo"
24+ }
25+ }],
26+ "context_case-insensitive": [{
27+ "expr": "SIMple.TEst",
28+ "result": {
29+ "kind": "Number",
30+ "value": 123.0
31+ },
32+ "contexts": {
33+ "simPLE": {
34+ "teST": 123
35+ }
36+ }
37+ }],
38+ "context access with wildcard": [{
39+ "expr": "toJson(input.*.foo)",
40+ "result": {
41+ "kind": "String",
42+ "value": "[\n 32,\n 42,\n -10,\n 0,\n 2,\n 17\n]"
43+ },
44+ "contexts": {
45+ "input": {
46+ "test": { "foo": 32 },
47+ "test2": { "foo": 42 },
48+ "test3": { "foo": -10 },
49+ "test4": { "foo": 0 },
50+ "test5": { "foo": 2 },
51+ "test6": { "foo": 17 }
52+ }
53+ }
54+ }],
55+ "unknown context": [
56+ {
57+ "expr": "nosuchcontext.foo",
58+ "err": {
59+ "kind": "parsing",
60+ "value": "Unrecognized named-value: 'nosuchcontext'. Located at position 1 within expression: nosuchcontext.foo"
61+ }
62+ }
63+ ]
64+}
A expr/testdata/languageservices/case.json +157 -0
@@ -0,0 +1,157 @@
1+{
2+ "case": [
3+ {
4+ "expr": "case(true, 'first', 'default')",
5+ "result": { "kind": "String", "value": "first" }
6+ },
7+ {
8+ "expr": "case(false, 'first', 'default')",
9+ "result": { "kind": "String", "value": "default" }
10+ },
11+ {
12+ "expr": "case(true, 'first', false, 'second', 'default')",
13+ "result": { "kind": "String", "value": "first" }
14+ },
15+ {
16+ "expr": "case(false, 'first', true, 'second', 'default')",
17+ "result": { "kind": "String", "value": "second" }
18+ },
19+ {
20+ "expr": "case(false, 'first', false, 'second', 'default')",
21+ "result": { "kind": "String", "value": "default" }
22+ },
23+ {
24+ "expr": "case(1 == 1, 'equal', 'not equal')",
25+ "result": { "kind": "String", "value": "equal" }
26+ },
27+ {
28+ "expr": "case(1 == 2, 'equal', 'not equal')",
29+ "result": { "kind": "String", "value": "not equal" }
30+ },
31+ {
32+ "expr": "case(github.ref == 'refs/heads/main', 'main', github.event_name == 'pull_request', 'pr', 'other')",
33+ "contexts": {
34+ "github": {
35+ "ref": "refs/heads/main",
36+ "event_name": "push"
37+ }
38+ },
39+ "result": { "kind": "String", "value": "main" }
40+ },
41+ {
42+ "expr": "case(github.ref == 'refs/heads/main', 'main', github.event_name == 'pull_request', 'pr', 'other')",
43+ "contexts": {
44+ "github": {
45+ "ref": "refs/heads/develop",
46+ "event_name": "pull_request"
47+ }
48+ },
49+ "result": { "kind": "String", "value": "pr" }
50+ },
51+ {
52+ "expr": "case(github.ref == 'refs/heads/main', 'main', github.event_name == 'pull_request', 'pr', 'other')",
53+ "contexts": {
54+ "github": {
55+ "ref": "refs/heads/develop",
56+ "event_name": "push"
57+ }
58+ },
59+ "result": { "kind": "String", "value": "other" }
60+ },
61+ {
62+ "expr": "case(true, 123, 456)",
63+ "result": { "kind": "Number", "value": 123 }
64+ },
65+ {
66+ "expr": "case(false, 123, 456)",
67+ "result": { "kind": "Number", "value": 456 }
68+ },
69+ {
70+ "expr": "case(github.event == 'pull_request', 0, 1)",
71+ "contexts": {
72+ "github": {
73+ "event": "pull_request"
74+ }
75+ },
76+ "result": { "kind": "Number", "value": 0 }
77+ },
78+ {
79+ "expr": "case(false, 0, 1)",
80+ "result": { "kind": "Number", "value": 1 }
81+ },
82+ {
83+ "expr": "case(true, false, true)",
84+ "result": { "kind": "Boolean", "value": false }
85+ },
86+ {
87+ "expr": "case(false, false, true)",
88+ "result": { "kind": "Boolean", "value": true }
89+ },
90+ {
91+ "expr": "case(true, '', 'default')",
92+ "result": { "kind": "String", "value": "" }
93+ },
94+ {
95+ "expr": "case(false, 'first', '')",
96+ "result": { "kind": "String", "value": "" }
97+ },
98+ {
99+ "expr": "case(true, fromJSON('[1,2,3]'), 'default')",
100+ "result": { "kind": "Array", "value": [1, 2, 3] }
101+ },
102+ {
103+ "expr": "case(true, fromJSON('{\"key\":\"value\"}'), 'default')",
104+ "result": { "kind": "Object", "value": { "key": "value" } }
105+ },
106+ {
107+ "expr": "case(false, 'first', false, 'second', false, 'third', false, 'fourth', 'default')",
108+ "result": { "kind": "String", "value": "default" }
109+ },
110+ {
111+ "expr": "case(false, 'first', false, 'second', true, 'third', false, 'fourth', 'default')",
112+ "result": { "kind": "String", "value": "third" }
113+ },
114+ {
115+ "expr": "case('not a boolean', 'first', 'default')",
116+ "err": {
117+ "kind": "evaluation",
118+ "value": "case predicate must evaluate to a boolean value"
119+ }
120+ },
121+ {
122+ "expr": "case(1, 'first', 'default')",
123+ "err": {
124+ "kind": "evaluation",
125+ "value": "case predicate must evaluate to a boolean value"
126+ }
127+ },
128+ {
129+ "expr": "case(null, 'first', 'default')",
130+ "err": {
131+ "kind": "evaluation",
132+ "value": "case predicate must evaluate to a boolean value"
133+ }
134+ },
135+ {
136+ "expr": "case(fromJSON('[]'), 'first', 'default')",
137+ "err": {
138+ "kind": "evaluation",
139+ "value": "case predicate must evaluate to a boolean value"
140+ }
141+ },
142+ {
143+ "expr": "case(fromJSON('{}'), 'first', 'default')",
144+ "err": {
145+ "kind": "evaluation",
146+ "value": "case predicate must evaluate to a boolean value"
147+ }
148+ },
149+ {
150+ "expr": "case(true, 'first', false, 'second')",
151+ "err": {
152+ "kind": "parsing",
153+ "value": "Even number of parameters supplied, requires an odd number of parameters: 'case'. Located at position 1 within expression: case(true, 'first', false, 'second')"
154+ }
155+ }
156+ ]
157+}
A expr/testdata/languageservices/coerce_boolean.json +4 -0
@@ -0,0 +1,4 @@
1+{
2+ "refer ./operator_not.json": [
3+ ]
4+}⏎̸
A expr/testdata/languageservices/coerce_number.json +124 -0
@@ -0,0 +1,124 @@
1+{
2+ "null": [
3+ {
4+ "expr": "null == 0",
5+ "result": { "kind": "Boolean", "value": true }
6+ }
7+ ],
8+ "boolean": [
9+ {
10+ "expr": "true == 1",
11+ "result": { "kind": "Boolean", "value": true }
12+ },
13+ {
14+ "expr": "false == 0",
15+ "result": { "kind": "Boolean", "value": true }
16+ }
17+ ],
18+ "string": [
19+ {
20+ "expr": "'' == 0",
21+ "result": { "kind": "Boolean", "value": true }
22+ },
23+ {
24+ "expr": "' 123456.789 ' == 123456.789",
25+ "result": { "kind": "Boolean", "value": true }
26+ },
27+ {
28+ "expr": "' +123456.789 ' == 123456.789",
29+ "result": { "kind": "Boolean", "value": true }
30+ },
31+ {
32+ "expr": "' -123456.789 ' == -123456.789",
33+ "result": { "kind": "Boolean", "value": true }
34+ },
35+ {
36+ "expr": "' 0xff ' == 255",
37+ "result": { "kind": "Boolean", "value": true }
38+ },
39+ {
40+ "expr": "' 0xFF ' == 255",
41+ "result": { "kind": "Boolean", "value": true }
42+ },
43+ {
44+ "expr": "' 0o10 ' == 8",
45+ "result": { "kind": "Boolean", "value": true }
46+ },
47+ {
48+ "expr": "' Infinity ' == Infinity",
49+ "result": { "kind": "Boolean", "value": true }
50+ },
51+ {
52+ "expr": "' -Infinity ' == -Infinity",
53+ "result": { "kind": "Boolean", "value": true }
54+ },
55+ {
56+ "expr": "' NaN ' != NaN",
57+ "result": { "kind": "Boolean", "value": true }
58+ },
59+ {
60+ "expr": "' NaN ' == NaN",
61+ "result": { "kind": "Boolean", "value": false }
62+ },
63+ {
64+ "expr": "' NaN ' > NaN",
65+ "result": { "kind": "Boolean", "value": false }
66+ },
67+ {
68+ "expr": "' NaN ' < NaN",
69+ "result": { "kind": "Boolean", "value": false }
70+ },
71+ {
72+ "expr": "' abc ' != NaN",
73+ "result": { "kind": "Boolean", "value": true }
74+ },
75+ {
76+ "expr": "' abc ' == NaN",
77+ "result": { "kind": "Boolean", "value": false }
78+ },
79+ {
80+ "expr": "' abc ' > NaN",
81+ "result": { "kind": "Boolean", "value": false }
82+ },
83+ {
84+ "expr": "' abc ' < NaN",
85+ "result": { "kind": "Boolean", "value": false }
86+ }
87+ ],
88+ "array": [
89+ {
90+ "expr": "fromjson('[]') != NaN",
91+ "result": { "kind": "Boolean", "value": true }
92+ },
93+ {
94+ "expr": "fromjson('[]') == NaN",
95+ "result": { "kind": "Boolean", "value": false }
96+ },
97+ {
98+ "expr": "fromjson('[]') > NaN",
99+ "result": { "kind": "Boolean", "value": false }
100+ },
101+ {
102+ "expr": "fromjson('[]') < NaN",
103+ "result": { "kind": "Boolean", "value": false }
104+ }
105+ ],
106+ "object": [
107+ {
108+ "expr": "fromjson('[]') != NaN",
109+ "result": { "kind": "Boolean", "value": true }
110+ },
111+ {
112+ "expr": "fromjson('[]') == NaN",
113+ "result": { "kind": "Boolean", "value": false }
114+ },
115+ {
116+ "expr": "fromjson('[]') > NaN",
117+ "result": { "kind": "Boolean", "value": false }
118+ },
119+ {
120+ "expr": "fromjson('[]') < NaN",
121+ "result": { "kind": "Boolean", "value": false }
122+ }
123+ ]
124+}⏎̸
A expr/testdata/languageservices/coerce_string.json +178 -0
@@ -0,0 +1,178 @@
1+{
2+ "null": [
3+ {
4+ "expr": "format('{0}', null)",
5+ "result": { "kind": "String", "value": "" }
6+ }
7+ ],
8+ "boolean": [
9+ {
10+ "expr": "format('{0}', true)",
11+ "result": { "kind": "String", "value": "true" }
12+ },
13+ {
14+ "expr": "format('{0}', false)",
15+ "result": { "kind": "String", "value": "false" }
16+ }
17+ ],
18+ "number": [
19+ {
20+ "expr": "format('{0}', 1)",
21+ "result": { "kind": "String", "value": "1" }
22+ },
23+ {
24+ "expr": "format('{0}', .5)",
25+ "result": { "kind": "String", "value": "0.5" }
26+ },
27+ {
28+ "expr": "format('{0}', 0.5)",
29+ "result": { "kind": "String", "value": "0.5" }
30+ },
31+ {
32+ "expr": "format('{0}', 2)",
33+ "result": { "kind": "String", "value": "2" }
34+ },
35+ {
36+ "expr": "format('{0}', -1)",
37+ "result": { "kind": "String", "value": "-1" }
38+ },
39+ {
40+ "expr": "format('{0}', -.5)",
41+ "result": { "kind": "String", "value": "-0.5" }
42+ },
43+ {
44+ "expr": "format('{0}', -0.5)",
45+ "result": { "kind": "String", "value": "-0.5" }
46+ },
47+ {
48+ "expr": "format('{0}', -2.0)",
49+ "result": { "kind": "String", "value": "-2" }
50+ },
51+ {
52+ "expr": "format('{0}', 0)",
53+ "result": { "kind": "String", "value": "0" }
54+ },
55+ {
56+ "expr": "format('{0}', 0.0)",
57+ "result": { "kind": "String", "value": "0" }
58+ },
59+ {
60+ "expr": "format('{0}', -0)",
61+ "result": { "kind": "String", "value": "0" }
62+ },
63+ {
64+ "expr": "format('{0}', -0.0)",
65+ "result": { "kind": "String", "value": "0" }
66+ },
67+ {
68+ "expr": "format('{0}', 123456.789)",
69+ "result": { "kind": "String", "value": "123456.789" }
70+ },
71+ {
72+ "expr": "format('{0}', +123456.789)",
73+ "result": { "kind": "String", "value": "123456.789" }
74+ },
75+ {
76+ "expr": "format('{0}', -123456.789)",
77+ "result": { "kind": "String", "value": "-123456.789" }
78+ },
79+ {
80+ "expr": "format('{0}', 0.84551240822557006)",
81+ "result": { "kind": "String", "value": "0.84551240822557" }
82+ },
83+ {
84+ "expr": "format('{0}', 1.9)",
85+ "result": { "kind": "String", "value": "1.9" }
86+ },
87+ {
88+ "expr": "format('{0}', 1234.56)",
89+ "result": { "kind": "String", "value": "1234.56" }
90+ },
91+ {
92+ "expr": "format('{0}', 0xff)",
93+ "result": { "kind": "String", "value": "255" }
94+ },
95+ {
96+ "expr": "format('{0}', 0xFF)",
97+ "result": { "kind": "String", "value": "255" }
98+ },
99+ {
100+ "expr": "format('{0}', 0o10)",
101+ "result": { "kind": "String", "value": "8" }
102+ },
103+ {
104+ "expr": "format('{0}', 1.2e2)",
105+ "result": { "kind": "String", "value": "120" }
106+ },
107+ {
108+ "expr": "format('{0}', 1.2E2)",
109+ "result": { "kind": "String", "value": "120" }
110+ },
111+ {
112+ "expr": "format('{0}', 1.2e+2)",
113+ "result": { "kind": "String", "value": "120" }
114+ },
115+ {
116+ "expr": "format('{0}', 1.2E+2)",
117+ "result": { "kind": "String", "value": "120" }
118+ },
119+ {
120+ "expr": "format('{0}', 1.2e-2)",
121+ "result": { "kind": "String", "value": "0.012" }
122+ },
123+ {
124+ "expr": "format('{0}', 1.2E-2)",
125+ "result": { "kind": "String", "value": "0.012" }
126+ },
127+ {
128+ "expr": "format('{0}', Infinity)",
129+ "result": { "kind": "String", "value": "Infinity" }
130+ },
131+ {
132+ "expr": "format('{0}', -Infinity)",
133+ "result": { "kind": "String", "value": "-Infinity" }
134+ },
135+ {
136+ "expr": "format('{0}', NaN)",
137+ "result": { "kind": "String", "value": "NaN" }
138+ }
139+ ],
140+ "string": [
141+ {
142+ "expr": "format('{0}', 'string value')",
143+ "result": { "kind": "String", "value": "string value" }
144+ }
145+ ],
146+ "array": [
147+ {
148+ "expr": "format('{0}', context)",
149+ "contexts": {
150+ "context": []
151+ },
152+ "result": { "kind": "String", "value": "Array" }
153+ },
154+ {
155+ "expr": "format('{0}', context)",
156+ "contexts": {
157+ "context": [1, 2, 3]
158+ },
159+ "result": { "kind": "String", "value": "Array" }
160+ }
161+ ],
162+ "object": [
163+ {
164+ "expr": "format('{0}', context)",
165+ "contexts": {
166+ "context": {}
167+ },
168+ "result": { "kind": "String", "value": "Object" }
169+ },
170+ {
171+ "expr": "format('{0}', context)",
172+ "contexts": {
173+ "context": { "a": 1, "b": 2, "c": 3 }
174+ },
175+ "result": { "kind": "String", "value": "Object" }
176+ }
177+ ]
178+}⏎̸
A expr/testdata/languageservices/contains.json +122 -0
@@ -0,0 +1,122 @@
1+{
2+ "string": [
3+ {
4+ "expr": "contains('abcdef', 'cde')",
5+ "result": { "kind": "Boolean", "value": true }
6+ },
7+ {
8+ "expr": "contains('abCdEf', 'cDe')",
9+ "result": { "kind": "Boolean", "value": true }
10+ },
11+ {
12+ "expr": "contains('abcdef', '')",
13+ "result": { "kind": "Boolean", "value": true }
14+ },
15+ {
16+ "expr": "contains('1234', 23)",
17+ "result": { "kind": "Boolean", "value": true }
18+ },
19+ {
20+ "expr": "contains('true', true)",
21+ "result": { "kind": "Boolean", "value": true }
22+ },
23+ {
24+ "expr": "contains('false', false)",
25+ "result": { "kind": "Boolean", "value": true }
26+ },
27+ {
28+ "expr": "contains('asdf', null)",
29+ "result": { "kind": "Boolean", "value": true }
30+ },
31+ {
32+ "expr": "contains('true', false)",
33+ "result": { "kind": "Boolean", "value": false }
34+ }
35+ ],
36+
37+ "array": [
38+ {
39+ "expr": "contains(test, 'hello')",
40+ "result": { "kind": "Boolean", "value": true },
41+ "contexts": { "test": ["hello"] }
42+ },
43+ {
44+ "expr": "contains(test, 'world')",
45+ "result": { "kind": "Boolean", "value": true },
46+ "contexts": { "test": ["hello", "world"] }
47+ },
48+ {
49+ "expr": "contains(test, 'asdf')",
50+ "result": { "kind": "Boolean", "value": false },
51+ "contexts": { "test": ["hello"] }
52+ },
53+ {
54+ "expr": "contains(test, 123)",
55+ "result": { "kind": "Boolean", "value": true },
56+ "contexts": { "test": [123.0] }
57+ },
58+ {
59+ "expr": "contains(test, 123)",
60+ "result": { "kind": "Boolean", "value": true },
61+ "contexts": { "test": [123.0] }
62+ },
63+ {
64+ "expr": "contains(test, null)",
65+ "result": { "kind": "Boolean", "value": true },
66+ "contexts": { "test": [""] }
67+ },
68+ {
69+ "expr": "contains(test, false)",
70+ "result": { "kind": "Boolean", "value": true },
71+ "contexts": { "test": [""] }
72+ },
73+ {
74+ "expr": "contains(test, false)",
75+ "result": { "kind": "Boolean", "value": true },
76+ "contexts": { "test": [0] }
77+ }
78+ ],
79+
80+ "filtered_array": [
81+ {
82+ "expr": "contains(test.*, 'hello')",
83+ "result": { "kind": "Boolean", "value": true },
84+ "contexts": { "test": ["hello"] }
85+ },
86+ {
87+ "expr": "contains(test.*, 'world')",
88+ "result": { "kind": "Boolean", "value": true },
89+ "contexts": { "test": ["hello", "world"] }
90+ },
91+ {
92+ "expr": "contains(test.*, 'asdf')",
93+ "result": { "kind": "Boolean", "value": false },
94+ "contexts": { "test": ["hello"] }
95+ },
96+ {
97+ "expr": "contains(test.*, 123)",
98+ "result": { "kind": "Boolean", "value": true },
99+ "contexts": { "test": [123.0] }
100+ },
101+ {
102+ "expr": "contains(test.*, 123)",
103+ "result": { "kind": "Boolean", "value": true },
104+ "contexts": { "test": [123.0] }
105+ },
106+ {
107+ "expr": "contains(test.*, null)",
108+ "result": { "kind": "Boolean", "value": true },
109+ "contexts": { "test": [""] }
110+ },
111+ {
112+ "expr": "contains(test.*, false)",
113+ "result": { "kind": "Boolean", "value": true },
114+ "contexts": { "test": [""] }
115+ },
116+ {
117+ "expr": "contains(test.*, false)",
118+ "result": { "kind": "Boolean", "value": true },
119+ "contexts": { "test": [0] }
120+ }
121+ ]
122+}
A expr/testdata/languageservices/endsWith.json +129 -0
@@ -0,0 +1,129 @@
1+{
2+ "basics": [
3+ {
4+ "expr": "endsWith('abcdef', 'def')",
5+ "result": { "kind": "Boolean", "value": true }
6+ },
7+ {
8+ "expr": "endsWith('abcdef', 'de')",
9+ "result": { "kind": "Boolean", "value": false }
10+ },
11+ {
12+ "expr": "endsWith('abcdef', '')",
13+ "result": { "kind": "Boolean", "value": true }
14+ },
15+ {
16+ "expr": "endsWith('1234', 34)",
17+ "result": { "kind": "Boolean", "value": true }
18+ },
19+ {
20+ "expr": "endsWith('true', true)",
21+ "result": { "kind": "Boolean", "value": true }
22+ },
23+ {
24+ "expr": "endsWith('false', false)",
25+ "result": { "kind": "Boolean", "value": true }
26+ },
27+ {
28+ "expr": "endsWith('asdf', null)",
29+ "result": { "kind": "Boolean", "value": true }
30+ },
31+ {
32+ "expr": "endsWith('1234', 23)",
33+ "result": { "kind": "Boolean", "value": false }
34+ },
35+ {
36+ "expr": "endsWith('true', false)",
37+ "result": { "kind": "Boolean", "value": false }
38+ }
39+ ],
40+
41+ "case-insensitive-a-thru-z": [
42+ {
43+ "expr": "endsWith('asdf_ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')",
44+ "result": { "kind": "Boolean", "value": true }
45+ },
46+ {
47+ "expr": "endsWith('asdf_abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')",
48+ "result": { "kind": "Boolean", "value": true }
49+ }
50+ ],
51+
52+ "case-insensitive-ς-(final-lowercase-sigma)-Σ-(capital-sigma)-σ-(non-final-sigma)": [
53+ {
54+ "expr": "endsWith('asdf_ς', 'Σ')",
55+ "result": { "kind": "Boolean", "value": true }
56+ },
57+ {
58+ "expr": "endsWith('asdf_ς', 'σ')",
59+ "result": { "kind": "Boolean", "value": true }
60+ },
61+ {
62+ "expr": "endsWith('asdf_Σ', 'ς')",
63+ "result": { "kind": "Boolean", "value": true }
64+ },
65+ {
66+ "expr": "endsWith('asdf_Σ', 'σ')",
67+ "result": { "kind": "Boolean", "value": true }
68+ },
69+ {
70+ "expr": "endsWith('asdf_σ', 'ς')",
71+ "result": { "kind": "Boolean", "value": true }
72+ },
73+ {
74+ "expr": "endsWith('asdf_σ', 'Σ')",
75+ "result": { "kind": "Boolean", "value": true }
76+ }
77+ ],
78+
79+ "case-insensitive-ü-Ü": [
80+ {
81+ "expr": "endsWith('asdf_ü', 'Ü')",
82+ "result": { "kind": "Boolean", "value": true }
83+ },
84+ {
85+ "expr": "endsWith('asdf_Ü', 'ü')",
86+ "result": { "kind": "Boolean", "value": true }
87+ }
88+ ],
89+
90+ "case-insensitive-ç-Ç": [
91+ {
92+ "expr": "endsWith('asdf_ç', 'Ç')",
93+ "result": { "kind": "Boolean", "value": true }
94+ },
95+ {
96+ "expr": "endsWith('asdf_Ç', 'ç')",
97+ "result": { "kind": "Boolean", "value": true }
98+ }
99+ ],
100+
101+ "case-sensitive-i-İ": [
102+ {
103+ "expr": "endsWith('asdf_i', 'İ')",
104+ "result": { "kind": "Boolean", "value": false }
105+ },
106+ {
107+ "expr": "endsWith('asdf_İ', 'i')",
108+ "result": { "kind": "Boolean", "value": false }
109+ }
110+ ],
111+
112+ "case-sensitive-ı-I": [
113+ {
114+ "expr": "endsWith('asdf_ı', 'I')",
115+ "result": { "kind": "Boolean", "value": false }
116+ },
117+ {
118+ "expr": "endsWith('asdf_I', 'ı')",
119+ "result": { "kind": "Boolean", "value": false }
120+ }
121+ ],
122+
123+ "cyrillic-letters": [
124+ {
125+ "expr": "endsWith('asdf_АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЬЭЮЯ', 'абвгдежзийклмнопрстуфхцчшщьэюя')",
126+ "result": { "kind": "Boolean", "value": true }
127+ }
128+ ]
129+}
A expr/testdata/languageservices/format.json +207 -0
@@ -0,0 +1,207 @@
1+{
2+ "format": [
3+ {
4+ "expr": "format(null)",
5+ "result": { "kind": "String", "value": "" }
6+ },
7+ {
8+ "expr": "format(null, 'some arg')",
9+ "result": { "kind": "String", "value": "" }
10+ },
11+ {
12+ "expr": "format('')",
13+ "result": { "kind": "String", "value": "" }
14+ },
15+ {
16+ "expr": "format('', 'some arg')",
17+ "result": { "kind": "String", "value": "" }
18+ },
19+ {
20+ "expr": "format('123{0}456', 'abc')",
21+ "result": { "kind": "String", "value": "123abc456" }
22+ },
23+ {
24+ "expr": "format('123{0}456{0}789', 'abc')",
25+ "result": { "kind": "String", "value": "123abc456abc789" }
26+ },
27+ {
28+ "expr": "format('123{0}456{1}789', 'abc', 'def')",
29+ "result": { "kind": "String", "value": "123abc456def789" }
30+ },
31+ {
32+ "expr": "format('{0}123', 'abc')",
33+ "result": { "kind": "String", "value": "abc123" }
34+ },
35+ {
36+ "expr": "format('123{0}', 'abc')",
37+ "result": { "kind": "String", "value": "123abc" }
38+ },
39+ {
40+ "expr": "format('123{0}{1}456', 'abc', 'def')",
41+ "result": { "kind": "String", "value": "123abcdef456" }
42+ },
43+ {
44+ "expr": "format('{{0}}', 'abc')",
45+ "result": { "kind": "String", "value": "{0}" }
46+ },
47+ {
48+ "expr": "format('{{{{0}}}}', 'abc')",
49+ "result": { "kind": "String", "value": "{{0}}" }
50+ },
51+ {
52+ "expr": "format('}}', 'abc')",
53+ "result": { "kind": "String", "value": "}" }
54+ },
55+ {
56+ "expr": "format('{{', 'abc')",
57+ "result": { "kind": "String", "value": "{" }
58+ },
59+ {
60+ "expr": "format('}}{{', 'abc')",
61+ "result": { "kind": "String", "value": "}{" }
62+ },
63+ {
64+ "expr": "format('}}{{}}', 'abc')",
65+ "result": { "kind": "String", "value": "}{}" }
66+ },
67+ {
68+ "expr": "format('{0}', Infinity)",
69+ "result": { "kind": "String", "value": "Infinity" }
70+ },
71+ {
72+ "expr": "format('{0}', -Infinity)",
73+ "result": { "kind": "String", "value": "-Infinity" }
74+ },
75+ {
76+ "expr": "format('{0}', NaN)",
77+ "result": { "kind": "String", "value": "NaN" }
78+ },
79+ {
80+ "expr": "format('{0}', -0)",
81+ "result": { "kind": "String", "value": "0" }
82+ },
83+ {
84+ "expr": "format('{0}', -0.0)",
85+ "result": { "kind": "String", "value": "0" }
86+ },
87+ {
88+ "expr": "format('{0')",
89+ "err": {
90+ "kind": "evaluation",
91+ "value": "The following format string is invalid: {0"
92+ }
93+ },
94+ {
95+ "expr": "format('{0', '')",
96+ "err": {
97+ "kind": "evaluation",
98+ "value": "The following format string is invalid: {0"
99+ }
100+ },
101+ {
102+ "expr": "format('{0}}', '')",
103+ "err": {
104+ "kind": "evaluation",
105+ "value": "The following format string is invalid: {0}}"
106+ }
107+ },
108+ {
109+ "expr": "format('{0}}}}', '')",
110+ "err": {
111+ "kind": "evaluation",
112+ "value": "The following format string is invalid: {0}}}}"
113+ }
114+ },
115+ {
116+ "expr": "format('0}')",
117+ "err": {
118+ "kind": "evaluation",
119+ "value": "The following format string is invalid: 0}"
120+ }
121+ },
122+ {
123+ "expr": "format('0}', '')",
124+ "err": {
125+ "kind": "evaluation",
126+ "value": "The following format string is invalid: 0}"
127+ }
128+ },
129+ {
130+ "expr": "format('{{0}')",
131+ "err": {
132+ "kind": "evaluation",
133+ "value": "The following format string is invalid: {{0}"
134+ }
135+ },
136+ {
137+ "expr": "format('{{0}', '')",
138+ "err": {
139+ "kind": "evaluation",
140+ "value": "The following format string is invalid: {{0}"
141+ }
142+ },
143+ {
144+ "expr": "format('{{{{0}')",
145+ "err": {
146+ "kind": "evaluation",
147+ "value": "The following format string is invalid: {{{{0}"
148+ }
149+ },
150+ {
151+ "expr": "format('{{{{0}', '')",
152+ "err": {
153+ "kind": "evaluation",
154+ "value": "The following format string is invalid: {{{{0}"
155+ }
156+ },
157+ {
158+ "expr": "format('}0{')",
159+ "err": {
160+ "kind": "evaluation",
161+ "value": "The following format string is invalid: }0{"
162+ }
163+ },
164+ {
165+ "expr": "format('}0{', '')",
166+ "err": {
167+ "kind": "evaluation",
168+ "value": "The following format string is invalid: }0{"
169+ }
170+ },
171+ {
172+ "expr": "format('}{0}')",
173+ "err": {
174+ "kind": "evaluation",
175+ "value": "The following format string is invalid: }{0}"
176+ }
177+ },
178+ {
179+ "expr": "format('}{0}', '')",
180+ "err": {
181+ "kind": "evaluation",
182+ "value": "The following format string is invalid: }{0}"
183+ }
184+ },
185+ {
186+ "expr": "format('{0}{', '')",
187+ "err": {
188+ "kind": "evaluation",
189+ "value": "The following format string is invalid: {0}{"
190+ }
191+ },
192+ {
193+ "expr": "format('{0}')",
194+ "err": {
195+ "kind": "evaluation",
196+ "value": "The following format string references more arguments than were supplied: {0}"
197+ }
198+ },
199+ {
200+ "expr": "format('{0}{1}', 'abc')",
201+ "err": {
202+ "kind": "evaluation",
203+ "value": "The following format string references more arguments than were supplied: {0}{1}"
204+ }
205+ }
206+ ]
207+}
A expr/testdata/languageservices/fromJSON.json +67 -0
@@ -0,0 +1,67 @@
1+{
2+ "basics": [
3+ { "expr": "fromJSON('null')", "result": { "kind": "Null", "value": null } },
4+ { "expr": "fromJSON('true')", "result": { "kind": "Boolean", "value": true } },
5+ { "expr": "fromJSON('false')", "result": { "kind": "Boolean", "value": false } },
6+ { "expr": "fromJSON('0')", "result": { "kind": "Number", "value": 0 } },
7+ { "expr": "fromJSON('-0')", "result": { "kind": "Number", "value": -0 } },
8+ { "expr": "fromJSON('123456789')", "result": { "kind": "Number", "value": 123456789 } },
9+ { "expr": "fromJSON('-123456789')", "result": { "kind": "Number", "value": -123456789 } },
10+ { "expr": "fromJSON('1234.5')", "result": { "kind": "Number", "value": 1234.5 } },
11+ { "expr": "fromJSON('-1234.5')", "result": { "kind": "Number", "value": -1234.5 } },
12+ { "expr": "fromJSON('\"\"')", "result": { "kind": "String", "value": "" } },
13+ { "expr": "fromJSON('\"abc\"')", "result": { "kind": "String", "value": "abc" } },
14+ { "expr": "fromJSON('\"abc''def\"')", "result": { "kind": "String", "value": "abc'def" } },
15+ { "expr": "fromJSON('\"abc\\\\\\\"def\"')", "result": { "kind": "String", "value": "abc\\\"def" } }
16+ ],
17+ "array": [
18+ { "expr": "fromJSON('[]')", "result": { "kind": "Array", "value": [] } },
19+ { "expr": "fromJSON('[1, 2, 3]')", "result": { "kind": "Array", "value": [1, 2, 3] } },
20+ {
21+ "expr": "fromJSON('[[1, 2, 3], [\"abc\",\"def\",\"ghi\"], [true, false, null, [], {}]]')",
22+ "result": {
23+ "kind": "Array",
24+ "value": [[1, 2, 3], ["abc", "def", "ghi"], [true, false, null, [], {}]]
25+ }
26+ }
27+ ],
28+ "object": [
29+ { "expr": "fromJSON('{}')", "result": { "kind": "Object", "value": {} } },
30+ {
31+ "expr": "fromJSON('{\"one\": \"value one\", \"two\": \"value two\", \"three\": \"value three\"}')",
32+ "result": {
33+ "kind": "Object",
34+ "value": {
35+ "one": "value one",
36+ "two": "value two",
37+ "three": "value three"
38+ }
39+ }
40+ },
41+ {
42+ "expr": "fromJSON('{\"nested-one\": {\"one\": 1,\"two\": 2,\"three\": 3},\"nested-two\": {\"string one\": \"value one\",\"string two\": \"value two\",\"string three\": \"value three\"},\"nested-three\": {\"true\": true,\"false\": false,\"null\": null,\"array\": [],\"object\": {}}\n}')",
43+ "result": {
44+ "kind": "Object",
45+ "value": {
46+ "nested-one": {
47+ "one": 1,
48+ "two": 2,
49+ "three": 3
50+ },
51+ "nested-two": {
52+ "string one": "value one",
53+ "string two": "value two",
54+ "string three": "value three"
55+ },
56+ "nested-three": {
57+ "true": true,
58+ "false": false,
59+ "null": null,
60+ "array": [],
61+ "object": {}
62+ }
63+ }
64+ }
65+ }
66+ ]
67+}⏎̸
A expr/testdata/languageservices/join.json +113 -0
@@ -0,0 +1,113 @@
1+{
2+ "join": [
3+ {
4+ "expr": "join(github.event.issue.labels.*.name, ', ')",
5+ "contexts": {
6+ "github": {
7+ "event": {
8+ "issue": {
9+ "labels": [
10+ {
11+ "name": "bug"
12+ },
13+ {
14+ "name": "enhancement"
15+ },
16+ {
17+ "name": "help wanted"
18+ }
19+ ]
20+ }
21+ }
22+ }
23+ },
24+ "result": { "kind": "String", "value": "bug, enhancement, help wanted" }
25+ },
26+ {
27+ "expr": "join(null)",
28+ "result": { "kind": "String", "value": "" }
29+ },
30+ {
31+ "expr": "join(true)",
32+ "result": { "kind": "String", "value": "true" }
33+ },
34+ {
35+ "expr": "join(123.456)",
36+ "result": { "kind": "String", "value": "123.456" }
37+ },
38+ {
39+ "expr": "join('abc')",
40+ "result": { "kind": "String", "value": "abc" }
41+ },
42+ {
43+ "expr": "join(myArray)",
44+ "contexts": { "myArray": [] },
45+ "result": { "kind": "String", "value": "" }
46+ },
47+ {
48+ "expr": "join(myObject)",
49+ "contexts": { "myObject": {} },
50+ "result": { "kind": "String", "value": "" }
51+ },
52+ {
53+ "expr": "join(myObject)",
54+ "contexts": { "myObject": { "key1": "value1" } },
55+ "result": { "kind": "String", "value": "" }
56+ },
57+ {
58+ "expr": "join(myArray)",
59+ "contexts": { "myArray": [ null, true, 123.456, "abc", [], ["def"], {}, { "key1": "value1" } ] },
60+ "result": { "kind": "String", "value": ",true,123.456,abc,Array,Array,Object,Object" }
61+ },
62+ {
63+ "expr": "join(myArray, null)",
64+ "contexts": { "myArray": [ "_ITEM-1_", "_ITEM-2_", "_ITEM-3_" ] },
65+ "result": { "kind": "String", "value": "_ITEM-1__ITEM-2__ITEM-3_" }
66+ },
67+ {
68+ "expr": "join(myArray, true)",
69+ "contexts": { "myArray": [ "_ITEM-1_", "_ITEM-2_", "_ITEM-3_" ] },
70+ "result": { "kind": "String", "value": "_ITEM-1_true_ITEM-2_true_ITEM-3_" }
71+ },
72+ {
73+ "expr": "join(myArray, 123.456)",
74+ "contexts": { "myArray": [ "_ITEM-1_", "_ITEM-2_", "_ITEM-3_" ] },
75+ "result": { "kind": "String", "value": "_ITEM-1_123.456_ITEM-2_123.456_ITEM-3_" }
76+ },
77+ {
78+ "expr": "join(myArray, ' | ')",
79+ "contexts": { "myArray": [ "_ITEM-1_", "_ITEM-2_", "_ITEM-3_" ] },
80+ "result": { "kind": "String", "value": "_ITEM-1_ | _ITEM-2_ | _ITEM-3_" }
81+ },
82+ {
83+ "expr": "join(myArray, mySeparator)",
84+ "contexts": {
85+ "myArray": [ "_ITEM-1_", "_ITEM-2_", "_ITEM-3_" ],
86+ "mySeparator": []
87+ },
88+ "result": { "kind": "String", "value": "_ITEM-1_,_ITEM-2_,_ITEM-3_" }
89+ },
90+ {
91+ "expr": "join(myArray, mySeparator)",
92+ "contexts": {
93+ "myArray": [ "_ITEM-1_", "_ITEM-2_", "_ITEM-3_" ],
94+ "mySeparator": {}
95+ },
96+ "result": { "kind": "String", "value": "_ITEM-1_,_ITEM-2_,_ITEM-3_" }
97+ },
98+ {
99+ "expr": "join()",
100+ "err": {
101+ "kind": "parsing",
102+ "value": "Too few parameters supplied: "
103+ }
104+ },
105+ {
106+ "expr": "join(1, 2, 3)",
107+ "err": {
108+ "kind": "parsing",
109+ "value": "Too many parameters supplied: "
110+ }
111+ }
112+ ]
113+}
A expr/testdata/languageservices/number.json +51 -0
@@ -0,0 +1,51 @@
1+{
2+ "number": [
3+ { "expr": "1", "result": { "kind": "Number", "value": 1.0 } },
4+ { "expr": ".5", "result": { "kind": "Number", "value": 0.5 } },
5+ { "expr": "0.5", "result": { "kind": "Number", "value": 0.5 } },
6+ { "expr": "2", "result": { "kind": "Number", "value": 2.0 } },
7+ { "expr": "-1", "result": { "kind": "Number", "value": -1.0 } },
8+ { "expr": "+1", "result": { "kind": "Number", "value": 1.0 } },
9+ { "expr": "-.5", "result": { "kind": "Number", "value": -0.5 } },
10+ { "expr": "-2", "result": { "kind": "Number", "value": -2.0 } },
11+ { "expr": "format('{0}', -Infinity)", "result": { "kind": "String", "value": "-Infinity" } },
12+ { "expr": "format('{0}', Infinity)", "result": { "kind": "String", "value": "Infinity" } },
13+ { "expr": "format('{0}', +Infinity)", "result": { "kind": "String", "value": "Infinity" } },
14+ { "expr": "format('{0}', NaN)", "result": { "kind": "String", "value": "NaN" } },
15+ { "expr": "0", "result": { "kind": "Number", "value": 0.0 } },
16+ { "expr": "0.0", "result": { "kind": "Number", "value": 0.0 } },
17+ { "expr": "-0", "result": { "kind": "Number", "value": -0.0 } },
18+ { "expr": "-0.0", "result": { "kind": "Number", "value": -0.0 } },
19+ { "expr": "0x0", "result": { "kind": "Number", "value": 0.0 } },
20+ { "expr": "0x00", "result": { "kind": "Number", "value": 0.0 } },
21+ { "expr": "0xf", "result": { "kind": "Number", "value": 15.0 } },
22+ { "expr": "0xfF", "result": { "kind": "Number", "value": 255.0 } },
23+ { "expr": "0xfFf", "result": { "kind": "Number", "value": 4095.0 } },
24+ { "expr": "0o0", "result": { "kind": "Number", "value": 0.0 } },
25+ { "expr": "0o7", "result": { "kind": "Number", "value": 7.0 } },
26+ { "expr": "0o77", "result": { "kind": "Number", "value": 63.0 } },
27+ { "expr": "0o777", "result": { "kind": "Number", "value": 511.0 } },
28+ { "expr": "1e1", "result": { "kind": "Number", "value": 10.0 } },
29+ { "expr": "1e2", "result": { "kind": "Number", "value": 100.0 } },
30+ { "expr": "1E1", "result": { "kind": "Number", "value": 10.0 } },
31+ { "expr": "1E+1", "result": { "kind": "Number", "value": 10.0 } },
32+ { "expr": "1e-1", "result": { "kind": "Number", "value": 0.1 } },
33+ { "expr": "1E-1", "result": { "kind": "Number", "value": 0.1 } },
34+ {
35+ "expr": "0x01p2",
36+ "err": { "kind": "lexing", "value": "Unexpected symbol: '0x01p2'. Located at position 1 within expression: 0x01p2" }
37+ },
38+ {
39+ "expr": "-Inf",
40+ "err": { "kind": "lexing", "value": "Unexpected symbol: '-Inf'. Located at position 1 within expression: -Inf" }
41+ },
42+ {
43+ "expr": "-0xFF",
44+ "err": { "kind": "lexing", "value": "Unexpected symbol: '-0xFF'. Located at position 1 within expression: -0xFF" }
45+ },
46+ {
47+ "expr": "0xFZ",
48+ "err": { "kind": "lexing", "value": "Unexpected symbol: '0xFZ'. Located at position 1 within expression: 0xFZ" }
49+ }
50+ ]
51+}
A expr/testdata/languageservices/op_and.json +51 -0
@@ -0,0 +1,51 @@
1+{
2+ "operator_and": [
3+ {
4+ "expr": "true && true && true",
5+ "result": { "kind": "Boolean", "value": true }
6+ },
7+ { "expr": "true && true", "result": { "kind": "Boolean", "value": true } },
8+ {
9+ "expr": "true && true && false",
10+ "result": { "kind": "Boolean", "value": false }
11+ },
12+ {
13+ "expr": "true && false && true",
14+ "result": { "kind": "Boolean", "value": false }
15+ },
16+ {
17+ "expr": "false && true",
18+ "result": { "kind": "Boolean", "value": false }
19+ },
20+ {
21+ "expr": "false && false",
22+ "result": { "kind": "Boolean", "value": false }
23+ },
24+ { "expr": "true && 1 && 2", "result": { "kind": "Number", "value": 2.0 } },
25+ { "expr": "true && 0 && 2", "result": { "kind": "Number", "value": 0.0 } },
26+ {
27+ "expr": "true && 'a' && 'b'",
28+ "result": { "kind": "String", "value": "b" }
29+ },
30+ {
31+ "expr": "true && '' && 'asdf'",
32+ "result": { "kind": "String", "value": "" }
33+ },
34+ { "expr": "null && true", "result": { "kind": "Null", "value": null } },
35+ {
36+ "expr": "test && 123",
37+ "contexts": { "test": {} },
38+ "result": { "kind": "Number", "value": 123.0 }
39+ },
40+ {
41+ "expr": "test && 456",
42+ "contexts": { "test": {} },
43+ "result": { "kind": "Number", "value": 456.0 }
44+ },
45+ {
46+ "expr": "test && 789",
47+ "contexts": { "test": [] },
48+ "result": { "kind": "Number", "value": 789.0 }
49+ }
50+ ]
51+}
A expr/testdata/languageservices/op_dot.json +202 -0
@@ -0,0 +1,202 @@
1+{
2+ "property-basics": [
3+ {
4+ "expr": "foo.bar",
5+ "contexts": {
6+ "foo": {
7+ "bar": "baz"
8+ }
9+ },
10+ "result": { "kind": "String", "value": "baz" }
11+ },
12+ {
13+ "expr": "foo.Bar",
14+ "contexts": {
15+ "foo": {
16+ "Bar": "baz"
17+ }
18+ },
19+ "result": { "kind": "String", "value": "baz" }
20+ },
21+ {
22+ "expr": "foo.b",
23+ "contexts": {
24+ "foo": {
25+ "b": "baz"
26+ }
27+ },
28+ "result": { "kind": "String", "value": "baz" }
29+ },
30+ {
31+ "expr": "foo._",
32+ "contexts": {
33+ "foo": {
34+ "_": "baz"
35+ }
36+ },
37+ "result": { "kind": "String", "value": "baz" }
38+ },
39+ {
40+ "expr": "foo._bar",
41+ "contexts": {
42+ "foo": {
43+ "_bar": "baz"
44+ }
45+ },
46+ "result": { "kind": "String", "value": "baz" }
47+ },
48+ {
49+ "expr": "foo.b_ar",
50+ "contexts": {
51+ "foo": {
52+ "b_ar": "baz"
53+ }
54+ },
55+ "result": { "kind": "String", "value": "baz" }
56+ },
57+ {
58+ "expr": "foo.b-ar",
59+ "contexts": {
60+ "foo": {
61+ "b-ar": "baz"
62+ }
63+ },
64+ "result": { "kind": "String", "value": "baz" }
65+ },
66+ {
67+ "expr": "fromJson('{\"one\": \"one val\"}').one",
68+ "result": { "kind": "String", "value": "one val" }
69+ },
70+ {
71+ "expr": "(fromJson('{\"one\": \"one val\"}')).one",
72+ "result": { "kind": "String", "value": "one val" }
73+ },
74+ {
75+ "expr": "foo[*]",
76+ "contexts": {
77+ "foo": {
78+ "one": "one val",
79+ "two": "two val"
80+ }
81+ },
82+ "result": { "kind": "Array", "value": ["one val", "two val"] }
83+ }
84+ ],
85+ "property-case-insensitive": [
86+ {
87+ "expr": "foo.bar",
88+ "contexts": {
89+ "foo": {
90+ "BAR": "baz"
91+ }
92+ },
93+ "result": { "kind": "String", "value": "baz" }
94+ },
95+ {
96+ "expr": "foo.BAR",
97+ "contexts": {
98+ "foo": {
99+ "bar": "baz"
100+ }
101+ },
102+ "result": { "kind": "String", "value": "baz" }
103+ }
104+ ],
105+ "property-matches-const": [
106+ {
107+ "expr": "foo.true",
108+ "contexts": {
109+ "foo": {
110+ "true": "it's true"
111+ }
112+ },
113+ "result": { "kind": "String", "value": "it's true" }
114+ },
115+ {
116+ "expr": "foo.false",
117+ "contexts": {
118+ "foo": {
119+ "false": "it's false"
120+ }
121+ },
122+ "result": { "kind": "String", "value": "it's false" }
123+ },
124+ {
125+ "expr": "foo.Infinity",
126+ "contexts": {
127+ "foo": {
128+ "Infinity": "it's Infinity"
129+ }
130+ },
131+ "result": { "kind": "String", "value": "it's Infinity" }
132+ },
133+ {
134+ "expr": "foo.NaN",
135+ "contexts": {
136+ "foo": {
137+ "NaN": "it's NaN"
138+ }
139+ },
140+ "result": { "kind": "String", "value": "it's NaN" }
141+ },
142+ {
143+ "expr": "foo.null",
144+ "contexts": {
145+ "foo": {
146+ "null": "it's null"
147+ }
148+ },
149+ "result": { "kind": "String", "value": "it's null" }
150+ },
151+ {
152+ "expr": "foo.format",
153+ "contexts": {
154+ "foo": {
155+ "format": "it's format"
156+ }
157+ },
158+ "result": { "kind": "String", "value": "it's format" }
159+ }
160+ ],
161+ "property-errors": [
162+ {
163+ "expr": "foo.b@r",
164+ "contexts": {
165+ "foo": {
166+ "b@r": "baz"
167+ }
168+ },
169+ "err": {
170+ "kind": "lexing",
171+ "value": "Unexpected symbol: 'b@r'. Located at position 5 within expression: foo.b@r"
172+ }
173+ },
174+ {
175+ "expr": "foo.1",
176+ "contexts": {
177+ "foo": {}
178+ },
179+ "err": {
180+ "kind": "parsing",
181+ "value": "Unexpected symbol: '1'. Located at position 5 within expression: foo.1"
182+ }
183+ },
184+ {
185+ "expr": "fromjson('').1",
186+ "err": {
187+ "kind": "parsing",
188+ "value": "Unexpected symbol: '1'. Located at position 14 within expression: fromjson('').1"
189+ }
190+ },
191+ {
192+ "expr": "foo[1].2",
193+ "contexts": {
194+ "foo": {}
195+ },
196+ "err": {
197+ "kind": "parsing",
198+ "value": "Unexpected symbol: '2'. Located at position 8 within expression: foo[1].2"
199+ }
200+ }
201+ ]
202+}
A expr/testdata/languageservices/op_eq.json +430 -0
@@ -0,0 +1,430 @@
1+{
2+ "boolean": [
3+ { "expr": "true == true", "result": { "kind": "Boolean", "value": true } },
4+ {
5+ "expr": "false == false",
6+ "result": { "kind": "Boolean", "value": true }
7+ },
8+ {
9+ "expr": "false == true",
10+ "result": { "kind": "Boolean", "value": false }
11+ }
12+ ],
13+
14+ "number": [
15+ { "expr": "0 == -0", "result": { "kind": "Boolean", "value": true } },
16+ { "expr": "2 == 2", "result": { "kind": "Boolean", "value": true } },
17+ { "expr": "1.001 == 1.002", "result": { "kind": "Boolean", "value": false } },
18+ { "expr": "120 == 1.2e2", "result": { "kind": "Boolean", "value": true } },
19+ { "expr": "1 == 2", "result": { "kind": "Boolean", "value": false } },
20+ { "expr": "NaN == NaN", "result": { "kind": "Boolean", "value": false } },
21+ {
22+ "expr": "Infinity == Infinity",
23+ "result": { "kind": "Boolean", "value": true }
24+ },
25+ {
26+ "expr": "-Infinity == Infinity",
27+ "result": { "kind": "Boolean", "value": false }
28+ },
29+ {
30+ "expr": "0 == Infinity",
31+ "result": { "kind": "Boolean", "value": false }
32+ },
33+ {
34+ "expr": "1 == Infinity",
35+ "result": { "kind": "Boolean", "value": false }
36+ }
37+ ],
38+
39+ "string": [
40+ { "expr": "'a' == 'a'", "result": { "kind": "Boolean", "value": true } },
41+ { "expr": "'a' == 'b'", "result": { "kind": "Boolean", "value": false } }
42+ ],
43+
44+ "null": [
45+ { "expr": "null == null", "result": { "kind": "Boolean", "value": true } }
46+ ],
47+
48+ "object": [
49+ {
50+ "expr": "object1 == object1",
51+ "contexts": { "object1": {} },
52+ "result": { "kind": "Boolean", "value": true }
53+ },
54+ {
55+ "expr": "object1 == object2",
56+ "contexts": { "object1": {}, "object2": {} },
57+ "result": { "kind": "Boolean", "value": false }
58+ }
59+ ],
60+
61+ "array": [
62+ {
63+ "expr": "array1 == array1",
64+ "contexts": { "array1": [] },
65+ "result": { "kind": "Boolean", "value": true }
66+ },
67+ {
68+ "expr": "array1 == array2",
69+ "contexts": { "array1": [], "array2": [] },
70+ "result": { "kind": "Boolean", "value": false }
71+ }
72+ ],
73+
74+ "coerce_bool_number": [
75+ { "expr": "false == 0", "result": { "kind": "Boolean", "value": true } },
76+ { "expr": "true == 1", "result": { "kind": "Boolean", "value": true } },
77+ { "expr": "false == NaN", "result": { "kind": "Boolean", "value": false } },
78+ { "expr": "true == 2", "result": { "kind": "Boolean", "value": false } }
79+ ],
80+
81+ "coerce_bool_string": [
82+ { "expr": "false == ''", "result": { "kind": "Boolean", "value": true } },
83+ {
84+ "expr": "false == ' '",
85+ "result": { "kind": "Boolean", "value": true }
86+ },
87+ {
88+ "expr": "false == ' 0.0 '",
89+ "result": { "kind": "Boolean", "value": true }
90+ },
91+ {
92+ "expr": "true == ' 1.0 '",
93+ "result": { "kind": "Boolean", "value": true }
94+ },
95+ {
96+ "expr": "true == ' 1 '",
97+ "result": { "kind": "Boolean", "value": true }
98+ },
99+ {
100+ "expr": "false == '-1'",
101+ "result": { "kind": "Boolean", "value": false }
102+ },
103+ { "expr": "true == '2'", "result": { "kind": "Boolean", "value": false } }
104+ ],
105+
106+ "coerce_bool_null": [
107+ {
108+ "expr": "false == null",
109+ "result": { "kind": "Boolean", "value": true }
110+ },
111+ {
112+ "expr": "true == null",
113+ "result": { "kind": "Boolean", "value": false }
114+ }
115+ ],
116+
117+ "coerce_bool_object-array": [
118+ {
119+ "expr": "false == test",
120+ "contexts": { "test": {} },
121+ "result": { "kind": "Boolean", "value": false }
122+ },
123+ {
124+ "expr": "false == test",
125+ "contexts": { "test": [] },
126+ "result": { "kind": "Boolean", "value": false }
127+ },
128+ {
129+ "expr": "true == test",
130+ "contexts": { "test": {} },
131+ "result": { "kind": "Boolean", "value": false }
132+ },
133+ {
134+ "expr": "true == test",
135+ "contexts": { "test": [] },
136+ "result": { "kind": "Boolean", "value": false }
137+ }
138+ ],
139+
140+ "coerce_number_bool": [
141+ { "expr": "0 == false", "result": { "kind": "Boolean", "value": true } },
142+ { "expr": "1 == true", "result": { "kind": "Boolean", "value": true } },
143+ {
144+ "expr": "NaN == false",
145+ "result": { "kind": "Boolean", "value": false }
146+ },
147+ { "expr": "2 == true", "result": { "kind": "Boolean", "value": false } }
148+ ],
149+
150+ "coerce_number_string": [
151+ {
152+ "expr": "0 == ' -0.0 '",
153+ "result": { "kind": "Boolean", "value": true }
154+ },
155+ { "expr": "0 == ''", "result": { "kind": "Boolean", "value": true } },
156+ { "expr": "0 == ' '", "result": { "kind": "Boolean", "value": true } },
157+ {
158+ "expr": "120 == ' +1.2e2 '",
159+ "result": { "kind": "Boolean", "value": true }
160+ },
161+ {
162+ "expr": "120.0 == ' 1.2E2 '",
163+ "result": { "kind": "Boolean", "value": true }
164+ },
165+ {
166+ "expr": "120 == ' 1.2e+2 '",
167+ "result": { "kind": "Boolean", "value": true }
168+ },
169+ {
170+ "expr": "-120 == ' -1.2E+2 '",
171+ "result": { "kind": "Boolean", "value": true }
172+ },
173+ {
174+ "expr": "0.012 == ' 1.2e-2 '",
175+ "result": { "kind": "Boolean", "value": true }
176+ },
177+ {
178+ "expr": "0.012 == ' 1.2E-2 '",
179+ "result": { "kind": "Boolean", "value": true }
180+ },
181+ {
182+ "expr": "255.0 == ' 0xff '",
183+ "result": { "kind": "Boolean", "value": true }
184+ },
185+ {
186+ "expr": "8.0 == ' 0o10 '",
187+ "result": { "kind": "Boolean", "value": true }
188+ },
189+ {
190+ "expr": "Infinity == ' Infinity '",
191+ "result": { "kind": "Boolean", "value": true }
192+ },
193+ {
194+ "expr": "-Infinity == ' -Infinity '",
195+ "result": { "kind": "Boolean", "value": true }
196+ },
197+ {
198+ "expr": "NaN == 'NaN'",
199+ "result": { "kind": "Boolean", "value": false }
200+ },
201+ { "expr": "1 == '0'", "result": { "kind": "Boolean", "value": false } },
202+ { "expr": "1 == 'a'", "result": { "kind": "Boolean", "value": false } }
203+ ],
204+
205+ "coerce_number_null": [
206+ { "expr": "0 == null", "result": { "kind": "Boolean", "value": true } }
207+ ],
208+
209+ "coerce_number_object-array": [
210+ {
211+ "expr": "0 == test",
212+ "contexts": { "test": {} },
213+ "result": { "kind": "Boolean", "value": false }
214+ },
215+ {
216+ "expr": "1 == test",
217+ "contexts": { "test": {} },
218+ "result": { "kind": "Boolean", "value": false }
219+ },
220+ {
221+ "expr": "0 == test",
222+ "contexts": { "test": [] },
223+ "result": { "kind": "Boolean", "value": false }
224+ },
225+ {
226+ "expr": "1 == test",
227+ "contexts": { "test": [] },
228+ "result": { "kind": "Boolean", "value": false }
229+ }
230+ ],
231+
232+ "coerce_string_bool": [
233+ { "expr": "'' == false", "result": { "kind": "Boolean", "value": true } },
234+ {
235+ "expr": "' ' == false",
236+ "result": { "kind": "Boolean", "value": true }
237+ },
238+ {
239+ "expr": "' 0.0 ' == false",
240+ "result": { "kind": "Boolean", "value": true }
241+ },
242+ {
243+ "expr": "' 1.0 ' == true",
244+ "result": { "kind": "Boolean", "value": true }
245+ },
246+ {
247+ "expr": "' 1 ' == true",
248+ "result": { "kind": "Boolean", "value": true }
249+ },
250+ {
251+ "expr": "'-1' == false",
252+ "result": { "kind": "Boolean", "value": false }
253+ },
254+ { "expr": "'2' == true", "result": { "kind": "Boolean", "value": false } }
255+ ],
256+
257+ "coerce_string_number": [
258+ {
259+ "expr": "' -0.0 ' == 0",
260+ "result": { "kind": "Boolean", "value": true }
261+ },
262+ { "expr": "'' == 0", "result": { "kind": "Boolean", "value": true } },
263+ { "expr": "' ' == 0", "result": { "kind": "Boolean", "value": true } },
264+ {
265+ "expr": "' +1.2e2 ' == 120",
266+ "result": { "kind": "Boolean", "value": true }
267+ },
268+ {
269+ "expr": "' 1.2E2 ' == 120.0",
270+ "result": { "kind": "Boolean", "value": true }
271+ },
272+ {
273+ "expr": "' 1.2e+2 ' == 120",
274+ "result": { "kind": "Boolean", "value": true }
275+ },
276+ {
277+ "expr": "' -1.2E+2 ' == -120",
278+ "result": { "kind": "Boolean", "value": true }
279+ },
280+ {
281+ "expr": "' 1.2e-2 ' == 0.012",
282+ "result": { "kind": "Boolean", "value": true }
283+ },
284+ {
285+ "expr": "' 1.2E-2 ' == 0.012",
286+ "result": { "kind": "Boolean", "value": true }
287+ },
288+ {
289+ "expr": "' 0xff ' == 255.0",
290+ "result": { "kind": "Boolean", "value": true }
291+ },
292+ {
293+ "expr": "' 0o10 ' == 8.0",
294+ "result": { "kind": "Boolean", "value": true }
295+ },
296+ {
297+ "expr": "' Infinity ' == Infinity",
298+ "result": { "kind": "Boolean", "value": true }
299+ },
300+ {
301+ "expr": "' -Infinity ' == -Infinity",
302+ "result": { "kind": "Boolean", "value": true }
303+ },
304+ {
305+ "expr": "'NaN' == NaN",
306+ "result": { "kind": "Boolean", "value": false }
307+ },
308+ { "expr": "'0' == 1", "result": { "kind": "Boolean", "value": false } },
309+ { "expr": "'a' == 1", "result": { "kind": "Boolean", "value": false } }
310+ ],
311+
312+ "coerce_string_null": [
313+ { "expr": "'' == null", "result": { "kind": "Boolean", "value": true } },
314+ {
315+ "expr": "' ' == null",
316+ "result": { "kind": "Boolean", "value": true }
317+ },
318+ { "expr": "'0' == null", "result": { "kind": "Boolean", "value": true } },
319+ {
320+ "expr": "'false' == null",
321+ "result": { "kind": "Boolean", "value": false }
322+ },
323+ {
324+ "expr": "'null' == null",
325+ "result": { "kind": "Boolean", "value": false }
326+ }
327+ ],
328+
329+ "coerce_string_object": [
330+ {
331+ "expr": "'' == test",
332+ "contexts": { "test": {} },
333+ "result": { "kind": "Boolean", "value": false }
334+ },
335+ {
336+ "expr": "'false' == test",
337+ "contexts": { "test": {} },
338+ "result": { "kind": "Boolean", "value": false }
339+ },
340+ {
341+ "expr": "'0' == test",
342+ "contexts": { "test": {} },
343+ "result": { "kind": "Boolean", "value": false }
344+ },
345+ {
346+ "expr": "'null' == test",
347+ "contexts": { "test": {} },
348+ "result": { "kind": "Boolean", "value": false }
349+ },
350+ {
351+ "expr": "'Object' == test",
352+ "contexts": { "test": {} },
353+ "result": { "kind": "Boolean", "value": false }
354+ }
355+ ],
356+
357+ "coerce_string_array": [
358+ {
359+ "expr": "'' == test",
360+ "contexts": { "test": [] },
361+ "result": { "kind": "Boolean", "value": false }
362+ },
363+ {
364+ "expr": "'false' == test",
365+ "contexts": { "test": [] },
366+ "result": { "kind": "Boolean", "value": false }
367+ },
368+ {
369+ "expr": "'0' == test",
370+ "contexts": { "test": [] },
371+ "result": { "kind": "Boolean", "value": false }
372+ },
373+ {
374+ "expr": "'null' == test",
375+ "contexts": { "test": [] },
376+ "result": { "kind": "Boolean", "value": false }
377+ },
378+ {
379+ "expr": "'Array' == test",
380+ "contexts": { "test": [] },
381+ "result": { "kind": "Boolean", "value": false }
382+ }
383+ ],
384+
385+ "coerce_null_bool": [
386+ {
387+ "expr": "null == false",
388+ "result": { "kind": "Boolean", "value": true }
389+ },
390+ {
391+ "expr": "null == true",
392+ "result": { "kind": "Boolean", "value": false }
393+ }
394+ ],
395+
396+ "coerce_null_number": [
397+ { "expr": "null == 0", "result": { "kind": "Boolean", "value": true } },
398+ { "expr": "false == 1", "result": { "kind": "Boolean", "value": false } }
399+ ],
400+
401+ "coerce_null_string": [
402+ { "expr": "null == ''", "result": { "kind": "Boolean", "value": true } },
403+ {
404+ "expr": "null == ' '",
405+ "result": { "kind": "Boolean", "value": true }
406+ },
407+ { "expr": "null == '0'", "result": { "kind": "Boolean", "value": true } },
408+ {
409+ "expr": "null == 'false'",
410+ "result": { "kind": "Boolean", "value": false }
411+ },
412+ {
413+ "expr": "null == 'null'",
414+ "result": { "kind": "Boolean", "value": false }
415+ }
416+ ],
417+
418+ "coerce_null_object-array": [
419+ {
420+ "expr": "null == test",
421+ "contexts": { "test": {} },
422+ "result": { "kind": "Boolean", "value": false }
423+ },
424+ {
425+ "expr": "null == test",
426+ "contexts": { "test": [] },
427+ "result": { "kind": "Boolean", "value": false }
428+ }
429+ ]
430+}
A expr/testdata/languageservices/op_gt.json +376 -0
@@ -0,0 +1,376 @@
1+{
2+ "bool": [
3+ {
4+ "expr": "false > true",
5+ "result": { "kind": "Boolean", "value": false }
6+ },
7+ {
8+ "expr": "false > false",
9+ "result": { "kind": "Boolean", "value": false }
10+ },
11+ {
12+ "expr": "true > false",
13+ "result": { "kind": "Boolean", "value": true }
14+ },
15+ {
16+ "expr": "true > true",
17+ "result": { "kind": "Boolean", "value": false }
18+ }
19+ ],
20+ "number": [
21+ {
22+ "expr": "1 > 2",
23+ "result": { "kind": "Boolean", "value": false }
24+ },
25+ {
26+ "expr": "1 > 1",
27+ "result": { "kind": "Boolean", "value": false }
28+ },
29+ {
30+ "expr": "2 > 1",
31+ "result": { "kind": "Boolean", "value": true }
32+ },
33+ {
34+ "expr": "1.002 > 1.001",
35+ "result": { "kind": "Boolean", "value": true }
36+ }
37+ ],
38+ "string": [
39+ {
40+ "expr": "'def' > 'abc'",
41+ "result": { "kind": "Boolean", "value": true }
42+ },
43+ {
44+ "expr": "'a' > 'b'",
45+ "result": { "kind": "Boolean", "value": false }
46+ }
47+ ],
48+
49+ "array": [
50+ {
51+ "expr": "test > test",
52+ "contexts": { "test": [] },
53+ "result": { "kind": "Boolean", "value": false }
54+ }
55+ ],
56+
57+ "object": [
58+ {
59+ "expr": "test > test",
60+ "contexts": { "test": {} },
61+ "result": { "kind": "Boolean", "value": false }
62+ }
63+ ],
64+
65+ "coerce_bool_number": [
66+ {
67+ "expr": "false > 0",
68+ "result": { "kind": "Boolean", "value": false }
69+ },
70+ {
71+ "expr": "false > -11",
72+ "result": { "kind": "Boolean", "value": true }
73+ },
74+ {
75+ "expr": "true > 1",
76+ "result": { "kind": "Boolean", "value": false }
77+ },
78+ {
79+ "expr": "true > 0",
80+ "result": { "kind": "Boolean", "value": true }
81+ },
82+ {
83+ "expr": "false > NaN",
84+ "result": { "kind": "Boolean", "value": false }
85+ },
86+ {
87+ "expr": "true > NaN",
88+ "result": { "kind": "Boolean", "value": false }
89+ },
90+ {
91+ "expr": "false > Infinity",
92+ "result": { "kind": "Boolean", "value": false }
93+ },
94+ {
95+ "expr": "true > Infinity",
96+ "result": { "kind": "Boolean", "value": false }
97+ },
98+ {
99+ "expr": "false > -Infinity",
100+ "result": { "kind": "Boolean", "value": true }
101+ },
102+ {
103+ "expr": "true > -Infinity",
104+ "result": { "kind": "Boolean", "value": true }
105+ }
106+ ],
107+
108+ "coerce_bool_string": [
109+ {
110+ "expr": "false > '0'",
111+ "result": { "kind": "Boolean", "value": false }
112+ },
113+ {
114+ "expr": "false > '-1'",
115+ "result": { "kind": "Boolean", "value": true }
116+ },
117+ {
118+ "expr": "true > '1'",
119+ "result": { "kind": "Boolean", "value": false }
120+ },
121+ {
122+ "expr": "true > '0'",
123+ "result": { "kind": "Boolean", "value": true }
124+ }
125+ ],
126+
127+ "coerce_bool_null": [
128+ {
129+ "expr": "false > null",
130+ "result": { "kind": "Boolean", "value": false }
131+ },
132+ {
133+ "expr": "true > null",
134+ "result": { "kind": "Boolean", "value": true }
135+ }
136+ ],
137+
138+ "coerce_bool_object": [
139+ {
140+ "expr": "false > test",
141+ "contexts": { "test": {} },
142+ "result": { "kind": "Boolean", "value": false }
143+ },
144+ {
145+ "expr": "true > test",
146+ "contexts": { "test": {} },
147+ "result": { "kind": "Boolean", "value": false }
148+ }
149+ ],
150+
151+ "coerce_bool_array": [
152+ {
153+ "expr": "false > test",
154+ "contexts": { "test": [] },
155+ "result": { "kind": "Boolean", "value": false }
156+ },
157+ {
158+ "expr": "true > test",
159+ "contexts": { "test": [] },
160+ "result": { "kind": "Boolean", "value": false }
161+ }
162+ ],
163+
164+ "coerce_number_bool": [
165+ {
166+ "expr": "1 > false",
167+ "result": { "kind": "Boolean", "value": true }
168+ },
169+ {
170+ "expr": "0 > false",
171+ "result": { "kind": "Boolean", "value": false }
172+ },
173+ {
174+ "expr": "2 > true",
175+ "result": { "kind": "Boolean", "value": true }
176+ },
177+ {
178+ "expr": "1 > true",
179+ "result": { "kind": "Boolean", "value": false }
180+ },
181+ {
182+ "expr": "NaN > false",
183+ "result": { "kind": "Boolean", "value": false }
184+ },
185+ {
186+ "expr": "NaN > true",
187+ "result": { "kind": "Boolean", "value": false }
188+ },
189+ {
190+ "expr": "Infinity > false",
191+ "result": { "kind": "Boolean", "value": true }
192+ },
193+ {
194+ "expr": "Infinity > true",
195+ "result": { "kind": "Boolean", "value": true }
196+ },
197+ {
198+ "expr": "-Infinity > false",
199+ "result": { "kind": "Boolean", "value": false }
200+ },
201+ {
202+ "expr": "-Infinity > true",
203+ "result": { "kind": "Boolean", "value": false }
204+ }
205+ ],
206+
207+ "coerce_number_string": [
208+ {
209+ "expr": "0 > ' 0 '",
210+ "result": { "kind": "Boolean", "value": false }
211+ },
212+ {
213+ "expr": "0 > ' -1 '",
214+ "result": { "kind": "Boolean", "value": true }
215+ },
216+ {
217+ "expr": "1 > ' 1 '",
218+ "result": { "kind": "Boolean", "value": false }
219+ },
220+ {
221+ "expr": "1 > ' 0 '",
222+ "result": { "kind": "Boolean", "value": true }
223+ }
224+ ],
225+
226+ "coerce_number_null": [
227+ {
228+ "expr": "1 > null",
229+ "result": { "kind": "Boolean", "value": true }
230+ },
231+ {
232+ "expr": "0 > null",
233+ "result": { "kind": "Boolean", "value": false }
234+ }
235+ ],
236+
237+ "coerce_number_object": [
238+ {
239+ "expr": "0 > test",
240+ "contexts": { "test": {} },
241+ "result": { "kind": "Boolean", "value": false }
242+ },
243+ {
244+ "expr": "1 > test",
245+ "contexts": { "test": {} },
246+ "result": { "kind": "Boolean", "value": false }
247+ }
248+ ],
249+
250+ "coerce_number_array": [
251+ {
252+ "expr": "0 > test",
253+ "contexts": { "test": [] },
254+ "result": { "kind": "Boolean", "value": false }
255+ },
256+ {
257+ "expr": "1 > test",
258+ "contexts": { "test": [] },
259+ "result": { "kind": "Boolean", "value": false }
260+ }
261+ ],
262+
263+ "coerce_string_bool": [
264+ {
265+ "expr": "'0' > false",
266+ "result": { "kind": "Boolean", "value": false }
267+ },
268+ {
269+ "expr": "'1' > false",
270+ "result": { "kind": "Boolean", "value": true }
271+ },
272+ {
273+ "expr": "'1' > true",
274+ "result": { "kind": "Boolean", "value": false }
275+ },
276+ {
277+ "expr": "'2' > true",
278+ "result": { "kind": "Boolean", "value": true }
279+ }
280+ ],
281+
282+ "coerce_string_number": [
283+ {
284+ "expr": "' 0 ' > -1",
285+ "result": { "kind": "Boolean", "value": true }
286+ },
287+ {
288+ "expr": "' 0 ' > 0",
289+ "result": { "kind": "Boolean", "value": false }
290+ },
291+ {
292+ "expr": "' 1 ' > 0",
293+ "result": { "kind": "Boolean", "value": true }
294+ },
295+ {
296+ "expr": "' 1 ' > 1",
297+ "result": { "kind": "Boolean", "value": false }
298+ }
299+ ],
300+
301+ "coerce_string_null": [
302+ {
303+ "expr": "'' > null",
304+ "result": { "kind": "Boolean", "value": false }
305+ },
306+ {
307+ "expr": "'1' > null",
308+ "result": { "kind": "Boolean", "value": true }
309+ }
310+ ],
311+
312+ "coerce_string_object": [
313+ {
314+ "expr": "'' > test",
315+ "contexts": { "test": {} },
316+ "result": { "kind": "Boolean", "value": false }
317+ }
318+ ],
319+
320+ "coerce_string_array": [
321+ {
322+ "expr": "'' > test",
323+ "contexts": { "test": [] },
324+ "result": { "kind": "Boolean", "value": false }
325+ }
326+ ],
327+
328+ "coerce_null_bool": [
329+ {
330+ "expr": "null > false",
331+ "result": { "kind": "Boolean", "value": false }
332+ },
333+ {
334+ "expr": "null > true",
335+ "result": { "kind": "Boolean", "value": false }
336+ }
337+ ],
338+
339+ "coerce_null_number": [
340+ {
341+ "expr": "null > 0",
342+ "result": { "kind": "Boolean", "value": false }
343+ },
344+ {
345+ "expr": "null > -1",
346+ "result": { "kind": "Boolean", "value": true }
347+ }
348+ ],
349+
350+ "coerce_null_string": [
351+ {
352+ "expr": "null > ' 0 '",
353+ "result": { "kind": "Boolean", "value": false }
354+ },
355+ {
356+ "expr": "null > ' -1 '",
357+ "result": { "kind": "Boolean", "value": true }
358+ }
359+ ],
360+
361+ "coerce_null_object": [
362+ {
363+ "expr": "null > test",
364+ "contexts": { "test": {} },
365+ "result": { "kind": "Boolean", "value": false }
366+ }
367+ ],
368+
369+ "coerce_null_array": [
370+ {
371+ "expr": "null > test",
372+ "contexts": { "test": [] },
373+ "result": { "kind": "Boolean", "value": false }
374+ }
375+ ]
376+}⏎̸
A expr/testdata/languageservices/op_gte.json +20 -0
@@ -0,0 +1,20 @@
1+{
2+ "bool": [
3+ {
4+ "expr": "false >= true",
5+ "result": { "kind": "Boolean", "value": false }
6+ },
7+ {
8+ "expr": "false >= false",
9+ "result": { "kind": "Boolean", "value": true }
10+ },
11+ {
12+ "expr": "true >= false",
13+ "result": { "kind": "Boolean", "value": true }
14+ },
15+ {
16+ "expr": "true >= true",
17+ "result": { "kind": "Boolean", "value": true }
18+ }
19+ ]
20+}⏎̸
A expr/testdata/languageservices/op_idx.json +354 -0
@@ -0,0 +1,354 @@
1+{
2+ "array-index-coercion": [
3+ {
4+ "expr": "foo[null]",
5+ "contexts": {
6+ "foo": [
7+ "zero",
8+ "one",
9+ "two"
10+ ]
11+ },
12+ "result": { "kind": "String", "value": "zero" }
13+ },
14+ {
15+ "expr": "foo[false]",
16+ "contexts": {
17+ "foo": [
18+ "zero",
19+ "one",
20+ "two"
21+ ]
22+ },
23+ "result": { "kind": "String", "value": "zero" }
24+ },
25+ {
26+ "expr": "foo[true]",
27+ "contexts": {
28+ "foo": [
29+ "zero",
30+ "one",
31+ "two"
32+ ]
33+ },
34+ "result": { "kind": "String", "value": "one" }
35+ },
36+ {
37+ "expr": "foo[' 0.0 ']",
38+ "contexts": {
39+ "foo": [
40+ "zero",
41+ "one",
42+ "two"
43+ ]
44+ },
45+ "result": { "kind": "String", "value": "zero" }
46+ },
47+ {
48+ "expr": "foo[' 0x02 ']",
49+ "contexts": {
50+ "foo": [
51+ "zero",
52+ "one",
53+ "two"
54+ ]
55+ },
56+ "result": { "kind": "String", "value": "two" }
57+ },
58+ {
59+ "expr": "foo[' asdf ']",
60+ "contexts": {
61+ "foo": [
62+ "zero",
63+ "one",
64+ "two"
65+ ]
66+ },
67+ "result": { "kind": "Null", "value": null }
68+ },
69+ {
70+ "expr": "foo[fromjson('[]')]",
71+ "contexts": {
72+ "foo": [
73+ "zero",
74+ "one",
75+ "two"
76+ ]
77+ },
78+ "result": { "kind": "Null", "value": null }
79+ },
80+ {
81+ "expr": "foo[fromjson('{}')]",
82+ "contexts": {
83+ "foo": [
84+ "zero",
85+ "one",
86+ "two"
87+ ]
88+ },
89+ "result": { "kind": "Null", "value": null }
90+ }
91+ ],
92+ "array-index-out-of-range": [
93+ {
94+ "expr": "foo[-1]",
95+ "contexts": {
96+ "foo": [
97+ "zero",
98+ "one",
99+ "two"
100+ ]
101+ },
102+ "result": { "kind": "Null", "value": null }
103+ },
104+ {
105+ "expr": "foo[3]",
106+ "contexts": {
107+ "foo": [
108+ "zero",
109+ "one",
110+ "two"
111+ ]
112+ },
113+ "result": { "kind": "Null", "value": null }
114+ },
115+ {
116+ "expr": "foo[-Infinity]",
117+ "contexts": {
118+ "foo": [
119+ "zero",
120+ "one",
121+ "two"
122+ ]
123+ },
124+ "result": { "kind": "Null", "value": null }
125+ },
126+ {
127+ "expr": "foo[Infinity]",
128+ "contexts": {
129+ "foo": [
130+ "zero",
131+ "one",
132+ "two"
133+ ]
134+ },
135+ "result": { "kind": "Null", "value": null }
136+ },
137+ {
138+ "expr": "foo[NaN]",
139+ "contexts": {
140+ "foo": [
141+ "zero",
142+ "one",
143+ "two"
144+ ]
145+ },
146+ "result": { "kind": "Null", "value": null }
147+ }
148+ ],
149+ "object-case-insensitive": [
150+ {
151+ "expr": "foo['bAr']",
152+ "contexts": {
153+ "foo": {
154+ "BaR": "baz"
155+ }
156+ },
157+ "result": { "kind": "String", "value": "baz" }
158+ }
159+ ],
160+ "object-index-coercion": [
161+ {
162+ "expr": "foo[5]",
163+ "contexts": {
164+ "foo": {
165+ "5": "it's 5"
166+ }
167+ },
168+ "result": { "kind": "String", "value": "it's 5" }
169+ },
170+ {
171+ "expr": "foo[.5]",
172+ "contexts": {
173+ "foo": {
174+ "0.5": "it's 0.5"
175+ }
176+ },
177+ "result": { "kind": "String", "value": "it's 0.5" }
178+ },
179+ {
180+ "expr": "foo[-.5]",
181+ "contexts": {
182+ "foo": {
183+ "-0.5": "it's -0.5"
184+ }
185+ },
186+ "result": { "kind": "String", "value": "it's -0.5" }
187+ },
188+ {
189+ "expr": "foo[0x0f]",
190+ "contexts": {
191+ "foo": {
192+ "15": "it's 15"
193+ }
194+ },
195+ "result": { "kind": "String", "value": "it's 15" }
196+ },
197+ {
198+ "expr": "foo[NaN]",
199+ "contexts": {
200+ "foo": {
201+ "NaN": "it's NaN"
202+ }
203+ },
204+ "result": { "kind": "String", "value": "it's NaN" }
205+ },
206+ {
207+ "expr": "foo[Infinity]",
208+ "contexts": {
209+ "foo": {
210+ "Infinity": "it's Infinity"
211+ }
212+ },
213+ "result": { "kind": "String", "value": "it's Infinity" }
214+ },
215+ {
216+ "expr": "foo[-Infinity]",
217+ "contexts": {
218+ "foo": {
219+ "-Infinity": "it's -Infinity"
220+ }
221+ },
222+ "result": { "kind": "String", "value": "it's -Infinity" }
223+ },
224+ {
225+ "expr": "foo[null]",
226+ "contexts": {
227+ "foo": {
228+ "": "it's null"
229+ }
230+ },
231+ "result": { "kind": "String", "value": "it's null" }
232+ },
233+ {
234+ "expr": "foo[true]",
235+ "contexts": {
236+ "foo": {
237+ "true": "it's true"
238+ }
239+ },
240+ "result": { "kind": "String", "value": "it's true" }
241+ },
242+ {
243+ "expr": "foo[false]",
244+ "contexts": {
245+ "foo": {
246+ "false": "it's false"
247+ }
248+ },
249+ "result": { "kind": "String", "value": "it's false" }
250+ },
251+ {
252+ "expr": "foo[fromJson('{}')]",
253+ "contexts": {
254+ "foo": {
255+ "Object": "It's Object"
256+ }
257+ },
258+ "result": { "kind": "Null", "value": null }
259+ },
260+ {
261+ "expr": "foo[format('{0}', fromJson('{}'))]",
262+ "contexts": {
263+ "foo": {
264+ "Object": "It's Object"
265+ }
266+ },
267+ "result": { "kind": "String", "value": "It's Object" }
268+ },
269+ {
270+ "expr": "foo[fromJson('[]')]",
271+ "contexts": {
272+ "foo": {
273+ "Array": "It's Array"
274+ }
275+ },
276+ "result": { "kind": "Null", "value": null }
277+ },
278+ {
279+ "expr": "foo[format('{0}', fromJson('[]'))]",
280+ "contexts": {
281+ "foo": {
282+ "Array": "It's Array"
283+ }
284+ },
285+ "result": { "kind": "String", "value": "It's Array" }
286+ }
287+ ],
288+ "object-index-out-of-range": [
289+ {
290+ "expr": "foo['']",
291+ "contexts": {
292+ "foo": {
293+ "bar": "baz"
294+ }
295+ },
296+ "result": { "kind": "Null", "value": null }
297+ },
298+ {
299+ "expr": "foo['asdf']",
300+ "contexts": {
301+ "foo": {
302+ "bar": "baz"
303+ }
304+ },
305+ "result": { "kind": "Null", "value": null }
306+ }
307+ ],
308+ "index-following-function": [
309+ {
310+ "expr": "fromJson('[\"one\", \"two\"]')[1]",
311+ "result": { "kind": "String", "value": "two" }
312+ }
313+ ],
314+ "index-following-group": [
315+ {
316+ "expr": "(fromJson('[\"one\", \"two\"]'))[1]",
317+ "result": { "kind": "String", "value": "two" }
318+ }
319+ ],
320+ "index-star": [
321+ {
322+ "expr": "foo[*]",
323+ "contexts": {
324+ "foo": {
325+ "one": "one val",
326+ "two": "two val",
327+ "*": "star val"
328+ }
329+ },
330+ "result": { "kind": "Array", "value": ["one val", "two val", "star val"] }
331+ },
332+ {
333+ "expr": "foo['*']",
334+ "contexts": {
335+ "foo": {
336+ "one": "one val",
337+ "two": "two val",
338+ "*": "star val"
339+ }
340+ },
341+ "result": { "kind": "String", "value": "star val" }
342+ },
343+ {
344+ "expr": "foo[*]",
345+ "contexts": {
346+ "foo": [
347+ "one",
348+ "two"
349+ ]
350+ },
351+ "result": { "kind": "Array", "value": ["one", "two"] }
352+ }
353+ ]
354+}
A expr/testdata/languageservices/op_idx_star.json +556 -0
@@ -0,0 +1,556 @@
1+{
2+ "filtered-array-from-literal": [
3+ {
4+ "expr": "foo.*",
5+ "contexts": {
6+ "foo": null
7+ },
8+ "result": { "kind": "Array", "value": [] }
9+ },
10+ {
11+ "expr": "foo.*",
12+ "contexts": {
13+ "foo": false
14+ },
15+ "result": { "kind": "Array", "value": [] }
16+ },
17+ {
18+ "expr": "foo.*",
19+ "contexts": {
20+ "foo": true
21+ },
22+ "result": { "kind": "Array", "value": [] }
23+ },
24+ {
25+ "expr": "foo.*",
26+ "contexts": {
27+ "foo": 123
28+ },
29+ "result": { "kind": "Array", "value": [] }
30+ },
31+ {
32+ "expr": "foo.*",
33+ "contexts": {
34+ "foo": "abc"
35+ },
36+ "result": { "kind": "Array", "value": [] }
37+ }
38+ ],
39+ "filtered-array-from-array": [
40+ {
41+ "expr": "foo.*",
42+ "contexts": {
43+ "foo": [
44+ "zero",
45+ "one"
46+ ]
47+ },
48+ "result": { "kind": "Array", "value": ["zero", "one"] }
49+ }
50+ ],
51+ "filtered-array-from-object": [
52+ {
53+ "expr": "foo.*",
54+ "contexts": {
55+ "foo": {
56+ "one": "one val",
57+ "two": "two val"
58+ }
59+ },
60+ "result": { "kind": "Array", "value": ["one val", "two val"] }
61+ }
62+ ],
63+ "nested-object": [
64+ {
65+ "expr": "foo.*.one",
66+ "contexts": {
67+ "foo": [
68+ {
69+ "one": "obj_1_prop_1",
70+ "two": "obj_1_prop_2"
71+ },
72+ {
73+ "one": "obj_2_prop_1",
74+ "two": "obj_2_prop_2"
75+ }
76+ ]
77+ },
78+ "result": { "kind": "Array", "value": ["obj_1_prop_1", "obj_2_prop_1"] }
79+ },
80+ {
81+ "expr": "foo[*]['']",
82+ "contexts": {
83+ "foo": [
84+ {
85+ "": "empty string"
86+ }
87+ ]
88+ },
89+ "result": { "kind": "Array", "value": ["empty string"] }
90+ }
91+ ],
92+ "nested-object-property-case-insensitive": [
93+ {
94+ "expr": "foo.*.thePROPERTY",
95+ "contexts": {
96+ "foo": [
97+ {
98+ "THEproperty": "the property"
99+ }
100+ ]
101+ },
102+ "result": { "kind": "Array", "value": ["the property"] }
103+ }
104+ ],
105+ "nested-object-property-not-found": [
106+ {
107+ "expr": "foo.*.one",
108+ "contexts": {
109+ "foo": [
110+ {
111+ "one": "obj_1_prop_1",
112+ "two": "obj_1_prop_2"
113+ },
114+ {
115+ "zero": "obj_2_prop_0",
116+ "three": "obj_2_prop_3"
117+ },
118+ {
119+ "one": "obj_3_prop_1",
120+ "two": "obj_3_prop_2"
121+ }
122+ ]
123+ },
124+ "result": { "kind": "Array", "value": ["obj_1_prop_1", "obj_3_prop_1"] }
125+ }
126+ ],
127+ "nested-object-property-coercion": [
128+ {
129+ "expr": "foo[*][null]",
130+ "contexts": {
131+ "foo": [
132+ {
133+ "": "empty string"
134+ }
135+ ]
136+ },
137+ "result": { "kind": "Array", "value": ["empty string"] }
138+ },
139+ {
140+ "expr": "foo[*][false]",
141+ "contexts": {
142+ "foo": [
143+ {
144+ "false": "It's false"
145+ }
146+ ]
147+ },
148+ "result": { "kind": "Array", "value": ["It's false"] }
149+ },
150+ {
151+ "expr": "foo[*][true]",
152+ "contexts": {
153+ "foo": [
154+ {
155+ "true": "It's true"
156+ }
157+ ]
158+ },
159+ "result": { "kind": "Array", "value": ["It's true"] }
160+ },
161+ {
162+ "expr": "foo[*][0x0f]",
163+ "contexts": {
164+ "foo": [
165+ {
166+ "15": "fifteen"
167+ }
168+ ]
169+ },
170+ "result": { "kind": "Array", "value": ["fifteen"] }
171+ },
172+ {
173+ "expr": "foo[*][NaN]",
174+ "contexts": {
175+ "foo": [
176+ {
177+ "NaN": "It's NaN"
178+ }
179+ ]
180+ },
181+ "result": { "kind": "Array", "value": ["It's NaN"] }
182+ },
183+ {
184+ "expr": "foo[*][Infinity]",
185+ "contexts": {
186+ "foo": [
187+ {
188+ "Infinity": "It's Infinity"
189+ }
190+ ]
191+ },
192+ "result": { "kind": "Array", "value": ["It's Infinity"] }
193+ },
194+ {
195+ "expr": "foo[*][-Infinity]",
196+ "contexts": {
197+ "foo": [
198+ {
199+ "-Infinity": "It's -Infinity"
200+ }
201+ ]
202+ },
203+ "result": { "kind": "Array", "value": ["It's -Infinity"] }
204+ },
205+ {
206+ "expr": "foo[*][fromjson('[]')]",
207+ "contexts": {
208+ "foo": [
209+ {
210+ "": "empty string",
211+ "Array": "It's array"
212+ }
213+ ]
214+ },
215+ "result": { "kind": "Array", "value": [] }
216+ },
217+ {
218+ "expr": "foo[*][fromjson('{}')]",
219+ "contexts": {
220+ "foo": [
221+ {
222+ "": "empty string",
223+ "Object": "It's object"
224+ }
225+ ]
226+ },
227+ "result": { "kind": "Array", "value": [] }
228+ }
229+ ],
230+ "nested-array": [
231+ {
232+ "expr": "foo[*][1]",
233+ "contexts": {
234+ "foo": [
235+ [
236+ "ary_0_idx_0",
237+ "ary_0_idx_1",
238+ "ary_0_idx_2"
239+ ],
240+ [
241+ "ary_1_idx_0",
242+ "ary_1_idx_1",
243+ "ary_1_idx_2"
244+ ]
245+ ]
246+ },
247+ "result": { "kind": "Array", "value": ["ary_0_idx_1", "ary_1_idx_1"] }
248+ }
249+ ],
250+ "nested-array-index-not-found": [
251+ {
252+ "expr": "foo[*][1]",
253+ "contexts": {
254+ "foo": [
255+ [
256+ "ary_0_idx_0",
257+ "ary_0_idx_1",
258+ "ary_0_idx_2"
259+ ],
260+ [
261+ "ary_1_idx_0"
262+ ],
263+ [
264+ "ary_2_idx_0",
265+ "ary_2_idx_1",
266+ "ary_2_idx_2"
267+ ]
268+ ]
269+ },
270+ "result": { "kind": "Array", "value": ["ary_0_idx_1", "ary_2_idx_1"] }
271+ },
272+ {
273+ "expr": "foo[*][-1]",
274+ "contexts": {
275+ "foo": [
276+ [
277+ "zero",
278+ "one",
279+ "two"
280+ ]
281+ ]
282+ },
283+ "result": { "kind": "Array", "value": [] }
284+ },
285+ {
286+ "expr": "foo[*][NaN]",
287+ "contexts": {
288+ "foo": [
289+ [
290+ "zero",
291+ "one",
292+ "two"
293+ ]
294+ ]
295+ },
296+ "result": { "kind": "Array", "value": [] }
297+ },
298+ {
299+ "expr": "foo[*][Infinity]",
300+ "contexts": {
301+ "foo": [
302+ [
303+ "zero",
304+ "one",
305+ "two"
306+ ]
307+ ]
308+ },
309+ "result": { "kind": "Array", "value": [] }
310+ },
311+ {
312+ "expr": "foo[*][Infinity]",
313+ "contexts": {
314+ "foo": [
315+ [
316+ "zero",
317+ "one",
318+ "two"
319+ ]
320+ ]
321+ },
322+ "result": { "kind": "Array", "value": [] }
323+ }
324+ ],
325+ "nested-array-index-coercion": [
326+ {
327+ "expr": "foo[*][null]",
328+ "contexts": {
329+ "foo": [
330+ [
331+ "zero",
332+ "one",
333+ "two"
334+ ]
335+ ]
336+ },
337+ "result": { "kind": "Array", "value": ["zero"] }
338+ },
339+ {
340+ "expr": "foo[*][false]",
341+ "contexts": {
342+ "foo": [
343+ [
344+ "zero",
345+ "one",
346+ "two"
347+ ]
348+ ]
349+ },
350+ "result": { "kind": "Array", "value": ["zero"] }
351+ },
352+ {
353+ "expr": "foo[*][true]",
354+ "contexts": {
355+ "foo": [
356+ [
357+ "zero",
358+ "one",
359+ "two"
360+ ]
361+ ]
362+ },
363+ "result": { "kind": "Array", "value": ["one"] }
364+ },
365+ {
366+ "expr": "foo[*]['']",
367+ "contexts": {
368+ "foo": [
369+ [
370+ "zero",
371+ "one",
372+ "two"
373+ ]
374+ ]
375+ },
376+ "result": { "kind": "Array", "value": ["zero"] }
377+ },
378+ {
379+ "expr": "foo[*]['abc']",
380+ "contexts": {
381+ "foo": [
382+ [
383+ "zero",
384+ "one",
385+ "two"
386+ ]
387+ ]
388+ },
389+ "result": { "kind": "Array", "value": [] }
390+ },
391+ {
392+ "expr": "foo[*][' 0x01 ']",
393+ "contexts": {
394+ "foo": [
395+ [
396+ "zero",
397+ "one",
398+ "two"
399+ ]
400+ ]
401+ },
402+ "result": { "kind": "Array", "value": ["one"] }
403+ },
404+ {
405+ "expr": "foo[*][fromjson('[]')]",
406+ "contexts": {
407+ "foo": [
408+ [
409+ "zero",
410+ "one",
411+ "two"
412+ ]
413+ ]
414+ },
415+ "result": { "kind": "Array", "value": [] }
416+ },
417+ {
418+ "expr": "foo[*][fromjson('{}')]",
419+ "contexts": {
420+ "foo": [
421+ [
422+ "zero",
423+ "one",
424+ "two"
425+ ]
426+ ]
427+ },
428+ "result": { "kind": "Array", "value": [] }
429+ }
430+ ],
431+ "double-star": [
432+ {
433+ "expr": "foo.*.*",
434+ "contexts": {
435+ "foo": [
436+ null,
437+ false,
438+ true,
439+ 123,
440+ "hello",
441+ [
442+ "zero",
443+ "one",
444+ "two"
445+ ],
446+ {
447+ "p1": "v1",
448+ "p2": "v2",
449+ "p3": "v3"
450+ }
451+ ]
452+ },
453+ "result": { "kind": "Array", "value": ["zero", "one", "two", "v1", "v2", "v3"] }
454+ }
455+ ],
456+ "double-property": [
457+ {
458+ "expr": "foo.*.p.nestedp",
459+ "contexts": {
460+ "foo": [
461+ {
462+ "p": {
463+ "nestedp": "val 1"
464+ }
465+ },
466+ {
467+ "p": {
468+ "nestedp": "val 2"
469+ }
470+ }
471+ ]
472+ },
473+ "result": { "kind": "Array", "value": ["val 1", "val 2"] }
474+ }
475+ ],
476+ "double-index": [
477+ {
478+ "expr": "foo[*][1][2]",
479+ "contexts": {
480+ "foo": [
481+ [
482+ [
483+ "0_0_0",
484+ "0_0_1",
485+ "0_0_2",
486+ "0_0_3"
487+ ],
488+ [
489+ "0_1_0",
490+ "0_1_1",
491+ "0_1_2",
492+ "0_1_3"
493+ ],
494+ [
495+ "0_2_0",
496+ "0_2_1",
497+ "0_2_2",
498+ "0_2_3"
499+ ]
500+ ],
501+ [
502+ [
503+ "1_0_0",
504+ "1_0_1",
505+ "1_0_2",
506+ "1_0_3"
507+ ],
508+ [
509+ "1_1_0",
510+ "1_1_1",
511+ "1_1_2",
512+ "1_1_3"
513+ ],
514+ [
515+ "1_2_0",
516+ "1_2_1",
517+ "1_2_2",
518+ "1_2_3"
519+ ]
520+ ]
521+ ]
522+ },
523+ "result": { "kind": "Array", "value": ["0_1_2", "1_1_2"] }
524+ }
525+ ],
526+ "not-found-always-returns-empty-array": [
527+ {
528+ "expr": "foo[*][1]",
529+ "contexts": {
530+ "foo": []
531+ },
532+ "result": { "kind": "Array", "value": [] }
533+ },
534+ {
535+ "expr": "foo[*][1][2]",
536+ "contexts": {
537+ "foo": []
538+ },
539+ "result": { "kind": "Array", "value": [] }
540+ },
541+ {
542+ "expr": "foo.*.bar",
543+ "contexts": {
544+ "foo": {}
545+ },
546+ "result": { "kind": "Array", "value": [] }
547+ },
548+ {
549+ "expr": "foo.*.bar.baz",
550+ "contexts": {
551+ "foo": []
552+ },
553+ "result": { "kind": "Array", "value": [] }
554+ }
555+ ]
556+}
A expr/testdata/languageservices/op_lt.json +378 -0
@@ -0,0 +1,378 @@
1+{
2+ "bool": [
3+ {
4+ "expr": "false < true",
5+ "result": { "kind": "Boolean", "value": true }
6+ },
7+ {
8+ "expr": "false < false",
9+ "result": { "kind": "Boolean", "value": false }
10+ },
11+ {
12+ "expr": "true < false",
13+ "result": { "kind": "Boolean", "value": false }
14+ },
15+ {
16+ "expr": "true < true",
17+ "result": { "kind": "Boolean", "value": false }
18+ }
19+ ],
20+
21+ "number": [
22+ {
23+ "expr": "1 < 2",
24+ "result": { "kind": "Boolean", "value": true }
25+ },
26+ {
27+ "expr": "1 < 1",
28+ "result": { "kind": "Boolean", "value": false }
29+ },
30+ {
31+ "expr": "2 < 1",
32+ "result": { "kind": "Boolean", "value": false }
33+ },
34+ {
35+ "expr": "1.001 < 1.002",
36+ "result": { "kind": "Boolean", "value": true }
37+ }
38+ ],
39+
40+ "string": [
41+ {
42+ "expr": "'abc' < 'def'",
43+ "result": { "kind": "Boolean", "value": true }
44+ },
45+ {
46+ "expr": "'b' < 'a'",
47+ "result": { "kind": "Boolean", "value": false }
48+ }
49+ ],
50+
51+ "array": [
52+ {
53+ "expr": "test < test",
54+ "contexts": { "test": [] },
55+ "result": { "kind": "Boolean", "value": false }
56+ }
57+ ],
58+
59+ "object": [
60+ {
61+ "expr": "test < test",
62+ "contexts": { "test": {} },
63+ "result": { "kind": "Boolean", "value": false }
64+ }
65+ ],
66+
67+ "coerce_bool_number": [
68+ {
69+ "expr": "false < 0",
70+ "result": { "kind": "Boolean", "value": false }
71+ },
72+ {
73+ "expr": "false < 1",
74+ "result": { "kind": "Boolean", "value": true }
75+ },
76+ {
77+ "expr": "true < 1",
78+ "result": { "kind": "Boolean", "value": false }
79+ },
80+ {
81+ "expr": "true < 2",
82+ "result": { "kind": "Boolean", "value": true }
83+ },
84+ {
85+ "expr": "false < NaN",
86+ "result": { "kind": "Boolean", "value": false }
87+ },
88+ {
89+ "expr": "true < NaN",
90+ "result": { "kind": "Boolean", "value": false }
91+ },
92+ {
93+ "expr": "false < Infinity",
94+ "result": { "kind": "Boolean", "value": true }
95+ },
96+ {
97+ "expr": "true < Infinity",
98+ "result": { "kind": "Boolean", "value": true }
99+ },
100+ {
101+ "expr": "false < -Infinity",
102+ "result": { "kind": "Boolean", "value": false }
103+ },
104+ {
105+ "expr": "true < -Infinity",
106+ "result": { "kind": "Boolean", "value": false }
107+ }
108+ ],
109+
110+ "coerce_bool_string": [
111+ {
112+ "expr": "false < '0'",
113+ "result": { "kind": "Boolean", "value": false }
114+ },
115+ {
116+ "expr": "false < '1'",
117+ "result": { "kind": "Boolean", "value": true }
118+ },
119+ {
120+ "expr": "true < '1'",
121+ "result": { "kind": "Boolean", "value": false }
122+ },
123+ {
124+ "expr": "true < '2'",
125+ "result": { "kind": "Boolean", "value": true }
126+ }
127+ ],
128+
129+ "coerce_bool_null": [
130+ {
131+ "expr": "false < null",
132+ "result": { "kind": "Boolean", "value": false }
133+ },
134+ {
135+ "expr": "true < null",
136+ "result": { "kind": "Boolean", "value": false }
137+ }
138+ ],
139+
140+ "coerce_bool_object": [
141+ {
142+ "expr": "false < test",
143+ "contexts": { "test": {} },
144+ "result": { "kind": "Boolean", "value": false }
145+ },
146+ {
147+ "expr": "true < test",
148+ "contexts": { "test": {} },
149+ "result": { "kind": "Boolean", "value": false }
150+ }
151+ ],
152+
153+ "coerce_bool_array": [
154+ {
155+ "expr": "false < test",
156+ "contexts": { "test": [] },
157+ "result": { "kind": "Boolean", "value": false }
158+ },
159+ {
160+ "expr": "true < test",
161+ "contexts": { "test": [] },
162+ "result": { "kind": "Boolean", "value": false }
163+ }
164+ ],
165+
166+ "coerce_number_bool": [
167+ {
168+ "expr": "-1 < false",
169+ "result": { "kind": "Boolean", "value": true }
170+ },
171+ {
172+ "expr": "0 < false",
173+ "result": { "kind": "Boolean", "value": false }
174+ },
175+ {
176+ "expr": "0 < true",
177+ "result": { "kind": "Boolean", "value": true }
178+ },
179+ {
180+ "expr": "1 < true",
181+ "result": { "kind": "Boolean", "value": false }
182+ },
183+ {
184+ "expr": "NaN < false",
185+ "result": { "kind": "Boolean", "value": false }
186+ },
187+ {
188+ "expr": "NaN < true",
189+ "result": { "kind": "Boolean", "value": false }
190+ },
191+ {
192+ "expr": "Infinity < false",
193+ "result": { "kind": "Boolean", "value": false }
194+ },
195+ {
196+ "expr": "Infinity < true",
197+ "result": { "kind": "Boolean", "value": false }
198+ },
199+ {
200+ "expr": "-Infinity < false",
201+ "result": { "kind": "Boolean", "value": true }
202+ },
203+ {
204+ "expr": "-Infinity < true",
205+ "result": { "kind": "Boolean", "value": true }
206+ }
207+ ],
208+
209+ "coerce_number_string": [
210+ {
211+ "expr": "0 < ' 0 '",
212+ "result": { "kind": "Boolean", "value": false }
213+ },
214+ {
215+ "expr": "0 < ' 1 '",
216+ "result": { "kind": "Boolean", "value": true }
217+ },
218+ {
219+ "expr": "1 < ' 1 '",
220+ "result": { "kind": "Boolean", "value": false }
221+ },
222+ {
223+ "expr": "1 < ' 2 '",
224+ "result": { "kind": "Boolean", "value": true }
225+ }
226+ ],
227+
228+ "coerce_number_null": [
229+ {
230+ "expr": "-1 < null",
231+ "result": { "kind": "Boolean", "value": true }
232+ },
233+ {
234+ "expr": "0 < null",
235+ "result": { "kind": "Boolean", "value": false }
236+ }
237+ ],
238+
239+ "coerce_number_object": [
240+ {
241+ "expr": "0 < test",
242+ "contexts": { "test": {} },
243+ "result": { "kind": "Boolean", "value": false }
244+ },
245+ {
246+ "expr": "-1 < test",
247+ "contexts": { "test": {} },
248+ "result": { "kind": "Boolean", "value": false }
249+ }
250+ ],
251+
252+ "coerce_number_array": [
253+ {
254+ "expr": "0 < test",
255+ "contexts": { "test": [] },
256+ "result": { "kind": "Boolean", "value": false }
257+ },
258+ {
259+ "expr": "-1 < test",
260+ "contexts": { "test": [] },
261+ "result": { "kind": "Boolean", "value": false }
262+ }
263+ ],
264+
265+ "coerce_string_bool": [
266+ {
267+ "expr": "'0' < false",
268+ "result": { "kind": "Boolean", "value": false }
269+ },
270+ {
271+ "expr": "'-1' < false",
272+ "result": { "kind": "Boolean", "value": true }
273+ },
274+ {
275+ "expr": "'1' < true",
276+ "result": { "kind": "Boolean", "value": false }
277+ },
278+ {
279+ "expr": "'0' < true",
280+ "result": { "kind": "Boolean", "value": true }
281+ }
282+ ],
283+
284+ "coerce_string_number": [
285+ {
286+ "expr": "' 0 ' < 1",
287+ "result": { "kind": "Boolean", "value": true }
288+ },
289+ {
290+ "expr": "' 0 ' < 0",
291+ "result": { "kind": "Boolean", "value": false }
292+ },
293+ {
294+ "expr": "' 1 ' < 2",
295+ "result": { "kind": "Boolean", "value": true }
296+ },
297+ {
298+ "expr": "' 1 ' < 1",
299+ "result": { "kind": "Boolean", "value": false }
300+ }
301+ ],
302+
303+ "coerce_string_null": [
304+ {
305+ "expr": "'' < null",
306+ "result": { "kind": "Boolean", "value": false }
307+ },
308+ {
309+ "expr": "'-1' < null",
310+ "result": { "kind": "Boolean", "value": true }
311+ }
312+ ],
313+
314+ "coerce_string_object": [
315+ {
316+ "expr": "'' < test",
317+ "contexts": { "test": {} },
318+ "result": { "kind": "Boolean", "value": false }
319+ }
320+ ],
321+
322+ "coerce_string_array": [
323+ {
324+ "expr": "'' < test",
325+ "contexts": { "test": [] },
326+ "result": { "kind": "Boolean", "value": false }
327+ }
328+ ],
329+
330+ "coerce_null_bool": [
331+ {
332+ "expr": "null < false",
333+ "result": { "kind": "Boolean", "value": false }
334+ },
335+ {
336+ "expr": "null < true",
337+ "result": { "kind": "Boolean", "value": true }
338+ }
339+ ],
340+
341+ "coerce_null_number": [
342+ {
343+ "expr": "null < 0",
344+ "result": { "kind": "Boolean", "value": false }
345+ },
346+ {
347+ "expr": "null < 1",
348+ "result": { "kind": "Boolean", "value": true }
349+ }
350+ ],
351+
352+ "coerce_null_string": [
353+ {
354+ "expr": "null < ' 0 '",
355+ "result": { "kind": "Boolean", "value": false }
356+ },
357+ {
358+ "expr": "null < ' 1 '",
359+ "result": { "kind": "Boolean", "value": true }
360+ }
361+ ],
362+
363+ "coerce_null_object": [
364+ {
365+ "expr": "null < test",
366+ "contexts": { "test": {} },
367+ "result": { "kind": "Boolean", "value": false }
368+ }
369+ ],
370+
371+ "coerce_null_array": [
372+ {
373+ "expr": "null < test",
374+ "contexts": { "test": [] },
375+ "result": { "kind": "Boolean", "value": false }
376+ }
377+ ]
378+}⏎̸
A expr/testdata/languageservices/op_lte.json +20 -0
@@ -0,0 +1,20 @@
1+{
2+ "bool": [
3+ {
4+ "expr": "false <= true",
5+ "result": { "kind": "Boolean", "value": true }
6+ },
7+ {
8+ "expr": "false <= false",
9+ "result": { "kind": "Boolean", "value": true }
10+ },
11+ {
12+ "expr": "true <= false",
13+ "result": { "kind": "Boolean", "value": false }
14+ },
15+ {
16+ "expr": "true <= true",
17+ "result": { "kind": "Boolean", "value": true }
18+ }
19+ ]
20+}⏎̸
A expr/testdata/languageservices/op_ne.json +597 -0
@@ -0,0 +1,597 @@
1+{
2+ "boolean": [
3+ {
4+ "expr": "true != true",
5+ "result": { "kind": "Boolean", "value": false }
6+ },
7+ {
8+ "expr": "false != false",
9+ "result": { "kind": "Boolean", "value": false }
10+ },
11+ {
12+ "expr": "true != true",
13+ "result": { "kind": "Boolean", "value": false }
14+ }
15+ ],
16+
17+ "number": [
18+ {
19+ "expr": "0 != -0",
20+ "result": { "kind": "Boolean", "value": false }
21+ },
22+ {
23+ "expr": "2 != 2",
24+ "result": { "kind": "Boolean", "value": false }
25+ },
26+ {
27+ "expr": "120 != 1.2e2",
28+ "result": { "kind": "Boolean", "value": false }
29+ },
30+ {
31+ "expr": "1 != 2",
32+ "result": { "kind": "Boolean", "value": true }
33+ },
34+ {
35+ "expr": "1.001 != 1.002",
36+ "result": { "kind": "Boolean", "value": true }
37+ },
38+ {
39+ "expr": "NaN != NaN",
40+ "result": { "kind": "Boolean", "value": true }
41+ },
42+ {
43+ "expr": "0 != NaN",
44+ "result": { "kind": "Boolean", "value": true }
45+ },
46+ {
47+ "expr": "1 != NaN",
48+ "result": { "kind": "Boolean", "value": true }
49+ },
50+ {
51+ "expr": "Infinity != Infinity",
52+ "result": { "kind": "Boolean", "value": false }
53+ },
54+ {
55+ "expr": "-Infinity != Infinity",
56+ "result": { "kind": "Boolean", "value": true }
57+ },
58+ {
59+ "expr": "0 != Infinity",
60+ "result": { "kind": "Boolean", "value": true }
61+ },
62+ {
63+ "expr": "1 != Infinity",
64+ "result": { "kind": "Boolean", "value": true }
65+ }
66+ ],
67+
68+ "string": [
69+ {
70+ "expr": "'a' != 'a'",
71+ "result": { "kind": "Boolean", "value": false }
72+ },
73+ {
74+ "expr": "'a' != 'b'",
75+ "result": { "kind": "Boolean", "value": true }
76+ }
77+ ],
78+
79+ "null": [
80+ { "expr": "null != null", "result": { "kind": "Boolean", "value": false } }
81+ ],
82+
83+ "object": [
84+ {
85+ "expr": "object1 != object1",
86+ "contexts": { "object1": {} },
87+ "result": { "kind": "Boolean", "value": false }
88+ },
89+ {
90+ "expr": "object1 != object2",
91+ "contexts": { "object1": {}, "object2": {} },
92+ "result": { "kind": "Boolean", "value": true }
93+ }
94+ ],
95+
96+ "array": [
97+ {
98+ "expr": "array1 != array1",
99+ "contexts": { "array1": [] },
100+ "result": { "kind": "Boolean", "value": false }
101+ },
102+ {
103+ "expr": "array1 != array2",
104+ "contexts": { "array1": [], "array2": [] },
105+ "result": { "kind": "Boolean", "value": true }
106+ }
107+ ],
108+
109+ "coerce_bool_number": [
110+ {
111+ "expr": "false != 0",
112+ "result": { "kind": "Boolean", "value": false }
113+ },
114+ {
115+ "expr": "false != 1",
116+ "result": { "kind": "Boolean", "value": true }
117+ },
118+ {
119+ "expr": "true != 1",
120+ "result": { "kind": "Boolean", "value": false }
121+ },
122+ {
123+ "expr": "false != NaN",
124+ "result": { "kind": "Boolean", "value": true }
125+ },
126+ {
127+ "expr": "true != 2",
128+ "result": { "kind": "Boolean", "value": true }
129+ }
130+ ],
131+
132+ "coerce_bool_string": [
133+ {
134+ "expr": "false != ''",
135+ "result": { "kind": "Boolean", "value": false }
136+ },
137+ {
138+ "expr": "false != ' '",
139+ "result": { "kind": "Boolean", "value": false }
140+ },
141+ {
142+ "expr": "false != ' 0.0 '",
143+ "result": { "kind": "Boolean", "value": false }
144+ },
145+ {
146+ "expr": "false != ' 1.0 '",
147+ "result": { "kind": "Boolean", "value": true }
148+ },
149+ {
150+ "expr": "true != ' 1.0 '",
151+ "result": { "kind": "Boolean", "value": false }
152+ },
153+ {
154+ "expr": "true != ' 1 '",
155+ "result": { "kind": "Boolean", "value": false }
156+ },
157+ {
158+ "expr": "false != '-1'",
159+ "result": { "kind": "Boolean", "value": true }
160+ },
161+ {
162+ "expr": "true != '2'",
163+ "result": { "kind": "Boolean", "value": true }
164+ }
165+ ],
166+
167+ "coerce_bool_null": [
168+ {
169+ "expr": "false != null",
170+ "result": { "kind": "Boolean", "value": false }
171+ },
172+ {
173+ "expr": "true != null",
174+ "result": { "kind": "Boolean", "value": true }
175+ }
176+ ],
177+
178+ "coerce_bool_object-array": [
179+ {
180+ "expr": "false != test",
181+ "contexts": { "test": {} },
182+ "result": { "kind": "Boolean", "value": true }
183+ },
184+ {
185+ "expr": "false != test",
186+ "contexts": { "test": [] },
187+ "result": { "kind": "Boolean", "value": true }
188+ },
189+ {
190+ "expr": "true != test",
191+ "contexts": { "test": {} },
192+ "result": { "kind": "Boolean", "value": true }
193+ },
194+ {
195+ "expr": "true != test",
196+ "contexts": { "test": [] },
197+ "result": { "kind": "Boolean", "value": true }
198+ }
199+ ],
200+
201+ "coerce_number_bool": [
202+ {
203+ "expr": "0 != false",
204+ "result": { "kind": "Boolean", "value": false }
205+ },
206+ {
207+ "expr": "1 != false",
208+ "result": { "kind": "Boolean", "value": true }
209+ },
210+ {
211+ "expr": "1 != true",
212+ "result": { "kind": "Boolean", "value": false }
213+ },
214+ {
215+ "expr": "2 != true",
216+ "result": { "kind": "Boolean", "value": true }
217+ },
218+ {
219+ "expr": "NaN != false",
220+ "result": { "kind": "Boolean", "value": true }
221+ }
222+ ],
223+
224+ "coerce_number_string": [
225+ {
226+ "expr": "0 != ' -0.0 '",
227+ "result": { "kind": "Boolean", "value": false }
228+ },
229+ {
230+ "expr": "0 != ''",
231+ "result": { "kind": "Boolean", "value": false }
232+ },
233+ {
234+ "expr": "0 != ' '",
235+ "result": { "kind": "Boolean", "value": false }
236+ },
237+ {
238+ "expr": "120 != ' +1.2e2 '",
239+ "result": { "kind": "Boolean", "value": false }
240+ },
241+ {
242+ "expr": "120.0 != ' 1.2E2 '",
243+ "result": { "kind": "Boolean", "value": false }
244+ },
245+ {
246+ "expr": "120 != ' 1.2e+2 '",
247+ "result": { "kind": "Boolean", "value": false }
248+ },
249+ {
250+ "expr": "-120 != ' -1.2E+2 '",
251+ "result": { "kind": "Boolean", "value": false }
252+ },
253+ {
254+ "expr": "0.012 != ' 1.2e-2 '",
255+ "result": { "kind": "Boolean", "value": false }
256+ },
257+ {
258+ "expr": "0.012 != ' 1.2E-2 '",
259+ "result": { "kind": "Boolean", "value": false }
260+ },
261+ {
262+ "expr": "255.0 != ' 0xff '",
263+ "result": { "kind": "Boolean", "value": false }
264+ },
265+ {
266+ "expr": "8.0 != ' 0o10 '",
267+ "result": { "kind": "Boolean", "value": false }
268+ },
269+ {
270+ "expr": "Infinity != ' Infinity '",
271+ "result": { "kind": "Boolean", "value": false }
272+ },
273+ {
274+ "expr": "-Infinity != ' -Infinity '",
275+ "result": { "kind": "Boolean", "value": false }
276+ },
277+ {
278+ "expr": "NaN != 'NaN'",
279+ "result": { "kind": "Boolean", "value": true }
280+ },
281+ {
282+ "expr": "1 != '0'",
283+ "result": { "kind": "Boolean", "value": true }
284+ },
285+ {
286+ "expr": "1 != '1'",
287+ "result": { "kind": "Boolean", "value": false }
288+ },
289+ {
290+ "expr": "1 != 'a'",
291+ "result": { "kind": "Boolean", "value": true }
292+ },
293+ {
294+ "expr": "0 != 'a'",
295+ "result": { "kind": "Boolean", "value": true }
296+ }
297+ ],
298+
299+ "coerce_number_null": [
300+ {
301+ "expr": "0 != null",
302+ "result": { "kind": "Boolean", "value": false }
303+ },
304+ {
305+ "expr": "1 != null",
306+ "result": { "kind": "Boolean", "value": true }
307+ }
308+ ],
309+
310+ "coerce_number_object-array": [
311+ {
312+ "expr": "0 != test",
313+ "contexts": { "test": {} },
314+ "result": { "kind": "Boolean", "value": true }
315+ },
316+ {
317+ "expr": "1 != test",
318+ "contexts": { "test": {} },
319+ "result": { "kind": "Boolean", "value": true }
320+ },
321+ {
322+ "expr": "0 != test",
323+ "contexts": { "test": [] },
324+ "result": { "kind": "Boolean", "value": true }
325+ },
326+ {
327+ "expr": "1 != test",
328+ "contexts": { "test": [] },
329+ "result": { "kind": "Boolean", "value": true }
330+ }
331+ ],
332+
333+ "coerce_string_bool": [
334+ {
335+ "expr": "'' != false",
336+ "result": { "kind": "Boolean", "value": false }
337+ },
338+ {
339+ "expr": "' ' != false",
340+ "result": { "kind": "Boolean", "value": false }
341+ },
342+ {
343+ "expr": "' 0.0 ' != false",
344+ "result": { "kind": "Boolean", "value": false }
345+ },
346+ {
347+ "expr": "' 1.0 ' != false",
348+ "result": { "kind": "Boolean", "value": true }
349+ },
350+ {
351+ "expr": "' 1.0 ' != true",
352+ "result": { "kind": "Boolean", "value": false }
353+ },
354+ {
355+ "expr": "' 1 ' != true",
356+ "result": { "kind": "Boolean", "value": false }
357+ },
358+ {
359+ "expr": "'-1' != true",
360+ "result": { "kind": "Boolean", "value": true }
361+ },
362+ {
363+ "expr": "'2' != true",
364+ "result": { "kind": "Boolean", "value": true }
365+ }
366+ ],
367+
368+ "coerce_string_number": [
369+ {
370+ "expr": "' -0.0 ' != 0",
371+ "result": { "kind": "Boolean", "value": false }
372+ },
373+ {
374+ "expr": "'' != 0",
375+ "result": { "kind": "Boolean", "value": false }
376+ },
377+ {
378+ "expr": "' ' != 0",
379+ "result": { "kind": "Boolean", "value": false }
380+ },
381+ {
382+ "expr": "' +1.2e2 ' != 120",
383+ "result": { "kind": "Boolean", "value": false }
384+ },
385+ {
386+ "expr": "' 1.2E2 ' != 120.0",
387+ "result": { "kind": "Boolean", "value": false }
388+ },
389+ {
390+ "expr": "' 1.2e+2 ' != 120",
391+ "result": { "kind": "Boolean", "value": false }
392+ },
393+ {
394+ "expr": "' -1.2E+2 ' != -120",
395+ "result": { "kind": "Boolean", "value": false }
396+ },
397+ {
398+ "expr": "' 1.2e-2 ' != 0.012",
399+ "result": { "kind": "Boolean", "value": false }
400+ },
401+ {
402+ "expr": "' 1.2E-2 ' != 0.012",
403+ "result": { "kind": "Boolean", "value": false }
404+ },
405+ {
406+ "expr": "' 0xff ' != 255.0",
407+ "result": { "kind": "Boolean", "value": false }
408+ },
409+ {
410+ "expr": "' 0o10 ' != 8.0",
411+ "result": { "kind": "Boolean", "value": false }
412+ },
413+ {
414+ "expr": "' Infinity ' != Infinity",
415+ "result": { "kind": "Boolean", "value": false }
416+ },
417+ {
418+ "expr": "' -Infinity ' != -Infinity",
419+ "result": { "kind": "Boolean", "value": false }
420+ },
421+ {
422+ "expr": "'NaN' != NaN",
423+ "result": { "kind": "Boolean", "value": true }
424+ },
425+ {
426+ "expr": "'0' != 1",
427+ "result": { "kind": "Boolean", "value": true }
428+ },
429+ {
430+ "expr": "'1' != 1",
431+ "result": { "kind": "Boolean", "value": false }
432+ },
433+ {
434+ "expr": "'a' != 1",
435+ "result": { "kind": "Boolean", "value": true }
436+ },
437+ {
438+ "expr": "'a' != 0",
439+ "result": { "kind": "Boolean", "value": true }
440+ }
441+ ],
442+
443+ "coerce_string_null": [
444+ {
445+ "expr": "'' != null",
446+ "result": { "kind": "Boolean", "value": false }
447+ },
448+ {
449+ "expr": "' ' != null",
450+ "result": { "kind": "Boolean", "value": false }
451+ },
452+ {
453+ "expr": "'0' != null",
454+ "result": { "kind": "Boolean", "value": false }
455+ },
456+ {
457+ "expr": "'1' != null",
458+ "result": { "kind": "Boolean", "value": true }
459+ },
460+ {
461+ "expr": "'false' != null",
462+ "result": { "kind": "Boolean", "value": true }
463+ },
464+ {
465+ "expr": "'null' != null",
466+ "result": { "kind": "Boolean", "value": true }
467+ }
468+ ],
469+
470+ "coerce_string_object": [
471+ {
472+ "expr": "'' != test",
473+ "contexts": { "test": {} },
474+ "result": { "kind": "Boolean", "value": true }
475+ },
476+ {
477+ "expr": "'false' != test",
478+ "contexts": { "test": {} },
479+ "result": { "kind": "Boolean", "value": true }
480+ },
481+ {
482+ "expr": "'0' != test",
483+ "contexts": { "test": {} },
484+ "result": { "kind": "Boolean", "value": true }
485+ },
486+ {
487+ "expr": "'1' != test",
488+ "contexts": { "test": {} },
489+ "result": { "kind": "Boolean", "value": true }
490+ },
491+ {
492+ "expr": "'null' != test",
493+ "contexts": { "test": {} },
494+ "result": { "kind": "Boolean", "value": true }
495+ },
496+ {
497+ "expr": "'Object' != test",
498+ "contexts": { "test": {} },
499+ "result": { "kind": "Boolean", "value": true }
500+ }
501+ ],
502+
503+ "coerce_string_array": [
504+ {
505+ "expr": "'' != test",
506+ "contexts": { "test": [] },
507+ "result": { "kind": "Boolean", "value": true }
508+ },
509+ {
510+ "expr": "'false' != test",
511+ "contexts": { "test": [] },
512+ "result": { "kind": "Boolean", "value": true }
513+ },
514+ {
515+ "expr": "'0' != test",
516+ "contexts": { "test": [] },
517+ "result": { "kind": "Boolean", "value": true }
518+ },
519+ {
520+ "expr": "'0' != test",
521+ "contexts": { "test": [] },
522+ "result": { "kind": "Boolean", "value": true }
523+ },
524+ {
525+ "expr": "'null' != test",
526+ "contexts": { "test": [] },
527+ "result": { "kind": "Boolean", "value": true }
528+ },
529+ {
530+ "expr": "'Array' != test",
531+ "contexts": { "test": [] },
532+ "result": { "kind": "Boolean", "value": true }
533+ }
534+ ],
535+
536+ "coerce_null_bool": [
537+ {
538+ "expr": "null != false",
539+ "result": { "kind": "Boolean", "value": false }
540+ },
541+ {
542+ "expr": "null != true",
543+ "result": { "kind": "Boolean", "value": true }
544+ }
545+ ],
546+
547+ "coerce_null_number": [
548+ {
549+ "expr": "null != 0",
550+ "result": { "kind": "Boolean", "value": false }
551+ },
552+ {
553+ "expr": "null != 1",
554+ "result": { "kind": "Boolean", "value": true }
555+ }
556+ ],
557+
558+ "coerce_null_string": [
559+ {
560+ "expr": "null != ''",
561+ "result": { "kind": "Boolean", "value": false }
562+ },
563+ {
564+ "expr": "null != ' '",
565+ "result": { "kind": "Boolean", "value": false }
566+ },
567+ {
568+ "expr": "null != '0'",
569+ "result": { "kind": "Boolean", "value": false }
570+ },
571+ {
572+ "expr": "null != '1'",
573+ "result": { "kind": "Boolean", "value": true }
574+ },
575+ {
576+ "expr": "null != 'false'",
577+ "result": { "kind": "Boolean", "value": true }
578+ },
579+ {
580+ "expr": "null != 'null'",
581+ "result": { "kind": "Boolean", "value": true }
582+ }
583+ ],
584+
585+ "coerce_null_object-array": [
586+ {
587+ "expr": "null != test",
588+ "contexts": { "test": {} },
589+ "result": { "kind": "Boolean", "value": true }
590+ },
591+ {
592+ "expr": "null != test",
593+ "contexts": { "test": [] },
594+ "result": { "kind": "Boolean", "value": true }
595+ }
596+ ]
597+}
A expr/testdata/languageservices/op_not.json +28 -0
@@ -0,0 +1,28 @@
1+{
2+ "not": [
3+ { "expr": "!!true", "result": { "kind": "Boolean", "value": true } },
4+ { "expr": "!!false", "result": { "kind": "Boolean", "value": false } },
5+ { "expr": "!!1", "result": { "kind": "Boolean", "value": true } },
6+ { "expr": "!!.5", "result": { "kind": "Boolean", "value": true } },
7+ { "expr": "!!0.5", "result": { "kind": "Boolean", "value": true } },
8+ { "expr": "!!2", "result": { "kind": "Boolean", "value": true } },
9+ { "expr": "!!-1", "result": { "kind": "Boolean", "value": true } },
10+ { "expr": "!!-.5", "result": { "kind": "Boolean", "value": true } },
11+ { "expr": "!!-2", "result": { "kind": "Boolean", "value": true } },
12+ { "expr": "!!-Infinity", "result": { "kind": "Boolean", "value": true } },
13+ { "expr": "!!Infinity", "result": { "kind": "Boolean", "value": true } },
14+ { "expr": "!!NaN", "result": { "kind": "Boolean", "value": false } },
15+ { "expr": "!!0", "result": { "kind": "Boolean", "value": false } },
16+ { "expr": "!!0.0", "result": { "kind": "Boolean", "value": false } },
17+ { "expr": "!!-0", "result": { "kind": "Boolean", "value": false } },
18+ { "expr": "!!-0.0", "result": { "kind": "Boolean", "value": false } },
19+ { "expr": "!!'a'", "result": { "kind": "Boolean", "value": true } },
20+ { "expr": "!!'false'", "result": { "kind": "Boolean", "value": true } },
21+ { "expr": "!!'0'", "result": { "kind": "Boolean", "value": true } },
22+ { "expr": "!!' '", "result": { "kind": "Boolean", "value": true } },
23+ { "expr": "!!''", "result": { "kind": "Boolean", "value": false } },
24+ { "expr": "!!fromJson('[]')", "result": { "kind": "Boolean", "value": true } },
25+ { "expr": "!!fromJson('{}')", "result": { "kind": "Boolean", "value": true } },
26+ { "expr": "!!null", "result": { "kind": "Boolean", "value": false } }
27+ ]
28+}
A expr/testdata/languageservices/op_or.json +31 -0
@@ -0,0 +1,31 @@
1+{
2+ "or": [
3+ {
4+ "expr": "true || true || true",
5+ "result": { "kind": "Boolean", "value": true }
6+ },
7+ { "expr": "true || true", "result": { "kind": "Boolean", "value": true } },
8+ {
9+ "expr": "true || true || false",
10+ "result": { "kind": "Boolean", "value": true }
11+ },
12+ { "expr": "true || false", "result": { "kind": "Boolean", "value": true } },
13+ { "expr": "false || true", "result": { "kind": "Boolean", "value": true } },
14+ {
15+ "expr": "false || false",
16+ "result": { "kind": "Boolean", "value": false }
17+ },
18+ {
19+ "expr": "0 || 0 || 2 || 3",
20+ "result": { "kind": "Number", "value": 2.0 }
21+ },
22+ { "expr": "false || 0", "result": { "kind": "Number", "value": 0.0 } },
23+ {
24+ "expr": "false || '' || 'a' || 'b'",
25+ "result": { "kind": "String", "value": "a" }
26+ },
27+ { "expr": "false || ''", "result": { "kind": "String", "value": "" } },
28+ { "expr": "null || true", "result": { "kind": "Boolean", "value": true } },
29+ { "expr": "false || null", "result": { "kind": "Null", "value": null } }
30+ ]
31+}
A expr/testdata/languageservices/operators_case_insensitive.json +376 -0
@@ -0,0 +1,376 @@
1+{
2+ "lower-vs-upper": [
3+ {
4+ "expr": "'abcdefghijklmnopqrstuvwxyz' == 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'",
5+ "result": { "kind": "Boolean", "value": true }
6+ },
7+ {
8+ "expr": "'abcdefghijklmnopqrstuvwxyz' != 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'",
9+ "result": { "kind": "Boolean", "value": false }
10+ },
11+ {
12+ "expr": "'abcdefghijklmnopqrstuvwxyz' < 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'",
13+ "result": { "kind": "Boolean", "value": false }
14+ },
15+ {
16+ "expr": "'abcdefghijklmnopqrstuvwxyz' <= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'",
17+ "result": { "kind": "Boolean", "value": true }
18+ },
19+ {
20+ "expr": "'abcdefghijklmnopqrstuvwxyz' > 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'",
21+ "result": { "kind": "Boolean", "value": false }
22+ },
23+ {
24+ "expr": "'abcdefghijklmnopqrstuvwxyz' >= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'",
25+ "result": { "kind": "Boolean", "value": true }
26+ }
27+ ],
28+
29+ "upper-vs-lower": [
30+ {
31+ "expr": "'ABCDEFGHIJKLMNOPQRSTUVWXYZ' == 'abcdefghijklmnopqrstuvwxyz'",
32+ "result": { "kind": "Boolean", "value": true }
33+ },
34+ {
35+ "expr": "'ABCDEFGHIJKLMNOPQRSTUVWXYZ' != 'abcdefghijklmnopqrstuvwxyz'",
36+ "result": { "kind": "Boolean", "value": false }
37+ },
38+ {
39+ "expr": "'ABCDEFGHIJKLMNOPQRSTUVWXYZ' < 'abcdefghijklmnopqrstuvwxyz'",
40+ "result": { "kind": "Boolean", "value": false }
41+ },
42+ {
43+ "expr": "'ABCDEFGHIJKLMNOPQRSTUVWXYZ' <= 'abcdefghijklmnopqrstuvwxyz'",
44+ "result": { "kind": "Boolean", "value": true }
45+ },
46+ {
47+ "expr": "'ABCDEFGHIJKLMNOPQRSTUVWXYZ' > 'abcdefghijklmnopqrstuvwxyz'",
48+ "result": { "kind": "Boolean", "value": false }
49+ },
50+ {
51+ "expr": "'ABCDEFGHIJKLMNOPQRSTUVWXYZ' >= 'abcdefghijklmnopqrstuvwxyz'",
52+ "result": { "kind": "Boolean", "value": true }
53+ }
54+ ],
55+
56+ "a-z-equivalent-to-A-Z-wrt-chars-between-Z-and-a": [
57+ {
58+ "expr": "'A' < '['",
59+ "result": { "kind": "Boolean", "value": true }
60+ },
61+ {
62+ "expr": "'A' <= '['",
63+ "result": { "kind": "Boolean", "value": true }
64+ },
65+ {
66+ "expr": "'A' > '['",
67+ "result": { "kind": "Boolean", "value": false }
68+ },
69+ {
70+ "expr": "'A' >= '['",
71+ "result": { "kind": "Boolean", "value": false }
72+ },
73+ {
74+ "expr": "'a' < '['",
75+ "result": { "kind": "Boolean", "value": true }
76+ },
77+ {
78+ "expr": "'a' <= '['",
79+ "result": { "kind": "Boolean", "value": true }
80+ },
81+ {
82+ "expr": "'a' > '['",
83+ "result": { "kind": "Boolean", "value": false }
84+ },
85+ {
86+ "expr": "'a' >= '['",
87+ "result": { "kind": "Boolean", "value": false }
88+ }
89+ ],
90+
91+ "case-insensitive-ς-(final-lowercase-sigma)-Σ-(capital-sigma)-σ-(non-final-sigma)": [
92+ {
93+ "expr": "'ς' == 'Σ'",
94+ "result": { "kind": "Boolean", "value": true }
95+ },
96+ {
97+ "expr": "'ς' != 'Σ'",
98+ "result": { "kind": "Boolean", "value": false }
99+ },
100+ {
101+ "expr": "'ς' < 'Σ'",
102+ "result": { "kind": "Boolean", "value": false }
103+ },
104+ {
105+ "expr": "'ς' <= 'Σ'",
106+ "result": { "kind": "Boolean", "value": true }
107+ },
108+ {
109+ "expr": "'ς' > 'Σ'",
110+ "result": { "kind": "Boolean", "value": false }
111+ },
112+ {
113+ "expr": "'ς' >= 'Σ'",
114+ "result": { "kind": "Boolean", "value": true }
115+ },
116+ {
117+ "expr": "'ς' == 'σ'",
118+ "result": { "kind": "Boolean", "value": true }
119+ },
120+ {
121+ "expr": "'ς' != 'σ'",
122+ "result": { "kind": "Boolean", "value": false }
123+ },
124+ {
125+ "expr": "'ς' < 'σ'",
126+ "result": { "kind": "Boolean", "value": false }
127+ },
128+ {
129+ "expr": "'ς' <= 'σ'",
130+ "result": { "kind": "Boolean", "value": true }
131+ },
132+ {
133+ "expr": "'ς' > 'σ'",
134+ "result": { "kind": "Boolean", "value": false }
135+ },
136+ {
137+ "expr": "'ς' >= 'σ'",
138+ "result": { "kind": "Boolean", "value": true }
139+ },
140+ {
141+ "expr": "'Σ' == 'σ'",
142+ "result": { "kind": "Boolean", "value": true }
143+ },
144+ {
145+ "expr": "'Σ' != 'σ'",
146+ "result": { "kind": "Boolean", "value": false }
147+ },
148+ {
149+ "expr": "'Σ' < 'σ'",
150+ "result": { "kind": "Boolean", "value": false }
151+ },
152+ {
153+ "expr": "'Σ' <= 'σ'",
154+ "result": { "kind": "Boolean", "value": true }
155+ },
156+ {
157+ "expr": "'Σ' > 'σ'",
158+ "result": { "kind": "Boolean", "value": false }
159+ },
160+ {
161+ "expr": "'Σ' >= 'σ'",
162+ "result": { "kind": "Boolean", "value": true }
163+ }
164+ ],
165+
166+ "case-insensitive-ü-Ü": [
167+ {
168+ "expr": "'ü' == 'Ü'",
169+ "result": { "kind": "Boolean", "value": true }
170+ },
171+ {
172+ "expr": "'ü' != 'Ü'",
173+ "result": { "kind": "Boolean", "value": false }
174+ },
175+ {
176+ "expr": "'ü' < 'Ü'",
177+ "result": { "kind": "Boolean", "value": false }
178+ },
179+ {
180+ "expr": "'ü' <= 'Ü'",
181+ "result": { "kind": "Boolean", "value": true }
182+ },
183+ {
184+ "expr": "'ü' > 'Ü'",
185+ "result": { "kind": "Boolean", "value": false }
186+ },
187+ {
188+ "expr": "'ü' >= 'Ü'",
189+ "result": { "kind": "Boolean", "value": true }
190+ },
191+ {
192+ "expr": "'Ü' == 'ü'",
193+ "result": { "kind": "Boolean", "value": true }
194+ },
195+ {
196+ "expr": "'Ü' != 'ü'",
197+ "result": { "kind": "Boolean", "value": false }
198+ },
199+ {
200+ "expr": "'Ü' < 'ü'",
201+ "result": { "kind": "Boolean", "value": false }
202+ },
203+ {
204+ "expr": "'Ü' <= 'ü'",
205+ "result": { "kind": "Boolean", "value": true }
206+ },
207+ {
208+ "expr": "'Ü' > 'ü'",
209+ "result": { "kind": "Boolean", "value": false }
210+ },
211+ {
212+ "expr": "'Ü' >= 'ü'",
213+ "result": { "kind": "Boolean", "value": true }
214+ }
215+ ],
216+
217+ "case-insensitive-ç-Ç": [
218+ {
219+ "expr": "'ç' == 'Ç'",
220+ "result": { "kind": "Boolean", "value": true }
221+ },
222+ {
223+ "expr": "'ç' != 'Ç'",
224+ "result": { "kind": "Boolean", "value": false }
225+ },
226+ {
227+ "expr": "'ç' < 'Ç'",
228+ "result": { "kind": "Boolean", "value": false }
229+ },
230+ {
231+ "expr": "'ç' <= 'Ç'",
232+ "result": { "kind": "Boolean", "value": true }
233+ },
234+ {
235+ "expr": "'ç' > 'Ç'",
236+ "result": { "kind": "Boolean", "value": false }
237+ },
238+ {
239+ "expr": "'ç' >= 'Ç'",
240+ "result": { "kind": "Boolean", "value": true }
241+ },
242+ {
243+ "expr": "'Ç' == 'ç'",
244+ "result": { "kind": "Boolean", "value": true }
245+ },
246+ {
247+ "expr": "'Ç' != 'ç'",
248+ "result": { "kind": "Boolean", "value": false }
249+ },
250+ {
251+ "expr": "'Ç' < 'ç'",
252+ "result": { "kind": "Boolean", "value": false }
253+ },
254+ {
255+ "expr": "'Ç' <= 'ç'",
256+ "result": { "kind": "Boolean", "value": true }
257+ },
258+ {
259+ "expr": "'Ç' > 'ç'",
260+ "result": { "kind": "Boolean", "value": false }
261+ },
262+ {
263+ "expr": "'Ç' >= 'ç'",
264+ "result": { "kind": "Boolean", "value": true }
265+ }
266+ ],
267+
268+ "case-sensitive-i-İ": [
269+ {
270+ "expr": "'i' == 'İ'",
271+ "result": { "kind": "Boolean", "value": false }
272+ },
273+ {
274+ "expr": "'i' != 'İ'",
275+ "result": { "kind": "Boolean", "value": true }
276+ },
277+ {
278+ "expr": "'i' < 'İ'",
279+ "result": { "kind": "Boolean", "value": true }
280+ },
281+ {
282+ "expr": "'i' <= 'İ'",
283+ "result": { "kind": "Boolean", "value": true }
284+ },
285+ {
286+ "expr": "'i' > 'İ'",
287+ "result": { "kind": "Boolean", "value": false }
288+ },
289+ {
290+ "expr": "'i' >= 'İ'",
291+ "result": { "kind": "Boolean", "value": false }
292+ },
293+ {
294+ "expr": "'İ' == 'i'",
295+ "result": { "kind": "Boolean", "value": false }
296+ },
297+ {
298+ "expr": "'İ' != 'i'",
299+ "result": { "kind": "Boolean", "value": true }
300+ },
301+ {
302+ "expr": "'İ' < 'i'",
303+ "result": { "kind": "Boolean", "value": false }
304+ },
305+ {
306+ "expr": "'İ' <= 'i'",
307+ "result": { "kind": "Boolean", "value": false }
308+ },
309+ {
310+ "expr": "'İ' > 'i'",
311+ "result": { "kind": "Boolean", "value": true }
312+ },
313+ {
314+ "expr": "'İ' >= 'i'",
315+ "result": { "kind": "Boolean", "value": true }
316+ }
317+ ],
318+
319+ "case-sensitive-ı-I": [
320+ {
321+ "expr": "'ı' == 'I'",
322+ "result": { "kind": "Boolean", "value": false }
323+ },
324+ {
325+ "expr": "'ı' != 'I'",
326+ "result": { "kind": "Boolean", "value": true }
327+ },
328+ {
329+ "expr": "'ı' < 'I'",
330+ "result": { "kind": "Boolean", "value": false }
331+ },
332+ {
333+ "expr": "'ı' <= 'I'",
334+ "result": { "kind": "Boolean", "value": false }
335+ },
336+ {
337+ "expr": "'ı' > 'I'",
338+ "result": { "kind": "Boolean", "value": true }
339+ },
340+ {
341+ "expr": "'ı' >= 'I'",
342+ "result": { "kind": "Boolean", "value": true }
343+ },
344+ {
345+ "expr": "'I' == 'ı'",
346+ "result": { "kind": "Boolean", "value": false }
347+ },
348+ {
349+ "expr": "'I' != 'ı'",
350+ "result": { "kind": "Boolean", "value": true }
351+ },
352+ {
353+ "expr": "'I' < 'ı'",
354+ "result": { "kind": "Boolean", "value": true }
355+ },
356+ {
357+ "expr": "'I' <= 'ı'",
358+ "result": { "kind": "Boolean", "value": true }
359+ },
360+ {
361+ "expr": "'I' > 'ı'",
362+ "result": { "kind": "Boolean", "value": false }
363+ },
364+ {
365+ "expr": "'I' >= 'ı'",
366+ "result": { "kind": "Boolean", "value": false }
367+ }
368+ ],
369+
370+ "cyrillic-letters": [
371+ {
372+ "expr": "'АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЬЭЮЯ' == 'абвгдежзийклмнопрстуфхцчшщьэюя'",
373+ "result": { "kind": "Boolean", "value": true }
374+ }
375+ ]
376+}
A expr/testdata/languageservices/operators_precedence.json +171 -0
@@ -0,0 +1,171 @@
1+{
2+ "operator_precedence_._and_._evaluate_left_to_right": [
3+ {
4+ "expr": "foo.bar.baz",
5+ "contexts": { "foo": { "bar": { "baz": 2 } } },
6+ "result": { "kind": "Number", "value": 2.0 }
7+ }
8+ ],
9+ "operator_precedence_._is_higher_than_!": [
10+ {
11+ "expr": "!foo.bar",
12+ "contexts": { "foo": { "bar": true } },
13+ "result": { "kind": "Boolean", "value": false }
14+ },
15+ {
16+ "expr": "(!foo).bar",
17+ "contexts": { "foo": { "bar": true } },
18+ "result": { "kind": "Null", "value": null }
19+ }
20+ ],
21+ "operator_precedence_._is_higher_than_>": [
22+ {
23+ "expr": "3 > foo.bar",
24+ "contexts": { "foo": { "bar": 2 } },
25+ "result": { "kind": "Boolean", "value": true }
26+ },
27+ {
28+ "expr": "foo.bar > 2",
29+ "contexts": { "foo": { "bar": 3 } },
30+ "result": { "kind": "Boolean", "value": true }
31+ }
32+ ],
33+ "operator_precedence_[]_is_higher_than_>": [
34+ {
35+ "expr": "3 > foo['bar']",
36+ "contexts": { "foo": { "bar": 2 } },
37+ "result": { "kind": "Boolean", "value": true }
38+ },
39+ {
40+ "expr": "foo['bar'] > 2",
41+ "contexts": { "foo": { "bar": 3 } },
42+ "result": { "kind": "Boolean", "value": true }
43+ }
44+ ],
45+ "operator_precedence_!_is_higher_than_<": [
46+ {
47+ "expr": "!2 < 3",
48+ "result": { "kind": "Boolean", "value": true }
49+ },
50+ {
51+ "expr": "!(2 < 3)",
52+ "result": { "kind": "Boolean", "value": false }
53+ }
54+ ],
55+ "operator_precedence_<_and_<_evaluate_left_to_right": [
56+ {
57+ "expr": "3 < 2 < 1",
58+ "result": { "kind": "Boolean", "value": true }
59+ },
60+ {
61+ "expr": "3 < (2 < 1)",
62+ "result": { "kind": "Boolean", "value": false }
63+ }
64+ ],
65+ "operator_precedence_<_and_<=_evaluate_left_to_right": [
66+ {
67+ "expr": "3 < 2 <= 1",
68+ "result": { "kind": "Boolean", "value": true }
69+ },
70+ {
71+ "expr": "3 < (2 <= 1)",
72+ "result": { "kind": "Boolean", "value": false }
73+ }
74+ ],
75+ "operator_precedence_<=_and_<_evaluate_left_to_right": [
76+ {
77+ "expr": "3 <= 2 < 1",
78+ "result": { "kind": "Boolean", "value": true }
79+ },
80+ {
81+ "expr": "3 <= (2 < 1)",
82+ "result": { "kind": "Boolean", "value": false }
83+ }
84+ ],
85+ "operator_precedence_>_and_<_evaluate_left_to_right": [
86+ {
87+ "expr": "0 > 0 < 1",
88+ "result": { "kind": "Boolean", "value": true }
89+ },
90+ {
91+ "expr": "0 > (0 < 1)",
92+ "result": { "kind": "Boolean", "value": false }
93+ }
94+ ],
95+ "operator_precedence_>_and_>_evaluate_left_to_right": [
96+ {
97+ "expr": "2 > 2 > 0",
98+ "result": { "kind": "Boolean", "value": false }
99+ },
100+ {
101+ "expr": "2 > (2 > 0)",
102+ "result": { "kind": "Boolean", "value": true }
103+ }
104+ ],
105+ "operator_precedence_<=_is_higher_than_==": [
106+ {
107+ "expr": "2 <= 3 == true",
108+ "result": { "kind": "Boolean", "value": true }
109+ },
110+ {
111+ "expr": "2 <= (3 == true)",
112+ "result": { "kind": "Boolean", "value": false }
113+ }
114+ ],
115+ "operator_precedence_==_and_==_evaluate_left_to_right": [
116+ {
117+ "expr": "2 == 2 == 1",
118+ "result": { "kind": "Boolean", "value": true }
119+ },
120+ {
121+ "expr": "2 == (2 == 1)",
122+ "result": { "kind": "Boolean", "value": false }
123+ }
124+ ],
125+ "operator_precedence_==_and_!=_evaluate_left_to_right": [
126+ {
127+ "expr": "2 == 2 != 0",
128+ "result": { "kind": "Boolean", "value": true }
129+ },
130+ {
131+ "expr": "2 == (2 != 0)",
132+ "result": { "kind": "Boolean", "value": false }
133+ }
134+ ],
135+ "operator_precedence_==_is_higher_than_&&": [
136+ {
137+ "expr": "1 == 1 && 2",
138+ "result": { "kind": "Number", "value": 2.0 }
139+ },
140+ {
141+ "expr": "1 == (1 && 2)",
142+ "result": { "kind": "Boolean", "value": false }
143+ },
144+ {
145+ "expr": "'a' == 'a' && 'b'",
146+ "result": { "kind": "String", "value": "b" }
147+ },
148+ {
149+ "expr": "'a' == ('a' && 'b')",
150+ "result": { "kind": "Boolean", "value": false }
151+ }
152+ ],
153+ "operator_precedence_&&_is_higher_than_||": [
154+ {
155+ "expr": "false && 0 || null",
156+ "result": { "kind": "Null", "value": null }
157+ },
158+ {
159+ "expr": "false && (0 || null)",
160+ "result": { "kind": "Boolean", "value": false }
161+ },
162+ {
163+ "expr": "1 || 2 && 3",
164+ "result": { "kind": "Number", "value": 1.0 }
165+ },
166+ {
167+ "expr": "(1 || 2) && 3",
168+ "result": { "kind": "Number", "value": 3.0 }
169+ }
170+ ]
171+}
A expr/testdata/languageservices/startsWith.json +143 -0
@@ -0,0 +1,143 @@
1+{
2+ "basics": [
3+ {
4+ "expr": "startsWith('abcdef', 'abc')",
5+ "result": { "kind": "Boolean", "value": true }
6+ },
7+ {
8+ "expr": "startsWith('abcdef', 'bc')",
9+ "result": { "kind": "Boolean", "value": false }
10+ },
11+ {
12+ "expr": "startsWith('abcdef', '')",
13+ "result": { "kind": "Boolean", "value": true }
14+ },
15+ {
16+ "expr": "startsWith('1234', 12)",
17+ "result": { "kind": "Boolean", "value": true }
18+ },
19+ {
20+ "expr": "startsWith('true', true)",
21+ "result": { "kind": "Boolean", "value": true }
22+ },
23+ {
24+ "expr": "startsWith('false', false)",
25+ "result": { "kind": "Boolean", "value": true }
26+ },
27+ {
28+ "expr": "startsWith('asdf', null)",
29+ "result": { "kind": "Boolean", "value": true }
30+ },
31+ {
32+ "expr": "startsWith('1234', 23)",
33+ "result": { "kind": "Boolean", "value": false }
34+ },
35+ {
36+ "expr": "startsWith('true', false)",
37+ "result": { "kind": "Boolean", "value": false }
38+ },
39+ {
40+ "expr": "startsWith('true', false, true)",
41+ "err": {
42+ "kind": "parsing",
43+ "value": "Too many parameters supplied: "
44+ }
45+ },
46+ {
47+ "expr": "startsWith('true')",
48+ "err": {
49+ "kind": "parsing",
50+ "value": "Too few parameters supplied: "
51+ }
52+ }
53+ ],
54+
55+ "case-insensitive-a-thru-z": [
56+ {
57+ "expr": "startsWith('ABCDEFGHIJKLMNOPQRSTUVWXYZ_asdf', 'abcdefghijklmnopqrstuvwxyz')",
58+ "result": { "kind": "Boolean", "value": true }
59+ },
60+ {
61+ "expr": "startsWith('abcdefghijklmnopqrstuvwxyz_asdf', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')",
62+ "result": { "kind": "Boolean", "value": true }
63+ }
64+ ],
65+
66+ "case-insensitive-ς-(final-lowercase-sigma)-Σ-(capital-sigma)-σ-(non-final-sigma)": [
67+ {
68+ "expr": "startsWith('ς_asdf', 'Σ')",
69+ "result": { "kind": "Boolean", "value": true }
70+ },
71+ {
72+ "expr": "startsWith('ς_asdf', 'σ')",
73+ "result": { "kind": "Boolean", "value": true }
74+ },
75+ {
76+ "expr": "startsWith('Σ_asdf', 'ς')",
77+ "result": { "kind": "Boolean", "value": true }
78+ },
79+ {
80+ "expr": "startsWith('Σ_asdf', 'σ')",
81+ "result": { "kind": "Boolean", "value": true }
82+ },
83+ {
84+ "expr": "startsWith('σ_asdf', 'ς')",
85+ "result": { "kind": "Boolean", "value": true }
86+ },
87+ {
88+ "expr": "startsWith('σ_asdf', 'Σ')",
89+ "result": { "kind": "Boolean", "value": true }
90+ }
91+ ],
92+
93+ "case-insensitive-ü-Ü": [
94+ {
95+ "expr": "startsWith('ü_asdf', 'Ü')",
96+ "result": { "kind": "Boolean", "value": true }
97+ },
98+ {
99+ "expr": "startsWith('Ü_asdf', 'ü')",
100+ "result": { "kind": "Boolean", "value": true }
101+ }
102+ ],
103+
104+ "case-insensitive-ç-Ç": [
105+ {
106+ "expr": "startsWith('ç_asdf', 'Ç')",
107+ "result": { "kind": "Boolean", "value": true }
108+ },
109+ {
110+ "expr": "startsWith('Ç_asdf', 'ç')",
111+ "result": { "kind": "Boolean", "value": true }
112+ }
113+ ],
114+
115+ "case-sensitive-i-İ": [
116+ {
117+ "expr": "startsWith('i_asdf', 'İ')",
118+ "result": { "kind": "Boolean", "value": false }
119+ },
120+ {
121+ "expr": "startsWith('İ_asdf', 'i')",
122+ "result": { "kind": "Boolean", "value": false }
123+ }
124+ ],
125+
126+ "case-sensitive-ı-I": [
127+ {
128+ "expr": "startsWith('ı_asdf', 'I')",
129+ "result": { "kind": "Boolean", "value": false }
130+ },
131+ {
132+ "expr": "startsWith('I_asdf', 'ı')",
133+ "result": { "kind": "Boolean", "value": false }
134+ }
135+ ],
136+
137+ "cyrillic-letters": [
138+ {
139+ "expr": "startsWith('АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЬЭЮЯ_asdf', 'абвгдежзийклмнопрстуфхцчшщьэюя')",
140+ "result": { "kind": "Boolean", "value": true }
141+ }
142+ ]
143+}
A expr/testdata/languageservices/syntax-errors.json +605 -0
@@ -0,0 +1,605 @@
1+{
2+ "parsing-errors": [
3+ {
4+ "expr": "1 <",
5+ "err": {
6+ "kind": "parsing",
7+ "value": "Unexpected end of expression: '<'. Located at position 3 within expression: 1 <"
8+ }
9+ },
10+ {
11+ "expr": "1 < )",
12+ "err": {
13+ "kind": "parsing",
14+ "value": "Unexpected symbol: ')'. Located at position 5 within expression: 1 < )"
15+ }
16+ },
17+ {
18+ "expr": "> 1",
19+ "err": {
20+ "kind": "parsing",
21+ "value": "Unexpected symbol: '>'. Located at position 1 within expression: > 1"
22+ }
23+ },
24+ {
25+ "expr": "github.()",
26+ "contexts": { "github": { "sha": "abc123" } },
27+ "err": {
28+ "kind": "parsing",
29+ "value": "Unexpected symbol: '('. Located at position 8 within expression: github.()"
30+ }
31+ },
32+ {
33+ "expr": "endswith(1, 2 a)",
34+ "err": {
35+ "kind": "parsing",
36+ "value": "Unexpected symbol: 'a'. Located at position 15 within expression: endswith(1, 2 a)"
37+ }
38+ },
39+ {
40+ "expr": "(1,",
41+ "err": {
42+ "kind": "parsing",
43+ "value": "Unexpected symbol: ','. Located at position 3 within expression: (1,"
44+ }
45+ },
46+ {
47+ "expr": "1 2",
48+ "err": {
49+ "kind": "parsing",
50+ "value": "Unexpected symbol: '2'. Located at position 3 within expression: 1 2"
51+ }
52+ },
53+ {
54+ "expr": "(1)2",
55+ "err": {
56+ "kind": "parsing",
57+ "value": "Unexpected symbol: '2'. Located at position 4 within expression: (1)2"
58+ }
59+ },
60+ {
61+ "expr": "tojson(1)2",
62+ "err": {
63+ "kind": "parsing",
64+ "value": "Unexpected symbol: '2'. Located at position 10 within expression: tojson(1)2"
65+ }
66+ },
67+ {
68+ "expr": "foo 2",
69+ "contexts": { "foo": "bar" },
70+ "err": {
71+ "kind": "parsing",
72+ "value": "Unexpected symbol: '2'. Located at position 5 within expression: foo 2"
73+ }
74+ },
75+ {
76+ "expr": "foo.bar 2",
77+ "contexts": { "foo": "bar" },
78+ "err": {
79+ "kind": "parsing",
80+ "value": "Unexpected symbol: '2'. Located at position 9 within expression: foo.bar 2"
81+ }
82+ },
83+ {
84+ "expr": "foo['bar']2",
85+ "contexts": { "foo": "bar" },
86+ "err": {
87+ "kind": "parsing",
88+ "value": "Unexpected symbol: '2'. Located at position 11 within expression: foo['bar']2"
89+ }
90+ },
91+ {
92+ "expr": "nonExistentFunction()",
93+ "err": {
94+ "kind": "parsing",
95+ "value": "Unrecognized function: 'nonExistentFunction'. Located at position 1"
96+ }
97+ },
98+ {
99+ "expr": "false && nonExistentFunction()",
100+ "err": {
101+ "kind": "parsing",
102+ "value": "Unrecognized function: 'nonExistentFunction'. Located at position 1"
103+ }
104+ },
105+ {
106+ "expr": "1 = < 2",
107+ "err": {
108+ "kind": "lexing",
109+ "value": "Unexpected symbol: '='. Located at position 3 within expression: 1 = < 2"
110+ }
111+ },
112+ {
113+ "expr": "1 & < 2",
114+ "err": {
115+ "kind": "lexing",
116+ "value": "Unexpected symbol: '&'. Located at position 3 within expression: 1 & < 2"
117+ }
118+ },
119+ {
120+ "expr": "1 | < 2",
121+ "err": {
122+ "kind": "lexing",
123+ "value": "Unexpected symbol: '|'. Located at position 3 within expression: 1 | < 2"
124+ }
125+ },
126+ {
127+ "expr": "1 =2 =3",
128+ "err": {
129+ "kind": "lexing",
130+ "value": "Unexpected symbol: '=2'. Located at position 3 within expression: 1 =2 =3"
131+ }
132+ },
133+ {
134+ "expr": "1 &2 &3",
135+ "err": {
136+ "kind": "lexing",
137+ "value": "Unexpected symbol: '&2'. Located at position 3 within expression: 1 &2 &3"
138+ }
139+ },
140+ {
141+ "expr": "1 |2 |3",
142+ "err": {
143+ "kind": "lexing",
144+ "value": "Unexpected symbol: '|2'. Located at position 3 within expression: 1 |2 |3"
145+ }
146+ },
147+ {
148+ "expr": "1 @abc 2",
149+ "err": {
150+ "kind": "lexing",
151+ "value": "Unexpected symbol: '@abc'. Located at position 3 within expression: 1 @abc 2"
152+ }
153+ },
154+ {
155+ "expr": "'foo",
156+ "err": {
157+ "kind": "lexing",
158+ "value": "Unexpected symbol: ''foo'. Located at position 1 within expression: 'foo"
159+ }
160+ },
161+ {
162+ "expr": "fromjson(a,b ",
163+ "err": {
164+ "kind": "parsing",
165+ "value": "Unrecognized named-value: 'a'. Located at position 10 within expression: fromjson(a,b "
166+ }
167+ },
168+ {
169+ "expr": " true ||( false && false",
170+ "err": {
171+ "kind": "parsing",
172+ "value": "Unexpected end of expression: 'false'. Located at position 20 within expression: true ||( false && false"
173+ }
174+ },
175+ {
176+ "expr": "😊 Emoji!! (unicode)",
177+ "err": {
178+ "kind": "lexing",
179+ "value": "Unexpected symbol: '😊'. Located at position 1 within expression: 😊 Emoji!! (unicode)"
180+ }
181+ },
182+ {
183+ "expr": "github.event_name == 'push'\n && !contains(env.COMMIT_MESSAGES)",
184+ "contexts": { "github": { "event_name": "push" }},
185+ "err": {
186+ "kind": "parsing",
187+ "value": "Unrecognized named-value: 'env'. Located at position 43 within expression: github.event_name == 'push'\n && !contains(env.COMMIT_MESSAGES)"
188+ },
189+ "options": {
190+ "skip": ["typescript"]
191+ }
192+ },
193+ {
194+ "expr": "github.event_name == 'push' \n&& true\n&& !contains(env.COMMIT_MESSAGES)",
195+ "contexts": { "github": { "event_name": "push" }},
196+ "err": {
197+ "kind": "parsing",
198+ "value": "Unrecognized named-value: 'env'. Located at position 51 within expression: github.event_name == 'push' \n&& true\n&& !contains(env.COMMIT_MESSAGES)"
199+ },
200+ "options": {
201+ "skip": ["typescript"]
202+ }
203+ },
204+ {
205+ "expr": "github.event_name == 'push' \n&& true\n&& true\n&& !contains(env.COMMIT_MESSAGES)",
206+ "contexts": { "github": { "event_name": "push" }},
207+ "err": {
208+ "kind": "parsing",
209+ "value": "Unrecognized named-value: 'env'. Located at position 59 within expression: github.event_name == 'push' \n&& true\n&& true\n&& !contains(env.COMMIT_MESSAGES)"
210+ },
211+ "options": {
212+ "skip": ["typescript"]
213+ }
214+ },
215+ {
216+ "expr": "github.event_name == 'push' \n&& true\n&& true\n&& true\n&& !contains(env.COMMIT_MESSAGES)",
217+ "contexts": { "github": { "event_name": "push" }},
218+ "err": {
219+ "kind": "parsing",
220+ "value": "Unrecognized named-value: 'env'. Located at position 67 within expression: github.event_name == 'push' \n&& true\n&& true\n&& true\n&& !contains(env.COMMIT_MESSAGES)"
221+ },
222+ "options": {
223+ "skip": ["typescript"]
224+ }
225+ },
226+ {
227+ "expr": "1 && ..github/workflow.md",
228+ "err": {
229+ "kind": "lexing",
230+ "value": "Unexpected symbol: '..github/workflow.md'. Located at position 6 within expression: 1 && ..github/workflow.md"
231+ }
232+ },
233+ {
234+ "expr": "..github/workflow.md",
235+ "err": {
236+ "kind": "lexing",
237+ "value": "Unexpected symbol: '..github/workflow.md'. Located at position 1 within expression: ..github/workflow.md"
238+ }
239+ },
240+ {
241+ "expr": ".github/workflow.md",
242+ "err": {
243+ "kind": "lexing",
244+ "value": "Unexpected symbol: '.github/workflow.md'. Located at position 1 within expression: .github/workflow.md"
245+ }
246+ },
247+ {
248+ "expr": ".github/workflow",
249+ "err": {
250+ "kind": "lexing",
251+ "value": "Unexpected symbol: '.github/workflow'. Located at position 1 within expression: .github/workflow"
252+ }
253+ },
254+ {
255+ "expr": "github/workflow.md",
256+ "err": {
257+ "kind": "lexing",
258+ "value": "Unexpected symbol: 'github/workflow'. Located at position 1 within expression: github/workflow.md"
259+ }
260+ },
261+ {
262+ "expr": "..github/workflow.md && 1",
263+ "err": {
264+ "kind": "lexing",
265+ "value": "Unexpected symbol: '..github/workflow.md'. Located at position 1 within expression: ..github/workflow.md && 1"
266+ }
267+ }
268+ ],
269+ "depth-errors": [
270+ {
271+ "expr": "!!!!! !!!!! !!!!! !!!!! !!!!! !!!!! !!!!! !!!!! !!!!! !!!!! false",
272+ "err": {
273+ "kind": "parsing",
274+ "value": "Exceeded max expression depth 50"
275+ }
276+ },
277+ {
278+ "expr": "!!!!! !!!!! !!!!! !!!!! !!!!! !!!!! !!!!! !!!!! !!!!! !!!! false",
279+ "result": { "kind": "Boolean", "value": true }
280+ },
281+ {
282+ "expr": "foo._1._2._3._4._5._6._7._8._9._10._11._12._13._14._15._16._17._18._19._20._21._22._23._24._25._26._27._28._29._30._31._32._33._34._35._36._37._38._39._40._41._42._43._44._45._46._47._48._49._50",
283+ "contexts": { "foo": null },
284+ "err": {
285+ "kind": "parsing",
286+ "value": "Exceeded max expression depth 50"
287+ }
288+ },
289+ {
290+ "expr": "foo._1._2._3._4._5._6._7._8._9._10._11._12._13._14._15._16._17._18._19._20._21._22._23._24._25._26._27._28._29._30._31._32._33._34._35._36._37._38._39._40._41._42._43._44._45._46._47._48._49",
291+ "contexts": { "foo": null },
292+ "result": { "kind": "Null", "value": null }
293+ },
294+ {
295+ "expr": "foo .*.*.*.*.* .*.*.*.*.* .*.*.*.*.* .*.*.*.*.* .*.*.*.*.* .*.*.*.*.* .*.*.*.*.* .*.*.*.*.* .*.*.*.*.* .*.*.*.*.*",
296+ "contexts": { "foo": null },
297+ "err": {
298+ "kind": "parsing",
299+ "value": "Exceeded max expression depth 50"
300+ }
301+ },
302+ {
303+ "expr": "foo .*.*.*.*.* .*.*.*.*.* .*.*.*.*.* .*.*.*.*.* .*.*.*.*.* .*.*.*.*.* .*.*.*.*.* .*.*.*.*.* .*.*.*.*.* .*.*.*.*",
304+ "contexts": { "foo": null },
305+ "result": { "kind": "Array", "value": [] }
306+ },
307+ {
308+ "expr": "foo[1][2][3][4][5][6][7][8][9][10][11][12][13][14][15][16][17][18][19][20][21][22][23][24][25][26][27][28][29][30][31][32][33][34][35][36][37][38][39][40][41][42][43][44][45][46][47][48][49][50]",
309+ "contexts": { "foo": null },
310+ "err": {
311+ "kind": "parsing",
312+ "value": "Exceeded max expression depth 50"
313+ }
314+ },
315+ {
316+ "expr": "foo[1][2][3][4][5][6][7][8][9][10][11][12][13][14][15][16][17][18][19][20][21][22][23][24][25][26][27][28][29][30][31][32][33][34][35][36][37][38][39][40][41][42][43][44][45][46][47][48][49]",
317+ "contexts": { "foo": null },
318+ "result": { "kind": "Null", "value": null }
319+ },
320+ {
321+ "expr": "foo [*][*][*][*][*] [*][*][*][*][*] [*][*][*][*][*] [*][*][*][*][*] [*][*][*][*][*] [*][*][*][*][*] [*][*][*][*][*] [*][*][*][*][*] [*][*][*][*][*] [*][*][*][*][*]",
322+ "contexts": { "foo": null },
323+ "err": {
324+ "kind": "parsing",
325+ "value": "Exceeded max expression depth 50"
326+ }
327+ },
328+ {
329+ "expr": "foo [*][*][*][*][*] [*][*][*][*][*] [*][*][*][*][*] [*][*][*][*][*] [*][*][*][*][*] [*][*][*][*][*] [*][*][*][*][*] [*][*][*][*][*] [*][*][*][*][*] [*][*][*][*]",
330+ "contexts": { "foo": null },
331+ "result": { "kind": "Array", "value": [] }
332+ },
333+ {
334+ "expr": "fromjson(tojson(fromjson(tojson(fromjson(tojson(fromjson(tojson(fromjson(tojson( fromjson(tojson(fromjson(tojson(fromjson(tojson(fromjson(tojson(fromjson(tojson( fromjson(tojson(fromjson(tojson(fromjson(tojson(fromjson(tojson(fromjson(tojson( fromjson(tojson(fromjson(tojson(fromjson(tojson(fromjson(tojson(fromjson(tojson( fromjson(tojson(fromjson(tojson(fromjson(tojson(fromjson(tojson(fromjson(tojson( 1 )))))))))) )))))))))) )))))))))) )))))))))) ))))))))))",
335+ "err": {
336+ "kind": "parsing",
337+ "value": "Exceeded max expression depth 50"
338+ }
339+ },
340+ {
341+ "expr": "fromjson(tojson(fromjson(tojson(fromjson(tojson(fromjson(tojson(fromjson(tojson( fromjson(tojson(fromjson(tojson(fromjson(tojson(fromjson(tojson(fromjson(tojson( fromjson(tojson(fromjson(tojson(fromjson(tojson(fromjson(tojson(fromjson(tojson( fromjson(tojson(fromjson(tojson(fromjson(tojson(fromjson(tojson(fromjson(tojson( fromjson(tojson(fromjson(tojson(fromjson(tojson(fromjson(tojson(fromjson( '1' ))))))))) )))))))))) )))))))))) )))))))))) ))))))))))",
342+ "result": { "kind": "Number", "value": 1 }
343+ },
344+ {
345+ "expr": "format('depth3'||format('depth5'||format('depth7'||format('depth9'||format('depth11'||format('depth13'||format('depth15'||format('depth17'||format('depth19'||format('depth21'||format('depth23'||format('depth25'||format('depth27'||format('depth29'||format('depth31'||format('depth33'||format('depth35'||format('depth37'||format('depth39'||format('depth41'||format('depth43'||format('depth45'||format('depth47'||format('depth49'||format('depth51'||'depth51')))))))))) )))))))))) )))))",
346+ "err": {
347+ "kind": "parsing",
348+ "value": "Exceeded max expression depth 50"
349+ }
350+ },
351+ {
352+ "expr": "format('depth3'||format('depth5'||format('depth7'||format('depth9'||format('depth11'||format('depth13'||format('depth15'||format('depth17'||format('depth19'||format('depth21'||format('depth23'||format('depth25'||format('depth27'||format('depth29'||format('depth31'||format('depth33'||format('depth35'||format('depth37'||format('depth39'||format('depth41'||format('depth43'||format('depth45'||format('depth47'||format('depth49'||format('depth50')))))))))) )))))))))) )))))",
353+ "result": { "kind": "String", "value": "depth3" }
354+ },
355+ {
356+ "expr": "format('depth3'&&format('depth5'&&format('depth7'&&format('depth9'&&format('depth11'&&format('depth13'&&format('depth15'&&format('depth17'&&format('depth19'&&format('depth21'&&format('depth23'&&format('depth25'&&format('depth27'&&format('depth29'&&format('depth31'&&format('depth33'&&format('depth35'&&format('depth37'&&format('depth39'&&format('depth41'&&format('depth43'&&format('depth45'&&format('depth47'&&format('depth49'&&format('depth51'&&'depth51')))))))))) )))))))))) )))))",
357+ "err": {
358+ "kind": "parsing",
359+ "value": "Exceeded max expression depth 50"
360+ }
361+ },
362+ {
363+ "expr": "format('depth3'&&format('depth5'&&format('depth7'&&format('depth9'&&format('depth11'&&format('depth13'&&format('depth15'&&format('depth17'&&format('depth19'&&format('depth21'&&format('depth23'&&format('depth25'&&format('depth27'&&format('depth29'&&format('depth31'&&format('depth33'&&format('depth35'&&format('depth37'&&format('depth39'&&format('depth41'&&format('depth43'&&format('depth45'&&format('depth47'&&format('depth49'&&format('depth50')))))))))) )))))))))) )))))",
364+ "result": { "kind": "String", "value": "depth50" }
365+ },
366+ {
367+ "expr": "1 || 2 || 3 || 4 || 5 || 6 || 7 || 8 || 9 || 10 || 11 || 12 || 13 || 14 || 15 || 16 || 17 || 18 || 19 || 20 || 21 || 22 || 23 || 24 || 25 || 26 || 27 || 28 || 29 || 30 || 31 || 32 || 33 || 34 || 35 || 36 || 37 || 38 || 39 || 40 || 41 || 42 || 43 || 44 || 45 || 46 || 47 || 48 || 49 || 50 || 51 || 52 || 53 || 54 || 55 || 56 || 57 || 58 || 59 || 60",
368+ "result": { "kind": "Number", "value": 1 }
369+ },
370+ {
371+ "expr": "1 && 2 && 3 && 4 && 5 && 6 && 7 && 8 && 9 && 10 && 11 && 12 && 13 && 14 && 15 && 16 && 17 && 18 && 19 && 20 && 21 && 22 && 23 && 24 && 25 && 26 && 27 && 28 && 29 && 30 && 31 && 32 && 33 && 34 && 35 && 36 && 37 && 38 && 39 && 40 && 41 && 42 && 43 && 44 && 45 && 46 && 47 && 48 && 49 && 50 && 51 && 52 && 53 && 54 && 55 && 56 && 57 && 58 && 59 && 60",
372+ "result": { "kind": "Number", "value": 60 }
373+ },
374+ {
375+ "expr": "1 && 2 || 3 && 4 || 5 && 6 || 7 && 8 || 9 && 10 || 11 && 12 || 13 && 14 || 15 && 16 || 17 && 18 || 19 && 20 || 21 && 22 || 23 && 24 || 25 && 26 || 27 && 28 || 29 && 30 || 31 && 32 || 33 && 34 || 35 && 36 || 37 && 38 || 39 && 40 || 41 && 42 || 43 && 44 || 45 && 46 || 47 && 48 || 49 && 50 || 51 && 52 || 53 && 54 || 55 && 56 || 57 && 58 || 59 && 60",
376+ "result": { "kind": "Number", "value": 2 }
377+ }
378+ ],
379+ "memory-errors": [
380+ {
381+ "options": {
382+ "skip": ["typescript"]
383+ },
384+ "expr": "startswith(format('{0}{0}{0}{0}{0}{0}{0}{0}{0}{0}{0}{0}{0}{0}{0}{0}{0}{0}{0}{0}{0}{0}{0}{0}{0}{0}{0}{0}{0}{0}{0}{0}{0}{0}{0}{0}{0}{0}{0}{0}', tojson(github)), format('{0}{0}{0}{0}{0}{0}{0}{0}{0}{0}{0}{0}{0}{0}{0}{0}{0}{0}{0}{0}{0}{0}{0}{0}{0}{0}{0}{0}{0}{0}{0}{0}{0}{0}{0}{0}{0}{0}{0}{0}', tojson(github)))",
385+ "contexts": {
386+ "github": {
387+ "ref": "refs/heads/main",
388+ "sha": "2ce6b095f4cceb616efed52266e3e3c0367ba795",
389+ "repository": "monalisa/testing",
390+ "repository_owner": "monalisa",
391+ "repository_owner_id": "12102068",
392+ "repositoryUrl": "git://github.com/monalisa/testing.git",
393+ "run_id": "2827197126",
394+ "run_number": "845",
395+ "retention_days": "90",
396+ "run_attempt": "1",
397+ "artifact_cache_size_limit": "10",
398+ "repository_visibility": "public",
399+ "repository_id": "1",
400+ "actor_id": "1",
401+ "actor": "monalisa",
402+ "triggering_actor": "monalisa",
403+ "workflow": "CI",
404+ "head_ref": "",
405+ "base_ref": "",
406+ "event_name": "push",
407+ "event": {
408+ "after": "2ce6b095f4cceb616efed52266e3e3c0367ba795",
409+ "base_ref": null,
410+ "before": "bbe29778fdad33232cd67bd84205d334b94412d7",
411+ "commits": [
412+ {
413+ "author": {
414+ "email": "monalisa@users.noreply.github.com",
415+ "name": "mona",
416+ "username": "monalisa"
417+ },
418+ "committer": {
419+ "email": "noreply@github.com",
420+ "name": "GitHub",
421+ "username": "web-flow"
422+ },
423+ "distinct": true,
424+ "id": "2ce6b095f4cceb616efed52266e3e3c0367ba795",
425+ "message": "Update main.yml",
426+ "timestamp": "2022-08-09T12:40:12-05:00",
427+ "tree_id": "0dfd49aedd0cc103865d00587df3d23aa6f571f7",
428+ "url": "https://github.com/monalisa/testing/commit/2ce6b095f4cceb616efed52266e3e3c0367ba795"
429+ }
430+ ],
431+ "compare": "https://github.com/monalisa/testing/compare/bbe29778fdad...2ce6b095f4cc",
432+ "created": false,
433+ "deleted": false,
434+ "forced": false,
435+ "head_commit": {
436+ "author": {
437+ "email": "monalisa@users.noreply.github.com",
438+ "name": "mona",
439+ "username": "monalisa"
440+ },
441+ "committer": {
442+ "email": "noreply@github.com",
443+ "name21": "GitHub",
444+ "username": "web-flow"
445+ },
446+ "distinct": true,
447+ "id": "2ce6b095f4cceb616efed52266e3e3c0367ba795",
448+ "message": "Update main.yml",
449+ "timestamp": "2022-08-09T12:40:12-05:00",
450+ "tree_id": "0dfd49aedd0cc103865d00587df3d23aa6f571f7",
451+ "url": "https://github.com/monalisa/testing/commit/2ce6b095f4cceb616efed52266e3e3c0367ba795"
452+ },
453+ "pusher": {
454+ "email": "monalisa@users.noreply.github.com",
455+ "name": "monalisa"
456+ },
457+ "ref": "refs/heads/main",
458+ "repository": {
459+ "allow_forking": true,
460+ "archive_url": "https://api.github.com/repos/monalisa/testing/{archive_format}{/ref}",
461+ "archived": false,
462+ "assignees_url": "https://api.github.com/repos/monalisa/testing/assignees{/user}",
463+ "blobs_url": "https://api.github.com/repos/monalisa/testing/git/blobs{/sha}",
464+ "branches_url": "https://api.github.com/repos/monalisa/testing/branches{/branch}",
465+ "clone_url": "https://github.com/monalisa/testing.git",
466+ "collaborators_url": "https://api.github.com/repos/monalisa/testing/collaborators{/collaborator}",
467+ "comments_url": "https://api.github.com/repos/monalisa/testing/comments{/number}",
468+ "commits_url": "https://api.github.com/repos/monalisa/testing/commits{/sha}",
469+ "compare_url": "https://api.github.com/repos/monalisa/testing/compare/{base}...{head}",
470+ "contents_url": "https://api.github.com/repos/monalisa/testing/contents/{+path}",
471+ "contributors_url": "https://api.github.com/repos/monalisa/testing/contributors",
472+ "created_at": 1516230842,
473+ "default_branch": "main",
474+ "deployments_url": "https://api.github.com/repos/monalisa/testing/deployments",
475+ "description": null,
476+ "disabled": false,
477+ "downloads_url": "https://api.github.com/repos/monalisa/testing/downloads",
478+ "events_url": "https://api.github.com/repos/monalisa/testing/events",
479+ "fork": false,
480+ "forks": 1,
481+ "forks_count": 1,
482+ "forks_url": "https://api.github.com/repos/monalisa/testing/forks",
483+ "full_name": "monalisa/testing",
484+ "git_commits_url": "https://api.github.com/repos/monalisa/testing/git/commits{/sha}",
485+ "git_refs_url": "https://api.github.com/repos/monalisa/testing/git/refs{/sha}",
486+ "git_tags_url": "https://api.github.com/repos/monalisa/testing/git/tags{/sha}",
487+ "git_url": "git://github.com/monalisa/testing.git",
488+ "has_downloads": true,
489+ "has_issues": true,
490+ "has_pages": false,
491+ "has_projects": true,
492+ "has_wiki": true,
493+ "homepage": null,
494+ "hooks_url": "https://api.github.com/repos/monalisa/testing/hooks",
495+ "html_url": "https://github.com/monalisa/testing",
496+ "id": 117904191,
497+ "is_template": false,
498+ "issue_comment_url": "https://api.github.com/repos/monalisa/testing/issues/comments{/number}",
499+ "issue_events_url": "https://api.github.com/repos/monalisa/testing/issues/events{/number}",
500+ "issues_url": "https://api.github.com/repos/monalisa/testing/issues{/number}",
501+ "keys_url": "https://api.github.com/repos/monalisa/testing/keys{/key_id}",
502+ "labels_url": "https://api.github.com/repos/monalisa/testing/labels{/name}",
503+ "language": "Shell",
504+ "languages_url": "https://api.github.com/repos/monalisa/testing/languages",
505+ "license": null,
506+ "master_branch": "main",
507+ "merges_url": "https://api.github.com/repos/monalisa/testing/merges",
508+ "milestones_url": "https://api.github.com/repos/monalisa/testing/milestones{/number}",
509+ "mirror_url": null,
510+ "name": "testing",
511+ "node_id": "MDEwOlJlcG9zaXRvcnkxMTc5MDQxOTE=",
512+ "notifications_url": "https://api.github.com/repos/monalisa/testing/notifications{?since,all,participating}",
513+ "open_issues": 5,
514+ "open_issues_count": 5,
515+ "owner": {
516+ "avatar_url": "https://avatars.githubusercontent.com/u/12102068?v=4",
517+ "email": "monalisa@users.noreply.github.com",
518+ "events_url": "https://api.github.com/users/monalisa/events{/privacy}",
519+ "followers_url": "https://api.github.com/users/monalisa/followers",
520+ "following_url": "https://api.github.com/users/monalisa/following{/other_user}",
521+ "gists_url": "https://api.github.com/users/monalisa/gists{/gist_id}",
522+ "gravatar_id": "",
523+ "html_url": "https://github.com/monalisa",
524+ "id": 12102068,
525+ "login": "monalisa",
526+ "name": "monalisa",
527+ "node_id": "MDQ6VXNlcjEyMTAyMDY4",
528+ "organizations_url": "https://api.github.com/users/monalisa/orgs",
529+ "received_events_url": "https://api.github.com/users/monalisa/received_events",
530+ "repos_url": "https://api.github.com/users/monalisa/repos",
531+ "site_admin": true,
532+ "starred_url": "https://api.github.com/users/monalisa/starred{/owner}{/repo}",
533+ "subscriptions_url": "https://api.github.com/users/monalisa/subscriptions",
534+ "type": "User",
535+ "url": "https://api.github.com/users/monalisa"
536+ },
537+ "private": false,
538+ "pulls_url": "https://api.github.com/repos/monalisa/testing/pulls{/number}",
539+ "pushed_at": 1660066812,
540+ "releases_url": "https://api.github.com/repos/monalisa/testing/releases{/id}",
541+ "size": 611,
542+ "ssh_url": "git@github.com:monalisa/testing.git",
543+ "stargazers": 1,
544+ "stargazers_count": 1,
545+ "stargazers_url": "https://api.github.com/repos/monalisa/testing/stargazers",
546+ "statuses_url": "https://api.github.com/repos/monalisa/testing/statuses/{sha}",
547+ "subscribers_url": "https://api.github.com/repos/monalisa/testing/subscribers",
548+ "subscription_url": "https://api.github.com/repos/monalisa/testing/subscription",
549+ "svn_url": "https://github.com/monalisa/testing",
550+ "tags_url": "https://api.github.com/repos/monalisa/testing/tags",
551+ "teams_url": "https://api.github.com/repos/monalisa/testing/teams",
552+ "topics": [],
553+ "trees_url": "https://api.github.com/repos/monalisa/testing/git/trees{/sha}",
554+ "updated_at": "2022-01-05T02:14:32Z",
555+ "url": "https://github.com/monalisa/testing",
556+ "visibility": "public",
557+ "watchers": 1,
558+ "watchers_count": 1,
559+ "web_commit_signoff_required": false
560+ },
561+ "sender": {
562+ "avatar_url": "https://avatars.githubusercontent.com/u/12102068?v=4",
563+ "events_url": "https://api.github.com/users/monalisa/events{/privacy}",
564+ "followers_url": "https://api.github.com/users/monalisa/followers",
565+ "following_url": "https://api.github.com/users/monalisa/following{/other_user}",
566+ "gists_url": "https://api.github.com/users/monalisa/gists{/gist_id}",
567+ "gravatar_id": "",
568+ "html_url": "https://github.com/monalisa",
569+ "id": 12102068,
570+ "login": "monalisa",
571+ "node_id": "MDQ6VXNlcjEyMTAyMDY4",
572+ "organizations_url": "https://api.github.com/users/monalisa/orgs",
573+ "received_events_url": "https://api.github.com/users/monalisa/received_events",
574+ "repos_url": "https://api.github.com/users/monalisa/repos",
575+ "site_admin": true,
576+ "starred_url": "https://api.github.com/users/monalisa/starred{/owner}{/repo}",
577+ "subscriptions_url": "https://api.github.com/users/monalisa/subscriptions",
578+ "type": "User",
579+ "url": "https://api.github.com/users/monalisa"
580+ }
581+ },
582+ "server_url": "https://github.com",
583+ "api_url": "https://api.github.com",
584+ "graphql_url": "https://api.github.com/graphql",
585+ "ref_name": "main",
586+ "ref_protected": false,
587+ "ref_type": "branch",
588+ "secret_source": "Actions",
589+ "workspace": "/home/runner/work/testing/testing",
590+ "action": "__run_2",
591+ "event_path": "/home/runner/work/_temp/_github_workflow/event.json",
592+ "action_repository": "",
593+ "action_ref": "",
594+ "path": "/home/runner/work/_temp/_runner_file_commands/add_path_04146e5b-5a26-490d-b886-886641aa5651",
595+ "env": "/home/runner/work/_temp/_runner_file_commands/set_env_04146e5b-5a26-490d-b886-886641aa5651",
596+ "step_summary": "/home/runner/work/_temp/_runner_file_commands/step_summary_04146e5b-5a26-490d-b886-886641aa5651"
597+ }
598+ },
599+ "err": {
600+ "kind": "evaluation",
601+ "value": "The maximum allowed memory size was exceeded"
602+ }
603+ }
604+ ]
605+}
A expr/testdata/languageservices/tojson.json +223 -0
@@ -0,0 +1,223 @@
1+{
2+ "basics": [
3+ {
4+ "expr": "tojson(null)",
5+ "result": {
6+ "kind": "String",
7+ "value": "null"
8+ }
9+ },
10+ {
11+ "expr": "tojson(true)",
12+ "result": {
13+ "kind": "String",
14+ "value": "true"
15+ }
16+ },
17+ {
18+ "expr": "tojson(false)",
19+ "result": {
20+ "kind": "String",
21+ "value": "false"
22+ }
23+ },
24+ {
25+ "expr": "tojson(0)",
26+ "result": {
27+ "kind": "String",
28+ "value": "0"
29+ }
30+ },
31+ {
32+ "expr": "tojson(-0)",
33+ "result": {
34+ "kind": "String",
35+ "value": "0"
36+ }
37+ },
38+ {
39+ "expr": "tojson(123456789)",
40+ "result": {
41+ "kind": "String",
42+ "value": "123456789"
43+ }
44+ },
45+ {
46+ "expr": "tojson(-123456789)",
47+ "result": {
48+ "kind": "String",
49+ "value": "-123456789"
50+ }
51+ },
52+ {
53+ "expr": "tojson(1234.5)",
54+ "result": {
55+ "kind": "String",
56+ "value": "1234.5"
57+ }
58+ },
59+ {
60+ "expr": "tojson(-1234.5)",
61+ "result": {
62+ "kind": "String",
63+ "value": "-1234.5"
64+ }
65+ },
66+ {
67+ "expr": "tojson('')",
68+ "result": {
69+ "kind": "String",
70+ "value": "\"\""
71+ }
72+ },
73+ {
74+ "expr": "tojson('abc')",
75+ "result": {
76+ "kind": "String",
77+ "value": "\"abc\""
78+ }
79+ },
80+ {
81+ "expr": "tojson('abc''def')",
82+ "result": {
83+ "kind": "String",
84+ "value": "\"abc'def\""
85+ }
86+ },
87+ {
88+ "expr": "tojson('abc\\\"def')",
89+ "result": {
90+ "kind": "String",
91+ "value": "\"abc\\\\\\\"def\""
92+ }
93+ },
94+ {
95+ "expr": "tojson(emptyArray)",
96+ "contexts": {
97+ "emptyArray": []
98+ },
99+ "result": {
100+ "kind": "String",
101+ "value": "[]"
102+ }
103+ },
104+ {
105+ "expr": "tojson(emptyObject)",
106+ "contexts": {
107+ "emptyObject": {}
108+ },
109+ "result": {
110+ "kind": "String",
111+ "value": "{}"
112+ }
113+ }
114+ ],
115+ "arrays": [
116+ {
117+ "expr": "tojson(myArray)",
118+ "contexts": {
119+ "myArray": []
120+ },
121+ "result": {
122+ "kind": "String",
123+ "value": "[]"
124+ }
125+ },
126+ {
127+ "expr": "tojson(myArray)",
128+ "contexts": {
129+ "myArray": [
130+ 1,
131+ 2,
132+ 3
133+ ]
134+ },
135+ "result": {
136+ "kind": "String",
137+ "value": "[\n 1,\n 2,\n 3\n]"
138+ }
139+ },
140+ {
141+ "expr": "tojson(myArray)",
142+ "contexts": {
143+ "myArray": [
144+ [
145+ 1,
146+ 2,
147+ 3
148+ ],
149+ [
150+ "abc",
151+ "def",
152+ "ghi"
153+ ],
154+ [
155+ true,
156+ false,
157+ null,
158+ [],
159+ {}
160+ ]
161+ ]
162+ },
163+ "result": {
164+ "kind": "String",
165+ "value": "[\n [\n 1,\n 2,\n 3\n ],\n [\n \"abc\",\n \"def\",\n \"ghi\"\n ],\n [\n true,\n false,\n null,\n [],\n {}\n ]\n]"
166+ }
167+ }
168+ ],
169+ "object": [
170+ {
171+ "expr": "tojson(myObject)",
172+ "contexts": {
173+ "myObject": {}
174+ },
175+ "result": {
176+ "kind": "String",
177+ "value": "{}"
178+ }
179+ },
180+ {
181+ "expr": "tojson(myObject)",
182+ "contexts": {
183+ "myObject": {
184+ "one": "value one",
185+ "two" : "value two",
186+ "three": "value three"
187+ }
188+ },
189+ "result": {
190+ "kind": "String",
191+ "value": "{\n \"one\": \"value one\",\n \"two\": \"value two\",\n \"three\": \"value three\"\n}"
192+ }
193+ },
194+ {
195+ "expr": "tojson(myObject)",
196+ "contexts": {
197+ "myObject": {
198+ "nested-one": {
199+ "one": 1,
200+ "two": 2,
201+ "three": 3
202+ },
203+ "nested-two": {
204+ "string one": "value one",
205+ "string two": "value two",
206+ "string three": "value three"
207+ },
208+ "nested-three": {
209+ "true": true,
210+ "false": false,
211+ "null": null,
212+ "array": [],
213+ "object": {}
214+ }
215+ }
216+ },
217+ "result": {
218+ "kind": "String",
219+ "value": "{\n \"nested-one\": {\n \"one\": 1,\n \"two\": 2,\n \"three\": 3\n },\n \"nested-two\": {\n \"string one\": \"value one\",\n \"string two\": \"value two\",\n \"string three\": \"value three\"\n },\n \"nested-three\": {\n \"true\": true,\n \"false\": false,\n \"null\": null,\n \"array\": [],\n \"object\": {}\n }\n}"
220+ }
221+ }
222+ ]
223+}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 1

Tags 3

↑↓ moveenter openesc close