@malloydata/malloy 0.0.236-dev250213234155 → 0.0.236-dev250219154103
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/lib/Malloy/MalloyParser.d.ts +6 -16
- package/dist/lang/lib/Malloy/MalloyParser.js +2217 -2329
- package/dist/lang/lib/Malloy/MalloyParserListener.d.ts +0 -11
- package/dist/lang/lib/Malloy/MalloyParserVisitor.d.ts +0 -7
- package/dist/lang/parse-malloy.d.ts +2 -9
- package/dist/lang/parse-malloy.js +5 -22
- package/dist/lang/syntax-errors/custom-error-messages.d.ts +10 -0
- package/dist/lang/syntax-errors/custom-error-messages.js +64 -0
- package/dist/lang/syntax-errors/malloy-error-strategy.d.ts +14 -0
- package/dist/lang/syntax-errors/malloy-error-strategy.js +42 -0
- package/dist/lang/syntax-errors/malloy-parser-error-listener.d.ts +12 -0
- package/dist/lang/syntax-errors/malloy-parser-error-listener.js +64 -0
- package/dist/lang/test/parse-expects.d.ts +1 -0
- package/dist/lang/test/parse-expects.js +7 -3
- package/dist/lang/test/parse.spec.js +1 -1
- package/dist/lang/test/syntax-errors.spec.d.ts +1 -0
- package/dist/lang/test/syntax-errors.spec.js +59 -0
- package/package.json +1 -1
|
@@ -236,7 +236,6 @@ import { ConnectionNameContext } from "./MalloyParser";
|
|
|
236
236
|
import { DebugExprContext } from "./MalloyParser";
|
|
237
237
|
import { DebugPartialContext } from "./MalloyParser";
|
|
238
238
|
import { ExperimentalStatementForTestingContext } from "./MalloyParser";
|
|
239
|
-
import { CloseCurlyContext } from "./MalloyParser";
|
|
240
239
|
/**
|
|
241
240
|
* This interface defines a complete listener for a parse tree produced by
|
|
242
241
|
* `MalloyParser`.
|
|
@@ -2784,14 +2783,4 @@ export interface MalloyParserListener extends ParseTreeListener {
|
|
|
2784
2783
|
* @param ctx the parse tree
|
|
2785
2784
|
*/
|
|
2786
2785
|
exitExperimentalStatementForTesting?: (ctx: ExperimentalStatementForTestingContext) => void;
|
|
2787
|
-
/**
|
|
2788
|
-
* Enter a parse tree produced by `MalloyParser.closeCurly`.
|
|
2789
|
-
* @param ctx the parse tree
|
|
2790
|
-
*/
|
|
2791
|
-
enterCloseCurly?: (ctx: CloseCurlyContext) => void;
|
|
2792
|
-
/**
|
|
2793
|
-
* Exit a parse tree produced by `MalloyParser.closeCurly`.
|
|
2794
|
-
* @param ctx the parse tree
|
|
2795
|
-
*/
|
|
2796
|
-
exitCloseCurly?: (ctx: CloseCurlyContext) => void;
|
|
2797
2786
|
}
|
|
@@ -236,7 +236,6 @@ import { ConnectionNameContext } from "./MalloyParser";
|
|
|
236
236
|
import { DebugExprContext } from "./MalloyParser";
|
|
237
237
|
import { DebugPartialContext } from "./MalloyParser";
|
|
238
238
|
import { ExperimentalStatementForTestingContext } from "./MalloyParser";
|
|
239
|
-
import { CloseCurlyContext } from "./MalloyParser";
|
|
240
239
|
/**
|
|
241
240
|
* This interface defines a complete generic visitor for a parse tree produced
|
|
242
241
|
* by `MalloyParser`.
|
|
@@ -1753,10 +1752,4 @@ export interface MalloyParserVisitor<Result> extends ParseTreeVisitor<Result> {
|
|
|
1753
1752
|
* @return the visitor result
|
|
1754
1753
|
*/
|
|
1755
1754
|
visitExperimentalStatementForTesting?: (ctx: ExperimentalStatementForTestingContext) => Result;
|
|
1756
|
-
/**
|
|
1757
|
-
* Visit a parse tree produced by `MalloyParser.closeCurly`.
|
|
1758
|
-
* @param ctx the parse tree
|
|
1759
|
-
* @return the visitor result
|
|
1760
|
-
*/
|
|
1761
|
-
visitCloseCurly?: (ctx: CloseCurlyContext) => Result;
|
|
1762
1755
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ParserRuleContext, Token } from 'antlr4ts';
|
|
2
2
|
import { DocumentLocation, DocumentPosition, DocumentRange, DocumentReference, ImportLocation, ModelDef, NamedModelObject, SourceDef, SQLSourceDef, DependencyTree } from '../model/malloy_types';
|
|
3
|
-
import { BaseMessageLogger, LogMessage, LogMessageOptions, MessageCode,
|
|
3
|
+
import { BaseMessageLogger, LogMessage, LogMessageOptions, MessageCode, MessageParameterType } from './parse-log';
|
|
4
4
|
import { Zone, ZoneData } from './zone';
|
|
5
5
|
import { ReferenceList } from './reference-list';
|
|
6
6
|
import { ASTResponse, CompletionsResponse, DataRequestResponse, ProblemResponse, FatalResponse, FinalResponse, HelpContextResponse, MetadataResponse, ModelDataRequest, NeedURLData, TranslateResponse, ModelAnnotationResponse, TablePathResponse } from './translate-response';
|
|
@@ -228,11 +228,4 @@ export interface UpdateData extends URLData, SchemaData, SQLSources, ModelData {
|
|
|
228
228
|
errors: Partial<ErrorData>;
|
|
229
229
|
}
|
|
230
230
|
export type ParseUpdate = Partial<UpdateData>;
|
|
231
|
-
export declare class MalloyParserErrorHandler implements ANTLRErrorListener<Token> {
|
|
232
|
-
readonly translator: MalloyTranslation;
|
|
233
|
-
readonly messages: MessageLogger;
|
|
234
|
-
constructor(translator: MalloyTranslation, messages: MessageLogger);
|
|
235
|
-
logError<T extends MessageCode>(code: T, parameters: MessageParameterType<T>, options?: Omit<LogMessageOptions, 'severity'>): T;
|
|
236
|
-
syntaxError(recognizer: unknown, offendingSymbol: Token | undefined, line: number, charPositionInLine: number, message: string, _e: unknown): void;
|
|
237
|
-
}
|
|
238
231
|
export {};
|
|
@@ -45,7 +45,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
45
45
|
return result;
|
|
46
46
|
};
|
|
47
47
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
48
|
-
exports.
|
|
48
|
+
exports.MalloyTranslator = exports.MalloyChildTranslator = exports.MalloyTranslation = void 0;
|
|
49
49
|
const antlr4ts_1 = require("antlr4ts");
|
|
50
50
|
const malloy_types_1 = require("../model/malloy_types");
|
|
51
51
|
const MalloyLexer_1 = require("./lib/Malloy/MalloyLexer");
|
|
@@ -64,6 +64,8 @@ const utils_1 = require("./utils");
|
|
|
64
64
|
const tags_1 = require("../tags");
|
|
65
65
|
const model_annotation_walker_1 = require("./parse-tree-walkers/model-annotation-walker");
|
|
66
66
|
const find_table_path_walker_1 = require("./parse-tree-walkers/find-table-path-walker");
|
|
67
|
+
const malloy_error_strategy_1 = require("./syntax-errors/malloy-error-strategy");
|
|
68
|
+
const malloy_parser_error_listener_1 = require("./syntax-errors/malloy-parser-error-listener");
|
|
67
69
|
/**
|
|
68
70
|
* This ignores a -> popMode when the mode stack is empty, which is a hack,
|
|
69
71
|
* but it let's us parse }%
|
|
@@ -159,7 +161,8 @@ class ParseStep {
|
|
|
159
161
|
const tokenStream = new antlr4ts_1.CommonTokenStream(lexer);
|
|
160
162
|
const malloyParser = new MalloyParser_1.MalloyParser(tokenStream);
|
|
161
163
|
malloyParser.removeErrorListeners();
|
|
162
|
-
malloyParser.addErrorListener(new
|
|
164
|
+
malloyParser.addErrorListener(new malloy_parser_error_listener_1.MalloyParserErrorListener(that, that.root.logger));
|
|
165
|
+
malloyParser.errorHandler = new malloy_error_strategy_1.MalloyErrorStrategy();
|
|
163
166
|
// Admitted code smell here, testing likes to parse from an arbitrary
|
|
164
167
|
// node and this is the simplest way to allow that.
|
|
165
168
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -883,26 +886,6 @@ class MalloyTranslator extends MalloyTranslation {
|
|
|
883
886
|
}
|
|
884
887
|
}
|
|
885
888
|
exports.MalloyTranslator = MalloyTranslator;
|
|
886
|
-
class MalloyParserErrorHandler {
|
|
887
|
-
constructor(translator, messages) {
|
|
888
|
-
this.translator = translator;
|
|
889
|
-
this.messages = messages;
|
|
890
|
-
}
|
|
891
|
-
logError(code, parameters, options) {
|
|
892
|
-
this.messages.log((0, parse_log_1.makeLogMessage)(code, parameters, { severity: 'error', ...options }));
|
|
893
|
-
return code;
|
|
894
|
-
}
|
|
895
|
-
syntaxError(recognizer, offendingSymbol, line, charPositionInLine, message, _e) {
|
|
896
|
-
const errAt = { line: line - 1, character: charPositionInLine };
|
|
897
|
-
const range = offendingSymbol
|
|
898
|
-
? this.translator.rangeFromToken(offendingSymbol)
|
|
899
|
-
: { start: errAt, end: errAt };
|
|
900
|
-
this.logError('syntax-error', { message }, {
|
|
901
|
-
at: { url: this.translator.sourceURL, range },
|
|
902
|
-
});
|
|
903
|
-
}
|
|
904
|
-
}
|
|
905
|
-
exports.MalloyParserErrorHandler = MalloyParserErrorHandler;
|
|
906
889
|
function flattenDependencyTree(dependencies) {
|
|
907
890
|
return [
|
|
908
891
|
...Object.keys(dependencies),
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Parser, Token } from 'antlr4ts';
|
|
2
|
+
export interface ErrorCase {
|
|
3
|
+
ruleContextOptions?: string[];
|
|
4
|
+
offendingSymbol?: number;
|
|
5
|
+
currentToken?: number;
|
|
6
|
+
precedingTokenOptions?: number[][];
|
|
7
|
+
lookAheadOptions?: number[][];
|
|
8
|
+
errorMessage: string;
|
|
9
|
+
}
|
|
10
|
+
export declare const checkCustomErrorMessage: (parser: Parser, offendingSymbol: Token | undefined, errorCases: ErrorCase[]) => string;
|
|
@@ -0,0 +1,64 @@
|
|
|
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.checkCustomErrorMessage = void 0;
|
|
10
|
+
const checkCustomErrorMessage = (parser, offendingSymbol, errorCases) => {
|
|
11
|
+
const currentRuleName = parser.getRuleInvocationStack()[0];
|
|
12
|
+
const currentToken = parser.currentToken;
|
|
13
|
+
for (const errorCase of errorCases) {
|
|
14
|
+
// Check to see if the initial conditions match
|
|
15
|
+
const isCurrentTokenMatch = !errorCase.currentToken || currentToken.type === errorCase.currentToken;
|
|
16
|
+
const isOffendingSymbolMatch = !errorCase.offendingSymbol ||
|
|
17
|
+
(offendingSymbol === null || offendingSymbol === void 0 ? void 0 : offendingSymbol.type) === errorCase.offendingSymbol;
|
|
18
|
+
const isRuleContextMatch = !errorCase.ruleContextOptions ||
|
|
19
|
+
errorCase.ruleContextOptions.includes(currentRuleName);
|
|
20
|
+
if (isCurrentTokenMatch && isOffendingSymbolMatch && isRuleContextMatch) {
|
|
21
|
+
// If so, try to check the preceding tokens.
|
|
22
|
+
if (errorCase.precedingTokenOptions) {
|
|
23
|
+
const hasPrecedingTokenMatch = errorCase.precedingTokenOptions.some(sequence => checkTokenSequenceMatch(parser, sequence, 'lookback'));
|
|
24
|
+
if (!hasPrecedingTokenMatch) {
|
|
25
|
+
continue; // Continue to check a different error case
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
if (errorCase.lookAheadOptions) {
|
|
29
|
+
const hasLookaheadTokenMatch = errorCase.lookAheadOptions.some(sequence => checkTokenSequenceMatch(parser, sequence, 'lookahead'));
|
|
30
|
+
if (!hasLookaheadTokenMatch) {
|
|
31
|
+
continue; // Continue to check a different error case
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
// If all cases match, return the custom error message
|
|
35
|
+
const message = errorCase.errorMessage.replace('${currentToken}', (offendingSymbol === null || offendingSymbol === void 0 ? void 0 : offendingSymbol.text) || currentToken.text || '');
|
|
36
|
+
return message;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return '';
|
|
40
|
+
};
|
|
41
|
+
exports.checkCustomErrorMessage = checkCustomErrorMessage;
|
|
42
|
+
const checkTokenSequenceMatch = (parser, sequence, direction) => {
|
|
43
|
+
try {
|
|
44
|
+
for (let i = 0; i < sequence.length; i++) {
|
|
45
|
+
// Note: positive lookahead starts at '2' because '1' is the current token.
|
|
46
|
+
const tokenIndex = direction === 'lookahead' ? i + 2 : -1 * (i + 1);
|
|
47
|
+
const streamToken = parser.inputStream.LA(tokenIndex);
|
|
48
|
+
// Note: negative checking is < -1 becuase Token.EOF is -1, but below
|
|
49
|
+
// that we use negatives to indicate "does-not-match" rules.
|
|
50
|
+
if (sequence[i] >= -1 && streamToken !== sequence[i]) {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
if (sequence[i] < -1 && streamToken === -1 * sequence[i]) {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
catch (ex) {
|
|
60
|
+
// There may not be enough lookback tokens. If so, the case doesn't match.
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
//# sourceMappingURL=custom-error-messages.js.map
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { DefaultErrorStrategy, Parser } from 'antlr4ts';
|
|
2
|
+
/**
|
|
3
|
+
* Custom error strategy for the Malloy Parser. This strategy attempts to
|
|
4
|
+
* detect known cases where the default error strategy results in an unhelpful
|
|
5
|
+
* parse tree or misleading messages. In any cases not explicitly handled, this
|
|
6
|
+
* custom error strategy will fall back to the default error strategy.
|
|
7
|
+
*
|
|
8
|
+
* For more details, read the documentation in DefaultErrorStrategy.d.ts
|
|
9
|
+
* or reference the superclass at:
|
|
10
|
+
* https://github.com/tunnelvisionlabs/antlr4ts/blob/master/src/DefaultErrorStrategy.ts
|
|
11
|
+
*/
|
|
12
|
+
export declare class MalloyErrorStrategy extends DefaultErrorStrategy {
|
|
13
|
+
sync(parser: Parser): void;
|
|
14
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
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.MalloyErrorStrategy = void 0;
|
|
10
|
+
const antlr4ts_1 = require("antlr4ts");
|
|
11
|
+
const MalloyParser_1 = require("../lib/Malloy/MalloyParser");
|
|
12
|
+
const custom_error_messages_1 = require("./custom-error-messages");
|
|
13
|
+
const customErrorCases = [
|
|
14
|
+
{
|
|
15
|
+
errorMessage: "Missing '{' after 'extend'",
|
|
16
|
+
currentToken: MalloyParser_1.MalloyParser.EXTEND,
|
|
17
|
+
ruleContextOptions: ['sqExpr'],
|
|
18
|
+
lookAheadOptions: [[-MalloyParser_1.MalloyParser.OCURLY]],
|
|
19
|
+
},
|
|
20
|
+
];
|
|
21
|
+
/**
|
|
22
|
+
* Custom error strategy for the Malloy Parser. This strategy attempts to
|
|
23
|
+
* detect known cases where the default error strategy results in an unhelpful
|
|
24
|
+
* parse tree or misleading messages. In any cases not explicitly handled, this
|
|
25
|
+
* custom error strategy will fall back to the default error strategy.
|
|
26
|
+
*
|
|
27
|
+
* For more details, read the documentation in DefaultErrorStrategy.d.ts
|
|
28
|
+
* or reference the superclass at:
|
|
29
|
+
* https://github.com/tunnelvisionlabs/antlr4ts/blob/master/src/DefaultErrorStrategy.ts
|
|
30
|
+
*/
|
|
31
|
+
class MalloyErrorStrategy extends antlr4ts_1.DefaultErrorStrategy {
|
|
32
|
+
sync(parser) {
|
|
33
|
+
const interceptedErrorMessage = (0, custom_error_messages_1.checkCustomErrorMessage)(parser, undefined, customErrorCases);
|
|
34
|
+
if (interceptedErrorMessage) {
|
|
35
|
+
parser.notifyErrorListeners(interceptedErrorMessage, parser.currentToken, undefined);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
super.sync(parser);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
exports.MalloyErrorStrategy = MalloyErrorStrategy;
|
|
42
|
+
//# sourceMappingURL=malloy-error-strategy.js.map
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { ANTLRErrorListener, Token } from 'antlr4ts';
|
|
2
|
+
import { ErrorCase } from './custom-error-messages';
|
|
3
|
+
import { MessageLogger, MessageCode, MessageParameterType, LogMessageOptions } from '../parse-log';
|
|
4
|
+
import { MalloyTranslation } from '../parse-malloy';
|
|
5
|
+
export declare const commonErrorCases: ErrorCase[];
|
|
6
|
+
export declare class MalloyParserErrorListener implements ANTLRErrorListener<Token> {
|
|
7
|
+
readonly translator: MalloyTranslation;
|
|
8
|
+
readonly messages: MessageLogger;
|
|
9
|
+
constructor(translator: MalloyTranslation, messages: MessageLogger);
|
|
10
|
+
logError<T extends MessageCode>(code: T, parameters: MessageParameterType<T>, options?: Omit<LogMessageOptions, 'severity'>): T;
|
|
11
|
+
syntaxError(recognizer: unknown, offendingSymbol: Token | undefined, line: number, charPositionInLine: number, message: string, _e: unknown): void;
|
|
12
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
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.MalloyParserErrorListener = exports.commonErrorCases = void 0;
|
|
10
|
+
const MalloyParser_1 = require("../lib/Malloy/MalloyParser");
|
|
11
|
+
const custom_error_messages_1 = require("./custom-error-messages");
|
|
12
|
+
const parse_log_1 = require("../parse-log");
|
|
13
|
+
exports.commonErrorCases = [
|
|
14
|
+
{
|
|
15
|
+
errorMessage: "'view:' must be followed by '<identifier> is {'",
|
|
16
|
+
ruleContextOptions: ['exploreQueryDef'],
|
|
17
|
+
offendingSymbol: MalloyParser_1.MalloyParser.OCURLY,
|
|
18
|
+
precedingTokenOptions: [[MalloyParser_1.MalloyParser.VIEW], [MalloyParser_1.MalloyParser.COLON]],
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
errorMessage: "Missing '}' at '${currentToken}'",
|
|
22
|
+
ruleContextOptions: ['vExpr'],
|
|
23
|
+
offendingSymbol: MalloyParser_1.MalloyParser.VIEW,
|
|
24
|
+
currentToken: MalloyParser_1.MalloyParser.OCURLY,
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
errorMessage: "Missing '}' at '${currentToken}'",
|
|
28
|
+
ruleContextOptions: [
|
|
29
|
+
'exploreProperties',
|
|
30
|
+
'queryProperties',
|
|
31
|
+
'exploreStatement',
|
|
32
|
+
],
|
|
33
|
+
lookAheadOptions: [
|
|
34
|
+
[MalloyParser_1.MalloyParser.EOF],
|
|
35
|
+
[MalloyParser_1.MalloyParser.RUN],
|
|
36
|
+
[MalloyParser_1.MalloyParser.SOURCE],
|
|
37
|
+
],
|
|
38
|
+
},
|
|
39
|
+
];
|
|
40
|
+
class MalloyParserErrorListener {
|
|
41
|
+
constructor(translator, messages) {
|
|
42
|
+
this.translator = translator;
|
|
43
|
+
this.messages = messages;
|
|
44
|
+
}
|
|
45
|
+
logError(code, parameters, options) {
|
|
46
|
+
this.messages.log((0, parse_log_1.makeLogMessage)(code, parameters, { severity: 'error', ...options }));
|
|
47
|
+
return code;
|
|
48
|
+
}
|
|
49
|
+
syntaxError(recognizer, offendingSymbol, line, charPositionInLine, message, _e) {
|
|
50
|
+
const errAt = { line: line - 1, character: charPositionInLine };
|
|
51
|
+
const range = offendingSymbol
|
|
52
|
+
? this.translator.rangeFromToken(offendingSymbol)
|
|
53
|
+
: { start: errAt, end: errAt };
|
|
54
|
+
const overrideMessage = (0, custom_error_messages_1.checkCustomErrorMessage)(recognizer, offendingSymbol, exports.commonErrorCases);
|
|
55
|
+
if (overrideMessage) {
|
|
56
|
+
message = overrideMessage;
|
|
57
|
+
}
|
|
58
|
+
this.logError('syntax-error', { message }, {
|
|
59
|
+
at: { url: this.translator.sourceURL, range },
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
exports.MalloyParserErrorListener = MalloyParserErrorListener;
|
|
64
|
+
//# sourceMappingURL=malloy-parser-error-listener.js.map
|
|
@@ -33,6 +33,7 @@ declare global {
|
|
|
33
33
|
toTranslate(): R;
|
|
34
34
|
toReturnType(tp: string): R;
|
|
35
35
|
toLog(...expectedErrors: ProblemSpec[]): R;
|
|
36
|
+
toLogAtLeast(...expectedErrors: ProblemSpec[]): R;
|
|
36
37
|
isLocationIn(at: DocumentLocation, txt: string): R;
|
|
37
38
|
/**
|
|
38
39
|
* expect(X).compilesTo('expression-string')
|
|
@@ -236,7 +236,11 @@ expect.extend({
|
|
|
236
236
|
},
|
|
237
237
|
toLog: function (s, ...msgs) {
|
|
238
238
|
const expectCompiles = !msgs.some(m => m.severity === 'error');
|
|
239
|
-
return checkForProblems(this, expectCompiles, s, ...msgs);
|
|
239
|
+
return checkForProblems(this, expectCompiles, s, false, ...msgs);
|
|
240
|
+
},
|
|
241
|
+
toLogAtLeast: function (s, ...msgs) {
|
|
242
|
+
const expectCompiles = !msgs.some(m => m.severity === 'error');
|
|
243
|
+
return checkForProblems(this, expectCompiles, s, true, ...msgs);
|
|
240
244
|
},
|
|
241
245
|
isLocationIn: function (checkAt, at, text) {
|
|
242
246
|
if (this.equals(at, checkAt)) {
|
|
@@ -327,7 +331,7 @@ expect.extend({
|
|
|
327
331
|
function problemSpecSummary(s) {
|
|
328
332
|
return `${s.severity} '${'message' in s ? s.message : s.code}' ${s.data !== undefined ? (0, test_translator_1.pretty)(s.data) : ''}`;
|
|
329
333
|
}
|
|
330
|
-
function checkForProblems(context, expectCompiles, s, ...msgs) {
|
|
334
|
+
function checkForProblems(context, expectCompiles, s, allowAdditionalErrors, ...msgs) {
|
|
331
335
|
var _a;
|
|
332
336
|
let emsg = `Expected ${expectCompiles ? 'to' : 'to not'} compile with: `;
|
|
333
337
|
const mSrc = isMarkedSource(s) ? s : undefined;
|
|
@@ -404,7 +408,7 @@ function checkForProblems(context, expectCompiles, s, ...msgs) {
|
|
|
404
408
|
if (i !== msgs.length) {
|
|
405
409
|
explain.push(...msgs.slice(i).map(m => `Missing: ${m}`));
|
|
406
410
|
}
|
|
407
|
-
if (i !== errList.length) {
|
|
411
|
+
if (!allowAdditionalErrors && i !== errList.length) {
|
|
408
412
|
explain.push(...errList.slice(i).map(m => `Unexpected Error: ${m.message}`));
|
|
409
413
|
}
|
|
410
414
|
if (explain.length === 0) {
|
|
@@ -89,7 +89,7 @@ describe('model statements', () => {
|
|
|
89
89
|
});
|
|
90
90
|
describe('error handling', () => {
|
|
91
91
|
test('no close brace', () => {
|
|
92
|
-
expect('run: a -> { group_by: ai').toLog((0, test_translator_1.errorMessage)("'
|
|
92
|
+
expect('run: a -> { group_by: ai').toLog((0, test_translator_1.errorMessage)("Missing '}' at '<EOF>'"));
|
|
93
93
|
});
|
|
94
94
|
test('field and query with same name does not overflow', () => {
|
|
95
95
|
expect(`
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import './parse-expects';
|
|
@@ -0,0 +1,59 @@
|
|
|
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 test_translator_1 = require("./test-translator");
|
|
10
|
+
require("./parse-expects");
|
|
11
|
+
describe('errors', () => {
|
|
12
|
+
test('source missing closing curly: EOF', () => {
|
|
13
|
+
expect('source: x is a extend {').toLogAtLeast((0, test_translator_1.errorMessage)("Missing '}' at '<EOF>'"));
|
|
14
|
+
});
|
|
15
|
+
test('view is missing name', () => {
|
|
16
|
+
expect(`
|
|
17
|
+
source: x is a extend {
|
|
18
|
+
view: {
|
|
19
|
+
group_by: b
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
`).toLogAtLeast((0, test_translator_1.errorMessage)("'view:' must be followed by '<identifier> is {'"));
|
|
23
|
+
});
|
|
24
|
+
test('missing closing curly, source>view', () => {
|
|
25
|
+
expect(`
|
|
26
|
+
source: x is a extend {
|
|
27
|
+
view: y is {
|
|
28
|
+
group_by: b
|
|
29
|
+
|
|
30
|
+
view: z is {
|
|
31
|
+
group_by: c
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
`).toLogAtLeast((0, test_translator_1.errorMessage)("Missing '}' at 'view:'"));
|
|
35
|
+
});
|
|
36
|
+
test('incorrect opening curly after dimension', () => {
|
|
37
|
+
expect(`
|
|
38
|
+
source: x is a extend {
|
|
39
|
+
dimension: {
|
|
40
|
+
test is best
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
`).toLogAtLeast((0, test_translator_1.errorMessage)("extraneous input '{' expecting {BQ_STRING, IDENTIFIER}"));
|
|
44
|
+
});
|
|
45
|
+
test('misspelled primarykey', () => {
|
|
46
|
+
expect(`
|
|
47
|
+
source: x is a extend {
|
|
48
|
+
primarykey: id
|
|
49
|
+
}
|
|
50
|
+
`).toLogAtLeast((0, test_translator_1.errorMessage)("no viable alternative at input 'primarykey'"));
|
|
51
|
+
});
|
|
52
|
+
test('missing opening curly after source extend keyword', () => {
|
|
53
|
+
expect(`
|
|
54
|
+
source: x is a extend
|
|
55
|
+
primary_key: id
|
|
56
|
+
`).toLogAtLeast((0, test_translator_1.errorMessage)("Missing '{' after 'extend'"));
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
//# sourceMappingURL=syntax-errors.spec.js.map
|