public EnumerationHandler(INamedTypeSymbol symbol, GeneratorExecutionContext context) { _symbol = symbol; _context = context; var attributeSymbol = context.GetSymbol <DescriptorAttribute>(); _descriptorAttributeData = symbol.FindAttribute(attributeSymbol); _generatedFields = new LinkedList <IUpdateFieldGenerator>(); }
public static bool HasAttribute <T>(this ISymbol symbol, GeneratorExecutionContext context) where T : Attribute { var attributeData = context.GetSymbol <T>(); if (attributeData == null) { return(false); } return(symbol.FindAttribute(attributeData) != null); }
public void Execute(GeneratorExecutionContext context) { // retrieve the populated receiver if (!(context.SyntaxContextReceiver is SyntaxReceiver receiver)) { return; } // get the added attribute, and INotifyPropertyChanged var notifySymbol = context.GetSymbol <INotifyPropertyChanged>(); // group the fields by class, and generate the source var fieldGroups = receiver.Fields.GroupBy(f => f.ContainingType, e => e, SymbolEqualityComparer.Default).ToDictionary(g => g.Key, g => g.ToList()); var propertyGroups = receiver.Properties.GroupBy(f => f.ContainingType, e => e, SymbolEqualityComparer.Default).ToDictionary(g => g.Key, g => g.ToList()); foreach (var containingType in fieldGroups.Select(f => f.Key) .Union(propertyGroups.Select(p => p.Key), SymbolEqualityComparer.Default).Cast <INamedTypeSymbol>()) { var npcImplemented = containingType.AllInterfaces.Contains(notifySymbol, SymbolEqualityComparer.Default); var npcEventHandler = context.GetSymbol <PropertyChangedEventHandler>(); if (!fieldGroups.TryGetValue(containingType, out var fields)) { fields = new List <IFieldSymbol>(); } if (!propertyGroups.TryGetValue(containingType, out var properties)) { properties = new List <IPropertySymbol>(); } var members = fields.Union(properties, SymbolEqualityComparer.Default); var file = _template.Render(new { GeneratorName = nameof(BitmaskPropertyGenerator), GenerationDate = DateTime.Now.ToString(), EnhancedTypeName = containingType.Name, NotifySymbolName = notifySymbol !.ToDisplayString(), NotifyEventHandler = npcImplemented ? null : npcEventHandler?.ToDisplayString(), ContainingNamespace = containingType.ContainingNamespace.ToDisplayString(), NeedsImplementation = containingType.GetAllMembers().All(m => m.Name != "NotifyPropertyChanged"), Properties = members.SelectMany(field => { if (field == null) { return(null); } var fieldType = field switch { IPropertySymbol propertySymbol => propertySymbol.Type, IFieldSymbol fieldSymbol => fieldSymbol.Type, _ => null }; if (fieldType == null) { return(null); } var attributeSymbol = context.Compilation.GetTypeByMetadataName(typeof(FlagsAttribute).FullName); var attributeData = fieldType.FindAttribute(attributeSymbol); if (attributeData == null) { return(null); } var fieldTypeEnumerations = fieldType.GetMembers().OfType <IFieldSymbol>(); return(fieldTypeEnumerations.Select(fieldEnumeration => { return new { BackingMember = field.Name, PropertyName = fieldEnumeration.Name, Enumeration = fieldEnumeration.Type.ToDisplayString() }; })); }).Where(i => i != null) }, memberInfo => memberInfo.Name);
public void Execute(GeneratorExecutionContext context) { // retrieve the populated receiver if (!(context.SyntaxContextReceiver is SyntaxReceiver receiver)) { return; } // get the added attribute, and INotifyPropertyChanged var notifySymbol = context.GetSymbol <INotifyPropertyChanged>(); var objectSymbol = context.GetSymbol <object>(); // group the fields by class, and generate the source foreach (var group in receiver.Fields.GroupBy(f => f.ContainingType, e => e, SymbolEqualityComparer.Default)) { var classSymbol = (INamedTypeSymbol)group.Key !; var npcImplemented = classSymbol.AllInterfaces.Contains(notifySymbol, SymbolEqualityComparer.Default); var npcEventHandler = context.GetSymbol <PropertyChangedEventHandler>(); string?chooseName(string fieldName, TypedConstant?overridenNameOpt) { if (overridenNameOpt.HasValue && overridenNameOpt.Value.IsNull) { return(overridenNameOpt.Value.Value !.ToString()); } fieldName = fieldName.TrimStart('_'); if (fieldName.Length == 0) { return(string.Empty); } if (fieldName.Length == 1) { return(fieldName.ToUpper()); } return(fieldName.Substring(0, 1).ToUpper() + fieldName.Substring(1)); } string?findCallbackName(AttributeData?attributeData, string callbackName) { if (attributeData == null) { return(null); } var arg = attributeData.FindArgument(callbackName); if (!arg.HasValue) { return(null); } if (arg.Value.IsNull) { return(null); } return(arg.Value.Value !.ToString()); } var file = _template.Render(new { GeneratorName = nameof(NotifyingPropertyGenerator), GenerationDate = DateTime.Now.ToString(CultureInfo.InvariantCulture), EnhancedTypeName = group.Key !.ToDisplayString().Split('.').Last(), BaseType = SymbolEqualityComparer.Default.Equals(classSymbol.BaseType, objectSymbol) ? null : classSymbol.BaseType, NotifySymbolName = notifySymbol !.ToDisplayString(), NotifyEventHandler = npcImplemented ? null : npcEventHandler?.ToDisplayString(), ContainingNamespace = classSymbol.ContainingNamespace.ToDisplayString(), NeedsImplementation = classSymbol.GetAllMembers().All(m => m.Name != "NotifyPropertyChanged"), Properties = group.Select(field => { var attributeData = field.FindAttribute <NotifyingPropertyAttribute>(context); var overridenNameOpt = attributeData?.NamedArguments.SingleOrDefault(kvp => kvp.Key == "PropertyName").Value; return(new { Type = field.Type.ToDisplayString(), FieldName = field.Name, PropertyName = chooseName(field.Name, overridenNameOpt), BeforeCallback = findCallbackName(attributeData, nameof(NotifyingPropertyAttribute.BeforeCallback)), AfterCallback = findCallbackName(attributeData, nameof(NotifyingPropertyAttribute.AfterCallback)) }); }) }, memberInfo => memberInfo.Name);