mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2026-04-22 09:13:07 +02:00
MISC: Show user-friendly error message when there is syntax error in scripts (#1963)
This commit is contained in:
@@ -146,7 +146,7 @@ function parseOnlyRamCalculate(
|
|||||||
const scriptFileType = getFileType(script.filename);
|
const scriptFileType = getFileType(script.filename);
|
||||||
let moduleAST;
|
let moduleAST;
|
||||||
try {
|
try {
|
||||||
moduleAST = parseAST(script.code, scriptFileType);
|
moduleAST = parseAST(script.filename, script.server, script.code, scriptFileType);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return {
|
return {
|
||||||
errorCode: RamCalculationErrorCode.ImportError,
|
errorCode: RamCalculationErrorCode.ImportError,
|
||||||
@@ -552,7 +552,7 @@ export function calculateRamUsage(
|
|||||||
): RamCalculation {
|
): RamCalculation {
|
||||||
try {
|
try {
|
||||||
const fileType = getFileType(scriptName);
|
const fileType = getFileType(scriptName);
|
||||||
const ast = typeof input === "string" ? parseAST(input, fileType) : input;
|
const ast = typeof input === "string" ? parseAST(scriptName, server, input, fileType) : input;
|
||||||
return parseOnlyRamCalculate(ast, scriptName, server, getFileTypeFeature(fileType), otherScripts);
|
return parseOnlyRamCalculate(ast, scriptName, server, getFileTypeFeature(fileType), otherScripts);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -276,7 +276,7 @@ function Root(props: IProps): React.ReactElement {
|
|||||||
}
|
}
|
||||||
let ast;
|
let ast;
|
||||||
try {
|
try {
|
||||||
ast = parseAST(newCode, getFileType(currentScript.path));
|
ast = parseAST(currentScript.path, currentScript.hostname, newCode, getFileType(currentScript.path));
|
||||||
makeModelsForImports(ast, server);
|
makeModelsForImports(ast, server);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
showRAMError({
|
showRAMError({
|
||||||
|
|||||||
@@ -63,32 +63,64 @@ export function getFileTypeFeature(fileType: FileType): FileTypeFeature {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function parseAST(code: string, fileType: FileType): AST {
|
export function parseAST(scriptName: string, hostname: string, code: string, fileType: FileType): AST {
|
||||||
const fileTypeFeature = getFileTypeFeature(fileType);
|
const fileTypeFeature = getFileTypeFeature(fileType);
|
||||||
let ast: AST;
|
let ast: AST;
|
||||||
/**
|
try {
|
||||||
* acorn is much faster than babel-parser, especially when parsing many big JS files, so we use it to parse the AST of
|
/**
|
||||||
* JS code. babel-parser is only useful when we have to parse JSX and TypeScript.
|
* acorn is much faster than babel-parser, especially when parsing many big JS files, so we use it to parse the AST of
|
||||||
*/
|
* JS code. babel-parser is only useful when we have to parse JSX and TypeScript.
|
||||||
if (fileType === FileType.JS) {
|
*/
|
||||||
ast = acorn.parse(code, { sourceType: "module", ecmaVersion: "latest" });
|
if (fileType === FileType.JS) {
|
||||||
} else {
|
ast = acorn.parse(code, { sourceType: "module", ecmaVersion: "latest" });
|
||||||
const plugins = [];
|
} else {
|
||||||
if (fileTypeFeature.isReact) {
|
const plugins = [];
|
||||||
plugins.push("jsx");
|
if (fileTypeFeature.isReact) {
|
||||||
|
plugins.push("jsx");
|
||||||
|
}
|
||||||
|
if (fileTypeFeature.isTypeScript) {
|
||||||
|
plugins.push("typescript");
|
||||||
|
}
|
||||||
|
ast = babel.packages.parser.parse(code, {
|
||||||
|
sourceType: "module",
|
||||||
|
ecmaVersion: "latest",
|
||||||
|
/**
|
||||||
|
* The usage of the "estree" plugin is mandatory. We use acorn-walk to walk the AST. acorn-walk only supports the
|
||||||
|
* ESTree AST format, but babel-parser uses the Babel AST format by default.
|
||||||
|
*/
|
||||||
|
plugins: [["estree", { classFeatures: true }], ...plugins],
|
||||||
|
}).program;
|
||||||
}
|
}
|
||||||
if (fileTypeFeature.isTypeScript) {
|
} catch (error) {
|
||||||
plugins.push("typescript");
|
/**
|
||||||
}
|
* The message of syntax errors may be cryptic for players without programming experience. For example, some players
|
||||||
ast = babel.packages.parser.parse(code, {
|
* asked us what "Unexpected token" means. Therefore, we will catch the error here and provide a user-friendly error
|
||||||
sourceType: "module",
|
* message.
|
||||||
ecmaVersion: "latest",
|
*/
|
||||||
|
if (error instanceof SyntaxError) {
|
||||||
|
let errorLocation = "unknown";
|
||||||
/**
|
/**
|
||||||
* The usage of the "estree" plugin is mandatory. We use acorn-walk to walk the AST. acorn-walk only supports the
|
* Some browsers (e.g., Firefox, Chrome) add the "loc" property to the error object. This property provides the
|
||||||
* ESTree AST format, but babel-parser uses the Babel AST format by default.
|
* line and column numbers of the error.
|
||||||
*/
|
*/
|
||||||
plugins: [["estree", { classFeatures: true }], ...plugins],
|
if (
|
||||||
}).program;
|
"loc" in error &&
|
||||||
|
error.loc &&
|
||||||
|
typeof error.loc === "object" &&
|
||||||
|
"line" in error.loc &&
|
||||||
|
"column" in error.loc
|
||||||
|
) {
|
||||||
|
errorLocation = `Line ${error.loc.line}, Column: ${error.loc.column}`;
|
||||||
|
}
|
||||||
|
throw new Error(
|
||||||
|
`Syntax error in ${scriptName}, server: ${hostname}. Error location: ${errorLocation}. Error message: ${error.message}.`,
|
||||||
|
{
|
||||||
|
cause: error,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return ast;
|
return ast;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user