Skip to content

Commit 31745cb

Browse files
committed
Update generator/analyzer diagnostics unit tests
1 parent 3486723 commit 31745cb

File tree

1 file changed

+61
-73
lines changed

1 file changed

+61
-73
lines changed

tests/CommunityToolkit.Mvvm.SourceGenerators.UnitTests/Test_SourceGeneratorsDiagnostics.cs

Lines changed: 61 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
using Microsoft.CodeAnalysis.CSharp;
1212
using CommunityToolkit.Mvvm.ComponentModel;
1313
using Microsoft.VisualStudio.TestTools.UnitTesting;
14+
using System.Threading.Tasks;
15+
using CommunityToolkit.Mvvm.SourceGenerators.UnitTests.Helpers;
16+
using System.Text.RegularExpressions;
1417

1518
namespace CommunityToolkit.Mvvm.SourceGenerators.UnitTests;
1619

@@ -231,73 +234,85 @@ public partial class SampleViewModel
231234
}
232235

233236
[TestMethod]
234-
public void UnsupportedCSharpLanguageVersion_FromINotifyPropertyChangedGenerator()
237+
public async Task UnsupportedCSharpLanguageVersion_FromINotifyPropertyChangedGenerator()
235238
{
236239
string source = @"
237240
using CommunityToolkit.Mvvm.ComponentModel;
238241
239242
namespace MyApp
240243
{
241244
[INotifyPropertyChanged]
242-
public partial class SampleViewModel
245+
public partial class {|MVVMTK0008:SampleViewModel|}
243246
{
244247
}
245248
}";
246249

247-
VerifyGeneratedDiagnostics<INotifyPropertyChangedGenerator>(
248-
CSharpSyntaxTree.ParseText(source, CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.CSharp7_3)),
249-
"MVVMTK0008");
250-
251-
VerifySuccessfulGeneration(source);
250+
await VerifyUnsupportedCSharpVersionAndSuccessfulGeneration(source);
252251
}
253252

254253
[TestMethod]
255-
public void UnsupportedCSharpLanguageVersion_FromObservableObjectGenerator()
254+
public async Task UnsupportedCSharpLanguageVersion_FromObservableObjectGenerator()
256255
{
257256
string source = @"
258257
using CommunityToolkit.Mvvm.ComponentModel;
259258
260259
namespace MyApp
261260
{
262261
[ObservableObject]
263-
public partial class SampleViewModel
262+
public partial class {|MVVMTK0008:SampleViewModel|}
264263
{
265264
}
266265
}";
267266

268-
VerifyGeneratedDiagnostics<ObservableObjectGenerator>(
269-
CSharpSyntaxTree.ParseText(source, CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.CSharp7_3)),
270-
"MVVMTK0008");
271-
272-
VerifySuccessfulGeneration(source);
267+
await VerifyUnsupportedCSharpVersionAndSuccessfulGeneration(source);
273268
}
274269

275270
[TestMethod]
276-
public void UnsupportedCSharpLanguageVersion_FromObservablePropertyGenerator()
271+
public async Task UnsupportedCSharpLanguageVersion_FromObservablePropertyGenerator()
277272
{
278273
string source = @"
279274
using CommunityToolkit.Mvvm.ComponentModel;
280275
281276
namespace MyApp
282277
{
283278
[INotifyPropertyChanged]
284-
public partial class SampleViewModel
279+
public partial class {|MVVMTK0008:SampleViewModel|}
285280
{
286281
[ObservableProperty]
287-
private string name;
282+
private string {|MVVMTK0008:name|};
288283
}
289284
}";
290285

291-
VerifyGeneratedDiagnostics<ObservablePropertyGenerator>(
292-
CSharpSyntaxTree.ParseText(source, CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.CSharp7_3)),
293-
"MVVMTK0008");
286+
await VerifyUnsupportedCSharpVersionAndSuccessfulGeneration(source);
287+
}
294288

295-
VerifySuccessfulGeneration(source);
289+
[TestMethod]
290+
public async Task UnsupportedCSharpLanguageVersion_FromObservablePropertyGenerator_MultipleAttributes()
291+
{
292+
string source = @"
293+
using CommunityToolkit.Mvvm.ComponentModel;
294+
295+
namespace MyApp
296+
{
297+
[ObservableObject]
298+
public partial class {|MVVMTK0008:SampleViewModel|}
299+
{
300+
[ObservableProperty]
301+
string {|MVVMTK0008:name|};
302+
303+
[ObservableProperty]
304+
[NotifyPropertyChangedFor(nameof(Bar))]
305+
int {|MVVMTK0008:number|};
306+
307+
string Bar { get; set; }
308+
}
309+
}";
310+
311+
await VerifyUnsupportedCSharpVersionAndSuccessfulGeneration(source);
296312
}
297313

