import * as path from 'path' ; import { DebugConfiguration , MessageItem , TaskDefinition } from 'vscode' ; import { DialogResponses , parseError } from 'vscode-azureextensionui' ; import { func , hostStartCommand , ProjectLanguage } from '../../../constants' ; import { FuncVersion , tryParseFuncVersion } from '../../../FuncVersion' ; import { localize } from "../../../localize" ; import { dotnetUtils } from '../../../utils/dotnetUtils' ; import { nonNullProp } from '../../../utils/nonNull' ; import { openUrl } from '../../../utils/openUrl' ; import { getFuncWatchProblemMatcher , getWorkspaceSetting , updateGlobalSetting } from '../../../vsCodeConfig/settings' ; import { convertToFunctionsTaskLabel } from '../../../vsCodeConfig/tasks' ; import { IProjectWizardContext } from '../../createNewProject/IProjectWizardContext' ; import { InitVSCodeStepBase } from './InitVSCodeStepBase' ; const dotnetPublishTaskLabel = convertToFunctionsTaskLabel ( 'publish' ) ; export class DotnetInitVSCodeStep extends InitVSCodeStepBase { protected preDeployTask : string = dotnetPublishTaskLabel ; private _debugSubpath : string ; protected getDebugConfiguration ( version ) { return { name : localize ( 'attachToNetFunc' , "Attach to .NET Functions" ) , type : version === FuncVersion . v1 ? 'clr' : 'coreclr' , request : 'attach' , processId : '\${command:azureFunctions.pickProcess}' } ; } protected getRecommendedExtensions ( language ) { const recs = [ 'ms-dotnettools.csharp' ] ; if ( language === ProjectLanguage . FSharp ) { recs . push ( 'ionide.ionide-fsharp' ) ; } return recs ; } /**
     * Detects the version based on the targetFramework from the proj file
     * Also performs a few validations and sets a few properties based on that targetFramework
     */ protected async executeCore ( context ) { const projectPath = context . projectPath ; const language = nonNullProp ( context , 'language' ) ; let projFile ; const projFiles = await dotnetUtils . getProjFiles ( context , language , projectPath ) ; const fileExt = language === ProjectLanguage . FSharp ? 'fsproj' : 'csproj' ; if ( projFiles . length === 1 ) { projFile = projFiles [ 0 ] ; } else if ( projFiles . length === 0 ) { context . errorHandling . suppressReportIssue = true ; throw new Error ( localize ( 'projNotFound' , 'Failed to find {0} file in folder "{1}".' , fileExt , path . basename ( projectPath ) ) ) ; } else { context . errorHandling . suppressReportIssue = true ; throw new Error ( localize ( 'projNotFound' , 'Expected to find a single {0} file in folder "{1}", but found multiple instead: {2}.' , fileExt , path . basename ( projectPath ) , projFiles . join ( ', ' ) ) ) ; } const versionInProjFile = await dotnetUtils . tryGetFuncVersion ( projFile ) ; context . telemetry . properties . versionInProjFile = versionInProjFile ; context . version = tryParseFuncVersion ( versionInProjFile ) || context . version ; if ( context . version === FuncVersion . v1 ) { const settingKey = 'show64BitWarning' ; if ( getWorkspaceSetting < boolean > ( settingKey ) ) { const message = localize ( '64BitWarning' , 'In order to debug .NET Framework functions in VS Code, you must install a 64-bit version of the Azure Functions Core Tools.' ) ; try { const result = await context . ui . showWarningMessage ( message , { stepName : 'netDebug64bit' } , DialogResponses . learnMore , DialogResponses . dontWarnAgain ) ; if ( result === DialogResponses . learnMore ) { await openUrl ( 'https://aka.ms/azFunc64bit' ) ; } else if ( result === DialogResponses . dontWarnAgain ) { await updateGlobalSetting ( settingKey , false ) ; } } catch ( err ) { if ( ! parseError ( err ) . isUserCancelledError ) { throw err ; } } } } const targetFramework = await dotnetUtils . getTargetFramework ( projFile ) ; this . setDeploySubpath ( context , `bin/Release/${ targetFramework }/publish` ) ; this . _debugSubpath = dotnetUtils . getDotnetDebugSubpath ( targetFramework ) ; } protected getTasks ( language ) { const commonArgs = [ '/property:GenerateFullPaths=true' , '/consoleloggerparameters:NoSummary' ] ; const releaseArgs = [ '--configuration' , 'Release' ] ; const buildLabel = convertToFunctionsTaskLabel ( 'build' ) ; const cleanLabel = convertToFunctionsTaskLabel ( 'clean' ) ; const cleanReleaseLabel = convertToFunctionsTaskLabel ( 'clean release' ) ; return [ { label : cleanLabel , command : 'dotnet' , args : [ 'clean' , ... commonArgs ] , type : 'process' , problemMatcher : '$msCompile' } , { label : buildLabel , command : 'dotnet' , args : [ 'build' , ... commonArgs ] , type : 'process' , dependsOn : cleanLabel , group : { kind : 'build' , isDefault : true } , problemMatcher : '$msCompile' } , { label : cleanReleaseLabel , command : 'dotnet' , args : [ 'clean' , ... releaseArgs , ... commonArgs ] , type : 'process' , problemMatcher : '$msCompile' } , { label : dotnetPublishTaskLabel , command : 'dotnet' , args : [ 'publish' , ... releaseArgs , ... commonArgs ] , type : 'process' , dependsOn : cleanReleaseLabel , problemMatcher : '$msCompile' } , { type : func , dependsOn : buildLabel , options : { cwd : this . _debugSubpath } , command : hostStartCommand , isBackground : true , problemMatcher : getFuncWatchProblemMatcher ( language ) } ] ; } }