smells-code-analyzer
Version:
CLI tool powered by LSP and tree-sitter for finding dead and smells code from your project
82 lines • 2.57 kB
JavaScript
import Parser from 'tree-sitter';
import parser from 'tree-sitter-typescript';
export const Grammars = {
typescript: parser.typescript,
};
export function findElemPositions(config, sourceCode) {
const tree = parse(config, sourceCode);
const foundNodes = findNodes(config.referenceNodes, tree);
return foundNodes;
}
function parse(config, sourceCode) {
const parser = new Parser();
const grammar = Grammars[config.grammar];
if (!grammar) {
console.error(`Grammar ${config.grammar} not found`);
}
parser.setLanguage(grammar);
const tree = parser.parse(sourceCode);
return tree;
}
function findNodes(referenceNodes, tree, parent) {
const foundNodeInfos = [];
for (const node of traverseTree(tree, parent)) {
foundNodeInfos.push(...handleNode(referenceNodes, node));
}
return foundNodeInfos;
}
function handleNode(referenceNodes, node) {
const foundNodeInfos = [];
referenceNodes.forEach((referenceNode) => {
if (node.type === referenceNode.type) {
const target = referenceNode.refType
? findTargetNode(node, referenceNode.refType)
: node;
if (!target) {
return;
}
const foundNode = {
name: target.text,
type: node.type,
startPos: target.startPosition,
children: [],
};
if (referenceNode.children) {
foundNode.children.push(...findNodes(referenceNode.children, node.tree, node));
}
foundNodeInfos.push(foundNode);
}
});
return foundNodeInfos;
}
function findTargetNode(parentNode, targetRef) {
for (const node of traverseTree(parentNode.tree, parentNode)) {
if (node.type === targetRef) {
return node;
}
}
}
function* traverseTree(tree, parentNode) {
const cursor = parentNode?.walk() ?? tree.walk();
let reachedRoot = false;
while (!reachedRoot) {
yield cursor.currentNode;
if (cursor.gotoFirstChild()) {
continue;
}
if (cursor.gotoNextSibling()) {
continue;
}
let retracing = true;
while (retracing) {
if (!cursor.gotoParent() || cursor.currentNode === parentNode) {
retracing = false;
reachedRoot = true;
}
if (cursor.gotoNextSibling()) {
retracing = false;
}
}
}
}
//# sourceMappingURL=ts-analyzer.js.map