Skip to content
50 changes: 50 additions & 0 deletions src/debug/getPreLaunchTaskChain.ts
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function seems to be a great candidate for unit tests

Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import * as vscode from 'vscode';
import { getTasks, ITask } from '../vsCodeConfig/tasks';

/**
* Resolves the full chain of tasks associated with a given `preLaunchTask`.
* Recursively follows the `dependsOn` references found in the `tasks.json`.
*/
export function getPreLaunchTaskChain(workspace: vscode.WorkspaceFolder, preLaunchTask: string): string[] {
const allTasks: ITask[] = getTasks(workspace);
const allTasksMap = new Map<string, ITask>();

for (const task of allTasks) {
if (task.label) {
allTasksMap.set(task.label, task);
}
}

const dependentTasks = new Set<string>();

function getDependentTasks(name: string): void {
if (dependentTasks.has(name)) {
return;
}
dependentTasks.add(name);

const task = allTasksMap.get(name);
if (!task) {
return;
}

const dependsOn: unknown = task?.dependsOn;
if (typeof dependsOn === 'string') {
getDependentTasks(dependsOn);
} else if (Array.isArray(dependsOn)) {
for (const dep of dependsOn) {
if (typeof dep === 'string') {
getDependentTasks(dep);
}
}
}
Comment thread
MicroFish91 marked this conversation as resolved.
}

getDependentTasks(preLaunchTask);
return Array.from(dependentTasks.values());
Comment thread
MicroFish91 marked this conversation as resolved.
}
53 changes: 32 additions & 21 deletions src/debug/validatePreDebug.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { durableUtils } from '../utils/durableUtils';
import { isPythonV2Plus } from '../utils/programmingModelUtils';
import { getDebugConfigs, isDebugConfigEqual } from '../vsCodeConfig/launch';
import { getWorkspaceSetting, tryGetFunctionsWorkerRuntimeForProject } from "../vsCodeConfig/settings";
import { getPreLaunchTaskChain } from './getPreLaunchTaskChain';
import { validateDTSConnectionPreDebug } from './storageProviders/validateDTSConnectionPreDebug';
import { validateNetheriteConnectionPreDebug } from './storageProviders/validateNetheriteConnectionPreDebug';
import { validateSQLConnectionPreDebug } from './storageProviders/validateSQLConnectionPreDebug';
Expand All @@ -32,12 +33,20 @@ export interface IPreDebugContext extends Omit<ISetConnectionSettingContext, 'pr
projectPath?: string;
}

const emulatorTaskRegExp: RegExp = /azurite|emulator/i;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Worried this could be pretty fragile


export async function preDebugValidate(actionContext: IActionContext, debugConfig: vscode.DebugConfiguration): Promise<IPreDebugValidateResult> {
const context: IPreDebugContext = Object.assign(actionContext, { action: CodeAction.Debug });
const workspace: vscode.WorkspaceFolder = getMatchingWorkspace(debugConfig);
let shouldContinue: boolean;
context.telemetry.properties.debugType = debugConfig.type;

// If one of the `preLaunchTasks` already handles starting emulators, assume we can skip our pre-validate setup for them
const preLaunchTaskName: string | undefined = debugConfig.preLaunchTask;
const preLaunchTaskChain: string[] = preLaunchTaskName ? getPreLaunchTaskChain(workspace, preLaunchTaskName) : [];
const hasEmulatorTask: boolean = preLaunchTaskChain.some(label => emulatorTaskRegExp.test(label));
context.telemetry.properties.hasEmulatorTask = String(hasEmulatorTask);

try {
context.telemetry.properties.lastValidateStep = 'funcInstalled';
const message: string = localize('installFuncTools', 'You must have the Azure Functions Core Tools installed to debug your local functions.');
Expand All @@ -62,28 +71,30 @@ export async function preDebugValidate(actionContext: IActionContext, debugConfi
context.telemetry.properties.lastValidateStep = 'workerRuntime';
await validateWorkerRuntime(context, projectLanguage, context.projectPath);

switch (durableStorageType) {
case DurableBackend.DTS:
context.telemetry.properties.lastValidateStep = 'dtsConnection';
await validateDTSConnectionPreDebug(context, context.projectPath);
break;
case DurableBackend.Netherite:
context.telemetry.properties.lastValidateStep = 'netheriteConnection';
await validateNetheriteConnectionPreDebug(context, context.projectPath);
break;
case DurableBackend.SQL:
context.telemetry.properties.lastValidateStep = 'sqlDbConnection';
await validateSQLConnectionPreDebug(context, context.projectPath);
break;
case DurableBackend.Storage:
default:
if (!hasEmulatorTask) {
switch (durableStorageType) {
case DurableBackend.DTS:
context.telemetry.properties.lastValidateStep = 'dtsConnection';
await validateDTSConnectionPreDebug(context, context.projectPath);
break;
case DurableBackend.Netherite:
context.telemetry.properties.lastValidateStep = 'netheriteConnection';
await validateNetheriteConnectionPreDebug(context, context.projectPath);
break;
case DurableBackend.SQL:
context.telemetry.properties.lastValidateStep = 'sqlDbConnection';
await validateSQLConnectionPreDebug(context, context.projectPath);
break;
case DurableBackend.Storage:
default:
}

context.telemetry.properties.lastValidateStep = 'azureWebJobsStorage';
await validateAzureWebJobsStorage(context, context.projectPath);

context.telemetry.properties.lastValidateStep = 'emulatorRunning';
shouldContinue = hasEmulatorTask || await validateEmulatorIsRunning(context, context.projectPath);
}
Comment thread
MicroFish91 marked this conversation as resolved.
Outdated
Comment thread
MicroFish91 marked this conversation as resolved.
Outdated

context.telemetry.properties.lastValidateStep = 'azureWebJobsStorage';
await validateAzureWebJobsStorage(context, context.projectPath);

context.telemetry.properties.lastValidateStep = 'emulatorRunning';
shouldContinue = await validateEmulatorIsRunning(context, context.projectPath);
}
}
} catch (error) {
Expand Down
Loading