'use strict'; const isArray = Array.isArray; const Node = require('./ast/Node'); const Literal = require('./ast/Literal'); const Identifier = require('./ast/Identifier'); const ok = require('assert').ok; const Container = require('./ast/Container'); const Comment = require('./ast/Comment'); const isValidJavaScriptVarName = require('./util/isValidJavaScriptVarName'); class CodeWriter { constructor(options, builder) { ok(builder, '"builder" is required'); options = options || {}; this.builder = builder; this.root = null; this._indentStr = options.indent != null ? options.indent : ' '; this._indentSize = this._indentStr.length; this._code = ''; this.currentIndent = ''; } getCode() { return this._code; } writeBlock(body) { if (!body) { this.write('{}'); return; } if (typeof body === 'function') { body = body(); } if (!body || (Array.isArray(body) && body.length === 0) || (body instanceof Container && body.length === 0)) { this.write('{}'); return; } this.write('{\n') .incIndent(); this.writeStatements(body); this.decIndent() .writeLineIndent() .write('}'); } writeStatements(nodes) { if (!nodes) { return; } ok(nodes, '"nodes" expected'); let firstStatement = true; var writeNode = (node) => { if (Array.isArray(node) || (node instanceof Container)) { node.forEach(writeNode); return; } else { if (firstStatement) { firstStatement = false; } else { this._write('\n'); } this.writeLineIndent(); if (typeof node === 'string') { this._write(node); } else { node.statement = true; this.write(node); } if (this._code.endsWith('\n')) { // Do nothing } else if (this._code.endsWith(';')) { this._code += '\n'; } else if (this._code.endsWith('\n' + this.currentIndent) || node instanceof Comment) { // Do nothing } else { this._code += ';\n'; } } }; if (nodes instanceof Node) { writeNode(nodes); } else { nodes.forEach(writeNode); } } write(code) { if (code == null || code === '') { return; } if (code instanceof Node) { let node = code; if (!node.writeCode) { throw new Error('Node does not have a `writeCode` method: ' + JSON.stringify(node, null, 4)); } node.writeCode(this); } else if (isArray(code) || code instanceof Container) { code.forEach(this.write, this); return; } else if (typeof code === 'string') { this._code += code; } else if (typeof code === 'boolean' || typeof code === 'number') { this._code += code.toString(); } else { throw new Error('Illegal argument: ' + JSON.stringify(code)); } return this; } _write(code) { this._code += code; return this; } incIndent(count) { if (count != null) { for (let i=0; i