UNPKG

@jqassistant/ts-lce

Version:

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

146 lines (145 loc) 9.44 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.MemberExpressionDependencyProcessor = exports.IdentifierDependencyProcessor = exports.DeclarationScopeProcessor = exports.ScopeProcessor = void 0; const utils_1 = require("@typescript-eslint/utils"); 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 expression_traverser_1 = require("../traversers/expression.traverser"); const function_traverser_1 = require("../traversers/function.traverser"); const method_traverser_1 = require("../traversers/method.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 type_alias_declaration_traverser_1 = require("../traversers/type-alias-declaration.traverser"); const context_keys_1 = require("../context.keys"); /** * Registers unnamed `FQNScope` local contexts for all nodes that create a new anonymous scope. */ class ScopeProcessor extends processor_1.Processor { executionCondition = new execution_condition_1.ExecutionCondition([utils_1.AST_NODE_TYPES.BlockStatement, utils_1.AST_NODE_TYPES.ForStatement, utils_1.AST_NODE_TYPES.ForInStatement, utils_1.AST_NODE_TYPES.ForOfStatement], () => true); preChildrenProcessing({ localContexts }) { dependency_resolution_processor_1.DependencyResolutionProcessor.addScopeContext(localContexts); } } exports.ScopeProcessor = ScopeProcessor; /** * Registers named `FQNScope` local contexts for all declaration nodes. */ class DeclarationScopeProcessor extends processor_1.Processor { executionCondition = new execution_condition_1.ExecutionCondition([ utils_1.AST_NODE_TYPES.ClassDeclaration, utils_1.AST_NODE_TYPES.FunctionDeclaration, utils_1.AST_NODE_TYPES.TSDeclareFunction, utils_1.AST_NODE_TYPES.TSInterfaceDeclaration, utils_1.AST_NODE_TYPES.TSTypeAliasDeclaration, utils_1.AST_NODE_TYPES.TSEnumDeclaration, ], () => true); preChildrenProcessing({ localContexts, node }) { if ((node.type === utils_1.AST_NODE_TYPES.ClassDeclaration || node.type === utils_1.AST_NODE_TYPES.FunctionDeclaration || node.type === utils_1.AST_NODE_TYPES.TSDeclareFunction || node.type === utils_1.AST_NODE_TYPES.TSInterfaceDeclaration || node.type === utils_1.AST_NODE_TYPES.TSTypeAliasDeclaration || node.type === utils_1.AST_NODE_TYPES.TSEnumDeclaration) && node.id) { dependency_resolution_processor_1.DependencyResolutionProcessor.addScopeContext(localContexts, context_1.FQN.id(node.id.name)); } else { dependency_resolution_processor_1.DependencyResolutionProcessor.addScopeContext(localContexts); } } } exports.DeclarationScopeProcessor = DeclarationScopeProcessor; class IdentifierDependencyProcessor extends processor_1.Processor { /** * This execution conditions filters out all identifier nodes that are already registered by other processors. */ executionCondition = new execution_condition_1.ExecutionCondition([utils_1.AST_NODE_TYPES.Identifier], ({ node, localContexts }) => !(node.parent?.type === utils_1.AST_NODE_TYPES.ClassDeclaration && (0, processor_utils_1.getParentPropName)(localContexts) === class_traverser_1.ClassTraverser.EXTENDS_PROP) && !((node.parent?.type === utils_1.AST_NODE_TYPES.MethodDefinition || node.parent?.type === utils_1.AST_NODE_TYPES.TSMethodSignature) && ((0, processor_utils_1.getParentPropName)(localContexts) === method_traverser_1.MethodTraverser.KEY_PROP || (0, processor_utils_1.getParentPropName)(localContexts) === method_traverser_1.MethodTraverser.PARAMETERS_PROP)) && !((node.parent?.type === utils_1.AST_NODE_TYPES.PropertyDefinition || node.parent?.type === utils_1.AST_NODE_TYPES.TSPropertySignature) && (0, processor_utils_1.getParentPropName)(localContexts) === property_traverser_1.PropertyTraverser.KEY_PROP) && !((node.parent?.type === utils_1.AST_NODE_TYPES.FunctionDeclaration || node.parent?.type === utils_1.AST_NODE_TYPES.TSDeclareFunction || node.parent?.type === utils_1.AST_NODE_TYPES.FunctionExpression) && (0, processor_utils_1.getParentPropName)(localContexts) === function_traverser_1.FunctionTraverser.PARAMETERS_PROP) && !(node.parent?.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression && (0, processor_utils_1.getParentPropName)(localContexts) === expression_traverser_1.ArrowFunctionExpressionTraverser.PARAMETERS_PROP) && !(node.parent?.type === utils_1.AST_NODE_TYPES.TaggedTemplateExpression && (0, processor_utils_1.getParentPropName)(localContexts) === expression_traverser_1.TaggedTemplateExpressionTraverser.TAG_PROP) && !(node.parent?.type === utils_1.AST_NODE_TYPES.MemberExpression && (0, processor_utils_1.getParentPropName)(localContexts) === expression_traverser_1.MemberExpressionTraverser.PROPERTY_PROP) && node.parent?.type !== utils_1.AST_NODE_TYPES.ArrayPattern && node.parent?.type !== utils_1.AST_NODE_TYPES.ObjectPattern && node.parent?.type !== utils_1.AST_NODE_TYPES.ImportExpression && node.parent?.type !== utils_1.AST_NODE_TYPES.TSInterfaceHeritage && !(node.parent?.type === utils_1.AST_NODE_TYPES.TSTypeReference && this.isDirectAncestorTypeAnnotation(node, localContexts))); /** * This method is used to filter out all type identifiers that are part of type annotations or type parameters, as they are already registered via the native type resolution */ isDirectAncestorTypeAnnotation(node, localContexts) { let ancestor = node.parent; let localContextIndex = localContexts.contexts.length - 2; while (ancestor?.parent) { const parentPropName = localContexts.contexts[localContextIndex].get(context_keys_1.CoreContextKeys.TRAVERSER_CONTEXT) .parentPropName; if (ancestor.parent.type === utils_1.AST_NODE_TYPES.TSTypeAnnotation || (ancestor.parent.type === utils_1.AST_NODE_TYPES.TSTypeAliasDeclaration && parentPropName === type_alias_declaration_traverser_1.TypeAliasDeclarationTraverser.TYPE_ANNOTATION_PROP) || (ancestor.parent.type === utils_1.AST_NODE_TYPES.TSTypeAliasDeclaration && parentPropName === type_alias_declaration_traverser_1.TypeAliasDeclarationTraverser.TYPE_PARAMETERS_PROP) || ((ancestor.parent.type === utils_1.AST_NODE_TYPES.FunctionExpression || ancestor.parent.type === utils_1.AST_NODE_TYPES.FunctionDeclaration || ancestor.parent.type === utils_1.AST_NODE_TYPES.TSDeclareFunction || ancestor.parent.type === utils_1.AST_NODE_TYPES.TSEmptyBodyFunctionExpression) && parentPropName === function_traverser_1.FunctionTraverser.TYPE_PARAMETERS_PROP)) { return true; } ancestor = ancestor.parent; localContextIndex--; if (localContextIndex < 0) { break; } } return false; } postChildrenProcessing({ node, localContexts }) { if (node.type === utils_1.AST_NODE_TYPES.Identifier) { dependency_resolution_processor_1.DependencyResolutionProcessor.registerDependency(localContexts, node.name); } return new Map(); } } exports.IdentifierDependencyProcessor = IdentifierDependencyProcessor; /** * Processes member expressions and adds appropriate dependencies. * Only processes identifier and direct literal property accesses. * Adds dependencies for all type member accesses. */ class MemberExpressionDependencyProcessor extends processor_1.Processor { executionCondition = new execution_condition_1.ExecutionCondition([utils_1.AST_NODE_TYPES.MemberExpression], () => true); postChildrenProcessing({ node, localContexts, ...unusedProcessingContext }) { if (node.type === utils_1.AST_NODE_TYPES.MemberExpression && (node.property.type === utils_1.AST_NODE_TYPES.Identifier || node.property.type === utils_1.AST_NODE_TYPES.Literal)) { const objectType = (0, type_utils_1.parseESNodeType)({ node, localContexts, ...unusedProcessingContext }, node.object, undefined, true); if (objectType instanceof type_concept_1.LCETypeDeclared) { const globalFqn = objectType.fqn.globalFqn + "." + this.getNamespace(node.property); dependency_resolution_processor_1.DependencyResolutionProcessor.registerDependency(localContexts, globalFqn, false); } } return new Map(); } getNamespace(node) { if (node.type === utils_1.AST_NODE_TYPES.Identifier) { return node.name; } else { return node.raw; } } } exports.MemberExpressionDependencyProcessor = MemberExpressionDependencyProcessor;