Skip to content

Commit 9cba6ba

Browse files
committed
ff
1 parent 374b2d0 commit 9cba6ba

File tree

4 files changed

+127
-3
lines changed

4 files changed

+127
-3
lines changed

src/CommunityToolkit.Mvvm.SourceGenerators/AnalyzerReleases.Shipped.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,9 @@ Rule ID | Category | Severity | Notes
8484
--------|----------|----------|-------
8585
MVVMTK0041 | CommunityToolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator | Error | See https://aka.ms/mvvmtoolkit/errors/mvvmtk0041
8686
MVVMTK0042 | CommunityToolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator | Info | See https://aka.ms/mvvmtoolkit/errors/mvvmtk0042
87-
MVVMTK0043| CommunityToolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator | Error | See https://aka.ms/mvvmtoolkit/errors/mvvmtk0043
88-
MVVMTK0044| CommunityToolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator | Error | See https://aka.ms/mvvmtoolkit/errors/mvvmtk0044
89-
MVVMTK0045| CommunityToolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator | Warning | See https://aka.ms/mvvmtoolkit/errors/mvvmtk0045
87+
MVVMTK0043 | CommunityToolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator | Error | See https://aka.ms/mvvmtoolkit/errors/mvvmtk0043
88+
MVVMTK0044 | CommunityToolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator | Error | See https://aka.ms/mvvmtoolkit/errors/mvvmtk0044
89+
MVVMTK0045 | CommunityToolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator | Warning | See https://aka.ms/mvvmtoolkit/errors/mvvmtk0045
9090
MVVMTK0046 | CommunityToolkit.Mvvm.SourceGenerators.RelayCommandGenerator | Warning | See https://aka.ms/mvvmtoolkit/errors/mvvmtk0046
91+
MVVMTK0047 | CommunityToolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator | Warning | See https://aka.ms/mvvmtoolkit/errors/mvvmtk0047
92+
MVVMTK0048 | CommunityToolkit.Mvvm.SourceGenerators.RelayCommandGenerator | Warning | See https://aka.ms/mvvmtoolkit/errors/mvvmtk0048

