Skip to content

Commit 21e0825

Browse files
committed
Added diagnostic for unsupported C# language version
1 parent 0ce4553 commit 21e0825

File tree

7 files changed

+55
-1
lines changed

7 files changed

+55
-1
lines changed

Microsoft.Toolkit.Mvvm.SourceGenerators/AnalyzerReleases.Unshipped.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,4 @@ MVVMTK0009 | Microsoft.Toolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator
1717
MVVMTK0010 | Microsoft.Toolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator | Error | See https://aka.ms/mvvmtoolkit/error
1818
MVVMTK0011 | Microsoft.Toolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator | Error | See https://aka.ms/mvvmtoolkit/error
1919
MVVMTK0012 | Microsoft.Toolkit.Mvvm.SourceGenerators.ICommandGenerator | Error | See https://aka.ms/mvvmtoolkit/error
20+
MVVMTK0013 | Microsoft.CodeAnalysis.CSharp.CSharpParseOptions | Error | See https://aka.ms/mvvmtoolkit/error

Microsoft.Toolkit.Mvvm.SourceGenerators/ComponentModel/ObservablePropertyGenerator.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,15 @@ public void Execute(GeneratorExecutionContext context)
4141
return;
4242
}
4343

44+
// Validate the language version. Note that we're emitting this diagnostic in each generator (excluding the one
45+
// only emitting the nullability annotation attributes if missing) so that the diagnostic is emitted only when
46+
// users are using one of these generators, and not by default as soon as they add a reference to the MVVM Toolkit.
47+
// This ensures that users not using any of the source generators won't be broken when upgrading to this new version.
48+
if (context.ParseOptions is not CSharpParseOptions { LanguageVersion: >= LanguageVersion.CSharp9 })
49+
{
50+
context.ReportDiagnostic(Diagnostic.Create(UnsupportedCSharpLanguageVersionError, null));
51+
}
52+
4453
// Sets of discovered property names
4554
HashSet<string>
4655
propertyChangedNames = new(),

Microsoft.Toolkit.Mvvm.SourceGenerators/ComponentModel/ObservableValidatorValidateAllPropertiesGenerator.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
using Microsoft.CodeAnalysis.Text;
1515
using Microsoft.Toolkit.Mvvm.SourceGenerators.Extensions;
1616
using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
17+
using static Microsoft.Toolkit.Mvvm.SourceGenerators.Diagnostics.DiagnosticDescriptors;
1718

1819
namespace Microsoft.Toolkit.Mvvm.SourceGenerators
1920
{
@@ -39,6 +40,12 @@ public void Execute(GeneratorExecutionContext context)
3940
return;
4041
}
4142

43+
// Validate the language version
44+
if (context.ParseOptions is not CSharpParseOptions { LanguageVersion: >= LanguageVersion.CSharp9 })
45+
{
46+
context.ReportDiagnostic(Diagnostic.Create(UnsupportedCSharpLanguageVersionError, null));
47+
}
48+
4249
// Get the symbol for the ValidationAttribute type
4350
INamedTypeSymbol validationSymbol = context.Compilation.GetTypeByMetadataName("System.ComponentModel.DataAnnotations.ValidationAttribute")!;
4451

Microsoft.Toolkit.Mvvm.SourceGenerators/ComponentModel/TransitiveMembersGenerator.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
using Microsoft.Toolkit.Mvvm.SourceGenerators.Extensions;
1919
using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
2020
using static Microsoft.CodeAnalysis.SymbolDisplayTypeQualificationStyle;
21+
using static Microsoft.Toolkit.Mvvm.SourceGenerators.Diagnostics.DiagnosticDescriptors;
2122

2223
namespace Microsoft.Toolkit.Mvvm.SourceGenerators
2324
{
@@ -67,6 +68,12 @@ public void Execute(GeneratorExecutionContext context)
6768
return;
6869
}
6970

71+
// Validate the language version
72+
if (context.ParseOptions is not CSharpParseOptions { LanguageVersion: >= LanguageVersion.CSharp9 })
73+
{
74+
context.ReportDiagnostic(Diagnostic.Create(UnsupportedCSharpLanguageVersionError, null));
75+
}
76+
7077
// Load the syntax tree with the members to generate
7178
SyntaxTree sourceSyntaxTree = LoadSourceSyntaxTree();
7279

