import * as process from 'process' ; import { CancellationToken , ShellExecution , ShellExecutionOptions , Task , TaskDefinition , TaskProvider , TaskScope , workspace , WorkspaceFolder } from 'vscode' ; import { callWithTelemetryAndErrorHandling , IActionContext } from 'vscode-azureextensionui' ; import { tryGetFunctionProjectRoot } from '../commands/createNewProject/verifyIsProject' ; import { buildNativeDeps , extInstallCommand , func , hostStartCommand , packCommand , ProjectLanguage , projectLanguageSetting } from '../constants' ; import { getFuncCliPath } from '../funcCoreTools/getFuncCliPath' ; import { venvUtils } from '../utils/venvUtils' ; import { getFuncWatchProblemMatcher , getWorkspaceSetting } from '../vsCodeConfig/settings' ; import { getTasks } from '../vsCodeConfig/tasks' ; import { FuncDebugProviderBase } from './FuncDebugProviderBase' ; import { JavaDebugProvider } from './JavaDebugProvider' ; import { NodeDebugProvider } from './NodeDebugProvider' ; import { PowerShellDebugProvider } from './PowerShellDebugProvider' ; import { PythonDebugProvider } from './PythonDebugProvider' ; export class FuncTaskProvider implements TaskProvider { private readonly _nodeDebugProvider : NodeDebugProvider ; private readonly _pythonDebugProvider : PythonDebugProvider ; private readonly _javaDebugProvider : JavaDebugProvider ; private readonly _powershellDebugProvider : PowerShellDebugProvider ; constructor ( nodeDebugProvider , pythonDebugProvider , javaDebugProvider , powershellDebugProvider ) { this . _nodeDebugProvider = nodeDebugProvider ; this . _pythonDebugProvider = pythonDebugProvider ; this . _javaDebugProvider = javaDebugProvider ; this . _powershellDebugProvider = powershellDebugProvider ; } public async provideTasks ( _token ? ) { const result = [ ] ; await callWithTelemetryAndErrorHandling ( 'provideTasks' , async ( context ) => { context . telemetry . properties . isActivationEvent = 'true' ; context . errorHandling . suppressDisplay = true ; context . telemetry . suppressIfSuccessful = true ; if ( workspace . workspaceFolders ) { let lastError ; for ( const folder of workspace . workspaceFolders ) { try { const projectRoot = await tryGetFunctionProjectRoot ( context , folder ) ; if ( projectRoot ) { const language = getWorkspaceSetting ( projectLanguageSetting , folder . uri . fsPath ) ; const commands = [ extInstallCommand ] ; if ( ! hasHostStartTask ( folder ) ) { commands . push ( hostStartCommand ) ; } if ( language === ProjectLanguage . Python ) { commands . push ( packCommand ) ; commands . push ( `${ packCommand } ${ buildNativeDeps }` ) ; } for ( const command of commands ) { result . push ( await this . createTask ( context , command , folder , projectRoot , language ) ) ; } } } catch ( err ) { lastError = err ; } } if ( ! ( lastError === null || lastError === undefined ) ) { throw lastError ; } } } ) ; return result ; } public async resolveTask ( task , _token ? ) { return await callWithTelemetryAndErrorHandling ( 'resolveTask' , async ( context ) => { context . telemetry . properties . isActivationEvent = 'true' ; context . errorHandling . suppressDisplay = true ; context . telemetry . suppressIfSuccessful = true ; const command = task . definition . command ; if ( command && task . scope !== undefined && task . scope !== TaskScope . Global && task . scope !== TaskScope . Workspace ) { const folder = task . scope ; const language = getWorkspaceSetting ( projectLanguageSetting , folder . uri . fsPath ) ; return this . createTask ( context , command , folder , undefined , language , task . definition ) ; } return undefined ; } ) ; } private async createTask ( context , command , folder , projectRoot , language , definition ? ) { const funcCliPath = await getFuncCliPath ( context , folder ) ; let commandLine = `${ funcCliPath } ${ command }` ; if ( language === ProjectLanguage . Python ) { commandLine = venvUtils . convertToVenvCommand ( commandLine , folder . uri . fsPath ) ; } let problemMatcher ; let options ; if ( /^\s*(host )?start/i . test ( command ) ) { problemMatcher = getFuncWatchProblemMatcher ( language ) ; options = await this . getHostStartOptions ( folder , language ) ; } options = options || { } ; if ( projectRoot ) { options . cwd = projectRoot ; } definition = definition || { type : func , command } ; return new Task ( definition , folder , command , func , new ShellExecution ( commandLine , options ) , problemMatcher ) ; } private async getHostStartOptions ( folder , language ) { let debugProvider ; switch ( language ) { case ProjectLanguage . Python : debugProvider = this . _pythonDebugProvider ; break ; case ProjectLanguage . JavaScript : case ProjectLanguage . TypeScript : debugProvider = this . _nodeDebugProvider ; break ; case ProjectLanguage . Java : debugProvider = this . _javaDebugProvider ; break ; case ProjectLanguage . PowerShell : debugProvider = this . _powershellDebugProvider ; break ; default : return undefined ; } return process . env [ debugProvider . workerArgKey ] ? undefined : { env : { [ debugProvider . workerArgKey ] : await debugProvider . getWorkerArgValue ( folder ) } } ; } } function hasHostStartTask ( folder ) { try { return getTasks ( folder ) . some ( t => t . type === func && t . command && /^\s*(host )?start/i . test ( t . command ) ) ; } catch { return false ; } }