mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-02-16 10:58:30 -05:00
Add error for sql bindings when .net 5 (#1259)
* add error for sql bindings when .net 5 * add test * cleanup linq stuff and move out common code
This commit is contained in:
@@ -23,8 +23,6 @@ namespace Microsoft.SqlTools.ServiceLayer.AzureFunctions
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
class AddSqlBindingOperation
|
class AddSqlBindingOperation
|
||||||
{
|
{
|
||||||
const string functionAttributeText = "FunctionName";
|
|
||||||
|
|
||||||
public AddSqlBindingParams Parameters { get; }
|
public AddSqlBindingParams Parameters { get; }
|
||||||
|
|
||||||
public AddSqlBindingOperation(AddSqlBindingParams parameters)
|
public AddSqlBindingOperation(AddSqlBindingParams parameters)
|
||||||
@@ -43,12 +41,10 @@ namespace Microsoft.SqlTools.ServiceLayer.AzureFunctions
|
|||||||
CompilationUnitSyntax root = tree.GetCompilationUnitRoot();
|
CompilationUnitSyntax root = tree.GetCompilationUnitRoot();
|
||||||
|
|
||||||
// look for Azure Function to update
|
// look for Azure Function to update
|
||||||
IEnumerable<MethodDeclarationSyntax> azureFunctionMethods = from methodDeclaration in root.DescendantNodes().OfType<MethodDeclarationSyntax>()
|
IEnumerable<MethodDeclarationSyntax> azureFunctionMethods = AzureFunctionsUtils.GetMethodsWithFunctionAttributes(root);
|
||||||
where methodDeclaration.AttributeLists.Count > 0
|
IEnumerable<MethodDeclarationSyntax> matchingMethods = azureFunctionMethods.Where(md => md.AttributeLists.Where(a => a.Attributes.Where(attr => attr.ArgumentList.Arguments.First().ToString().Equals($"\"{Parameters.functionName}\"")).Any()).Any());
|
||||||
where methodDeclaration.AttributeLists.Where(a => a.Attributes.Where(attr => attr.Name.ToString().Contains(functionAttributeText) && attr.ArgumentList.Arguments.First().ToString().Equals($"\"{Parameters.functionName}\"")).Count() == 1).Count() == 1
|
|
||||||
select methodDeclaration;
|
|
||||||
|
|
||||||
if (azureFunctionMethods.Count() == 0)
|
if (matchingMethods.Count() == 0)
|
||||||
{
|
{
|
||||||
return new ResultStatus()
|
return new ResultStatus()
|
||||||
{
|
{
|
||||||
@@ -56,7 +52,7 @@ namespace Microsoft.SqlTools.ServiceLayer.AzureFunctions
|
|||||||
ErrorMessage = SR.CouldntFindAzureFunction(Parameters.functionName, Parameters.filePath)
|
ErrorMessage = SR.CouldntFindAzureFunction(Parameters.functionName, Parameters.filePath)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
else if (azureFunctionMethods.Count() > 1)
|
else if (matchingMethods.Count() > 1)
|
||||||
{
|
{
|
||||||
return new ResultStatus()
|
return new ResultStatus()
|
||||||
{
|
{
|
||||||
@@ -65,7 +61,7 @@ namespace Microsoft.SqlTools.ServiceLayer.AzureFunctions
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
MethodDeclarationSyntax azureFunction = azureFunctionMethods.First();
|
MethodDeclarationSyntax azureFunction = matchingMethods.First();
|
||||||
var newParam = this.Parameters.bindingType == BindingType.input ? this.GenerateInputBinding() : this.GenerateOutputBinding();
|
var newParam = this.Parameters.bindingType == BindingType.input ? this.GenerateInputBinding() : this.GenerateOutputBinding();
|
||||||
|
|
||||||
// Generate updated method with the new parameter
|
// Generate updated method with the new parameter
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Microsoft.SqlTools.ServiceLayer.AzureFunctions
|
||||||
|
{
|
||||||
|
internal static class AzureFunctionsUtils
|
||||||
|
{
|
||||||
|
public const string functionAttributeText = "FunctionName";
|
||||||
|
public const string net5FunctionAttributeText = "Function";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets all the methods in the syntax tree with an Azure Function attribute
|
||||||
|
/// </summary>
|
||||||
|
public static IEnumerable<MethodDeclarationSyntax> GetMethodsWithFunctionAttributes(CompilationUnitSyntax root)
|
||||||
|
{
|
||||||
|
// Look for Azure Functions in the file
|
||||||
|
// Get all method declarations
|
||||||
|
IEnumerable<MethodDeclarationSyntax> methodDeclarations = root.DescendantNodes().OfType<MethodDeclarationSyntax>();
|
||||||
|
|
||||||
|
// .NET 5 is not currently supported for sql bindings, so an error should be returned if this file has .NET 5 style Azure Functions
|
||||||
|
if (HasNet5StyleAzureFunctions(methodDeclarations))
|
||||||
|
{
|
||||||
|
throw new Exception(SR.SqlBindingsNet5NotSupported);
|
||||||
|
}
|
||||||
|
|
||||||
|
// get all the method declarations with the FunctionName attribute
|
||||||
|
IEnumerable<MethodDeclarationSyntax> methodsWithFunctionAttributes = methodDeclarations.Where(md => md.AttributeLists.Where(a => a.Attributes.Where(attr => attr.Name.ToString().Equals(functionAttributeText)).Any()).Any());
|
||||||
|
|
||||||
|
return methodsWithFunctionAttributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if any of the method declarations have .NET 5 style Azure Function attributes
|
||||||
|
/// .NET 5 AFs use the Function attribute, while .NET 3.1 AFs use FunctionName attritube
|
||||||
|
/// </summary>
|
||||||
|
public static bool HasNet5StyleAzureFunctions(IEnumerable<MethodDeclarationSyntax> methodDeclarations)
|
||||||
|
{
|
||||||
|
// get all the method declarations with the Function attribute
|
||||||
|
return methodDeclarations.Any(md => md.AttributeLists.Any(al => al.Attributes.Any(attr => attr.Name.ToString().Equals(net5FunctionAttributeText))));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -21,8 +21,6 @@ namespace Microsoft.SqlTools.ServiceLayer.AzureFunctions
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
class GetAzureFunctionsOperation
|
class GetAzureFunctionsOperation
|
||||||
{
|
{
|
||||||
const string functionAttributeText = "FunctionName";
|
|
||||||
|
|
||||||
public GetAzureFunctionsParams Parameters { get; }
|
public GetAzureFunctionsParams Parameters { get; }
|
||||||
|
|
||||||
public GetAzureFunctionsOperation(GetAzureFunctionsParams parameters)
|
public GetAzureFunctionsOperation(GetAzureFunctionsParams parameters)
|
||||||
@@ -44,15 +42,11 @@ namespace Microsoft.SqlTools.ServiceLayer.AzureFunctions
|
|||||||
SyntaxTree tree = CSharpSyntaxTree.ParseText(text);
|
SyntaxTree tree = CSharpSyntaxTree.ParseText(text);
|
||||||
CompilationUnitSyntax root = tree.GetCompilationUnitRoot();
|
CompilationUnitSyntax root = tree.GetCompilationUnitRoot();
|
||||||
|
|
||||||
// Look for Azure Functions in the file
|
|
||||||
// Get all method declarations
|
|
||||||
IEnumerable<MethodDeclarationSyntax> methodDeclarations = root.DescendantNodes().OfType<MethodDeclarationSyntax>();
|
|
||||||
|
|
||||||
// get all the method declarations with the FunctionName attribute
|
// get all the method declarations with the FunctionName attribute
|
||||||
IEnumerable<MethodDeclarationSyntax> methodsWithFunctionAttributes = methodDeclarations.Where(md => md.AttributeLists.Count > 0).Where(md => md.AttributeLists.Where(a => a.Attributes.Where(attr => attr.Name.ToString().Contains(functionAttributeText)).Count() == 1).Count() == 1);
|
IEnumerable<MethodDeclarationSyntax> methodsWithFunctionAttributes = AzureFunctionsUtils.GetMethodsWithFunctionAttributes(root);
|
||||||
|
|
||||||
// Get FunctionName attributes
|
// Get FunctionName attributes
|
||||||
IEnumerable<AttributeSyntax> functionNameAttributes = methodsWithFunctionAttributes.Select(md => md.AttributeLists.Select(a => a.Attributes.Where(attr => attr.Name.ToString().Contains(functionAttributeText)).First()).First());
|
IEnumerable<AttributeSyntax> functionNameAttributes = methodsWithFunctionAttributes.Select(md => md.AttributeLists.Select(a => a.Attributes.Where(attr => attr.Name.ToString().Equals(AzureFunctionsUtils.functionAttributeText)).First()).First());
|
||||||
|
|
||||||
// Get the function names in the FunctionName attributes
|
// Get the function names in the FunctionName attributes
|
||||||
IEnumerable<AttributeArgumentSyntax> nameArgs = functionNameAttributes.Select(a => a.ArgumentList.Arguments.First());
|
IEnumerable<AttributeArgumentSyntax> nameArgs = functionNameAttributes.Select(a => a.ArgumentList.Arguments.First());
|
||||||
|
|||||||
@@ -3053,6 +3053,14 @@ namespace Microsoft.SqlTools.ServiceLayer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string SqlBindingsNet5NotSupported
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Keys.GetString(Keys.SqlBindingsNet5NotSupported);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static string ConnectionServiceListDbErrorNotConnected(string uri)
|
public static string ConnectionServiceListDbErrorNotConnected(string uri)
|
||||||
{
|
{
|
||||||
return Keys.GetString(Keys.ConnectionServiceListDbErrorNotConnected, uri);
|
return Keys.GetString(Keys.ConnectionServiceListDbErrorNotConnected, uri);
|
||||||
@@ -4571,6 +4579,9 @@ namespace Microsoft.SqlTools.ServiceLayer
|
|||||||
public const string MoreThanOneAzureFunctionWithName = "MoreThanOneAzureFunctionWithName";
|
public const string MoreThanOneAzureFunctionWithName = "MoreThanOneAzureFunctionWithName";
|
||||||
|
|
||||||
|
|
||||||
|
public const string SqlBindingsNet5NotSupported = "SqlBindingsNet5NotSupported";
|
||||||
|
|
||||||
|
|
||||||
private Keys()
|
private Keys()
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
|||||||
@@ -1864,4 +1864,8 @@
|
|||||||
<comment>.
|
<comment>.
|
||||||
Parameters: 0 - functionName (string), 1 - fileName (string) </comment>
|
Parameters: 0 - functionName (string), 1 - fileName (string) </comment>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SqlBindingsNet5NotSupported" xml:space="preserve">
|
||||||
|
<value>Adding SQL bindings is not supported for .NET 5</value>
|
||||||
|
<comment></comment>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|||||||
@@ -853,4 +853,5 @@ SqlAssessmentUnsuppoertedEdition(int editionCode) = Unsupported engine edition {
|
|||||||
############################################################################
|
############################################################################
|
||||||
# Azure Functions
|
# Azure Functions
|
||||||
CouldntFindAzureFunction(string functionName, string fileName) = Couldn't find Azure function with FunctionName '{0}' in {1}
|
CouldntFindAzureFunction(string functionName, string fileName) = Couldn't find Azure function with FunctionName '{0}' in {1}
|
||||||
MoreThanOneAzureFunctionWithName(string functionName, string fileName) = More than one Azure function found with the FunctionName '{0}' in {1}
|
MoreThanOneAzureFunctionWithName(string functionName, string fileName) = More than one Azure function found with the FunctionName '{0}' in {1}
|
||||||
|
SqlBindingsNet5NotSupported = Adding SQL bindings is not supported for .NET 5
|
||||||
@@ -2173,6 +2173,11 @@
|
|||||||
<note>.
|
<note>.
|
||||||
Parameters: 0 - functionName (string), 1 - fileName (string) </note>
|
Parameters: 0 - functionName (string), 1 - fileName (string) </note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="SqlBindingsNet5NotSupported">
|
||||||
|
<source>Adding SQL bindings is not supported for .NET 5</source>
|
||||||
|
<target state="new">Adding SQL bindings is not supported for .NET 5</target>
|
||||||
|
<note></note>
|
||||||
|
</trans-unit>
|
||||||
</body>
|
</body>
|
||||||
</file>
|
</file>
|
||||||
</xliff>
|
</xliff>
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Net;
|
||||||
|
using Microsoft.Azure.Functions.Worker;
|
||||||
|
using Microsoft.Azure.Functions.Worker.Http;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
namespace Company.Function
|
||||||
|
{
|
||||||
|
public static class HttpTrigger1
|
||||||
|
{
|
||||||
|
[Function("HttpTrigger1")]
|
||||||
|
public static HttpResponseData Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequestData req,
|
||||||
|
FunctionContext executionContext)
|
||||||
|
{
|
||||||
|
var logger = executionContext.GetLogger("HttpTrigger1");
|
||||||
|
logger.LogInformation("C# HTTP trigger function processed a request.");
|
||||||
|
|
||||||
|
var response = req.CreateResponse(HttpStatusCode.OK);
|
||||||
|
response.Headers.Add("Content-Type", "text/plain; charset=utf-8");
|
||||||
|
|
||||||
|
response.WriteString("Welcome to Azure Functions!");
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -165,7 +165,6 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.AzureFunctions
|
|||||||
string testFile = Path.Join(Path.GetTempPath(), $"NoAzureFunctions-{DateTime.Now.ToString("yyyy - dd - MM--HH - mm - ss")}.cs");
|
string testFile = Path.Join(Path.GetTempPath(), $"NoAzureFunctions-{DateTime.Now.ToString("yyyy - dd - MM--HH - mm - ss")}.cs");
|
||||||
FileStream fstream = File.Create(testFile);
|
FileStream fstream = File.Create(testFile);
|
||||||
fstream.Close();
|
fstream.Close();
|
||||||
|
|
||||||
GetAzureFunctionsParams parameters = new GetAzureFunctionsParams
|
GetAzureFunctionsParams parameters = new GetAzureFunctionsParams
|
||||||
{
|
{
|
||||||
filePath = testFile
|
filePath = testFile
|
||||||
@@ -178,5 +177,24 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.AzureFunctions
|
|||||||
Assert.Null(result.ErrorMessage);
|
Assert.Null(result.ErrorMessage);
|
||||||
Assert.AreEqual(0, result.azureFunctions.Length);
|
Assert.AreEqual(0, result.azureFunctions.Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Verify there are no errors when a file doesn't have any Azure functions
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void GetAzureFunctionsNet5()
|
||||||
|
{
|
||||||
|
string testFile = Path.Join(testAzureFunctionsFolder, "AzureFunctionsNet5.cs");
|
||||||
|
|
||||||
|
GetAzureFunctionsParams parameters = new GetAzureFunctionsParams
|
||||||
|
{
|
||||||
|
filePath = testFile
|
||||||
|
};
|
||||||
|
|
||||||
|
GetAzureFunctionsOperation operation = new GetAzureFunctionsOperation(parameters);
|
||||||
|
|
||||||
|
Exception ex = Assert.Throws<Exception>(() => { operation.GetAzureFunctions(); });
|
||||||
|
Assert.AreEqual(SR.SqlBindingsNet5NotSupported, ex.Message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,6 +43,7 @@
|
|||||||
<Compile Remove="AzureFunctions\AzureFunctionTestFiles\AzureFunctionsMultipleSameFunction.cs" />
|
<Compile Remove="AzureFunctions\AzureFunctionTestFiles\AzureFunctionsMultipleSameFunction.cs" />
|
||||||
<Compile Remove="AzureFunctions\AzureFunctionTestFiles\AzureFunctionsNoBindings.cs" />
|
<Compile Remove="AzureFunctions\AzureFunctionTestFiles\AzureFunctionsNoBindings.cs" />
|
||||||
<Compile Remove="AzureFunctions\AzureFunctionTestFiles\AzureFunctionsOutputBinding.cs" />
|
<Compile Remove="AzureFunctions\AzureFunctionTestFiles\AzureFunctionsOutputBinding.cs" />
|
||||||
|
<Compile Remove="AzureFunctions\AzureFunctionTestFiles\AzureFunctionsNet5.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Folder Include="DacFx\Dacpacs\" />
|
<Folder Include="DacFx\Dacpacs\" />
|
||||||
|
|||||||
Reference in New Issue
Block a user