298314
[TestMethod]
299-
[Ignore("The generator should just not trigger at all in this scenario, update this after migrating diagnostics")]
300-
public void UnsupportedCSharpLanguageVersion_FromObservableValidatorValidateAllPropertiesGenerator()
315+
public async Task UnsupportedCSharpLanguageVersion_FromObservableValidatorValidateAllPropertiesGenerator()
301316
{
302317
string source = @"
303318
using System.ComponentModel.DataAnnotations;
@@ -312,15 +327,11 @@ public partial class SampleViewModel : ObservableValidator
312327
}
313328
}";
314329

315-
// Compilation should be fine on C# 7.3 as well (the generator just doesn't trigger)
316-
VerifyGeneratedDiagnostics<ObservableValidatorValidateAllPropertiesGenerator>(
317-
CSharpSyntaxTree.ParseText(source, CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.CSharp7_3)));
318-
319-
VerifySuccessfulGeneration(source);
330+
await VerifyUnsupportedCSharpVersionAndSuccessfulGeneration(source);
320331
}
321332

322333
[TestMethod]
323-
public void UnsupportedCSharpLanguageVersion_FromRelayCommandGenerator()
334+
public async Task UnsupportedCSharpLanguageVersion_FromRelayCommandGenerator()
324335
{
325336
string source = @"
326337
using CommunityToolkit.Mvvm.Input;
@@ -330,21 +341,17 @@ namespace MyApp
330341
public partial class SampleViewModel
331342
{
332343
[RelayCommand]
333-
private void GreetUser(object value)
344+
private void {|MVVMTK0008:GreetUser|}(object value)
334345
{
335346
}
336347
}
337348
}";
338349

339-
VerifyGeneratedDiagnostics<RelayCommandGenerator>(
340-
CSharpSyntaxTree.ParseText(source, CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.CSharp7_3)),
341-
"MVVMTK0008");
342-
343-
VerifySuccessfulGeneration(source);
350+
await VerifyUnsupportedCSharpVersionAndSuccessfulGeneration(source);
344351
}
345352

346353
[TestMethod]
347-
public void UnsupportedCSharpLanguageVersion_FromIMessengerRegisterAllGenerator()
354+
public async Task UnsupportedCSharpLanguageVersion_FromIMessengerRegisterAllGenerator()
348355
{
349356
string source = @"
350357
using CommunityToolkit.Mvvm.Messaging;
@@ -363,12 +370,7 @@ public void Receive(MyMessage message)
363370
}
364371
}";
365372

366-
// This should run fine on C# 8.0 too, as it doesn't use any newer features. Additionally, when not supported this
367-
// generator should just not run, not cause issues. The MVVM Toolkit has a reflection-based fallback path for this.
368-
VerifyGeneratedDiagnostics<IMessengerRegisterAllGenerator>(
369-
CSharpSyntaxTree.ParseText(source, CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.CSharp8)));
370-
371-
VerifySuccessfulGeneration(source);
373+
await VerifyUnsupportedCSharpVersionAndSuccessfulGeneration(source);
372374
}
373375

374376
[TestMethod]
@@ -1425,35 +1427,14 @@ private void GreetUser(User user)
14251427
VerifyGeneratedDiagnostics<RelayCommandGenerator>(source, "MVVMTK0031");
14261428
}
14271429

