Skip to content

Commit fe00d7c

Browse files
authored
Disable compiler warning CS0618 in DirectFunctionExecutor (#2952)
* Disable compiler warning CS0618 in DirectFunctionExecutor * Use SymbolEqualityComparer * fix: removed hardcoded newline character * chore: feedback
1 parent d26b46f commit fe00d7c

File tree

5 files changed

+129
-10
lines changed

5 files changed

+129
-10
lines changed

sdk/Sdk.Generators/FunctionExecutor/FunctionExecutorGenerator.Emitter.cs

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ private static string GetMethodBody(IEnumerable<ExecutableFunction> functions, b
158158
159159
if (string.Equals(context.FunctionDefinition.EntryPoint, "{{function.EntryPoint}}", StringComparison.Ordinal))
160160
{
161-
{{(fast ? EmitFastPath(function) : EmitSlowPath())}}
161+
{{(fast ? EmitFastPath(function) : EmitSlowPath())}}
162162
return;
163163
}
164164
""");
@@ -170,21 +170,22 @@ private static string GetMethodBody(IEnumerable<ExecutableFunction> functions, b
170170
private static string EmitFastPath(ExecutableFunction function)
171171
{
172172
var sb = new StringBuilder();
173-
173+
174174
if (!function.IsStatic)
175175
{
176176
sb.Append($"""
177-
var instanceType = types["{function.ParentFunctionClassName}"];
177+
var instanceType = types["{function.ParentFunctionClassName}"];
178178
var i = _functionActivator.CreateInstance(instanceType, context) as {function.ParentFunctionFullyQualifiedClassName};
179+
179180
""");
180181
}
181182

182-
sb.Append(!function.IsStatic
183-
? """
184-
185-
186-
"""
187-
: " ");
183+
if (function.IsObsolete)
184+
{
185+
sb.AppendLine("#pragma warning disable CS0618");
186+
}
187+
188+
sb.Append(" ");
188189

189190
if (function.IsReturnValueAssignable)
190191
{
@@ -210,13 +211,19 @@ private static string EmitFastPath(ExecutableFunction function)
210211
sb.Append(function.IsStatic
211212
? $"{function.ParentFunctionFullyQualifiedClassName}.{function.MethodName}({methodParamsStr});"
212213
: $"i.{function.MethodName}({methodParamsStr});");
214+
215+
if (function.IsObsolete)
216+
{
217+
sb.Append(Constants.NewLine);
218+
sb.Append("#pragma warning restore CS0618");
219+
}
213220

214221
return sb.ToString();
215222
}
216223

217224
private static string EmitSlowPath()
218225
{
219-
return " await _defaultExecutor.Value.ExecuteAsync(context);";
226+
return " await _defaultExecutor.Value.ExecuteAsync(context);";
220227
}
221228
}
222229
}

sdk/Sdk.Generators/FunctionExecutor/FunctionExecutorGenerator.ExecutableFunction.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,5 +63,10 @@ internal class ExecutableFunction
6363
/// ex: FooAssembly, Version=1.2.3.4, Culture=neutral, PublicKeyToken=9475d07f10cb09df
6464
/// </summary>
6565
internal string AssemblyIdentity { get; set; } = null!;
66+
67+
/// <summary>
68+
/// Gets or sets if the function is Obsolete.
69+
/// </summary>
70+
internal bool IsObsolete { get; set; }
6671
}
6772
}

sdk/Sdk.Generators/FunctionExecutor/FunctionExecutorGenerator.Parser.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ internal ICollection<ExecutableFunction> GetFunctions(IEnumerable<IMethodSymbol>
4242
var defaultFormatClassName = method.ContainingSymbol.ToDisplayString();
4343
var fullyQualifiedClassName = method.ContainingSymbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
4444

45+
var isObsolete = method.GetAttributes()
46+
.Any(attr => SymbolEqualityComparer.Default.Equals(attr.AttributeClass, _knownTypes.ObsoleteAttr));
47+
4548
var function = new ExecutableFunction
4649
{
4750
EntryPoint = $"{defaultFormatClassName}.{method.Name}",
@@ -54,6 +57,7 @@ internal ICollection<ExecutableFunction> GetFunctions(IEnumerable<IMethodSymbol>
5457
ParentFunctionFullyQualifiedClassName = fullyQualifiedClassName,
5558
Visibility = method.GetVisibility(),
5659
AssemblyIdentity = method.ContainingAssembly.Identity.GetDisplayName(),
60+
IsObsolete = isObsolete,
5761
};
5862

5963
functionList.Add(function);

sdk/Sdk.Generators/KnownTypes.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ internal readonly struct KnownTypes
2727
private readonly Lazy<INamedTypeSymbol> _readOnlyMemoryOfBytes;
2828
private readonly Lazy<INamedTypeSymbol> _lookupGeneric;
2929
private readonly Lazy<INamedTypeSymbol> _dictionaryGeneric;
30+
private readonly Lazy<INamedTypeSymbol> _obsoleteAttr;
3031

3132
internal KnownTypes(Compilation compilation)
3233
{
@@ -44,6 +45,7 @@ internal KnownTypes(Compilation compilation)
4445
_readOnlyMemoryOfBytes = new Lazy<INamedTypeSymbol>(() => compilation.GetTypeByMetadataName(typeof(ReadOnlyMemory<byte>).FullName)!);
4546
_lookupGeneric = new Lazy<INamedTypeSymbol>(() => compilation.GetTypeByMetadataName(typeof(ILookup<,>).FullName)!);
4647
_dictionaryGeneric = new Lazy<INamedTypeSymbol>(() => compilation.GetTypeByMetadataName(typeof(IDictionary<,>).FullName)!);
48+
_obsoleteAttr = new Lazy<INamedTypeSymbol>(() => compilation.GetTypeByMetadataName(typeof(ObsoleteAttribute).FullName)!);
4749
}
4850

4951
public INamedTypeSymbol TaskType { get => _taskType.Value; }
@@ -73,5 +75,7 @@ internal KnownTypes(Compilation compilation)
7375
public INamedTypeSymbol LookupGeneric { get => _lookupGeneric.Value; }
7476

7577
public INamedTypeSymbol DictionaryGeneric { get => _dictionaryGeneric.Value; }
78+
79+
public INamedTypeSymbol ObsoleteAttr { get => _obsoleteAttr.Value; }
7680
}
7781
}

test/Sdk.Generator.Tests/FunctionExecutor/FunctionExecutorGeneratorTests.cs

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -816,5 +816,104 @@ public static IHostBuilder ConfigureGeneratedFunctionExecutor(this IHostBuilder
816816
}
817817
""";
818818
}
819+
820+
[Theory]
821+
[InlineData(LanguageVersion.CSharp7_3)]
822+
[InlineData(LanguageVersion.CSharp8)]
823+
[InlineData(LanguageVersion.CSharp9)]
824+
[InlineData(LanguageVersion.CSharp10)]
825+
[InlineData(LanguageVersion.CSharp11)]
826+
[InlineData(LanguageVersion.Latest)]
827+
public async Task ObsoleteFunction(LanguageVersion languageVersion)
828+
{
829+
const string inputSourceCode = @"
830+
using System;
831+
using System.Threading.Tasks;
832+
using Microsoft.Extensions.Hosting;
833+
using Azure.Storage.Queues.Models;
834+
using Microsoft.Azure.Functions.Worker;
835+
using Microsoft.Azure.Functions.Worker.Http;
836+
using Microsoft.Extensions.Logging;
837+
namespace TestProject
838+
{
839+
public class TestProject
840+
{
841+
[Function(""FunctionA"")]
842+
[Obsolete(""Do not use"")]
843+
public HttpResponseData Foo([HttpTrigger(AuthorizationLevel.User, ""get"")] HttpRequestData r, FunctionContext c)
844+
{
845+
return r.CreateResponse(System.Net.HttpStatusCode.OK);
846+
}
847+
848+
[Function(""FunctionB"")]
849+
[Obsolete(""Do not use"")]
850+
public static HttpResponseData FooStatic([HttpTrigger(AuthorizationLevel.User, ""get"")] HttpRequestData r, FunctionContext c)
851+
{
852+
return r.CreateResponse(System.Net.HttpStatusCode.OK);
853+
}
854+
}
855+
}
856+
";
857+
var expectedOutput = $@"// <auto-generated/>
858+
using System;
859+
using System.Threading.Tasks;
860+
using System.Collections.Generic;
861+
using Microsoft.Extensions.Hosting;
862+
using Microsoft.Extensions.DependencyInjection;
863+
using Microsoft.Azure.Functions.Worker;
864+
using Microsoft.Azure.Functions.Worker.Context.Features;
865+
using Microsoft.Azure.Functions.Worker.Invocation;
866+
namespace TestProject
867+
{{
868+
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)]
869+
{Constants.GeneratedCodeAttribute}
870+
internal class DirectFunctionExecutor : global::Microsoft.Azure.Functions.Worker.Invocation.IFunctionExecutor
871+
{{
872+
private readonly global::Microsoft.Azure.Functions.Worker.IFunctionActivator _functionActivator;
873+
private readonly Dictionary<string, Type> types = new Dictionary<string, Type>()
874+
{{
875+
{{ ""TestProject.TestProject"", Type.GetType(""TestProject.TestProject, TestProject, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"") }}
876+
}};
877+
878+
public DirectFunctionExecutor(global::Microsoft.Azure.Functions.Worker.IFunctionActivator functionActivator)
879+
{{
880+
_functionActivator = functionActivator ?? throw new global::System.ArgumentNullException(nameof(functionActivator));
881+
}}
882+
883+
/// <inheritdoc/>
884+
public async global::System.Threading.Tasks.ValueTask ExecuteAsync(global::Microsoft.Azure.Functions.Worker.FunctionContext context)
885+
{{
886+
var inputBindingFeature = context.Features.Get<global::Microsoft.Azure.Functions.Worker.Context.Features.IFunctionInputBindingFeature>();
887+
var inputBindingResult = await inputBindingFeature.BindFunctionInputAsync(context);
888+
var inputArguments = inputBindingResult.Values;
889+
890+
if (string.Equals(context.FunctionDefinition.EntryPoint, ""TestProject.TestProject.Foo"", StringComparison.Ordinal))
891+
{{
892+
var instanceType = types[""TestProject.TestProject""];
893+
var i = _functionActivator.CreateInstance(instanceType, context) as global::TestProject.TestProject;
894+
#pragma warning disable CS0618
895+
context.GetInvocationResult().Value = i.Foo((global::Microsoft.Azure.Functions.Worker.Http.HttpRequestData)inputArguments[0], (global::Microsoft.Azure.Functions.Worker.FunctionContext)inputArguments[1]);
896+
#pragma warning restore CS0618
897+
return;
898+
}}
899+
if (string.Equals(context.FunctionDefinition.EntryPoint, ""TestProject.TestProject.FooStatic"", StringComparison.Ordinal))
900+
{{
901+
#pragma warning disable CS0618
902+
context.GetInvocationResult().Value = global::TestProject.TestProject.FooStatic((global::Microsoft.Azure.Functions.Worker.Http.HttpRequestData)inputArguments[0], (global::Microsoft.Azure.Functions.Worker.FunctionContext)inputArguments[1]);
903+
#pragma warning restore CS0618
904+
return;
905+
}}
906+
}}
907+
}}
908+
{GetExpectedExtensionMethodCode()}
909+
}}".Replace("'", "\"");
910+
911+
await TestHelpers.RunTestAsync<Worker.Sdk.Generators.FunctionExecutorGenerator>(
912+
_referencedAssemblies,
913+
inputSourceCode,
914+
Constants.FileNames.GeneratedFunctionExecutor,
915+
expectedOutput,
916+
languageVersion: languageVersion);
917+
}
819918
}
820919
}

0 commit comments

Comments
 (0)