Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Options validation source generator #87587

Merged
merged 13 commits into from
Jun 20, 2023
40 changes: 40 additions & 0 deletions src/libraries/Common/src/System/ThrowHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,46 @@ internal static partial class ThrowHelper
[DoesNotReturn]
#endif
private static void Throw(string? paramName) => throw new ArgumentNullException(paramName);

/// <summary>
/// Throws either an <see cref="System.ArgumentNullException"/> or an <see cref="System.ArgumentException"/>
/// if the specified string is <see langword="null"/> or whitespace respectively.
/// </summary>
/// <param name="argument">String to be checked for <see langword="null"/> or whitespace.</param>
/// <param name="paramName">The name of the parameter being checked.</param>
/// <returns>The original value of <paramref name="argument"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#if NETCOREAPP3_0_OR_GREATER
[return: NotNull]
#endif
public static string IfNullOrWhitespace(
#if NETCOREAPP3_0_OR_GREATER
[NotNull]
#endif
string? argument,
[CallerArgumentExpression(nameof(argument))] string paramName = "")
{
#if !NETCOREAPP3_1_OR_GREATER
if (argument == null)
{
throw new ArgumentNullException(paramName);
}
#endif

if (string.IsNullOrWhiteSpace(argument))
{
if (argument == null)
{
throw new ArgumentNullException(paramName);
}
else
{
throw new ArgumentException(paramName, "Argument is whitespace");
}
}

return argument;
}
}
}

Expand Down
95 changes: 95 additions & 0 deletions src/libraries/Microsoft.Extensions.Options/gen/DiagDescriptors.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using Microsoft.CodeAnalysis;
using System;

namespace Microsoft.Extensions.Options.Generators
{
internal sealed class DiagDescriptors : DiagDescriptorsBase
{
private const string Category = "Microsoft.Extensions.Options.SourceGeneration";

public static DiagnosticDescriptor CantUseWithGenericTypes { get; } = Make(
id: "SYSLIB1201",
tarekgh marked this conversation as resolved.
Show resolved Hide resolved
title: SR.CantUseWithGenericTypesTitle,
messageFormat: SR.CantUseWithGenericTypesMessage,
category: Category);

public static DiagnosticDescriptor NoEligibleMember { get; } = Make(
id: "SYSLIB1202",
title: SR.NoEligibleMemberTitle,
messageFormat: SR.NoEligibleMemberMessage,
category: Category,
defaultSeverity: DiagnosticSeverity.Warning);

public static DiagnosticDescriptor NoEligibleMembersFromValidator { get; } = Make(
id: "SYSLIB1203",
title: SR.NoEligibleMembersFromValidatorTitle,
messageFormat: SR.NoEligibleMembersFromValidatorMessage,
category: Category,
defaultSeverity: DiagnosticSeverity.Warning);

public static DiagnosticDescriptor DoesntImplementIValidateOptions { get; } = Make(
id: "SYSLIB1204",
title: SR.DoesntImplementIValidateOptionsTitle,
messageFormat: SR.DoesntImplementIValidateOptionsMessage,
category: Category);

public static DiagnosticDescriptor AlreadyImplementsValidateMethod { get; } = Make(
id: "SYSLIB1205",
title: SR.AlreadyImplementsValidateMethodTitle,
messageFormat: SR.AlreadyImplementsValidateMethodMessage,
category: Category);

public static DiagnosticDescriptor MemberIsInaccessible { get; } = Make(
id: "SYSLIB1206",
title: SR.MemberIsInaccessibleTitle,
messageFormat: SR.MemberIsInaccessibleMessage,
category: Category);

public static DiagnosticDescriptor NotEnumerableType { get; } = Make(
id: "SYSLIB1207",
title: SR.NotEnumerableTypeTitle,
messageFormat: SR.NotEnumerableTypeMessage,
category: Category);

public static DiagnosticDescriptor ValidatorsNeedSimpleConstructor { get; } = Make(
id: "SYSLIB1208",
title: SR.ValidatorsNeedSimpleConstructorTitle,
messageFormat: SR.ValidatorsNeedSimpleConstructorMessage,
category: Category);

public static DiagnosticDescriptor CantBeStaticClass { get; } = Make(
id: "SYSLIB1209",
title: SR.CantBeStaticClassTitle,
messageFormat: SR.CantBeStaticClassMessage,
category: Category);

public static DiagnosticDescriptor NullValidatorType { get; } = Make(
id: "SYSLIB1210",
title: SR.NullValidatorTypeTitle,
messageFormat: SR.NullValidatorTypeMessage,
category: Category);

public static DiagnosticDescriptor CircularTypeReferences { get; } = Make(
id: "SYSLIB1211",
title: SR.CircularTypeReferencesTitle,
messageFormat: SR.CircularTypeReferencesMessage,
category: Category);

public static DiagnosticDescriptor PotentiallyMissingTransitiveValidation { get; } = Make(
id: "SYSLIB1212",
title: SR.PotentiallyMissingTransitiveValidationTitle,
messageFormat: SR.PotentiallyMissingTransitiveValidationMessage,
category: Category,
defaultSeverity: DiagnosticSeverity.Warning);

public static DiagnosticDescriptor PotentiallyMissingEnumerableValidation { get; } = Make(
id: "SYSLIB1213",
title: SR.PotentiallyMissingEnumerableValidationTitle,
messageFormat: SR.PotentiallyMissingEnumerableValidationMessage,
category: Category,
defaultSeverity: DiagnosticSeverity.Warning);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// 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 Microsoft.CodeAnalysis;

namespace Microsoft.Extensions.Options.Generators
{
#pragma warning disable CA1052 // Static holder types should be Static or NotInheritable
internal class DiagDescriptorsBase
#pragma warning restore CA1052
{
protected static DiagnosticDescriptor Make(
string id,
string title,
string messageFormat,
string category,
DiagnosticSeverity defaultSeverity = DiagnosticSeverity.Error,
bool isEnabledByDefault = true)
{
return new(
id,
title,
messageFormat,
category,
defaultSeverity,
isEnabledByDefault);
}
}
}