diff --git a/package.json b/package.json index 8865589f..5316c503 100644 --- a/package.json +++ b/package.json @@ -67,7 +67,8 @@ "onCommand:truffle-vscode.views.dashboard.restartDashboardServer", "onCommand:truffle-vscode.views.dashboard.openDashboard", "onCommand:truffle-vscode.views.dashboard.copyRPCEndpointAddress", - "onDebug" + "onDebug", + "onUri" ], "contributes": { "configuration": { diff --git a/src/commands/DebuggerCommands.ts b/src/commands/DebuggerCommands.ts index cf3c0188..b65aa7ba 100644 --- a/src/commands/DebuggerCommands.ts +++ b/src/commands/DebuggerCommands.ts @@ -10,7 +10,7 @@ import {shortenHash} from '@/debugAdapter/functions'; import {TransactionProvider} from '@/debugAdapter/transaction/transactionProvider'; import {Web3Wrapper} from '@/debugAdapter/web3Wrapper'; import {getTruffleWorkspace, getPathByPlatform} from '@/helpers/workspace'; -import {showInputBox, showQuickPick} from '@/helpers/userInteraction'; +import {showQuickPick} from '@/helpers/userInteraction'; import {Telemetry} from '@/TelemetryClient'; export namespace DebuggerCommands { @@ -29,28 +29,20 @@ export namespace DebuggerCommands { // const workspaceFolder = workspace.getWorkspaceFolder(workspaceUri); - if (debugNetwork.isLocalNetwork()) { - // if local service then provide last transactions to choose - const transactionProvider = new TransactionProvider(web3, contractBuildDir); - const txHashesAsQuickPickItems = await getQuickPickItems(transactionProvider); + const transactionProvider = new TransactionProvider(web3, contractBuildDir); + const txHashesAsQuickPickItems = await getQuickPickItems(transactionProvider); - const txHashSelection = await showQuickPick(txHashesAsQuickPickItems, { - ignoreFocusOut: true, - placeHolder: 'Enter the transaction hash to debug', - }); + const txHashSelection = await showQuickPick(txHashesAsQuickPickItems, { + ignoreFocusOut: true, + placeHolder: 'Enter the transaction hash to debug', + }); - const txHash = txHashSelection.detail || txHashSelection.label; + const txHash = txHashSelection.detail || txHashSelection.label; - await startDebugging(txHash, workingDirectory, providerUrl); - } else { - // if remote network then require txHash - const placeHolder = 'Type the transaction hash you want to debug (0x...)'; - const txHash = await showInputBox({placeHolder}); + // TODO: Add a way to select if the user wants to fetch external contracts. For now, we will keep it as false. + const fetchExternal = false; - if (txHash) { - await startDebugging(txHash, workingDirectory, providerUrl); - } - } + await startDebugging(txHash, workingDirectory, providerUrl, fetchExternal); } } @@ -66,10 +58,19 @@ async function getQuickPickItems(txProvider: TransactionProvider) { }); } -export function generateDebugAdapterConfig( +/** + * This function is reponsible to generate the debug configuration adapter with the given parameters. + * + * @param txHash A transaction hash. + * @param workingDirectory The working directory of the project. + * @param providerUrl The network provider url. + * @param fetchExternal Indicates if the debugger should fetch external contracts. + */ +function generateDebugAdapterConfig( txHash: string, workingDirectory: string, - providerUrl: string + providerUrl: string, + fetchExternal: boolean ): DebugConfiguration { return { files: [], @@ -80,12 +81,26 @@ export function generateDebugAdapterConfig( type: DEBUG_TYPE, workingDirectory, timeout: 30000, + fetchExternal, } as DebugConfiguration; } -export async function startDebugging(txHash: string, workingDirectory: string, providerUrl: string): Promise { +/** + * This functions is responsible for starting the solidity debugger with the given parameters. + * + * @param txHash A transaction hash. + * @param workingDirectory The working directory of the project. + * @param providerUrl The network provider url. + * @param fetchExternal Indicates if the debugger should fetch external contracts. + */ +export async function startDebugging( + txHash: string, + workingDirectory: string, + providerUrl: string, + fetchExternal: boolean +): Promise { const workspaceFolder = workspace.getWorkspaceFolder(Uri.parse(workingDirectory)); - const config = generateDebugAdapterConfig(txHash, workingDirectory, providerUrl); + const config = generateDebugAdapterConfig(txHash, workingDirectory, providerUrl, fetchExternal); debug.startDebugging(workspaceFolder, config).then(() => { Telemetry.sendEvent('DebuggerCommands.startSolidityDebugger.commandFinished'); diff --git a/src/debugAdapter/debugNetwork.ts b/src/debugAdapter/debugNetwork.ts index f1fff8bd..0ce4beaf 100644 --- a/src/debugAdapter/debugNetwork.ts +++ b/src/debugAdapter/debugNetwork.ts @@ -37,15 +37,6 @@ export class DebugNetwork { return this._networkForDebug; } - // Port and host are defined - public isLocalNetwork() { - if (!this._networkForDebug || !this._networkForDebug.options) { - throw new Error('Network is not defined. Try to call this.load()'); - } - const options = this._networkForDebug.options; - return !!(options.host && options.port); - } - private async loadConfiguration(): Promise { const configuration = await this._basedConfig!.getConfiguration(this.workingDirectory); diff --git a/src/debugAdapter/models/debuggerTypes.ts b/src/debugAdapter/models/debuggerTypes.ts index abab1e85..8f375461 100644 --- a/src/debugAdapter/models/debuggerTypes.ts +++ b/src/debugAdapter/models/debuggerTypes.ts @@ -25,9 +25,10 @@ export namespace DebuggerTypes { trace?: boolean; host?: string; txHash: string; - files: string[]; + files?: string[]; workingDirectory: string; providerUrl: string; + fetchExternal?: boolean; } export class LaunchedEvent implements DebugProtocol.Event { diff --git a/src/helpers/uriHandlerController.ts b/src/helpers/uriHandlerController.ts index f3a87d16..c7ebb986 100644 --- a/src/helpers/uriHandlerController.ts +++ b/src/helpers/uriHandlerController.ts @@ -1,35 +1,51 @@ import {startDebugging} from '@/commands'; import {Constants} from '@/Constants'; +import {DebuggerTypes} from '@/debugAdapter/models/debuggerTypes'; import {Uri, UriHandler, window} from 'vscode'; - -type TDebugInformation = { - txHash: string; - workingDirectory: string; - providerUrl: string; -}; - +/** + * This enum is used to identify the different types of commands that can be executed. + */ enum Commands { + /** + * The command to start the debugger. + */ debug = 'debug', } export class UriHandlerController implements UriHandler { + /** + * This function is responsible for handling the `truffle-vscode` protocol callings. + * + * @param uri The URI to handle. + */ async handleUri(uri: Uri): Promise { try { - // Gets the command name + // Parse the URI to get the command and the parameters. const command = uri.path.replace('/', ''); + const searchParams = new URLSearchParams(uri.query); - // Gets the configuration arguments - const debugConfig = JSON.parse(uri.query) as TDebugInformation; + // Convert the URI parameters to a TDebugInformation object. + const launchRequest: DebuggerTypes.ILaunchRequestArguments = { + txHash: searchParams.get('txHash')!, + workingDirectory: searchParams.get('workingDirectory')!, + providerUrl: searchParams.get('providerUrl')!, + fetchExternal: searchParams.get('fetchExternal')! === 'true', + }; - // Checks what kind of command it will need to execute + // Checks the command and executes the corresponding action. switch (command) { case Commands.debug: - // Calls the debugger - await startDebugging(debugConfig.txHash, debugConfig.workingDirectory, debugConfig.providerUrl); + // Calls the debugger with the given parameters. + await startDebugging( + launchRequest.txHash, + launchRequest.workingDirectory, + launchRequest.providerUrl, + launchRequest.fetchExternal! + ); break; } } catch (error) { - // Displays a message if the command or arguments are badly formatted + // Display an error message if something went wrong. window.showErrorMessage(Constants.errorMessageStrings.UriHandlerError); } } diff --git a/test/commands/DebuggerCommands.test.ts b/test/commands/DebuggerCommands.test.ts index 38c21b61..47ac26f4 100644 --- a/test/commands/DebuggerCommands.test.ts +++ b/test/commands/DebuggerCommands.test.ts @@ -54,9 +54,8 @@ describe('DebuggerCommands unit tests', () => { sinon.restore(); }); - it('should generate and show quickPick when debugNetwork.isLocalNetwork() is true', async () => { + it('should generate and show quickPick when debugger is called', async () => { // Arrange - sinon.stub(DebugNetwork.prototype, 'isLocalNetwork').returns(true); const createQuickPickFn = sinon.stub(userInteraction, 'showQuickPick').resolves({} as QuickPickItem); // Act @@ -67,18 +66,4 @@ describe('DebuggerCommands unit tests', () => { assert.strictEqual(mockGetTxInfos.calledOnce, true, 'getTransactionsInfo should be called'); assert.strictEqual(createQuickPickFn.called, true, 'createQuickPic should be called'); }); - - it('should show inputBox when debugNetwork.isLocalNetwork() is false', async () => { - // Arrange - sinon.stub(DebugNetwork.prototype, 'isLocalNetwork').returns(false); - const showInputBoxFn = sinon.stub(userInteraction, 'showInputBox').resolves(''); - - // Act - await debugCommands.DebuggerCommands.startSolidityDebugger(); - - // Assert - assert.strictEqual(showInputBoxFn.called, true, 'showInputBox should be called'); - assert.strictEqual(mockGetTxHashes.calledOnce, false, "getLastTransactionHashes shouldn't be called"); - assert.strictEqual(mockGetTxInfos.calledOnce, false, "getTransactionsInfo shouldn't be called"); - }); });