mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2026-04-26 11:10:58 +02:00
CODEBASE: Expand lint rules, and Aliases are stored as maps (#501)
This commit is contained in:
@@ -36,47 +36,51 @@ const specialReferenceWHILE = "__SPECIAL_referenceWhile";
|
||||
// The global scope of a script is registered under this key during parsing.
|
||||
const memCheckGlobalKey = ".__GLOBAL__";
|
||||
|
||||
/** Function for getting a function's ram cost, either from the ramcost function (singularity) or the static cost */
|
||||
function getNumericCost(cost: number | (() => number)): number {
|
||||
return typeof cost === "function" ? cost() : cost;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses code into an AST and walks through it recursively to calculate
|
||||
* RAM usage. Also accounts for imported modules.
|
||||
* @param otherScripts - All other scripts on the server. Used to account for imported scripts
|
||||
* @param code - The code being parsed */
|
||||
function parseOnlyRamCalculate(otherScripts: Map<ScriptFilePath, Script>, code: string, ns1?: boolean): RamCalculation {
|
||||
try {
|
||||
/**
|
||||
* Maps dependent identifiers to their dependencies.
|
||||
*
|
||||
* The initial identifier is __SPECIAL_INITIAL_MODULE__.__GLOBAL__.
|
||||
* It depends on all the functions declared in the module, all the global scopes
|
||||
* of its imports, and any identifiers referenced in this global scope. Each
|
||||
* function depends on all the identifiers referenced internally.
|
||||
* We walk the dependency graph to calculate RAM usage, given that some identifiers
|
||||
* reference Netscript functions which have a RAM cost.
|
||||
*/
|
||||
let dependencyMap: { [key: string]: string[] } = {};
|
||||
/**
|
||||
* Maps dependent identifiers to their dependencies.
|
||||
*
|
||||
* The initial identifier is __SPECIAL_INITIAL_MODULE__.__GLOBAL__.
|
||||
* It depends on all the functions declared in the module, all the global scopes
|
||||
* of its imports, and any identifiers referenced in this global scope. Each
|
||||
* function depends on all the identifiers referenced internally.
|
||||
* We walk the dependency graph to calculate RAM usage, given that some identifiers
|
||||
* reference Netscript functions which have a RAM cost.
|
||||
*/
|
||||
let dependencyMap: Record<string, string[]> = {};
|
||||
|
||||
// Scripts we've parsed.
|
||||
const completedParses = new Set();
|
||||
// Scripts we've parsed.
|
||||
const completedParses = new Set();
|
||||
|
||||
// Scripts we've discovered that need to be parsed.
|
||||
const parseQueue: string[] = [];
|
||||
// Scripts we've discovered that need to be parsed.
|
||||
const parseQueue: string[] = [];
|
||||
// Parses a chunk of code with a given module name, and updates parseQueue and dependencyMap.
|
||||
function parseCode(code: string, moduleName: string): void {
|
||||
const result = parseOnlyCalculateDeps(code, moduleName);
|
||||
completedParses.add(moduleName);
|
||||
|
||||
// Parses a chunk of code with a given module name, and updates parseQueue and dependencyMap.
|
||||
function parseCode(code: string, moduleName: string): void {
|
||||
const result = parseOnlyCalculateDeps(code, moduleName);
|
||||
completedParses.add(moduleName);
|
||||
|
||||
// Add any additional modules to the parse queue;
|
||||
for (let i = 0; i < result.additionalModules.length; ++i) {
|
||||
if (!completedParses.has(result.additionalModules[i])) {
|
||||
parseQueue.push(result.additionalModules[i]);
|
||||
}
|
||||
// Add any additional modules to the parse queue;
|
||||
for (let i = 0; i < result.additionalModules.length; ++i) {
|
||||
if (!completedParses.has(result.additionalModules[i])) {
|
||||
parseQueue.push(result.additionalModules[i]);
|
||||
}
|
||||
|
||||
// Splice all the references in
|
||||
dependencyMap = Object.assign(dependencyMap, result.dependencyMap);
|
||||
}
|
||||
|
||||
// Splice all the references in
|
||||
dependencyMap = Object.assign(dependencyMap, result.dependencyMap);
|
||||
}
|
||||
|
||||
try {
|
||||
// Parse the initial module, which is the "main" script that is being run
|
||||
const initialModule = "__SPECIAL_INITIAL_MODULE__";
|
||||
parseCode(code, initialModule);
|
||||
@@ -141,16 +145,6 @@ function parseOnlyRamCalculate(otherScripts: Map<ScriptFilePath, Script>, code:
|
||||
// Check if this identifier is a function in the workerScript environment.
|
||||
// If it is, then we need to get its RAM cost.
|
||||
try {
|
||||
function applyFuncRam(cost: number | (() => number)): number {
|
||||
if (typeof cost === "number") {
|
||||
return cost;
|
||||
} else if (typeof cost === "function") {
|
||||
return cost();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Only count each function once
|
||||
if (loadedFns[ref]) {
|
||||
continue;
|
||||
@@ -176,7 +170,7 @@ function parseOnlyRamCalculate(otherScripts: Map<ScriptFilePath, Script>, code:
|
||||
};
|
||||
|
||||
const details = findFunc("", RamCosts, ref);
|
||||
const fnRam = applyFuncRam(details?.func ?? 0);
|
||||
const fnRam = getNumericCost(details?.func ?? 0);
|
||||
ram += fnRam;
|
||||
detailedCosts.push({ type: "fn", name: details?.refDetail ?? "", cost: fnRam });
|
||||
} catch (error) {
|
||||
@@ -237,9 +231,7 @@ export function checkInfiniteLoop(code: string): number {
|
||||
}
|
||||
|
||||
interface ParseDepsResult {
|
||||
dependencyMap: {
|
||||
[key: string]: Set<string> | undefined;
|
||||
};
|
||||
dependencyMap: Record<string, Set<string> | undefined>;
|
||||
additionalModules: string[];
|
||||
}
|
||||
|
||||
@@ -254,12 +246,12 @@ function parseOnlyCalculateDeps(code: string, currentModule: string): ParseDepsR
|
||||
// Everything from the global scope goes in ".". Everything else goes in ".function", where only
|
||||
// the outermost layer of functions counts.
|
||||
const globalKey = currentModule + memCheckGlobalKey;
|
||||
const dependencyMap: { [key: string]: Set<string> | undefined } = {};
|
||||
const dependencyMap: Record<string, Set<string> | undefined> = {};
|
||||
dependencyMap[globalKey] = new Set<string>();
|
||||
|
||||
// If we reference this internal name, we're really referencing that external name.
|
||||
// Filled when we import names from other modules.
|
||||
const internalToExternal: { [key: string]: string | undefined } = {};
|
||||
const internalToExternal: Record<string, string | undefined> = {};
|
||||
|
||||
const additionalModules: string[] = [];
|
||||
|
||||
|
||||
@@ -62,8 +62,8 @@ export class RunningScript {
|
||||
// hostname of the server on which this script is running
|
||||
server = "";
|
||||
|
||||
// Cached key for ByArgs lookups
|
||||
scriptKey: ScriptKey = "";
|
||||
// Cached key for ByArgs lookups. Will be overwritten by a correct ScriptKey in fromJSON or constructor
|
||||
scriptKey = "" as ScriptKey;
|
||||
|
||||
// Number of threads that this script is running with
|
||||
threads = 1 as PositiveInteger;
|
||||
@@ -72,7 +72,7 @@ export class RunningScript {
|
||||
temporary = false;
|
||||
|
||||
// Script urls for the current running script for translating urls back to file names in errors
|
||||
dependencies: Map<ScriptURL, Script> = new Map();
|
||||
dependencies = new Map<ScriptURL, Script>();
|
||||
|
||||
constructor(script?: Script, ramUsage?: number, args: ScriptArg[] = []) {
|
||||
if (!script) return;
|
||||
@@ -145,7 +145,9 @@ export class RunningScript {
|
||||
|
||||
// Initializes a RunningScript Object from a JSON save state
|
||||
static fromJSON(value: IReviverValue): RunningScript {
|
||||
return Generic_fromJSON(RunningScript, value.data, includedProperties);
|
||||
const runningScript = Generic_fromJSON(RunningScript, value.data, includedProperties);
|
||||
if (!runningScript.scriptKey) runningScript.scriptKey = scriptKey(runningScript.filename, runningScript.args);
|
||||
return runningScript;
|
||||
}
|
||||
}
|
||||
const includedProperties = getKeyList(RunningScript, { removedKeys: ["logs", "dependencies", "logUpd", "pid"] });
|
||||
|
||||
@@ -21,13 +21,13 @@ export class Script implements ContentFile {
|
||||
// Runtime data that only exists when the script has been initiated. Cleared when script or a dependency script is updated.
|
||||
mod: LoadedModule | null = null;
|
||||
/** Scripts that directly import this one. Stored so we can invalidate these dependent scripts when this one is invalidated. */
|
||||
dependents: Set<Script> = new Set();
|
||||
dependents = new Set<Script>();
|
||||
/**
|
||||
* Scripts that we directly or indirectly import, including ourselves.
|
||||
* Stored only so RunningScript can use it, to translate urls in error messages.
|
||||
* Because RunningScript uses the reference directly (to reduce object copies), it must be immutable.
|
||||
*/
|
||||
dependencies: Map<ScriptURL, Script> = new Map();
|
||||
dependencies = new Map<ScriptURL, Script>();
|
||||
|
||||
get content() {
|
||||
return this.code;
|
||||
|
||||
@@ -29,7 +29,7 @@ export function scriptCalculateOfflineProduction(runningScript: RunningScript):
|
||||
|
||||
// Grow
|
||||
for (const hostname of Object.keys(runningScript.dataMap)) {
|
||||
if (runningScript.dataMap.hasOwnProperty(hostname)) {
|
||||
if (Object.hasOwn(runningScript.dataMap, hostname)) {
|
||||
if (runningScript.dataMap[hostname][2] == 0 || runningScript.dataMap[hostname][2] == null) {
|
||||
continue;
|
||||
}
|
||||
@@ -60,7 +60,7 @@ export function scriptCalculateOfflineProduction(runningScript: RunningScript):
|
||||
|
||||
// Weaken
|
||||
for (const hostname of Object.keys(runningScript.dataMap)) {
|
||||
if (runningScript.dataMap.hasOwnProperty(hostname)) {
|
||||
if (Object.hasOwn(runningScript.dataMap, hostname)) {
|
||||
if (runningScript.dataMap[hostname][3] == 0 || runningScript.dataMap[hostname][3] == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user