src/CommunityToolkit.Mvvm.SourceGenerators/CommunityToolkit.Mvvm.SourceGenerators.projitems

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
<Compile Include="$(MSBuildThisFileDirectory)ComponentModel\TransitiveMembersGenerator.Execute.cs" />
4242
<Compile Include="$(MSBuildThisFileDirectory)Diagnostics\Analyzers\AsyncVoidReturningRelayCommandMethodAnalyzer.cs" />
4343
<Compile Include="$(MSBuildThisFileDirectory)Diagnostics\Analyzers\InvalidGeneratedPropertyObservablePropertyAttributeAnalyzer.cs" />
44+
<Compile Include="$(MSBuildThisFileDirectory)Diagnostics\Analyzers\WinRTGeneratedBindableCustomPropertyWithBasesMemberAnalyzer.cs" />
4445
<Compile Include="$(MSBuildThisFileDirectory)Diagnostics\Analyzers\WinRTRelayCommandIsNotGeneratedBindableCustomPropertyCompatibleAnalyzer.cs" />
4546
<Compile Include="$(MSBuildThisFileDirectory)Diagnostics\Analyzers\WinRTObservablePropertyOnFieldsIsNotAotCompatibleAnalyzer.cs" />
4647
<Compile Include="$(MSBuildThisFileDirectory)Diagnostics\Analyzers\PropertyNameCollisionObservablePropertyAttributeAnalyzer.cs" />
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
#if ROSLYN_4_11_0_OR_GREATER
6+
7+
using System.Collections.Immutable;
8+
using CommunityToolkit.Mvvm.SourceGenerators.Extensions;
9+
using Microsoft.CodeAnalysis;
10+
using Microsoft.CodeAnalysis.Diagnostics;
11+
using static CommunityToolkit.Mvvm.SourceGenerators.Diagnostics.DiagnosticDescriptors;
12+
13+
namespace CommunityToolkit.Mvvm.SourceGenerators;
14+
15+
/// <summary>
16+
/// A diagnostic analyzer that generates an error when <c>[GeneratedBindableCustomProperty]</c> is used on types with invalid generated base members.
17+
/// </summary>
18+
[DiagnosticAnalyzer(LanguageNames.CSharp)]
19+
public sealed class WinRTGeneratedBindableCustomPropertyWithBasesMemberAnalyzer : DiagnosticAnalyzer
20+
{
21+
/// <inheritdoc/>
22+
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get; } = ImmutableArray.Create(
23+
WinRTGeneratedBindableCustomPropertyWithBaseObservablePropertyOnField,
24+
WinRTGeneratedBindableCustomPropertyWithBaseRelayCommand);
25+
26+
/// <inheritdoc/>
27+
public override void Initialize(AnalysisContext context)
28+
{
29+
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
30+
context.EnableConcurrentExecution();
31+
32+
context.RegisterCompilationStartAction(static context =>
33+
{
34+
// This analyzer is only enabled when CsWinRT is also used
35+
if (!context.Options.AnalyzerConfigOptionsProvider.GlobalOptions.IsUsingWindowsRuntimePack())
36+
{
37+
return;
38+
}
39+
40+
// Get the symbol for [ObservableProperty], [RelayCommand] and [GeneratedBindableCustomProperty]
41+
if (context.Compilation.GetTypeByMetadataName("CommunityToolkit.Mvvm.ComponentModel.ObservablePropertyAttribute") is not INamedTypeSymbol observablePropertySymbol ||
42+
context.Compilation.GetTypeByMetadataName("CommunityToolkit.Mvvm.Input.RelayCommandAttribute") is not INamedTypeSymbol relayCommandSymbol ||
43+
context.Compilation.GetTypeByMetadataName("WinRT.GeneratedBindableCustomPropertyAttribute") is not INamedTypeSymbol generatedBindableCustomPropertySymbol)
44+
{
45+
return;
46+
}
47+
48+
bool isLanguageVersionPreview = context.Compilation.IsLanguageVersionPreview();
49+
50+
context.RegisterSymbolAction(context =>
51+
{
52+
// Ensure we do have a valid field
53+
if (context.Symbol is not IFieldSymbol fieldSymbol)
54+
{
55+
return;
56+
}
57+
58+
// Emit a diagnostic if the field is using the [ObservableProperty] attribute
59+
if (fieldSymbol.TryGetAttributeWithType(observablePropertySymbol, out AttributeData? observablePropertyAttribute))
60+
{
61+
// If the C# version is preview, we can include the necessary information to trigger the
62+
// code fixer. If that is not the case, we shouldn't do that, to avoid the code fixer
63+
// changing the code to invalid C# (as without the preview version, it wouldn't compile).
64+
if (isLanguageVersionPreview)
65+
{
66+
context.ReportDiagnostic(Diagnostic.Create(
67+
WinRTObservablePropertyOnFieldsIsNotAotCompatible,
68+
observablePropertyAttribute.GetLocation(),
69+
ImmutableDictionary.Create<string, string?>()
70+
.Add(FieldReferenceForObservablePropertyFieldAnalyzer.FieldNameKey, fieldSymbol.Name)
71+
.Add(FieldReferenceForObservablePropertyFieldAnalyzer.PropertyNameKey, ObservablePropertyGenerator.Execute.GetGeneratedPropertyName(fieldSymbol)),
72+
fieldSymbol.ContainingType,
73+
fieldSymbol.Name));
74+
}
75+
else
76+
{
77+
context.ReportDiagnostic(Diagnostic.Create(
78+
WinRTObservablePropertyOnFieldsIsNotAotCompatible,
79+
observablePropertyAttribute.GetLocation(),
80+
fieldSymbol.ContainingType,
81+
fieldSymbol.Name));
82+
}
83+
}
84+
}, SymbolKind.Field);
85+
});
86+
}
87+
}
88+
89+
#endif

