UNPKG

@jqassistant/ts-lce

Version:

Tool to extract language concepts from a TypeScript codebase and export them to a JSON file.

87 lines (86 loc) 3.44 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.SimpleTraverser = exports.Traverser = void 0; exports.createProcessorMap = createProcessorMap; const concept_1 = require("./concept"); const context_keys_1 = require("./context.keys"); const log_utils_1 = require("./utils/log.utils"); /** * Used for traversing an AST. * Provides context for and executes processors for the current node. * Delegates the traversal of any child nodes. */ class Traverser { traverse(traverserContext, processingContext, processors) { // push new local context processingContext.localContexts.pushContexts(); // add traverser context to local context processingContext.localContexts.currentContexts.set(context_keys_1.CoreContextKeys.TRAVERSER_CONTEXT, traverserContext); // find matching processors for current context const processorCandidates = processors.get(processingContext.node.type); let validProcessors = []; if (processorCandidates) { validProcessors = processorCandidates.filter((proc) => proc.executionCondition.check(processingContext)); } (0, log_utils_1.debugTraversalStack)(processingContext.localContexts); // pre-processing if (validProcessors) { for (const proc of validProcessors) { proc.preChildrenProcessing(processingContext); } } // process children const childConcepts = this.traverseChildren(processingContext, processors); // post-processing const concepts = []; if (validProcessors) { for (const proc of validProcessors) { concepts.push(proc.postChildrenProcessing(processingContext, childConcepts)); } } // pop local context processingContext.localContexts.popContexts(); // apply metadata assignment rules for (let i = processingContext.metadataAssignments.length - 1; i >= 0; i--) { const rule = processingContext.metadataAssignments[i]; let applied = false; for (const conceptMap of concepts) { conceptMap.forEach((innerMap) => { innerMap.forEach((innerConcepts) => { innerConcepts.forEach((innerConcept) => { applied = applied || rule.apply(innerConcept); }); }); }); } // remove rule, if it was applied at least once if (applied) { processingContext.metadataAssignments.splice(i, 1); } } // merge newly created concepts and remaining childConcepts return (0, concept_1.mergeConceptMaps)(childConcepts, ...concepts); } } exports.Traverser = Traverser; class SimpleTraverser extends Traverser { traverseChildren() { return new Map(); } } exports.SimpleTraverser = SimpleTraverser; function createProcessorMap(processors) { const processorMap = new Map(); for (const proc of processors) { for (const nodeType of proc.executionCondition.currentNodeType) { const arr = processorMap.get(nodeType); if (arr) { arr.push(proc); } else { processorMap.set(nodeType, [proc]); } } } return processorMap; }