Skip to content

Commit

Permalink
Set minimum language version allowed by config binding generator (#83996
Browse files Browse the repository at this point in the history
)

* Set minimum language version allowed by config binding generator

* Address feedback; use correct diagnostic severity
  • Loading branch information
layomia authored Mar 29, 2023
1 parent 384d4bd commit 9111203
Show file tree
Hide file tree
Showing 20 changed files with 298 additions and 99 deletions.
29 changes: 17 additions & 12 deletions docs/project/list-of-diagnostics.md
Original file line number Diff line number Diff line change
Expand Up @@ -213,18 +213,23 @@ The diagnostic id values reserved for .NET Libraries analyzer warnings are `SYSL
| __`SYSLIB1099`__ | _`SYSLIB1092`-`SYSLIB1099` reserved for Microsoft.Interop.ComInteropGenerator._ |
| __`SYSLIB1100`__ | Configuration binding generator: type is not supported. |
| __`SYSLIB1101`__ | Configuration binding generator: property on type is not supported. |
| __`SYSLIB1102`__ | *_`SYSLIB1101`-`SYSLIB1113` reserved for Microsoft.Extensions.Configuration.Binder.SourceGeneration.* |
| __`SYSLIB1103`__ | *_`SYSLIB1101`-`SYSLIB1113` reserved for Microsoft.Extensions.Configuration.Binder.SourceGeneration.* |
| __`SYSLIB1104`__ | *_`SYSLIB1101`-`SYSLIB1113` reserved for Microsoft.Extensions.Configuration.Binder.SourceGeneration.* |
| __`SYSLIB1105`__ | *_`SYSLIB1101`-`SYSLIB1113` reserved for Microsoft.Extensions.Configuration.Binder.SourceGeneration.* |
| __`SYSLIB1106`__ | *_`SYSLIB1101`-`SYSLIB1113` reserved for Microsoft.Extensions.Configuration.Binder.SourceGeneration.* |
| __`SYSLIB1107`__ | *_`SYSLIB1101`-`SYSLIB1113` reserved for Microsoft.Extensions.Configuration.Binder.SourceGeneration.* |
| __`SYSLIB1108`__ | *_`SYSLIB1101`-`SYSLIB1113` reserved for Microsoft.Extensions.Configuration.Binder.SourceGeneration.* |
| __`SYSLIB1109`__ | *_`SYSLIB1101`-`SYSLIB1113` reserved for Microsoft.Extensions.Configuration.Binder.SourceGeneration.* |
| __`SYSLIB1110`__ | *_`SYSLIB1101`-`SYSLIB1113` reserved for Microsoft.Extensions.Configuration.Binder.SourceGeneration.* |
| __`SYSLIB1111`__ | *_`SYSLIB1101`-`SYSLIB1113` reserved for Microsoft.Extensions.Configuration.Binder.SourceGeneration.* |
| __`SYSLIB1112`__ | *_`SYSLIB1101`-`SYSLIB1113` reserved for Microsoft.Extensions.Configuration.Binder.SourceGeneration.* |
| __`SYSLIB1113`__ | *_`SYSLIB1101`-`SYSLIB1113` reserved for Microsoft.Extensions.Configuration.Binder.SourceGeneration.* |
| __`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.* |
| __`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.* |
| __`SYSLIB1108`__ | *_`SYSLIB1100`-`SYSLIB1118` reserved for Microsoft.Extensions.Configuration.Binder.SourceGeneration.* |
| __`SYSLIB1109`__ | *_`SYSLIB1100`-`SYSLIB1118` reserved for Microsoft.Extensions.Configuration.Binder.SourceGeneration.* |
| __`SYSLIB1110`__ | *_`SYSLIB1100`-`SYSLIB1118` reserved for Microsoft.Extensions.Configuration.Binder.SourceGeneration.* |
| __`SYSLIB1111`__ | *_`SYSLIB1100`-`SYSLIB1118` reserved for Microsoft.Extensions.Configuration.Binder.SourceGeneration.* |
| __`SYSLIB1112`__ | *_`SYSLIB1100`-`SYSLIB1118` reserved for Microsoft.Extensions.Configuration.Binder.SourceGeneration.* |
| __`SYSLIB1113`__ | *_`SYSLIB1100`-`SYSLIB1118` reserved for Microsoft.Extensions.Configuration.Binder.SourceGeneration.* |
| __`SYSLIB1114`__ | *_`SYSLIB1100`-`SYSLIB1118` reserved for Microsoft.Extensions.Configuration.Binder.SourceGeneration.* |
| __`SYSLIB1115`__ | *_`SYSLIB1100`-`SYSLIB1118` reserved for Microsoft.Extensions.Configuration.Binder.SourceGeneration.* |
| __`SYSLIB1116`__ | *_`SYSLIB1100`-`SYSLIB1118` reserved for Microsoft.Extensions.Configuration.Binder.SourceGeneration.* |
| __`SYSLIB1117`__ | *_`SYSLIB1100`-`SYSLIB1118` reserved for Microsoft.Extensions.Configuration.Binder.SourceGeneration.* |
| __`SYSLIB1118`__ | *_`SYSLIB1100`-`SYSLIB1118` reserved for Microsoft.Extensions.Configuration.Binder.SourceGeneration.* |


### Diagnostic Suppressions (`SYSLIBSUPPRESS****`)
Expand Down
11 changes: 8 additions & 3 deletions src/libraries/Common/tests/SourceGenerators/RoslynTestUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ internal static class RoslynTestUtils
/// </summary>
/// <param name="references">Assembly references to include in the project.</param>
/// <param name="includeBaseReferences">Whether to include references to the BCL assemblies.</param>
public static Project CreateTestProject(IEnumerable<Assembly>? references, bool includeBaseReferences = true)
public static Project CreateTestProject(
IEnumerable<Assembly>? references,
bool includeBaseReferences = true,
LanguageVersion langVersion = LanguageVersion.Preview)
{
string corelib = Assembly.GetAssembly(typeof(object))!.Location;
string runtimeDir = Path.GetDirectoryName(corelib)!;
Expand All @@ -51,7 +54,8 @@ public static Project CreateTestProject(IEnumerable<Assembly>? references, bool
.AddSolution(SolutionInfo.Create(SolutionId.CreateNewId(), VersionStamp.Create()))
.AddProject("Test", "test.dll", "C#")
.WithMetadataReferences(refs)
.WithCompilationOptions(new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary).WithNullableContextOptions(NullableContextOptions.Enable));
.WithCompilationOptions(new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary).WithNullableContextOptions(NullableContextOptions.Enable))
.WithParseOptions(new CSharpParseOptions(langVersion));
}

public static Task CommitChanges(this Project proj, params string[] ignorables)
Expand Down Expand Up @@ -149,9 +153,10 @@ public static TextSpan MakeSpan(string text, int spanNum)
IEnumerable<Assembly>? references,
IEnumerable<string> sources,
bool includeBaseReferences = true,
LanguageVersion langVersion = LanguageVersion.Preview,
CancellationToken cancellationToken = default)
{
Project proj = CreateTestProject(references, includeBaseReferences);
Project proj = CreateTestProject(references, includeBaseReferences, langVersion);
proj = proj.WithDocuments(sources);
Assert.True(proj.Solution.Workspace.TryApplyChanges(proj.Solution));
Compilation? comp = await proj!.GetCompilationAsync(CancellationToken.None).ConfigureAwait(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Diagnostics;
using System.Text;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Text;

namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
{
Expand All @@ -18,15 +15,23 @@ public sealed partial class ConfigurationBindingSourceGenerator
title: new LocalizableResourceString(nameof(SR.TypeNotSupportedTitle), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Configuration.Binder.SourceGeneration.SR)),
messageFormat: new LocalizableResourceString(nameof(SR.TypeNotSupportedMessageFormat), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Configuration.Binder.SourceGeneration.SR)),
category: GeneratorProjectName,
defaultSeverity: DiagnosticSeverity.Info,
defaultSeverity: DiagnosticSeverity.Warning,
isEnabledByDefault: true);

private 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: GeneratorProjectName,
defaultSeverity: DiagnosticSeverity.Info,
defaultSeverity: DiagnosticSeverity.Warning,
isEnabledByDefault: true);

private 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: GeneratorProjectName,
defaultSeverity: DiagnosticSeverity.Error,
isEnabledByDefault: true);

// Unlike sourcegen warnings, exception messages should not be localized so we keep them in source.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Collections.Immutable;
using System.Threading;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.DotnetRuntime.Extensions;
using Microsoft.CodeAnalysis.Operations;
Expand All @@ -19,23 +20,25 @@ public sealed partial class ConfigurationBindingSourceGenerator : IIncrementalGe
{
public void Initialize(IncrementalGeneratorInitializationContext context)
{
IncrementalValueProvider<KnownTypeData> compilationData =
IncrementalValueProvider<CompilationData?> compilationData =
context.CompilationProvider
.Select((compilation, _) => new KnownTypeData(compilation));
.Select((compilation, _) => compilation.Options is CSharpCompilationOptions options
? new CompilationData((CSharpCompilation)compilation)
: null);

IncrementalValuesProvider<BinderInvocationOperation> inputCalls = context.SyntaxProvider.CreateSyntaxProvider(
(node, _) => node is InvocationExpressionSyntax invocation,
(context, cancellationToken) => new BinderInvocationOperation(context, cancellationToken));

IncrementalValueProvider<(KnownTypeData, ImmutableArray<BinderInvocationOperation>)> inputData = compilationData.Combine(inputCalls.Collect());
IncrementalValueProvider<(CompilationData?, ImmutableArray<BinderInvocationOperation>)> inputData = compilationData.Combine(inputCalls.Collect());

context.RegisterSourceOutput(inputData, (spc, source) => Execute(source.Item1, source.Item2, spc));
}

/// <summary>
/// Generates source code to optimize binding with ConfigurationBinder.
/// </summary>
private static void Execute(KnownTypeData typeData, ImmutableArray<BinderInvocationOperation> inputCalls, SourceProductionContext context)
private static void Execute(CompilationData compilationData, ImmutableArray<BinderInvocationOperation> inputCalls, SourceProductionContext context)
{
#if LAUNCH_DEBUGGER
if (!System.Diagnostics.Debugger.IsAttached)
Expand All @@ -48,7 +51,13 @@ private static void Execute(KnownTypeData typeData, ImmutableArray<BinderInvocat
return;
}

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

Parser parser = new(context, compilationData.TypeData!);
SourceGenerationSpec? spec = parser.GetSourceGenerationSpec(inputCalls);
if (spec is not null)
{
Expand All @@ -57,6 +66,21 @@ private static void Execute(KnownTypeData typeData, ImmutableArray<BinderInvocat
}
}

private sealed record CompilationData
{
public bool LanguageVersionIsSupported { get; }
public KnownTypeData? TypeData { get; }

public CompilationData(CSharpCompilation compilation)
{
LanguageVersionIsSupported = compilation.LanguageVersion >= LanguageVersion.CSharp11;
if (LanguageVersionIsSupported)
{
TypeData = new KnownTypeData(compilation);
}
}
}

private sealed record KnownTypeData
{
public INamedTypeSymbol SymbolForGenericIList { get; }
Expand All @@ -75,7 +99,7 @@ private sealed record KnownTypeData
public INamedTypeSymbol? SymbolForISet { get; }
public INamedTypeSymbol? SymbolForList { get; }

public KnownTypeData(Compilation compilation)
public KnownTypeData(CSharpCompilation compilation)
{
SymbolForIEnumerable = compilation.GetSpecialType(SpecialType.System_Collections_IEnumerable);
SymbolForConfigurationKeyNameAttribute = compilation.GetBestTypeByMetadataName(TypeFullName.ConfigurationKeyNameAttribute);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,16 +117,22 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Language VersionIsNotSupportedMessageFormat" xml:space="preserve">
<value>The project's language version has to be at least 'C# 11'.</value>
</data>
<data name="LanguageVersionIsNotSupportedTitle" xml:space="preserve">
<value>Language version is required to be at least C# 11</value>
</data>
<data name="PropertyNotSupportedMessageFormat" xml:space="preserve">
<value>Property '{0}' on type '{1}' is not supported.</value>
</data>
<data name="PropertyNotSupportedTitle" xml:space="preserve">
<value>Did not generate binding logic for a property on a type.</value>
<value>Did not generate binding logic for a property on a type</value>
</data>
<data name="TypeNotSupportedMessageFormat" xml:space="preserve">
<value>Type '{0}' is not supported: {1}.</value>
</data>
<data name="TypeNotSupportedTitle" xml:space="preserve">
<value>Did not generate binding logic for a type.</value>
<value>Did not generate binding logic for a type</value>
</data>
</root>
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,24 @@
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
<file datatype="xml" source-language="en" target-language="cs" original="../Strings.resx">
<body>
<trans-unit id="Language VersionIsNotSupportedMessageFormat">
<source>The project's language version has to be at least 'C# 11'.</source>
<target state="new">The project's language version has to be at least 'C# 11'.</target>
<note />
</trans-unit>
<trans-unit id="LanguageVersionIsNotSupportedTitle">
<source>Language version is required to be at least C# 11</source>
<target state="new">Language version is required to be at least C# 11</target>
<note />
</trans-unit>
<trans-unit id="PropertyNotSupportedMessageFormat">
<source>Property '{0}' on type '{1}' is not supported.</source>
<target state="translated">Vlastnost „{0}“ u typu „{1}“ se nepodporuje.</target>
<note />
</trans-unit>
<trans-unit id="PropertyNotSupportedTitle">
<source>Did not generate binding logic for a property on a type.</source>
<target state="translated">Nevygenerovala se logika vazby pro vlastnost typu.</target>
<source>Did not generate binding logic for a property on a type</source>
<target state="needs-review-translation">Nevygenerovala se logika vazby pro vlastnost typu.</target>
<note />
</trans-unit>
<trans-unit id="TypeNotSupportedMessageFormat">
Expand All @@ -18,8 +28,8 @@
<note />
</trans-unit>
<trans-unit id="TypeNotSupportedTitle">
<source>Did not generate binding logic for a type.</source>
<target state="translated">Nevygenerovala se logika vazby pro typ.</target>
<source>Did not generate binding logic for a type</source>
<target state="needs-review-translation">Nevygenerovala se logika vazby pro typ.</target>
<note />
</trans-unit>
</body>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,24 @@
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
<file datatype="xml" source-language="en" target-language="de" original="../Strings.resx">
<body>
<trans-unit id="Language VersionIsNotSupportedMessageFormat">
<source>The project's language version has to be at least 'C# 11'.</source>
<target state="new">The project's language version has to be at least 'C# 11'.</target>
<note />
</trans-unit>
<trans-unit id="LanguageVersionIsNotSupportedTitle">
<source>Language version is required to be at least C# 11</source>
<target state="new">Language version is required to be at least C# 11</target>
<note />
</trans-unit>
<trans-unit id="PropertyNotSupportedMessageFormat">
<source>Property '{0}' on type '{1}' is not supported.</source>
<target state="translated">Die Eigenschaft „{0}“ für den Typ „{1}“ wird nicht unterstützt.</target>
<note />
</trans-unit>
<trans-unit id="PropertyNotSupportedTitle">
<source>Did not generate binding logic for a property on a type.</source>
<target state="translated">Für eine Eigenschaft eines Typs wurde keine Bindungslogik generiert.</target>
<source>Did not generate binding logic for a property on a type</source>
<target state="needs-review-translation">Für eine Eigenschaft eines Typs wurde keine Bindungslogik generiert.</target>
<note />
</trans-unit>
<trans-unit id="TypeNotSupportedMessageFormat">
Expand All @@ -18,8 +28,8 @@
<note />
</trans-unit>
<trans-unit id="TypeNotSupportedTitle">
<source>Did not generate binding logic for a type.</source>
<target state="translated">Für einen Typ wurde keine Bindungslogik generiert.</target>
<source>Did not generate binding logic for a type</source>
<target state="needs-review-translation">Für einen Typ wurde keine Bindungslogik generiert.</target>
<note />
</trans-unit>
</body>
Expand Down
Loading

0 comments on commit 9111203

Please sign in to comment.