UNPKG

@devaloop/prettier-plugin-devalang

Version:

Prettier plugin for Devalang formatting

169 lines (168 loc) 6.23 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.astFormat = exports.preprocess = exports.hasPragma = exports.massageAstNode = exports.insertPragma = exports.embed = exports.print = void 0; const prettier_1 = require("prettier"); const parser_1 = require("./parser"); const { hardline, indent, join, group } = prettier_1.doc.builders; /** * Prints an expression by its type. * @param expr Expression * @returns string */ const printExpression = (expr) => { switch (expr.type) { case "Identifier": return expr.name; case "NumberLiteral": return expr.value.toString(); case "StringLiteral": return `"${expr.value}"`; case "BooleanLiteral": return expr.value ? "true" : "false"; case "ObjectLiteral": if (!expr.properties || expr.properties.length === 0) { return ""; } return `{ ${expr.properties .map((p) => `${p.key ? p.key + ':' : ''} ${printExpression(p.value)}`) .join(", ")} }`; case "ObjectProperty": return `${expr.key}: ${printExpression(expr.value)}`; case "SynthReference": return `synth ${expr.name}`; default: throw new Error(`Unsupported expression type: ${expr.type}`); } }; /** * Prints a node matching its type. * @param path AstPath<Node> * @param options any * @param print (path: AstPath<Node>) => Doc * @returns Doc */ const print = (path, options, print) => { const node = path.node ? path.node : path.getValue(); // NOTE: See the parsed AST in the console for debugging purposes. if (node.type === "Program") { console.log("\nPrettier AST :"); console.dir(node, { depth: null, colors: true }); console.log(); } switch (node.type) { case "Program": { const printedNodes = path.map(print, "body"); const parts = []; for (let i = 0; i < node.body.length; i++) { const printed = printedNodes[i]; if (printed === "" || printed === undefined) continue; parts.push(printed); const nextNode = node.body[i + 1]; if (!nextNode || nextNode.type === "BlankLine") continue; parts.push(hardline); } while (parts.length > 0 && parts[parts.length - 1] === hardline) { parts.pop(); } return parts; } case "BpmDeclaration": return `bpm ${node.identifier}`; case "BankDeclaration": return `bank ${node.identifier}`; case "LetDeclaration": return `let ${node.name} = ${printExpression(node.value)}`; case "Loop": { const parts = (0, parser_1.parseBlock)(node.body); return group([ `loop ${node.iterator.value}:`, indent([hardline, ...parts]) ]); } case "Trigger": return `${node.name} ${node.args.length && node.duration ? node.duration.value + " " : node.duration ? node.duration.value : ""}${printArguments(node.args)}`; case "ImportStatement": return `@import { ${node.identifiers.join(", ")} } from "${node.from}"`; case "ExportStatement": return `@export { ${node.identifiers.join(", ")} }`; case "LoadSample": return `@load "${node.path}" as ${node.alias}`; case "Group": { const rawChildren = node.body; const parts = (0, parser_1.parseBlock)(rawChildren); return ["group ", node.name, ":", indent([hardline, ...parts])]; } case "Call": return `call ${node.identifier}`; case "Sleep": return `sleep ${node.value}`; case "Spawn": return `spawn ${node.identifier}`; case "If": { const parts = []; // if parts.push(`if ${node.condition}:`); parts.push(indent([hardline, ...(0, parser_1.parseBlock)(node.body)])); // else ifs for (const elseIf of node.elseIfs ?? []) { parts.push(hardline, `else if ${elseIf.condition}:`); parts.push(indent([hardline, ...(0, parser_1.parseBlock)(elseIf.body)])); } // else if (node.alternate && node.alternate.length > 0) { parts.push(hardline, "else:"); parts.push(indent([hardline, ...(0, parser_1.parseBlock)(node.alternate)])); } return group(parts); } case "Comment": return node.value; case "Unknown": return node.value; case "BlankLine": return hardline; case "ArrowCall": return printArrowCall(node); default: throw new Error(`Unsupported node type: ${node.type}`); } }; exports.print = print; const printArrowCall = (call) => { const target = call.target; const func = call.method; const args = call.args .filter((arg) => !(arg.type === "ObjectLiteral" && arg.properties.length === 0)); if (args.length === 0) { return `${target} -> ${func}()`; } return group([ `${target} -> ${func}(`, join(", ", args.map(printExpression)), ")" ]); }; const printArguments = (args) => { if (args.length === 0) return ""; const isAllObjectProps = args.every(arg => arg.type === "ObjectProperty"); if (isAllObjectProps) { const props = args; const printedProps = props .map((p) => `${p.key}: ${printExpression(p.value)}`) .join(", "); return printedProps ? `{ ${printedProps} }` : ""; } if (args.length === 1 && args[0].type === "Identifier") { return args[0].name; } return args.map(printExpression).join(", "); }; exports.embed = undefined; exports.insertPragma = undefined; exports.massageAstNode = undefined; exports.hasPragma = undefined; exports.preprocess = undefined; exports.astFormat = "devalang";