@malloydata/malloy 0.0.153 → 0.0.154-dev240722014518

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.
@@ -265,7 +265,7 @@ class ExprFunc extends expression_def_1.ExpressionDef {
265
265
  if (unsupportedInterpolations.length > 0) {
266
266
  const unsupportedInterpolationMsg = unsupportedInterpolations.length === 1
267
267
  ? `'.' paths are not yet supported in sql interpolations, found ${unsupportedInterpolations.at(0)}`
268
- : `'.' paths are not yet supported in sql interpolations, found [${unsupportedInterpolations.join(', ')}]`;
268
+ : `'.' paths are not yet supported in sql interpolations, found (${unsupportedInterpolations.join(', ')})`;
269
269
  this.log(unsupportedInterpolationMsg);
270
270
  return (0, ast_utils_1.errorFor)(`${unsupportedInterpolationMsg}. See LookML \${...} documentation at https://cloud.google.com/looker/docs/reference/param-field-sql#sql_for_dimensions`);
271
271
  }
@@ -76,7 +76,7 @@ class Pick extends expression_def_1.ExpressionDef {
76
76
  anyEvalSpace = (0, malloy_types_1.mergeEvalSpaces)(anyEvalSpace, whenExpr.evalSpace, thenExpr.evalSpace);
77
77
  if (returnType && !fragtype_utils_1.FT.typeEq(returnType, thenExpr, true)) {
78
78
  const whenType = fragtype_utils_1.FT.inspect(thenExpr);
79
- this.log(`pick type '${whenType}', expected '${returnType.dataType}'`);
79
+ this.log(`pick type '${whenType}', expected '${returnType.dataType}'[pick-values-must-match]`);
80
80
  return (0, ast_utils_1.errorFor)('pick when type');
81
81
  }
82
82
  returnType = typeCoalesce(returnType, thenExpr);
@@ -87,7 +87,7 @@ class Pick extends expression_def_1.ExpressionDef {
87
87
  returnType = typeCoalesce(returnType, elseVal);
88
88
  if (!fragtype_utils_1.FT.typeEq(returnType, elseVal, true)) {
89
89
  const errSrc = this.elsePick ? 'else' : 'pick default';
90
- this.log(`${errSrc} type '${fragtype_utils_1.FT.inspect(elseVal)}', expected '${returnType.dataType}'`);
90
+ this.log(`${errSrc} type '${fragtype_utils_1.FT.inspect(elseVal)}', expected '${returnType.dataType}'[pick-values-must-match]`);
91
91
  return (0, ast_utils_1.errorFor)('pick else type');
92
92
  }
93
93
  return {
@@ -129,7 +129,7 @@ class Pick extends expression_def_1.ExpressionDef {
129
129
  }
130
130
  if (returnType && !fragtype_utils_1.FT.typeEq(returnType, aChoice.pick, true)) {
131
131
  const whenType = fragtype_utils_1.FT.inspect(aChoice.pick);
132
- this.log(`pick type '${whenType}', expected '${returnType.dataType}'`);
132
+ this.log(`pick type '${whenType}', expected '${returnType.dataType}'[pick-values-must-match]`);
133
133
  return (0, ast_utils_1.errorFor)('pick value type');
134
134
  }
135
135
  returnType = typeCoalesce(returnType, aChoice.pick);
@@ -142,7 +142,7 @@ class Pick extends expression_def_1.ExpressionDef {
142
142
  anyEvalSpace = (0, malloy_types_1.mergeEvalSpaces)(anyEvalSpace, defVal.evalSpace);
143
143
  returnType = typeCoalesce(returnType, defVal);
144
144
  if (!fragtype_utils_1.FT.typeEq(returnType, defVal, true)) {
145
- this.elsePick.log(`else type '${fragtype_utils_1.FT.inspect(defVal)}', expected '${returnType.dataType}'`);
145
+ this.elsePick.log(`else type '${fragtype_utils_1.FT.inspect(defVal)}', expected '${returnType.dataType}'[pick-values-must-match]`);
146
146
  return (0, ast_utils_1.errorFor)('pick value type mismatch');
147
147
  }
148
148
  caseValue.push(' ELSE ', ...defVal.value, ' END');
@@ -7,6 +7,7 @@ export interface LogMessage {
7
7
  message: string;
8
8
  at?: DocumentLocation;
9
9
  severity: LogSeverity;
10
+ errorTag?: string;
10
11
  }
11
12
  export interface MessageLogger {
12
13
  log(logMsg: LogMessage): void;
@@ -19,6 +20,12 @@ export interface MessageLogger {
19
20
  export declare class MessageLog implements MessageLogger {
20
21
  private rawLog;
21
22
  getLog(): LogMessage[];
23
+ /**
24
+ * Add a message to the log.
25
+ *
26
+ * If the messsage ends with '[tag]', the tag is removed and stored in the `errorTag` field.
27
+ * @param logMsg Message possibly containing an error tag
28
+ */
22
29
  log(logMsg: LogMessage): void;
23
30
  reset(): void;
24
31
  noErrors(): boolean;
@@ -30,7 +30,23 @@ class MessageLog {
30
30
  getLog() {
31
31
  return this.rawLog;
32
32
  }
33
+ /**
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
+ */
33
39
  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
+ }
34
50
  this.rawLog.push(logMsg);
35
51
  }
36
52
  reset() {
@@ -879,4 +879,10 @@ describe('sql_functions', () => {
879
879
  });
880
880
  });
881
881
  test('non breaking space in source', () => expect('source:\u00a0z\u00a0is\u00a0a').toParse());
882
+ test('error tagging', () => {
883
+ const m = (0, test_translator_1.model) `run: a -> { select: err is pick 1 when true else 'one' }`;
884
+ expect(m).translationToFailWith("else type 'string', expected 'number'");
885
+ const firstErr = m.translator.root.logger.getLog()[0];
886
+ expect(firstErr === null || firstErr === void 0 ? void 0 : firstErr.errorTag).toBe('pick-values-must-match');
887
+ });
882
888
  //# sourceMappingURL=parse.spec.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@malloydata/malloy",
3
- "version": "0.0.153",
3
+ "version": "0.0.154-dev240722014518",
4
4
  "license": "MIT",
5
5
  "exports": {
6
6
  ".": "./dist/index.js",