mirror of
https://github.com/open-goal/opengoal-vscode.git
synced 2024-10-19 20:47:37 -04:00
decomp: add option to auto-format decompiler results (#336)
This commit is contained in:
parent
40a94c4e2e
commit
bcf8098b8f
18
package.json
18
package.json
|
@ -240,6 +240,14 @@
|
|||
"default": null,
|
||||
"description": "File path to the decompiler executable"
|
||||
},
|
||||
"opengoal.formatterPath": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
],
|
||||
"default": null,
|
||||
"description": "File path to the formatter executable for when invoking directly (not via LSP)"
|
||||
},
|
||||
"opengoal.typeSearcherPath": {
|
||||
"type": [
|
||||
"string",
|
||||
|
@ -262,6 +270,11 @@
|
|||
"type": "string",
|
||||
"default": "ntsc_v1",
|
||||
"description": "Config version to use for decompiling Jak 3 related files"
|
||||
},
|
||||
"opengoal.formatDecompilationOutput": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "Whether or not the results of the decompiler should be auto-formatted"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -427,11 +440,6 @@
|
|||
"command": "opengoal.decomp.openManPage",
|
||||
"group": "z_commands"
|
||||
}
|
||||
],
|
||||
"editor/title": [
|
||||
{
|
||||
"when": "resourceScheme == opengoalBatchRename"
|
||||
}
|
||||
]
|
||||
},
|
||||
"languages": [
|
||||
|
|
|
@ -13,10 +13,14 @@ export function getConfig() {
|
|||
opengoalLspPath: configOptions.get<string>("opengoalLspPath"),
|
||||
opengoalLspLogPath: configOptions.get<string>("opengoalLspLogPath"),
|
||||
opengoalLspLogVerbose: configOptions.get<boolean>("opengoalLspLogVerbose"),
|
||||
formatDecompilationOutput: configOptions.get<boolean>(
|
||||
"formatDecompilationOutput",
|
||||
),
|
||||
|
||||
eeManPagePath: configOptions.get<string>("eeManPagePath"),
|
||||
vuManPagePath: configOptions.get<string>("vuManPagePath"),
|
||||
decompilerPath: configOptions.get<string>("decompilerPath"),
|
||||
formatterPath: configOptions.get<string>("formatterPath"),
|
||||
typeSearcherPath: configOptions.get<string>("typeSearcherPath"),
|
||||
jak1DecompConfigVersion: configOptions.get<string>(
|
||||
"decompilerJak1ConfigVersion",
|
||||
|
@ -83,6 +87,15 @@ export async function updateDecompilerPath(path: string) {
|
|||
);
|
||||
}
|
||||
|
||||
export async function updateFormatterPath(path: string) {
|
||||
const userConfig = vscode.workspace.getConfiguration();
|
||||
await userConfig.update(
|
||||
"opengoal.formatterPath",
|
||||
path,
|
||||
vscode.ConfigurationTarget.Global,
|
||||
);
|
||||
}
|
||||
|
||||
export async function updateTypeSearcherPath(path: string) {
|
||||
const userConfig = vscode.workspace.getConfiguration();
|
||||
await userConfig.update(
|
||||
|
|
|
@ -4,7 +4,11 @@ import * as vscode from "vscode";
|
|||
import { determineGameFromPath, GameName } from "../utils/file-utils";
|
||||
import { open_in_pdf } from "./man-page";
|
||||
import * as util from "util";
|
||||
import { getConfig, updateDecompilerPath } from "../config/config";
|
||||
import {
|
||||
getConfig,
|
||||
updateDecompilerPath,
|
||||
updateFormatterPath,
|
||||
} from "../config/config";
|
||||
import * as path from "path";
|
||||
import { getExtensionContext, getProjectRoot } from "../context";
|
||||
import {
|
||||
|
@ -36,6 +40,7 @@ enum DecompStatus {
|
|||
Idle,
|
||||
Running,
|
||||
Errored,
|
||||
Formatting,
|
||||
}
|
||||
|
||||
function updateStatus(status: DecompStatus, metadata?: any) {
|
||||
|
@ -71,6 +76,20 @@ function updateStatus(status: DecompStatus, metadata?: any) {
|
|||
decompStatusItem.tooltip = "Decompiling...";
|
||||
decompStatusItem.command = undefined;
|
||||
break;
|
||||
case DecompStatus.Formatting:
|
||||
if (metadata.objectNames.length > 0) {
|
||||
if (metadata.objectNames.length <= 5) {
|
||||
subText = metadata.objectNames.join(", ");
|
||||
} else {
|
||||
subText = `${metadata.objectNames.slice(0, 5).join(", ")}, and ${
|
||||
metadata.objectNames.length - 5
|
||||
} more`;
|
||||
}
|
||||
}
|
||||
decompStatusItem.text = `$(loading~spin) Formatting - ${subText} - [ ${metadata.decompConfig} ]`;
|
||||
decompStatusItem.tooltip = "Formatting...";
|
||||
decompStatusItem.command = undefined;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -85,6 +104,15 @@ function defaultDecompPath() {
|
|||
}
|
||||
}
|
||||
|
||||
function defaultFormatterPath() {
|
||||
const platform = process.platform;
|
||||
if (platform == "win32") {
|
||||
return "out/build/Release/bin/formatter.exe";
|
||||
} else {
|
||||
return "build/tools/formatter";
|
||||
}
|
||||
}
|
||||
|
||||
function getDecompilerConfig(gameName: GameName): string | undefined {
|
||||
let decompConfigPath = undefined;
|
||||
if (gameName == GameName.Jak1) {
|
||||
|
@ -159,6 +187,39 @@ async function checkDecompilerPath(): Promise<string | undefined> {
|
|||
return decompilerPath;
|
||||
}
|
||||
|
||||
async function checkFormatterPath(): Promise<string | undefined> {
|
||||
let formatterPath = getConfig().formatterPath;
|
||||
|
||||
// Look for the decompiler if the path isn't set or the file is now missing
|
||||
if (formatterPath !== undefined && existsSync(formatterPath)) {
|
||||
return formatterPath;
|
||||
}
|
||||
|
||||
const potentialPath = vscode.Uri.joinPath(
|
||||
getProjectRoot(),
|
||||
defaultFormatterPath(),
|
||||
);
|
||||
if (existsSync(potentialPath.fsPath)) {
|
||||
formatterPath = potentialPath.fsPath;
|
||||
} else {
|
||||
// Ask the user to find it cause we have no idea
|
||||
const path = await vscode.window.showOpenDialog({
|
||||
canSelectMany: false,
|
||||
openLabel: "Select Formatter",
|
||||
title: "Provide the formatter executable's path",
|
||||
});
|
||||
if (path === undefined || path.length == 0) {
|
||||
vscode.window.showErrorMessage(
|
||||
"OpenGOAL - Aborting formatting, you didn't provide a path to the executable",
|
||||
);
|
||||
return undefined;
|
||||
}
|
||||
formatterPath = path[0].fsPath;
|
||||
}
|
||||
updateFormatterPath(formatterPath);
|
||||
return formatterPath;
|
||||
}
|
||||
|
||||
async function decompFiles(
|
||||
gameName: GameName,
|
||||
fileNames: string[],
|
||||
|
@ -216,6 +277,49 @@ async function decompFiles(
|
|||
`DECOMP ERROR:\nSTDOUT:\n${error.stdout}\nSTDERR:\n${error.stderr}`,
|
||||
);
|
||||
}
|
||||
|
||||
// Format results
|
||||
if (getConfig().formatDecompilationOutput) {
|
||||
const formatterPath = await checkFormatterPath();
|
||||
if (!formatterPath) {
|
||||
return;
|
||||
}
|
||||
|
||||
updateStatus(DecompStatus.Formatting, {
|
||||
objectNames: fileNames,
|
||||
decompConfig: path.parse(decompConfig).name,
|
||||
});
|
||||
|
||||
for (const name of fileNames) {
|
||||
const filePath = path.join(
|
||||
getProjectRoot()?.fsPath,
|
||||
"decompiler_out",
|
||||
gameName,
|
||||
`${name}_disasm.gc`,
|
||||
);
|
||||
|
||||
const formatterArgs = ["--write", "--file", filePath];
|
||||
try {
|
||||
const { stdout, stderr } = await execFileAsync(
|
||||
formatterPath,
|
||||
formatterArgs,
|
||||
{
|
||||
encoding: "utf8",
|
||||
cwd: getProjectRoot()?.fsPath,
|
||||
timeout: 20000,
|
||||
},
|
||||
);
|
||||
channel.append(stdout.toString());
|
||||
channel.append(stderr.toString());
|
||||
} catch (error: any) {
|
||||
updateStatus(DecompStatus.Errored);
|
||||
channel.append(
|
||||
`DECOMP ERROR:\nSTDOUT:\n${error.stdout}\nSTDERR:\n${error.stderr}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
updateStatus(DecompStatus.Idle);
|
||||
}
|
||||
}
|
||||
|
||||
async function getValidObjectNames(gameName: string) {
|
||||
|
|
|
@ -45,19 +45,21 @@ export class IRCompletionItemProvider implements vscode.CompletionItemProvider {
|
|||
// ! - mutated (if it's involved in a set)
|
||||
// ? - optional (can't easily determine this and is frankly rare)
|
||||
let paramFound = false;
|
||||
let paramPrinted = false;
|
||||
for (let i = 1; i < funcBody.length; i++) {
|
||||
const line = funcBody[i];
|
||||
if (line.includes(`(set! (-> ${arg.name}`)) {
|
||||
docstring += ` @param! ${arg.name} something\n`;
|
||||
paramFound = true;
|
||||
paramPrinted = true;
|
||||
break;
|
||||
} else if (line.includes(arg.name)) {
|
||||
paramFound = true;
|
||||
}
|
||||
}
|
||||
if (paramFound) {
|
||||
if (paramFound && !paramPrinted) {
|
||||
docstring += ` @param ${arg.name} something\n`;
|
||||
} else {
|
||||
} else if (!paramPrinted) {
|
||||
docstring += ` @param_ ${arg.name} something\n`;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue