@malloydata/malloy 0.0.240-dev250311202829 → 0.0.240-dev250311214430
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/api/core.d.ts +1 -0
- package/dist/api/core.js +2 -1
- package/dist/lang/malloy-parse-info.d.ts +2 -10
- package/dist/lang/malloy-to-ast.d.ts +1 -0
- package/dist/lang/malloy-to-ast.js +9 -6
- package/dist/lang/malloy-to-stable-query.d.ts +76 -0
- package/dist/lang/malloy-to-stable-query.js +660 -0
- package/dist/lang/parse-log.d.ts +1 -0
- package/dist/lang/parse-malloy.d.ts +2 -9
- package/dist/lang/parse-malloy.js +7 -112
- package/dist/lang/parse-tree-walkers/model-annotation-walker.js +1 -1
- package/dist/lang/run-malloy-parser.d.ts +3 -0
- package/dist/lang/run-malloy-parser.js +53 -0
- package/dist/lang/syntax-errors/malloy-parser-error-listener.d.ts +4 -3
- package/dist/lang/syntax-errors/malloy-parser-error-listener.js +8 -4
- package/dist/lang/utils.d.ts +27 -1
- package/dist/lang/utils.js +78 -1
- package/package.json +3 -3
- package/dist/api/asynchronous.spec.d.ts +0 -1
- package/dist/api/asynchronous.spec.js +0 -240
- package/dist/api/sessioned.spec.d.ts +0 -1
- package/dist/api/sessioned.spec.js +0 -476
- package/dist/api/stateless.spec.d.ts +0 -1
- package/dist/api/stateless.spec.js +0 -400
- package/dist/lang/test/annotation.spec.d.ts +0 -14
- package/dist/lang/test/annotation.spec.js +0 -809
- package/dist/lang/test/composite-field-usage.spec.d.ts +0 -1
- package/dist/lang/test/composite-field-usage.spec.js +0 -261
- package/dist/lang/test/document-help-context-walker.spec.d.ts +0 -1
- package/dist/lang/test/document-help-context-walker.spec.js +0 -55
- package/dist/lang/test/document-symbol-walker.spec.d.ts +0 -1
- package/dist/lang/test/document-symbol-walker.spec.js +0 -209
- package/dist/lang/test/expressions.spec.d.ts +0 -1
- package/dist/lang/test/expressions.spec.js +0 -1181
- package/dist/lang/test/field-symbols.spec.d.ts +0 -1
- package/dist/lang/test/field-symbols.spec.js +0 -194
- package/dist/lang/test/find-table-path-walker.spec.d.ts +0 -1
- package/dist/lang/test/find-table-path-walker.spec.js +0 -50
- package/dist/lang/test/imports.spec.d.ts +0 -1
- package/dist/lang/test/imports.spec.js +0 -283
- package/dist/lang/test/lenses.spec.d.ts +0 -1
- package/dist/lang/test/lenses.spec.js +0 -384
- package/dist/lang/test/literals.spec.d.ts +0 -1
- package/dist/lang/test/literals.spec.js +0 -267
- package/dist/lang/test/locations.spec.d.ts +0 -1
- package/dist/lang/test/locations.spec.js +0 -679
- package/dist/lang/test/model-annotation-walker.spec.d.ts +0 -1
- package/dist/lang/test/model-annotation-walker.spec.js +0 -46
- package/dist/lang/test/model_serialization.spec.d.ts +0 -5
- package/dist/lang/test/model_serialization.spec.js +0 -116
- package/dist/lang/test/parameters.spec.d.ts +0 -1
- package/dist/lang/test/parameters.spec.js +0 -619
- package/dist/lang/test/parse.spec.d.ts +0 -1
- package/dist/lang/test/parse.spec.js +0 -893
- package/dist/lang/test/pretranslate.spec.d.ts +0 -1
- package/dist/lang/test/pretranslate.spec.js +0 -80
- package/dist/lang/test/query.spec.d.ts +0 -1
- package/dist/lang/test/query.spec.js +0 -1149
- package/dist/lang/test/source.spec.d.ts +0 -1
- package/dist/lang/test/source.spec.js +0 -570
- package/dist/lang/test/sql-block.spec.d.ts +0 -1
- package/dist/lang/test/sql-block.spec.js +0 -145
- package/dist/lang/test/syntax-errors.spec.d.ts +0 -1
- package/dist/lang/test/syntax-errors.spec.js +0 -142
- package/dist/model/utils.spec.d.ts +0 -1
- package/dist/model/utils.spec.js +0 -38
|
@@ -46,10 +46,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
46
46
|
};
|
|
47
47
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
48
48
|
exports.MalloyTranslator = exports.MalloyChildTranslator = exports.MalloyTranslation = void 0;
|
|
49
|
-
const antlr4ts_1 = require("antlr4ts");
|
|
50
49
|
const malloy_types_1 = require("../model/malloy_types");
|
|
51
|
-
const MalloyLexer_1 = require("./lib/Malloy/MalloyLexer");
|
|
52
|
-
const MalloyParser_1 = require("./lib/Malloy/MalloyParser");
|
|
53
50
|
const ast = __importStar(require("./ast"));
|
|
54
51
|
const malloy_to_ast_1 = require("./malloy-to-ast");
|
|
55
52
|
const parse_log_1 = require("./parse-log");
|
|
@@ -65,20 +62,7 @@ const malloy_tag_1 = require("@malloydata/malloy-tag");
|
|
|
65
62
|
const model_annotation_walker_1 = require("./parse-tree-walkers/model-annotation-walker");
|
|
66
63
|
const find_table_path_walker_1 = require("./parse-tree-walkers/find-table-path-walker");
|
|
67
64
|
const annotation_1 = require("../annotation");
|
|
68
|
-
const
|
|
69
|
-
const malloy_parser_error_listener_1 = require("./syntax-errors/malloy-parser-error-listener");
|
|
70
|
-
/**
|
|
71
|
-
* This ignores a -> popMode when the mode stack is empty, which is a hack,
|
|
72
|
-
* but it let's us parse }%
|
|
73
|
-
*/
|
|
74
|
-
class HandlesOverpoppingLexer extends MalloyLexer_1.MalloyLexer {
|
|
75
|
-
popMode() {
|
|
76
|
-
if (this._modeStack.isEmpty) {
|
|
77
|
-
return this._mode;
|
|
78
|
-
}
|
|
79
|
-
return super.popMode();
|
|
80
|
-
}
|
|
81
|
-
}
|
|
65
|
+
const run_malloy_parser_1 = require("./run-malloy-parser");
|
|
82
66
|
class ParseStep {
|
|
83
67
|
step(that) {
|
|
84
68
|
if (this.response) {
|
|
@@ -101,10 +85,10 @@ class ParseStep {
|
|
|
101
85
|
return { urls: [that.sourceURL] };
|
|
102
86
|
}
|
|
103
87
|
const source = srcEnt.value === '' ? '\n' : srcEnt.value;
|
|
104
|
-
this.sourceInfo =
|
|
88
|
+
this.sourceInfo = (0, utils_1.getSourceInfo)(source);
|
|
105
89
|
let parse;
|
|
106
90
|
try {
|
|
107
|
-
parse = this.runParser(source, that);
|
|
91
|
+
parse = this.runParser(source, this.sourceInfo, that);
|
|
108
92
|
}
|
|
109
93
|
catch (parseException) {
|
|
110
94
|
that.root.logError('parse-exception', { message: parseException.message });
|
|
@@ -121,65 +105,11 @@ class ParseStep {
|
|
|
121
105
|
}
|
|
122
106
|
return this.response;
|
|
123
107
|
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
* to the line/char positions favored by LSP and VSCode.
|
|
127
|
-
*/
|
|
128
|
-
getSourceInfo(code) {
|
|
129
|
-
const eolRegex = /\r?\n/;
|
|
130
|
-
const info = {
|
|
131
|
-
at: [],
|
|
132
|
-
lines: [],
|
|
133
|
-
length: code.length,
|
|
134
|
-
};
|
|
135
|
-
let src = code;
|
|
136
|
-
let lineStart = 0;
|
|
137
|
-
while (src !== '') {
|
|
138
|
-
const eol = src.match(eolRegex);
|
|
139
|
-
if (eol && eol.index !== undefined) {
|
|
140
|
-
// line text DOES NOT include the EOL
|
|
141
|
-
info.lines.push(src.slice(0, eol.index));
|
|
142
|
-
const lineLength = eol.index + eol[0].length;
|
|
143
|
-
info.at.push({
|
|
144
|
-
begin: lineStart,
|
|
145
|
-
end: lineStart + lineLength,
|
|
146
|
-
});
|
|
147
|
-
lineStart += lineLength;
|
|
148
|
-
src = src.slice(lineLength);
|
|
149
|
-
}
|
|
150
|
-
else {
|
|
151
|
-
// last line, does not have a line end
|
|
152
|
-
info.lines.push(src);
|
|
153
|
-
info.at.push({ begin: lineStart, end: lineStart + src.length });
|
|
154
|
-
break;
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
return info;
|
|
158
|
-
}
|
|
159
|
-
runParser(source, that) {
|
|
160
|
-
const inputStream = antlr4ts_1.CharStreams.fromString(source);
|
|
161
|
-
const lexer = new HandlesOverpoppingLexer(inputStream);
|
|
162
|
-
const tokenStream = new antlr4ts_1.CommonTokenStream(lexer);
|
|
163
|
-
const malloyParser = new MalloyParser_1.MalloyParser(tokenStream);
|
|
164
|
-
malloyParser.removeErrorListeners();
|
|
165
|
-
malloyParser.addErrorListener(new malloy_parser_error_listener_1.MalloyParserErrorListener(that, that.root.logger));
|
|
166
|
-
malloyParser.errorHandler = new malloy_error_strategy_1.MalloyErrorStrategy();
|
|
167
|
-
// Admitted code smell here, testing likes to parse from an arbitrary
|
|
168
|
-
// node and this is the simplest way to allow that.
|
|
169
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
170
|
-
const parseFunc = malloyParser[that.grammarRule];
|
|
171
|
-
if (!parseFunc) {
|
|
172
|
-
throw new Error(`No such parse rule as ${that.grammarRule}`);
|
|
173
|
-
}
|
|
108
|
+
runParser(source, sourceInfo, that) {
|
|
109
|
+
const parse = (0, run_malloy_parser_1.runMalloyParser)(source, that.sourceURL, sourceInfo, that.root.logger, that.grammarRule);
|
|
174
110
|
return {
|
|
175
|
-
|
|
176
|
-
tokenStream: tokenStream,
|
|
177
|
-
sourceStream: inputStream,
|
|
178
|
-
sourceURL: that.sourceURL,
|
|
111
|
+
...parse,
|
|
179
112
|
importBaseURL: that.importBaseURL || that.sourceURL,
|
|
180
|
-
rangeFromContext: cx => that.rangeFromContext(cx),
|
|
181
|
-
// TODO some way to not forget to update this
|
|
182
|
-
malloyVersion: '4.0.0',
|
|
183
113
|
};
|
|
184
114
|
}
|
|
185
115
|
}
|
|
@@ -786,42 +716,7 @@ class MalloyTranslation {
|
|
|
786
716
|
};
|
|
787
717
|
}
|
|
788
718
|
rangeFromContext(pcx) {
|
|
789
|
-
return
|
|
790
|
-
}
|
|
791
|
-
rangeFromTokens(startToken, stopToken) {
|
|
792
|
-
const start = {
|
|
793
|
-
line: startToken.line - 1,
|
|
794
|
-
character: startToken.charPositionInLine,
|
|
795
|
-
};
|
|
796
|
-
if (this.parseStep.sourceInfo && stopToken.stopIndex !== -1) {
|
|
797
|
-
// Find the line which contains the stopIndex
|
|
798
|
-
const lastLine = this.parseStep.sourceInfo.lines.length - 1;
|
|
799
|
-
for (let lineNo = startToken.line - 1; lineNo <= lastLine; lineNo++) {
|
|
800
|
-
const at = this.parseStep.sourceInfo.at[lineNo];
|
|
801
|
-
if (stopToken.stopIndex >= at.begin && stopToken.stopIndex < at.end) {
|
|
802
|
-
return {
|
|
803
|
-
start,
|
|
804
|
-
end: {
|
|
805
|
-
line: lineNo,
|
|
806
|
-
character: stopToken.stopIndex - at.begin + 1,
|
|
807
|
-
},
|
|
808
|
-
};
|
|
809
|
-
}
|
|
810
|
-
}
|
|
811
|
-
// Should be impossible to get here, but if we do ... return the last
|
|
812
|
-
// character of the last line of the file
|
|
813
|
-
return {
|
|
814
|
-
start,
|
|
815
|
-
end: {
|
|
816
|
-
line: lastLine,
|
|
817
|
-
character: this.parseStep.sourceInfo.lines[lastLine].length,
|
|
818
|
-
},
|
|
819
|
-
};
|
|
820
|
-
}
|
|
821
|
-
return { start, end: start };
|
|
822
|
-
}
|
|
823
|
-
rangeFromToken(token) {
|
|
824
|
-
return this.rangeFromTokens(token, token);
|
|
719
|
+
return (0, utils_1.rangeFromContext)(this.parseStep.sourceInfo, pcx);
|
|
825
720
|
}
|
|
826
721
|
firstReferenceToDialect(dialect) {
|
|
827
722
|
if (this.dialectAlreadyChecked[dialect]) {
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.runMalloyParser = void 0;
|
|
10
|
+
const antlr4ts_1 = require("antlr4ts");
|
|
11
|
+
const MalloyLexer_1 = require("./lib/Malloy/MalloyLexer");
|
|
12
|
+
const MalloyParser_1 = require("./lib/Malloy/MalloyParser");
|
|
13
|
+
const malloy_error_strategy_1 = require("./syntax-errors/malloy-error-strategy");
|
|
14
|
+
const malloy_parser_error_listener_1 = require("./syntax-errors/malloy-parser-error-listener");
|
|
15
|
+
/**
|
|
16
|
+
* This ignores a -> popMode when the mode stack is empty, which is a hack,
|
|
17
|
+
* but it let's us parse }%
|
|
18
|
+
*/
|
|
19
|
+
class HandlesOverpoppingLexer extends MalloyLexer_1.MalloyLexer {
|
|
20
|
+
popMode() {
|
|
21
|
+
if (this._modeStack.isEmpty) {
|
|
22
|
+
return this._mode;
|
|
23
|
+
}
|
|
24
|
+
return super.popMode();
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function runMalloyParser(code, sourceURL, sourceInfo, logger, grammarRule = 'malloyDocument') {
|
|
28
|
+
const inputStream = antlr4ts_1.CharStreams.fromString(code);
|
|
29
|
+
const lexer = new HandlesOverpoppingLexer(inputStream);
|
|
30
|
+
const tokenStream = new antlr4ts_1.CommonTokenStream(lexer);
|
|
31
|
+
const malloyParser = new MalloyParser_1.MalloyParser(tokenStream);
|
|
32
|
+
malloyParser.removeErrorListeners();
|
|
33
|
+
malloyParser.addErrorListener(new malloy_parser_error_listener_1.MalloyParserErrorListener(logger, sourceURL, sourceInfo));
|
|
34
|
+
malloyParser.errorHandler = new malloy_error_strategy_1.MalloyErrorStrategy();
|
|
35
|
+
// Admitted code smell here, testing likes to parse from an arbitrary
|
|
36
|
+
// node and this is the simplest way to allow that.
|
|
37
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
38
|
+
const parseFunc = malloyParser[grammarRule];
|
|
39
|
+
if (!parseFunc) {
|
|
40
|
+
throw new Error(`No such parse rule as ${grammarRule}`);
|
|
41
|
+
}
|
|
42
|
+
return {
|
|
43
|
+
root: parseFunc.call(malloyParser),
|
|
44
|
+
tokenStream: tokenStream,
|
|
45
|
+
sourceStream: inputStream,
|
|
46
|
+
sourceInfo,
|
|
47
|
+
sourceURL,
|
|
48
|
+
// TODO some way to not forget to update this
|
|
49
|
+
malloyVersion: '4.0.0',
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
exports.runMalloyParser = runMalloyParser;
|
|
53
|
+
//# sourceMappingURL=run-malloy-parser.js.map
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { ANTLRErrorListener, Token } from 'antlr4ts';
|
|
2
2
|
import { ErrorCase } from './custom-error-messages';
|
|
3
3
|
import { MessageLogger, MessageCode, MessageParameterType, LogMessageOptions } from '../parse-log';
|
|
4
|
-
import {
|
|
4
|
+
import { SourceInfo } from '../utils';
|
|
5
5
|
export declare const malloyCustomErrorCases: ErrorCase[];
|
|
6
6
|
export declare class MalloyParserErrorListener implements ANTLRErrorListener<Token> {
|
|
7
|
-
readonly translator: MalloyTranslation;
|
|
8
7
|
readonly messages: MessageLogger;
|
|
9
|
-
|
|
8
|
+
readonly sourceURL: string;
|
|
9
|
+
readonly sourceInfo: SourceInfo;
|
|
10
|
+
constructor(messages: MessageLogger, sourceURL: string, sourceInfo: SourceInfo);
|
|
10
11
|
logError<T extends MessageCode>(code: T, parameters: MessageParameterType<T>, options?: Omit<LogMessageOptions, 'severity'>): T;
|
|
11
12
|
syntaxError(recognizer: unknown, offendingSymbol: Token | undefined, line: number, charPositionInLine: number, message: string, _e: unknown): void;
|
|
12
13
|
}
|
|
@@ -10,6 +10,7 @@ exports.MalloyParserErrorListener = exports.malloyCustomErrorCases = void 0;
|
|
|
10
10
|
const MalloyParser_1 = require("../lib/Malloy/MalloyParser");
|
|
11
11
|
const custom_error_messages_1 = require("./custom-error-messages");
|
|
12
12
|
const parse_log_1 = require("../parse-log");
|
|
13
|
+
const utils_1 = require("../utils");
|
|
13
14
|
// A set of custom error messages and their triggering cases,
|
|
14
15
|
// used for syntax error message re-writing when ANTLR would
|
|
15
16
|
// otherwise print a standard (and not very useful) error message.
|
|
@@ -141,9 +142,12 @@ exports.malloyCustomErrorCases = [
|
|
|
141
142
|
},
|
|
142
143
|
];
|
|
143
144
|
class MalloyParserErrorListener {
|
|
144
|
-
constructor(
|
|
145
|
-
|
|
145
|
+
constructor(
|
|
146
|
+
// readonly translator: MalloyTranslation,
|
|
147
|
+
messages, sourceURL, sourceInfo) {
|
|
146
148
|
this.messages = messages;
|
|
149
|
+
this.sourceURL = sourceURL;
|
|
150
|
+
this.sourceInfo = sourceInfo;
|
|
147
151
|
}
|
|
148
152
|
logError(code, parameters, options) {
|
|
149
153
|
this.messages.log((0, parse_log_1.makeLogMessage)(code, parameters, { severity: 'error', ...options }));
|
|
@@ -152,14 +156,14 @@ class MalloyParserErrorListener {
|
|
|
152
156
|
syntaxError(recognizer, offendingSymbol, line, charPositionInLine, message, _e) {
|
|
153
157
|
const errAt = { line: line - 1, character: charPositionInLine };
|
|
154
158
|
const range = offendingSymbol
|
|
155
|
-
?
|
|
159
|
+
? (0, utils_1.rangeFromToken)(this.sourceInfo, offendingSymbol)
|
|
156
160
|
: { start: errAt, end: errAt };
|
|
157
161
|
const overrideMessage = (0, custom_error_messages_1.checkCustomErrorMessage)(recognizer, offendingSymbol, exports.malloyCustomErrorCases);
|
|
158
162
|
if (overrideMessage) {
|
|
159
163
|
message = overrideMessage;
|
|
160
164
|
}
|
|
161
165
|
this.logError('syntax-error', { message }, {
|
|
162
|
-
at: { url: this.
|
|
166
|
+
at: { url: this.sourceURL, range },
|
|
163
167
|
});
|
|
164
168
|
}
|
|
165
169
|
}
|
package/dist/lang/utils.d.ts
CHANGED
|
@@ -1,3 +1,29 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { CodePointCharStream, CommonTokenStream, ParserRuleContext, Token } from 'antlr4ts';
|
|
2
|
+
import { DocumentLocation, DocumentPosition, DocumentRange } from '../model/malloy_types';
|
|
3
|
+
import { ParseTree } from 'antlr4ts/tree';
|
|
2
4
|
export declare function locationContainsPosition(location: DocumentLocation, position: DocumentPosition): boolean;
|
|
3
5
|
export declare function isNotUndefined<T>(value: T | undefined): value is T;
|
|
6
|
+
export interface SourceInfo {
|
|
7
|
+
lines: string[];
|
|
8
|
+
at: {
|
|
9
|
+
begin: number;
|
|
10
|
+
end: number;
|
|
11
|
+
}[];
|
|
12
|
+
length: number;
|
|
13
|
+
}
|
|
14
|
+
export declare function rangeFromTokens(sourceInfo: SourceInfo | undefined, startToken: Token, stopToken: Token): DocumentRange;
|
|
15
|
+
export declare function rangeFromToken(sourceInfo: SourceInfo | undefined, token: Token): DocumentRange;
|
|
16
|
+
export declare function rangeFromContext(sourceInfo: SourceInfo | undefined, pcx: ParserRuleContext): DocumentRange;
|
|
17
|
+
/**
|
|
18
|
+
* Split the source up into lines so we can correctly compute offset
|
|
19
|
+
* to the line/char positions favored by LSP and VSCode.
|
|
20
|
+
*/
|
|
21
|
+
export declare function getSourceInfo(code: string): SourceInfo;
|
|
22
|
+
export interface ParseInfo {
|
|
23
|
+
root: ParseTree;
|
|
24
|
+
tokenStream: CommonTokenStream;
|
|
25
|
+
sourceStream: CodePointCharStream;
|
|
26
|
+
sourceURL: string;
|
|
27
|
+
malloyVersion: string;
|
|
28
|
+
sourceInfo: SourceInfo;
|
|
29
|
+
}
|
package/dist/lang/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.isNotUndefined = exports.locationContainsPosition = void 0;
|
|
25
|
+
exports.getSourceInfo = exports.rangeFromContext = exports.rangeFromToken = exports.rangeFromTokens = exports.isNotUndefined = exports.locationContainsPosition = void 0;
|
|
26
26
|
function locationContainsPosition(location, position) {
|
|
27
27
|
return (location.range.start.line <= position.line &&
|
|
28
28
|
location.range.end.line >= position.line &&
|
|
@@ -36,4 +36,81 @@ function isNotUndefined(value) {
|
|
|
36
36
|
return value !== undefined;
|
|
37
37
|
}
|
|
38
38
|
exports.isNotUndefined = isNotUndefined;
|
|
39
|
+
function rangeFromTokens(sourceInfo, startToken, stopToken) {
|
|
40
|
+
const start = {
|
|
41
|
+
line: startToken.line - 1,
|
|
42
|
+
character: startToken.charPositionInLine,
|
|
43
|
+
};
|
|
44
|
+
if (sourceInfo && stopToken.stopIndex !== -1) {
|
|
45
|
+
// Find the line which contains the stopIndex
|
|
46
|
+
const lastLine = sourceInfo.lines.length - 1;
|
|
47
|
+
for (let lineNo = startToken.line - 1; lineNo <= lastLine; lineNo++) {
|
|
48
|
+
const at = sourceInfo.at[lineNo];
|
|
49
|
+
if (stopToken.stopIndex >= at.begin && stopToken.stopIndex < at.end) {
|
|
50
|
+
return {
|
|
51
|
+
start,
|
|
52
|
+
end: {
|
|
53
|
+
line: lineNo,
|
|
54
|
+
character: stopToken.stopIndex - at.begin + 1,
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// Should be impossible to get here, but if we do ... return the last
|
|
60
|
+
// character of the last line of the file
|
|
61
|
+
return {
|
|
62
|
+
start,
|
|
63
|
+
end: {
|
|
64
|
+
line: lastLine,
|
|
65
|
+
character: sourceInfo.lines[lastLine].length,
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
return { start, end: start };
|
|
70
|
+
}
|
|
71
|
+
exports.rangeFromTokens = rangeFromTokens;
|
|
72
|
+
function rangeFromToken(sourceInfo, token) {
|
|
73
|
+
return rangeFromTokens(sourceInfo, token, token);
|
|
74
|
+
}
|
|
75
|
+
exports.rangeFromToken = rangeFromToken;
|
|
76
|
+
function rangeFromContext(sourceInfo, pcx) {
|
|
77
|
+
return rangeFromTokens(sourceInfo, pcx.start, pcx.stop || pcx.start);
|
|
78
|
+
}
|
|
79
|
+
exports.rangeFromContext = rangeFromContext;
|
|
80
|
+
/**
|
|
81
|
+
* Split the source up into lines so we can correctly compute offset
|
|
82
|
+
* to the line/char positions favored by LSP and VSCode.
|
|
83
|
+
*/
|
|
84
|
+
function getSourceInfo(code) {
|
|
85
|
+
const eolRegex = /\r?\n/;
|
|
86
|
+
const info = {
|
|
87
|
+
at: [],
|
|
88
|
+
lines: [],
|
|
89
|
+
length: code.length,
|
|
90
|
+
};
|
|
91
|
+
let src = code;
|
|
92
|
+
let lineStart = 0;
|
|
93
|
+
while (src !== '') {
|
|
94
|
+
const eol = src.match(eolRegex);
|
|
95
|
+
if (eol && eol.index !== undefined) {
|
|
96
|
+
// line text DOES NOT include the EOL
|
|
97
|
+
info.lines.push(src.slice(0, eol.index));
|
|
98
|
+
const lineLength = eol.index + eol[0].length;
|
|
99
|
+
info.at.push({
|
|
100
|
+
begin: lineStart,
|
|
101
|
+
end: lineStart + lineLength,
|
|
102
|
+
});
|
|
103
|
+
lineStart += lineLength;
|
|
104
|
+
src = src.slice(lineLength);
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
// last line, does not have a line end
|
|
108
|
+
info.lines.push(src);
|
|
109
|
+
info.at.push({ begin: lineStart, end: lineStart + src.length });
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return info;
|
|
114
|
+
}
|
|
115
|
+
exports.getSourceInfo = getSourceInfo;
|
|
39
116
|
//# sourceMappingURL=utils.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@malloydata/malloy",
|
|
3
|
-
"version": "0.0.240-
|
|
3
|
+
"version": "0.0.240-dev250311214430",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./dist/index.js",
|
|
@@ -41,8 +41,8 @@
|
|
|
41
41
|
"generate-version-file": "VERSION=$(npm pkg get version --workspaces=false | tr -d \\\")\necho \"// generated with 'generate-version-file' script; do not edit manually\\nexport const MALLOY_VERSION = '$VERSION';\" > src/version.ts"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@malloydata/malloy-interfaces": "^0.0.240-
|
|
45
|
-
"@malloydata/malloy-tag": "^0.0.240-
|
|
44
|
+
"@malloydata/malloy-interfaces": "^0.0.240-dev250311214430",
|
|
45
|
+
"@malloydata/malloy-tag": "^0.0.240-dev250311214430",
|
|
46
46
|
"antlr4ts": "^0.5.0-alpha.4",
|
|
47
47
|
"assert": "^2.0.0",
|
|
48
48
|
"jest-diff": "^29.6.2",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,240 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/*
|
|
3
|
-
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
4
|
-
*
|
|
5
|
-
* This source code is licensed under the MIT license found in the
|
|
6
|
-
* LICENSE file in the root directory of this source tree.
|
|
7
|
-
*/
|
|
8
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
-
const asynchronous_1 = require("./asynchronous");
|
|
10
|
-
describe('api', () => {
|
|
11
|
-
describe('compile model', () => {
|
|
12
|
-
test('compile model with table dependency', async () => {
|
|
13
|
-
const connection = {
|
|
14
|
-
dialectName: 'duckdb',
|
|
15
|
-
fetchSchemaForTable: async (_name) => {
|
|
16
|
-
return {
|
|
17
|
-
fields: [
|
|
18
|
-
{
|
|
19
|
-
kind: 'dimension',
|
|
20
|
-
name: 'carrier',
|
|
21
|
-
type: { kind: 'string_type' },
|
|
22
|
-
},
|
|
23
|
-
],
|
|
24
|
-
};
|
|
25
|
-
},
|
|
26
|
-
fetchSchemaForSQLQuery: async (_sql) => {
|
|
27
|
-
throw new Error('not implemented');
|
|
28
|
-
},
|
|
29
|
-
};
|
|
30
|
-
const urls = {
|
|
31
|
-
readURL: async (_url) => {
|
|
32
|
-
return "source: flights is connection.table('flights')";
|
|
33
|
-
},
|
|
34
|
-
};
|
|
35
|
-
const connections = {
|
|
36
|
-
lookupConnection: async (_name) => {
|
|
37
|
-
return connection;
|
|
38
|
-
},
|
|
39
|
-
};
|
|
40
|
-
const fetchers = {
|
|
41
|
-
urls,
|
|
42
|
-
connections,
|
|
43
|
-
};
|
|
44
|
-
const result = await (0, asynchronous_1.compileModel)({
|
|
45
|
-
model_url: 'file://test.malloy',
|
|
46
|
-
}, fetchers);
|
|
47
|
-
const expected = {
|
|
48
|
-
model: {
|
|
49
|
-
entries: [
|
|
50
|
-
{
|
|
51
|
-
kind: 'source',
|
|
52
|
-
name: 'flights',
|
|
53
|
-
schema: {
|
|
54
|
-
fields: [
|
|
55
|
-
{
|
|
56
|
-
kind: 'dimension',
|
|
57
|
-
name: 'carrier',
|
|
58
|
-
type: { kind: 'string_type' },
|
|
59
|
-
},
|
|
60
|
-
],
|
|
61
|
-
},
|
|
62
|
-
},
|
|
63
|
-
],
|
|
64
|
-
anonymous_queries: [],
|
|
65
|
-
},
|
|
66
|
-
};
|
|
67
|
-
expect(result).toMatchObject(expected);
|
|
68
|
-
});
|
|
69
|
-
});
|
|
70
|
-
describe('compile query', () => {
|
|
71
|
-
test('compile query with table dependency', async () => {
|
|
72
|
-
const connection = {
|
|
73
|
-
dialectName: 'duckdb',
|
|
74
|
-
fetchSchemaForTable: async (_name) => {
|
|
75
|
-
return {
|
|
76
|
-
fields: [
|
|
77
|
-
{
|
|
78
|
-
kind: 'dimension',
|
|
79
|
-
name: 'carrier',
|
|
80
|
-
type: { kind: 'string_type' },
|
|
81
|
-
},
|
|
82
|
-
],
|
|
83
|
-
};
|
|
84
|
-
},
|
|
85
|
-
fetchSchemaForSQLQuery: async (_sql) => {
|
|
86
|
-
throw new Error('not implemented');
|
|
87
|
-
},
|
|
88
|
-
};
|
|
89
|
-
const urls = {
|
|
90
|
-
readURL: async (_url) => {
|
|
91
|
-
return "source: flights is connection.table('flights')";
|
|
92
|
-
},
|
|
93
|
-
};
|
|
94
|
-
const connections = {
|
|
95
|
-
lookupConnection: async (_name) => {
|
|
96
|
-
return connection;
|
|
97
|
-
},
|
|
98
|
-
};
|
|
99
|
-
const fetchers = {
|
|
100
|
-
urls,
|
|
101
|
-
connections,
|
|
102
|
-
};
|
|
103
|
-
const result = await (0, asynchronous_1.compileQuery)({
|
|
104
|
-
model_url: 'file://test.malloy',
|
|
105
|
-
query: {
|
|
106
|
-
definition: {
|
|
107
|
-
kind: 'arrow',
|
|
108
|
-
source_reference: { name: 'flights' },
|
|
109
|
-
view: {
|
|
110
|
-
kind: 'segment',
|
|
111
|
-
operations: [
|
|
112
|
-
{
|
|
113
|
-
kind: 'group_by',
|
|
114
|
-
field: {
|
|
115
|
-
expression: { kind: 'field_reference', name: 'carrier' },
|
|
116
|
-
},
|
|
117
|
-
},
|
|
118
|
-
],
|
|
119
|
-
},
|
|
120
|
-
},
|
|
121
|
-
},
|
|
122
|
-
}, fetchers);
|
|
123
|
-
const expected = {
|
|
124
|
-
result: {
|
|
125
|
-
connection_name: 'connection',
|
|
126
|
-
sql: `SELECT \n\
|
|
127
|
-
base."carrier" as "carrier"
|
|
128
|
-
FROM flights as base
|
|
129
|
-
GROUP BY 1
|
|
130
|
-
ORDER BY 1 asc NULLS LAST
|
|
131
|
-
`,
|
|
132
|
-
schema: {
|
|
133
|
-
fields: [
|
|
134
|
-
{
|
|
135
|
-
kind: 'dimension',
|
|
136
|
-
name: 'carrier',
|
|
137
|
-
type: { kind: 'string_type' },
|
|
138
|
-
},
|
|
139
|
-
],
|
|
140
|
-
},
|
|
141
|
-
},
|
|
142
|
-
};
|
|
143
|
-
expect(result).toMatchObject(expected);
|
|
144
|
-
});
|
|
145
|
-
});
|
|
146
|
-
describe('run query', () => {
|
|
147
|
-
test('run query with table dependency', async () => {
|
|
148
|
-
const data = {
|
|
149
|
-
kind: 'array_cell',
|
|
150
|
-
array_value: [
|
|
151
|
-
{
|
|
152
|
-
kind: 'record_cell',
|
|
153
|
-
record_value: [{ kind: 'string_cell', string_value: 'WN' }],
|
|
154
|
-
},
|
|
155
|
-
{
|
|
156
|
-
kind: 'record_cell',
|
|
157
|
-
record_value: [{ kind: 'string_cell', string_value: 'AA' }],
|
|
158
|
-
},
|
|
159
|
-
],
|
|
160
|
-
};
|
|
161
|
-
const connection = {
|
|
162
|
-
dialectName: 'duckdb',
|
|
163
|
-
fetchSchemaForTable: async (_name) => {
|
|
164
|
-
return {
|
|
165
|
-
fields: [
|
|
166
|
-
{
|
|
167
|
-
kind: 'dimension',
|
|
168
|
-
name: 'carrier',
|
|
169
|
-
type: { kind: 'string_type' },
|
|
170
|
-
},
|
|
171
|
-
],
|
|
172
|
-
};
|
|
173
|
-
},
|
|
174
|
-
fetchSchemaForSQLQuery: async (_sql) => {
|
|
175
|
-
throw new Error('not implemented');
|
|
176
|
-
},
|
|
177
|
-
runSQL: async (_sql) => {
|
|
178
|
-
return data;
|
|
179
|
-
},
|
|
180
|
-
};
|
|
181
|
-
const urls = {
|
|
182
|
-
readURL: async (_url) => {
|
|
183
|
-
return "source: flights is connection.table('flights')";
|
|
184
|
-
},
|
|
185
|
-
};
|
|
186
|
-
const connections = {
|
|
187
|
-
lookupConnection: async (_name) => {
|
|
188
|
-
return connection;
|
|
189
|
-
},
|
|
190
|
-
};
|
|
191
|
-
const fetchers = {
|
|
192
|
-
urls,
|
|
193
|
-
connections,
|
|
194
|
-
};
|
|
195
|
-
const result = await (0, asynchronous_1.runQuery)({
|
|
196
|
-
model_url: 'file://test.malloy',
|
|
197
|
-
query: {
|
|
198
|
-
definition: {
|
|
199
|
-
kind: 'arrow',
|
|
200
|
-
source_reference: { name: 'flights' },
|
|
201
|
-
view: {
|
|
202
|
-
kind: 'segment',
|
|
203
|
-
operations: [
|
|
204
|
-
{
|
|
205
|
-
kind: 'group_by',
|
|
206
|
-
field: {
|
|
207
|
-
expression: { kind: 'field_reference', name: 'carrier' },
|
|
208
|
-
},
|
|
209
|
-
},
|
|
210
|
-
],
|
|
211
|
-
},
|
|
212
|
-
},
|
|
213
|
-
},
|
|
214
|
-
}, fetchers);
|
|
215
|
-
const expected = {
|
|
216
|
-
result: {
|
|
217
|
-
connection_name: 'connection',
|
|
218
|
-
sql: `SELECT \n\
|
|
219
|
-
base."carrier" as "carrier"
|
|
220
|
-
FROM flights as base
|
|
221
|
-
GROUP BY 1
|
|
222
|
-
ORDER BY 1 asc NULLS LAST
|
|
223
|
-
`,
|
|
224
|
-
schema: {
|
|
225
|
-
fields: [
|
|
226
|
-
{
|
|
227
|
-
kind: 'dimension',
|
|
228
|
-
name: 'carrier',
|
|
229
|
-
type: { kind: 'string_type' },
|
|
230
|
-
},
|
|
231
|
-
],
|
|
232
|
-
},
|
|
233
|
-
data,
|
|
234
|
-
},
|
|
235
|
-
};
|
|
236
|
-
expect(result).toMatchObject(expected);
|
|
237
|
-
});
|
|
238
|
-
});
|
|
239
|
-
});
|
|
240
|
-
//# sourceMappingURL=asynchronous.spec.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|