@malloydata/malloy 0.0.190 → 0.0.191-dev240925232958

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.
Files changed (90) hide show
  1. package/dist/lang/ast/expressions/constant-expression.js +4 -1
  2. package/dist/lang/ast/expressions/expr-aggregate-function.js +25 -14
  3. package/dist/lang/ast/expressions/expr-alternation-tree.js +1 -3
  4. package/dist/lang/ast/expressions/expr-cast.js +1 -1
  5. package/dist/lang/ast/expressions/expr-coalesce.js +1 -1
  6. package/dist/lang/ast/expressions/expr-func.js +20 -31
  7. package/dist/lang/ast/expressions/expr-granular-time.js +1 -1
  8. package/dist/lang/ast/expressions/expr-id-reference.js +1 -3
  9. package/dist/lang/ast/expressions/expr-props.js +8 -8
  10. package/dist/lang/ast/expressions/expr-time-extract.js +7 -13
  11. package/dist/lang/ast/expressions/expr-ungroup.js +4 -8
  12. package/dist/lang/ast/expressions/for-range.js +2 -3
  13. package/dist/lang/ast/expressions/function-ordering.js +6 -6
  14. package/dist/lang/ast/expressions/partial-compare.js +1 -3
  15. package/dist/lang/ast/expressions/pick-when.js +30 -20
  16. package/dist/lang/ast/expressions/range.js +1 -1
  17. package/dist/lang/ast/expressions/top-by.js +1 -1
  18. package/dist/lang/ast/field-space/dynamic-space.js +1 -1
  19. package/dist/lang/ast/field-space/index-field-space.js +6 -6
  20. package/dist/lang/ast/field-space/parameter-space.js +14 -3
  21. package/dist/lang/ast/field-space/project-field-space.js +1 -1
  22. package/dist/lang/ast/field-space/query-spaces.d.ts +2 -1
  23. package/dist/lang/ast/field-space/query-spaces.js +7 -6
  24. package/dist/lang/ast/field-space/reference-field.js +1 -1
  25. package/dist/lang/ast/field-space/refined-space.js +3 -3
  26. package/dist/lang/ast/field-space/static-space.js +11 -2
  27. package/dist/lang/ast/parameters/has-parameter.js +4 -4
  28. package/dist/lang/ast/query-builders/index-builder.js +4 -4
  29. package/dist/lang/ast/query-builders/project-builder.js +2 -2
  30. package/dist/lang/ast/query-builders/reduce-builder.js +5 -5
  31. package/dist/lang/ast/query-elements/anonymous-query.js +1 -1
  32. package/dist/lang/ast/query-elements/query-reference.js +2 -2
  33. package/dist/lang/ast/query-items/field-declaration.js +7 -4
  34. package/dist/lang/ast/query-items/field-references.js +1 -1
  35. package/dist/lang/ast/query-items/typecheck_utils.js +31 -11
  36. package/dist/lang/ast/query-properties/filters.js +4 -4
  37. package/dist/lang/ast/query-properties/ordering.js +3 -3
  38. package/dist/lang/ast/query-properties/qop-desc.js +2 -2
  39. package/dist/lang/ast/query-properties/top.js +5 -5
  40. package/dist/lang/ast/query-utils.js +1 -1
  41. package/dist/lang/ast/source-elements/named-source.d.ts +2 -2
  42. package/dist/lang/ast/source-elements/named-source.js +12 -13
  43. package/dist/lang/ast/source-elements/refined-source.js +9 -7
  44. package/dist/lang/ast/source-elements/sql-source.js +5 -5
  45. package/dist/lang/ast/source-elements/table-source.js +2 -2
  46. package/dist/lang/ast/source-properties/joins.js +6 -6
  47. package/dist/lang/ast/source-properties/renames.js +3 -3
  48. package/dist/lang/ast/source-query-elements/source-query-element.d.ts +2 -1
  49. package/dist/lang/ast/source-query-elements/source-query-element.js +3 -2
  50. package/dist/lang/ast/source-query-elements/sq-arrow.js +2 -2
  51. package/dist/lang/ast/source-query-elements/sq-extend.js +1 -1
  52. package/dist/lang/ast/source-query-elements/sq-reference.js +5 -5
  53. package/dist/lang/ast/source-query-elements/sq-refine.js +2 -2
  54. package/dist/lang/ast/source-query-elements/sq-source.js +1 -1
  55. package/dist/lang/ast/sql-elements/sql-string.js +2 -2
  56. package/dist/lang/ast/statements/define-query.js +2 -2
  57. package/dist/lang/ast/statements/define-source.js +3 -3
  58. package/dist/lang/ast/statements/import-statement.js +7 -7
  59. package/dist/lang/ast/struct-utils.js +1 -1
  60. package/dist/lang/ast/types/expression-def.js +21 -22
  61. package/dist/lang/ast/types/lookup-result.d.ts +5 -1
  62. package/dist/lang/ast/types/malloy-element.d.ts +8 -5
  63. package/dist/lang/ast/types/malloy-element.js +33 -27
  64. package/dist/lang/ast/view-elements/qop-desc-view.js +3 -3
  65. package/dist/lang/ast/view-elements/reference-view.js +6 -6
  66. package/dist/lang/ast/view-elements/refine-utils.js +6 -6
  67. package/dist/lang/ast/view-elements/view-arrow.js +1 -1
  68. package/dist/lang/ast/view-elements/view-refine.js +1 -1
  69. package/dist/lang/malloy-to-ast.d.ts +7 -7
  70. package/dist/lang/malloy-to-ast.js +56 -55
  71. package/dist/lang/parse-log.d.ts +323 -6
  72. package/dist/lang/parse-log.js +62 -16
  73. package/dist/lang/parse-malloy.d.ts +5 -3
  74. package/dist/lang/parse-malloy.js +22 -31
  75. package/dist/lang/test/annotation.spec.js +4 -4
  76. package/dist/lang/test/expressions.spec.js +93 -74
  77. package/dist/lang/test/imports.spec.js +5 -5
  78. package/dist/lang/test/lenses.spec.js +18 -18
  79. package/dist/lang/test/literals.spec.js +1 -1
  80. package/dist/lang/test/locations.spec.js +5 -5
  81. package/dist/lang/test/parameters.spec.js +34 -34
  82. package/dist/lang/test/parse-expects.d.ts +10 -28
  83. package/dist/lang/test/parse-expects.js +38 -33
  84. package/dist/lang/test/parse.spec.js +49 -49
  85. package/dist/lang/test/query.spec.js +82 -82
  86. package/dist/lang/test/source.spec.js +6 -6
  87. package/dist/lang/test/test-translator.d.ts +19 -0
  88. package/dist/lang/test/test-translator.js +20 -1
  89. package/dist/tags.js +4 -2
  90. package/package.json +1 -1
