diff --git a/libraries/analysis-javascript/lib/RootContext.ts b/libraries/analysis-javascript/lib/RootContext.ts index 119a2d338..986b1daca 100644 --- a/libraries/analysis-javascript/lib/RootContext.ts +++ b/libraries/analysis-javascript/lib/RootContext.ts @@ -27,7 +27,7 @@ import { DependencyFactory } from "./dependency/DependencyFactory"; import { Export } from "./target/export/Export"; import { TargetFactory } from "./target/TargetFactory"; import { TypeModelFactory } from "./type/resolving/TypeModelFactory"; -import { getAllFiles, readFile } from "./utils/fileSystem"; +import { readFile } from "./utils/fileSystem"; import { ExportFactory } from "./target/export/ExportFactory"; import { TypeExtractor } from "./type/discovery/TypeExtractor"; import { TypeModel } from "./type/resolving/TypeModel"; @@ -51,7 +51,9 @@ export class RootContext extends CoreRootContext { protected _constantPoolFactory: ConstantPoolFactory; - protected _files: string[]; + protected _targetFiles: Set; + protected _analysisFiles: Set; + // filepath -> id -> element protected _elementMap: Map>; // filepath -> id -> relation @@ -67,6 +69,8 @@ export class RootContext extends CoreRootContext { constructor( rootPath: string, + targetFiles: Set, + analysisFiles: Set, abstractSyntaxTreeFactory: AbstractSyntaxTreeFactory, controlFlowGraphFactory: ControlFlowGraphFactory, targetFactory: TargetFactory, @@ -85,6 +89,8 @@ export class RootContext extends CoreRootContext { dependencyFactory ); RootContext.LOGGER = getLogger("RootContext"); + this._targetFiles = targetFiles; + this._analysisFiles = analysisFiles; this._exportFactory = exportFactory; this._typeExtractor = typeExtractor; this._typeResolver = typeResolver; @@ -95,21 +101,6 @@ export class RootContext extends CoreRootContext { return this._rootPath; } - // TODO something with the types - - getFiles() { - if (!this._files) { - this._files = getAllFiles(this.rootPath, ".js").filter( - (x) => - !x.includes("/test/") && - !x.includes(".test.js") && - !x.includes("node_modules") - ); // maybe we should also take those into account - } - - return this._files; - } - override getSource(filePath: string) { let absoluteTargetPath = this.resolvePath(filePath); @@ -172,7 +163,7 @@ export class RootContext extends CoreRootContext { if (!this._exportMap) { this._exportMap = new Map(); - for (const filepath of this.getFiles()) { + for (const filepath of this._analysisFiles) { this._exportMap.set(filepath, this.getExports(filepath)); } } @@ -208,7 +199,7 @@ export class RootContext extends CoreRootContext { if (!this._elementMap) { this._elementMap = new Map(); - for (const filepath of this.getFiles()) { + for (const filepath of this._analysisFiles) { this._elementMap.set(filepath, this.getElements(filepath)); } } @@ -244,7 +235,7 @@ export class RootContext extends CoreRootContext { if (!this._relationMap) { this._relationMap = new Map(); - for (const filepath of this.getFiles()) { + for (const filepath of this._analysisFiles) { this._relationMap.set(filepath, this.getRelations(filepath)); } } @@ -280,7 +271,7 @@ export class RootContext extends CoreRootContext { if (!this._objectMap) { this._objectMap = new Map(); - for (const filepath of this.getFiles()) { + for (const filepath of this._analysisFiles) { this._objectMap.set(filepath, this.getObjectTypes(filepath)); } } @@ -332,7 +323,7 @@ export class RootContext extends CoreRootContext { // TODO cache private _getContextConstantPool(): ConstantPool { const constantPool = new ConstantPool(); - for (const filepath of this.getFiles()) { + for (const filepath of this._analysisFiles) { const ast = this.getAbstractSyntaxTree(filepath); this._constantPoolFactory.extract(filepath, ast, constantPool); } diff --git a/tools/javascript/lib/JavaScriptLauncher.ts b/tools/javascript/lib/JavaScriptLauncher.ts index 107718571..de4be0f1b 100644 --- a/tools/javascript/lib/JavaScriptLauncher.ts +++ b/tools/javascript/lib/JavaScriptLauncher.ts @@ -44,6 +44,7 @@ import { ProcreationPlugin, TerminationTriggerPlugin, PropertyName, + FileSelector, } from "@syntest/base-language"; import { UserInterface, @@ -170,8 +171,35 @@ export class JavaScriptLauncher extends Launcher { (this.arguments_).syntaxForgiving ); + const fileSelector = new FileSelector(); + const targetFiles = fileSelector.loadFilePaths( + this.arguments_.targetInclude, + this.arguments_.targetExclude + ); + + if (this.arguments_.analysisInclude.length === 0) { + JavaScriptLauncher.LOGGER.warn( + "'analysis-include' config parameter is empty so we only use the target files for analysis" + ); + } + + for (const target of targetFiles) { + if (this.arguments_.analysisExclude.includes(target)) { + throw new Error( + `Target files cannot be excluded from analysis. Target file: ${target}` + ); + } + } + + const analysisFiles = fileSelector.loadFilePaths( + [...targetFiles, ...this.arguments_.analysisInclude], + this.arguments_.analysisExclude + ); + this.rootContext = new RootContext( this.arguments_.targetRootDirectory, + targetFiles, + analysisFiles, abstractSyntaxTreeFactory, controlFlowGraphFactory, targetFactory, @@ -184,15 +212,6 @@ export class JavaScriptLauncher extends Launcher { this.userInterface.printHeader("GENERAL INFO"); - // TODO ui info messages - - // this.userInterface.report("property-set", [ - // "Target Settings", - // ( - // ([["Target Root Directory", this.arguments_.targetRootDirectory]]) - // ), - // ]); - const timeInMs = (Date.now() - start) / 1000; this.metricManager.recordProperty( PropertyName.INITIALIZATION_TIME, @@ -209,8 +228,8 @@ export class JavaScriptLauncher extends Launcher { const startTargetSelection = Date.now(); const targetSelector = new TargetSelector(this.rootContext); this.targets = targetSelector.loadTargets( - this.arguments_.include, - this.arguments_.exclude + this.arguments_.targetInclude, + this.arguments_.targetExclude ); let timeInMs = (Date.now() - startTargetSelection) / 1000; this.metricManager.recordProperty( @@ -221,7 +240,7 @@ export class JavaScriptLauncher extends Launcher { if (this.targets.length === 0) { // Shut server down this.userInterface.printError( - `No targets where selected! Try changing the 'include' parameter` + `No targets where selected! Try changing the 'target-include' parameter` ); await this.exit(); // eslint-disable-next-line unicorn/no-process-exit @@ -243,6 +262,19 @@ export class JavaScriptLauncher extends Launcher { this.userInterface.printItemization("TARGETS", itemization); + const selectionSettings: TableObject = { + headers: ["Setting", "Value"], + rows: [ + ["Target Root Directory", this.arguments_.targetRootDirectory], + ["Target Include", `${this.arguments_.targetInclude.join(", ")}`], + ["Target Exclude", `${this.arguments_.targetExclude.join(", ")}`], + ["Analysis Include", `${this.arguments_.analysisInclude.join(", ")}`], + ["Analysis Exclude", `${this.arguments_.analysisExclude.join(", ")}`], + ], + footers: ["", ""], + }; + this.userInterface.printTable("SELECTION SETTINGS", selectionSettings); + const settings: TableObject = { headers: ["Setting", "Value"], rows: [