@jqassistant/ts-lce
Version:
Tool to extract language concepts from a TypeScript codebase and export them to a JSON file.
94 lines (93 loc) • 7.07 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.FunctionParameterProcessor = exports.FunctionDeclarationProcessor = void 0;
const utils_1 = require("@typescript-eslint/utils");
const concept_1 = require("../concept");
const decorator_concept_1 = require("../concepts/decorator.concept");
const function_declaration_concept_1 = require("../concepts/function-declaration.concept");
const method_declaration_concept_1 = require("../concepts/method-declaration.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 function_traverser_1 = require("../traversers/function.traverser");
const dependency_resolution_processor_1 = require("./dependency-resolution.processor");
const type_utils_1 = require("./type.utils");
const code_coordinate_utils_1 = require("./code-coordinate.utils");
const context_keys_1 = require("../context.keys");
/**
* Extracts concepts for globally declared functions.
*
* Note: Nested functions are not processed.
*/
class FunctionDeclarationProcessor extends processor_1.Processor {
executionCondition = new execution_condition_1.ExecutionCondition([utils_1.AST_NODE_TYPES.FunctionDeclaration, utils_1.AST_NODE_TYPES.TSDeclareFunction, utils_1.AST_NODE_TYPES.ArrowFunctionExpression], ({ node }) => {
return (!!node.parent &&
(node.parent.type === utils_1.AST_NODE_TYPES.ExportNamedDeclaration ||
node.parent.type === utils_1.AST_NODE_TYPES.ExportDefaultDeclaration ||
node.parent.type === utils_1.AST_NODE_TYPES.Program));
});
preChildrenProcessing({ node, localContexts, globalContext, ...unusedProcessingContext }) {
if (node.type === utils_1.AST_NODE_TYPES.FunctionDeclaration ||
node.type === utils_1.AST_NODE_TYPES.TSDeclareFunction ||
node.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression) {
const fqnIdentifier = dependency_resolution_processor_1.DependencyResolutionProcessor.isDefaultDeclaration(localContexts, node, node.id?.name) ? "default" : node.id?.name;
if (fqnIdentifier) {
dependency_resolution_processor_1.DependencyResolutionProcessor.addScopeContext(localContexts, context_1.FQN.id(fqnIdentifier));
dependency_resolution_processor_1.DependencyResolutionProcessor.createDependencyIndex(localContexts);
}
const functionType = (0, type_utils_1.parseFunctionType)({ localContexts, node, globalContext, ...unusedProcessingContext }, node);
if (functionType) {
localContexts.currentContexts.set(context_keys_1.CoreContextKeys.FUNCTION_TYPE, functionType);
if (fqnIdentifier) {
const fqn = dependency_resolution_processor_1.DependencyResolutionProcessor.constructScopeFQN(localContexts);
let id = dependency_resolution_processor_1.DependencyResolutionProcessor.constructDeclarationIdentifier(localContexts, node, node.id?.name);
dependency_resolution_processor_1.DependencyResolutionProcessor.registerDeclaration(localContexts, id, fqn, true);
}
}
}
}
postChildrenProcessing({ node, localContexts, globalContext }, childConcepts) {
if (node.type === utils_1.AST_NODE_TYPES.FunctionDeclaration ||
node.type === utils_1.AST_NODE_TYPES.TSDeclareFunction ||
node.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression) {
// TODO: handle overloads
const functionType = localContexts.currentContexts.get(context_keys_1.CoreContextKeys.FUNCTION_TYPE);
if (functionType) {
const functionName = dependency_resolution_processor_1.DependencyResolutionProcessor.constructDeclarationIdentifier(localContexts, node, node.id?.name);
const fqn = dependency_resolution_processor_1.DependencyResolutionProcessor.constructScopeFQN(localContexts);
const typeParameters = functionType.typeParameters;
const returnType = functionType.returnType;
return (0, concept_1.mergeConceptMaps)((0, concept_1.singleEntryConceptMap)(function_declaration_concept_1.LCEFunctionDeclaration.conceptId, new function_declaration_concept_1.LCEFunctionDeclaration(functionName, fqn, (0, processor_utils_1.getAndDeleteChildConcepts)(function_traverser_1.FunctionTraverser.PARAMETERS_PROP, method_declaration_concept_1.LCEParameterDeclaration.conceptId, childConcepts), returnType, functionType.async, typeParameters, code_coordinate_utils_1.CodeCoordinateUtils.getCodeCoordinates(globalContext, node, true))), dependency_resolution_processor_1.DependencyResolutionProcessor.getRegisteredDependencies(localContexts));
}
}
return new Map();
}
}
exports.FunctionDeclarationProcessor = FunctionDeclarationProcessor;
/**
* Extracts concepts for functions parameters of functions that are processed by the `FunctionDeclarationProcessor`
*/
class FunctionParameterProcessor extends processor_1.Processor {
executionCondition = new execution_condition_1.ExecutionCondition([utils_1.AST_NODE_TYPES.Identifier, utils_1.AST_NODE_TYPES.ObjectPattern], // TODO: add other parameter patterns
({ localContexts }) => !!localContexts.parentContexts && localContexts.parentContexts.has(context_keys_1.CoreContextKeys.FUNCTION_TYPE));
postChildrenProcessing({ node, localContexts, globalContext }, childConcepts) {
if (localContexts.parentContexts) {
const functionType = localContexts.parentContexts.get(context_keys_1.CoreContextKeys.FUNCTION_TYPE);
if (functionType) {
const paramIndex = (0, processor_utils_1.getParentPropIndex)(localContexts);
if (paramIndex !== undefined) {
const funcTypeParam = functionType.parameters[paramIndex];
// TODO: handle function overloads: funcTypeParam must always be defined!
if (funcTypeParam) {
const paramName = node.type === utils_1.AST_NODE_TYPES.Identifier ? funcTypeParam.name : "";
return (0, concept_1.singleEntryConceptMap)(method_declaration_concept_1.LCEParameterDeclaration.conceptId, new method_declaration_concept_1.LCEParameterDeclaration(funcTypeParam.index, paramName, funcTypeParam.type, "optional" in node && !!node.optional, (0, processor_utils_1.getAndDeleteChildConcepts)(expression_traverser_1.IdentifierTraverser.DECORATORS_PROP, decorator_concept_1.LCEDecorator.conceptId, childConcepts), code_coordinate_utils_1.CodeCoordinateUtils.getCodeCoordinates(globalContext, node)));
}
}
}
}
return new Map();
}
}
exports.FunctionParameterProcessor = FunctionParameterProcessor;