@malloydata/malloy 0.0.385 → 0.0.387

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 (37) hide show
  1. package/dist/internal.d.ts +2 -0
  2. package/dist/internal.js +3 -1
  3. package/dist/lang/prettify/binary-chain.d.ts +3 -0
  4. package/dist/lang/prettify/binary-chain.js +65 -0
  5. package/dist/lang/prettify/block-body.d.ts +4 -0
  6. package/dist/lang/prettify/block-body.js +87 -0
  7. package/dist/lang/prettify/error-listener.d.ts +6 -0
  8. package/dist/lang/prettify/error-listener.js +19 -0
  9. package/dist/lang/prettify/field-properties.d.ts +3 -0
  10. package/dist/lang/prettify/field-properties.js +57 -0
  11. package/dist/lang/prettify/formatter.d.ts +17 -0
  12. package/dist/lang/prettify/formatter.js +150 -0
  13. package/dist/lang/prettify/import-select.d.ts +3 -0
  14. package/dist/lang/prettify/import-select.js +88 -0
  15. package/dist/lang/prettify/index.d.ts +19 -0
  16. package/dist/lang/prettify/index.js +163 -0
  17. package/dist/lang/prettify/inline-renderer.d.ts +3 -0
  18. package/dist/lang/prettify/inline-renderer.js +101 -0
  19. package/dist/lang/prettify/leaf.d.ts +9 -0
  20. package/dist/lang/prettify/leaf.js +340 -0
  21. package/dist/lang/prettify/out.d.ts +12 -0
  22. package/dist/lang/prettify/out.js +74 -0
  23. package/dist/lang/prettify/pick-case.d.ts +5 -0
  24. package/dist/lang/prettify/pick-case.js +222 -0
  25. package/dist/lang/prettify/rules.d.ts +13 -0
  26. package/dist/lang/prettify/rules.js +111 -0
  27. package/dist/lang/prettify/sections.d.ts +4 -0
  28. package/dist/lang/prettify/sections.js +380 -0
  29. package/dist/lang/prettify/tokens.d.ts +13 -0
  30. package/dist/lang/prettify/tokens.js +185 -0
  31. package/dist/lang/prettify/types.d.ts +9 -0
  32. package/dist/lang/prettify/types.js +7 -0
  33. package/dist/lang/run-malloy-parser.d.ts +23 -0
  34. package/dist/lang/run-malloy-parser.js +32 -8
  35. package/dist/version.d.ts +1 -1
  36. package/dist/version.js +1 -1
  37. package/package.json +4 -4
@@ -1,3 +1,5 @@
1
1
  export { mkArrayDef, mkArrayTypeDef, mkFieldDef, mkModelDef, mkQuerySourceDef, mkSQLSourceDef, mkTableSourceDef, pathToKey, } from './model';
2
2
  export { TinyParseError, TinyParser } from './dialect/tiny_parser';
3
3
  export type { TinyToken } from './dialect/tiny_parser';
4
+ export { prettify } from './lang/prettify';
5
+ export type { PrettifyResult, PrettifyError } from './lang/prettify';
package/dist/internal.js CHANGED
@@ -4,7 +4,7 @@
4
4
  * SPDX-License-Identifier: MIT
5
5
  */
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.TinyParser = exports.TinyParseError = exports.pathToKey = exports.mkTableSourceDef = exports.mkSQLSourceDef = exports.mkQuerySourceDef = exports.mkModelDef = exports.mkFieldDef = exports.mkArrayTypeDef = exports.mkArrayDef = void 0;
7
+ exports.prettify = exports.TinyParser = exports.TinyParseError = exports.pathToKey = exports.mkTableSourceDef = exports.mkSQLSourceDef = exports.mkQuerySourceDef = exports.mkModelDef = exports.mkFieldDef = exports.mkArrayTypeDef = exports.mkArrayDef = void 0;
8
8
  // Unstable implementation-facing exports for Malloy packages, tests, and
