Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding ability to select the .NET language on create #2667

Merged
merged 11 commits into from Dec 7, 2021
Expand Up @@ -137,6 +137,10 @@ public async override Task RunAsync()
Language = SelectionMenuHelper.DisplaySelectionWizard(displayList);
}
}
else if (WorkerRuntimeLanguageHelper.IsDotnet(workerRuntime))
{
InferAndUpdateLanguage(workerRuntime);
}
}
else if (!string.IsNullOrWhiteSpace(Language))
{
Expand All @@ -151,7 +155,7 @@ public async override Task RunAsync()
FunctionName = FunctionName ?? Console.ReadLine();
ColoredConsole.WriteLine(FunctionName);
var namespaceStr = Path.GetFileName(Environment.CurrentDirectory);
await DotnetHelpers.DeployDotnetFunction(TemplateName.Replace(" ", string.Empty), Utilities.SanitizeClassName(FunctionName), Utilities.SanitizeNameSpace(namespaceStr), workerRuntime, AuthorizationLevel);
await DotnetHelpers.DeployDotnetFunction(TemplateName.Replace(" ", string.Empty), Utilities.SanitizeClassName(FunctionName), Utilities.SanitizeNameSpace(namespaceStr), Language.Replace("-isolated", ""), workerRuntime, AuthorizationLevel);
}
else
{
Expand Down Expand Up @@ -221,13 +225,28 @@ private void ConfigureAuthorizationLevel(Template template)

private bool InferAndUpdateLanguage(WorkerRuntime workerRuntime)
{
// If there is a tsconfig.json present, we assume that the language is typescript
if (workerRuntime == WorkerRuntime.node)
switch (workerRuntime)
{
Language = FileSystemHelpers.FileExists(Path.Combine(Environment.CurrentDirectory, "tsconfig.json")) ? Constants.Languages.TypeScript : Constants.Languages.JavaScript;
return true;
case WorkerRuntime.dotnet:
// use fsproj as an indication that we have a F# project
Language = FileSystemHelpers.GetFiles(Environment.CurrentDirectory, searchPattern: "*.fsproj").Any() ? Constants.Languages.FSharp : Constants.Languages.CSharp;
return true;
case WorkerRuntime.dotnetIsolated:
// use fsproj as an indication that we have a F# project
Language = FileSystemHelpers.GetFiles(Environment.CurrentDirectory, searchPattern: "*.fsproj").Any() ? Constants.Languages.FSharpIsolated : Constants.Languages.CSharpIsolated;
return true;
case WorkerRuntime.node:
// use tsconfig.json as an indicator that we have a TypeScript project
Language = FileSystemHelpers.FileExists(Path.Combine(Environment.CurrentDirectory, "tsconfig.json")) ? Constants.Languages.TypeScript : Constants.Languages.JavaScript;
return true;
case WorkerRuntime.None:
case WorkerRuntime.python:
case WorkerRuntime.java:
case WorkerRuntime.powershell:
case WorkerRuntime.custom:
default:
return false;
}
return false;
}

private void PerformPostDeployTasks(string functionName, string language)
Expand Down
Expand Up @@ -227,7 +227,9 @@ private static (WorkerRuntime, string) ResolveWorkerRuntimeAndLanguage(string wo

private static string LanguageSelectionIfRelevant(WorkerRuntime workerRuntime)
{
if (workerRuntime == Helpers.WorkerRuntime.node)
if (workerRuntime == Helpers.WorkerRuntime.node
|| workerRuntime == Helpers.WorkerRuntime.dotnetIsolated
|| workerRuntime == Helpers.WorkerRuntime.dotnet)
{
if (WorkerRuntimeLanguageHelper.WorkerToSupportedLanguages.TryGetValue(workerRuntime, out IEnumerable<string> languages)
&& languages.Count() != 0)
Expand Down
3 changes: 3 additions & 0 deletions src/Azure.Functions.Cli/Common/Constants.cs
Expand Up @@ -106,6 +106,9 @@ public static class Languages
public const string TypeScript = "typescript";
public const string Python = "python";
public const string CSharp = "c#";
public const string FSharp = "f#";
public const string CSharpIsolated = "c#-isolated";
public const string FSharpIsolated = "f#-isolated";
public const string Powershell = "powershell";
public const string Java = "java";
public const string Custom = "custom";
Expand Down
4 changes: 2 additions & 2 deletions src/Azure.Functions.Cli/Helpers/DotnetHelpers.cs
Expand Up @@ -41,13 +41,13 @@ public async static Task DeployDotnetProject(string Name, bool force, WorkerRunt
}, workerRuntime);
}

public static async Task DeployDotnetFunction(string templateName, string functionName, string namespaceStr, WorkerRuntime workerRuntime, AuthorizationLevel? httpAuthorizationLevel = null)
public static async Task DeployDotnetFunction(string templateName, string functionName, string namespaceStr, string language, WorkerRuntime workerRuntime, AuthorizationLevel? httpAuthorizationLevel = null)
{
await TemplateOperation(async () =>
{
// In .NET 6.0, the 'dotnet new' command requires the short name.
string templateShortName = GetTemplateShortName(templateName);
string exeCommandArguments = $"new {templateShortName} --name {functionName} --namespace {namespaceStr}";
string exeCommandArguments = $"new {templateShortName} --name {functionName} --namespace {namespaceStr} --language {language}";
if (httpAuthorizationLevel != null)
{
if (templateName.Equals(Constants.HttpTriggerTemplateName, StringComparison.OrdinalIgnoreCase))
Expand Down
11 changes: 7 additions & 4 deletions src/Azure.Functions.Cli/Helpers/WorkerRuntimeLanguageHelper.cs
Expand Up @@ -25,7 +25,7 @@ public static class WorkerRuntimeLanguageHelper
private static readonly IDictionary<WorkerRuntime, IEnumerable<string>> availableWorkersRuntime = new Dictionary<WorkerRuntime, IEnumerable<string>>
{
{ WorkerRuntime.dotnet, new [] { "c#", "csharp", "f#", "fsharp" } },
{ WorkerRuntime.dotnetIsolated, new [] { "dotnet-isolated" } },
{ WorkerRuntime.dotnetIsolated, new [] { "dotnet-isolated", "c#-isolated", "csharp-isolated", "f#-isolated", "fsharp-isolated" } },
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we still need dotnet-isolated in the array containing c#-isolated and csharp-isolated here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'll have to have a second look at it, but I think the reason I kept dotnet-isolated in there was for backwards compatibility, as prior to this change that's how things were identified.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've had a bit of a poke around and I don't think it can be removed with a lot of other cascading changes.

Removing dotnet-isolated will cause existing projects to fail to launch using func start as it's unable to detect the worker type. I also tested changing the worker type in local.settings.json to c#-isolated but that then errors within the WebJobs dependency as it couldn't find the functions language c#-isolated, so there'd be a downstream impact.

Additionally, all templates would need to be updated to either say c#-isolated or f#-isolated in them before the change would usable.

Ultimately, the additional worker types are probably not doing anything of value at present, they are more future proofing 😅

{ WorkerRuntime.node, new [] { "js", "javascript", "typescript", "ts" } },
{ WorkerRuntime.python, new [] { "py" } },
{ WorkerRuntime.java, new string[] { } },
Expand All @@ -41,7 +41,7 @@ public static class WorkerRuntimeLanguageHelper
private static readonly IDictionary<WorkerRuntime, string> workerToDefaultLanguageMap = new Dictionary<WorkerRuntime, string>
{
{ WorkerRuntime.dotnet, Constants.Languages.CSharp },
{ WorkerRuntime.dotnetIsolated, Constants.Languages.CSharp },
{ WorkerRuntime.dotnetIsolated, Constants.Languages.CSharpIsolated },
Copy link
Member

Choose a reason for hiding this comment

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

Does this need entries for F#?

Copy link
Member

Choose a reason for hiding this comment

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

I see it's the defaults

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, figured that the default of C# makes the most sense

{ WorkerRuntime.node, Constants.Languages.JavaScript },
{ WorkerRuntime.python, Constants.Languages.Python },
{ WorkerRuntime.powershell, Constants.Languages.Powershell },
Expand All @@ -55,7 +55,8 @@ public static class WorkerRuntimeLanguageHelper
{ Constants.Languages.TypeScript, new [] { "ts" } },
{ Constants.Languages.Python, new [] { "py" } },
{ Constants.Languages.Powershell, new [] { "pwsh" } },
{ Constants.Languages.CSharp, new [] { "csharp", "dotnet", "dotnet-isolated", "dotnetIsolated" } },
{ Constants.Languages.CSharp, new [] { "csharp", "dotnet" } },
{ Constants.Languages.CSharpIsolated, new [] { "dotnet-isolated", "dotnetIsolated" } },
{ Constants.Languages.Java, new string[] { } },
{ Constants.Languages.Custom, new string[] { } }
};
Expand All @@ -67,7 +68,9 @@ public static class WorkerRuntimeLanguageHelper

public static readonly IDictionary<WorkerRuntime, IEnumerable<string>> WorkerToSupportedLanguages = new Dictionary<WorkerRuntime, IEnumerable<string>>
{
{ WorkerRuntime.node, new [] { Constants.Languages.JavaScript, Constants.Languages.TypeScript } }
{ WorkerRuntime.node, new [] { Constants.Languages.JavaScript, Constants.Languages.TypeScript } },
{ WorkerRuntime.dotnet, new [] { Constants.Languages.CSharp, Constants.Languages.FSharp } },
{ WorkerRuntime.dotnetIsolated, new [] { Constants.Languages.CSharpIsolated, Constants.Languages.FSharpIsolated } }
};

public static string AvailableWorkersRuntimeString =>
Expand Down