import * as fse from 'fs-extra' ; import * as path from 'path' ; import { IActionContext } from 'vscode-azureextensionui' ; import { ProjectLanguage } from '../constants' ; import { FuncVersion } from '../FuncVersion' ; import { localize } from "../localize" ; import { cliFeedUtils } from './cliFeedUtils' ; import { telemetryUtils } from './telemetryUtils' ; import { findFiles } from './workspace' ; export namespace dotnetUtils { export const isolatedSdkName = 'Microsoft.Azure.Functions.Worker.Sdk' ; export class ProjectFile { public name : string ; public fullPath : string ; private _cachedContents : string | undefined ; constructor ( name , projectPath ) { this . name = name ; this . fullPath = path . join ( projectPath , name ) ; } public async getContents ( ) { if ( this . _cachedContents === undefined ) { this . _cachedContents = ( await fse . readFile ( this . fullPath ) ) . toString ( ) ; } return this . _cachedContents ; } } export function getDotnetDebugSubpath ( targetFramework ) { return path . posix . join ( 'bin' , 'Debug' , targetFramework ) ; } /**
     * NOTE: 'extensions.csproj' is excluded as it has special meaning for the func cli
     */ export async function getProjFiles ( context , projectLanguage , projectPath ) { return await telemetryUtils . runWithDurationTelemetry ( context , 'getNetProjFiles' , async ( ) => { const pattern = projectLanguage === ProjectLanguage . FSharp ? '*.fsproj' : '*.csproj' ; const uris = await findFiles ( projectPath , pattern ) ; return uris . map ( uri => path . basename ( uri . fsPath ) ) . filter ( f => f . toLowerCase ( ) !== 'extensions.csproj' ) . map ( f => new ProjectFile ( f , projectPath ) ) ; } ) ; } export async function getTargetFramework ( projFile ) { return await getPropertyInProjFile ( projFile , 'TargetFramework' ) ; } export async function tryGetFuncVersion ( projFile ) { try { return await getPropertyInProjFile ( projFile , 'AzureFunctionsVersion' ) ; } catch { return undefined ; } } export async function tryGetPlatformTarget ( projFile ) { try { return await getPropertyInProjFile ( projFile , 'PlatformTarget' ) ; } catch { return undefined ; } } export async function getIsIsolated ( projFile ) { try { return ( await projFile . getContents ( ) ) . toLowerCase ( ) . includes ( isolatedSdkName . toLowerCase ( ) ) ; } catch { return false ; } } async function getPropertyInProjFile ( projFile , prop ) { const regExp = new RegExp ( `<${ prop }>(.*)<\\/${ prop }>` ) ; const matches = ( await projFile . getContents ( ) ) . match ( regExp ) ; if ( ! matches ) { throw new Error ( localize ( 'failedToFindProp' , 'Failed to find "{0}" in project file "{1}".' , prop , projFile . name ) ) ; } else { return matches [ 1 ] ; } } export async function getTemplateKeyFromProjFile ( context , projectPath , version , language ) { let isIsolated = false ; let targetFramework ; switch ( version ) { case FuncVersion . v4 : targetFramework = 'net6.0' ; break ; case FuncVersion . v3 : targetFramework = 'netcoreapp3.1' ; break ; case FuncVersion . v2 : targetFramework = 'netcoreapp2.1' ; break ; case FuncVersion . v1 : targetFramework = 'net48' ; break ; } if ( projectPath && await fse . pathExists ( projectPath ) ) { const projFiles = await getProjFiles ( context , language , projectPath ) ; if ( projFiles . length === 1 ) { targetFramework = await getTargetFramework ( projFiles [ 0 ] ) ; isIsolated = await getIsIsolated ( projFiles [ 0 ] ) ; } } return getProjectTemplateKey ( targetFramework , isIsolated ) ; } export function getTemplateKeyFromFeedEntry ( runtimeInfo ) { const isIsolated = runtimeInfo . sdk . name . toLowerCase ( ) === isolatedSdkName . toLowerCase ( ) ; return getProjectTemplateKey ( runtimeInfo . targetFramework , isIsolated ) ; } function getProjectTemplateKey ( targetFramework , isIsolated ) { let result = targetFramework . split ( '-' ) [ 0 ] ; if ( isIsolated ) { result += '-isolated' ; } return result ; } }