Skip to content

Commit 61e9e47

Browse files
committed
Update source generator tests to actually generate the compiled output, update tests to use the minimum supported C# language version (8.0), and also validate that unsupported version cases actually succeed with the supported version
1 parent 31e712f commit 61e9e47

File tree

1 file changed

+93
-10
lines changed

1 file changed

+93
-10
lines changed

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

Lines changed: 93 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
using Microsoft.CodeAnalysis.CSharp;
1212
using CommunityToolkit.Mvvm.ComponentModel;
1313
using Microsoft.VisualStudio.TestTools.UnitTesting;
14+
using System.Reflection.Emit;
1415

1516
namespace CommunityToolkit.Mvvm.SourceGenerators.UnitTests;
1617

@@ -247,6 +248,9 @@ public partial class SampleViewModel
247248
VerifyGeneratedDiagnostics<INotifyPropertyChangedGenerator>(
248249
CSharpSyntaxTree.ParseText(source, CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.CSharp7_3)),
249250
"MVVMTK0008");
251+
252+
// Ensure that it succeeds with the minimum supported language version
253+
VerifySuccessfulGeneration(source);
250254
}
251255

252256
[TestMethod]
@@ -266,6 +270,9 @@ public partial class SampleViewModel
266270
VerifyGeneratedDiagnostics<ObservableObjectGenerator>(
267271
CSharpSyntaxTree.ParseText(source, CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.CSharp7_3)),
268272
"MVVMTK0008");
273+
274+
// Ensure that it succeeds with the minimum supported language version
275+
VerifySuccessfulGeneration(source);
269276
}
270277

271278
[TestMethod]
@@ -287,12 +294,16 @@ public partial class SampleViewModel
287294
VerifyGeneratedDiagnostics<ObservablePropertyGenerator>(
288295
CSharpSyntaxTree.ParseText(source, CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.CSharp7_3)),
289296
"MVVMTK0008");
297+
298+
// Ensure that it succeeds with the minimum supported language version
299+
VerifySuccessfulGeneration(source);
290300
}
291301

292302
[TestMethod]
293303
public void UnsupportedCSharpLanguageVersion_FromObservableValidatorValidateAllPropertiesGenerator()
294304
{
295305
string source = @"
306+
using System.ComponentModel.DataAnnotations;
296307
using CommunityToolkit.Mvvm.ComponentModel;
297308
298309
namespace MyApp
@@ -304,9 +315,12 @@ public partial class SampleViewModel : ObservableValidator
304315
}
305316
}";
306317

307-
// This is explicitly allowed in C# < 8.0, as it doesn't use any new features
308318
VerifyGeneratedDiagnostics<ObservableValidatorValidateAllPropertiesGenerator>(
309-
CSharpSyntaxTree.ParseText(source, CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.CSharp7_3)));
319+
CSharpSyntaxTree.ParseText(source, CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.CSharp7_3)),
320+
"MVVMTK0008");
321+
322+
// Ensure that it succeeds with the minimum supported language version
323+
VerifySuccessfulGeneration(source);
310324
}
311325

312326
[TestMethod]
@@ -329,6 +343,9 @@ private void GreetUser(object value)
329343
VerifyGeneratedDiagnostics<RelayCommandGenerator>(
330344
CSharpSyntaxTree.ParseText(source, CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.CSharp7_3)),
331345
"MVVMTK0008");
346+
347+
// Ensure that it succeeds with the minimum supported language version
348+
VerifySuccessfulGeneration(source);
332349
}
333350

334351
[TestMethod]
@@ -351,9 +368,12 @@ public void Receive(MyMessage message)
351368
}
352369
}";
353370

354-
// This is explicitly allowed in C# < 8.0, as it doesn't use any new features
355371
VerifyGeneratedDiagnostics<IMessengerRegisterAllGenerator>(
356-
CSharpSyntaxTree.ParseText(source, CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.CSharp7_3)));
372+
CSharpSyntaxTree.ParseText(source, CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.CSharp7_3)),
373+
"MVVMTK0008");
374+
375+
// Ensure that it succeeds with the minimum supported language version
376+
VerifySuccessfulGeneration(source);
357377
}
358378

359379
[TestMethod]
@@ -1410,6 +1430,29 @@ private void GreetUser(User user)
14101430
VerifyGeneratedDiagnostics<RelayCommandGenerator>(source, "MVVMTK0031");
14111431
}
14121432

