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 28, 2024
1 parent 4007c29 commit 746a4ec
Show file tree
Hide file tree
Showing 8 changed files with 24 additions and 0 deletions.
Expand Up @@ -15,6 +15,7 @@ private sealed partial class Emitter
private readonly TypeIndex _typeIndex;
private readonly bool _emitEnumParseMethod;
private readonly bool _emitGenericParseEnum;
private readonly bool _emitNotNullIfNotNull;
private readonly bool _emitThrowIfNullMethod;

private readonly SourceWriter _writer = new();
Expand All @@ -26,6 +27,7 @@ public Emitter(SourceGenerationSpec sourceGenSpec)
_typeIndex = new TypeIndex(sourceGenSpec.ConfigTypes);
_emitEnumParseMethod = sourceGenSpec.EmitEnumParseMethod;
_emitGenericParseEnum = sourceGenSpec.EmitGenericParseEnum;
_emitNotNullIfNotNull = sourceGenSpec.EmitNotNullIfNotNull;
_emitThrowIfNullMethod = sourceGenSpec.EmitThrowIfNullMethod;
}

Expand Down
Expand Up @@ -57,6 +57,7 @@ internal sealed partial class Parser(CompilationData compilationData)
ConfigTypes = _createdTypeSpecs.Values.OrderBy(s => s.TypeRef.FullyQualifiedName).ToImmutableEquatableArray(),
EmitEnumParseMethod = _emitEnumParseMethod,
EmitGenericParseEnum = _emitGenericParseEnum,
EmitNotNullIfNotNull = _typeSymbols.NotNullIfNotNullAttribute is not null,
EmitThrowIfNullMethod = IsThrowIfNullMethodToBeEmitted()
};
}
Expand Down
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);
EmitNotNullIfNotNull(Identifier.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,11 +88,22 @@ private void EmitGetValueMethods()
if (ShouldEmitMethods(MethodsToGen.ConfigBinder_GetValue_TypeOf_key_defaultValue))
{
EmitStartDefinition_Get_Or_GetValue_Overload(MethodsToGen.ConfigBinder_GetValue_TypeOf_key_defaultValue, documentation);
EmitNotNullIfNotNull(Identifier.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};");
}
}

private void EmitNotNullIfNotNull(string parameterName)
{
if (!_emitNotNullIfNotNull)
{
return;
}

_writer.WriteLine($"[return: global::System.Diagnostics.CodeAnalysis.NotNullIfNotNull(nameof({parameterName}))]");
}

private void EmitBindMethods_ConfigurationBinder()
{
if (!ShouldEmitMethods(MethodsToGen.ConfigBinder_Bind))
Expand Down
Expand Up @@ -64,6 +64,7 @@ internal sealed class KnownTypeSymbols
public INamedTypeSymbol? MemberInfo { get; }
public INamedTypeSymbol? ParameterInfo { get; }
public INamedTypeSymbol? Delegate { get; }
public INamedTypeSymbol? NotNullIfNotNullAttribute { get; }

public KnownTypeSymbols(CSharpCompilation compilation)
{
Expand Down Expand Up @@ -132,6 +133,9 @@ public KnownTypeSymbols(CSharpCompilation compilation)
IntPtr = Compilation.GetSpecialType(SpecialType.System_IntPtr);
UIntPtr = Compilation.GetSpecialType(SpecialType.System_UIntPtr);
Delegate = Compilation.GetSpecialType(SpecialType.System_Delegate);

// Only generate nullable attributes if available
NotNullIfNotNullAttribute = compilation.GetBestTypeByMetadataName("System.Diagnostics.CodeAnalysis.NotNullIfNotNullAttribute");
}
}
}
Expand Up @@ -12,6 +12,7 @@ public sealed record SourceGenerationSpec
public required ImmutableEquatableArray<TypeSpec> ConfigTypes { get; init; }
public required bool EmitEnumParseMethod { get; set; }
public required bool EmitGenericParseEnum { get; set; }
public required bool EmitNotNullIfNotNull { get; set; }
public required bool EmitThrowIfNullMethod { get; set; }
}
}
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
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
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 746a4ec

Please sign in to comment.