Skip to content

Commit

Permalink
Annotate generated GetValue() with [NotNullIfNotNull]
Browse files Browse the repository at this point in the history
  • Loading branch information
dahlbyk committed Apr 22, 2024
1 parent c2008d3 commit 860871c
Show file tree
Hide file tree
Showing 9 changed files with 36 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.IO;
using Microsoft.CodeAnalysis;
using SourceGenerators;

Expand Down Expand Up @@ -36,6 +38,13 @@ public void Emit(SourceProductionContext context)
return;
}

if (ShouldEmitMethods(
MethodsToGen.ConfigBinder_GetValue_TypeOf_key_defaultValue |
MethodsToGen.ConfigBinder_GetValue_T_key_defaultValue))
{
AddSourceNullableAttributes(context);
}

_writer.WriteLine("""
// <auto-generated/>
Expand Down Expand Up @@ -96,6 +105,22 @@ private void EmitUsingStatements()
_writer.WriteLine($"using {@namespace};");
}
}

private static void AddSourceNullableAttributes(SourceProductionContext context)
{
using Stream stream = typeof(Emitter).Assembly
.GetManifestResourceStream(
"Microsoft.Extensions.Configuration.Binder.SourceGeneration.Resources.NullableAttributes.cs"
);

// Resource only exists for netstandard2.0
if (stream is null)
return;

using var reader = new StreamReader(stream);
string source = reader.ReadToEnd();
context.AddSource("NullableAttributes.cs", source);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ private void EmitGetValueMethods()
if (ShouldEmitMethods(MethodsToGen.ConfigBinder_GetValue_T_key_defaultValue))
{
EmitStartDefinition_Get_Or_GetValue_Overload(MethodsToGen.ConfigBinder_GetValue_T_key_defaultValue, documentation);
_writer.WriteLine("[return: global::System.Diagnostics.CodeAnalysis.NotNullIfNotNull(nameof(defaultValue))]");
_writer.WriteLine($"public static T? {Identifier.GetValue}<T>(this {Identifier.IConfiguration} {Identifier.configuration}, string {Identifier.key}, T {Identifier.defaultValue}) => " +
$"(T?)({expressionForGetValueCore}({Identifier.configuration}, typeof(T), {Identifier.key}) ?? {Identifier.defaultValue});");
}
Expand All @@ -87,6 +88,7 @@ private void EmitGetValueMethods()
if (ShouldEmitMethods(MethodsToGen.ConfigBinder_GetValue_TypeOf_key_defaultValue))
{
EmitStartDefinition_Get_Or_GetValue_Overload(MethodsToGen.ConfigBinder_GetValue_TypeOf_key_defaultValue, documentation);
_writer.WriteLine("[return: global::System.Diagnostics.CodeAnalysis.NotNullIfNotNull(nameof(defaultValue))]");
_writer.WriteLine($"public static object? {Identifier.GetValue}(this {Identifier.IConfiguration} {Identifier.configuration}, Type {Identifier.type}, string {Identifier.key}, object? {Identifier.defaultValue}) => " +
$"{expressionForGetValueCore}({Identifier.configuration}, {Identifier.type}, {Identifier.key}) ?? {Identifier.defaultValue};");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
</ItemGroup>

<ItemGroup Condition="'$(TargetFrameworkIdentifier)' == 'netstandard2.0'">
<Compile Include="$(CoreLibSharedDir)System\Diagnostics\CodeAnalysis\NullableAttributes.cs" Link="System.Private.CoreLib\System\Diagnostics\CodeAnalysis\NullableAttributes.cs" />
<EmbeddedResource Include="$(CoreLibSharedDir)System\Diagnostics\CodeAnalysis\NullableAttributes.cs" Link="Resources\NullableAttributes.cs" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration

/// <summary>Extracts the value with the specified key and converts it to the specified type.</summary>
[InterceptsLocation(@"src-0.cs", 16, 24)]
[return: global::System.Diagnostics.CodeAnalysis.NotNullIfNotNull(nameof(defaultValue))]
public static T? GetValue<T>(this IConfiguration configuration, string key, T defaultValue) => (T?)(BindingExtensions.GetValueCore(configuration, typeof(T), key) ?? defaultValue);

/// <summary>Extracts the value with the specified key and converts it to the specified type.</summary>
Expand All @@ -47,6 +48,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration

/// <summary>Extracts the value with the specified key and converts it to the specified type.</summary>
[InterceptsLocation(@"src-0.cs", 17, 24)]
[return: global::System.Diagnostics.CodeAnalysis.NotNullIfNotNull(nameof(defaultValue))]
public static object? GetValue(this IConfiguration configuration, Type type, string key, object? defaultValue) => BindingExtensions.GetValueCore(configuration, type, key) ?? defaultValue;
#endregion IConfiguration extensions.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
#region IConfiguration extensions.
/// <summary>Extracts the value with the specified key and converts it to the specified type.</summary>
[InterceptsLocation(@"src-0.cs", 12, 20)]
[return: global::System.Diagnostics.CodeAnalysis.NotNullIfNotNull(nameof(defaultValue))]
public static T? GetValue<T>(this IConfiguration configuration, string key, T defaultValue) => (T?)(BindingExtensions.GetValueCore(configuration, typeof(T), key) ?? defaultValue);
#endregion IConfiguration extensions.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
#region IConfiguration extensions.
/// <summary>Extracts the value with the specified key and converts it to the specified type.</summary>
[InterceptsLocation(@"src-0.cs", 11, 20)]
[return: global::System.Diagnostics.CodeAnalysis.NotNullIfNotNull(nameof(defaultValue))]
public static object? GetValue(this IConfiguration configuration, Type type, string key, object? defaultValue) => BindingExtensions.GetValueCore(configuration, type, key) ?? defaultValue;
#endregion IConfiguration extensions.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration

/// <summary>Extracts the value with the specified key and converts it to the specified type.</summary>
[InterceptsLocation(@"src-0.cs", 16, 24)]
[return: global::System.Diagnostics.CodeAnalysis.NotNullIfNotNull(nameof(defaultValue))]
public static T? GetValue<T>(this IConfiguration configuration, string key, T defaultValue) => (T?)(BindingExtensions.GetValueCore(configuration, typeof(T), key) ?? defaultValue);

/// <summary>Extracts the value with the specified key and converts it to the specified type.</summary>
Expand All @@ -47,6 +48,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration

/// <summary>Extracts the value with the specified key and converts it to the specified type.</summary>
[InterceptsLocation(@"src-0.cs", 17, 24)]
[return: global::System.Diagnostics.CodeAnalysis.NotNullIfNotNull(nameof(defaultValue))]
public static object? GetValue(this IConfiguration configuration, Type type, string key, object? defaultValue) => BindingExtensions.GetValueCore(configuration, type, key) ?? defaultValue;
#endregion IConfiguration extensions.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
#region IConfiguration extensions.
/// <summary>Extracts the value with the specified key and converts it to the specified type.</summary>
[InterceptsLocation(@"src-0.cs", 12, 20)]
[return: global::System.Diagnostics.CodeAnalysis.NotNullIfNotNull(nameof(defaultValue))]
public static T? GetValue<T>(this IConfiguration configuration, string key, T defaultValue) => (T?)(BindingExtensions.GetValueCore(configuration, typeof(T), key) ?? defaultValue);
#endregion IConfiguration extensions.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
#region IConfiguration extensions.
/// <summary>Extracts the value with the specified key and converts it to the specified type.</summary>
[InterceptsLocation(@"src-0.cs", 11, 20)]
[return: global::System.Diagnostics.CodeAnalysis.NotNullIfNotNull(nameof(defaultValue))]
public static object? GetValue(this IConfiguration configuration, Type type, string key, object? defaultValue) => BindingExtensions.GetValueCore(configuration, type, key) ?? defaultValue;
#endregion IConfiguration extensions.

Expand Down

0 comments on commit 860871c

Please sign in to comment.