@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
JavaScript
;
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;
}