/// <summary> /// Called for every syntax node in the compilation, we can inspect the nodes and save any information useful for generation /// </summary> public void OnVisitSyntaxNode(GeneratorSyntaxContext context) { if (context.Node is ClassDeclarationSyntax classDeclaration) { INamedTypeSymbol classTypeSymbol = context.SemanticModel.GetDeclaredSymbol(classDeclaration) as INamedTypeSymbol; if (classTypeSymbol.GetAttributes().Any(ad => ad.AttributeClass.ToDisplayString() == "System.Mvvm.MVVMViewModelAttribute")) { ClassTypeSymbol = classTypeSymbol; var props = classDeclaration.Members.OfType <PropertyDeclarationSyntax>(); ImmutableArray <ISymbol> members = ClassTypeSymbol.GetMembers(); foreach (ISymbol member in members) { if (member is IFieldSymbol fieldSymbol) { if (fieldSymbol.Type.ToDisplayString() == "System.Mvvm.DelegateCommand") { CommandFields.Add(fieldSymbol); } } } //check to see if any properties are exposed if (props.Any()) { var commandFieldnames = new List <string>(); var fieldsToRemove = new List <IFieldSymbol>(); //work through each property foreach (PropertyDeclarationSyntax propertySyntax in props) { IPropertySymbol propertySymbol = context.SemanticModel.GetDeclaredSymbol(propertySyntax); if (propertySymbol.Type.ToDisplayString() == "System.Windows.Input.ICommand" || (propertySymbol.Type.ToDisplayString() == "System.Mvvm.DelegateCommand")) { var propCode = propertySyntax.ToString(); if (CommandFields.Any()) { foreach (var command in CommandFields) { if (propCode.Contains(command.Name)) { //don't notify the field as its cheaper to call the OnPropertyChanged notification fieldsToRemove.Add(command); } } } Properties.Add(propertySymbol); } } //remove removed fields :-) foreach (var field in fieldsToRemove) { CommandFields.Remove(field); } } } } }