Skip to content

Commit

Permalink
Update binder gen parser to issue diagnostics for invalid input types (
Browse files Browse the repository at this point in the history
…dotnet#86856)

* Update binder gen parser to issue diagnostics for invalid input types

* Address feedback; tests for more invalid types; fix failing CI test
  • Loading branch information
layomia authored Jun 1, 2023
1 parent 9c4d51c commit ac5febd
Show file tree
Hide file tree
Showing 28 changed files with 629 additions and 149 deletions.
4 changes: 2 additions & 2 deletions docs/project/list-of-diagnostics.md
Original file line number Diff line number Diff line change
Expand Up @@ -219,8 +219,8 @@ The diagnostic id values reserved for .NET Libraries analyzer warnings are `SYSL
| __`SYSLIB1100`__ | Configuration binding generator: type is not supported. |
| __`SYSLIB1101`__ | Configuration binding generator: property on type is not supported. |
| __`SYSLIB1102`__ | Configuration binding generator: project's language version must be at least C# 11.|
| __`SYSLIB1103`__ | *_`SYSLIB1100`-`SYSLIB1118` reserved for Microsoft.Extensions.Configuration.Binder.SourceGeneration.* |
| __`SYSLIB1104`__ | *_`SYSLIB1100`-`SYSLIB1118` reserved for Microsoft.Extensions.Configuration.Binder.SourceGeneration.* |
| __`SYSLIB1103`__ | Configuration binding generator: value types are invalid inputs to configuration 'Bind' methods.* |
| __`SYSLIB1104`__ | Configuration binding generator: Generator cannot determine the target configuration type.* |
| __`SYSLIB1105`__ | *_`SYSLIB1100`-`SYSLIB1118` reserved for Microsoft.Extensions.Configuration.Binder.SourceGeneration.* |
| __`SYSLIB1106`__ | *_`SYSLIB1100`-`SYSLIB1118` reserved for Microsoft.Extensions.Configuration.Binder.SourceGeneration.* |
| __`SYSLIB1107`__ | *_`SYSLIB1100`-`SYSLIB1118` reserved for Microsoft.Extensions.Configuration.Binder.SourceGeneration.* |
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ private static void Execute(CompilationData compilationData, ImmutableArray<Bind

if (compilationData?.LanguageVersionIsSupported != true)
{
context.ReportDiagnostic(Diagnostic.Create(ParserDiagnostics.LanguageVersionNotSupported, location: null));
context.ReportDiagnostic(Diagnostic.Create(Parser.Diagnostics.LanguageVersionNotSupported, location: null));
return;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
{
public sealed partial class ConfigurationBindingGenerator
{
private sealed partial class Emitter
{
// Runtime exception messages; not localized so we keep them in source.
internal static class ExceptionMessages
{
public const string CannotBindToConstructorParameter = "Cannot create instance of type '{0}' because one or more parameters cannot be bound to. Constructor parameters cannot be declared as in, out, or ref. Invalid parameters are: '{1}'";
public const string CannotSpecifyBindNonPublicProperties = "The configuration binding source generator does not support 'BinderOptions.BindNonPublicProperties'.";
public const string ConstructorParametersDoNotMatchProperties = "Cannot create instance of type '{0}' because one or more parameters cannot be bound to. Constructor parameters must have corresponding properties. Fields are not supported. Missing properties are: '{1}'";
public const string FailedBinding = "Failed to convert configuration value at '{0}' to type '{1}'.";
public const string MissingConfig = "'{0}' was set on the provided {1}, but the following properties were not found on the instance of {2}: {3}";
public const string MissingPublicInstanceConstructor = "Cannot create instance of type '{0}' because it is missing a public instance constructor.";
public const string MultipleParameterizedConstructors = "Cannot create instance of type '{0}' because it has multiple public parameterized constructors.";
public const string ParameterHasNoMatchingConfig = "Cannot create instance of type '{0}' because parameter '{1}' has no matching config. Each parameter in the constructor that does not have a default value must have a corresponding config entry.";
public const string TypeNotDetectedAsInput = "Unable to bind to type '{0}': generator did not detect the type as input.";
}
}
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// 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.Configuration.Binder.SourceGeneration
{
public sealed partial class ConfigurationBindingGenerator
{
private sealed partial class Parser
{
internal static class Diagnostics
{
public static DiagnosticDescriptor TypeNotSupported { get; } = CreateTypeNotSupportedDescriptor(nameof(SR.TypeNotSupported));
public static DiagnosticDescriptor MissingPublicInstanceConstructor { get; } = CreateTypeNotSupportedDescriptor(nameof(SR.MissingPublicInstanceConstructor));
public static DiagnosticDescriptor CollectionNotSupported { get; } = CreateTypeNotSupportedDescriptor(nameof(SR.CollectionNotSupported));
public static DiagnosticDescriptor DictionaryKeyNotSupported { get; } = CreateTypeNotSupportedDescriptor(nameof(SR.DictionaryKeyNotSupported));
public static DiagnosticDescriptor ElementTypeNotSupported { get; } = CreateTypeNotSupportedDescriptor(nameof(SR.ElementTypeNotSupported));
public static DiagnosticDescriptor MultipleParameterizedConstructors { get; } = CreateTypeNotSupportedDescriptor(nameof(SR.MultipleParameterizedConstructors));
public static DiagnosticDescriptor MultiDimArraysNotSupported { get; } = CreateTypeNotSupportedDescriptor(nameof(SR.MultiDimArraysNotSupported));
public static DiagnosticDescriptor NullableUnderlyingTypeNotSupported { get; } = CreateTypeNotSupportedDescriptor(nameof(SR.NullableUnderlyingTypeNotSupported));

public static DiagnosticDescriptor PropertyNotSupported { get; } = new DiagnosticDescriptor(
id: "SYSLIB1101",
title: new LocalizableResourceString(nameof(SR.PropertyNotSupportedTitle), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Configuration.Binder.SourceGeneration.SR)),
messageFormat: new LocalizableResourceString(nameof(SR.PropertyNotSupportedMessageFormat), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Configuration.Binder.SourceGeneration.SR)),
category: ProjectName,
defaultSeverity: DiagnosticSeverity.Warning,
isEnabledByDefault: true);

public static DiagnosticDescriptor LanguageVersionNotSupported { get; } = new DiagnosticDescriptor(
id: "SYSLIB1102",
title: new LocalizableResourceString(nameof(SR.LanguageVersionIsNotSupportedTitle), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Configuration.Binder.SourceGeneration.SR)),
messageFormat: new LocalizableResourceString(nameof(SR.Language_VersionIsNotSupportedMessageFormat), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Configuration.Binder.SourceGeneration.SR)),
category: ProjectName,
defaultSeverity: DiagnosticSeverity.Error,
isEnabledByDefault: true);

public static DiagnosticDescriptor ValueTypesInvalidForBind { get; } = new DiagnosticDescriptor(
id: "SYSLIB1103",
title: new LocalizableResourceString(nameof(SR.ValueTypesInvalidForBindTitle), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Configuration.Binder.SourceGeneration.SR)),
messageFormat: new LocalizableResourceString(nameof(SR.ValueTypesInvalidForBindMessageFormat), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Configuration.Binder.SourceGeneration.SR)),
category: ProjectName,
defaultSeverity: DiagnosticSeverity.Warning,
isEnabledByDefault: true);

public static DiagnosticDescriptor CouldNotDetermineTypeInfo { get; } = new DiagnosticDescriptor(
id: "SYSLIB1104",
title: new LocalizableResourceString(nameof(SR.CouldNotDetermineTypeInfoTitle), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Configuration.Binder.SourceGeneration.SR)),
messageFormat: new LocalizableResourceString(nameof(SR.CouldNotDetermineTypeInfoMessageFormat), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Configuration.Binder.SourceGeneration.SR)),
category: ProjectName,
defaultSeverity: DiagnosticSeverity.Warning,
isEnabledByDefault: true);

private static DiagnosticDescriptor CreateTypeNotSupportedDescriptor(string nameofLocalizableMessageFormat) =>
new DiagnosticDescriptor(
id: "SYSLIB1100",
title: new LocalizableResourceString(nameof(SR.TypeNotSupportedTitle), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Configuration.Binder.SourceGeneration.SR)),
messageFormat: new LocalizableResourceString(nameofLocalizableMessageFormat, SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Configuration.Binder.SourceGeneration.SR)),
category: ProjectName,
defaultSeverity: DiagnosticSeverity.Warning,
isEnabledByDefault: true);
}
}
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,16 @@
<Compile Include="ConfigurationBindingGenerator.cs" />
<Compile Include="ConfigurationBindingGenerator.Emitter.cs" />
<Compile Include="ConfigurationBindingGenerator.Parser.cs" />
<Compile Include="Helpers\Emitter.ExceptionMessages.cs" />
<Compile Include="Helpers\Emitter.Helpers.cs" />
<Compile Include="Helpers\ExceptionMessages.cs" />
<Compile Include="Helpers\KnownTypeSymbols.cs" />
<Compile Include="Helpers\ParserDiagnostics.cs" />
<Compile Include="Helpers\Parser.Diagnostics.cs" />
<Compile Include="Helpers\SourceWriter.cs" />
<Compile Include="Model\BinderInvocationOperation.cs" />
<Compile Include="Model\BinderMethodSpecifier.cs" />
<Compile Include="Model\CollectionSpec.cs" />
<Compile Include="Model\ConfigurationSectionSpec.cs" />
<Compile Include="Model\InitializationStrategy.cs" />
<Compile Include="Model\KnownTypeSymbols.cs" />
<Compile Include="Model\NullableSpec.cs" />
<Compile Include="Model\ObjectSpec.cs" />
<Compile Include="Model\ParameterSpec.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,12 @@
<data name="CollectionNotSupported" xml:space="preserve">
<value>The collection type is not supported: '{0}'.</value>
</data>
<data name="CouldNotDetermineTypeInfoMessageFormat" xml:space="preserve">
<value>Binding logic was not generated for a binder call. Unsupported input patterns include generic calls and passing boxed objects.</value>
</data>
<data name="CouldNotDetermineTypeInfoTitle" xml:space="preserve">
<value>The target type for a binder call could not be determined</value>
</data>
<data name="DictionaryKeyNotSupported" xml:space="preserve">
<value>The dictionary key type is not supported: '{0}'.</value>
</data>
Expand Down Expand Up @@ -156,4 +162,10 @@
<data name="TypeNotSupportedTitle" xml:space="preserve">
<value>Did not generate binding logic for a type</value>
</data>
<data name="ValueTypesInvalidForBindMessageFormat" xml:space="preserve">
<value>Binding logic was not generated for a binder call with target type '{0}'. Value types are invalid inputs to configuration 'Bind' methods.</value>
</data>
<data name="ValueTypesInvalidForBindTitle" xml:space="preserve">
<value>Value types are invalid inputs to configuration 'Bind' methods</value>
</data>
</root>
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,16 @@
<target state="translated">Typ kolekce se nepodporuje: „{0}“.</target>
<note />
</trans-unit>
<trans-unit id="CouldNotDetermineTypeInfoMessageFormat">
<source>Binding logic was not generated for a binder call. Unsupported input patterns include generic calls and passing boxed objects.</source>
<target state="new">Binding logic was not generated for a binder call. Unsupported input patterns include generic calls and passing boxed objects.</target>
<note />
</trans-unit>
<trans-unit id="CouldNotDetermineTypeInfoTitle">
<source>The target type for a binder call could not be determined</source>
<target state="new">The target type for a binder call could not be determined</target>
<note />
</trans-unit>
<trans-unit id="DictionaryKeyNotSupported">
<source>The dictionary key type is not supported: '{0}'.</source>
<target state="translated">Typ klíče slovníku se nepodporuje:„{0}“.</target>
Expand Down Expand Up @@ -67,6 +77,16 @@
<target state="translated">Negenerovala se logika vazby pro typ</target>
<note />
</trans-unit>
<trans-unit id="ValueTypesInvalidForBindMessageFormat">
<source>Binding logic was not generated for a binder call with target type '{0}'. Value types are invalid inputs to configuration 'Bind' methods.</source>
<target state="new">Binding logic was not generated for a binder call with target type '{0}'. Value types are invalid inputs to configuration 'Bind' methods.</target>
<note />
</trans-unit>
<trans-unit id="ValueTypesInvalidForBindTitle">
<source>Value types are invalid inputs to configuration 'Bind' methods</source>
<target state="new">Value types are invalid inputs to configuration 'Bind' methods</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
Loading

0 comments on commit ac5febd

Please sign in to comment.