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