@malloydata/malloy 0.0.43-dev230621180201 → 0.0.43-dev230621212545
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lang/test/imports.spec.js +18 -15
- package/dist/lang/test/parse-expects.d.ts +32 -6
- package/dist/lang/test/parse-expects.js +39 -60
- package/dist/lang/test/parse.spec.js +731 -452
- package/dist/lang/test/sql-block.spec.js +15 -12
- package/dist/lang/test/test-translator.d.ts +6 -0
- package/dist/lang/test/test-translator.js +15 -1
- package/package.json +1 -1
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
/*
|
|
4
7
|
* Copyright 2023 Google LLC
|
|
@@ -24,30 +27,31 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
24
27
|
*/
|
|
25
28
|
require("./parse-expects");
|
|
26
29
|
const test_translator_1 = require("./test-translator");
|
|
30
|
+
const escapeRegExp_1 = __importDefault(require("lodash/escapeRegExp"));
|
|
27
31
|
describe('import:', () => {
|
|
28
32
|
test('simple source', () => {
|
|
29
33
|
const docParse = new test_translator_1.TestTranslator('import "child"');
|
|
30
34
|
const xr = docParse.unresolved();
|
|
31
|
-
expect(docParse).
|
|
35
|
+
expect(docParse).toParse();
|
|
32
36
|
expect(xr).toEqual({ urls: ['internal://test/langtests/child'] });
|
|
33
37
|
docParse.update({
|
|
34
38
|
urls: { 'internal://test/langtests/child': 'source: aa is a' },
|
|
35
39
|
});
|
|
36
|
-
expect(docParse).
|
|
40
|
+
expect(docParse).toTranslate();
|
|
37
41
|
const aa = docParse.getSourceDef('aa');
|
|
38
42
|
expect(aa).toBeDefined();
|
|
39
43
|
});
|
|
40
44
|
test('simple query', () => {
|
|
41
45
|
const docParse = new test_translator_1.TestTranslator('import "child"');
|
|
42
46
|
const xr = docParse.unresolved();
|
|
43
|
-
expect(docParse).
|
|
47
|
+
expect(docParse).toParse();
|
|
44
48
|
expect(xr).toEqual({ urls: ['internal://test/langtests/child'] });
|
|
45
49
|
docParse.update({
|
|
46
50
|
urls: {
|
|
47
51
|
'internal://test/langtests/child': 'query: aq is a->{ project: * }',
|
|
48
52
|
},
|
|
49
53
|
});
|
|
50
|
-
expect(docParse).
|
|
54
|
+
expect(docParse).toTranslate();
|
|
51
55
|
const aq = docParse.getQuery('aq');
|
|
52
56
|
expect(aq).toBeDefined();
|
|
53
57
|
});
|
|
@@ -59,7 +63,7 @@ source: newSrc is a {
|
|
|
59
63
|
}
|
|
60
64
|
`);
|
|
61
65
|
const xr = docParse.unresolved();
|
|
62
|
-
expect(docParse).
|
|
66
|
+
expect(docParse).toParse();
|
|
63
67
|
expect(xr).toEqual({ urls: ['internal://test/langtests/child'] });
|
|
64
68
|
docParse.update({
|
|
65
69
|
urls: {
|
|
@@ -70,7 +74,7 @@ source: botProjQSrc is from(->botProjQ)
|
|
|
70
74
|
`,
|
|
71
75
|
},
|
|
72
76
|
});
|
|
73
|
-
expect(docParse).
|
|
77
|
+
expect(docParse).toTranslate();
|
|
74
78
|
const newSrc = docParse.getSourceDef('newSrc');
|
|
75
79
|
const f = newSrc === null || newSrc === void 0 ? void 0 : newSrc.fields.find(f => f.name === 'b');
|
|
76
80
|
expect(f === null || f === void 0 ? void 0 : f.type).toBe('struct');
|
|
@@ -85,7 +89,7 @@ source: botProjQSrc is from(->botProjQ)
|
|
|
85
89
|
test('missing import', () => {
|
|
86
90
|
const docParse = new test_translator_1.TestTranslator('import "child"');
|
|
87
91
|
const xr = docParse.unresolved();
|
|
88
|
-
expect(docParse).
|
|
92
|
+
expect(docParse).toParse();
|
|
89
93
|
expect(xr).toEqual({ urls: ['internal://test/langtests/child'] });
|
|
90
94
|
const reportedError = 'ENOWAY: No way to find your child';
|
|
91
95
|
docParse.update({
|
|
@@ -94,8 +98,7 @@ source: botProjQSrc is from(->botProjQ)
|
|
|
94
98
|
},
|
|
95
99
|
});
|
|
96
100
|
docParse.translate();
|
|
97
|
-
expect(docParse).
|
|
98
|
-
expect(docParse.prettyErrors()).toContain(reportedError);
|
|
101
|
+
expect(docParse).translationToFailWith(new RegExp((0, escapeRegExp_1.default)(reportedError)));
|
|
99
102
|
});
|
|
100
103
|
test('chained imports', () => {
|
|
101
104
|
const docParse = new test_translator_1.TestTranslator('import "child"');
|
|
@@ -103,12 +106,12 @@ source: botProjQSrc is from(->botProjQ)
|
|
|
103
106
|
urls: { 'internal://test/langtests/child': 'import "grandChild"' },
|
|
104
107
|
});
|
|
105
108
|
const xr = docParse.unresolved();
|
|
106
|
-
expect(docParse).
|
|
109
|
+
expect(docParse).toParse();
|
|
107
110
|
expect(xr).toEqual({ urls: ['internal://test/langtests/grandChild'] });
|
|
108
111
|
});
|
|
109
112
|
test('relative imports', () => {
|
|
110
113
|
const docParse = new test_translator_1.TestTranslator('import "../parent.malloy"');
|
|
111
|
-
expect(docParse).
|
|
114
|
+
expect(docParse).toParse();
|
|
112
115
|
const xr = docParse.unresolved();
|
|
113
116
|
expect(xr).toEqual({ urls: ['internal://test/parent.malloy'] });
|
|
114
117
|
docParse.update({
|
|
@@ -116,11 +119,11 @@ source: botProjQSrc is from(->botProjQ)
|
|
|
116
119
|
'internal://test/parent.malloy': "source: aa is table('aTable')",
|
|
117
120
|
},
|
|
118
121
|
});
|
|
119
|
-
expect(docParse).
|
|
122
|
+
expect(docParse).toTranslate();
|
|
120
123
|
});
|
|
121
124
|
test('relative imports with errors', () => {
|
|
122
125
|
const docParse = new test_translator_1.TestTranslator('import "../parent.malloy"');
|
|
123
|
-
expect(docParse).
|
|
126
|
+
expect(docParse).toParse();
|
|
124
127
|
const xr = docParse.unresolved();
|
|
125
128
|
expect(xr).toEqual({ urls: ['internal://test/parent.malloy'] });
|
|
126
129
|
docParse.update({
|
|
@@ -131,7 +134,7 @@ source: botProjQSrc is from(->botProjQ)
|
|
|
131
134
|
}`,
|
|
132
135
|
},
|
|
133
136
|
});
|
|
134
|
-
expect(docParse).
|
|
137
|
+
expect(docParse).translationToFailWith("Cannot redefine 'astr'");
|
|
135
138
|
});
|
|
136
139
|
test('source references expanded when not exported', () => {
|
|
137
140
|
const srcFiles = {
|
|
@@ -145,7 +148,7 @@ source: botProjQSrc is from(->botProjQ)
|
|
|
145
148
|
import "middle"
|
|
146
149
|
`);
|
|
147
150
|
fullModel.update({ urls: srcFiles });
|
|
148
|
-
expect(fullModel).
|
|
151
|
+
expect(fullModel).toTranslate();
|
|
149
152
|
const ms = fullModel.getSourceDef('midSrc');
|
|
150
153
|
expect(ms).toBeDefined();
|
|
151
154
|
if (ms) {
|
|
@@ -3,13 +3,39 @@ declare type ErrorSpec = string | RegExp;
|
|
|
3
3
|
declare global {
|
|
4
4
|
namespace jest {
|
|
5
5
|
interface Matchers<R> {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
/**
|
|
7
|
+
* expect(X).toParse()
|
|
8
|
+
*
|
|
9
|
+
* Passes if the source parses to an AST without errors.
|
|
10
|
+
*
|
|
11
|
+
* X can be a MarkedSource, a string, or a model. If it is a marked
|
|
12
|
+
* source, the errors which are found must match the locations of
|
|
13
|
+
* the markings.
|
|
14
|
+
*/
|
|
15
|
+
toParse(): R;
|
|
16
|
+
/**
|
|
17
|
+
* expect(X).toTranslate()
|
|
18
|
+
*
|
|
19
|
+
* Passes if the source compiles to code which could be used to
|
|
20
|
+
* generate SQL.
|
|
21
|
+
*
|
|
22
|
+
* X can be a MarkedSource, a string, or a model. If it is a marked
|
|
23
|
+
* source, the errors which are found must match the locations of
|
|
24
|
+
* the markings.
|
|
25
|
+
*/
|
|
26
|
+
toTranslate(): R;
|
|
11
27
|
toReturnType(tp: string): R;
|
|
12
|
-
|
|
28
|
+
/**
|
|
29
|
+
* expect(X).translateToFailWith(expectedErrors)
|
|
30
|
+
*
|
|
31
|
+
* X can be a MarkedSource, a string, or a model. If it is a marked
|
|
32
|
+
* source, the errors which are found must match the locations of
|
|
33
|
+
* the markings.
|
|
34
|
+
*
|
|
35
|
+
* @param expectedErrors varargs list of strings which must match
|
|
36
|
+
* exactly, or regular expressions.
|
|
37
|
+
*/
|
|
38
|
+
translationToFailWith(...expectedErrors: ErrorSpec[]): R;
|
|
13
39
|
isLocationIn(at: DocumentLocation, txt: string): R;
|
|
14
40
|
}
|
|
15
41
|
}
|
|
@@ -92,60 +92,53 @@ function highlightError(dl, txt) {
|
|
|
92
92
|
}
|
|
93
93
|
return output.join('\n');
|
|
94
94
|
}
|
|
95
|
+
function isMarkedSource(ts) {
|
|
96
|
+
return typeof ts !== 'string' && !(ts instanceof test_translator_1.TestTranslator);
|
|
97
|
+
}
|
|
98
|
+
function xlator(ts) {
|
|
99
|
+
if (ts instanceof test_translator_1.TestTranslator) {
|
|
100
|
+
return ts;
|
|
101
|
+
}
|
|
102
|
+
if (typeof ts === 'string') {
|
|
103
|
+
return new test_translator_1.TestTranslator(ts);
|
|
104
|
+
}
|
|
105
|
+
return ts.translator || new test_translator_1.TestTranslator(ts.code);
|
|
106
|
+
}
|
|
107
|
+
function xlated(tt) {
|
|
108
|
+
const errorCheck = checkForErrors(tt);
|
|
109
|
+
if (!errorCheck.pass) {
|
|
110
|
+
return errorCheck;
|
|
111
|
+
}
|
|
112
|
+
tt.translate();
|
|
113
|
+
return checkForNeededs(tt);
|
|
114
|
+
}
|
|
95
115
|
expect.extend({
|
|
96
|
-
|
|
97
|
-
const x =
|
|
98
|
-
x.compile();
|
|
99
|
-
const errorCheck = checkForErrors(x);
|
|
100
|
-
if (!errorCheck.pass) {
|
|
101
|
-
return errorCheck;
|
|
102
|
-
}
|
|
103
|
-
x.translate();
|
|
104
|
-
return checkForNeededs(x);
|
|
105
|
-
},
|
|
106
|
-
modelParsed: function (x) {
|
|
116
|
+
toParse: function (tx) {
|
|
117
|
+
const x = xlator(tx);
|
|
107
118
|
x.compile();
|
|
108
119
|
return checkForErrors(x);
|
|
109
120
|
},
|
|
110
|
-
|
|
121
|
+
toTranslate: function (tx) {
|
|
122
|
+
const x = xlator(tx);
|
|
111
123
|
x.compile();
|
|
112
|
-
|
|
113
|
-
if (!errorCheck.pass) {
|
|
114
|
-
return errorCheck;
|
|
115
|
-
}
|
|
116
|
-
x.translate();
|
|
117
|
-
return checkForNeededs(x);
|
|
124
|
+
return xlated(x);
|
|
118
125
|
},
|
|
119
|
-
|
|
120
|
-
const
|
|
121
|
-
|
|
122
|
-
const
|
|
123
|
-
if (!
|
|
124
|
-
return
|
|
126
|
+
toReturnType: function (exprText, returnType) {
|
|
127
|
+
const exprModel = new test_translator_1.BetaExpression(exprText);
|
|
128
|
+
exprModel.compile();
|
|
129
|
+
const ok = xlated(exprModel);
|
|
130
|
+
if (!ok.pass) {
|
|
131
|
+
return ok;
|
|
125
132
|
}
|
|
126
|
-
|
|
133
|
+
const d = exprModel.generated();
|
|
134
|
+
const pass = d.dataType === returnType;
|
|
135
|
+
const msg = `Expression type ${d.dataType} ${pass ? '=' : '!='} $[returnType`;
|
|
136
|
+
return { pass, message: () => msg };
|
|
127
137
|
},
|
|
128
|
-
|
|
129
|
-
return checkForErrors(trans);
|
|
130
|
-
},
|
|
131
|
-
toReturnType: function (functionCall, returnType) {
|
|
132
|
-
const exprModel = new test_translator_1.TestTranslator(`source: x is a { dimension: d is ${functionCall} }`);
|
|
133
|
-
expect(exprModel).modelCompiled();
|
|
134
|
-
const x = exprModel.getSourceDef('x');
|
|
135
|
-
expect(x).toBeDefined();
|
|
136
|
-
if (x) {
|
|
137
|
-
const d = x.fields.find(f => f.name === 'd');
|
|
138
|
-
expect(d === null || d === void 0 ? void 0 : d.type).toBe(returnType);
|
|
139
|
-
}
|
|
140
|
-
return {
|
|
141
|
-
pass: true,
|
|
142
|
-
message: () => '',
|
|
143
|
-
};
|
|
144
|
-
},
|
|
145
|
-
compileToFailWith: function (s, ...msgs) {
|
|
138
|
+
translationToFailWith: function (s, ...msgs) {
|
|
146
139
|
var _a;
|
|
147
140
|
let emsg = 'Compile Error expectation not met\nExpected message';
|
|
148
|
-
|
|
141
|
+
const mSrc = isMarkedSource(s) ? s : undefined;
|
|
149
142
|
const qmsgs = msgs.map(s => `error '${s}'`);
|
|
150
143
|
if (msgs.length === 1) {
|
|
151
144
|
emsg += ` ${qmsgs[0]}`;
|
|
@@ -153,22 +146,8 @@ expect.extend({
|
|
|
153
146
|
else {
|
|
154
147
|
emsg += `s [\n${qmsgs.join('\n')}\n]`;
|
|
155
148
|
}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
if (s instanceof test_translator_1.TestTranslator) {
|
|
159
|
-
m = s;
|
|
160
|
-
src = m.testSrc;
|
|
161
|
-
}
|
|
162
|
-
else {
|
|
163
|
-
if (typeof s === 'string') {
|
|
164
|
-
src = s;
|
|
165
|
-
}
|
|
166
|
-
else {
|
|
167
|
-
src = s.code;
|
|
168
|
-
mSrc = s;
|
|
169
|
-
}
|
|
170
|
-
m = new test_translator_1.TestTranslator(src);
|
|
171
|
-
}
|
|
149
|
+
const m = xlator(s);
|
|
150
|
+
const src = m.testSrc;
|
|
172
151
|
emsg += `\nSource:\n${src}`;
|
|
173
152
|
m.compile();
|
|
174
153
|
const t = m.translate();
|