@@ -1,4 +1,4 @@
1
- import { DocumentLocation } from '../model/malloy_types';
1
+ import { DocumentLocation, FieldValueType } from '../model/malloy_types';
2
2
  export type LogSeverity = 'error' | 'warn' | 'debug';
3
3
  /**
4
4
  * Default severity is "error"
@@ -7,8 +7,10 @@ export interface LogMessage {
7
7
  message: string;
8
8
  at?: DocumentLocation;
9
9
  severity: LogSeverity;
10
- errorTag?: string;
10
+ code: string;
11
11
  replacement?: string;
12
+ errorTag?: string;
13
+ data?: any;
12
14
  }
13
15
  export interface MessageLogger {
14
16
  log(logMsg: LogMessage): void;
@@ -18,14 +20,11 @@ export interface MessageLogger {
18
20
  noErrors(): boolean;
19
21
  empty(): boolean;
20
22
  }
21
- export declare class MessageLog implements MessageLogger {
23
+ export declare class BaseMessageLogger implements MessageLogger {
22
24
  private rawLog;
23
25
  getLog(): LogMessage[];
24
26
  /**
25
27
  * Add a message to the log.
26
- *
27
- * If the messsage ends with '[tag]', the tag is removed and stored in the `errorTag` field.
28
- * @param logMsg Message possibly containing an error tag
29
28
  */
30
29
  log(logMsg: LogMessage): void;
31
30
  reset(): void;
@@ -33,3 +32,321 @@ export declare class MessageLog implements MessageLogger {
33
32
  hasErrors(): boolean;
34
33
  empty(): boolean;
35
34
  }
