@malloydata/malloy 0.0.236-dev250219154103 → 0.0.236-dev250221173808

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.
@@ -6,5 +6,6 @@ export interface ErrorCase {
6
6
  precedingTokenOptions?: number[][];
7
7
  lookAheadOptions?: number[][];
8
8
  errorMessage: string;
9
+ lookbackFromOffendingSymbol?: boolean;
9
10
  }
10
11
  export declare const checkCustomErrorMessage: (parser: Parser, offendingSymbol: Token | undefined, errorCases: ErrorCase[]) => string;
@@ -20,13 +20,17 @@ const checkCustomErrorMessage = (parser, offendingSymbol, errorCases) => {
20
20
  if (isCurrentTokenMatch && isOffendingSymbolMatch && isRuleContextMatch) {
21
21
  // If so, try to check the preceding tokens.
22
22
  if (errorCase.precedingTokenOptions) {
23
- const hasPrecedingTokenMatch = errorCase.precedingTokenOptions.some(sequence => checkTokenSequenceMatch(parser, sequence, 'lookback'));
23
+ const hasPrecedingTokenMatch = errorCase.precedingTokenOptions.some(sequence => checkTokenSequenceMatch(parser, sequence, 'lookback', errorCase.lookbackFromOffendingSymbol
24
+ ? offendingSymbol === null || offendingSymbol === void 0 ? void 0 : offendingSymbol.tokenIndex
25
+ : undefined));
24
26
  if (!hasPrecedingTokenMatch) {
25
27
  continue; // Continue to check a different error case
26
28
  }
27
29
  }
28
30
  if (errorCase.lookAheadOptions) {
29
- const hasLookaheadTokenMatch = errorCase.lookAheadOptions.some(sequence => checkTokenSequenceMatch(parser, sequence, 'lookahead'));
31
+ const hasLookaheadTokenMatch = errorCase.lookAheadOptions.some(sequence => checkTokenSequenceMatch(parser, sequence, 'lookahead', errorCase.lookbackFromOffendingSymbol
32
+ ? offendingSymbol === null || offendingSymbol === void 0 ? void 0 : offendingSymbol.tokenIndex
33
+ : undefined));
30
34
  if (!hasLookaheadTokenMatch) {
31
35
  continue; // Continue to check a different error case
32
36
  }
@@ -39,12 +43,19 @@ const checkCustomErrorMessage = (parser, offendingSymbol, errorCases) => {
39
43
  return '';
40
44
  };
41
45
  exports.checkCustomErrorMessage = checkCustomErrorMessage;
42
- const checkTokenSequenceMatch = (parser, sequence, direction) => {
46
+ const checkTokenSequenceMatch = (parser, sequence, direction, anchorTokenPosition) => {
43
47
  try {
44
48
  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);
49
+ let streamToken = undefined;
50
+ if (typeof anchorTokenPosition === 'number') {
51
+ const tokenOffset = direction === 'lookahead' ? i + 1 : -1 * (i + 1);
52
+ streamToken = parser.inputStream.get(anchorTokenPosition + tokenOffset).type;
53
+ }
54
+ else {
55
+ // Note: positive lookahead starts at '2' because '1' is the current token.
56
+ const tokenOffset = direction === 'lookahead' ? i + 2 : -1 * (i + 1);
57
+ streamToken = parser.inputStream.LA(tokenOffset);
58
+ }
48
59
  // Note: negative checking is < -1 becuase Token.EOF is -1, but below
49
60
  // that we use negatives to indicate "does-not-match" rules.
50
61
  if (sequence[i] >= -1 && streamToken !== sequence[i]) {
@@ -36,6 +36,12 @@ exports.commonErrorCases = [
36
36
  [MalloyParser_1.MalloyParser.SOURCE],
37
37
  ],
38
38
  },
39
+ {
40
+ errorMessage: "'aggregate:' entries must include a name (ex: `some_name is count()`)",
41
+ precedingTokenOptions: [[MalloyParser_1.MalloyParser.AGGREGATE]],
42
+ lookAheadOptions: [[-MalloyParser_1.MalloyParser.IS]],
43
+ lookbackFromOffendingSymbol: true,
44
+ },
39
45
  ];
40
46
  class MalloyParserErrorListener {
41
47
  constructor(translator, messages) {
@@ -55,5 +55,34 @@ describe('errors', () => {
55
55
  primary_key: id
56
56
  `).toLogAtLeast((0, test_translator_1.errorMessage)("Missing '{' after 'extend'"));
57
57
  });
58
+ test('missing alias for aggregate entry', () => {
59
+ expect(`
60
+ run: x -> {
61
+ aggregate: count()
62
+ }
63
+ `).toLogAtLeast((0, test_translator_1.errorMessage)("'aggregate:' entries must include a name (ex: `some_name is count()`)"));
64
+ });
65
+ test('missing alias for aggregate inside source>view', () => {
66
+ expect(`
67
+ source: x is aa extend {
68
+ measure: airport_count is count()
69
+
70
+ view: by_state is {
71
+ where: state is not null
72
+ aggregate: count()
73
+ }
74
+ }
75
+ `).toLogAtLeast((0, test_translator_1.errorMessage)("'aggregate:' entries must include a name (ex: `some_name is count()`)"));
76
+ });
77
+ test('run opening curly to EOF', () => {
78
+ expect(`
79
+ run: x -> {
80
+ `).toLogAtLeast((0, test_translator_1.errorMessage)("Missing '}' at '<EOF>'"));
81
+ });
82
+ test('source opening curly to EOF', () => {
83
+ expect(`
84
+ source: y is x extend {
85
+ `).toLogAtLeast((0, test_translator_1.errorMessage)("Missing '}' at '<EOF>'"));
86
+ });
58
87
  });
59
88
  //# sourceMappingURL=syntax-errors.spec.js.map
@@ -88,6 +88,7 @@ function _resolveCompositeSources(path, source, compositeFieldUsage, narrowedCom
88
88
  return { error: { code: 'not_a_composite_source', data: { path } } };
89
89
  }
90
90
  }
91
+ base.arguments = source.arguments;
91
92
  const fieldsByName = {};
92
93
  const narrowedJoinedSources = (_e = narrowedCompositeFieldResolution === null || narrowedCompositeFieldResolution === void 0 ? void 0 : narrowedCompositeFieldResolution.joined) !== null && _e !== void 0 ? _e : {};
93
94
  for (const field of base.fields) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@malloydata/malloy",
3
- "version": "0.0.236-dev250219154103",
3
+ "version": "0.0.236-dev250221173808",
4
4
  "license": "MIT",
5
5
  "exports": {
6
6
  ".": "./dist/index.js",