@prisma-next/psl-parser 0.16.0-dev.30 → 0.16.0-dev.31

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.
@@ -1 +1 @@
1
- {"version":3,"file":"format.d.mts","names":[],"sources":["../src/format/options.ts","../src/format/format.ts"],"mappings":";UAAiB;WACN;WACA;;;;iBCGK,OAAO,gBAAgB,UAAU"}
1
+ {"version":3,"file":"format.d.mts","names":[],"sources":["../src/format/options.ts","../src/format/format.ts"],"mappings":";UAEiB;WACN;WACA;;;;iBCCK,OAAO,gBAAgB,UAAU"}
package/dist/format.mjs CHANGED
@@ -442,9 +442,15 @@ function pslError(code, message, options) {
442
442
  //#region src/format/options.ts
443
443
  function resolveFormatOptions(options) {
444
444
  const indent = options?.indent ?? 2;
445
- if (indent !== "tab" && (typeof indent !== "number" || !Number.isInteger(indent) || indent < 1)) throw new TypeError(`Invalid format options: indent must be a positive integer or 'tab', got ${String(indent)}`);
445
+ if (indent !== "tab" && (typeof indent !== "number" || !Number.isInteger(indent) || indent < 1)) throw pslError("PSL.FORMAT_OPTION_INVALID", `Invalid format options: indent must be a positive integer or 'tab', got ${String(indent)}`, { meta: {
446
+ option: "indent",
447
+ received: String(indent)
448
+ } });
446
449
  const newline = options?.newline ?? "LF";
447
- if (newline !== "LF" && newline !== "CRLF") throw new TypeError(`Invalid format options: newline must be 'LF' or 'CRLF', got ${String(newline)}`);
450
+ if (newline !== "LF" && newline !== "CRLF") throw pslError("PSL.FORMAT_OPTION_INVALID", `Invalid format options: newline must be 'LF' or 'CRLF', got ${String(newline)}`, { meta: {
451
+ option: "newline",
452
+ received: String(newline)
453
+ } });
448
454
  return {
449
455
  indentUnit: indent === "tab" ? " " : " ".repeat(indent),
450
456
  newline: newline === "CRLF" ? "\r\n" : "\n"
@@ -1 +1 @@
1
- {"version":3,"file":"format.mjs","names":["#indentUnit","#newline","#out","#depth","#lastWasBlank","#lineOpen","#prevKind","#line","#hasContent"],"sources":["../src/format/emit.ts","../src/format/error.ts","../src/format/options.ts","../src/format/format.ts"],"sourcesContent":["import { ModelAttributeAst } from '../syntax/ast/attributes';\nimport {\n CompositeTypeDeclarationAst,\n type DocumentAst,\n FieldDeclarationAst,\n GenericBlockDeclarationAst,\n KeyValuePairAst,\n ModelDeclarationAst,\n NamedTypeDeclarationAst,\n NamespaceDeclarationAst,\n TypesBlockAst,\n} from '../syntax/ast/declarations';\nimport { type SyntaxElement, SyntaxNode, type SyntaxToken } from '../syntax/red';\nimport type { TokenKind } from '../tokenizer';\n\nexport function emitDocument(document: DocumentAst, indentUnit: string, newline: string): string {\n const writer = new LineWriter(indentUnit, newline);\n emitTopLevel(writer, document);\n return writer.finish();\n}\n\nclass LineWriter {\n readonly #indentUnit: string;\n readonly #newline: string;\n readonly #out: string[] = [];\n #depth = 0;\n #line = '';\n #lineOpen = false;\n #prevKind: TokenKind | undefined;\n #lastWasBlank = false;\n #hasContent = false;\n\n constructor(indentUnit: string, newline: string) {\n this.#indentUnit = indentUnit;\n this.#newline = newline;\n }\n\n indent(): void {\n this.#depth += 1;\n }\n\n unindent(): void {\n this.#depth = Math.max(0, this.#depth - 1);\n }\n\n lastIsBlank(): boolean {\n return this.#lastWasBlank;\n }\n\n lineOpen(): boolean {\n return this.#lineOpen;\n }\n\n prevKind(): TokenKind | undefined {\n return this.#prevKind;\n }\n\n newline(): void {\n if (!this.#lineOpen) return;\n this.#out.push(`${this.#indentUnit.repeat(this.#depth)}${this.#line}`);\n this.#line = '';\n this.#lineOpen = false;\n this.#prevKind = undefined;\n this.#lastWasBlank = false;\n this.#hasContent = true;\n }\n\n blank(): void {\n this.newline();\n if (!this.#hasContent || this.#lastWasBlank) return;\n this.#out.push('');\n this.#lastWasBlank = true;\n }\n\n write(token: SyntaxToken, space: boolean, padTo?: number): void {\n if (this.#lineOpen && padTo !== undefined) {\n this.#line = this.#line.padEnd(padTo);\n } else if (this.#lineOpen && space) {\n this.#line += ' ';\n }\n this.#line += token.text;\n this.#lineOpen = true;\n this.#prevKind = token.kind;\n }\n\n writeRaw(text: string): void {\n this.#line += text;\n this.#lineOpen = true;\n }\n\n comment(text: string): void {\n if (this.#lineOpen) this.#line += ` ${text}`;\n else this.#line = text;\n this.#lineOpen = true;\n this.newline();\n }\n\n finish(): string {\n this.newline();\n const body = this.#out.join(this.#newline);\n return body.length > 0 ? `${body}${this.#newline}` : '';\n }\n}\n\n// Qualified-name separators hug; argument/object colons keep the usual value space.\nfunction spaceBetween(\n prev: TokenKind | undefined,\n cur: TokenKind,\n inQualifiedName: boolean,\n): boolean {\n if (prev === undefined) return false;\n if (inQualifiedName) return false;\n\n switch (cur) {\n case 'LParen':\n case 'LBracket':\n case 'RParen':\n case 'RBracket':\n case 'Comma':\n case 'Question':\n case 'Dot':\n case 'Colon':\n return false;\n case 'RBrace':\n return prev !== 'LBrace';\n default:\n break;\n }\n switch (prev) {\n case 'LParen':\n case 'LBracket':\n case 'Dot':\n case 'At':\n case 'DoubleAt':\n return false;\n default:\n return true;\n }\n}\n\nfunction streamNode(writer: LineWriter, node: SyntaxNode, padTo?: number): number {\n let continuation = 0;\n let first = true;\n let prevQualified = false;\n\n const walk = (parent: SyntaxNode, qualified: boolean): void => {\n for (const child of parent.children()) {\n if (child instanceof SyntaxNode) {\n walk(child, qualified || child.kind === 'QualifiedName');\n continue;\n }\n if (child.kind === 'Whitespace' || child.kind === 'Newline') continue;\n if (child.kind === 'Comment') {\n writer.comment(child.text);\n writer.indent();\n continuation += 1;\n prevQualified = false;\n first = false;\n continue;\n }\n const pad = first ? padTo : undefined;\n const space = spaceBetween(writer.prevKind(), child.kind, qualified && prevQualified);\n writer.write(child, space, writer.lineOpen() ? pad : undefined);\n prevQualified = qualified;\n first = false;\n }\n };\n\n walk(node, false);\n return continuation;\n}\n\nfunction closeContinuation(writer: LineWriter, count: number): void {\n for (let i = 0; i < count; i++) writer.unindent();\n}\n\nfunction emitField(\n writer: LineWriter,\n field: FieldDeclarationAst,\n columns: AlignmentColumns | undefined,\n): number {\n return streamRow(writer, field.syntax, columns);\n}\n\nfunction emitNamedType(writer: LineWriter, decl: NamedTypeDeclarationAst): number {\n return streamRow(writer, decl.syntax, undefined);\n}\n\nfunction streamRow(\n writer: LineWriter,\n row: SyntaxNode,\n columns: AlignmentColumns | undefined,\n): number {\n let continuation = 0;\n let sawAttribute = false;\n\n for (const child of row.children()) {\n if (child instanceof SyntaxNode) {\n let padTo: number | undefined;\n if (child.kind === 'TypeAnnotation' && continuation === 0) {\n padTo = columns?.typeColumn;\n } else if (child.kind === 'FieldAttribute') {\n if (continuation > 0) writer.newline();\n else if (!sawAttribute) padTo = columns?.attributeColumn;\n sawAttribute = true;\n }\n continuation += streamNode(writer, child, padTo);\n continue;\n }\n if (child.kind === 'Whitespace' || child.kind === 'Newline') continue;\n if (child.kind === 'Comment') {\n writer.comment(child.text);\n writer.indent();\n continuation += 1;\n continue;\n }\n const space = spaceBetween(writer.prevKind(), child.kind, false);\n writer.write(child, space);\n }\n\n return continuation;\n}\n\nfunction emitBlockAttribute(writer: LineWriter, attribute: ModelAttributeAst): number {\n return streamNode(writer, attribute.syntax);\n}\n\nfunction emitKeyValue(writer: LineWriter, pair: KeyValuePairAst): number {\n return streamNode(writer, pair.syntax);\n}\n\ntype MemberCategory = 'regular' | 'blockAttribute' | 'nestedBlock';\n\ninterface BlockMember {\n readonly category: MemberCategory;\n emit(trailing: string | undefined): number;\n}\n\nfunction leafMember(\n writer: LineWriter,\n category: MemberCategory,\n print: () => number,\n): BlockMember {\n return {\n category,\n emit(trailing) {\n const continuation = print();\n if (trailing !== undefined) writer.comment(trailing);\n else writer.newline();\n return continuation;\n },\n };\n}\n\ntype MemberClassifier = (node: SyntaxNode) => BlockMember | undefined;\n\nfunction emitModel(\n writer: LineWriter,\n model: ModelDeclarationAst,\n trailing: string | undefined,\n): void {\n const columns = alignmentMap(model.syntax);\n emitBlockBody(writer, model.syntax, trailing, (node) => {\n const field = FieldDeclarationAst.cast(node);\n if (field) return leafMember(writer, 'regular', () => emitField(writer, field, columns));\n const attribute = ModelAttributeAst.cast(node);\n if (attribute)\n return leafMember(writer, 'blockAttribute', () => emitBlockAttribute(writer, attribute));\n return undefined;\n });\n}\n\nfunction emitCompositeType(\n writer: LineWriter,\n composite: CompositeTypeDeclarationAst,\n trailing: string | undefined,\n): void {\n const columns = alignmentMap(composite.syntax);\n emitBlockBody(writer, composite.syntax, trailing, (node) => {\n const field = FieldDeclarationAst.cast(node);\n if (field) return leafMember(writer, 'regular', () => emitField(writer, field, columns));\n const attribute = ModelAttributeAst.cast(node);\n if (attribute)\n return leafMember(writer, 'blockAttribute', () => emitBlockAttribute(writer, attribute));\n return undefined;\n });\n}\n\nfunction emitGenericBlock(\n writer: LineWriter,\n block: GenericBlockDeclarationAst,\n trailing: string | undefined,\n): void {\n emitBlockBody(writer, block.syntax, trailing, (node) => {\n const entry = KeyValuePairAst.cast(node);\n if (entry) return leafMember(writer, 'regular', () => emitKeyValue(writer, entry));\n const attribute = ModelAttributeAst.cast(node);\n if (attribute)\n return leafMember(writer, 'blockAttribute', () => emitBlockAttribute(writer, attribute));\n return undefined;\n });\n}\n\nfunction emitNamespace(\n writer: LineWriter,\n namespace: NamespaceDeclarationAst,\n trailing: string | undefined,\n): void {\n emitBlockBody(writer, namespace.syntax, trailing, (node) => {\n const declaration = castBlockDeclaration(node);\n if (declaration) return nestedBlockMember(writer, declaration);\n return undefined;\n });\n}\n\nfunction emitTypesBlock(\n writer: LineWriter,\n block: TypesBlockAst,\n trailing: string | undefined,\n): void {\n emitBlockBody(writer, block.syntax, trailing, (node) => {\n const named = NamedTypeDeclarationAst.cast(node);\n if (named) return leafMember(writer, 'regular', () => emitNamedType(writer, named));\n return undefined;\n });\n}\n\nfunction emitTopLevel(writer: LineWriter, document: DocumentAst): void {\n walkRegion(writer, Array.from(document.syntax.children()), undefined, (node) => {\n const declaration = castTopLevelDeclaration(node);\n if (declaration) return nestedBlockMember(writer, declaration);\n return undefined;\n });\n}\n\ntype BlockEmitter = (writer: LineWriter, trailing: string | undefined) => void;\n\nfunction nestedBlockMember(writer: LineWriter, block: BlockEmitter): BlockMember {\n return {\n category: 'nestedBlock',\n emit(trailing) {\n block(writer, trailing);\n return 0;\n },\n };\n}\n\nfunction castBlockDeclaration(node: SyntaxNode): BlockEmitter | undefined {\n const model = ModelDeclarationAst.cast(node);\n if (model) return (writer, trailing) => emitModel(writer, model, trailing);\n const composite = CompositeTypeDeclarationAst.cast(node);\n if (composite) return (writer, trailing) => emitCompositeType(writer, composite, trailing);\n const generic = GenericBlockDeclarationAst.cast(node);\n if (generic) return (writer, trailing) => emitGenericBlock(writer, generic, trailing);\n return undefined;\n}\n\nfunction castTopLevelDeclaration(node: SyntaxNode): BlockEmitter | undefined {\n const block = castBlockDeclaration(node);\n if (block) return block;\n const namespace = NamespaceDeclarationAst.cast(node);\n if (namespace) return (writer, trailing) => emitNamespace(writer, namespace, trailing);\n const types = TypesBlockAst.cast(node);\n if (types) return (writer, trailing) => emitTypesBlock(writer, types, trailing);\n return undefined;\n}\n\nfunction emitBlockBody(\n writer: LineWriter,\n node: SyntaxNode,\n closingTrailing: string | undefined,\n classify: MemberClassifier,\n): void {\n const children = Array.from(node.children());\n const openIndex = children.findIndex((el) => !(el instanceof SyntaxNode) && el.kind === 'LBrace');\n\n streamHeader(writer, node);\n const headerComment = sameLineCommentAfter(children, openIndex);\n if (headerComment !== undefined) writer.comment(headerComment);\n else writer.newline();\n\n writer.indent();\n walkRegion(writer, children, 'RBrace', classify);\n writer.unindent();\n\n writer.writeRaw('}');\n if (closingTrailing !== undefined) writer.comment(closingTrailing);\n else writer.newline();\n}\n\nfunction streamHeader(writer: LineWriter, node: SyntaxNode): void {\n let done = false;\n const walk = (parent: SyntaxNode): void => {\n for (const child of parent.children()) {\n if (done) return;\n if (child instanceof SyntaxNode) {\n walk(child);\n continue;\n }\n if (child.kind === 'Whitespace' || child.kind === 'Newline' || child.kind === 'Comment') {\n continue;\n }\n const space = spaceBetween(writer.prevKind(), child.kind, false);\n writer.write(child, space);\n if (child.kind === 'LBrace') {\n done = true;\n return;\n }\n }\n };\n walk(node);\n}\n\nfunction walkRegion(\n writer: LineWriter,\n elements: readonly SyntaxElement[],\n closeKind: 'RBrace' | undefined,\n classify: MemberClassifier,\n): void {\n let sawOpenBrace = closeKind === undefined;\n let sawContent = false;\n let lastWasRegular = false;\n let ledByComment = false;\n let newlines = 0;\n\n for (let i = 0; i < elements.length; i++) {\n const element = elements[i];\n if (element === undefined) continue;\n\n if (element instanceof SyntaxNode) {\n if (!sawOpenBrace) continue;\n const member = classify(element);\n if (member === undefined) continue;\n if (!ledByComment) {\n if (newlines >= 2 && sawContent && !writer.lastIsBlank()) writer.blank();\n else if (separationBlankWanted(writer, member.category, sawContent, lastWasRegular)) {\n writer.blank();\n }\n }\n\n const trailing = sameLineTrailingComment(elements, i);\n closeContinuation(writer, member.emit(trailing.text));\n if (trailing.index !== undefined) i = trailing.index;\n sawContent = true;\n lastWasRegular = member.category !== 'blockAttribute';\n ledByComment = false;\n newlines = 0;\n continue;\n }\n\n if (element.kind === 'LBrace' && closeKind === 'RBrace' && !sawOpenBrace) {\n sawOpenBrace = true;\n newlines = 0;\n continue;\n }\n if (!sawOpenBrace) continue;\n if (closeKind === 'RBrace' && element.kind === 'RBrace') break;\n if (element.kind === 'Whitespace') continue;\n if (element.kind === 'Newline') {\n newlines += 1;\n continue;\n }\n if (element.kind === 'Comment') {\n if (closeKind === 'RBrace' && newlines === 0 && !sawContent) {\n // Same-line comment trailing the opening `{`: owned by the block header.\n continue;\n }\n if (newlines >= 2 && sawContent && !writer.lastIsBlank()) writer.blank();\n else if (!ledByComment) {\n const led = leadingMemberAfter(elements, i, classify);\n if (led && separationBlankWanted(writer, led, sawContent, lastWasRegular)) writer.blank();\n }\n writer.writeRaw(element.text);\n writer.newline();\n sawContent = true;\n ledByComment = true;\n newlines = 0;\n }\n }\n}\n\nfunction separationBlankWanted(\n writer: LineWriter,\n category: MemberCategory,\n sawContent: boolean,\n lastWasRegular: boolean,\n): boolean {\n if (!sawContent || writer.lastIsBlank()) return false;\n if (category === 'nestedBlock') return true;\n return category === 'blockAttribute' && lastWasRegular;\n}\n\nfunction leadingMemberAfter(\n elements: readonly SyntaxElement[],\n commentIndex: number,\n classify: MemberClassifier,\n): MemberCategory | undefined {\n for (let i = commentIndex + 1; i < elements.length; i++) {\n const element = elements[i];\n if (element === undefined) continue;\n if (element instanceof SyntaxNode) return classify(element)?.category;\n if (element.kind === 'RBrace') return undefined;\n }\n return undefined;\n}\n\nfunction sameLineTrailingComment(\n elements: readonly SyntaxElement[],\n memberIndex: number,\n): { text: string | undefined; index: number | undefined } {\n for (let i = memberIndex + 1; i < elements.length; i++) {\n const element = elements[i];\n if (element === undefined) continue;\n if (element instanceof SyntaxNode) break;\n if (element.kind === 'Whitespace') continue;\n if (element.kind === 'Comment') return { text: element.text, index: i };\n break;\n }\n return { text: undefined, index: undefined };\n}\n\nfunction sameLineCommentAfter(\n children: readonly SyntaxElement[],\n openIndex: number,\n): string | undefined {\n for (let i = openIndex + 1; i < children.length; i++) {\n const child = children[i];\n if (child === undefined) continue;\n if (child instanceof SyntaxNode) return undefined;\n if (child.kind === 'Whitespace') continue;\n if (child.kind === 'Comment') return child.text;\n return undefined;\n }\n return undefined;\n}\n\ninterface AlignmentColumns {\n readonly typeColumn: number;\n readonly attributeColumn: number;\n}\n\nfunction alignmentMap(block: SyntaxNode): AlignmentColumns | undefined {\n const fields: SyntaxNode[] = [];\n for (const element of block.children()) {\n if (!(element instanceof SyntaxNode)) continue;\n if (FieldDeclarationAst.cast(element) === undefined) continue;\n // Interior comments split rows into continuation lines, so those rows opt out of alignment.\n if (hasInteriorComment(element)) continue;\n fields.push(element);\n }\n if (fields.length === 0) return undefined;\n return alignmentColumns(fields);\n}\n\nfunction alignmentColumns(rows: readonly SyntaxNode[]): AlignmentColumns {\n let nameWidth = 0;\n for (const row of rows) {\n const field = FieldDeclarationAst.cast(row);\n if (!field) continue;\n nameWidth = Math.max(nameWidth, renderTokens(field.name()?.syntax).length);\n }\n const typeColumn = nameWidth + 1;\n let cellEnd = 0;\n for (const row of rows) {\n const field = FieldDeclarationAst.cast(row);\n if (!field) continue;\n const name = renderTokens(field.name()?.syntax);\n const type = renderTokens(field.typeAnnotation()?.syntax);\n cellEnd = Math.max(cellEnd, type.length > 0 ? typeColumn + type.length : name.length);\n }\n return { typeColumn, attributeColumn: cellEnd + 1 };\n}\n\nfunction hasInteriorComment(node: SyntaxNode): boolean {\n for (const token of node.tokens()) {\n if (token.kind === 'Comment') return true;\n }\n return false;\n}\n\nfunction renderTokens(node: SyntaxNode | undefined): string {\n if (!node) return '';\n let out = '';\n let prev: TokenKind | undefined;\n let prevQualified = false;\n const walk = (parent: SyntaxNode, qualified: boolean): void => {\n for (const child of parent.children()) {\n if (child instanceof SyntaxNode) {\n walk(child, qualified || child.kind === 'QualifiedName');\n continue;\n }\n if (child.kind === 'Whitespace' || child.kind === 'Newline' || child.kind === 'Comment') {\n continue;\n }\n if (spaceBetween(prev, child.kind, qualified && prevQualified)) out += ' ';\n out += child.text;\n prev = child.kind;\n prevQualified = qualified;\n }\n };\n walk(node, false);\n return out;\n}\n","import type { StructuredError, StructuredErrorOptions } from '@prisma-next/utils/structured-error';\nimport { structuredError } from '@prisma-next/utils/structured-error';\n\nexport type PslCode = `PSL.${PslSubcode}`;\n\ntype PslSubcode = 'PARSE_FAILED';\n\nexport function pslError(\n code: PslCode,\n message: string,\n options?: StructuredErrorOptions,\n): StructuredError {\n return structuredError(code, message, options);\n}\n","export interface FormatOptions {\n readonly indent?: number | 'tab';\n readonly newline?: 'LF' | 'CRLF';\n}\n\nexport interface ResolvedFormatOptions {\n readonly indentUnit: string;\n readonly newline: string;\n}\n\nexport function resolveFormatOptions(options: FormatOptions | undefined): ResolvedFormatOptions {\n const indent = options?.indent ?? 2;\n if (indent !== 'tab' && (typeof indent !== 'number' || !Number.isInteger(indent) || indent < 1)) {\n throw new TypeError(\n `Invalid format options: indent must be a positive integer or 'tab', got ${String(indent)}`,\n );\n }\n const newline = options?.newline ?? 'LF';\n if (newline !== 'LF' && newline !== 'CRLF') {\n throw new TypeError(\n `Invalid format options: newline must be 'LF' or 'CRLF', got ${String(newline)}`,\n );\n }\n return {\n indentUnit: indent === 'tab' ? '\\t' : ' '.repeat(indent),\n newline: newline === 'CRLF' ? '\\r\\n' : '\\n',\n };\n}\n","import { parse } from '../parse';\nimport { emitDocument } from './emit';\nimport { pslError } from './error';\nimport { type FormatOptions, resolveFormatOptions } from './options';\n\nexport function format(source: string, options?: FormatOptions): string {\n const resolved = resolveFormatOptions(options);\n const { document, diagnostics } = parse(source);\n if (diagnostics.length > 0) {\n const summary = diagnostics[0]?.message ?? 'unknown parse error';\n const more = diagnostics.length > 1 ? ` (and ${diagnostics.length - 1} more)` : '';\n throw pslError('PSL.PARSE_FAILED', `Cannot format PSL with parse errors: ${summary}${more}`, {\n meta: { diagnostics },\n });\n }\n return emitDocument(document, resolved.indentUnit, resolved.newline);\n}\n"],"mappings":";;;;AAeA,SAAgB,aAAa,UAAuB,YAAoB,SAAyB;CAC/F,MAAM,SAAS,IAAI,WAAW,YAAY,OAAO;CACjD,aAAa,QAAQ,QAAQ;CAC7B,OAAO,OAAO,OAAO;AACvB;AAEA,IAAM,aAAN,MAAiB;CACf;CACA;CACA,OAA0B,CAAC;CAC3B,SAAS;CACT,QAAQ;CACR,YAAY;CACZ;CACA,gBAAgB;CAChB,cAAc;CAEd,YAAY,YAAoB,SAAiB;EAC/C,KAAKA,cAAc;EACnB,KAAKC,WAAW;CAClB;CAEA,SAAe;EACb,KAAKE,UAAU;CACjB;CAEA,WAAiB;EACf,KAAKA,SAAS,KAAK,IAAI,GAAG,KAAKA,SAAS,CAAC;CAC3C;CAEA,cAAuB;EACrB,OAAO,KAAKC;CACd;CAEA,WAAoB;EAClB,OAAO,KAAKC;CACd;CAEA,WAAkC;EAChC,OAAO,KAAKC;CACd;CAEA,UAAgB;EACd,IAAI,CAAC,KAAKD,WAAW;EACrB,KAAKH,KAAK,KAAK,GAAG,KAAKF,YAAY,OAAO,KAAKG,MAAM,IAAI,KAAKI,OAAO;EACrE,KAAKA,QAAQ;EACb,KAAKF,YAAY;EACjB,KAAKC,YAAY,KAAA;EACjB,KAAKF,gBAAgB;EACrB,KAAKI,cAAc;CACrB;CAEA,QAAc;EACZ,KAAK,QAAQ;EACb,IAAI,CAAC,KAAKA,eAAe,KAAKJ,eAAe;EAC7C,KAAKF,KAAK,KAAK,EAAE;EACjB,KAAKE,gBAAgB;CACvB;CAEA,MAAM,OAAoB,OAAgB,OAAsB;EAC9D,IAAI,KAAKC,aAAa,UAAU,KAAA,GAC9B,KAAKE,QAAQ,KAAKA,MAAM,OAAO,KAAK;OAC/B,IAAI,KAAKF,aAAa,OAC3B,KAAKE,SAAS;EAEhB,KAAKA,SAAS,MAAM;EACpB,KAAKF,YAAY;EACjB,KAAKC,YAAY,MAAM;CACzB;CAEA,SAAS,MAAoB;EAC3B,KAAKC,SAAS;EACd,KAAKF,YAAY;CACnB;CAEA,QAAQ,MAAoB;EAC1B,IAAI,KAAKA,WAAW,KAAKE,SAAS,IAAI;OACjC,KAAKA,QAAQ;EAClB,KAAKF,YAAY;EACjB,KAAK,QAAQ;CACf;CAEA,SAAiB;EACf,KAAK,QAAQ;EACb,MAAM,OAAO,KAAKH,KAAK,KAAK,KAAKD,QAAQ;EACzC,OAAO,KAAK,SAAS,IAAI,GAAG,OAAO,KAAKA,aAAa;CACvD;AACF;AAGA,SAAS,aACP,MACA,KACA,iBACS;CACT,IAAI,SAAS,KAAA,GAAW,OAAO;CAC/B,IAAI,iBAAiB,OAAO;CAE5B,QAAQ,KAAR;EACE,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK,SACH,OAAO;EACT,KAAK,UACH,OAAO,SAAS;EAClB,SACE;CACJ;CACA,QAAQ,MAAR;EACE,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK,YACH,OAAO;EACT,SACE,OAAO;CACX;AACF;AAEA,SAAS,WAAW,QAAoB,MAAkB,OAAwB;CAChF,IAAI,eAAe;CACnB,IAAI,QAAQ;CACZ,IAAI,gBAAgB;CAEpB,MAAM,QAAQ,QAAoB,cAA6B;EAC7D,KAAK,MAAM,SAAS,OAAO,SAAS,GAAG;GACrC,IAAI,iBAAiB,YAAY;IAC/B,KAAK,OAAO,aAAa,MAAM,SAAS,eAAe;IACvD;GACF;GACA,IAAI,MAAM,SAAS,gBAAgB,MAAM,SAAS,WAAW;GAC7D,IAAI,MAAM,SAAS,WAAW;IAC5B,OAAO,QAAQ,MAAM,IAAI;IACzB,OAAO,OAAO;IACd,gBAAgB;IAChB,gBAAgB;IAChB,QAAQ;IACR;GACF;GACA,MAAM,MAAM,QAAQ,QAAQ,KAAA;GAC5B,MAAM,QAAQ,aAAa,OAAO,SAAS,GAAG,MAAM,MAAM,aAAa,aAAa;GACpF,OAAO,MAAM,OAAO,OAAO,OAAO,SAAS,IAAI,MAAM,KAAA,CAAS;GAC9D,gBAAgB;GAChB,QAAQ;EACV;CACF;CAEA,KAAK,MAAM,KAAK;CAChB,OAAO;AACT;AAEA,SAAS,kBAAkB,QAAoB,OAAqB;CAClE,KAAK,IAAI,IAAI,GAAG,IAAI,OAAO,KAAK,OAAO,SAAS;AAClD;AAEA,SAAS,UACP,QACA,OACA,SACQ;CACR,OAAO,UAAU,QAAQ,MAAM,QAAQ,OAAO;AAChD;AAEA,SAAS,cAAc,QAAoB,MAAuC;CAChF,OAAO,UAAU,QAAQ,KAAK,QAAQ,KAAA,CAAS;AACjD;AAEA,SAAS,UACP,QACA,KACA,SACQ;CACR,IAAI,eAAe;CACnB,IAAI,eAAe;CAEnB,KAAK,MAAM,SAAS,IAAI,SAAS,GAAG;EAClC,IAAI,iBAAiB,YAAY;GAC/B,IAAI;GACJ,IAAI,MAAM,SAAS,oBAAoB,iBAAiB,GACtD,QAAQ,SAAS;QACZ,IAAI,MAAM,SAAS,kBAAkB;IAC1C,IAAI,eAAe,GAAG,OAAO,QAAQ;SAChC,IAAI,CAAC,cAAc,QAAQ,SAAS;IACzC,eAAe;GACjB;GACA,gBAAgB,WAAW,QAAQ,OAAO,KAAK;GAC/C;EACF;EACA,IAAI,MAAM,SAAS,gBAAgB,MAAM,SAAS,WAAW;EAC7D,IAAI,MAAM,SAAS,WAAW;GAC5B,OAAO,QAAQ,MAAM,IAAI;GACzB,OAAO,OAAO;GACd,gBAAgB;GAChB;EACF;EACA,MAAM,QAAQ,aAAa,OAAO,SAAS,GAAG,MAAM,MAAM,KAAK;EAC/D,OAAO,MAAM,OAAO,KAAK;CAC3B;CAEA,OAAO;AACT;AAEA,SAAS,mBAAmB,QAAoB,WAAsC;CACpF,OAAO,WAAW,QAAQ,UAAU,MAAM;AAC5C;AAEA,SAAS,aAAa,QAAoB,MAA+B;CACvE,OAAO,WAAW,QAAQ,KAAK,MAAM;AACvC;AASA,SAAS,WACP,QACA,UACA,OACa;CACb,OAAO;EACL;EACA,KAAK,UAAU;GACb,MAAM,eAAe,MAAM;GAC3B,IAAI,aAAa,KAAA,GAAW,OAAO,QAAQ,QAAQ;QAC9C,OAAO,QAAQ;GACpB,OAAO;EACT;CACF;AACF;AAIA,SAAS,UACP,QACA,OACA,UACM;CACN,MAAM,UAAU,aAAa,MAAM,MAAM;CACzC,cAAc,QAAQ,MAAM,QAAQ,WAAW,SAAS;EACtD,MAAM,QAAQ,oBAAoB,KAAK,IAAI;EAC3C,IAAI,OAAO,OAAO,WAAW,QAAQ,iBAAiB,UAAU,QAAQ,OAAO,OAAO,CAAC;EACvF,MAAM,YAAY,kBAAkB,KAAK,IAAI;EAC7C,IAAI,WACF,OAAO,WAAW,QAAQ,wBAAwB,mBAAmB,QAAQ,SAAS,CAAC;CAE3F,CAAC;AACH;AAEA,SAAS,kBACP,QACA,WACA,UACM;CACN,MAAM,UAAU,aAAa,UAAU,MAAM;CAC7C,cAAc,QAAQ,UAAU,QAAQ,WAAW,SAAS;EAC1D,MAAM,QAAQ,oBAAoB,KAAK,IAAI;EAC3C,IAAI,OAAO,OAAO,WAAW,QAAQ,iBAAiB,UAAU,QAAQ,OAAO,OAAO,CAAC;EACvF,MAAM,YAAY,kBAAkB,KAAK,IAAI;EAC7C,IAAI,WACF,OAAO,WAAW,QAAQ,wBAAwB,mBAAmB,QAAQ,SAAS,CAAC;CAE3F,CAAC;AACH;AAEA,SAAS,iBACP,QACA,OACA,UACM;CACN,cAAc,QAAQ,MAAM,QAAQ,WAAW,SAAS;EACtD,MAAM,QAAQ,gBAAgB,KAAK,IAAI;EACvC,IAAI,OAAO,OAAO,WAAW,QAAQ,iBAAiB,aAAa,QAAQ,KAAK,CAAC;EACjF,MAAM,YAAY,kBAAkB,KAAK,IAAI;EAC7C,IAAI,WACF,OAAO,WAAW,QAAQ,wBAAwB,mBAAmB,QAAQ,SAAS,CAAC;CAE3F,CAAC;AACH;AAEA,SAAS,cACP,QACA,WACA,UACM;CACN,cAAc,QAAQ,UAAU,QAAQ,WAAW,SAAS;EAC1D,MAAM,cAAc,qBAAqB,IAAI;EAC7C,IAAI,aAAa,OAAO,kBAAkB,QAAQ,WAAW;CAE/D,CAAC;AACH;AAEA,SAAS,eACP,QACA,OACA,UACM;CACN,cAAc,QAAQ,MAAM,QAAQ,WAAW,SAAS;EACtD,MAAM,QAAQ,wBAAwB,KAAK,IAAI;EAC/C,IAAI,OAAO,OAAO,WAAW,QAAQ,iBAAiB,cAAc,QAAQ,KAAK,CAAC;CAEpF,CAAC;AACH;AAEA,SAAS,aAAa,QAAoB,UAA6B;CACrE,WAAW,QAAQ,MAAM,KAAK,SAAS,OAAO,SAAS,CAAC,GAAG,KAAA,IAAY,SAAS;EAC9E,MAAM,cAAc,wBAAwB,IAAI;EAChD,IAAI,aAAa,OAAO,kBAAkB,QAAQ,WAAW;CAE/D,CAAC;AACH;AAIA,SAAS,kBAAkB,QAAoB,OAAkC;CAC/E,OAAO;EACL,UAAU;EACV,KAAK,UAAU;GACb,MAAM,QAAQ,QAAQ;GACtB,OAAO;EACT;CACF;AACF;AAEA,SAAS,qBAAqB,MAA4C;CACxE,MAAM,QAAQ,oBAAoB,KAAK,IAAI;CAC3C,IAAI,OAAO,QAAQ,QAAQ,aAAa,UAAU,QAAQ,OAAO,QAAQ;CACzE,MAAM,YAAY,4BAA4B,KAAK,IAAI;CACvD,IAAI,WAAW,QAAQ,QAAQ,aAAa,kBAAkB,QAAQ,WAAW,QAAQ;CACzF,MAAM,UAAU,2BAA2B,KAAK,IAAI;CACpD,IAAI,SAAS,QAAQ,QAAQ,aAAa,iBAAiB,QAAQ,SAAS,QAAQ;AAEtF;AAEA,SAAS,wBAAwB,MAA4C;CAC3E,MAAM,QAAQ,qBAAqB,IAAI;CACvC,IAAI,OAAO,OAAO;CAClB,MAAM,YAAY,wBAAwB,KAAK,IAAI;CACnD,IAAI,WAAW,QAAQ,QAAQ,aAAa,cAAc,QAAQ,WAAW,QAAQ;CACrF,MAAM,QAAQ,cAAc,KAAK,IAAI;CACrC,IAAI,OAAO,QAAQ,QAAQ,aAAa,eAAe,QAAQ,OAAO,QAAQ;AAEhF;AAEA,SAAS,cACP,QACA,MACA,iBACA,UACM;CACN,MAAM,WAAW,MAAM,KAAK,KAAK,SAAS,CAAC;CAC3C,MAAM,YAAY,SAAS,WAAW,OAAO,EAAE,cAAc,eAAe,GAAG,SAAS,QAAQ;CAEhG,aAAa,QAAQ,IAAI;CACzB,MAAM,gBAAgB,qBAAqB,UAAU,SAAS;CAC9D,IAAI,kBAAkB,KAAA,GAAW,OAAO,QAAQ,aAAa;MACxD,OAAO,QAAQ;CAEpB,OAAO,OAAO;CACd,WAAW,QAAQ,UAAU,UAAU,QAAQ;CAC/C,OAAO,SAAS;CAEhB,OAAO,SAAS,GAAG;CACnB,IAAI,oBAAoB,KAAA,GAAW,OAAO,QAAQ,eAAe;MAC5D,OAAO,QAAQ;AACtB;AAEA,SAAS,aAAa,QAAoB,MAAwB;CAChE,IAAI,OAAO;CACX,MAAM,QAAQ,WAA6B;EACzC,KAAK,MAAM,SAAS,OAAO,SAAS,GAAG;GACrC,IAAI,MAAM;GACV,IAAI,iBAAiB,YAAY;IAC/B,KAAK,KAAK;IACV;GACF;GACA,IAAI,MAAM,SAAS,gBAAgB,MAAM,SAAS,aAAa,MAAM,SAAS,WAC5E;GAEF,MAAM,QAAQ,aAAa,OAAO,SAAS,GAAG,MAAM,MAAM,KAAK;GAC/D,OAAO,MAAM,OAAO,KAAK;GACzB,IAAI,MAAM,SAAS,UAAU;IAC3B,OAAO;IACP;GACF;EACF;CACF;CACA,KAAK,IAAI;AACX;AAEA,SAAS,WACP,QACA,UACA,WACA,UACM;CACN,IAAI,eAAe,cAAc,KAAA;CACjC,IAAI,aAAa;CACjB,IAAI,iBAAiB;CACrB,IAAI,eAAe;CACnB,IAAI,WAAW;CAEf,KAAK,IAAI,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;EACxC,MAAM,UAAU,SAAS;EACzB,IAAI,YAAY,KAAA,GAAW;EAE3B,IAAI,mBAAmB,YAAY;GACjC,IAAI,CAAC,cAAc;GACnB,MAAM,SAAS,SAAS,OAAO;GAC/B,IAAI,WAAW,KAAA,GAAW;GAC1B,IAAI,CAAC;QACC,YAAY,KAAK,cAAc,CAAC,OAAO,YAAY,GAAG,OAAO,MAAM;SAClE,IAAI,sBAAsB,QAAQ,OAAO,UAAU,YAAY,cAAc,GAChF,OAAO,MAAM;GAAA;GAIjB,MAAM,WAAW,wBAAwB,UAAU,CAAC;GACpD,kBAAkB,QAAQ,OAAO,KAAK,SAAS,IAAI,CAAC;GACpD,IAAI,SAAS,UAAU,KAAA,GAAW,IAAI,SAAS;GAC/C,aAAa;GACb,iBAAiB,OAAO,aAAa;GACrC,eAAe;GACf,WAAW;GACX;EACF;EAEA,IAAI,QAAQ,SAAS,YAAY,cAAc,YAAY,CAAC,cAAc;GACxE,eAAe;GACf,WAAW;GACX;EACF;EACA,IAAI,CAAC,cAAc;EACnB,IAAI,cAAc,YAAY,QAAQ,SAAS,UAAU;EACzD,IAAI,QAAQ,SAAS,cAAc;EACnC,IAAI,QAAQ,SAAS,WAAW;GAC9B,YAAY;GACZ;EACF;EACA,IAAI,QAAQ,SAAS,WAAW;GAC9B,IAAI,cAAc,YAAY,aAAa,KAAK,CAAC,YAE/C;GAEF,IAAI,YAAY,KAAK,cAAc,CAAC,OAAO,YAAY,GAAG,OAAO,MAAM;QAClE,IAAI,CAAC,cAAc;IACtB,MAAM,MAAM,mBAAmB,UAAU,GAAG,QAAQ;IACpD,IAAI,OAAO,sBAAsB,QAAQ,KAAK,YAAY,cAAc,GAAG,OAAO,MAAM;GAC1F;GACA,OAAO,SAAS,QAAQ,IAAI;GAC5B,OAAO,QAAQ;GACf,aAAa;GACb,eAAe;GACf,WAAW;EACb;CACF;AACF;AAEA,SAAS,sBACP,QACA,UACA,YACA,gBACS;CACT,IAAI,CAAC,cAAc,OAAO,YAAY,GAAG,OAAO;CAChD,IAAI,aAAa,eAAe,OAAO;CACvC,OAAO,aAAa,oBAAoB;AAC1C;AAEA,SAAS,mBACP,UACA,cACA,UAC4B;CAC5B,KAAK,IAAI,IAAI,eAAe,GAAG,IAAI,SAAS,QAAQ,KAAK;EACvD,MAAM,UAAU,SAAS;EACzB,IAAI,YAAY,KAAA,GAAW;EAC3B,IAAI,mBAAmB,YAAY,OAAO,SAAS,OAAO,CAAC,EAAE;EAC7D,IAAI,QAAQ,SAAS,UAAU,OAAO,KAAA;CACxC;AAEF;AAEA,SAAS,wBACP,UACA,aACyD;CACzD,KAAK,IAAI,IAAI,cAAc,GAAG,IAAI,SAAS,QAAQ,KAAK;EACtD,MAAM,UAAU,SAAS;EACzB,IAAI,YAAY,KAAA,GAAW;EAC3B,IAAI,mBAAmB,YAAY;EACnC,IAAI,QAAQ,SAAS,cAAc;EACnC,IAAI,QAAQ,SAAS,WAAW,OAAO;GAAE,MAAM,QAAQ;GAAM,OAAO;EAAE;EACtE;CACF;CACA,OAAO;EAAE,MAAM,KAAA;EAAW,OAAO,KAAA;CAAU;AAC7C;AAEA,SAAS,qBACP,UACA,WACoB;CACpB,KAAK,IAAI,IAAI,YAAY,GAAG,IAAI,SAAS,QAAQ,KAAK;EACpD,MAAM,QAAQ,SAAS;EACvB,IAAI,UAAU,KAAA,GAAW;EACzB,IAAI,iBAAiB,YAAY,OAAO,KAAA;EACxC,IAAI,MAAM,SAAS,cAAc;EACjC,IAAI,MAAM,SAAS,WAAW,OAAO,MAAM;EAC3C;CACF;AAEF;AAOA,SAAS,aAAa,OAAiD;CACrE,MAAM,SAAuB,CAAC;CAC9B,KAAK,MAAM,WAAW,MAAM,SAAS,GAAG;EACtC,IAAI,EAAE,mBAAmB,aAAa;EACtC,IAAI,oBAAoB,KAAK,OAAO,MAAM,KAAA,GAAW;EAErD,IAAI,mBAAmB,OAAO,GAAG;EACjC,OAAO,KAAK,OAAO;CACrB;CACA,IAAI,OAAO,WAAW,GAAG,OAAO,KAAA;CAChC,OAAO,iBAAiB,MAAM;AAChC;AAEA,SAAS,iBAAiB,MAA+C;CACvE,IAAI,YAAY;CAChB,KAAK,MAAM,OAAO,MAAM;EACtB,MAAM,QAAQ,oBAAoB,KAAK,GAAG;EAC1C,IAAI,CAAC,OAAO;EACZ,YAAY,KAAK,IAAI,WAAW,aAAa,MAAM,KAAK,CAAC,EAAE,MAAM,CAAC,CAAC,MAAM;CAC3E;CACA,MAAM,aAAa,YAAY;CAC/B,IAAI,UAAU;CACd,KAAK,MAAM,OAAO,MAAM;EACtB,MAAM,QAAQ,oBAAoB,KAAK,GAAG;EAC1C,IAAI,CAAC,OAAO;EACZ,MAAM,OAAO,aAAa,MAAM,KAAK,CAAC,EAAE,MAAM;EAC9C,MAAM,OAAO,aAAa,MAAM,eAAe,CAAC,EAAE,MAAM;EACxD,UAAU,KAAK,IAAI,SAAS,KAAK,SAAS,IAAI,aAAa,KAAK,SAAS,KAAK,MAAM;CACtF;CACA,OAAO;EAAE;EAAY,iBAAiB,UAAU;CAAE;AACpD;AAEA,SAAS,mBAAmB,MAA2B;CACrD,KAAK,MAAM,SAAS,KAAK,OAAO,GAC9B,IAAI,MAAM,SAAS,WAAW,OAAO;CAEvC,OAAO;AACT;AAEA,SAAS,aAAa,MAAsC;CAC1D,IAAI,CAAC,MAAM,OAAO;CAClB,IAAI,MAAM;CACV,IAAI;CACJ,IAAI,gBAAgB;CACpB,MAAM,QAAQ,QAAoB,cAA6B;EAC7D,KAAK,MAAM,SAAS,OAAO,SAAS,GAAG;GACrC,IAAI,iBAAiB,YAAY;IAC/B,KAAK,OAAO,aAAa,MAAM,SAAS,eAAe;IACvD;GACF;GACA,IAAI,MAAM,SAAS,gBAAgB,MAAM,SAAS,aAAa,MAAM,SAAS,WAC5E;GAEF,IAAI,aAAa,MAAM,MAAM,MAAM,aAAa,aAAa,GAAG,OAAO;GACvE,OAAO,MAAM;GACb,OAAO,MAAM;GACb,gBAAgB;EAClB;CACF;CACA,KAAK,MAAM,KAAK;CAChB,OAAO;AACT;;;ACnlBA,SAAgB,SACd,MACA,SACA,SACiB;CACjB,OAAO,gBAAgB,MAAM,SAAS,OAAO;AAC/C;;;ACHA,SAAgB,qBAAqB,SAA2D;CAC9F,MAAM,SAAS,SAAS,UAAU;CAClC,IAAI,WAAW,UAAU,OAAO,WAAW,YAAY,CAAC,OAAO,UAAU,MAAM,KAAK,SAAS,IAC3F,MAAM,IAAI,UACR,2EAA2E,OAAO,MAAM,GAC1F;CAEF,MAAM,UAAU,SAAS,WAAW;CACpC,IAAI,YAAY,QAAQ,YAAY,QAClC,MAAM,IAAI,UACR,+DAA+D,OAAO,OAAO,GAC/E;CAEF,OAAO;EACL,YAAY,WAAW,QAAQ,MAAO,IAAI,OAAO,MAAM;EACvD,SAAS,YAAY,SAAS,SAAS;CACzC;AACF;;;ACtBA,SAAgB,OAAO,QAAgB,SAAiC;CACtE,MAAM,WAAW,qBAAqB,OAAO;CAC7C,MAAM,EAAE,UAAU,gBAAgB,MAAM,MAAM;CAC9C,IAAI,YAAY,SAAS,GAGvB,MAAM,SAAS,oBAAoB,wCAFnB,YAAY,EAAE,EAAE,WAAW,wBAC9B,YAAY,SAAS,IAAI,SAAS,YAAY,SAAS,EAAE,UAAU,MACa,EAC3F,MAAM,EAAE,YAAY,EACtB,CAAC;CAEH,OAAO,aAAa,UAAU,SAAS,YAAY,SAAS,OAAO;AACrE"}
1
+ {"version":3,"file":"format.mjs","names":["#indentUnit","#newline","#out","#depth","#lastWasBlank","#lineOpen","#prevKind","#line","#hasContent"],"sources":["../src/format/emit.ts","../src/format/error.ts","../src/format/options.ts","../src/format/format.ts"],"sourcesContent":["import { ModelAttributeAst } from '../syntax/ast/attributes';\nimport {\n CompositeTypeDeclarationAst,\n type DocumentAst,\n FieldDeclarationAst,\n GenericBlockDeclarationAst,\n KeyValuePairAst,\n ModelDeclarationAst,\n NamedTypeDeclarationAst,\n NamespaceDeclarationAst,\n TypesBlockAst,\n} from '../syntax/ast/declarations';\nimport { type SyntaxElement, SyntaxNode, type SyntaxToken } from '../syntax/red';\nimport type { TokenKind } from '../tokenizer';\n\nexport function emitDocument(document: DocumentAst, indentUnit: string, newline: string): string {\n const writer = new LineWriter(indentUnit, newline);\n emitTopLevel(writer, document);\n return writer.finish();\n}\n\nclass LineWriter {\n readonly #indentUnit: string;\n readonly #newline: string;\n readonly #out: string[] = [];\n #depth = 0;\n #line = '';\n #lineOpen = false;\n #prevKind: TokenKind | undefined;\n #lastWasBlank = false;\n #hasContent = false;\n\n constructor(indentUnit: string, newline: string) {\n this.#indentUnit = indentUnit;\n this.#newline = newline;\n }\n\n indent(): void {\n this.#depth += 1;\n }\n\n unindent(): void {\n this.#depth = Math.max(0, this.#depth - 1);\n }\n\n lastIsBlank(): boolean {\n return this.#lastWasBlank;\n }\n\n lineOpen(): boolean {\n return this.#lineOpen;\n }\n\n prevKind(): TokenKind | undefined {\n return this.#prevKind;\n }\n\n newline(): void {\n if (!this.#lineOpen) return;\n this.#out.push(`${this.#indentUnit.repeat(this.#depth)}${this.#line}`);\n this.#line = '';\n this.#lineOpen = false;\n this.#prevKind = undefined;\n this.#lastWasBlank = false;\n this.#hasContent = true;\n }\n\n blank(): void {\n this.newline();\n if (!this.#hasContent || this.#lastWasBlank) return;\n this.#out.push('');\n this.#lastWasBlank = true;\n }\n\n write(token: SyntaxToken, space: boolean, padTo?: number): void {\n if (this.#lineOpen && padTo !== undefined) {\n this.#line = this.#line.padEnd(padTo);\n } else if (this.#lineOpen && space) {\n this.#line += ' ';\n }\n this.#line += token.text;\n this.#lineOpen = true;\n this.#prevKind = token.kind;\n }\n\n writeRaw(text: string): void {\n this.#line += text;\n this.#lineOpen = true;\n }\n\n comment(text: string): void {\n if (this.#lineOpen) this.#line += ` ${text}`;\n else this.#line = text;\n this.#lineOpen = true;\n this.newline();\n }\n\n finish(): string {\n this.newline();\n const body = this.#out.join(this.#newline);\n return body.length > 0 ? `${body}${this.#newline}` : '';\n }\n}\n\n// Qualified-name separators hug; argument/object colons keep the usual value space.\nfunction spaceBetween(\n prev: TokenKind | undefined,\n cur: TokenKind,\n inQualifiedName: boolean,\n): boolean {\n if (prev === undefined) return false;\n if (inQualifiedName) return false;\n\n switch (cur) {\n case 'LParen':\n case 'LBracket':\n case 'RParen':\n case 'RBracket':\n case 'Comma':\n case 'Question':\n case 'Dot':\n case 'Colon':\n return false;\n case 'RBrace':\n return prev !== 'LBrace';\n default:\n break;\n }\n switch (prev) {\n case 'LParen':\n case 'LBracket':\n case 'Dot':\n case 'At':\n case 'DoubleAt':\n return false;\n default:\n return true;\n }\n}\n\nfunction streamNode(writer: LineWriter, node: SyntaxNode, padTo?: number): number {\n let continuation = 0;\n let first = true;\n let prevQualified = false;\n\n const walk = (parent: SyntaxNode, qualified: boolean): void => {\n for (const child of parent.children()) {\n if (child instanceof SyntaxNode) {\n walk(child, qualified || child.kind === 'QualifiedName');\n continue;\n }\n if (child.kind === 'Whitespace' || child.kind === 'Newline') continue;\n if (child.kind === 'Comment') {\n writer.comment(child.text);\n writer.indent();\n continuation += 1;\n prevQualified = false;\n first = false;\n continue;\n }\n const pad = first ? padTo : undefined;\n const space = spaceBetween(writer.prevKind(), child.kind, qualified && prevQualified);\n writer.write(child, space, writer.lineOpen() ? pad : undefined);\n prevQualified = qualified;\n first = false;\n }\n };\n\n walk(node, false);\n return continuation;\n}\n\nfunction closeContinuation(writer: LineWriter, count: number): void {\n for (let i = 0; i < count; i++) writer.unindent();\n}\n\nfunction emitField(\n writer: LineWriter,\n field: FieldDeclarationAst,\n columns: AlignmentColumns | undefined,\n): number {\n return streamRow(writer, field.syntax, columns);\n}\n\nfunction emitNamedType(writer: LineWriter, decl: NamedTypeDeclarationAst): number {\n return streamRow(writer, decl.syntax, undefined);\n}\n\nfunction streamRow(\n writer: LineWriter,\n row: SyntaxNode,\n columns: AlignmentColumns | undefined,\n): number {\n let continuation = 0;\n let sawAttribute = false;\n\n for (const child of row.children()) {\n if (child instanceof SyntaxNode) {\n let padTo: number | undefined;\n if (child.kind === 'TypeAnnotation' && continuation === 0) {\n padTo = columns?.typeColumn;\n } else if (child.kind === 'FieldAttribute') {\n if (continuation > 0) writer.newline();\n else if (!sawAttribute) padTo = columns?.attributeColumn;\n sawAttribute = true;\n }\n continuation += streamNode(writer, child, padTo);\n continue;\n }\n if (child.kind === 'Whitespace' || child.kind === 'Newline') continue;\n if (child.kind === 'Comment') {\n writer.comment(child.text);\n writer.indent();\n continuation += 1;\n continue;\n }\n const space = spaceBetween(writer.prevKind(), child.kind, false);\n writer.write(child, space);\n }\n\n return continuation;\n}\n\nfunction emitBlockAttribute(writer: LineWriter, attribute: ModelAttributeAst): number {\n return streamNode(writer, attribute.syntax);\n}\n\nfunction emitKeyValue(writer: LineWriter, pair: KeyValuePairAst): number {\n return streamNode(writer, pair.syntax);\n}\n\ntype MemberCategory = 'regular' | 'blockAttribute' | 'nestedBlock';\n\ninterface BlockMember {\n readonly category: MemberCategory;\n emit(trailing: string | undefined): number;\n}\n\nfunction leafMember(\n writer: LineWriter,\n category: MemberCategory,\n print: () => number,\n): BlockMember {\n return {\n category,\n emit(trailing) {\n const continuation = print();\n if (trailing !== undefined) writer.comment(trailing);\n else writer.newline();\n return continuation;\n },\n };\n}\n\ntype MemberClassifier = (node: SyntaxNode) => BlockMember | undefined;\n\nfunction emitModel(\n writer: LineWriter,\n model: ModelDeclarationAst,\n trailing: string | undefined,\n): void {\n const columns = alignmentMap(model.syntax);\n emitBlockBody(writer, model.syntax, trailing, (node) => {\n const field = FieldDeclarationAst.cast(node);\n if (field) return leafMember(writer, 'regular', () => emitField(writer, field, columns));\n const attribute = ModelAttributeAst.cast(node);\n if (attribute)\n return leafMember(writer, 'blockAttribute', () => emitBlockAttribute(writer, attribute));\n return undefined;\n });\n}\n\nfunction emitCompositeType(\n writer: LineWriter,\n composite: CompositeTypeDeclarationAst,\n trailing: string | undefined,\n): void {\n const columns = alignmentMap(composite.syntax);\n emitBlockBody(writer, composite.syntax, trailing, (node) => {\n const field = FieldDeclarationAst.cast(node);\n if (field) return leafMember(writer, 'regular', () => emitField(writer, field, columns));\n const attribute = ModelAttributeAst.cast(node);\n if (attribute)\n return leafMember(writer, 'blockAttribute', () => emitBlockAttribute(writer, attribute));\n return undefined;\n });\n}\n\nfunction emitGenericBlock(\n writer: LineWriter,\n block: GenericBlockDeclarationAst,\n trailing: string | undefined,\n): void {\n emitBlockBody(writer, block.syntax, trailing, (node) => {\n const entry = KeyValuePairAst.cast(node);\n if (entry) return leafMember(writer, 'regular', () => emitKeyValue(writer, entry));\n const attribute = ModelAttributeAst.cast(node);\n if (attribute)\n return leafMember(writer, 'blockAttribute', () => emitBlockAttribute(writer, attribute));\n return undefined;\n });\n}\n\nfunction emitNamespace(\n writer: LineWriter,\n namespace: NamespaceDeclarationAst,\n trailing: string | undefined,\n): void {\n emitBlockBody(writer, namespace.syntax, trailing, (node) => {\n const declaration = castBlockDeclaration(node);\n if (declaration) return nestedBlockMember(writer, declaration);\n return undefined;\n });\n}\n\nfunction emitTypesBlock(\n writer: LineWriter,\n block: TypesBlockAst,\n trailing: string | undefined,\n): void {\n emitBlockBody(writer, block.syntax, trailing, (node) => {\n const named = NamedTypeDeclarationAst.cast(node);\n if (named) return leafMember(writer, 'regular', () => emitNamedType(writer, named));\n return undefined;\n });\n}\n\nfunction emitTopLevel(writer: LineWriter, document: DocumentAst): void {\n walkRegion(writer, Array.from(document.syntax.children()), undefined, (node) => {\n const declaration = castTopLevelDeclaration(node);\n if (declaration) return nestedBlockMember(writer, declaration);\n return undefined;\n });\n}\n\ntype BlockEmitter = (writer: LineWriter, trailing: string | undefined) => void;\n\nfunction nestedBlockMember(writer: LineWriter, block: BlockEmitter): BlockMember {\n return {\n category: 'nestedBlock',\n emit(trailing) {\n block(writer, trailing);\n return 0;\n },\n };\n}\n\nfunction castBlockDeclaration(node: SyntaxNode): BlockEmitter | undefined {\n const model = ModelDeclarationAst.cast(node);\n if (model) return (writer, trailing) => emitModel(writer, model, trailing);\n const composite = CompositeTypeDeclarationAst.cast(node);\n if (composite) return (writer, trailing) => emitCompositeType(writer, composite, trailing);\n const generic = GenericBlockDeclarationAst.cast(node);\n if (generic) return (writer, trailing) => emitGenericBlock(writer, generic, trailing);\n return undefined;\n}\n\nfunction castTopLevelDeclaration(node: SyntaxNode): BlockEmitter | undefined {\n const block = castBlockDeclaration(node);\n if (block) return block;\n const namespace = NamespaceDeclarationAst.cast(node);\n if (namespace) return (writer, trailing) => emitNamespace(writer, namespace, trailing);\n const types = TypesBlockAst.cast(node);\n if (types) return (writer, trailing) => emitTypesBlock(writer, types, trailing);\n return undefined;\n}\n\nfunction emitBlockBody(\n writer: LineWriter,\n node: SyntaxNode,\n closingTrailing: string | undefined,\n classify: MemberClassifier,\n): void {\n const children = Array.from(node.children());\n const openIndex = children.findIndex((el) => !(el instanceof SyntaxNode) && el.kind === 'LBrace');\n\n streamHeader(writer, node);\n const headerComment = sameLineCommentAfter(children, openIndex);\n if (headerComment !== undefined) writer.comment(headerComment);\n else writer.newline();\n\n writer.indent();\n walkRegion(writer, children, 'RBrace', classify);\n writer.unindent();\n\n writer.writeRaw('}');\n if (closingTrailing !== undefined) writer.comment(closingTrailing);\n else writer.newline();\n}\n\nfunction streamHeader(writer: LineWriter, node: SyntaxNode): void {\n let done = false;\n const walk = (parent: SyntaxNode): void => {\n for (const child of parent.children()) {\n if (done) return;\n if (child instanceof SyntaxNode) {\n walk(child);\n continue;\n }\n if (child.kind === 'Whitespace' || child.kind === 'Newline' || child.kind === 'Comment') {\n continue;\n }\n const space = spaceBetween(writer.prevKind(), child.kind, false);\n writer.write(child, space);\n if (child.kind === 'LBrace') {\n done = true;\n return;\n }\n }\n };\n walk(node);\n}\n\nfunction walkRegion(\n writer: LineWriter,\n elements: readonly SyntaxElement[],\n closeKind: 'RBrace' | undefined,\n classify: MemberClassifier,\n): void {\n let sawOpenBrace = closeKind === undefined;\n let sawContent = false;\n let lastWasRegular = false;\n let ledByComment = false;\n let newlines = 0;\n\n for (let i = 0; i < elements.length; i++) {\n const element = elements[i];\n if (element === undefined) continue;\n\n if (element instanceof SyntaxNode) {\n if (!sawOpenBrace) continue;\n const member = classify(element);\n if (member === undefined) continue;\n if (!ledByComment) {\n if (newlines >= 2 && sawContent && !writer.lastIsBlank()) writer.blank();\n else if (separationBlankWanted(writer, member.category, sawContent, lastWasRegular)) {\n writer.blank();\n }\n }\n\n const trailing = sameLineTrailingComment(elements, i);\n closeContinuation(writer, member.emit(trailing.text));\n if (trailing.index !== undefined) i = trailing.index;\n sawContent = true;\n lastWasRegular = member.category !== 'blockAttribute';\n ledByComment = false;\n newlines = 0;\n continue;\n }\n\n if (element.kind === 'LBrace' && closeKind === 'RBrace' && !sawOpenBrace) {\n sawOpenBrace = true;\n newlines = 0;\n continue;\n }\n if (!sawOpenBrace) continue;\n if (closeKind === 'RBrace' && element.kind === 'RBrace') break;\n if (element.kind === 'Whitespace') continue;\n if (element.kind === 'Newline') {\n newlines += 1;\n continue;\n }\n if (element.kind === 'Comment') {\n if (closeKind === 'RBrace' && newlines === 0 && !sawContent) {\n // Same-line comment trailing the opening `{`: owned by the block header.\n continue;\n }\n if (newlines >= 2 && sawContent && !writer.lastIsBlank()) writer.blank();\n else if (!ledByComment) {\n const led = leadingMemberAfter(elements, i, classify);\n if (led && separationBlankWanted(writer, led, sawContent, lastWasRegular)) writer.blank();\n }\n writer.writeRaw(element.text);\n writer.newline();\n sawContent = true;\n ledByComment = true;\n newlines = 0;\n }\n }\n}\n\nfunction separationBlankWanted(\n writer: LineWriter,\n category: MemberCategory,\n sawContent: boolean,\n lastWasRegular: boolean,\n): boolean {\n if (!sawContent || writer.lastIsBlank()) return false;\n if (category === 'nestedBlock') return true;\n return category === 'blockAttribute' && lastWasRegular;\n}\n\nfunction leadingMemberAfter(\n elements: readonly SyntaxElement[],\n commentIndex: number,\n classify: MemberClassifier,\n): MemberCategory | undefined {\n for (let i = commentIndex + 1; i < elements.length; i++) {\n const element = elements[i];\n if (element === undefined) continue;\n if (element instanceof SyntaxNode) return classify(element)?.category;\n if (element.kind === 'RBrace') return undefined;\n }\n return undefined;\n}\n\nfunction sameLineTrailingComment(\n elements: readonly SyntaxElement[],\n memberIndex: number,\n): { text: string | undefined; index: number | undefined } {\n for (let i = memberIndex + 1; i < elements.length; i++) {\n const element = elements[i];\n if (element === undefined) continue;\n if (element instanceof SyntaxNode) break;\n if (element.kind === 'Whitespace') continue;\n if (element.kind === 'Comment') return { text: element.text, index: i };\n break;\n }\n return { text: undefined, index: undefined };\n}\n\nfunction sameLineCommentAfter(\n children: readonly SyntaxElement[],\n openIndex: number,\n): string | undefined {\n for (let i = openIndex + 1; i < children.length; i++) {\n const child = children[i];\n if (child === undefined) continue;\n if (child instanceof SyntaxNode) return undefined;\n if (child.kind === 'Whitespace') continue;\n if (child.kind === 'Comment') return child.text;\n return undefined;\n }\n return undefined;\n}\n\ninterface AlignmentColumns {\n readonly typeColumn: number;\n readonly attributeColumn: number;\n}\n\nfunction alignmentMap(block: SyntaxNode): AlignmentColumns | undefined {\n const fields: SyntaxNode[] = [];\n for (const element of block.children()) {\n if (!(element instanceof SyntaxNode)) continue;\n if (FieldDeclarationAst.cast(element) === undefined) continue;\n // Interior comments split rows into continuation lines, so those rows opt out of alignment.\n if (hasInteriorComment(element)) continue;\n fields.push(element);\n }\n if (fields.length === 0) return undefined;\n return alignmentColumns(fields);\n}\n\nfunction alignmentColumns(rows: readonly SyntaxNode[]): AlignmentColumns {\n let nameWidth = 0;\n for (const row of rows) {\n const field = FieldDeclarationAst.cast(row);\n if (!field) continue;\n nameWidth = Math.max(nameWidth, renderTokens(field.name()?.syntax).length);\n }\n const typeColumn = nameWidth + 1;\n let cellEnd = 0;\n for (const row of rows) {\n const field = FieldDeclarationAst.cast(row);\n if (!field) continue;\n const name = renderTokens(field.name()?.syntax);\n const type = renderTokens(field.typeAnnotation()?.syntax);\n cellEnd = Math.max(cellEnd, type.length > 0 ? typeColumn + type.length : name.length);\n }\n return { typeColumn, attributeColumn: cellEnd + 1 };\n}\n\nfunction hasInteriorComment(node: SyntaxNode): boolean {\n for (const token of node.tokens()) {\n if (token.kind === 'Comment') return true;\n }\n return false;\n}\n\nfunction renderTokens(node: SyntaxNode | undefined): string {\n if (!node) return '';\n let out = '';\n let prev: TokenKind | undefined;\n let prevQualified = false;\n const walk = (parent: SyntaxNode, qualified: boolean): void => {\n for (const child of parent.children()) {\n if (child instanceof SyntaxNode) {\n walk(child, qualified || child.kind === 'QualifiedName');\n continue;\n }\n if (child.kind === 'Whitespace' || child.kind === 'Newline' || child.kind === 'Comment') {\n continue;\n }\n if (spaceBetween(prev, child.kind, qualified && prevQualified)) out += ' ';\n out += child.text;\n prev = child.kind;\n prevQualified = qualified;\n }\n };\n walk(node, false);\n return out;\n}\n","import type { StructuredError, StructuredErrorOptions } from '@prisma-next/utils/structured-error';\nimport { structuredError } from '@prisma-next/utils/structured-error';\n\nexport type PslCode = `PSL.${PslSubcode}`;\n\ntype PslSubcode = 'FORMAT_OPTION_INVALID' | 'PARSE_FAILED';\n\nexport function pslError(\n code: PslCode,\n message: string,\n options?: StructuredErrorOptions,\n): StructuredError {\n return structuredError(code, message, options);\n}\n","import { pslError } from './error';\n\nexport interface FormatOptions {\n readonly indent?: number | 'tab';\n readonly newline?: 'LF' | 'CRLF';\n}\n\nexport interface ResolvedFormatOptions {\n readonly indentUnit: string;\n readonly newline: string;\n}\n\nexport function resolveFormatOptions(options: FormatOptions | undefined): ResolvedFormatOptions {\n const indent = options?.indent ?? 2;\n if (indent !== 'tab' && (typeof indent !== 'number' || !Number.isInteger(indent) || indent < 1)) {\n throw pslError(\n 'PSL.FORMAT_OPTION_INVALID',\n `Invalid format options: indent must be a positive integer or 'tab', got ${String(indent)}`,\n { meta: { option: 'indent', received: String(indent) } },\n );\n }\n const newline = options?.newline ?? 'LF';\n if (newline !== 'LF' && newline !== 'CRLF') {\n throw pslError(\n 'PSL.FORMAT_OPTION_INVALID',\n `Invalid format options: newline must be 'LF' or 'CRLF', got ${String(newline)}`,\n { meta: { option: 'newline', received: String(newline) } },\n );\n }\n return {\n indentUnit: indent === 'tab' ? '\\t' : ' '.repeat(indent),\n newline: newline === 'CRLF' ? '\\r\\n' : '\\n',\n };\n}\n","import { parse } from '../parse';\nimport { emitDocument } from './emit';\nimport { pslError } from './error';\nimport { type FormatOptions, resolveFormatOptions } from './options';\n\nexport function format(source: string, options?: FormatOptions): string {\n const resolved = resolveFormatOptions(options);\n const { document, diagnostics } = parse(source);\n if (diagnostics.length > 0) {\n const summary = diagnostics[0]?.message ?? 'unknown parse error';\n const more = diagnostics.length > 1 ? ` (and ${diagnostics.length - 1} more)` : '';\n throw pslError('PSL.PARSE_FAILED', `Cannot format PSL with parse errors: ${summary}${more}`, {\n meta: { diagnostics },\n });\n }\n return emitDocument(document, resolved.indentUnit, resolved.newline);\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,19 +1,19 @@
1
1
  {
2
2
  "name": "@prisma-next/psl-parser",
3
- "version": "0.16.0-dev.30",
3
+ "version": "0.16.0-dev.31",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "sideEffects": false,
7
7
  "description": "Reusable parser for Prisma Schema Language (PSL)",
8
8
  "dependencies": {
9
- "@prisma-next/config": "0.16.0-dev.30",
10
- "@prisma-next/contract": "0.16.0-dev.30",
11
- "@prisma-next/framework-components": "0.16.0-dev.30",
12
- "@prisma-next/utils": "0.16.0-dev.30"
9
+ "@prisma-next/config": "0.16.0-dev.31",
10
+ "@prisma-next/contract": "0.16.0-dev.31",
11
+ "@prisma-next/framework-components": "0.16.0-dev.31",
12
+ "@prisma-next/utils": "0.16.0-dev.31"
13
13
  },
14
14
  "devDependencies": {
15
- "@prisma-next/tsconfig": "0.16.0-dev.30",
16
- "@prisma-next/tsdown": "0.16.0-dev.30",
15
+ "@prisma-next/tsconfig": "0.16.0-dev.31",
16
+ "@prisma-next/tsdown": "0.16.0-dev.31",
17
17
  "tsdown": "0.22.8",
18
18
  "typescript": "5.9.3",
19
19
  "vitest": "4.1.10"
@@ -3,7 +3,7 @@ import { structuredError } from '@prisma-next/utils/structured-error';
3
3
 
4
4
  export type PslCode = `PSL.${PslSubcode}`;
5
5
 
6
- type PslSubcode = 'PARSE_FAILED';
6
+ type PslSubcode = 'FORMAT_OPTION_INVALID' | 'PARSE_FAILED';
7
7
 
8
8
  export function pslError(
9
9
  code: PslCode,
@@ -1,3 +1,5 @@
1
+ import { pslError } from './error';
2
+
1
3
  export interface FormatOptions {
2
4
  readonly indent?: number | 'tab';
3
5
  readonly newline?: 'LF' | 'CRLF';
@@ -11,14 +13,18 @@ export interface ResolvedFormatOptions {
11
13
  export function resolveFormatOptions(options: FormatOptions | undefined): ResolvedFormatOptions {
12
14
  const indent = options?.indent ?? 2;
13
15
  if (indent !== 'tab' && (typeof indent !== 'number' || !Number.isInteger(indent) || indent < 1)) {
14
- throw new TypeError(
16
+ throw pslError(
17
+ 'PSL.FORMAT_OPTION_INVALID',
15
18
  `Invalid format options: indent must be a positive integer or 'tab', got ${String(indent)}`,
19
+ { meta: { option: 'indent', received: String(indent) } },
16
20
  );
17
21
  }
18
22
  const newline = options?.newline ?? 'LF';
19
23
  if (newline !== 'LF' && newline !== 'CRLF') {
20
- throw new TypeError(
24
+ throw pslError(
25
+ 'PSL.FORMAT_OPTION_INVALID',
21
26
  `Invalid format options: newline must be 'LF' or 'CRLF', got ${String(newline)}`,
27
+ { meta: { option: 'newline', received: String(newline) } },
22
28
  );
23
29
  }
24
30
  return {