35
+ type MessageParameterTypes = {
36
+ 'pick-type-does-not-match': {
37
+ pickType: FieldValueType;
38
+ returnType: FieldValueType;
39
+ };
40
+ 'pick-else-type-does-not-match': {
41
+ elseType: FieldValueType;
42
+ returnType: FieldValueType;
43
+ };
44
+ 'pick-default-type-does-not-match': {
45
+ defaultType: FieldValueType;
46
+ returnType: FieldValueType;
47
+ };
48
+ 'pick-missing-else': {};
49
+ 'pick-missing-value': {};
50
+ 'pick-illegal-partial': {};
51
+ 'pick-when-must-be-boolean': {
52
+ whenType: string;
53
+ };
54
+ 'experiment-not-enabled': {
55
+ experimentId: string;
56
+ };
57
+ 'experimental-dialect-not-enabled': {
58
+ dialect: string;
59
+ };
60
+ 'sql-native-not-allowed-in-expression': {
61
+ rawType: string | undefined;
62
+ };
63
+ 'ambiguous-view-type': {};
64
+ 'failed-to-compute-absolute-import-url': string;
65
+ 'import-error': {
66
+ message: string;
67
+ url: string;
68
+ };
69
+ 'parsed-non-malloy-document': {
70
+ url: string;
71
+ };
72
+ 'parse-exception': {
73
+ message: string;
74
+ };
75
+ 'syntax-error': {
76
+ message: string;
77
+ };
78
+ 'internal-translator-error': {
79
+ message: string;
80
+ };
81
+ 'invalid-timezone': {
82
+ timezone: string;
83
+ };
84
+ 'aggregate-source-not-found': string;
85
+ 'name-conflict-with-global': string;
86
+ 'too-many-arguments-for-time-extraction': string;
87
+ 'invalid-type-for-time-extraction': string;
88
+ 'invalid-types-for-time-measurement': string;
89
+ 'invalid-timeframe-for-time-measurement': string;
90
+ 'invalid-time-extraction-unit': string;
91
+ 'untranslated-parse-node': string;
92
+ 'invalid-aggregate-source': string;
93
+ 'missing-aggregate-expression': string;
94
+ 'aggregate-of-aggregate': string;
95
+ 'bad-join-usage': string;
96
+ 'aggregate-traverses-join-cross': string;
97
+ 'aggregate-traverses-join-many': string;
98
+ 'aggregate-traverses-repeated-relationship': string;
99
+ 'alternation-as-value': string;
100
+ 'invalid-sql-native-type': string;
101
+ 'mismatched-coalesce-types': string;
102
+ 'function-not-found': string;
103
+ 'case-insensitive-function': string;
104
+ 'struct-not-callable': string;
105
+ 'connection-not-callable': string;
106
+ 'query-not-callable': string;
107
+ 'no-matching-function-overload': string;
108
+ 'invalid-function-argument-expression-type': string;
109
+ 'invalid-function-argument-evaluation-space': string;
110
+ 'literal-null-function-argument': string;
111
+ 'non-aggregate-function-with-source': string;
112
+ 'aggregate-order-by-experiment-not-enabled': string;
113
+ 'function-does-not-support-order-by': string;
114
+ 'function-does-not-support-limit': string;
115
+ 'partition-by-not-found': string;
116
+ 'non-scalar-or-aggregate-partition-by': string;
117
+ 'sql-functions-experiment-not-enabled': string;
118
+ 'invalid-sql-function-argument': string;
119
+ 'unsupported-sql-function-interpolation': string;
120
+ 'sql-function-interpolation-not-found': string;
121
+ 'function-returns-any': string;
122
+ 'unsupported-type-for-time-truncation': string;
123
+ 'filter-of-non-aggregate': string;
124
+ 'aggregate-filter-expression-not-scalar': string;
125
+ 'partition-by-of-non-window-function': string;
126
+ 'expression-limit-already-specified': string;
127
+ 'limit-of-non-aggregate-function': string;
128
+ 'order-by-of-non-aggregate-function': string;
129
+ 'unsupported-type-for-time-extraction': string;
130
+ 'ungroup-of-non-aggregate': string;
131
+ 'ungroup-of-ungrouped-aggregate': string;
132
+ 'ungroup-field-not-in-output': string;
133
+ 'ungroup-with-non-scalar': string;
134
+ 'invalid-duration-quantity': string;
135
+ 'range-as-value': string;
136
+ 'analytic-order-by-missing-field': string;
137
+ 'analytic-order-by-not-output': string;
138
+ 'analytic-order-by-not-aggregate-or-output': string;
139
+ 'aggregate-order-by-not-scalar': string;
140
+ 'aggregate-order-by-expression-not-allowed': string;
141
+ 'aggregate-order-by-without-field-or-direction': string;
142
+ 'partial-as-value': string;
143
+ 'top-by-non-aggregate': string;
144
+ 'definition-name-conflict': string;
145
+ 'invalid-field-in-index-query': string;
146
+ 'invalid-wildcard-source': string;
147
+ 'wildcard-source-not-found': string;
148
+ 'name-conflict-in-wildcard-expansion': string;
149
+ 'invalid-parameter-reference': string;
150
+ 'parameter-not-found': string;
151
+ 'wildcard-source-not-defined': string;
152
+ 'unexpected-index-segment': string;
153
+ 'accept-parameter': string;
154
+ 'except-parameter': string;
155
+ 'field-list-edit-not-found': string;
156
+ 'unexpected-element-type': string;
157
+ 'field-not-found': string;
158
+ 'invalid-property-access-in-field-reference': string;
159
+ 'parameter-default-does-not-match-declared-type': string;
160
+ 'parameter-null-default-without-declared-type': string;
161
+ 'parameter-illegal-default-type': string;
162
+ 'parameter-missing-default-or-type': string;
163
+ 'index-limit-already-specified': string;
164
+ 'index-by-already-specified': string;
165
+ 'illegal-operation-for-index': string;
166
+ 'refinement-of-index-segment': string;
167
+ 'incompatible-segment-for-select-refinement': string;
168
+ 'illegal-operation-in-select-segment': string;
169
+ 'limit-already-specified': string;
170
+ 'ordering-already-specified': string;
171
+ 'incompatible-segment-for-reduce-refinement': string;
172
+ 'query-reference-not-found': string;
173
+ 'non-query-used-as-query': string;
174
+ 'failed-field-definition': string;
175
+ 'null-typed-field-definition': string;
176
+ 'invalid-type-for-field-definition': string;
177
+ 'circular-reference-in-field-definition': string;
178
+ 'output-name-conflict': string;
179
+ 'select-of-view': string;
180
+ 'select-of-analytic': string;
181
+ 'select-of-aggregate': string;
182
+ 'aggregate-in-dimension': string;
183
+ 'index-of-view': string;
184
+ 'index-of-analytic': string;
185
+ 'index-of-aggregate': string;
186
+ 'analytic-in-dimension': string;
187
+ 'scalar-in-measure': string;
188
+ 'analytic-in-measure': string;
189
+ 'view-in-declare': string;
190
+ 'analytic-in-declare': string;
191
+ 'calculate-of-view': string;
192
+ 'calculate-of-aggregate': string;
193
+ 'calculate-of-scalar': string;
194
+ 'aggregate-of-view': string;
195
+ 'aggregate-of-analytic': string;
196
+ 'aggregate-of-scalar': string;
197
+ 'group-by-view': string;
198
+ 'group-by-analytic': string;
199
+ 'group-by-aggregate': string;
200
+ 'non-boolean-filter': string;
201
+ 'analytic-in-having': string;
202
+ 'analytic-in-where': string;
203
+ 'aggregate-in-where': string;
204
+ 'order-by-not-found-in-output': string;
205
+ 'order-by-analytic': string;
206
+ 'illegal-index-operation': string;
207
+ 'illegal-project-operation': string;
208
+ 'illegal-grouping-operation': string;
209
+ 'top-by-not-found-in-output': string;
210
+ 'top-by-analytic': string;
211
+ 'top-by-aggregate': string;
212
+ 'top-by-not-in-output': string;
213
+ 'source-not-found': string;
214
+ 'invalid-source-from-query': string;
215
+ 'invalid-source-from-function': string;
216
+ 'invalid-source-from-connection': string;
217
+ 'invalid-source-from-sql-block': string;
218
+ 'unnamed-source-argument': string;
219
+ 'duplicate-source-argument': string;
220
+ 'source-parameter-not-found': string;
221
+ 'missing-source-argument': string;
222
+ 'multiple-field-list-edits': string;
223
+ 'multiple-primary-keys': string;
224
+ 'unexpected-source-property': string;
225
+ 'aggregate-in-source-filter': string;
226
+ 'invalid-connection-for-sql-source': string;
227
+ 'failed-to-fetch-sql-source-schema': string;
228
+ 'invalid-sql-source': string;
229
+ 'non-top-level-sql-source': string;
230
+ 'failed-to-fetch-table-schema': string;
231
+ 'invalid-connection-for-table-source': string;
232
+ 'join-on-primary-key-type-mismatch': string;
233
+ 'join-primary-key-not-found': string;
234
+ 'join-with-without-primary-key': string;
235
+ 'non-boolean-join-on': string;
236
+ 'invalid-rename-with-same-name': string;
237
+ 'failed-rename': string;
238
+ 'rename-field-not-found': string;
239
+ 'invalid-join-source': string;
240
+ 'failed-to-compute-arrow-source': string;
241
+ 'failed-to-compute-source-from-query': string;
242
+ 'failed-to-compute-source-to-extend': string;
243
+ 'cannot-use-function-as-query': string;
244
+ 'cannot-use-struct-as-query': string;
245
+ 'cannot-use-connection-as-query': string;
246
+ 'source-or-query-not-found': string;
247
+ 'illegal-query-argument': string;
248
+ 'cannot-use-function-as-source': string;
249
+ 'cannot-use-connection-as-source': string;
250
+ 'illegal-refinement-of-source': string;
251
+ 'invalid-source-as-query': string;
252
+ 'invalid-sql-source-interpolation': string;
253
+ 'failed-to-expand-sql-source': string;
254
+ 'query-definition-name-conflict': string;
255
+ 'query-definition-from-non-query': string;
256
+ 'source-definition-name-conflict': string;
257
+ 'parameter-name-conflict': string;
258
+ 'parameter-shadowing-field': string;
259
+ 'invalid-import-url': string;
260
+ 'no-translator-for-import': string;
261
+ 'name-conflict-on-selective-import': string;
262
+ 'selective-import-not-found': string;
263
+ 'name-conflict-on-indiscriminate-import': string;
264
+ 'failed-import': string;
265
+ 'failed-to-compute-output-schema': string;
266
+ 'invalid-timeframe-for-time-offset': string;
267
+ 'time-comparison-type-mismatch': string;
268
+ 'arithmetic-operation-type-mismatch': string;
269
+ 'time-offset-type-mismatch': string;
270
+ 'unexpected-binary-operator': string;
271
+ 'illegal-reference-in-parameter-default': string;
272
+ 'aggregate-analytic-in-select': string;
273
+ 'refinement-of-raw-query': string;
274
+ 'illegal-multistage-refinement-operation': string;
275
+ 'illegal-refinement-operation': string;
276
+ 'view-not-found': string;
277
+ 'refinement-with-joined-view': string;
278
+ 'nest-of-joined-view': string;
279
+ 'refinement-with-source': string;
280
+ 'nest-of-source': string;
281
+ 'mismatched-view-types-for-refinement': string;
282
+ 'ordering-overridden-in-refinement': string;
283
+ 'limit-overridden-in-refinement': string;
284
+ 'name-conflict-in-refinement': string;
285
+ 'refinement-with-multistage-view': string;
286
+ 'foreign-key-in-join-cross': string;
287
+ 'expression-type-error': string;
288
+ 'unexpected-statement-in-translation': string;
289
+ 'filter-shortcut': string;
290
+ 'illegal-query-interpolation-outside-sql-block': string;
291
+ 'percent-terminated-query-interpolation': string;
292
+ 'failed-to-parse-time-literal': string;
293
+ 'table-function': string;
294
+ 'missing-on-in-join-many': string;
295
+ 'foreign-key-in-join-many': string;
296
+ 'join-statement-in-view': string;
297
+ 'unknown-matrix-operation': string;
298
+ 'declare': string;
299
+ 'query-in-source': string;
300
+ 'invalid-reference-only-aggregation': string;
301
+ 'project': string;
302
+ 'top-by': string;
303
+ 'anonymous-query': string;
304
+ 'anonymous-nest': string;
305
+ 'count-expression-with-locality': string;
306
+ 'invalid-symmetric-aggregate': string;
307
+ 'invalid-asymmetric-aggregate': string;
308
+ 'aggregate-parse-error': string;
309
+ 'wildcard-in-aggregate': string;
310
+ 'unexpected-malloy-type': string;
311
+ 'failed-to-parse-function-name': string;
312
+ 'orphaned-object-annotation': string;
313
+ 'misplaced-model-annotation': string;
314
+ 'unexpected-non-source-query-expression-node': string;
315
+ 'sql-not-like': string;
316
+ 'sql-like': string;
317
+ 'sql-is-not-null': string;
318
+ 'sql-is-null': string;
319
+ };
320
+ export declare const MESSAGE_FORMATTERS: PartialErrorCodeMessageMap;
321
+ export type MessageCode = keyof MessageParameterTypes;
322
+ export type MessageParameterType<T extends MessageCode> = MessageParameterTypes[T];
323
+ type MessageFormatter<T extends MessageCode> = MessageInfo | ((parameters: MessageParameterType<T>) => MessageInfo);
324
+ type ErrorCodeMessageMap = {
325
+ [key in keyof MessageParameterTypes]: MessageFormatter<key>;
326
+ };
327
+ type PartialErrorCodeMessageMap = Partial<ErrorCodeMessageMap>;
328
+ type MessageInfo = string | {
329
+ message: string;
330
+ severity?: LogSeverity;
331
+ replacement?: string;
332
+ tag?: string;
333
+ data?: any;
334
+ };
335
+ export interface ALogMessage<T extends MessageCode> {
336
+ code: T;
337
+ message: string;
338
+ at?: DocumentLocation;
339
+ data: MessageParameterType<T>;
340
+ severity: LogSeverity;
341
+ errorTag?: string;
342
+ replacement?: string;
343
+ }
344
+ export type AnyLogMessage = ALogMessage<MessageCode>;
345
+ export interface LogMessageOptions {
346
+ replacement?: string;
347
+ at?: DocumentLocation;
348
+ severity?: LogSeverity;
349
+ tag?: string;
350
+ }
351
+ export declare function makeLogMessage<T extends MessageCode>(code: T, parameters: MessageParameterType<T>, options?: LogMessageOptions): LogMessage;
352
+ export {};
@@ -22,8 +22,8 @@
22
22
  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