Microsoft.Toolkit.Mvvm.SourceGenerators/Diagnostics/DiagnosticDescriptors.cs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
using System.ComponentModel;
66
using Microsoft.CodeAnalysis;
7+
using Microsoft.CodeAnalysis.CSharp;
78

89
namespace Microsoft.Toolkit.Mvvm.SourceGenerators.Diagnostics
910
{
@@ -201,7 +202,23 @@ internal static class DiagnosticDescriptors
201202
category: typeof(ICommandGenerator).FullName,
202203
defaultSeverity: DiagnosticSeverity.Error,
203204
isEnabledByDefault: true,
204-
description: $"Cannot apply [ICommand] to methods with a signature that doesn't match any of the existing relay command types.",
205+
description: "Cannot apply [ICommand] to methods with a signature that doesn't match any of the existing relay command types.",
206+
helpLinkUri: "https://aka.ms/mvvmtoolkit");
207+
208+
/// <summary>
209+
/// Gets a <see cref="DiagnosticDescriptor"/> indicating when an unsupported C# language version is being used.
210+
/// <para>
211+
/// Format: <c>"The method {0}.{1} cannot be used to generate a command property, as its signature isn't compatible with any of the existing relay command types"</c>.
212+
/// </para>
213+
/// </summary>
214+
public static readonly DiagnosticDescriptor UnsupportedCSharpLanguageVersionError = new(
215+
id: "MVVMTK0013",
216+
title: "Unsupported C# language version",
217+
messageFormat: "The source generator features from the MVVM Toolkit require consuming projects to set the C# language version to at least C# 9.0",
218+
category: typeof(CSharpParseOptions).FullName,
219+
defaultSeverity: DiagnosticSeverity.Error,
220+
isEnabledByDefault: true,
221+
description: "The source generator features from the MVVM Toolkit require consuming projects to set the C# language version to at least C# 9.0. Make sure to add <LangVersion>9.0</LangVersion> (or above) to your .csproj file.",
205222
helpLinkUri: "https://aka.ms/mvvmtoolkit");
206223
}
207224
}

Microsoft.Toolkit.Mvvm.SourceGenerators/Input/ICommandGenerator.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,12 @@ public void Execute(GeneratorExecutionContext context)
4343
return;
4444
}
4545

46+
// Validate the language version
47+
if (context.ParseOptions is not CSharpParseOptions { LanguageVersion: >= LanguageVersion.CSharp9 })
48+
{
49+
context.ReportDiagnostic(Diagnostic.Create(UnsupportedCSharpLanguageVersionError, null));
50+
}
51+
4652
foreach (var items in syntaxReceiver.GatheredInfo.GroupBy<SyntaxReceiver.Item, INamedTypeSymbol>(static item => item.MethodSymbol.ContainingType, SymbolEqualityComparer.Default))
4753
{
4854
if (items.Key.DeclaringSyntaxReferences.Length > 0 &&

Microsoft.Toolkit.Mvvm.SourceGenerators/Messaging/IMessengerRegisterAllGenerator.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
using Microsoft.CodeAnalysis.Text;
1414
using Microsoft.Toolkit.Mvvm.SourceGenerators.Extensions;
1515
using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
16+
using static Microsoft.Toolkit.Mvvm.SourceGenerators.Diagnostics.DiagnosticDescriptors;
1617

1718
namespace Microsoft.Toolkit.Mvvm.SourceGenerators
1819
{
@@ -38,6 +39,12 @@ public void Execute(GeneratorExecutionContext context)
3839
return;
3940
}
4041

42+
// Validate the language version
43+
if (context.ParseOptions is not CSharpParseOptions { LanguageVersion: >= LanguageVersion.CSharp9 })
44+
{
45+
context.ReportDiagnostic(Diagnostic.Create(UnsupportedCSharpLanguageVersionError, null));
46+
}
47+
4148
// Get the symbol for the IRecipient<T> interface type
4249
INamedTypeSymbol iRecipientSymbol = context.Compilation.GetTypeByMetadataName("Microsoft.Toolkit.Mvvm.Messaging.IRecipient`1")!;
4350

0 commit comments

Comments
 (0)