@malloydata/malloy 0.0.43-dev230622144455 → 0.0.43-dev230622180905

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.
@@ -76,6 +76,9 @@ class ExprFunc extends expression_def_1.ExpressionDef {
76
76
  this.log(`Cannot call '${this.name}', which is of type ${func.type}`);
77
77
  return (0, ast_utils_1.errorFor)('called non function');
78
78
  }
79
+ if (func.name !== this.name) {
80
+ this.log(`Case insensitivity for function names is deprecated, use '${func.name}' instead`, 'warn');
81
+ }
79
82
  // Find the 'implicit argument' for aggregate functions called like `some_join.some_field.agg(...args)`
80
83
  // where the full arg list is `(some_field, ...args)`.
81
84
  let implicitExpr = undefined;
@@ -1,4 +1,5 @@
1
1
  import { DocumentLocation, DocumentReference, ModelDef, Query, SQLBlockStructDef } from '../../../model/malloy_types';
2
+ import { LogSeverity } from '../../parse-log';
2
3
  import { MalloyTranslation } from '../../parse-malloy';
3
4
  import { ModelDataRequest } from '../../translate-response';
4
5
  import { DocumentCompileResult } from './document-compile-result';
@@ -31,7 +32,7 @@ export declare abstract class MalloyElement {
31
32
  private get sourceURL();
32
33
  errorsExist(): boolean;
33
34
  private readonly logged;
34
- log(message: string): void;
35
+ log(message: string, severity?: LogSeverity): void;
35
36
  /**
36
37
  * Mostly for debugging / testing. A string-y version of this object which
37
38
  * is used to ask "are these two AST segments equal". Formatted so that
@@ -151,7 +151,7 @@ class MalloyElement {
151
151
  }
152
152
  return true;
153
153
  }
154
- log(message) {
154
+ log(message, severity = 'error') {
155
155
  if (this.codeLocation) {
156
156
  /*
157
157
  * If this element has a location, then don't report the same
@@ -163,7 +163,7 @@ class MalloyElement {
163
163
  this.logged.add(message);
164
164
  }
165
165
  const trans = this.translator();
166
- const msg = { at: this.location, message };
166
+ const msg = { at: this.location, message, severity };
167
167
  const logTo = trans === null || trans === void 0 ? void 0 : trans.root.logger;
168
168
  if (logTo) {
169
169
  logTo.log(msg);
@@ -36,6 +36,7 @@ class MalloyParserErrorHandler {
36
36
  const error = {
37
37
  message: msg,
38
38
  at: { url: this.translator.sourceURL, range },
39
+ severity: 'error',
39
40
  };
40
41
  this.messages.log(error);
41
42
  }
@@ -6,7 +6,7 @@ export declare type LogSeverity = 'error' | 'warn' | 'debug';
6
6
  export interface LogMessage {
7
7
  message: string;
8
8
  at?: DocumentLocation;
9
- severity?: LogSeverity;
9
+ severity: LogSeverity;
10
10
  }
11
11
  export interface MessageLogger {
12
12
  log(logMsg: LogMessage): void;
@@ -1,10 +1,10 @@
1
1
  import { CodePointCharStream, CommonTokenStream, ParserRuleContext, Token } from 'antlr4ts';
2
2
  import { ParseTree } from 'antlr4ts/tree';
3
3
  import { DocumentLocation, DocumentPosition, DocumentRange, DocumentReference, ModelDef, NamedModelObject, Query, SQLBlockStructDef, StructDef } from '../model/malloy_types';
4
- import { MessageLog } from './parse-log';
4
+ import { LogMessage, MessageLog } from './parse-log';
5
5
  import { Zone, ZoneData } from './zone';
6
6
  import { ReferenceList } from './reference-list';
7
- import { ASTResponse, CompletionsResponse, DataRequestResponse, ErrorResponse, FatalResponse, FinalResponse, HelpContextResponse, MetadataResponse, ModelDataRequest, NeedURLData, TranslateResponse } from './translate-response';
7
+ import { ASTResponse, CompletionsResponse, DataRequestResponse, ProblemResponse, FatalResponse, FinalResponse, HelpContextResponse, MetadataResponse, ModelDataRequest, NeedURLData, TranslateResponse } from './translate-response';
8
8
  export declare type StepResponses = DataRequestResponse | ASTResponse | TranslateResponse | ParseResponse | MetadataResponse;
9
9
  /**
10
10
  * A Translation is a series of translation steps. Each step can depend
@@ -28,7 +28,7 @@ export interface MalloyParseRoot {
28
28
  subTranslator: MalloyTranslation;
29
29
  malloyVersion: string;
30
30
  }
31
- interface ParseData extends ErrorResponse, NeedURLData, FinalResponse {
31
+ interface ParseData extends ProblemResponse, NeedURLData, FinalResponse {
32
32
  parse: MalloyParseRoot;
33
33
  }
34
34
  export declare type ParseResponse = Partial<ParseData>;
@@ -116,12 +116,18 @@ export declare abstract class MalloyTranslation {
116
116
  addChild(url: string): void;
117
117
  addReference(reference: DocumentReference): void;
118
118
  referenceAt(position: DocumentPosition): DocumentReference | undefined;
119
- fatalErrors(): FatalResponse;
120
119
  /**
121
- * The error log can grow as progressively deeper questions are asked.
122
- * When returning "errors so far", make a snapshot.
120
+ * This returns a *final* response containing all problems, for when there are
121
+ * errors and the translation needs to stop and report errors. When doing so,
122
+ * it also reports warnings.
123
123
  */
124
- errors(): ErrorResponse;
124
+ fatalResponse(): FatalResponse;
125
+ /**
126
+ * The problem log can grow as progressively deeper questions are asked.
127
+ * When returning "problems so far", make a snapshot.
128
+ */
129
+ problemResponse(): ProblemResponse;
130
+ problems(): LogMessage[];
125
131
  getLineMap(url: string): string[] | undefined;
126
132
  prettyErrors(): string;
127
133
  childRequest(importURL: string): ModelDataRequest;
@@ -88,11 +88,12 @@ class ParseStep {
88
88
  that.urlIsFullPath = false;
89
89
  that.root.logger.log({
90
90
  message: `Could not compute full path URL: ${msg}`,
91
+ severity: 'error',
91
92
  });
92
93
  }
93
94
  }