23
  */
24
24
  Object.defineProperty(exports, "__esModule", { value: true });
25
- exports.MessageLog = void 0;
26
- class MessageLog {
25
+ exports.makeLogMessage = exports.MESSAGE_FORMATTERS = exports.BaseMessageLogger = void 0;
26
+ class BaseMessageLogger {
27
27
  constructor() {
28
28
  this.rawLog = [];
29
29
  }
@@ -32,21 +32,8 @@ class MessageLog {
32
32
  }
33
33
  /**
34
34
  * Add a message to the log.
35
- *
36
- * If the messsage ends with '[tag]', the tag is removed and stored in the `errorTag` field.
37
- * @param logMsg Message possibly containing an error tag
38
35
  */
39
36
  log(logMsg) {
40
- const msg = logMsg.message;
41
- // github security is worried about msg.match(/^(.+)\[(.+)\]$/ because if someone
42
- // could craft code with a long varibale name which would blow up that regular expression
43
- if (msg.endsWith(']')) {
44
- const tagStart = msg.lastIndexOf('[');
45
- if (tagStart > 0) {
46
- logMsg.message = msg.slice(0, tagStart);
47
- logMsg.errorTag = msg.slice(tagStart + 1, -1);
48
- }
49
- }
50
37
  this.rawLog.push(logMsg);
51
38
  }
52
39
  reset() {
@@ -63,5 +50,64 @@ class MessageLog {
63
50
  return this.rawLog.length === 0;
64
51
  }
65
52
  }
66
- exports.MessageLog = MessageLog;
53
+ exports.BaseMessageLogger = BaseMessageLogger;
54
+ exports.MESSAGE_FORMATTERS = {
55
+ 'pick-type-does-not-match': e => ({
56
+ message: `pick type \`${e.pickType}\` does not match return type \`${e.returnType}\``,
57
+ tag: 'pick-values-must-match',
58
+ }),
59
+ 'pick-else-type-does-not-match': e => ({
60
+ message: `else type \`${e.elseType}\` does not match return type \`${e.returnType}\``,
61
+ tag: 'pick-values-must-match',
62
+ }),
63
+ 'pick-default-type-does-not-match': e => ({
64
+ message: `default type \`${e.defaultType}\` does not match return type \`${e.returnType}\``,
65
+ tag: 'pick-values-must-match',
66
+ }),
67
+ 'experimental-dialect-not-enabled': e => `Requires compiler flag '##! experimental.dialect.${e.dialect}'`,
68
+ 'pick-missing-else': "pick incomplete, missing 'else'",
69
+ 'pick-missing-value': 'pick with no value can only be used with apply',
70
+ 'pick-illegal-partial': 'pick with partial when can only be used with apply',
71
+ 'pick-when-must-be-boolean': e => `when expression must be boolean, not ${e.whenType}`,
72
+ 'sql-native-not-allowed-in-expression': e => ({
73
+ message: `Unsupported SQL native type '${e.rawType}' not allowed in expression`,
74
+ tag: 'unsupported-sql-native-type-not-allowed-in-expression',
75
+ }),
76
+ 'experiment-not-enabled': e => `Experimental flag \`${e.experimentId}\` is not set, feature not available`,
77
+ 'ambiguous-view-type': "Can't determine view type (`group_by` / `aggregate` / `nest`, `project`, `index`)",
78
+ 'import-error': e => e.message.includes(e.url)
79
+ ? `import error: ${e.message}`
80
+ : `import '${e.url}' error: ${e.message}`,
81
+ 'parsed-non-malloy-document': e => `'${e.url}' did not parse to malloy document`,
82
+ 'parse-exception': e => `Malloy internal parser exception [${e.message}]`,
83
+ 'syntax-error': e => e.message,
84
+ 'internal-translator-error': e => `Internal Translator Error: ${e.message}`,
85
+ 'invalid-timezone': e => `Invalid timezone: ${e.timezone}`,
86
+ };
87
+ function makeLogMessage(code, parameters, options) {
88
+ var _a, _b, _c, _d, _e;
89
+ const format = exports.MESSAGE_FORMATTERS[code];
90
+ const info = format
91
+ ? format instanceof Function
92
+ ? format(parameters)
93
+ : format
94
+ : typeof parameters === 'string'
95
+ ? parameters
96
+ : undefined;
97
+ if (info === undefined) {
98
+ throw new Error(`No message formatter for error code \`${code}\`.`);
99
+ }
100
+ const template = typeof info === 'string' ? { message: info } : info;
101
+ const data = ((_a = template.data) !== null && _a !== void 0 ? _a : typeof parameters === 'string') ? null : parameters;
102
+ return {
103
+ code,
104
+ data,
105
+ message: template.message,
106
+ severity: (_c = (_b = options === null || options === void 0 ? void 0 : options.severity) !== null && _b !== void 0 ? _b : template.severity) !== null && _c !== void 0 ? _c : 'error',
107
+ errorTag: (_d = options === null || options === void 0 ? void 0 : options.tag) !== null && _d !== void 0 ? _d : template.tag,
108
+ replacement: (_e = options === null || options === void 0 ? void 0 : options.replacement) !== null && _e !== void 0 ? _e : template.replacement,
109
+ at: options === null || options === void 0 ? void 0 : options.at,
110
+ };
111
+ }
112
+ exports.makeLogMessage = makeLogMessage;
67
113
  //# sourceMappingURL=parse-log.js.map
@@ -1,6 +1,6 @@
1
1
  import { ANTLRErrorListener, ParserRuleContext, Token } from 'antlr4ts';
2
2
  import { DocumentLocation, DocumentPosition, DocumentRange, DocumentReference, ImportLocation, ModelDef, NamedModelObject, Query, SQLBlockStructDef, StructDef } from '../model/malloy_types';
3
- import { LogMessage, MessageLog, MessageLogger } from './parse-log';
3
+ import { BaseMessageLogger, LogMessage, LogMessageOptions, MessageCode, MessageLogger, 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';
@@ -187,10 +187,11 @@ export declare class MalloyTranslator extends MalloyTranslation {
187
187
  schemaZone: Zone<StructDef>;
188
188
  importZone: Zone<string>;
189
189
  sqlQueryZone: Zone<SQLBlockStructDef>;
190
- logger: MessageLog;
190
+ logger: BaseMessageLogger;
191
191
  readonly root: MalloyTranslator;
192
192
  constructor(rootURL: string, importURL?: string | null, preload?: ParseUpdate | null);
193
193
  update(dd: ParseUpdate): void;
194
+ logError<T extends MessageCode>(code: T, parameters: MessageParameterType<T>, options?: Omit<LogMessageOptions, 'severity'>): T;
194
195
  }
195
196
  interface ErrorData {
196
197
  tables: Record<string, string>;
@@ -214,6 +215,7 @@ export declare class MalloyParserErrorHandler implements ANTLRErrorListener<Toke
214
215
  readonly translator: MalloyTranslation;
215
216
  readonly messages: MessageLogger;
216
217
  constructor(translator: MalloyTranslation, messages: MessageLogger);
217
- syntaxError(recognizer: unknown, offendingSymbol: Token | undefined, line: number, charPositionInLine: number, msg: string, _e: unknown): void;
218
+ logError<T extends MessageCode>(code: T, parameters: MessageParameterType<T>, options?: Omit<LogMessageOptions, 'severity'>): T;
219
+ syntaxError(recognizer: unknown, offendingSymbol: Token | undefined, line: number, charPositionInLine: number, message: string, _e: unknown): void;
218
220
  }
219
221
  export {};
@@ -88,10 +88,7 @@ class ParseStep {
88
88
  catch (e) {
89
89
  const msg = e instanceof Error ? e.message : '';
90
90
  that.urlIsFullPath = false;
91
- that.root.logger.log({
92
- message: `Could not compute full path URL: ${msg}`,
93
- severity: 'error',
94
- });
91
+ that.root.logError('failed-to-compute-absolute-import-url', `Could not compute full path URL: ${msg}`);
95
92
  }
96
93
  }
97
94
  if (!that.urlIsFullPath) {
@@ -100,11 +97,11 @@ class ParseStep {
100
97
  const srcEnt = that.root.importZone.getEntry(that.sourceURL);
101
98
  if (srcEnt.status !== 'present') {
102
99
  if (srcEnt.status === 'error') {
103
- const message = srcEnt.message.includes(that.sourceURL)
104
- ? `import error: ${srcEnt.message}`
105
- : `import '${that.sourceURL}' error: ${srcEnt.message}`;
106
100
  const at = srcEnt.firstReference || that.defaultLocation();
107
- that.root.logger.log({ message, at, severity: 'error' });
101
+ that.root.logError('import-error', {
102
+ message: srcEnt.message,
103
+ url: that.sourceURL,
104
+ }, { at });
108
105
  this.response = that.fatalResponse();
109
106
  return this.response;
110
107
  }
@@ -117,10 +114,7 @@ class ParseStep {
117
114
  parse = this.runParser(source, that);
118
115
  }
119
116
  catch (parseException) {
120
- that.root.logger.log({
121
- message: `Malloy internal parser exception [${parseException.message}]`,
122
- severity: 'error',
123
- });
117
+ that.root.logError('parse-exception', { message: parseException.message });
124
118
  parse = undefined;
125
119
  }
126
120
  if (that.root.logger.hasErrors()) {
@@ -231,11 +225,7 @@ class ImportsAndTablesStep {
231
225
  // This import spec is so bad the URL library threw up, this
232
226
  // may be impossible, because it will append any garbage
233
227
  // to the known good rootURL assuming it is relative
234
- that.root.logger.log({
235
- message: `Malformed URL '${relativeRef}'"`,
236
- at: { url: that.sourceURL, range: firstRef },
237
- severity: 'error',
238
- });
228
+ that.root.logError('invalid-import-url', `Malformed URL '${relativeRef}'"`, { at: { url: that.sourceURL, range: firstRef } });
239
229
  }
240
230
  }
241
231
  }
@@ -300,7 +290,7 @@ class ASTStep {
300
290
  const newAst = secondPass.visit(parse.root);
301
291
  that.compilerFlags = secondPass.compilerFlags;
302
292
  if (newAst.elementType === 'unimplemented') {
303
- newAst.log('INTERNAL COMPILER ERROR: Untranslated parse node');
293
+ newAst.logError('untranslated-parse-node', 'INTERNAL COMPILER ERROR: Untranslated parse node');
304
294
  }
305
295
  if (!this.walked) {
306
296
  // The DocumentStatement.needs method has largely replaced the need to walk
@@ -308,7 +298,7 @@ class ASTStep {
308
298
  // it should probably never be hit
309
299
  for (const walkedTo of newAst.walk()) {
310
300
  if (walkedTo instanceof ast.Unimplemented) {
311
- walkedTo.log('INTERNAL COMPILER ERROR: Untranslated parse node');
301
+ walkedTo.logError('untranslated-parse-node', 'INTERNAL COMPILER ERROR: Untranslated parse node');
312
302
  }
313
303
  }
314
304
  this.walked = true;
@@ -503,11 +493,7 @@ class TranslateStep {
503
493
  }
504
494
  }
505
495
  else {
506
- that.root.logger.log({
507
- message: `'${that.sourceURL}' did not parse to malloy document`,
508
- at: that.defaultLocation(),
509
- severity: 'error',
510
- });
496
+ that.root.logError('parsed-non-malloy-document', { url: that.sourceURL }, { at: that.defaultLocation() });
511
497
  }
512
498
  }
513
499
  if (that.root.logger.hasErrors()) {
@@ -825,7 +811,7 @@ class MalloyTranslator extends MalloyTranslation {
825
811
  this.schemaZone = new zone_1.Zone();
826
812
  this.importZone = new zone_1.Zone();
827
813
  this.sqlQueryZone = new zone_1.Zone();
828
- this.logger = new parse_log_1.MessageLog();
814
+ this.logger = new parse_log_1.BaseMessageLogger();
829
815
  this.root = this;
830
816
  if (preload) {
831
817
  this.update(preload);
@@ -837,6 +823,10 @@ class MalloyTranslator extends MalloyTranslation {
837
823
  this.importZone.updateFrom(dd.urls, (_b = dd.errors) === null || _b === void 0 ? void 0 : _b.urls);
838
824
  this.sqlQueryZone.updateFrom(dd.compileSQL, (_c = dd.errors) === null || _c === void 0 ? void 0 : _c.compileSQL);
839
825
  }
826
+ logError(code, parameters, options) {
827
+ this.logger.log((0, parse_log_1.makeLogMessage)(code, parameters, { severity: 'error', ...options }));
828
+ return code;
829
+ }
840
830
  }
841
831
  exports.MalloyTranslator = MalloyTranslator;
842
832
  class MalloyParserErrorHandler {
@@ -844,17 +834,18 @@ class MalloyParserErrorHandler {
844
834
  this.translator = translator;
845
835
  this.messages = messages;
846
836
  }
847
- syntaxError(recognizer, offendingSymbol, line, charPositionInLine, msg, _e) {
837
+ logError(code, parameters, options) {
838
+ this.messages.log((0, parse_log_1.makeLogMessage)(code, parameters, { severity: 'error', ...options }));
839
+ return code;
840
+ }
841
+ syntaxError(recognizer, offendingSymbol, line, charPositionInLine, message, _e) {
848
842
  const errAt = { line: line - 1, character: charPositionInLine };
849
843
  const range = offendingSymbol
850
844
  ? this.translator.rangeFromToken(offendingSymbol)
851
845
  : { start: errAt, end: errAt };
852
- const error = {
853
- message: msg,
846
+ this.logError('syntax-error', { message }, {
854
847
  at: { url: this.translator.sourceURL, range },
855
- severity: 'error',
856
- };
857
- this.messages.log(error);
848
+ });
858
849
  }
859
850
  }
860
851
  exports.MalloyParserErrorHandler = MalloyParserErrorHandler;
@@ -232,12 +232,12 @@ describe('document annotation', () => {
232
232
  # note1
233
233
  ## model1
234
234
  `);
235
- expect(m).translationToFailWith('Object annotation not connected to any object');
235
+ expect(m).toLog((0, test_translator_1.errorMessage)('Object annotation not connected to any object'));
236
236
  });
237
237
  test('errors reported from compiler flags', () => {
238
238
  expect(`
239
239
  ##! missingCloseQuote="...
240
- `).translationToFailWith(/no viable alternative at input/);
240
+ `).toLog((0, test_translator_1.errorMessage)(/no viable alternative at input/));
241
241
  });
242
242
  test('checking compiler flags', () => {
243
243
  const m = (0, test_translator_1.model) `
@@ -379,7 +379,7 @@ describe('source definition annotations', () => {
379
379
  ## model1
380
380
  }
381
381
  `);
382
- expect(m).translationToFailWith('Model annotations not allowed at this scope');
382
+ expect(m).toLog((0, test_translator_1.errorMessage)('Model annotations not allowed at this scope'));
383
383
  });
384
384
  });
385
385
  describe('query operation annotations', () => {
@@ -389,7 +389,7 @@ describe('query operation annotations', () => {
389
389
  ## model1
390
390
  select: *
391
391
  }
392
- `).translationToFailWith('Model annotations not allowed at this scope');
392
+ `).toLog((0, test_translator_1.errorMessage)('Model annotations not allowed at this scope'));
393
393
  });
394
394
  test('project new definition annotation', () => {
395
395
  const m = new test_translator_1.TestTranslator(`