UNPKG

@jqassistant/ts-lce

Version:

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

212 lines (211 loc) 7.03 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.JSXDependencyProcessor = exports.JSXDependencyContextProcessor = void 0; const utils_1 = require("@typescript-eslint/utils"); const context_1 = require("../../core/context"); const execution_condition_1 = require("../../core/execution-condition"); const processor_1 = require("../../core/processor"); const react_jsx_dependency_1 = require("../concepts/react-jsx-dependency"); const dependency_resolution_processor_1 = require("../../core/processors/dependency-resolution.processor"); const class_declaration_concept_1 = require("../../core/concepts/class-declaration.concept"); const variable_declaration_concept_1 = require("../../core/concepts/variable-declaration.concept"); const function_declaration_concept_1 = require("../../core/concepts/function-declaration.concept"); const variable_declaration_processor_1 = require("../../core/processors/variable-declaration.processor"); const context_keys_1 = require("../context.keys"); class JSXDependencyContextProcessor extends processor_1.Processor { static JSX_DEPENDENCY_METADATA; executionCondition = new execution_condition_1.ExecutionCondition([ utils_1.AST_NODE_TYPES.VariableDeclarator, utils_1.AST_NODE_TYPES.FunctionDeclaration, utils_1.AST_NODE_TYPES.ArrowFunctionExpression, utils_1.AST_NODE_TYPES.ClassDeclaration, ], ({ localContexts, node }) => !!localContexts.parentContexts?.get(variable_declaration_processor_1.VariableDeclarationProcessor.VARIABLE_DECLARATION_KIND_CONTEXT) || (!!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(processingContext) { processingContext.localContexts.currentContexts.set(context_keys_1.ReactContextKeys.JSX_DEPENDENCIES, new Array()); } postChildrenProcessing({ localContexts, metadataAssignments }) { const jsxContext = localContexts.getNextContext(context_keys_1.ReactContextKeys.JSX_DEPENDENCIES)[0]; const aggregatedDependencies = new Map(); for (const dep of jsxContext) { if (aggregatedDependencies.has(dep.fqn.globalFqn)) { aggregatedDependencies.get(dep.fqn.globalFqn).cardinality++; } else { aggregatedDependencies.set(dep.fqn.globalFqn, dep); } } metadataAssignments.push(new context_1.MetadataAssignmentRule((c) => { return c instanceof class_declaration_concept_1.LCEClassDeclaration || c instanceof variable_declaration_concept_1.LCEVariableDeclaration || c instanceof function_declaration_concept_1.LCEFunctionDeclaration; }, new Map([[JSXDependencyContextProcessor.JSX_DEPENDENCY_METADATA, [...aggregatedDependencies.values()]]]))); return new Map(); } } exports.JSXDependencyContextProcessor = JSXDependencyContextProcessor; class JSXDependencyProcessor extends processor_1.Processor { executionCondition = new execution_condition_1.ExecutionCondition([utils_1.AST_NODE_TYPES.JSXOpeningElement], () => true); postChildrenProcessing({ node, localContexts, globalContext }) { if (node.type === utils_1.AST_NODE_TYPES.JSXOpeningElement) { let name = ""; // try to determine name of the tag, abort processing, if not possible if (node.name.type === utils_1.AST_NODE_TYPES.JSXIdentifier) { name = node.name.name; } else if (node.name.type === utils_1.AST_NODE_TYPES.JSXMemberExpression) { let depth = 0; name = node.name.property.name; let currentExpression = node.name.object; while (currentExpression.type === utils_1.AST_NODE_TYPES.JSXMemberExpression) { if (depth > 20) { console.log("ERROR: Could not resolve JSX member expression:"); console.log(name); return new Map(); } name = currentExpression.property.name + "." + name; currentExpression = currentExpression.object; depth++; } if (currentExpression.type === utils_1.AST_NODE_TYPES.JSXIdentifier) { name = currentExpression.name + "." + name; } else { name = currentExpression.namespace.name + "." + name; } } else { return new Map(); } const dep = new react_jsx_dependency_1.LCEJSXDependency(new context_1.FQN(name), name, 1); if (!STANDARD_HTML_ELEMENTS.includes(name)) { // Custom Element: try to resolve reference and register dependency dependency_resolution_processor_1.DependencyResolutionProcessor.scheduleFqnResolution(localContexts, name, dep); dependency_resolution_processor_1.DependencyResolutionProcessor.registerDependency(localContexts, name); } const jsxDependencyContext = localContexts.getNextContext(context_keys_1.ReactContextKeys.JSX_DEPENDENCIES); if (jsxDependencyContext) { jsxDependencyContext[0].push(dep); } } return new Map(); } } exports.JSXDependencyProcessor = JSXDependencyProcessor; const STANDARD_HTML_ELEMENTS = [ "a", "abbr", "address", "area", "article", "aside", "audio", "b", "base", "bdi", "bdo", "blockquote", "body", "br", "button", "canvas", "caption", "cite", "code", "col", "colgroup", "data", "datalist", "dd", "del", "details", "dfn", "dialog", "div", "dl", "dt", "em", "embed", "fieldset", "figcaption", "figure", "footer", "form", "h1", "h2", "h3", "h4", "h5", "h6", "head", "header", "hgroup", "hr", "html", "i", "iframe", "img", "input", "ins", "kbd", "label", "legend", "li", "link", "main", "map", "mark", "math", "menu", "meta", "meter", "nav", "noscript", "object", "ol", "optgroup", "option", "output", "p", "picture", "pre", "progress", "q", "rp", "rt", "ruby", "s", "samp", "script", "search", "section", "select", "slot", "small", "source", "span", "strong", "style", "sub", "summary", "sup", "svg", "table", "tbody", "td", "template", "textarea", "tfoot", "th", "thead", "time", "title", "tr", "track", "u", "ul", "var", "video", "wbr", ];