94
95
  if (!that.urlIsFullPath) {
95
- return that.fatalErrors();
96
+ return that.fatalResponse();
96
97
  }
97
98
  const srcEnt = that.root.importZone.getEntry(that.sourceURL);
98
99
  if (srcEnt.status !== 'present') {
@@ -101,8 +102,8 @@ class ParseStep {
101
102
  ? `import error: ${srcEnt.message}`
102
103
  : `import '${that.sourceURL}' error: ${srcEnt.message}`;
103
104
  const at = srcEnt.firstReference || that.defaultLocation();
104
- that.root.logger.log({ message, at });
105
- this.response = that.fatalErrors();
105
+ that.root.logger.log({ message, at, severity: 'error' });
106
+ this.response = that.fatalResponse();
106
107
  return this.response;
107
108
  }
108
109
  return { urls: [that.sourceURL] };
@@ -116,13 +117,14 @@ class ParseStep {
116
117
  catch (parseException) {
117
118
  that.root.logger.log({
118
119
  message: `Malloy internal parser exception [${parseException.message}]`,
120
+ severity: 'error',
119
121
  });
120
122
  parse = undefined;
121
123
  }
122
124
  if (that.root.logger.hasErrors()) {
123
125
  this.response = {
124
126
  parse,
125
- ...that.fatalErrors(),
127
+ ...that.fatalResponse(),
126
128
  };
127
129
  }
128
130
  else {
@@ -228,6 +230,7 @@ class ImportsAndTablesStep {
228
230
  that.root.logger.log({
229
231
  message: `Malformed URL '${relativeRef}'"`,
230
232
  at: { url: that.sourceURL, range: firstRef },
233
+ severity: 'error',
231
234
  });
232
235
  }
233
236
  }
@@ -275,7 +278,7 @@ class ASTStep {
275
278
  const parseResponse = that.parseStep.response;
276
279
  // Errors in self or children will show up here ..
277
280
  if (that.root.logger.hasErrors()) {
278
- this.response = that.fatalErrors();
281
+ this.response = that.fatalResponse();
279
282
  return this.response;
280
283
  }
281
284
  const parse = parseResponse === null || parseResponse === void 0 ? void 0 : parseResponse.parse;
@@ -285,7 +288,7 @@ class ASTStep {
285
288
  const secondPass = new malloy_to_ast_1.MalloyToAST(parse, that.root.logger);
286
289
  const newAst = secondPass.visit(parse.root);
287
290
  if (that.root.logger.hasErrors()) {
288
- this.response = that.fatalErrors();
291
+ this.response = that.fatalResponse();
289
292
  return this.response;
290
293
  }
291
294
  if (newAst.elementType === 'unimplemented') {
@@ -316,7 +319,7 @@ class ASTStep {
316
319
  }
317
320
  // If there is a partial ast ...
318
321
  if (that.root.logger.hasErrors()) {
319
- this.response = that.fatalErrors();
322
+ this.response = that.fatalResponse();
320
323
  return this.response;
321
324
  }
322
325
  /*
@@ -336,7 +339,7 @@ class ASTStep {
336
339
  }
337
340
  newAst.setTranslator(that);
338
341
  this.response = {
339
- ...that.errors(),
342
+ ...that.problemResponse(),
340
343
  ast: newAst,
341
344
  final: true,
342
345
  };
@@ -474,11 +477,12 @@ class TranslateStep {
474
477
  that.root.logger.log({
475
478
  message: `'${that.sourceURL}' did not parse to malloy document`,
476
479
  at: that.defaultLocation(),
480
+ severity: 'error',
477
481
  });
478
482
  }
479
483
  }
480
484
  if (that.root.logger.hasErrors()) {
481
- this.response = that.fatalErrors();
485
+ this.response = that.fatalResponse();
482
486
  }
483
487
  else {
484
488
  this.response = {
@@ -487,7 +491,7 @@ class TranslateStep {
487
491
  queryList: that.queryList,
488
492
  sqlBlocks: that.sqlBlocks,
489
493
  },
490
- ...that.errors(),
494
+ ...that.problemResponse(),
491
495
  final: true,
492
496
  };
493
497
  }
@@ -533,19 +537,26 @@ class MalloyTranslation {
533
537
  referenceAt(position) {
534
538
  return this.references.find(position);
535
539
  }
536
- fatalErrors() {
540
+ /**
541
+ * This returns a *final* response containing all problems, for when there are
542
+ * errors and the translation needs to stop and report errors. When doing so,
543
+ * it also reports warnings.
544
+ */
545
+ fatalResponse() {
537
546
  return {
538
547
  final: true,
539
- errors: [...this.root.logger.getLog()],
548
+ ...this.problemResponse(),
540
549
  };
541
550
  }
542
551
  /**
543
- * The error log can grow as progressively deeper questions are asked.
544
- * When returning "errors so far", make a snapshot.
552
+ * The problem log can grow as progressively deeper questions are asked.
553
+ * When returning "problems so far", make a snapshot.
545
554
  */
546
- errors() {
547
- const errors = this.root.logger.getLog();
548
- return { errors: [...errors] };
555
+ problemResponse() {
556
+ return { problems: this.problems() };
557
+ }
558
+ problems() {
559
+ return [...this.root.logger.getLog()];
549
560
  }
550
561
  getLineMap(url) {
551
562
  var _a, _b;
@@ -1,5 +1,11 @@
1
1
  import { DocumentLocation } from '../../model';
2
- declare type ErrorSpec = string | RegExp;
2
+ import { LogSeverity } from '../parse-log';
3
+ declare type SimpleProblemSpec = string | RegExp;
4
+ declare type ComplexProblemSpec = {
5
+ severity: LogSeverity;
6
+ message: SimpleProblemSpec;
7
+ };
8
+ declare type ProblemSpec = SimpleProblemSpec | ComplexProblemSpec;
3
9
  declare global {
4
10
  namespace jest {
5
11
  interface Matchers<R> {
@@ -24,6 +30,19 @@ declare global {
24
30
  * the markings.
25
31
  */
26
32
  toTranslate(): R;
33
+ /**
34
+ * expect(X).toTranslateWithWarnings(expectedWarnings)
35
+ *
36
+ * Passes if the source compiles to code which could be used to
37
+ * generate SQL, and the specified warnings appear. If X is a marked
38
+ * source, the warnings which are found must match the locations of
39
+ * the markings.
40
+ *
41
+ * X can be a MarkedSource, a string, or a model. If it is a marked
42
+ * source, the errors which are found must match the locations of
43
+ * the markings.
44
+ */
45
+ toTranslateWithWarnings(...expectedWarnings: SimpleProblemSpec[]): R;
27
46
  toReturnType(tp: string): R;
28
47
  /**
29
48
  * expect(X).translateToFailWith(expectedErrors)
@@ -35,7 +54,7 @@ declare global {
35
54
  * @param expectedErrors varargs list of strings which must match
36
55
  * exactly, or regular expressions.
37
56
  */
38
- translationToFailWith(...expectedErrors: ErrorSpec[]): R;
57
+ translationToFailWith(...expectedErrors: ProblemSpec[]): R;
39
58
  isLocationIn(at: DocumentLocation, txt: string): R;
40
59
  }
41
60
  }
@@ -25,13 +25,13 @@
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
26
  const test_translator_1 = require("./test-translator");
27
27
  const util_1 = require("util");
28
- function checkForErrors(trans) {
28
+ function ensureNoProblems(trans) {
29
29
  if (trans.logger === undefined) {
30
30
  throw new Error('JESTERY BROKEN, CANT FIND ERORR LOG');
31
31
  }
32
- if (trans.logger.hasErrors()) {
32
+ if (!trans.logger.empty()) {
33
33
  return {
34
- message: () => `Translation Errors:\n${trans.prettyErrors()}`,
34
+ message: () => `Translation problems:\n${trans.prettyErrors()}`,
35
35
  pass: false,
36
36
  };
37
37
  }
@@ -92,6 +92,19 @@ function highlightError(dl, txt) {
92
92
  }
93
93
  return output.join('\n');
94
94
  }
95
+ function normalizeProblemSpec(defaultSeverity) {
96
+ return function (spec) {
97
+ if (typeof spec === 'string') {
98
+ return { severity: defaultSeverity, message: spec };
99
+ }
100
+ else if (spec instanceof RegExp) {
101
+ return { severity: defaultSeverity, message: spec };
102
+ }
103
+ else {
104
+ return spec;
105
+ }
106
+ };
107
+ }
95
108
  function isMarkedSource(ts) {
96
109
  return typeof ts !== 'string' && !(ts instanceof test_translator_1.TestTranslator);
97
110
  }
@@ -105,7 +118,7 @@ function xlator(ts) {
105
118
  return ts.translator || new test_translator_1.TestTranslator(ts.code);
106
119
  }
107
120
  function xlated(tt) {
108
- const errorCheck = checkForErrors(tt);
121
+ const errorCheck = ensureNoProblems(tt);
109
122
  if (!errorCheck.pass) {
110
123
  return errorCheck;
111
124
  }
@@ -116,7 +129,7 @@ expect.extend({
116
129
  toParse: function (tx) {
117
130
  const x = xlator(tx);
118
131
  x.compile();
119
- return checkForErrors(x);
132
+ return ensureNoProblems(x);
120
133
  },
121
134
  toTranslate: function (tx) {
122
135
  const x = xlator(tx);
@@ -136,74 +149,10 @@ expect.extend({
136
149
  return { pass, message: () => msg };
137
150
  },
138
151
  translationToFailWith: function (s, ...msgs) {
139
- var _a;
140
- let emsg = 'Compile Error expectation not met\nExpected message';
141
- const mSrc = isMarkedSource(s) ? s : undefined;
142
- const qmsgs = msgs.map(s => `error '${s}'`);
143
- if (msgs.length === 1) {
144
- emsg += ` ${qmsgs[0]}`;
145
- }
146
- else {
147
- emsg += `s [\n${qmsgs.join('\n')}\n]`;
148
- }
149
- const m = xlator(s);
150
- const src = m.testSrc;
151
- emsg += `\nSource:\n${src}`;
152
- m.compile();
153
- const t = m.translate();
154
- if (t.translated) {
155
- return { pass: false, message: () => emsg };
156
- }
157
- else if (t.errors === undefined) {
158
- return {
159
- pass: false,
160
- message: () => 'TEST ERROR, not all objects resolved in source\n' +
161
- (0, test_translator_1.pretty)(t) +
162
- '\n' +
163
- emsg,
164
- };
165
- }
166
- else {
167
- const explain = [];
168
- const errList = m.errors().errors;
169
- let i;
170
- for (i = 0; i < msgs.length && errList[i]; i += 1) {
171
- const msg = msgs[i];
172
- const err = errList[i];
173
- const matched = typeof msg === 'string'
174
- ? msg === err.message
175
- : err.message.match(msg);
176
- if (!matched) {
177
- explain.push(`Expected: ${msg}\nGot: ${err.message}`);
178
- }
179
- else {
180
- if (mSrc === null || mSrc === void 0 ? void 0 : mSrc.locations[i]) {
181
- const have = (_a = err.at) === null || _a === void 0 ? void 0 : _a.range;
182
- const want = mSrc.locations[i].range;
183
- if (!this.equals(have, want)) {
184
- explain.push(`Expected '${msg}' at location: ${(0, util_1.inspect)(want)}\n` +
185
- `Actual location: ${(0, util_1.inspect)(have)}`);
186
- }
187
- }
188
- }
189
- }
190
- if (i !== msgs.length) {
191
- explain.push(...msgs.slice(i).map(m => `Missing: ${m}`));
192
- }
193
- if (i !== errList.length) {
194
- explain.push(...errList.slice(i).map(m => `Unexpected Error: ${m.message}`));
195
- }
196
- if (explain.length === 0) {
197
- return {
198
- pass: true,
199
- message: () => `All expected errors found: ${(0, test_translator_1.pretty)(msgs)}`,
200
- };
201
- }
202
- return {
203
- pass: false,
204
- message: () => `Compiler did not generated expected errors\n${explain.join('\n')}`,
205
- };
206
- }
152
+ return checkForProblems(this, false, s, 'error', ...msgs);
153
+ },
154
+ toTranslateWithWarnings: function (s, ...msgs) {
155
+ return checkForProblems(this, true, s, 'warn', ...msgs);
207
156
  },
208
157
  isLocationIn: function (checkAt, at, text) {
209
158
  if (this.equals(at, checkAt)) {
@@ -221,4 +170,79 @@ expect.extend({
221
170
  };
222
171
  },
223
172
  });
173
+ function checkForProblems(context, expectCompiles, s, defaultSeverity, ...msgs) {
174
+ var _a;
175
+ let emsg = `Expected ${expectCompiles ? 'to' : 'to not'} compile with: `;
176
+ const mSrc = isMarkedSource(s) ? s : undefined;
177
+ const normalize = normalizeProblemSpec(defaultSeverity);
178
+ const normMsgs = msgs.map(normalize);
179
+ const qmsgs = normMsgs.map(s => `${s.severity} '${s.message}'`);
180
+ if (msgs.length === 1) {
181
+ emsg += ` ${qmsgs[0]}`;
182
+ }
183
+ else {
184
+ emsg += `s [\n${qmsgs.join('\n')}\n]`;
185
+ }
186
+ const m = xlator(s);
187
+ const src = m.testSrc;
188
+ emsg += `\nSource:\n${src}`;
189
+ m.compile();
190
+ const t = m.translate();
191
+ if (t.translated && !expectCompiles) {
192
+ return { pass: false, message: () => emsg };
193
+ }
194
+ else if (t.problems === undefined) {
195
+ return {
196
+ pass: false,
197
+ message: () => 'TEST ERROR, not all objects resolved in source\n' +
198
+ (0, test_translator_1.pretty)(t) +
199
+ '\n' +
200
+ emsg,
201
+ };
202
+ }
203
+ else {
204
+ const explain = [];
205
+ const errList = m.problemResponse().problems;
206
+ let i;
207
+ for (i = 0; i < normMsgs.length && errList[i]; i += 1) {
208
+ const msg = normMsgs[i];
209
+ const err = errList[i];
210
+ const matched = typeof msg.message === 'string'
211
+ ? msg.message === err.message
212
+ : err.message.match(msg.message);
213
+ if (err.severity !== msg.severity) {
214
+ explain.push(`Expected ${msg.severity}, got ${err.severity} ${err.message}`);
215
+ }
216
+ if (!matched) {
217
+ explain.push(`Expected: ${msg.message}\nGot: ${err.message}`);
218
+ }
219
+ else {
220
+ if (mSrc === null || mSrc === void 0 ? void 0 : mSrc.locations[i]) {
221
+ const have = (_a = err.at) === null || _a === void 0 ? void 0 : _a.range;
222
+ const want = mSrc.locations[i].range;
223
+ if (!context.equals(have, want)) {
224
+ explain.push(`Expected '${msg.message}' at location: ${(0, util_1.inspect)(want)}\n` +
225
+ `Actual location: ${(0, util_1.inspect)(have)}`);
226
+ }
227
+ }
228
+ }
229
+ }
230
+ if (i !== msgs.length) {
231
+ explain.push(...msgs.slice(i).map(m => `Missing: ${m}`));
232
+ }
233
+ if (i !== errList.length) {
234
+ explain.push(...errList.slice(i).map(m => `Unexpected Error: ${m.message}`));
235
+ }
236
+ if (explain.length === 0) {
237
+ return {
238
+ pass: true,
239
+ message: () => `All expected errors found: ${(0, test_translator_1.pretty)(msgs)}`,
240
+ };
241
+ }
242
+ return {
243
+ pass: false,
244
+ message: () => `Compiler did not generated expected errors\n${explain.join('\n')}`,
245
+ };
246
+ }
247
+ }
224
248
  //# sourceMappingURL=parse-expects.js.map
@@ -85,7 +85,7 @@ describe('model statements', () => {
85
85
  `).toTranslate();
86
86
  });
87
87
  test('from(query) refined into query', () => {
88
- expect('query: from(ab -> {group_by: astr}) { dimension: bigstr is UPPER(astr) } -> { group_by: bigstr }').toTranslate();
88
+ expect('query: from(ab -> {group_by: astr}) { dimension: bigstr is upper(astr) } -> { group_by: bigstr }').toTranslate();
89
89
  });
90
90
  test('query with shortcut filtered turtle', () => {
91
91
  expect("query: allA is ab->aturtle {? astr ~ 'a%' }").toTranslate();
@@ -371,6 +371,11 @@ describe('model statements', () => {
371
371
  expect(`query: a -> {
372
372
  group_by: s is concat('a', 'b')
373
373
  }`).toTranslate();
374
+ });
375
+ test('function incorrect case', () => {
376
+ expect(`query: a -> {
377
+ group_by: s is CONCAT('a', 'b')
378
+ }`).toTranslateWithWarnings("Case insensitivity for function names is deprecated, use 'concat' instead");
374
379
  });
375
380
  test('function no matching overload', () => {
376
381
  expect(`query: a -> {
@@ -1531,7 +1536,7 @@ describe('error handling', () => {
1531
1536
  expect('source: na is a { rename: astr is astr }').translationToFailWith("Can't rename field to itself");
1532
1537
  });
1533
1538
  test('reference to field in its definition', () => {
1534
- expect('source: na is a { dimension: ustr is UPPER(ustr) } ').translationToFailWith("Circular reference to 'ustr' in definition");
1539
+ expect('source: na is a { dimension: ustr is upper(ustr) } ').translationToFailWith("Circular reference to 'ustr' in definition");
1535
1540
  });
1536
1541
  test('empty model', () => {
1537
1542
  expect('').toTranslate();
@@ -2336,7 +2341,6 @@ describe('translation need error locations', () => {
2336
2341
  errors: { urls: { [(result.urls || [])[0]]: 'Bad file!' } },
2337
2342
  });
2338
2343
  expect(source).translationToFailWith(/Bad file!/);
2339
- return undefined;
2340
2344
  });
2341
2345
  test('sql struct error location', () => {
2342
2346
  const source = (0, test_translator_1.markSource) `
@@ -2351,7 +2355,7 @@ describe('translation need error locations', () => {
2351
2355
  m.update({ errors: { compileSQL: { [req.name]: 'Bad SQL!' } } });
2352
2356
  }
2353
2357
  expect(m).not.toTranslate();
2354
- const errList = m.errors().errors;
2358
+ const errList = m.problems();
2355
2359
  expect(errList[0].at).isLocationIn(source.locations[0], source.code);
2356
2360
  });
2357
2361
  test('table struct error location', () => {
@@ -176,7 +176,7 @@ describe('sql:', () => {
176
176
  extModel.importZone.define('sqlblocktest://main', 'query: malloy_source -> { project: * }');
177
177
  const tr = extModel.translate(modelDef);
178
178
  // because extModel is not a TestTranslator we can't use the hotness
179
- expect(tr.errors).toEqual([]);
179
+ expect(tr.problems).toEqual([]);
180
180
  expect(tr.translated).toBeDefined();
181
181
  });
182
182
  });
@@ -284,6 +284,7 @@ class TestTranslator extends parse_malloy_1.MalloyTranslator {
284
284
  this.logger.log({
285
285
  at: this.defaultLocation(),
286
286
  message: `Missing imports: ${whatImports.join(',')}`,
287
+ severity: 'error',
287
288
  });
288
289
  }
289
290
  const needThese = this.schemaZone.getUndefined();
@@ -292,12 +293,14 @@ class TestTranslator extends parse_malloy_1.MalloyTranslator {
292
293
  this.logger.log({
293
294
  at: this.defaultLocation(),
294
295
  message: `Missing schema: ${needThese.join(',')}`,
296
+ severity: 'error',
295
297
  });
296
298
  }
297
299
  if (mysterious) {
298
300
  this.logger.log({
299
301
  at: this.defaultLocation(),
300
302
  message: 'mysterious translation failure',
303
+ severity: 'error',
301
304
  });
302
305
  }
303
306
  }
@@ -12,10 +12,10 @@ import { DocumentHelpContext } from './parse-tree-walkers/document-help-context-
12
12
  export interface FinalResponse {
13
13
  final: true;
14
14
  }
15
- export interface ErrorResponse {
16
- errors: LogMessage[];
15
+ export interface ProblemResponse {
16
+ problems: LogMessage[];
17
17
  }
18
- export declare type FatalResponse = FinalResponse & ErrorResponse;
18
+ export declare type FatalResponse = FinalResponse & ProblemResponse;
19
19
  export interface NeedSchemaData {
20
20
  tables: string[];
21
21
  }
@@ -31,24 +31,24 @@ interface NeededData extends NeedURLData, NeedSchemaData, NeedCompileSQL {
31
31
  export declare type DataRequestResponse = Partial<NeededData> | null;
32
32
  export declare function isNeedResponse(dr: DataRequestResponse): dr is NeededData;
33
33
  export declare type ModelDataRequest = NeedCompileSQL | undefined;
34
- interface ASTData extends ErrorResponse, NeededData, FinalResponse {
34
+ interface ASTData extends ProblemResponse, NeededData, FinalResponse {
35
35
  ast: MalloyElement;
36
36
  }
37
37
  export declare type ASTResponse = Partial<ASTData>;
38
- interface Metadata extends NeededData, ErrorResponse, FinalResponse {
38
+ interface Metadata extends NeededData, ProblemResponse, FinalResponse {
39
39
  symbols: DocumentSymbol[];
40
40
  highlights: DocumentHighlight[];
41
41
  }
42
42
  export declare type MetadataResponse = Partial<Metadata>;
43
- interface Completions extends NeededData, ErrorResponse, FinalResponse {
43
+ interface Completions extends NeededData, ProblemResponse, FinalResponse {
44
44
  completions: DocumentCompletion[];
45
45
  }
46
46
  export declare type CompletionsResponse = Partial<Completions>;
47
- interface HelpContext extends NeededData, ErrorResponse, FinalResponse {
47
+ interface HelpContext extends NeededData, ProblemResponse, FinalResponse {
48
48
  helpContext: DocumentHelpContext | undefined;
49
49
  }
50
50
  export declare type HelpContextResponse = Partial<HelpContext>;
51
- interface TranslatedResponseData extends NeededData, ErrorResponse, FinalResponse {
51
+ interface TranslatedResponseData extends NeededData, ProblemResponse, FinalResponse {
52
52
  translated: {
53
53
  modelDef: ModelDef;
54
54
  queryList: Query[];
package/dist/malloy.d.ts CHANGED
@@ -134,11 +134,11 @@ export declare class Malloy {
134
134
  * A Malloy error, which may contain log messages produced during compilation.
135
135
  */
136
136
  export declare class MalloyError extends Error {
137
+ readonly problems: LogMessage[];
137
138
  /**
138
139
  * An array of log messages produced during compilation.
139
140
  */
140
- readonly log: LogMessage[];
141
- constructor(message: string, log?: LogMessage[]);
141
+ constructor(message: string, problems?: LogMessage[]);
142
142
  }
143
143
  /**
144
144
  * A compiled Malloy document.
@@ -148,7 +148,8 @@ export declare class Model {
148
148
  private queryList;
149
149
  private sqlBlocks;
150
150
  _referenceAt: (location: ModelDocumentPosition) => DocumentReference | undefined;
151
- constructor(modelDef: ModelDef, queryList: InternalQuery[], sqlBlocks: SQLBlockStructDef[], referenceAt?: (location: ModelDocumentPosition) => DocumentReference | undefined);
151
+ readonly problems: LogMessage[];
152
+ constructor(modelDef: ModelDef, queryList: InternalQuery[], sqlBlocks: SQLBlockStructDef[], problems: LogMessage[], referenceAt?: (location: ModelDocumentPosition) => DocumentReference | undefined);
152
153
  /**
153
154
  * Retrieve a document reference for the token at the given position within
154
155
  * the document that produced this model.
package/dist/malloy.js CHANGED
@@ -78,10 +78,10 @@ class Malloy {
78
78
  const result = translator.translate(model === null || model === void 0 ? void 0 : model._modelDef);
79
79
  if (result.final) {
80
80
  if (result.translated) {
81
- return new Model(result.translated.modelDef, result.translated.queryList, result.translated.sqlBlocks, (position) => translator.referenceAt(position));
81
+ return new Model(result.translated.modelDef, result.translated.queryList, result.translated.sqlBlocks, result.problems || [], (position) => translator.referenceAt(position));
82
82
  }
83
83
  else {
84
- const errors = result.errors || [];
84
+ const errors = result.problems || [];
85
85
  const errText = translator.prettyErrors();
86
86
  throw new MalloyError(`Error(s) compiling model:\n${errText}`, errors);
87
87
  }
@@ -304,9 +304,12 @@ exports.Malloy = Malloy;
304
304
  * A Malloy error, which may contain log messages produced during compilation.
305
305
  */
306
306
  class MalloyError extends Error {
307
- constructor(message, log = []) {
307
+ /**
308
+ * An array of log messages produced during compilation.
309
+ */
310
+ constructor(message, problems = []) {
308
311
  super(message);
309
- this.log = log;
312
+ this.problems = problems;
310
313
  }
311
314
  }
312
315
  exports.MalloyError = MalloyError;
@@ -314,11 +317,12 @@ exports.MalloyError = MalloyError;
314
317
  * A compiled Malloy document.
315
318
  */
316
319
  class Model {
317
- constructor(modelDef, queryList, sqlBlocks, referenceAt = () => undefined) {
320
+ constructor(modelDef, queryList, sqlBlocks, problems, referenceAt = () => undefined) {
318
321
  this.modelDef = modelDef;
319
322
  this.queryList = queryList;
320
323
  this.sqlBlocks = sqlBlocks;
321
324
  this._referenceAt = referenceAt;
325
+ this.problems = problems;
322
326
  }
323
327
  /**
324
328
  * Retrieve a document reference for the token at the given position within
@@ -894,7 +898,7 @@ class Explore extends Entity {
894
898
  };
895
899
  }
896
900
  getSingleExploreModel() {
897
- return new Model(this.modelDef, [], []);
901
+ return new Model(this.modelDef, [], [], []);
898
902
  }
899
903
  get fieldMap() {
900
904
  var _a;
@@ -1396,7 +1400,7 @@ class Runtime {
1396
1400
  // be used in tests.
1397
1401
  _loadModelFromModelDef(modelDef) {
1398
1402
  return new ModelMaterializer(this, async () => {
1399
- return new Model(modelDef, [], []);
1403
+ return new Model(modelDef, [], [], []);
1400
1404
  });
1401
1405
  }
1402
1406
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@malloydata/malloy",
3
- "version": "0.0.43-dev230622144455",
3
+ "version": "0.0.43-dev230622180905",
4
4
  "license": "MIT",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",