1428-
[TestMethod]
1429-
public void ValidObservablePropertyGeneratorScenarios()
1430-
{
1431-
string source = @"
1432-
using CommunityToolkit.Mvvm.ComponentModel;
1433-
1434-
namespace MyApp
1435-
{
1436-
[ObservableObject]
1437-
public partial class SampleViewModel
1438-
{
1439-
[ObservableProperty]
1440-
string name;
1441-
1442-
[ObservableProperty]
1443-
[NotifyPropertyChangedFor(nameof(Name))]
1444-
int number;
1445-
}
1446-
}";
1447-
1448-
VerifySuccessfulGeneration(source);
1449-
}
1450-
14511430
/// <summary>
1452-
/// Verifies that all available source generators can run successfully with the input source (including subsequent compilation).
1431+
/// Verifies the diagnostic error for unsupported C# version, and that all available source generators can run successfully with the input source (including subsequent compilation).
14531432
/// </summary>
1454-
/// <param name="source">The input source to process.</param>
1455-
private static void VerifySuccessfulGeneration(string source)
1433+
/// <param name="markdownSource">The input source to process with diagnostic annotations.</param>
1434+
private static async Task VerifyUnsupportedCSharpVersionAndSuccessfulGeneration(string markdownSource)
14561435
{
1436+
await CSharpAnalyzerWithLanguageVersionTest<UnsupportedCSharpLanguageVersionAnalyzer>.VerifyAnalyzerAsync(markdownSource, LanguageVersion.CSharp7_3);
1437+
14571438
IIncrementalGenerator[] generators =
14581439
{
14591440
new IMessengerRegisterAllGenerator(),
@@ -1466,7 +1447,10 @@ private static void VerifySuccessfulGeneration(string source)
14661447
new RelayCommandGenerator()
14671448
};
14681449

1469-
VerifyGeneratedDiagnostics(CSharpSyntaxTree.ParseText(source, CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.CSharp8)), generators, Array.Empty<string>());
1450+
// Transform diagnostic annotations back to normal C# (eg. "{|MVVMTK0008:Foo()|}" ---> "Foo()")
1451+
string source = Regex.Replace(markdownSource, @"{\|((?:,?\w+)+):(.+)\|}", m => m.Groups[2].Value);
1452+
1453+
VerifyGeneratedDiagnostics(CSharpSyntaxTree.ParseText(source, CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.CSharp7_3)), generators, Array.Empty<string>());
14701454
}
14711455

14721456
/// <summary>
@@ -1505,15 +1489,18 @@ private static void VerifyGeneratedDiagnostics<TGenerator>(SyntaxTree syntaxTree
15051489
/// <param name="generatorDiagnosticsIds">The diagnostic ids to expect for the input source code.</param>
15061490
private static void VerifyGeneratedDiagnostics(SyntaxTree syntaxTree, IIncrementalGenerator[] generators, string[] generatorDiagnosticsIds)
15071491
{
1492+
// Ensure CommunityToolkit.Mvvm and System.ComponentModel.DataAnnotations are loaded
15081493
Type observableObjectType = typeof(ObservableObject);
15091494
Type validationAttributeType = typeof(ValidationAttribute);
15101495

1496+
// Get all assembly references for the loaded assemblies (easy way to pull in all necessary dependencies)
15111497
IEnumerable<MetadataReference> references =
15121498
from assembly in AppDomain.CurrentDomain.GetAssemblies()
15131499
where !assembly.IsDynamic
15141500
let reference = MetadataReference.CreateFromFile(assembly.Location)
15151501
select reference;
15161502

1503+
// Create a syntax tree with the input source
15171504
CSharpCompilation compilation = CSharpCompilation.Create(
15181505
"original",
15191506
new SyntaxTree[] { syntaxTree },
@@ -1522,19 +1509,20 @@ from assembly in AppDomain.CurrentDomain.GetAssemblies()
15221509

15231510
GeneratorDriver driver = CSharpGeneratorDriver.Create(generators).WithUpdatedParseOptions((CSharpParseOptions)syntaxTree.Options);
15241511

1512+
// Run all source generators on the input source code
15251513
_ = driver.RunGeneratorsAndUpdateCompilation(compilation, out Compilation outputCompilation, out ImmutableArray<Diagnostic> diagnostics);
15261514

1527-
HashSet<string> resultingIds = diagnostics.Select(diagnostic => diagnostic.Id).ToHashSet();
1515+
string[] resultingIds = diagnostics.Select(diagnostic => diagnostic.Id).ToArray();
15281516

1529-
CollectionAssert.AreEquivalent(generatorDiagnosticsIds, resultingIds.ToArray(), $"resultingIds: {string.Join(", ", resultingIds)}");
1517+
CollectionAssert.AreEquivalent(generatorDiagnosticsIds, resultingIds, $"resultingIds: {string.Join(", ", resultingIds)}");
15301518

15311519
// If the compilation was supposed to succeed, ensure that no further errors were generated
1532-
if (resultingIds.Count == 0)
1520+
if (resultingIds.Length == 0)
15331521
{
15341522
// Compute diagnostics for the final compiled output (just include errors)
15351523
List<Diagnostic> outputCompilationDiagnostics = outputCompilation.GetDiagnostics().Where(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error).ToList();
15361524

1537-
Assert.IsTrue(outputCompilationDiagnostics.Count == 0, $"resultingIds:{Environment.NewLine} {string.Join(Environment.NewLine, outputCompilationDiagnostics)}");
1525+
Assert.IsTrue(outputCompilationDiagnostics.Count == 0, $"resultingIds: {string.Join(", ", outputCompilationDiagnostics)}");
15381526
}
15391527

15401528
GC.KeepAlive(observableObjectType);

0 commit comments

Comments
 (0)