@malloydata/malloy 0.0.80-dev230906223653 → 0.0.80-dev230907131802
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/ast/elements/import-statement.d.ts +13 -2
- package/dist/lang/ast/elements/import-statement.js +51 -8
- package/dist/lang/lib/Malloy/MalloyParser.d.ts +143 -113
- package/dist/lang/lib/Malloy/MalloyParser.js +1785 -1573
- package/dist/lang/lib/Malloy/MalloyParserListener.d.ts +22 -0
- package/dist/lang/lib/Malloy/MalloyParserVisitor.d.ts +14 -0
- package/dist/lang/malloy-to-ast.js +16 -1
- package/dist/lang/parse-utils.d.ts +1 -0
- package/dist/lang/parse-utils.js +8 -4
- package/dist/lang/test/imports.spec.js +66 -0
- package/dist/lang/test/query.spec.js +11 -6
- package/package.json +1 -1
|
@@ -92,6 +92,8 @@ import { BlockSQLDefContext } from "./MalloyParser";
|
|
|
92
92
|
import { SqlStringContext } from "./MalloyParser";
|
|
93
93
|
import { SqlInterpolationContext } from "./MalloyParser";
|
|
94
94
|
import { ImportStatementContext } from "./MalloyParser";
|
|
95
|
+
import { ImportSelectContext } from "./MalloyParser";
|
|
96
|
+
import { ImportItemContext } from "./MalloyParser";
|
|
95
97
|
import { ImportURLContext } from "./MalloyParser";
|
|
96
98
|
import { DocAnnotationsContext } from "./MalloyParser";
|
|
97
99
|
import { IgnoredObjectAnnotationsContext } from "./MalloyParser";
|
|
@@ -1297,6 +1299,26 @@ export interface MalloyParserListener extends ParseTreeListener {
|
|
|
1297
1299
|
* @param ctx the parse tree
|
|
1298
1300
|
*/
|
|
1299
1301
|
exitImportStatement?: (ctx: ImportStatementContext) => void;
|
|
1302
|
+
/**
|
|
1303
|
+
* Enter a parse tree produced by `MalloyParser.importSelect`.
|
|
1304
|
+
* @param ctx the parse tree
|
|
1305
|
+
*/
|
|
1306
|
+
enterImportSelect?: (ctx: ImportSelectContext) => void;
|
|
1307
|
+
/**
|
|
1308
|
+
* Exit a parse tree produced by `MalloyParser.importSelect`.
|
|
1309
|
+
* @param ctx the parse tree
|
|
1310
|
+
*/
|
|
1311
|
+
exitImportSelect?: (ctx: ImportSelectContext) => void;
|
|
1312
|
+
/**
|
|
1313
|
+
* Enter a parse tree produced by `MalloyParser.importItem`.
|
|
1314
|
+
* @param ctx the parse tree
|
|
1315
|
+
*/
|
|
1316
|
+
enterImportItem?: (ctx: ImportItemContext) => void;
|
|
1317
|
+
/**
|
|
1318
|
+
* Exit a parse tree produced by `MalloyParser.importItem`.
|
|
1319
|
+
* @param ctx the parse tree
|
|
1320
|
+
*/
|
|
1321
|
+
exitImportItem?: (ctx: ImportItemContext) => void;
|
|
1300
1322
|
/**
|
|
1301
1323
|
* Enter a parse tree produced by `MalloyParser.importURL`.
|
|
1302
1324
|
* @param ctx the parse tree
|
|
@@ -92,6 +92,8 @@ import { BlockSQLDefContext } from "./MalloyParser";
|
|
|
92
92
|
import { SqlStringContext } from "./MalloyParser";
|
|
93
93
|
import { SqlInterpolationContext } from "./MalloyParser";
|
|
94
94
|
import { ImportStatementContext } from "./MalloyParser";
|
|
95
|
+
import { ImportSelectContext } from "./MalloyParser";
|
|
96
|
+
import { ImportItemContext } from "./MalloyParser";
|
|
95
97
|
import { ImportURLContext } from "./MalloyParser";
|
|
96
98
|
import { DocAnnotationsContext } from "./MalloyParser";
|
|
97
99
|
import { IgnoredObjectAnnotationsContext } from "./MalloyParser";
|
|
@@ -849,6 +851,18 @@ export interface MalloyParserVisitor<Result> extends ParseTreeVisitor<Result> {
|
|
|
849
851
|
* @return the visitor result
|
|
850
852
|
*/
|
|
851
853
|
visitImportStatement?: (ctx: ImportStatementContext) => Result;
|
|
854
|
+
/**
|
|
855
|
+
* Visit a parse tree produced by `MalloyParser.importSelect`.
|
|
856
|
+
* @param ctx the parse tree
|
|
857
|
+
* @return the visitor result
|
|
858
|
+
*/
|
|
859
|
+
visitImportSelect?: (ctx: ImportSelectContext) => Result;
|
|
860
|
+
/**
|
|
861
|
+
* Visit a parse tree produced by `MalloyParser.importItem`.
|
|
862
|
+
* @param ctx the parse tree
|
|
863
|
+
* @return the visitor result
|
|
864
|
+
*/
|
|
865
|
+
visitImportItem?: (ctx: ImportItemContext) => Result;
|
|
852
866
|
/**
|
|
853
867
|
* Visit a parse tree produced by `MalloyParser.importURL`.
|
|
854
868
|
* @param ctx the parse tree
|
|
@@ -303,6 +303,10 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
|
|
|
303
303
|
const source = this.visitUnextendableSource(pcx.unextendableSource());
|
|
304
304
|
const query = new ast.FullQuery(source);
|
|
305
305
|
query.turtleName = this.getFieldName(pcx);
|
|
306
|
+
const idTxt = pcx.id().text;
|
|
307
|
+
if (this.m4WarningsEnabled() && pcx.ARROW()) {
|
|
308
|
+
this.contextError(pcx, `Use '.${idTxt}' instead of '->${idTxt}' to reference the query contained in the source`, 'warn');
|
|
309
|
+
}
|
|
306
310
|
return this.astAt(query, pcx);
|
|
307
311
|
}
|
|
308
312
|
visitQueryByName(pcx) {
|
|
@@ -1199,7 +1203,18 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
|
|
|
1199
1203
|
}
|
|
1200
1204
|
visitImportStatement(pcx) {
|
|
1201
1205
|
const url = this.getPlainString(pcx.importURL());
|
|
1202
|
-
|
|
1206
|
+
const importStmt = this.astAt(new ast.ImportStatement(url, this.parseInfo.sourceURL), pcx);
|
|
1207
|
+
const selectCx = pcx.importSelect();
|
|
1208
|
+
if (selectCx) {
|
|
1209
|
+
for (const item of selectCx.importItem()) {
|
|
1210
|
+
const ids = item.id();
|
|
1211
|
+
const oldName = ids[1]
|
|
1212
|
+
? this.astAt(new ast.ImportSourceName((0, parse_utils_1.idToStr)(ids[1])), ids[1])
|
|
1213
|
+
: undefined;
|
|
1214
|
+
importStmt.push(this.astAt(new ast.ImportSelect((0, parse_utils_1.idToStr)(ids[0]), oldName), ids[0]));
|
|
1215
|
+
}
|
|
1216
|
+
}
|
|
1217
|
+
return importStmt;
|
|
1203
1218
|
}
|
|
1204
1219
|
visitJustExpr(pcx) {
|
|
1205
1220
|
return this.getFieldExpr(pcx.fieldExpr());
|
|
@@ -35,6 +35,7 @@ export type HasID = ParserRuleContext & {
|
|
|
35
35
|
* @returns The indenftifier text
|
|
36
36
|
*/
|
|
37
37
|
export declare function getId(cx: HasID): string;
|
|
38
|
+
export declare function idToStr(cx: IdContext): string;
|
|
38
39
|
export declare function getOptionalId(cx: ParserRuleContext): string | undefined;
|
|
39
40
|
export declare function unIndent(parts: (string | unknown)[]): void;
|
|
40
41
|
export {};
|
package/dist/lang/parse-utils.js
CHANGED
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
23
23
|
*/
|
|
24
24
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
-
exports.unIndent = exports.getOptionalId = exports.getId = exports.parseString = exports.getStringParts = exports.getStringIfShort = exports.getShortString = void 0;
|
|
25
|
+
exports.unIndent = exports.getOptionalId = exports.idToStr = exports.getId = exports.parseString = exports.getStringParts = exports.getStringIfShort = exports.getShortString = void 0;
|
|
26
26
|
/**
|
|
27
27
|
* Take the text of a matched string, including the matching quote
|
|
28
28
|
* characters, and return the actual contents of the string after
|
|
@@ -152,13 +152,17 @@ exports.parseString = parseString;
|
|
|
152
152
|
* @returns The indenftifier text
|
|
153
153
|
*/
|
|
154
154
|
function getId(cx) {
|
|
155
|
-
|
|
155
|
+
return idToStr(cx.id());
|
|
156
|
+
}
|
|
157
|
+
exports.getId = getId;
|
|
158
|
+
function idToStr(cx) {
|
|
159
|
+
const quoted = cx.BQ_STRING();
|
|
156
160
|
if (quoted) {
|
|
157
161
|
return parseString(quoted.text, '`');
|
|
158
162
|
}
|
|
159
|
-
return cx.
|
|
163
|
+
return cx.text;
|
|
160
164
|
}
|
|
161
|
-
exports.
|
|
165
|
+
exports.idToStr = idToStr;
|
|
162
166
|
function getOptionalId(cx) {
|
|
163
167
|
function containsID(cx) {
|
|
164
168
|
return 'id' in cx;
|
|
@@ -159,5 +159,71 @@ source: botProjQSrc is from(->botProjQ)
|
|
|
159
159
|
}
|
|
160
160
|
}
|
|
161
161
|
});
|
|
162
|
+
test('selective import of source', () => {
|
|
163
|
+
const docParse = new test_translator_1.TestTranslator('import { bb } from "child"');
|
|
164
|
+
const xr = docParse.unresolved();
|
|
165
|
+
expect(docParse).toParse();
|
|
166
|
+
expect(xr).toEqual({ urls: ['internal://test/langtests/child'] });
|
|
167
|
+
docParse.update({
|
|
168
|
+
urls: {
|
|
169
|
+
'internal://test/langtests/child': 'source: aa is a; source: bb is a',
|
|
170
|
+
},
|
|
171
|
+
});
|
|
172
|
+
expect(docParse).toTranslate();
|
|
173
|
+
const bb = docParse.getSourceDef('bb');
|
|
174
|
+
expect(bb).toBeDefined();
|
|
175
|
+
const aa = docParse.getSourceDef('aa');
|
|
176
|
+
expect(aa).toBeUndefined();
|
|
177
|
+
});
|
|
178
|
+
test('renaming import of source', () => {
|
|
179
|
+
const docParse = new test_translator_1.TestTranslator('import { bb is aa } from "child"');
|
|
180
|
+
const xr = docParse.unresolved();
|
|
181
|
+
expect(docParse).toParse();
|
|
182
|
+
expect(xr).toEqual({ urls: ['internal://test/langtests/child'] });
|
|
183
|
+
docParse.update({
|
|
184
|
+
urls: { 'internal://test/langtests/child': 'source: aa is a' },
|
|
185
|
+
});
|
|
186
|
+
expect(docParse).toTranslate();
|
|
187
|
+
const bb = docParse.getSourceDef('bb');
|
|
188
|
+
expect(bb).toBeDefined();
|
|
189
|
+
});
|
|
190
|
+
test('selective import of source, not found', () => {
|
|
191
|
+
const doc = (0, test_translator_1.model) `import { ${'bb'} } from "child"`;
|
|
192
|
+
const xr = doc.translator.unresolved();
|
|
193
|
+
expect(doc).toParse();
|
|
194
|
+
expect(xr).toEqual({ urls: ['internal://test/langtests/child'] });
|
|
195
|
+
doc.translator.update({
|
|
196
|
+
urls: {
|
|
197
|
+
'internal://test/langtests/child': 'source: aa is a',
|
|
198
|
+
},
|
|
199
|
+
});
|
|
200
|
+
expect(doc.translator).translationToFailWith("Cannot find 'bb', not imported");
|
|
201
|
+
});
|
|
202
|
+
test('selective renamed import of source, not found', () => {
|
|
203
|
+
const doc = (0, test_translator_1.model) `import { cc is ${'bb'} } from "child"`;
|
|
204
|
+
const xr = doc.translator.unresolved();
|
|
205
|
+
expect(doc).toParse();
|
|
206
|
+
expect(xr).toEqual({ urls: ['internal://test/langtests/child'] });
|
|
207
|
+
doc.translator.update({
|
|
208
|
+
urls: {
|
|
209
|
+
'internal://test/langtests/child': 'source: aa is a',
|
|
210
|
+
},
|
|
211
|
+
});
|
|
212
|
+
expect(doc.translator).translationToFailWith("Cannot find 'bb', not imported");
|
|
213
|
+
});
|
|
214
|
+
test('selective import of source, no-redefinition', () => {
|
|
215
|
+
const doc = (0, test_translator_1.model) `
|
|
216
|
+
import { cc is ${'bb'} } from "child"
|
|
217
|
+
import { cc is ${'bb'} } from "child"`;
|
|
218
|
+
const xr = doc.translator.unresolved();
|
|
219
|
+
expect(doc).toParse();
|
|
220
|
+
expect(xr).toEqual({ urls: ['internal://test/langtests/child'] });
|
|
221
|
+
doc.translator.update({
|
|
222
|
+
urls: {
|
|
223
|
+
'internal://test/langtests/child': 'source: bb is a',
|
|
224
|
+
},
|
|
225
|
+
});
|
|
226
|
+
expect(doc.translator).translationToFailWith("Cannot redefine 'cc'");
|
|
227
|
+
});
|
|
162
228
|
});
|
|
163
229
|
//# sourceMappingURL=imports.spec.js.map
|
|
@@ -64,17 +64,22 @@ describe('query:', () => {
|
|
|
64
64
|
test('from(query) refined into query', () => {
|
|
65
65
|
expect('query: from(ab -> {group_by: astr}) { dimension: bigstr is upper(astr) } -> { group_by: bigstr }').toTranslate();
|
|
66
66
|
});
|
|
67
|
+
test('arrow turtle geenrates m4 warning', () => {
|
|
68
|
+
expect(`##! m4warnings
|
|
69
|
+
run: ab -> aturtle
|
|
70
|
+
`).toTranslateWithWarnings("Use '.aturtle' instead of '->aturtle' to reference the query contained in the source");
|
|
71
|
+
});
|
|
67
72
|
test('query with shortcut filtered turtle', () => {
|
|
68
|
-
expect("query: allA is ab
|
|
73
|
+
expect("query: allA is ab.aturtle {? astr ~ 'a%' }").toTranslate();
|
|
69
74
|
});
|
|
70
75
|
test('query with shortcut filtered turtle m4warning', () => {
|
|
71
76
|
expect(`
|
|
72
77
|
##! m4warnings
|
|
73
|
-
query: allA is ab
|
|
78
|
+
query: allA is ab.aturtle refine {? astr ~ 'a%' }
|
|
74
79
|
`).toTranslateWithWarnings('Filter shortcut `{? condition }` is deprecated; use `{ where: condition } instead');
|
|
75
80
|
});
|
|
76
81
|
test('query with filtered turtle', () => {
|
|
77
|
-
expect("query: allA is ab
|
|
82
|
+
expect("query: allA is ab.aturtle { where: astr ~ 'a%' }").toTranslate();
|
|
78
83
|
});
|
|
79
84
|
test('nest: in group_by:', () => {
|
|
80
85
|
expect(`
|
|
@@ -903,7 +908,7 @@ describe('query:', () => {
|
|
|
903
908
|
declare: aratio is ai / acount
|
|
904
909
|
}
|
|
905
910
|
}
|
|
906
|
-
query: nab
|
|
911
|
+
query: nab.xturtle + { aggregate: aratio }
|
|
907
912
|
`);
|
|
908
913
|
expect(m).toTranslate();
|
|
909
914
|
const t = m.translate();
|
|
@@ -925,7 +930,7 @@ describe('query:', () => {
|
|
|
925
930
|
});
|
|
926
931
|
test('refine query source with field', () => {
|
|
927
932
|
const m = new test_translator_1.TestTranslator(`
|
|
928
|
-
query: ab
|
|
933
|
+
query: ab.aturtle + {
|
|
929
934
|
declare: aratio is ai / acount
|
|
930
935
|
aggregate: aratio
|
|
931
936
|
}
|
|
@@ -949,7 +954,7 @@ describe('query:', () => {
|
|
|
949
954
|
});
|
|
950
955
|
test('refine query source with join', () => {
|
|
951
956
|
const m = new test_translator_1.TestTranslator(`
|
|
952
|
-
query: ab
|
|
957
|
+
query: ab.aturtle + {
|
|
953
958
|
join_one: bb is b on bb.astr = astr
|
|
954
959
|
group_by: foo is bb.astr
|
|
955
960
|
}
|