UNPKG

@jqassistant/ts-lce

Version:

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

226 lines (225 loc) 14.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ComplexValueProcessor = exports.ClassValueProcessor = exports.FunctionValueProcessor = exports.CallValueProcessor = exports.ArrayValueProcessor = exports.ObjectValuePropertyProcessor = exports.ObjectValueProcessor = exports.MemberValueProcessor = exports.IdentifierValueProcessor = exports.LiteralValueProcessor = void 0; const utils_1 = require("@typescript-eslint/utils"); const concept_1 = require("../concept"); const value_concept_1 = require("../concepts/value.concept"); const context_1 = require("../context"); const execution_condition_1 = require("../execution-condition"); const processor_1 = require("../processor"); const processor_utils_1 = require("../utils/processor.utils"); const expression_traverser_1 = require("../traversers/expression.traverser"); const property_traverser_1 = require("../traversers/property.traverser"); const dependency_resolution_processor_1 = require("./dependency-resolution.processor"); const type_utils_1 = require("./type.utils"); const variable_declaration_processor_1 = require("./variable-declaration.processor"); const context_keys_1 = require("../context.keys"); class LiteralValueProcessor extends processor_1.Processor { executionCondition = new execution_condition_1.ExecutionCondition([utils_1.AST_NODE_TYPES.Literal], ({ localContexts }) => { return !!localContexts.parentContexts?.has(context_keys_1.CoreContextKeys.VALUE_PROCESSING_FLAG); }); postChildrenProcessing({ node }) { if (node.type === utils_1.AST_NODE_TYPES.Literal) { if (node.value === null) { return (0, concept_1.singleEntryConceptMap)(value_concept_1.LCEValueNull.conceptId, new value_concept_1.LCEValueNull("null")); } else { return (0, concept_1.singleEntryConceptMap)(value_concept_1.LCEValueLiteral.conceptId, new value_concept_1.LCEValueLiteral(node.value)); } } return new Map(); } } exports.LiteralValueProcessor = LiteralValueProcessor; class IdentifierValueProcessor extends processor_1.Processor { executionCondition = new execution_condition_1.ExecutionCondition([utils_1.AST_NODE_TYPES.Identifier], ({ localContexts }) => { return !!localContexts.parentContexts?.has(context_keys_1.CoreContextKeys.VALUE_PROCESSING_FLAG); }); postChildrenProcessing({ node, localContexts, ...unusedProcessingContext }) { if (node.type === utils_1.AST_NODE_TYPES.Identifier) { if (node.name === "undefined") { return (0, concept_1.singleEntryConceptMap)(value_concept_1.LCEValueNull.conceptId, new value_concept_1.LCEValueNull("undefined")); } else { const declaredValue = new value_concept_1.LCEValueDeclared((0, type_utils_1.parseESNodeType)({ node, localContexts, ...unusedProcessingContext, }, node, node.name, true), new context_1.FQN(node.name)); const resolve = localContexts.parentContexts?.get(context_keys_1.CoreContextKeys.DO_NOT_RESOLVE_IDENTIFIER_FLAG); if (resolve === undefined || (resolve === 0 && (0, processor_utils_1.getParentPropName)(localContexts) === expression_traverser_1.MemberExpressionTraverser.OBJECT_PROP)) { dependency_resolution_processor_1.DependencyResolutionProcessor.scheduleFqnResolution(localContexts, node.name, declaredValue); } return (0, concept_1.singleEntryConceptMap)(value_concept_1.LCEValueDeclared.conceptId, declaredValue); } } return new Map(); } } exports.IdentifierValueProcessor = IdentifierValueProcessor; class MemberValueProcessor extends processor_1.Processor { executionCondition = new execution_condition_1.ExecutionCondition([utils_1.AST_NODE_TYPES.MemberExpression], ({ localContexts }) => { return !!localContexts.parentContexts?.has(context_keys_1.CoreContextKeys.VALUE_PROCESSING_FLAG); }); preChildrenProcessing({ localContexts }) { localContexts.currentContexts.set(context_keys_1.CoreContextKeys.VALUE_PROCESSING_FLAG, true); if (localContexts.parentContexts?.has(context_keys_1.CoreContextKeys.DO_NOT_RESOLVE_IDENTIFIER_FLAG)) { localContexts.currentContexts.set(context_keys_1.CoreContextKeys.DO_NOT_RESOLVE_IDENTIFIER_FLAG, localContexts.parentContexts?.get(context_keys_1.CoreContextKeys.DO_NOT_RESOLVE_IDENTIFIER_FLAG) + 1); } else { localContexts.currentContexts.set(context_keys_1.CoreContextKeys.DO_NOT_RESOLVE_IDENTIFIER_FLAG, 0); } } postChildrenProcessing({ node }, childConcepts) { if (node.type === utils_1.AST_NODE_TYPES.MemberExpression && childConcepts.has(expression_traverser_1.MemberExpressionTraverser.OBJECT_PROP) && childConcepts.has(expression_traverser_1.MemberExpressionTraverser.PROPERTY_PROP)) { const objects = (0, processor_utils_1.getAndDeleteAllValueChildConcepts)(expression_traverser_1.MemberExpressionTraverser.OBJECT_PROP, childConcepts); const properties = (0, processor_utils_1.getAndDeleteAllValueChildConcepts)(expression_traverser_1.MemberExpressionTraverser.PROPERTY_PROP, childConcepts); if (node.computed) { // TODO: handled computed member expressions return (0, concept_1.singleEntryConceptMap)(value_concept_1.LCEValueComplex.conceptId, new value_concept_1.LCEValueComplex("computed member expression")); } if (objects.length === 1 && properties.length === 1) { return (0, concept_1.singleEntryConceptMap)(value_concept_1.LCEValueMember.conceptId, new value_concept_1.LCEValueMember(properties[0].type, objects[0], properties[0])); } } return new Map(); } } exports.MemberValueProcessor = MemberValueProcessor; class ObjectValueProcessor extends processor_1.Processor { executionCondition = new execution_condition_1.ExecutionCondition([utils_1.AST_NODE_TYPES.ObjectExpression], ({ localContexts }) => { return !!localContexts.parentContexts?.has(context_keys_1.CoreContextKeys.VALUE_PROCESSING_FLAG); }); preChildrenProcessing({ localContexts }) { localContexts.currentContexts.set(context_keys_1.CoreContextKeys.VALUE_PROCESSING_FLAG, true); } postChildrenProcessing({ node, localContexts, ...unusedProcessingContext }, childConcepts) { if (node.type === utils_1.AST_NODE_TYPES.ObjectExpression) { const properties = (0, processor_utils_1.getAndDeleteChildConcepts)(expression_traverser_1.ObjectExpressionTraverser.PROPERTIES_PROP, value_concept_1.LCEValueObjectProperty.conceptId, childConcepts); const variableDeclarationFQN = localContexts.getNextContext(variable_declaration_processor_1.VariableDeclaratorProcessor.VARIABLE_DECLARATOR_FQN_CONTEXT); const type = (0, type_utils_1.parseESNodeType)({ node, localContexts, ...unusedProcessingContext }, node, variableDeclarationFQN?.[0]); return (0, concept_1.singleEntryConceptMap)(value_concept_1.LCEValueObject.conceptId, new value_concept_1.LCEValueObject(type, new Map(properties.map((prop) => [prop.name, prop.value])))); } return new Map(); } } exports.ObjectValueProcessor = ObjectValueProcessor; class ObjectValuePropertyProcessor extends processor_1.Processor { executionCondition = new execution_condition_1.ExecutionCondition([utils_1.AST_NODE_TYPES.Property], ({ localContexts }) => { return !!localContexts.parentContexts?.has(context_keys_1.CoreContextKeys.VALUE_PROCESSING_FLAG); }); preChildrenProcessing({ localContexts }) { localContexts.currentContexts.set(context_keys_1.CoreContextKeys.VALUE_PROCESSING_FLAG, true); } postChildrenProcessing({ node }, childConcepts) { if (node.type === utils_1.AST_NODE_TYPES.Property) { (0, processor_utils_1.getAndDeleteAllValueChildConcepts)(property_traverser_1.PropertyTraverser.KEY_PROP, childConcepts); const properties = (0, processor_utils_1.getAndDeleteAllValueChildConcepts)(property_traverser_1.PropertyTraverser.INITIALIZER_PROP, childConcepts); if (node.key.type === utils_1.AST_NODE_TYPES.Identifier && properties.length === 1) { return (0, concept_1.singleEntryConceptMap)(value_concept_1.LCEValueObjectProperty.conceptId, new value_concept_1.LCEValueObjectProperty(node.key.name, properties[0])); } } return new Map(); } } exports.ObjectValuePropertyProcessor = ObjectValuePropertyProcessor; class ArrayValueProcessor extends processor_1.Processor { executionCondition = new execution_condition_1.ExecutionCondition([utils_1.AST_NODE_TYPES.ArrayExpression], ({ localContexts }) => { return !!localContexts.parentContexts?.has(context_keys_1.CoreContextKeys.VALUE_PROCESSING_FLAG); }); preChildrenProcessing({ localContexts }) { localContexts.currentContexts.set(context_keys_1.CoreContextKeys.VALUE_PROCESSING_FLAG, true); } postChildrenProcessing({ node, ...unusedProcessingContext }, childConcepts) { if (node.type === utils_1.AST_NODE_TYPES.ArrayExpression) { const elements = (0, processor_utils_1.getAndDeleteAllValueChildConcepts)(expression_traverser_1.ArrayExpressionTraverser.ELEMENTS_PROP, childConcepts); return (0, concept_1.singleEntryConceptMap)(value_concept_1.LCEValueArray.conceptId, new value_concept_1.LCEValueArray((0, type_utils_1.parseESNodeType)({ node, ...unusedProcessingContext }, node), elements)); } return new Map(); } } exports.ArrayValueProcessor = ArrayValueProcessor; class CallValueProcessor extends processor_1.Processor { executionCondition = new execution_condition_1.ExecutionCondition([utils_1.AST_NODE_TYPES.CallExpression], ({ localContexts }) => { return !!localContexts.parentContexts?.has(context_keys_1.CoreContextKeys.VALUE_PROCESSING_FLAG); }); preChildrenProcessing({ localContexts }) { localContexts.currentContexts.set(context_keys_1.CoreContextKeys.VALUE_PROCESSING_FLAG, true); } postChildrenProcessing({ node, ...unusedProcessingContext }, childConcepts) { if (node.type === utils_1.AST_NODE_TYPES.CallExpression) { const callee = (0, processor_utils_1.getAndDeleteAllValueChildConcepts)(expression_traverser_1.CallExpressionTraverser.CALLEE_PROP, childConcepts); const args = (0, processor_utils_1.getAndDeleteAllValueChildConcepts)(expression_traverser_1.CallExpressionTraverser.ARGUMENTS_PROP, childConcepts); return (0, concept_1.singleEntryConceptMap)(value_concept_1.LCEValueCall.conceptId, new value_concept_1.LCEValueCall((0, type_utils_1.parseESNodeType)({ node, ...unusedProcessingContext }, node), callee[0], args, node.typeArguments?.params.map((param) => (0, type_utils_1.parseESNodeType)({ node: param, ...unusedProcessingContext, }, param)) ?? [])); } return new Map(); } } exports.CallValueProcessor = CallValueProcessor; class FunctionValueProcessor extends processor_1.Processor { executionCondition = new execution_condition_1.ExecutionCondition([utils_1.AST_NODE_TYPES.FunctionExpression, utils_1.AST_NODE_TYPES.ArrowFunctionExpression], ({ localContexts }) => { return !!localContexts.parentContexts?.has(context_keys_1.CoreContextKeys.VALUE_PROCESSING_FLAG); }); postChildrenProcessing({ node, ...unusedProcessingContext }) { if (node.type === utils_1.AST_NODE_TYPES.FunctionExpression || node.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression) { let type; if (node.parent && node.parent.type === utils_1.AST_NODE_TYPES.VariableDeclarator && node.parent.id.type === utils_1.AST_NODE_TYPES.Identifier) { type = (0, type_utils_1.parseESNodeType)({ node, ...unusedProcessingContext }, node, node.parent.id.name); } else { type = (0, type_utils_1.parseESNodeType)({ node, ...unusedProcessingContext }, node); } return (0, concept_1.singleEntryConceptMap)(value_concept_1.LCEValueFunction.conceptId, new value_concept_1.LCEValueFunction(type, node.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression)); } return new Map(); } } exports.FunctionValueProcessor = FunctionValueProcessor; class ClassValueProcessor extends processor_1.Processor { executionCondition = new execution_condition_1.ExecutionCondition([utils_1.AST_NODE_TYPES.ClassExpression], ({ localContexts }) => { return !!localContexts.parentContexts?.has(context_keys_1.CoreContextKeys.VALUE_PROCESSING_FLAG); }); postChildrenProcessing({ node }) { if (node.type === utils_1.AST_NODE_TYPES.ClassExpression) { // TODO: add proper class value return (0, concept_1.singleEntryConceptMap)(value_concept_1.LCEValueClass.conceptId, new value_concept_1.LCEValueClass()); } return new Map(); } } exports.ClassValueProcessor = ClassValueProcessor; class ComplexValueProcessor extends processor_1.Processor { executionCondition = new execution_condition_1.ExecutionCondition([ utils_1.AST_NODE_TYPES.SpreadElement, utils_1.AST_NODE_TYPES.ArrayPattern, utils_1.AST_NODE_TYPES.AssignmentExpression, utils_1.AST_NODE_TYPES.AwaitExpression, utils_1.AST_NODE_TYPES.BinaryExpression, utils_1.AST_NODE_TYPES.ChainExpression, utils_1.AST_NODE_TYPES.ConditionalExpression, utils_1.AST_NODE_TYPES.ImportExpression, utils_1.AST_NODE_TYPES.LogicalExpression, utils_1.AST_NODE_TYPES.NewExpression, utils_1.AST_NODE_TYPES.ObjectPattern, utils_1.AST_NODE_TYPES.SequenceExpression, utils_1.AST_NODE_TYPES.TaggedTemplateExpression, utils_1.AST_NODE_TYPES.TemplateLiteral, utils_1.AST_NODE_TYPES.TSAsExpression, utils_1.AST_NODE_TYPES.TSNonNullExpression, utils_1.AST_NODE_TYPES.TSTypeAssertion, utils_1.AST_NODE_TYPES.UnaryExpression, utils_1.AST_NODE_TYPES.UpdateExpression, utils_1.AST_NODE_TYPES.YieldExpression, ], ({ localContexts }) => { return !!localContexts.parentContexts?.has(context_keys_1.CoreContextKeys.VALUE_PROCESSING_FLAG); }); postChildrenProcessing({ node, globalContext }) { return (0, concept_1.singleEntryConceptMap)(value_concept_1.LCEValueComplex.conceptId, new value_concept_1.LCEValueComplex(globalContext.services.esTreeNodeToTSNodeMap.get(node).getText())); } } exports.ComplexValueProcessor = ComplexValueProcessor;