@@ -247,6 +247,8 @@ public partial class SampleViewModel
247
247
VerifyGeneratedDiagnostics < INotifyPropertyChangedGenerator > (
248
248
CSharpSyntaxTree . ParseText ( source , CSharpParseOptions . Default . WithLanguageVersion ( LanguageVersion . CSharp7_3 ) ) ,
249
249
"MVVMTK0008" ) ;
250
+
251
+ VerifySuccessfulGeneration ( source ) ;
250
252
}
251
253
252
254
[ TestMethod ]
@@ -266,6 +268,8 @@ public partial class SampleViewModel
266
268
VerifyGeneratedDiagnostics < ObservableObjectGenerator > (
267
269
CSharpSyntaxTree . ParseText ( source , CSharpParseOptions . Default . WithLanguageVersion ( LanguageVersion . CSharp7_3 ) ) ,
268
270
"MVVMTK0008" ) ;
271
+
272
+ VerifySuccessfulGeneration ( source ) ;
269
273
}
270
274
271
275
[ TestMethod ]
@@ -287,12 +291,16 @@ public partial class SampleViewModel
287
291
VerifyGeneratedDiagnostics < ObservablePropertyGenerator > (
288
292
CSharpSyntaxTree . ParseText ( source , CSharpParseOptions . Default . WithLanguageVersion ( LanguageVersion . CSharp7_3 ) ) ,
289
293
"MVVMTK0008" ) ;
294
+
295
+ VerifySuccessfulGeneration ( source ) ;
290
296
}
291
297
292
298
[ TestMethod ]
299
+ [ Ignore ( "The generator should just not trigger at all in this scenario, update this after migrating diagnostics" ) ]
293
300
public void UnsupportedCSharpLanguageVersion_FromObservableValidatorValidateAllPropertiesGenerator ( )
294
301
{
295
302
string source = @"
303
+ using System.ComponentModel.DataAnnotations;
296
304
using CommunityToolkit.Mvvm.ComponentModel;
297
305
298
306
namespace MyApp
@@ -304,9 +312,11 @@ public partial class SampleViewModel : ObservableValidator
304
312
}
305
313
}" ;
306
314
307
- // This is explicitly allowed in C# < 8.0, as it doesn't use any new features
315
+ // Compilation should be fine on C# 7.3 as well (the generator just doesn't trigger)
308
316
VerifyGeneratedDiagnostics < ObservableValidatorValidateAllPropertiesGenerator > (
309
317
CSharpSyntaxTree . ParseText ( source , CSharpParseOptions . Default . WithLanguageVersion ( LanguageVersion . CSharp7_3 ) ) ) ;
318
+
319
+ VerifySuccessfulGeneration ( source ) ;
310
320
}
311
321
312
322
[ TestMethod ]
@@ -329,6 +339,8 @@ private void GreetUser(object value)
329
339
VerifyGeneratedDiagnostics < RelayCommandGenerator > (
330
340
CSharpSyntaxTree . ParseText ( source , CSharpParseOptions . Default . WithLanguageVersion ( LanguageVersion . CSharp7_3 ) ) ,
331
341
"MVVMTK0008" ) ;
342
+
343
+ VerifySuccessfulGeneration ( source ) ;
332
344
}
333
345
334
346
[ TestMethod ]
@@ -351,9 +363,12 @@ public void Receive(MyMessage message)
351
363
}
352
364
}" ;
353
365
354
- // This is explicitly allowed in C# < 8.0, as it doesn't use any new features
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.
355
368
VerifyGeneratedDiagnostics < IMessengerRegisterAllGenerator > (
356
- CSharpSyntaxTree . ParseText ( source , CSharpParseOptions . Default . WithLanguageVersion ( LanguageVersion . CSharp7_3 ) ) ) ;
369
+ CSharpSyntaxTree . ParseText ( source , CSharpParseOptions . Default . WithLanguageVersion ( LanguageVersion . CSharp8 ) ) ) ;
370
+
371
+ VerifySuccessfulGeneration ( source ) ;
357
372
}
358
373
359
374
[ TestMethod ]
@@ -1410,6 +1425,50 @@ private void GreetUser(User user)
1410
1425
VerifyGeneratedDiagnostics < RelayCommandGenerator > ( source , "MVVMTK0031" ) ;
1411
1426
}
1412
1427
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
+
1451
+ /// <summary>
1452
+ /// Verifies that all available source generators can run successfully with the input source (including subsequent compilation).
1453
+ /// </summary>
1454
+ /// <param name="source">The input source to process.</param>
1455
+ private static void VerifySuccessfulGeneration ( string source )
1456
+ {
1457
+ IIncrementalGenerator [ ] generators =
1458
+ {
1459
+ new IMessengerRegisterAllGenerator ( ) ,
1460
+ new NullabilityAttributesGenerator ( ) ,
1461
+ new ObservableObjectGenerator ( ) ,
1462
+ new INotifyPropertyChangedGenerator ( ) ,
1463
+ new ObservablePropertyGenerator ( ) ,
1464
+ new ObservableRecipientGenerator ( ) ,
1465
+ new ObservableValidatorValidateAllPropertiesGenerator ( ) ,
1466
+ new RelayCommandGenerator ( )
1467
+ } ;
1468
+
1469
+ VerifyGeneratedDiagnostics ( CSharpSyntaxTree . ParseText ( source , CSharpParseOptions . Default . WithLanguageVersion ( LanguageVersion . CSharp8 ) ) , generators , Array . Empty < string > ( ) ) ;
1470
+ }
1471
+
1413
1472
/// <summary>
1414
1473
/// Verifies the output of a source generator.
1415
1474
/// </summary>
@@ -1419,17 +1478,32 @@ private void GreetUser(User user)
1419
1478
private static void VerifyGeneratedDiagnostics < TGenerator > ( string source , params string [ ] diagnosticsIds )
1420
1479
where TGenerator : class , IIncrementalGenerator , new ( )
1421
1480
{
1422
- VerifyGeneratedDiagnostics < TGenerator > ( CSharpSyntaxTree . ParseText ( source ) , diagnosticsIds ) ;
1481
+ IIncrementalGenerator generator = new TGenerator ( ) ;
1482
+
1483
+ VerifyGeneratedDiagnostics ( CSharpSyntaxTree . ParseText ( source , CSharpParseOptions . Default . WithLanguageVersion ( LanguageVersion . CSharp8 ) ) , new [ ] { generator } , diagnosticsIds ) ;
1423
1484
}
1424
1485
1425
1486
/// <summary>
1426
1487
/// Verifies the output of a source generator.
1427
1488
/// </summary>
1428
1489
/// <typeparam name="TGenerator">The generator type to use.</typeparam>
1429
- /// <param name="syntaxTree">The input source tree to process.</param>
1490
+ /// <param name="syntaxTree">The input source to process.</param>
1430
1491
/// <param name="diagnosticsIds">The diagnostic ids to expect for the input source code.</param>
1431
1492
private static void VerifyGeneratedDiagnostics < TGenerator > ( SyntaxTree syntaxTree , params string [ ] diagnosticsIds )
1432
1493
where TGenerator : class , IIncrementalGenerator , new ( )
1494
+ {
1495
+ IIncrementalGenerator generator = new TGenerator ( ) ;
1496
+
1497
+ VerifyGeneratedDiagnostics ( syntaxTree , new [ ] { generator } , diagnosticsIds ) ;
1498
+ }
1499
+
1500
+ /// <summary>
1501
+ /// Verifies the output of one or more source generators.
1502
+ /// </summary>
1503
+ /// <param name="syntaxTree">The input source tree to process.</param>
1504
+ /// <param name="generators">The generators to apply to the input syntax tree.</param>
1505
+ /// <param name="generatorDiagnosticsIds">The diagnostic ids to expect for the input source code.</param>
1506
+ private static void VerifyGeneratedDiagnostics ( SyntaxTree syntaxTree , IIncrementalGenerator [ ] generators , string [ ] generatorDiagnosticsIds )
1433
1507
{
1434
1508
Type observableObjectType = typeof ( ObservableObject ) ;
1435
1509
Type validationAttributeType = typeof ( ValidationAttribute ) ;
@@ -1446,15 +1520,22 @@ from assembly in AppDomain.CurrentDomain.GetAssemblies()
1446
1520
references ,
1447
1521
new CSharpCompilationOptions ( OutputKind . DynamicallyLinkedLibrary ) ) ;
1448
1522
1449
- IIncrementalGenerator generator = new TGenerator ( ) ;
1450
-
1451
- GeneratorDriver driver = CSharpGeneratorDriver . Create ( generator ) . WithUpdatedParseOptions ( ( CSharpParseOptions ) syntaxTree . Options ) ;
1523
+ GeneratorDriver driver = CSharpGeneratorDriver . Create ( generators ) . WithUpdatedParseOptions ( ( CSharpParseOptions ) syntaxTree . Options ) ;
1452
1524
1453
1525
_ = driver . RunGeneratorsAndUpdateCompilation ( compilation , out Compilation outputCompilation , out ImmutableArray < Diagnostic > diagnostics ) ;
1454
1526
1455
1527
HashSet < string > resultingIds = diagnostics . Select ( diagnostic => diagnostic . Id ) . ToHashSet ( ) ;
1456
1528
1457
- CollectionAssert . AreEquivalent ( diagnosticsIds , resultingIds . ToArray ( ) ) ;
1529
+ CollectionAssert . AreEquivalent ( generatorDiagnosticsIds , resultingIds . ToArray ( ) , $ "resultingIds: { string . Join ( ", " , resultingIds ) } ") ;
1530
+
1531
+ // If the compilation was supposed to succeed, ensure that no further errors were generated
1532
+ if ( resultingIds . Count == 0 )
1533
+ {
1534
+ // Compute diagnostics for the final compiled output (just include errors)
1535
+ List < Diagnostic > outputCompilationDiagnostics = outputCompilation . GetDiagnostics ( ) . Where ( diagnostic => diagnostic . Severity == DiagnosticSeverity . Error ) . ToList ( ) ;
1536
+
1537
+ Assert . IsTrue ( outputCompilationDiagnostics . Count == 0 , $ "resultingIds:{ Environment . NewLine } { string . Join ( Environment . NewLine , outputCompilationDiagnostics ) } ") ;
1538
+ }
1458
1539
1459
1540
GC . KeepAlive ( observableObjectType ) ;
1460
1541
GC . KeepAlive ( validationAttributeType ) ;
0 commit comments