Add Operations to GetAzureFunctions request (#1527)

* Add Operations to GetAzureFunctions request

* add comment

* comments
This commit is contained in:
Charles Gagnon
2022-06-06 12:59:59 -07:00
committed by GitHub
parent 97a106c575
commit 294873613a
6 changed files with 188 additions and 23 deletions

View File

@@ -5,6 +5,7 @@
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.SqlTools.ServiceLayer.AzureFunctions.Contracts;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -40,11 +41,23 @@ namespace Microsoft.SqlTools.ServiceLayer.AzureFunctions
}
/// <summary>
/// Gets the route from an HttpTrigger attribute if specified
/// Gets the info for a HttpTriggerBinding for the specified method (if such a binding exists)
/// </summary>
/// <param name="m">The method</param>
/// <returns>The name of the route, or null if no route is specified (or there isn't an HttpTrigger binding)</returns>
public static string? GetHttpRoute(this MethodDeclarationSyntax m)
/// <returns>The HttpTriggerBinding, or null if none exists</returns>
public static HttpTriggerBinding? GetHttpTriggerBinding(this MethodDeclarationSyntax m)
{
var httpTriggerAttribute = m.GetHttpTriggerAttribute();
return httpTriggerAttribute == null ? null : new HttpTriggerBinding(httpTriggerAttribute.GetHttpRoute(), httpTriggerAttribute.GetHttpOperations());
}
/// <summary>
/// Gets the HttpTrigger attribute on the parameters for this method if one exists
/// https://docs.microsoft.com/en-us/azure/azure-functions/functions-bindings-http-webhook-trigger
/// </summary>
/// <param name="m">The method</param>
/// <returns>The attribute if such a binding exists</returns>
public static AttributeSyntax? GetHttpTriggerAttribute(this MethodDeclarationSyntax m)
{
return m
.ParameterList
@@ -53,8 +66,18 @@ namespace Microsoft.SqlTools.ServiceLayer.AzureFunctions
p.AttributeLists // Get a list of all attributes on any of the parameters
.SelectMany(al => al.Attributes)
).Where(a => a.Name.ToString().Equals(HTTP_TRIGGER_ATTRIBUTE_NAME) // Find any HttpTrigger attributes
).FirstOrDefault() // Get the first one available - there should only ever be 0 or 1
?.ArgumentList // Get all the arguments for the attribute
).FirstOrDefault(); // Get the first one available - there should only ever be 0 or 1
}
/// <summary>
/// Gets the route from the HttpTrigger attribute
/// https://docs.microsoft.com/en-us/azure/azure-functions/functions-bindings-http-webhook-trigger?tabs=in-process%2Cfunctionsv2&pivots=programming-language-csharp#attributes
/// </summary>
/// <param name="m">The attribute</param>
/// <returns>The name of the route, or null if no route is specified (or there isn't an HttpTrigger binding)</returns>
public static string? GetHttpRoute(this AttributeSyntax a)
{
return a.ArgumentList
?.Arguments
.Where(a => a.ChildNodes().OfType<NameEqualsSyntax>().Where(nes => nes.Name.ToString().Equals(ROUTE_ARGUMENT_NAME)).Any()) // Find the Route argument - it should always be a named argument
.FirstOrDefault()
@@ -63,8 +86,22 @@ namespace Microsoft.SqlTools.ServiceLayer.AzureFunctions
.Where(le => le.Kind() != SyntaxKind.NullLiteralExpression) // Skip the null expressions so they aren't ToString()'d into "null"
.FirstOrDefault()
?.ToString()
.TrimStart('$') // Remove $ from interpolated string, since this will always be outside the quotes we can just trim
.Trim('\"'); // Trim off the quotes from the string value - additional quotes at the beginning and end aren't valid syntax so it's fine to trim
.TrimStringQuotes();
}
/// <summary>
/// Get the operations (methods) on an HttpTrigger attribute. These are string params arguments to the attribute
/// https://docs.microsoft.com/en-us/azure/azure-functions/functions-bindings-http-webhook-trigger?tabs=in-process%2Cfunctionsv2&pivots=programming-language-csharp#attributes
/// </summary>
/// <param name="a">The attribute</param>
/// <returns>The operations (methods) specified</returns>
public static string[]? GetHttpOperations(this AttributeSyntax a)
{
return a.ArgumentList
?.Arguments
.Where(a => a.Expression.Kind() == SyntaxKind.StringLiteralExpression && a.NameEquals == null) // Operations are string literals who don't have a name (Route is always a named param)
.Select(a => a.ToString().TrimStringQuotes().ToUpper()) // upper case for consistent naming
.ToArray();
}
/// <summary>
@@ -90,8 +127,19 @@ namespace Microsoft.SqlTools.ServiceLayer.AzureFunctions
?.Arguments
.FirstOrDefault() // The first argument is the function name
?.ToString()
.TrimStringQuotes() ?? "";
}
/// <summary>
/// Removes the quotes (and $ for interpolated strings) around a string literal
/// </summary>
/// <param name="s">The string</param>
/// <returns>The string without quotes</returns>
public static string TrimStringQuotes(this string s)
{
return s
.TrimStart('$') // Remove $ from interpolated string, since this will always be outside the quotes we can just trim
.Trim('\"') ?? ""; // Trim off the quotes from the string value - additional quotes at the beginning and end aren't valid syntax so it's fine to trim
.Trim('\"'); // Trim off the quotes from the string value - additional quotes at the beginning and end aren't valid syntax so it's fine to trim
}
/// <summary>

View File

@@ -22,17 +22,36 @@ namespace Microsoft.SqlTools.ServiceLayer.AzureFunctions.Contracts
/// <summary>
/// The name of the function
/// </summary>
public string Name { get; set; }
public string Name { get; }
/// <summary>
/// The route of the HttpTrigger binding if one exists on this function
/// The HttpTrigger binding if one is specified
/// </summary>
public string? Route { get; set; }
public HttpTriggerBinding? HttpTriggerBinding { get; }
public AzureFunction(string name, string? route)
public AzureFunction(string name, HttpTriggerBinding? httpTriggerBinding)
{
this.Name = name;
this.HttpTriggerBinding = httpTriggerBinding;
}
}
public class HttpTriggerBinding
{
/// <summary>
/// The route specified
/// </summary>
public string? Route { get; }
/// <summary>
/// The operations (methods) specified
/// </summary>
public string[]? Operations { get; }
public HttpTriggerBinding(string? route, string[]? operations)
{
this.Route = route;
this.Operations = operations;
}
}

View File

@@ -45,7 +45,10 @@ namespace Microsoft.SqlTools.ServiceLayer.AzureFunctions
// get all the method declarations with the FunctionName attribute
IEnumerable<MethodDeclarationSyntax> methodsWithFunctionAttributes = AzureFunctionsUtils.GetMethodsWithFunctionAttributes(root);
var azureFunctions = methodsWithFunctionAttributes.Select(m => new AzureFunction(m.GetFunctionName(), m.GetHttpRoute())).ToArray();
var azureFunctions = methodsWithFunctionAttributes.Select(m => new AzureFunction(
m.GetFunctionName(),
m.GetHttpTriggerBinding()))
.ToArray();
return new GetAzureFunctionsResult(azureFunctions);
}