@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
JavaScript
"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;