sql-formatter
Version:
Formats whitespaces in a SQL query to make it more readable
210 lines (157 loc) • 8.02 kB
JavaScript
"use strict";
exports.__esModule = true;
var _classCallCheck2 = require("babel-runtime/helpers/classCallCheck");
var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
var _trimEnd = require("lodash/trimEnd");
var _trimEnd2 = _interopRequireDefault(_trimEnd);
var _tokenTypes = require("./tokenTypes");
var _tokenTypes2 = _interopRequireDefault(_tokenTypes);
var _Indentation = require("./Indentation");
var _Indentation2 = _interopRequireDefault(_Indentation);
var _InlineBlock = require("./InlineBlock");
var _InlineBlock2 = _interopRequireDefault(_InlineBlock);
var _Params = require("./Params");
var _Params2 = _interopRequireDefault(_Params);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
var Formatter = function () {
/**
* @param {Object} cfg
* @param {Object} cfg.indent
* @param {Object} cfg.params
* @param {Tokenizer} tokenizer
*/
function Formatter(cfg, tokenizer) {
(0, _classCallCheck3["default"])(this, Formatter);
this.cfg = cfg || {};
this.indentation = new _Indentation2["default"](this.cfg.indent);
this.inlineBlock = new _InlineBlock2["default"]();
this.params = new _Params2["default"](this.cfg.params);
this.tokenizer = tokenizer;
this.previousReservedWord = {};
}
/**
* Formats whitespaces in a SQL string to make it easier to read.
*
* @param {String} query The SQL query string
* @return {String} formatted query
*/
Formatter.prototype.format = function format(query) {
var tokens = this.tokenizer.tokenize(query);
var formattedQuery = this.getFormattedQueryFromTokens(tokens);
return formattedQuery.trim();
};
Formatter.prototype.getFormattedQueryFromTokens = function getFormattedQueryFromTokens(tokens) {
var _this = this;
var formattedQuery = "";
tokens.forEach(function (token, index) {
if (token.type === _tokenTypes2["default"].WHITESPACE) {
return;
} else if (token.type === _tokenTypes2["default"].LINE_COMMENT) {
formattedQuery = _this.formatLineComment(token, formattedQuery);
} else if (token.type === _tokenTypes2["default"].BLOCK_COMMENT) {
formattedQuery = _this.formatBlockComment(token, formattedQuery);
} else if (token.type === _tokenTypes2["default"].RESERVED_TOPLEVEL) {
formattedQuery = _this.formatToplevelReservedWord(token, formattedQuery);
_this.previousReservedWord = token;
} else if (token.type === _tokenTypes2["default"].RESERVED_NEWLINE) {
formattedQuery = _this.formatNewlineReservedWord(token, formattedQuery);
_this.previousReservedWord = token;
} else if (token.type === _tokenTypes2["default"].RESERVED) {
formattedQuery = _this.formatWithSpaces(token, formattedQuery);
_this.previousReservedWord = token;
} else if (token.type === _tokenTypes2["default"].OPEN_PAREN) {
formattedQuery = _this.formatOpeningParentheses(tokens, index, formattedQuery);
} else if (token.type === _tokenTypes2["default"].CLOSE_PAREN) {
formattedQuery = _this.formatClosingParentheses(token, formattedQuery);
} else if (token.type === _tokenTypes2["default"].PLACEHOLDER) {
formattedQuery = _this.formatPlaceholder(token, formattedQuery);
} else if (token.value === ",") {
formattedQuery = _this.formatComma(token, formattedQuery);
} else if (token.value === ":") {
formattedQuery = _this.formatWithSpaceAfter(token, formattedQuery);
} else if (token.value === "." || token.value === ";") {
formattedQuery = _this.formatWithoutSpaces(token, formattedQuery);
} else {
formattedQuery = _this.formatWithSpaces(token, formattedQuery);
}
});
return formattedQuery;
};
Formatter.prototype.formatLineComment = function formatLineComment(token, query) {
return this.addNewline(query + token.value);
};
Formatter.prototype.formatBlockComment = function formatBlockComment(token, query) {
return this.addNewline(this.addNewline(query) + this.indentComment(token.value));
};
Formatter.prototype.indentComment = function indentComment(comment) {
return comment.replace(/\n/g, "\n" + this.indentation.getIndent());
};
Formatter.prototype.formatToplevelReservedWord = function formatToplevelReservedWord(token, query) {
this.indentation.decreaseTopLevel();
query = this.addNewline(query);
this.indentation.increaseToplevel();
query += this.equalizeWhitespace(token.value);
return this.addNewline(query);
};
Formatter.prototype.formatNewlineReservedWord = function formatNewlineReservedWord(token, query) {
return this.addNewline(query) + this.equalizeWhitespace(token.value) + " ";
};
// Replace any sequence of whitespace characters with single space
Formatter.prototype.equalizeWhitespace = function equalizeWhitespace(string) {
return string.replace(/\s+/g, " ");
};
// Opening parentheses increase the block indent level and start a new line
Formatter.prototype.formatOpeningParentheses = function formatOpeningParentheses(tokens, index, query) {
// Take out the preceding space unless there was whitespace there in the original query or another opening parens
var previousToken = tokens[index - 1];
if (previousToken && previousToken.type !== _tokenTypes2["default"].WHITESPACE && previousToken.type !== _tokenTypes2["default"].OPEN_PAREN) {
query = (0, _trimEnd2["default"])(query);
}
query += tokens[index].value;
this.inlineBlock.beginIfPossible(tokens, index);
if (!this.inlineBlock.isActive()) {
this.indentation.increaseBlockLevel();
query = this.addNewline(query);
}
return query;
};
// Closing parentheses decrease the block indent level
Formatter.prototype.formatClosingParentheses = function formatClosingParentheses(token, query) {
if (this.inlineBlock.isActive()) {
this.inlineBlock.end();
return this.formatWithSpaceAfter(token, query);
} else {
this.indentation.decreaseBlockLevel();
return this.formatWithSpaces(token, this.addNewline(query));
}
};
Formatter.prototype.formatPlaceholder = function formatPlaceholder(token, query) {
return query + this.params.get(token) + " ";
};
// Commas start a new line (unless within inline parentheses or SQL "LIMIT" clause)
Formatter.prototype.formatComma = function formatComma(token, query) {
query = (0, _trimEnd2["default"])(query) + token.value + " ";
if (this.inlineBlock.isActive()) {
return query;
} else if (/^LIMIT$/i.test(this.previousReservedWord.value)) {
return query;
} else {
return this.addNewline(query);
}
};
Formatter.prototype.formatWithSpaceAfter = function formatWithSpaceAfter(token, query) {
return (0, _trimEnd2["default"])(query) + token.value + " ";
};
Formatter.prototype.formatWithoutSpaces = function formatWithoutSpaces(token, query) {
return (0, _trimEnd2["default"])(query) + token.value;
};
Formatter.prototype.formatWithSpaces = function formatWithSpaces(token, query) {
return query + token.value + " ";
};
Formatter.prototype.addNewline = function addNewline(query) {
return (0, _trimEnd2["default"])(query) + "\n" + this.indentation.getIndent();
};
return Formatter;
}();
exports["default"] = Formatter;
module.exports = exports["default"];