src/CommunityToolkit.Mvvm.SourceGenerators/Diagnostics/DiagnosticDescriptors.cs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -780,4 +780,36 @@ internal static class DiagnosticDescriptors
780780
isEnabledByDefault: true,
781781
description: "Using [RelayCommand] on methods within a type also using [GeneratedBindableCustomProperty] is not supported, and a manually declared command property should be used instead (the [GeneratedBindableCustomProperty] generator cannot see the generated command property that is produced by the MVVM Toolkit generator).",
782782
helpLinkUri: "https://aka.ms/mvvmtoolkit/errors/mvvmtk0046");
783+
784+
/// <summary>
785+
/// Gets a <see cref="DiagnosticDescriptor"/> for when <c>[GeneratedBindableCustomProperty]</c> is used on a type that also uses <c>[ObservableProperty]</c> on any declared or inherited fields.
786+
/// <para>
787+
/// Format: <c>"The type {0} using [GeneratedBindableCustomProperty] is also using [ObservableProperty] on its declared (or inherited) field {1}.{2}: combining the two generators is not supported, and partial properties should be used instead (the [GeneratedBindableCustomProperty] generator cannot see the generated property that is produced by the MVVM Toolkit generator)"</c>.
788+
/// </para>
789+
/// </summary>
790+
public static readonly DiagnosticDescriptor WinRTGeneratedBindableCustomPropertyWithBaseObservablePropertyOnField = new(
791+
id: "MVVMTK0047",
792+
title: "Using [GeneratedBindableCustomProperty] is not compatible with [ObservableProperty] on fields",
793+
messageFormat: """The type {0} using [GeneratedBindableCustomProperty] is also using [RelayCommand] on its declared (or inherited) method {1}: combining the two generators is not supported, and a manually declared command property should be used instead (the [GeneratedBindableCustomProperty] generator cannot see the generated property that is produced by the MVVM Toolkit generator)""",
794+
category: typeof(ObservablePropertyGenerator).FullName,
795+
defaultSeverity: DiagnosticSeverity.Warning,
796+
isEnabledByDefault: true,
797+
description: "Using [GeneratedBindableCustomProperty] on types that also use [ObservableProperty] on any declared (or inherited) fields is not supported, and partial properties should be used instead (the [GeneratedBindableCustomProperty] generator cannot see the generated property that is produced by the MVVM Toolkit generator).",
798+
helpLinkUri: "https://aka.ms/mvvmtoolkit/errors/mvvmtk0047");
799+
800+
/// <summary>
801+
/// Gets a <see cref="DiagnosticDescriptor"/> for when <c>[GeneratedBindableCustomProperty]</c> is used on a type that also uses <c>[RelayCommand]</c> on any declared or inherited methods.
802+
/// <para>
803+
/// Format: <c>"The method {0} using [RelayCommand] within a type also using [GeneratedBindableCustomProperty], which is not supported, and a manually declared command property should be used instead (the [GeneratedBindableCustomProperty] generator cannot see the generated command property that is produced by the MVVM Toolkit generator)"</c>.
804+
/// </para>
805+
/// </summary>
806+
public static readonly DiagnosticDescriptor WinRTGeneratedBindableCustomPropertyWithBaseRelayCommand = new(
807+
id: "MVVMTK0048",
808+
title: "Using [GeneratedBindableCustomProperty] is not compatible with [RelayCommand]",
809+
messageFormat: """The type {0} using [GeneratedBindableCustomProperty] is also using [RelayCommand] on its declared (or inherited) method {1}: combining the two generators is not supported, and a manually declared command property should be used instead (the [GeneratedBindableCustomProperty] generator cannot see the generated property that is produced by the MVVM Toolkit generator)""",
810+
category: typeof(RelayCommandGenerator).FullName,
811+
defaultSeverity: DiagnosticSeverity.Warning,
812+
isEnabledByDefault: true,
813+
description: "Using [GeneratedBindableCustomProperty] on types that also use [RelayCommand] on any declared (or inherited) methods is not supported, and a manually declared command property should be used instead (the [GeneratedBindableCustomProperty] generator cannot see the generated property that is produced by the MVVM Toolkit generator).",
814+
helpLinkUri: "https://aka.ms/mvvmtoolkit/errors/mvvmtk0048");
783815
}

0 commit comments

Comments
 (0)