@syntest/analysis-javascript
Version:
SynTest CFG JavaScript is a library for generating control flow graphs for the JavaScript language
203 lines • 8.8 kB
JavaScript
"use strict";
/*
* Copyright 2020-2023 Delft University of Technology and SynTest contributors
*
* This file is part of SynTest Framework - SynTest Javascript.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.RootContext = void 0;
const node_fs_1 = require("node:fs");
const analysis_1 = require("@syntest/analysis");
const logging_1 = require("@syntest/logging");
const ConstantPool_1 = require("./constant/ConstantPool");
const ConstantPoolManager_1 = require("./constant/ConstantPoolManager");
const TypePool_1 = require("./type/resolving/TypePool");
const fileSystem_1 = require("./utils/fileSystem");
class RootContext extends analysis_1.RootContext {
constructor(rootPath, targetFiles, analysisFiles, abstractSyntaxTreeFactory, controlFlowGraphFactory, targetFactory, dependencyFactory, exportFactory, typeExtractor, typeResolver, constantPoolFactory) {
super(rootPath, undefined, abstractSyntaxTreeFactory, controlFlowGraphFactory, targetFactory, dependencyFactory);
RootContext.LOGGER = (0, logging_1.getLogger)("RootContext");
this._targetFiles = targetFiles;
this._analysisFiles = analysisFiles;
this._exportFactory = exportFactory;
this._typeExtractor = typeExtractor;
this._typeResolver = typeResolver;
this._constantPoolFactory = constantPoolFactory;
}
get rootPath() {
return this._rootPath;
}
getSource(filePath) {
let absoluteTargetPath = this.resolvePath(filePath);
if (!this._sources.has(absoluteTargetPath)) {
if (!(0, node_fs_1.existsSync)(absoluteTargetPath)) {
if ((0, node_fs_1.existsSync)(absoluteTargetPath + ".js")) {
absoluteTargetPath += ".js";
}
else if ((0, node_fs_1.existsSync)(absoluteTargetPath + ".ts")) {
absoluteTargetPath += ".ts";
}
else {
throw new Error("Cannot find source: " + absoluteTargetPath);
}
}
const stats = (0, node_fs_1.lstatSync)(absoluteTargetPath);
if (stats.isDirectory()) {
if ((0, node_fs_1.existsSync)(absoluteTargetPath + "/index.js")) {
absoluteTargetPath += "/index.js";
}
else if ((0, node_fs_1.existsSync)(absoluteTargetPath + "/index.ts")) {
absoluteTargetPath += "/index.ts";
}
else {
throw new Error("Cannot find source: " + absoluteTargetPath);
}
}
this._sources.set(absoluteTargetPath, (0, fileSystem_1.readFile)(absoluteTargetPath));
}
return this._sources.get(absoluteTargetPath);
}
getExports(filePath) {
const absolutePath = this.resolvePath(filePath);
if (!this._exportMap.has(absolutePath)) {
process.emit("exportExtractionStart", this, absolutePath);
this._exportMap.set(absolutePath, this._exportFactory.extract(absolutePath, this.getAbstractSyntaxTree(absolutePath)));
process.emit("exportExtractionComplete", this, absolutePath);
}
return this._exportMap.get(absolutePath);
}
getAllExports() {
if (!this._exportMap) {
this._exportMap = new Map();
for (const filepath of this._analysisFiles) {
this._exportMap.set(filepath, this.getExports(filepath));
}
}
return this._exportMap;
}
getElements(filepath) {
const absolutePath = this.resolvePath(filepath);
if (!this._elementMap.has(absolutePath)) {
process.emit("elementExtractionStart", this, absolutePath);
const elementMap = this._typeExtractor.extractElements(absolutePath, this.getAbstractSyntaxTree(absolutePath));
this._elementMap.set(absolutePath, elementMap);
process.emit("elementExtractionComplete", this, absolutePath);
}
return this._elementMap.get(absolutePath);
}
getAllElements() {
if (!this._elementMap) {
this._elementMap = new Map();
for (const filepath of this._analysisFiles) {
this._elementMap.set(filepath, this.getElements(filepath));
}
}
return this._elementMap;
}
getRelations(filepath) {
const absolutePath = this.resolvePath(filepath);
if (!this._relationMap.has(absolutePath)) {
process.emit("relationExtractionStart", this, absolutePath);
const relationsMap = this._typeExtractor.extractRelations(absolutePath, this.getAbstractSyntaxTree(absolutePath));
this._relationMap.set(absolutePath, relationsMap);
process.emit("relationExtractionComplete", this, absolutePath);
}
return this._relationMap.get(absolutePath);
}
getAllRelations() {
if (!this._relationMap) {
this._relationMap = new Map();
for (const filepath of this._analysisFiles) {
this._relationMap.set(filepath, this.getRelations(filepath));
}
}
return this._relationMap;
}
getObjectTypes(filepath) {
const absolutePath = this.resolvePath(filepath);
if (!this._objectMap.has(absolutePath)) {
process.emit("objectTypeExtractionStart", this, absolutePath);
const objectsMap = this._typeExtractor.extractObjectTypes(absolutePath, this.getAbstractSyntaxTree(absolutePath));
this._objectMap.set(absolutePath, objectsMap);
process.emit("objectTypeExtractionComplete", this, absolutePath);
}
return this._objectMap.get(absolutePath);
}
getAllObjectTypes() {
if (!this._objectMap) {
this._objectMap = new Map();
for (const filepath of this._analysisFiles) {
this._objectMap.set(filepath, this.getObjectTypes(filepath));
}
}
return this._objectMap;
}
resolveTypes() {
// TODO allow sub selections of files (do not consider entire context)
if (!this._elementMap) {
this.getAllElements();
}
if (!this._relationMap) {
this.getAllRelations();
}
if (!this._objectMap) {
this.getAllObjectTypes();
}
if (!this._exportMap) {
this.getAllExports();
}
if (!this._typeModel) {
process.emit("typeResolvingStart", this);
this._typeModel = this._typeResolver.resolveTypes(this._elementMap, this._relationMap);
this._typePool = new TypePool_1.TypePool(this._objectMap, this._exportMap);
process.emit("typeResolvingComplete", this);
}
}
getTypeModel() {
if (!this._typeModel) {
this.resolveTypes();
}
return this._typeModel;
}
getTypePool() {
if (!this._typePool) {
this.resolveTypes();
}
return this._typePool;
}
// TODO cache
_getContextConstantPool() {
const constantPool = new ConstantPool_1.ConstantPool();
for (const filepath of this._analysisFiles) {
const ast = this.getAbstractSyntaxTree(filepath);
this._constantPoolFactory.extract(filepath, ast, constantPool);
}
return constantPool;
}
// TODO cache
getConstantPoolManager(filepath) {
const absolutePath = this.resolvePath(filepath);
RootContext.LOGGER.info("Extracting constants");
const ast = this.getAbstractSyntaxTree(absolutePath);
const targetConstantPool = this._constantPoolFactory.extract(absolutePath, ast);
const contextConstantPool = this._getContextConstantPool();
const dynamicConstantPool = new ConstantPool_1.ConstantPool();
const constantPoolManager = new ConstantPoolManager_1.ConstantPoolManager(targetConstantPool, contextConstantPool, dynamicConstantPool);
RootContext.LOGGER.info("Extracting constants done");
return constantPoolManager;
}
}
exports.RootContext = RootContext;
//# sourceMappingURL=RootContext.js.map