public EnumerationHandler(INamedTypeSymbol symbol, GeneratorExecutionContext context)
        {
            _symbol  = symbol;
            _context = context;

            var attributeSymbol = context.GetSymbol <DescriptorAttribute>();

            _descriptorAttributeData = symbol.FindAttribute(attributeSymbol);

            _generatedFields = new LinkedList <IUpdateFieldGenerator>();
        }
Beispiel #2
0
        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);
        }
Beispiel #3
0
        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);