From bb075226f0a279b5105a9d5b8193a0d98f1506cc Mon Sep 17 00:00:00 2001 From: jianmosier <19506927+jianmosier@users.noreply.github.com> Date: Wed, 20 May 2026 20:29:28 +0800 Subject: [PATCH] feat: add active file mini trace command --- package.json | 5 +++++ scripts/generate-contributes.ts | 3 +++ src/commands.ts | 28 ++++++++++++++++++++++++---- src/constants.ts | 1 + src/traceCommand.ts | 7 +++++++ test/traceCommand.test.ts | 12 ++++++++++++ 6 files changed, 52 insertions(+), 4 deletions(-) create mode 100644 src/traceCommand.ts create mode 100644 test/traceCommand.test.ts diff --git a/package.json b/package.json index ddfb78b..9499278 100644 --- a/package.json +++ b/package.json @@ -297,6 +297,11 @@ "command": "tsperf.tracer.runTrace", "category": "Tracer" }, + { + "title": "Trace current file", + "command": "tsperf.tracer.runTraceActiveFile", + "category": "Tracer" + }, { "title": "Send Trace to Trace Viewer", "command": "tsperf.tracer.sendTrace", diff --git a/scripts/generate-contributes.ts b/scripts/generate-contributes.ts index 59f33f1..e1573e4 100755 --- a/scripts/generate-contributes.ts +++ b/scripts/generate-contributes.ts @@ -49,6 +49,9 @@ const commandRecord: Record = { explorerContext: 'resourceFilename =~ /./', }, }, + 'tsperf.tracer.runTraceActiveFile': { + title: 'Trace current file', + }, 'tsperf.tracer.sendTrace': { title: 'Send Trace to Trace Viewer', when: { diff --git a/src/commands.ts b/src/commands.ts index 57b522b..506a794 100644 --- a/src/commands.ts +++ b/src/commands.ts @@ -13,6 +13,7 @@ import { addTraceFile, getWorkspacePath, openTerminal, openTraceDirectoryExterna import { addTraceDiagnostics, clearTaceDiagnostics } from './traceDiagnostics' import { setStatusBarState } from './statusBar' import { afterWatches, projectPath, saveName, state, traceFiles, traceRunning } from './appState' +import { traceSaveNameForFile } from './traceCommand' const readdir = promisify(readdirC) @@ -21,6 +22,7 @@ const commandHandlers: Record< (context: vscode.ExtensionContext) => (...args: any[]) => void > = { 'tsperf.tracer.runTrace': () => (...args: unknown[]) => runTrace(args), + 'tsperf.tracer.runTraceActiveFile': () => () => runTraceActiveFile(), 'tsperf.tracer.openInBrowser': (context: vscode.ExtensionContext) => () => prepareWebView(context), 'tsperf.tracer.gotoTracePosition': (context: vscode.ExtensionContext) => () => gotoTracePosition(context), 'tsperf.tracer.sendTrace': () => (event: unknown) => { @@ -35,6 +37,20 @@ const commandHandlers: Record< 'tsperf.tracer.openTraceDirExternal': () => () => openTraceDirectoryExternal(), } as const +async function runTraceActiveFile() { + const editor = vscode.window.activeTextEditor + if (!editor || editor.document.uri.scheme !== 'file') { + vscode.window.showWarningMessage('Open a TypeScript file before running a mini trace') + return + } + + const workspacePath = state.workspacePath.value || getWorkspacePath() + await runTrace([], { + cwd: workspacePath, + saveName: traceSaveNameForFile(workspacePath, editor.document.uri.fsPath), + }) +} + async function sendTrace(dirName: string, fileName: string) { const fullFileName = join(dirName, fileName) @@ -97,7 +113,7 @@ function gotoTracePosition(context: vscode.ExtensionContext) { showTree('', relativePath, startOffset - (editor.document.getText()[startOffset + 1] === '\n' ? 0 : 1)) } -async function runTrace(args?: unknown[]) { +async function runTrace(args?: unknown[], options?: { cwd?: string, saveName?: string }) { const workspacePath = state.workspacePath.value const { traceCmd } = getCurrentConfig() @@ -114,7 +130,10 @@ async function runTrace(args?: unknown[]) { } } - if (dirName) { + if (options?.saveName) { + saveName.value = options.saveName + } + else if (dirName) { log(`dirName: ${dirName}`) saveName.value = relative(workspacePath, dirName) } @@ -128,13 +147,14 @@ async function runTrace(args?: unknown[]) { return } + const traceCwd = options?.cwd ?? newDirName ?? workspacePath const quotedTraceDir = `'${traceDir}'` // eslint-disable-next-line no-template-curly-in-string - const fullCmd = `(cd '${newDirName ?? workspacePath}'; ${traceCmd.replace('${traceDir}', quotedTraceDir)})` + const fullCmd = `(cd '${traceCwd}'; ${traceCmd.replace('${traceDir}', quotedTraceDir)})` log(fullCmd) - const newProjectPath = newDirName ?? projectPath.value + const newProjectPath = traceCwd || projectPath.value if (!newProjectPath) { vscode.window.showErrorMessage('could not get project path from workspace folders') return diff --git a/src/constants.ts b/src/constants.ts index fc97b3b..91b8316 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -25,6 +25,7 @@ export const commandIds = [ 'tsperf.tracer.gotoTracePosition', 'tsperf.tracer.openInBrowser', 'tsperf.tracer.runTrace', + 'tsperf.tracer.runTraceActiveFile', 'tsperf.tracer.sendTrace', 'tsperf.tracer.openTerminal', 'tsperf.tracer.openTraceDirExternal', diff --git a/src/traceCommand.ts b/src/traceCommand.ts new file mode 100644 index 0000000..a941578 --- /dev/null +++ b/src/traceCommand.ts @@ -0,0 +1,7 @@ +import { extname, relative } from 'node:path' + +export function traceSaveNameForFile(workspacePath: string, filePath: string): string { + const relativeFile = relative(workspacePath, filePath) + const extension = extname(relativeFile) + return extension ? relativeFile.slice(0, -extension.length) : relativeFile +} diff --git a/test/traceCommand.test.ts b/test/traceCommand.test.ts new file mode 100644 index 0000000..f44752e --- /dev/null +++ b/test/traceCommand.test.ts @@ -0,0 +1,12 @@ +import { describe, expect, it } from 'vitest' +import { traceSaveNameForFile } from '../src/traceCommand' + +describe('traceSaveNameForFile', () => { + it('uses the workspace-relative file path without extension', () => { + expect(traceSaveNameForFile('/repo', '/repo/src/features/example.ts')).toBe('src/features/example') + }) + + it('preserves files without extensions', () => { + expect(traceSaveNameForFile('/repo', '/repo/tsconfig')).toBe('tsconfig') + }) +})