fish-lsp
Version:
LSP implementation for fish/fish-shell
98 lines (97 loc) • 3.06 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.convertIfToCombinersString = convertIfToCombinersString;
const tree_sitter_1 = require("../utils/tree-sitter");
const node_types_1 = require("../utils/node-types");
function convertIfToCombinersString(node) {
const combiner = new StatementCombiner();
const queue = (0, tree_sitter_1.getNamedChildNodes)(node);
while (queue.length > 0) {
const n = queue.shift();
if (!n)
break;
switch (true) {
case (0, node_types_1.isConditional)(n):
combiner.newBlock(n.type);
break;
case n.type === 'negated_statement':
case n.type === 'conditional_execution':
combiner.appendCommand(n);
skipChildren(n, queue);
break;
case n.type === 'comment':
case n.type === 'command':
combiner.appendCommand(n);
break;
}
}
return combiner.build();
}
function skipChildren(node, queue) {
while (queue.length > 0) {
const peek = queue.at(0);
if (!peek)
break;
if (peek.endIndex > node.endIndex || peek.startIndex < node.startIndex)
break;
queue.shift();
}
}
var ConditionalBlock;
(function (ConditionalBlock) {
function create(keyword, body = []) {
return { keyword, body };
}
ConditionalBlock.create = create;
})(ConditionalBlock || (ConditionalBlock = {}));
class StatementCombiner {
blocks = [];
get currentBlock() {
if (this.blocks.length === 0) {
return undefined;
}
return this.blocks[this.blocks.length - 1];
}
newBlock(keywordType) {
this.blocks.push(ConditionalBlock.create(keywordType));
}
appendCommand(node) {
if (!this.currentBlock) {
throw new Error('Cannot append command to non-existent block, please create a new block first');
}
this.currentBlock.body.push(node);
}
getCombinerFromKeyword(block) {
switch (block.keyword) {
case 'if_statement':
return '';
case 'else_if_clause':
case 'else_clause':
return 'or ';
}
}
buildBlockString(block) {
let str = this.getCombinerFromKeyword(block);
block.body.forEach((node, idx) => {
const nextNode = block.body.length - 1 >= idx
? block.body[idx + 1]
: undefined;
if (nextNode && nextNode.type === 'comment') {
str += node.text + '\n';
}
else if (nextNode && nextNode.type === 'command') {
str += node.text + '\nand ';
}
else {
str += node.text + '\n';
}
});
return str;
}
build() {
return this.blocks
.map(block => this.buildBlockString(block))
.join('\n')
.trim();
}
}