1433+
[TestMethod]
1434+
public void ValidObservablePropertyGeneratorScenarios()
1435+
{
1436+
string source = @"
1437+
using CommunityToolkit.Mvvm.ComponentModel;
1438+
1439+
namespace MyApp
1440+
{
1441+
[ObservableObject]
1442+
public partial class SampleViewModel
1443+
{
1444+
[ObservableProperty]
1445+
string name;
1446+
1447+
[ObservableProperty]
1448+
[NotifyPropertyChangedFor(nameof(Name))]
1449+
int number;
1450+
}
1451+
}";
1452+
1453+
VerifySuccessfulGeneration(source);
1454+
}
1455+
14131456
/// <summary>
14141457
/// Verifies the output of a source generator.
14151458
/// </summary>
@@ -1419,17 +1462,50 @@ private void GreetUser(User user)
14191462
private static void VerifyGeneratedDiagnostics<TGenerator>(string source, params string[] diagnosticsIds)
14201463
where TGenerator : class, IIncrementalGenerator, new()
14211464
{
1422-
VerifyGeneratedDiagnostics<TGenerator>(CSharpSyntaxTree.ParseText(source), diagnosticsIds);
1465+
IIncrementalGenerator generator = new TGenerator();
1466+
VerifyGeneratedDiagnostics(CSharpSyntaxTree.ParseText(source, CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.CSharp8)), new[] { generator }, diagnosticsIds);
1467+
}
1468+
1469+
/// <summary>
1470+
/// Verifies the output of all source generators for input source (including subsequent compilation).
1471+
/// </summary>
1472+
/// <param name="source"></param>
1473+
private static void VerifySuccessfulGeneration(string source)
1474+
{
1475+
IIncrementalGenerator[] generators =
1476+
{
1477+
new IMessengerRegisterAllGenerator(),
1478+
new NullabilityAttributesGenerator(),
1479+
new ObservableObjectGenerator(),
1480+
new INotifyPropertyChangedGenerator(),
1481+
new ObservablePropertyGenerator(),
1482+
new ObservableRecipientGenerator(),
1483+
new ObservableValidatorValidateAllPropertiesGenerator(),
1484+
new RelayCommandGenerator()
1485+
};
1486+
VerifyGeneratedDiagnostics(CSharpSyntaxTree.ParseText(source, CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.CSharp8)), generators, new string[] { });
14231487
}
14241488

14251489
/// <summary>
14261490
/// Verifies the output of a source generator.
14271491
/// </summary>
14281492
/// <typeparam name="TGenerator">The generator type to use.</typeparam>
1429-
/// <param name="syntaxTree">The input source tree to process.</param>
1493+
/// <param name="syntaxTree">The input source to process.</param>
14301494
/// <param name="diagnosticsIds">The diagnostic ids to expect for the input source code.</param>
14311495
private static void VerifyGeneratedDiagnostics<TGenerator>(SyntaxTree syntaxTree, params string[] diagnosticsIds)
14321496
where TGenerator : class, IIncrementalGenerator, new()
1497+
{
1498+
IIncrementalGenerator generator = new TGenerator();
1499+
VerifyGeneratedDiagnostics(syntaxTree, new[] { generator }, diagnosticsIds);
1500+
}
1501+
1502+
/// <summary>
1503+
/// Verifies the output of a source generator.
1504+
/// </summary>
1505+
/// <typeparam name="TGenerator">The generator type to use.</typeparam>
1506+
/// <param name="syntaxTree">The input source tree to process.</param>
1507+
/// <param name="diagnosticsIds">The diagnostic ids to expect for the input source code.</param>
1508+
private static void VerifyGeneratedDiagnostics(SyntaxTree syntaxTree, IIncrementalGenerator[] generators, string[] generatorDiagnosticsIds)
14331509
{
14341510
Type observableObjectType = typeof(ObservableObject);
14351511
Type validationAttributeType = typeof(ValidationAttribute);
@@ -1446,15 +1522,22 @@ from assembly in AppDomain.CurrentDomain.GetAssemblies()
14461522
references,
14471523
new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
14481524

1449-
IIncrementalGenerator generator = new TGenerator();
1450-
1451-
GeneratorDriver driver = CSharpGeneratorDriver.Create(generator).WithUpdatedParseOptions((CSharpParseOptions)syntaxTree.Options);
1525+
GeneratorDriver driver = CSharpGeneratorDriver.Create(generators).WithUpdatedParseOptions((CSharpParseOptions)syntaxTree.Options);
14521526

14531527
_ = driver.RunGeneratorsAndUpdateCompilation(compilation, out Compilation outputCompilation, out ImmutableArray<Diagnostic> diagnostics);
14541528

14551529
HashSet<string> resultingIds = diagnostics.Select(diagnostic => diagnostic.Id).ToHashSet();
14561530

1457-
CollectionAssert.AreEquivalent(diagnosticsIds, resultingIds.ToArray());
1531+
CollectionAssert.AreEquivalent(generatorDiagnosticsIds, resultingIds.ToArray(), $"resultingIds: {string.Join(", ", resultingIds)}");
1532+
1533+
// If the compilation was supposed to succeed, ensure that no further errors were generated
1534+
if (resultingIds.Count == 0)
1535+
{
1536+
// Compute diagnostics for the final compiled output (just include errors)
1537+
List<Diagnostic> outputCompilationDiagnostics = outputCompilation.GetDiagnostics().Where(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error).ToList();
1538+
1539+
Assert.IsTrue(outputCompilationDiagnostics.Count == 0, $"resultingIds:{Environment.NewLine} {string.Join(Environment.NewLine, outputCompilationDiagnostics)}");
1540+
}
14581541

14591542
GC.KeepAlive(observableObjectType);
14601543
GC.KeepAlive(validationAttributeType);

0 commit comments

Comments
 (0)