9
9
  // advanced integrations. Do not treat this surface as public API.
10
10
  var model_1 = require("./model");
@@ -19,4 +19,6 @@ Object.defineProperty(exports, "pathToKey", { enumerable: true, get: function ()
19
19
  var tiny_parser_1 = require("./dialect/tiny_parser");
20
20
  Object.defineProperty(exports, "TinyParseError", { enumerable: true, get: function () { return tiny_parser_1.TinyParseError; } });
21
21
  Object.defineProperty(exports, "TinyParser", { enumerable: true, get: function () { return tiny_parser_1.TinyParser; } });
22
+ var prettify_1 = require("./lang/prettify");
23
+ Object.defineProperty(exports, "prettify", { enumerable: true, get: function () { return prettify_1.prettify; } });
22
24
  //# sourceMappingURL=internal.js.map
@@ -0,0 +1,3 @@
1
+ import { ParserRuleContext } from 'antlr4ts';
2
+ import type { Formatter } from './formatter';
3
+ export declare function formatBinaryChain(f: Formatter, ctx: ParserRuleContext): void;
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ /*
3
+ * Copyright Contributors to the Malloy project
4
+ * SPDX-License-Identifier: MIT
5
+ *
6
+ * RULE: BINARY CHAIN — formatBinaryChain
7
+ *
8
+ * Handles `and`/`or`/`??`/`+`/`-` chains. The grammar is left-recursive, so a
9
+ * chain `a + b + c` parses as `((a + b) + c)`. Only the OUTERMOST chain
10
+ * context emits; inner same-class contexts fall through to default recursion
11
+ * so the outer can collect all operands.
12
+ *
13
+ * Inline if it fits. Otherwise: first operand inline; each subsequent
14
+ * operator+operand on its own line at +1 indent (leading-operator style).
15
+ *
16
+ * We deliberately do NOT break at comparison operators — see prettify header.
17
+ */
18
+ Object.defineProperty(exports, "__esModule", { value: true });
19
+ exports.formatBinaryChain = formatBinaryChain;
20
+ const antlr4ts_1 = require("antlr4ts");
21
+ const tree_1 = require("antlr4ts/tree");
22
+ const tokens_1 = require("./tokens");
23
+ const leaf_1 = require("./leaf");
24
+ function formatBinaryChain(f, ctx) {
25
+ // Same chain class as our parent? Then we're an inner node of the chain —
26
+ // let the outermost one collect all operands and emit.
27
+ if (ctx.parent && ctx.parent.constructor === ctx.constructor) {
28
+ for (let i = 0; i < ctx.childCount; i++)
29
+ f.format(ctx.getChild(i));
30
+ return;
31
+ }
32
+ const operands = [];
33
+ const operators = [];
34
+ const collect = (n) => {
35
+ if (n instanceof antlr4ts_1.ParserRuleContext && n.constructor === ctx.constructor) {
36
+ // Inner same-class chain node. Grammar guarantees getChild(1) is a
37
+ // TerminalNode (the operator); the guard makes that explicit without
38
+ // a cast.
39
+ collect(n.getChild(0));
40
+ const op = n.getChild(1);
41
+ if (op instanceof tree_1.TerminalNode)
42
+ operators.push(op);
43
+ operands.push(n.getChild(2));
44
+ }
45
+ else {
46
+ operands.push(n);
47
+ }
48
+ };
49
+ collect(ctx);
50
+ const inlineLen = (0, leaf_1.approxInlineSpan)(f, ctx._start.tokenIndex, ctx._stop.tokenIndex);
51
+ if (f.o.lineLengthSoFar() + 1 + inlineLen <= tokens_1.LINE_BUDGET) {
52
+ for (let i = 0; i < ctx.childCount; i++)
53
+ f.format(ctx.getChild(i));
54
+ return;
55
+ }
56
+ f.format(operands[0]);
57
+ f.o.indent++;
58
+ for (let i = 0; i < operators.length; i++) {
59
+ f.o.nl();
60
+ f.format(operators[i]);
61
+ f.format(operands[i + 1]);
62
+ }
63
+ f.o.indent--;
64
+ }
65
+ //# sourceMappingURL=binary-chain.js.map
@@ -0,0 +1,4 @@
1
+ import { ParserRuleContext } from 'antlr4ts';
2
+ import type { Formatter } from './formatter';
3
+ export declare function formatTopLevel(f: Formatter, ctx: ParserRuleContext): void;
4
+ export declare function formatBlockBody(f: Formatter, ctx: ParserRuleContext): void;
@@ -0,0 +1,87 @@
1
+ "use strict";
2
+ /*
3
+ * Copyright Contributors to the Malloy project
4
+ * SPDX-License-Identifier: MIT
5
+ *
6
+ * RULE: BLOCK BODY
7
+ *
8
+ * A `{ … }` body containing statements (extend body, view body, etc.). Walks
9
+ * children; between adjacent statements:
10
+ * - `view:` definitions always get a blank line before them (and after
11
+ * the previous one), regardless of whether the source had a blank or
12
+ * what kind preceded — view definitions read as their own sections.
13
+ * - For other kinds: preserve a single user-supplied blank line only if
14
+ * the kinds differ. Same-kind adjacent statements (consecutive
15
+ * dimensions, measures, etc.) never get a blank.
16
+ *
17
+ * Also: top-level body — forces a blank line before each statement after the
18
+ * first, regardless of source spacing (top-level statements should breathe).
19
+ */
20
+ Object.defineProperty(exports, "__esModule", { value: true });
21
+ exports.formatTopLevel = formatTopLevel;
22
+ exports.formatBlockBody = formatBlockBody;
23
+ const antlr4ts_1 = require("antlr4ts");
24
+ const tree_1 = require("antlr4ts/tree");
25
+ const rules_1 = require("./rules");
26
+ const tokens_1 = require("./tokens");
27
+ const leaf_1 = require("./leaf");
28
+ function statementKind(ctx) {
29
+ for (const r of rules_1.STATEMENT_KIND_BY_CTX) {
30
+ if (ctx instanceof r.ctxClass)
31
+ return r.kind;
32
+ }
33
+ return ctx.constructor.name;
34
+ }
35
+ function formatTopLevel(f, ctx) {
36
+ let emittedFirst = false;
37
+ for (let i = 0; i < ctx.childCount; i++) {
38
+ const c = ctx.getChild(i);
39
+ if (c instanceof tree_1.TerminalNode) {
40
+ const tok = c.symbol;
41
+ if (tok.type !== antlr4ts_1.Token.EOF)
42
+ (0, leaf_1.emitVisibleToken)(f, tok, tok.tokenIndex);
43
+ continue;
44
+ }
45
+ if (c instanceof antlr4ts_1.ParserRuleContext) {
46
+ if (emittedFirst)
47
+ f.needBlank = true;
48
+ f.format(c);
49
+ emittedFirst = true;
50
+ }
51
+ }
52
+ }
53
+ function formatBlockBody(f, ctx) {
54
+ let lastChild = null;
55
+ let lastChildEndLine = 0;
56
+ for (let i = 0; i < ctx.childCount; i++) {
57
+ const c = ctx.getChild(i);
58
+ if (c instanceof tree_1.TerminalNode) {
59
+ // OCURLY / CCURLY / SEMI — let the leaf walker handle them.
60
+ const tok = c.symbol;
61
+ if (tok.type !== antlr4ts_1.Token.EOF)
62
+ (0, leaf_1.emitVisibleToken)(f, tok, tok.tokenIndex);
63
+ continue;
64
+ }
65
+ if (c instanceof antlr4ts_1.ParserRuleContext) {
66
+ if (lastChild !== null) {
67
+ const userHadBlank = c._start.line - lastChildEndLine > 1;
68
+ const lastKind = statementKind(lastChild);
69
+ const curKind = statementKind(c);
70
+ const sameKind = lastKind === curKind;
71
+ // `view:` definitions always breathe — blank line above each one
72
+ // (and after the previous one) regardless of the user's source
73
+ // spacing or what kind preceded.
74
+ if (curKind === 'view' || lastKind === 'view') {
75
+ f.o.blank();
76
+ }
77
+ else if (userHadBlank && !sameKind) {
78
+ f.o.blank();
79
+ }
80
+ }
81
+ f.format(c);
82
+ lastChild = c;
83
+ lastChildEndLine = (0, tokens_1.endLineOf)(c._stop);
84
+ }
85
+ }
86
+ }
87
+ //# sourceMappingURL=block-body.js.map
@@ -0,0 +1,6 @@
1
+ import type { ANTLRErrorListener, RecognitionException, Recognizer } from 'antlr4ts';
2
+ import type { PrettifyError } from './types';
3
+ export declare class CollectingErrorListener implements ANTLRErrorListener<any> {
4
+ errors: PrettifyError[];
5
+ syntaxError<T>(_recognizer: Recognizer<T, any>, _offendingSymbol: T | undefined, line: number, charPositionInLine: number, msg: string, _e: RecognitionException | undefined): void;
6
+ }
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ /*
3
+ * Copyright Contributors to the Malloy project
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.CollectingErrorListener = void 0;
8
+ /* eslint-disable @typescript-eslint/no-explicit-any */
9
+ class CollectingErrorListener {
10
+ constructor() {
11
+ this.errors = [];
12
+ }
13
+ syntaxError(_recognizer, _offendingSymbol, line, charPositionInLine, msg, _e) {
14
+ this.errors.push({ message: msg, line, column: charPositionInLine });
15
+ }
16
+ }
17
+ exports.CollectingErrorListener = CollectingErrorListener;
18
+ /* eslint-enable @typescript-eslint/no-explicit-any */
19
+ //# sourceMappingURL=error-listener.js.map
@@ -0,0 +1,3 @@
1
+ import type * as parser from '../lib/Malloy/MalloyParser';
2
+ import type { Formatter } from './formatter';
3
+ export declare function formatFieldProperties(f: Formatter, ctx: parser.FieldPropertiesContext): void;
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ /*
3
+ * Copyright Contributors to the Malloy project
4
+ * SPDX-License-Identifier: MIT
5
+ *
6
+ * RULE: POSTFIX `{…}` — formatFieldProperties
7
+ *
8
+ * `expr { kw: ... }` — filter shortcut and friends. Inline if it fits;
9
+ * otherwise emit as a block with each inner statement on its own line. Inner
10
+ * statements are rendered atomically via formatTokenRange (no recursive
11
+ * section-list rewriting): they're part of the expression.
12
+ */
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.formatFieldProperties = formatFieldProperties;
15
+ const antlr4ts_1 = require("antlr4ts");
16
+ const tokens_1 = require("./tokens");
17
+ const leaf_1 = require("./leaf");
18
+ const inline_renderer_1 = require("./inline-renderer");
19
+ function formatFieldProperties(f, ctx) {
20
+ const startIdx = ctx._start.tokenIndex;
21
+ const stopIdx = ctx._stop.tokenIndex;
22
+ const hasComments = (0, leaf_1.hasCommentsInRange)(f, startIdx, stopIdx);
23
+ if (!hasComments) {
24
+ const inline = (0, inline_renderer_1.renderItemInline)(f, ctx);
25
+ if (f.o.lineLengthSoFar() + 1 + inline.length <= tokens_1.LINE_BUDGET) {
26
+ f.o.space();
27
+ f.o.text(inline);
28
+ (0, leaf_1.note)(f, tokens_1.L.CCURLY, stopIdx, ctx._stop);
29
+ return;
30
+ }
31
+ }
32
+ // Wrapped form. Each inner statement runs through the leaf walker
33
+ // (formatTokenRange) so comments inside it are preserved naturally.
34
+ f.o.space();
35
+ f.o.text('{');
36
+ f.o.indent++;
37
+ // Advance past the OCURLY ourselves so flushHiddenBefore for the first inner
38
+ // statement doesn't try to re-emit it.
39
+ f.lastEmittedIdx = startIdx;
40
+ for (let i = 0; i < ctx.childCount; i++) {
41
+ const c = ctx.getChild(i);
42
+ // Skip OCURLY / CCURLY / SEMI; only inner statement contexts get walked.
43
+ if (!(c instanceof antlr4ts_1.ParserRuleContext))
44
+ continue;
45
+ f.o.nl();
46
+ (0, leaf_1.formatTokenRange)(f, c._start.tokenIndex, c._stop.tokenIndex);
47
+ }
48
+ // Flush any tail hidden tokens between the last inner statement and the
49
+ // closing `}` so trailing comments emit at the inner indent rather than
50
+ // disappearing.
51
+ (0, leaf_1.flushHiddenBefore)(f, stopIdx);
52
+ f.o.indent--;
53
+ f.o.nl();
54
+ f.o.text('}');
55
+ (0, leaf_1.note)(f, tokens_1.L.CCURLY, stopIdx, ctx._stop);
56
+ }
57
+ //# sourceMappingURL=field-properties.js.map
@@ -0,0 +1,17 @@
1
+ import { Token } from 'antlr4ts';
2
+ import type { ParseTree } from 'antlr4ts/tree';
3
+ import { Out } from './out';
4
+ export declare class Formatter {
5
+ readonly src: string;
6
+ readonly tokens: Token[];
7
+ o: Out;
8
+ lastEmittedIdx: number;
9
+ lastEmittedType: number | null;
10
+ prevTokenEndLine: number;
11
+ needBlank: boolean;
12
+ parenDepth: number;
13
+ parenBreaks: boolean[];
14
+ private rootFormatted;
15
+ constructor(src: string, tokens: Token[]);
16
+ format(node: ParseTree): void;
17
+ }
@@ -0,0 +1,150 @@
1
+ "use strict";
2
+ /*
3
+ * Copyright Contributors to the Malloy project
4
+ * SPDX-License-Identifier: MIT
5
+ *
6
+ * Formatter: per-format-call state container plus the parse-tree dispatcher.
7
+ *
8
+ * State (Out buffer, last-emitted token tracking, paren-depth stack) is
9
+ * mutable and read/written directly by the per-rule free functions in sibling
10
+ * modules. The dispatcher is the only method on the class — it routes each
11
+ * parse-tree node to the appropriate per-rule formatter, falling back to
12
+ * left-to-right child recursion.
13
+ *
14
+ * The class itself is not exported beyond ./index, so its fields being
15
+ * "package-public" is hygiene only — no external API leakage.
16
+ */
17
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
18
+ if (k2 === undefined) k2 = k;
19
+ var desc = Object.getOwnPropertyDescriptor(m, k);
20
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
21
+ desc = { enumerable: true, get: function() { return m[k]; } };
22
+ }
23
+ Object.defineProperty(o, k2, desc);
24
+ }) : (function(o, m, k, k2) {
25
+ if (k2 === undefined) k2 = k;
26
+ o[k2] = m[k];
27
+ }));
28
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
29
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
30
+ }) : function(o, v) {
31
+ o["default"] = v;
32
+ });
33
+ var __importStar = (this && this.__importStar) || (function () {
34
+ var ownKeys = function(o) {
35
+ ownKeys = Object.getOwnPropertyNames || function (o) {
36
+ var ar = [];
37
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
38
+ return ar;
39
+ };
40
+ return ownKeys(o);
41
+ };
42
+ return function (mod) {
43
+ if (mod && mod.__esModule) return mod;
44
+ var result = {};
45
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
46
+ __setModuleDefault(result, mod);
47
+ return result;
48
+ };
49
+ })();
50
+ Object.defineProperty(exports, "__esModule", { value: true });
51
+ exports.Formatter = void 0;
52
+ const antlr4ts_1 = require("antlr4ts");
53
+ const tree_1 = require("antlr4ts/tree");
54
+ const parser = __importStar(require("../lib/Malloy/MalloyParser"));
55
+ const out_1 = require("./out");
56
+ const rules_1 = require("./rules");
57
+ const leaf_1 = require("./leaf");
58
+ const block_body_1 = require("./block-body");
59
+ const sections_1 = require("./sections");
60
+ const field_properties_1 = require("./field-properties");
61
+ const pick_case_1 = require("./pick-case");
62
+ const binary_chain_1 = require("./binary-chain");
63
+ const import_select_1 = require("./import-select");
64
+ class Formatter {
65
+ constructor(src, tokens) {
66
+ this.src = src;
67
+ this.tokens = tokens;
68
+ this.o = new out_1.Out();
69
+ // -- Per-token state (updated by `note(f, ...)` after every token emit) --
70
+ // Index of the last token (visible or implicitly skipped) we've accounted
71
+ // for. flushHiddenBefore won't re-emit anything at or before this index.
72
+ this.lastEmittedIdx = -1;
73
+ // Type of the last visible token emitted. Drives spacing decisions
74
+ // (e.g. CALL_HUG_AFTER membership for `(`).
75
+ this.lastEmittedType = null;
76
+ // 1-based line in the SOURCE where the last emitted token ended. Used to
77
+ // distinguish trailing-comments (same line) from leading-comments (different
78
+ // line).
79
+ this.prevTokenEndLine = 0;
80
+ // After end-of-top-level-statement, the next statement-starter gets a blank
81
+ // line. Consumed once, then reset.
82
+ this.needBlank = false;
83
+ // -- Paren-pair state --
84
+ this.parenDepth = 0;
85
+ // For each open paren-pair: did we choose to break args/content across
86
+ // lines? Stack matches parenDepth.
87
+ this.parenBreaks = [];
88
+ // Set when format() is invoked at the top level (a MalloyDocument). Guards
89
+ // against accidental reuse of a Formatter instance — the Out buffer
90
+ // accumulates and would emit garbage on a second call. Construct a fresh
91
+ // Formatter per top-level call.
92
+ this.rootFormatted = false;
93
+ }
94
+ format(node) {
95
+ if (node instanceof tree_1.TerminalNode) {
96
+ const tok = node.symbol;
97
+ if (tok.type !== antlr4ts_1.Token.EOF)
98
+ (0, leaf_1.emitVisibleToken)(this, tok, tok.tokenIndex);
99
+ return;
100
+ }
101
+ if (!(node instanceof antlr4ts_1.ParserRuleContext))
102
+ return;
103
+ // RULE: TOP-LEVEL BODY — one blank line between adjacent statements.
104
+ if (node instanceof parser.MalloyDocumentContext) {
105
+ if (this.rootFormatted) {
106
+ throw new Error('Formatter is single-use; construct a new instance per top-level format call');
107
+ }
108
+ this.rootFormatted = true;
109
+ return (0, block_body_1.formatTopLevel)(this, node);
110
+ }
111
+ // RULE: POSTFIX `{…}` — filter shortcut etc.
112
+ if (node instanceof parser.FieldPropertiesContext) {
113
+ return (0, field_properties_1.formatFieldProperties)(this, node);
114
+ }
115
+ // RULE: BLOCK BODY — walk children, blank-lines between different kinds.
116
+ if (node instanceof parser.ExplorePropertiesContext ||
117
+ node instanceof parser.QueryPropertiesContext ||
118
+ node instanceof parser.QueryExtendStatementListContext) {
119
+ return (0, block_body_1.formatBlockBody)(this, node);
120
+ }
121
+ // RULE: SECTION-STATEMENT — table-driven dispatch.
122
+ for (const rule of rules_1.SECTION_STATEMENT_RULES) {
123
+ if (node instanceof rule.ctxClass) {
124
+ return (0, sections_1.formatSectionStatement)(this, node, rule);
125
+ }
126
+ }
127
+ // RULE: IMPORT SELECT — `import {a, b} from 'x'` stays compact.
128
+ if (node instanceof parser.ImportSelectContext) {
129
+ return (0, import_select_1.formatImportSelect)(this, node);
130
+ }
131
+ // RULE: PICK / CASE / BINARY CHAIN.
132
+ if (node instanceof parser.PickStatementContext)
133
+ return (0, pick_case_1.formatPickStatement)(this, node);
134
+ if (node instanceof parser.PickContext)
135
+ return (0, pick_case_1.formatPick)(this, node);
136
+ if (node instanceof parser.CaseStatementContext)
137
+ return (0, pick_case_1.formatCaseStatement)(this, node);
138
+ if (node instanceof parser.ExprLogicalAndContext ||
139
+ node instanceof parser.ExprLogicalOrContext ||
140
+ node instanceof parser.ExprCoalesceContext ||
141
+ node instanceof parser.ExprAddSubContext) {
142
+ return (0, binary_chain_1.formatBinaryChain)(this, node);
143
+ }
144
+ // Default: recurse on children left-to-right.
145
+ for (let i = 0; i < node.childCount; i++)
146
+ this.format(node.getChild(i));
147
+ }
148
+ }
149
+ exports.Formatter = Formatter;
150
+ //# sourceMappingURL=formatter.js.map
@@ -0,0 +1,3 @@
1
+ import type * as parser from '../lib/Malloy/MalloyParser';
2
+ import type { Formatter } from './formatter';
3
+ export declare function formatImportSelect(f: Formatter, ctx: parser.ImportSelectContext): void;
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+ /*
3
+ * Copyright Contributors to the Malloy project
4
+ * SPDX-License-Identifier: MIT
5
+ *
6
+ * RULE: IMPORT SELECT — `import {a, b, c} from 'url'`
7
+ *
8
+ * The selection list is `{ id (IS id)? (, id (IS id)?)* }`. Inline if the
9
+ * whole brace-and-contents fits on the current line. Otherwise wrap with
10
+ * each item on its own line at +1 indent.
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.formatImportSelect = formatImportSelect;
14
+ const tokens_1 = require("./tokens");
15
+ const leaf_1 = require("./leaf");
16
+ const inline_renderer_1 = require("./inline-renderer");
17
+ function formatImportSelect(f, ctx) {
18
+ // Flush hidden tokens between the previous emit (IMPORT) and our opener
19
+ // so a comment like `import /* tag */ {a} from 'x'` is preserved.
20
+ (0, leaf_1.flushHiddenBefore)(f, ctx._start.tokenIndex);
21
+ const items = ctx.importItem();
22
+ // Grammar puts FROM as the last token of importSelect: emit it ourselves
23
+ // so the trailing space and lastEmittedIdx land correctly.
24
+ const fromTok = ctx.FROM().symbol;
25
+ const fromIdx = fromTok.tokenIndex;
26
+ if (items.length === 0) {
27
+ f.o.space();
28
+ f.o.text('{} from');
29
+ (0, leaf_1.note)(f, tokens_1.L.FROM, fromIdx, fromTok);
30
+ return;
31
+ }
32
+ const firstItem = items[0];
33
+ const lastItem = items[items.length - 1];
34
+ // Comments anywhere in the items' span (between items, inside an `as is`
35
+ // form, etc.) get stripped by renderItemInline. Fall back to a comment-
36
+ // safe wrap that emits each item via f.format — the leaf walker handles
37
+ // hidden-channel placement.
38
+ const itemsHaveComments = (0, leaf_1.hasCommentsInRange)(f, firstItem._start.tokenIndex, lastItem._stop.tokenIndex);
39
+ if (!itemsHaveComments) {
40
+ const itemStrs = items.map(it => (0, inline_renderer_1.renderItemInline)(f, it));
41
+ const inlineBody = '{' + itemStrs.join(', ') + '} from';
42
+ if (f.o.lineLengthSoFar() + 1 + inlineBody.length <= tokens_1.LINE_BUDGET) {
43
+ f.o.space();
44
+ f.o.text(inlineBody);
45
+ (0, leaf_1.note)(f, tokens_1.L.FROM, fromIdx, fromTok);
46
+ return;
47
+ }
48
+ // Wrap form (no comments): one item per line at +1 indent. Pre-rendered
49
+ // text is fine because renderItemInline saw no comments to drop.
50
+ f.o.space();
51
+ f.o.text('{');
52
+ f.o.indent++;
53
+ for (let i = 0; i < itemStrs.length; i++) {
54
+ f.o.nl();
55
+ f.o.text(itemStrs[i]);
56
+ if (i < itemStrs.length - 1)
57
+ f.o.text(',');
58
+ }
59
+ f.o.indent--;
60
+ f.o.nl();
61
+ f.o.text('} from');
62
+ (0, leaf_1.note)(f, tokens_1.L.FROM, fromIdx, fromTok);
63
+ return;
64
+ }
65
+ // Comment-safe wrap: each item emits via f.format so flushHiddenBefore
66
+ // can place its leading/inter-item comments correctly. Trailing `,` after
67
+ // each non-last item, leaf walker turns it into a newline at indent.
68
+ f.o.space();
69
+ f.o.text('{');
70
+ f.o.indent++;
71
+ // Advance past the OCURLY we just emitted manually so the first item's
72
+ // flushHiddenBefore doesn't try to re-emit it.
73
+ f.lastEmittedIdx = ctx._start.tokenIndex;
74
+ for (let i = 0; i < items.length; i++) {
75
+ (0, leaf_1.flushHiddenBefore)(f, items[i]._start.tokenIndex);
76
+ f.o.nl();
77
+ f.format(items[i]);
78
+ if (i < items.length - 1)
79
+ f.o.text(',');
80
+ }
81
+ // Catch any tail comments between the last item and the closing `}`.
82
+ (0, leaf_1.flushHiddenBefore)(f, fromIdx);
83
+ f.o.indent--;
84
+ f.o.nl();
85
+ f.o.text('} from');
86
+ (0, leaf_1.note)(f, tokens_1.L.FROM, fromIdx, fromTok);
87
+ }
88
+ //# sourceMappingURL=import-select.js.map
@@ -0,0 +1,19 @@
1
+ import type { PrettifyResult } from './types';
2
+ export type { PrettifyError, PrettifyResult } from './types';
3
+ /**
4
+ * Pretty-print a Malloy source string.
5
+ *
6
+ * **Experimental — this API may vanish or change at any time without notice.**
7
+ * It is exposed only via `@malloydata/malloy/internal` and is not covered by
8
+ * any compatibility commitment. Do not depend on it from anything you can't
9
+ * fix in a single PR.
10
+ *
11
+ * Parses the input, walks the parse tree, and emits a reformatted string.
12
+ *
13
+ * `errors` surfaces parse errors only (lexer + parser). Semantic / compile
14
+ * errors aren't checked here. If `errors.length > 0` you have a bigger problem
15
+ * than formatting — output is best-effort and not guaranteed to round-trip.
16
+ *
17
+ * @experimental
18
+ */
19
+ export declare function prettify(src: string): PrettifyResult;