UNPKG

@jqassistant/ts-lce

Version:

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

116 lines (115 loc) 3.91 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.MetadataAssignmentRule = exports.LocalContexts = exports.GlobalContext = exports.FQN = void 0; /** * Represents a fully qualified name. * An object can be identified by a global fully qualified name which is unique, even across projects, but may be hard-to-read by humans. * The local fully qualified name provides an alternative to this, however, it is only unique within a project (it may be left empty for concepts that use the FQN only for linking nodes). */ class FQN { globalFqn; localFqn; constructor(globalFqn, localFqn = "") { this.globalFqn = globalFqn; this.localFqn = localFqn; } /** * Returns a new FQN instance using the provided identifier for both global and local FQNs. */ static id(identifier) { return new FQN(identifier, identifier); } } exports.FQN = FQN; /** * describes basic data structures provided to all Processors on a file level */ class GlobalContext { projectInfo; sourceFilePathAbsolute; sourceFilePathRelative; ast; services; typeChecker; constructor(projectInfo, sourceFilePathAbsolute, sourceFilePathRelative, ast, services, typeChecker) { this.projectInfo = projectInfo; this.sourceFilePathAbsolute = sourceFilePathAbsolute; this.sourceFilePathRelative = sourceFilePathRelative; this.ast = ast; this.services = services; this.typeChecker = typeChecker; } } exports.GlobalContext = GlobalContext; /** * represents the local contexts currently available at a given node inside the AST */ class LocalContexts { contexts = []; get currentContexts() { if (this.contexts.length === 0) { return new Map(); } else { return this.contexts[this.contexts.length - 1]; } } get parentContexts() { if (this.contexts.length < 2) { return undefined; } else { return this.contexts[this.contexts.length - 2]; } } /** * @param name name of the context type to searched for * @returns closest context with given name to the current contexts, along with its position inside the stack (0 being the current context), or * `undefined` if no context with the given name exists */ getNextContext(name) { for (let i = this.contexts.length - 1; i >= 0; i--) { const context = this.contexts[i].get(name); if (context) return [context, this.contexts.length - i - 1]; } return undefined; } pushContexts() { this.contexts.push(new Map()); } popContexts() { return this.contexts.pop(); } } exports.LocalContexts = LocalContexts; /** * Represents a rule for attaching certain metadata to concepts created during the post-children-processing phase. * The condition has to resolve to true in order for the metadata to be attached to a concept. * * A rule is propagated up the AST until it can be applied to at least one concept after the post-children-processing phase. */ class MetadataAssignmentRule { condition; metadata; constructor(condition, metadata) { this.condition = condition; this.metadata = metadata; } /** * Checks if the condition is met for a given concept and if it is, applies the specified metadata to it. * * @param concept Concept to which the metadata should be attached to * @return whether the metadata was applied */ apply(concept) { const result = this.condition(concept); if (result) { this.metadata.forEach((value, key) => { concept.metadata.set(key, value); }); } return result; } } exports.MetadataAssignmentRule = MetadataAssignmentRule;