@jqassistant/ts-lce
Version:
Tool to extract language concepts from a TypeScript codebase and export them to a JSON file.
107 lines (106 loc) • 8.35 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ImplementsDeclarationProcessor = exports.SuperClassDeclarationProcessor = exports.ClassDeclarationProcessor = void 0;
const utils_1 = require("@typescript-eslint/utils");
const concept_1 = require("../concept");
const class_declaration_concept_1 = require("../concepts/class-declaration.concept");
const decorator_concept_1 = require("../concepts/decorator.concept");
const method_declaration_concept_1 = require("../concepts/method-declaration.concept");
const property_declaration_concept_1 = require("../concepts/property-declaration.concept");
const type_concept_1 = require("../concepts/type.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 class_traverser_1 = require("../traversers/class.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 accessor_declaration_concept_1 = require("../concepts/accessor-declaration.concept");
const context_keys_1 = require("../context.keys");
class ClassDeclarationProcessor extends processor_1.Processor {
executionCondition = new execution_condition_1.ExecutionCondition([utils_1.AST_NODE_TYPES.ClassDeclaration], ({ 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 }) {
if (node.type === utils_1.AST_NODE_TYPES.ClassDeclaration) {
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);
}
}
localContexts.currentContexts.set(context_keys_1.CoreContextKeys.PROCESS_CLASS_LIKE_MEMBERS, 2);
}
postChildrenProcessing({ globalContext, localContexts, node, ...unusedProcessingContext }, childConcepts) {
if (node.type === utils_1.AST_NODE_TYPES.ClassDeclaration) {
const className = dependency_resolution_processor_1.DependencyResolutionProcessor.constructDeclarationIdentifier(localContexts, node, node.id?.name);
const fqn = dependency_resolution_processor_1.DependencyResolutionProcessor.constructScopeFQN(localContexts);
dependency_resolution_processor_1.DependencyResolutionProcessor.registerDeclaration(localContexts, className, fqn, true);
// merge accessor properties
const childAccProps = (0, processor_utils_1.getAndDeleteChildConcepts)(class_traverser_1.ClassTraverser.BODY_PROP, accessor_declaration_concept_1.LCEAccessorProperty.conceptId, childConcepts);
const accessorProperties = new Map();
for (const accProp of childAccProps) {
if (accessorProperties.has(accProp.fqn.globalFqn)) {
const existingAccProp = accessorProperties.get(accProp.fqn.globalFqn);
if (!existingAccProp.getter) {
existingAccProp.getter = accProp.getter;
}
if (!existingAccProp.setter) {
existingAccProp.setter = accProp.setter;
}
if (!existingAccProp.autoAccessor) {
existingAccProp.autoAccessor = accProp.autoAccessor;
}
}
else {
accessorProperties.set(accProp.fqn.globalFqn, accProp);
}
}
const classDecl = new class_declaration_concept_1.LCEClassDeclaration(className, fqn, node.abstract ?? false, (0, type_utils_1.parseClassLikeTypeParameters)({ globalContext, localContexts, node, ...unusedProcessingContext }, node), (0, processor_utils_1.getAndDeleteChildConcepts)(class_traverser_1.ClassTraverser.EXTENDS_PROP, type_concept_1.LCETypeDeclared.conceptId, childConcepts)[0], (0, processor_utils_1.getAndDeleteChildConcepts)(class_traverser_1.ClassTraverser.IMPLEMENTS_PROP, type_concept_1.LCETypeDeclared.conceptId, childConcepts), (0, processor_utils_1.getAndDeleteChildConcepts)(class_traverser_1.ClassTraverser.BODY_PROP, method_declaration_concept_1.LCEConstructorDeclaration.conceptId, childConcepts)[0], (0, processor_utils_1.getAndDeleteChildConcepts)(class_traverser_1.ClassTraverser.BODY_PROP, property_declaration_concept_1.LCEPropertyDeclaration.conceptId, childConcepts), (0, processor_utils_1.getAndDeleteChildConcepts)(class_traverser_1.ClassTraverser.BODY_PROP, method_declaration_concept_1.LCEMethodDeclaration.conceptId, childConcepts), [...accessorProperties.values()], (0, processor_utils_1.getAndDeleteChildConcepts)(class_traverser_1.ClassTraverser.DECORATORS_PROP, decorator_concept_1.LCEDecorator.conceptId, childConcepts), code_coordinate_utils_1.CodeCoordinateUtils.getCodeCoordinates(globalContext, node, true));
dependency_resolution_processor_1.DependencyResolutionProcessor.scheduleFqnResolution(localContexts, className, classDecl);
return (0, concept_1.mergeConceptMaps)((0, concept_1.singleEntryConceptMap)(class_declaration_concept_1.LCEClassDeclaration.conceptId, classDecl), dependency_resolution_processor_1.DependencyResolutionProcessor.getRegisteredDependencies(localContexts));
}
return new Map();
}
}
exports.ClassDeclarationProcessor = ClassDeclarationProcessor;
class SuperClassDeclarationProcessor extends processor_1.Processor {
executionCondition = new execution_condition_1.ExecutionCondition([utils_1.AST_NODE_TYPES.Identifier, utils_1.AST_NODE_TYPES.MemberExpression], ({ node, localContexts }) => !!node.parent && node.parent.type === utils_1.AST_NODE_TYPES.ClassDeclaration && (0, processor_utils_1.getParentPropName)(localContexts) === class_traverser_1.ClassTraverser.EXTENDS_PROP);
postChildrenProcessing({ node, ...unusedProcessingContext }) {
if (node.parent?.type === utils_1.AST_NODE_TYPES.ClassDeclaration) {
if (node.type === utils_1.AST_NODE_TYPES.Identifier || node.type === utils_1.AST_NODE_TYPES.MemberExpression) {
const superType = (0, type_utils_1.parseClassLikeBaseType)({
node,
...unusedProcessingContext,
}, node, node.parent.superTypeArguments?.params);
if (superType) {
return (0, concept_1.singleEntryConceptMap)(type_concept_1.LCETypeDeclared.conceptId, superType);
}
}
}
return new Map();
}
}
exports.SuperClassDeclarationProcessor = SuperClassDeclarationProcessor;
class ImplementsDeclarationProcessor extends processor_1.Processor {
executionCondition = new execution_condition_1.ExecutionCondition([utils_1.AST_NODE_TYPES.TSClassImplements], ({ node, localContexts }) => !!node.parent &&
node.parent.type === utils_1.AST_NODE_TYPES.ClassDeclaration &&
(0, processor_utils_1.getParentPropName)(localContexts) === class_traverser_1.ClassTraverser.IMPLEMENTS_PROP);
postChildrenProcessing({ node, ...unusedProcessingContext }) {
if (node.type === utils_1.AST_NODE_TYPES.TSClassImplements) {
const implementsType = (0, type_utils_1.parseClassLikeBaseType)({
node,
...unusedProcessingContext,
}, node, node.typeArguments?.params);
if (implementsType) {
return (0, concept_1.singleEntryConceptMap)(type_concept_1.LCETypeDeclared.conceptId, implementsType);
}
}
return new Map();
}
}
exports.ImplementsDeclarationProcessor = ImplementsDeclarationProcessor;