private PropertyDetails GetPropertyDetails(PropertyDeclarationSyntax propertyDeclaration, SemanticModel semModel)
        {
            var propertyType = Unknown;

            switch (propertyDeclaration.Type)
            {
            case GenericNameSyntax gns:
                propertyType = gns.ToString();     // Lazy way to get generic types
                break;

            case PredefinedTypeSyntax pds:
                propertyType = pds.Keyword.ValueText;
                break;

            case IdentifierNameSyntax ins:
                propertyType = ins.Identifier.ValueText;
                break;

            case QualifiedNameSyntax qns:
                propertyType = qns.Right.Identifier.ValueText;

                if (qns.Right is GenericNameSyntax qgns)
                {
                    propertyType += qgns.TypeArgumentList.ToString();
                }

                break;

            case NullableTypeSyntax nts:
                propertyType = ((PredefinedTypeSyntax)nts.ElementType).Keyword.Text;

                if (!propertyType.ToLowerInvariant().Contains("nullable"))
                {
                    propertyType += nts.QuestionToken.Text;
                }

                break;

            case ArrayTypeSyntax ats:
                propertyType = ats.ToString();
                break;
            }

            var propertyName = this.GetIdentifier(propertyDeclaration);

            bool?propIsReadOnly;
            var  setter = propertyDeclaration?.AccessorList?.Accessors
                          .FirstOrDefault(a => a.RawKind == (ushort)SyntaxKind.SetAccessorDeclaration);

            if (setter == null)
            {
                propIsReadOnly = true;
            }
            else
            {
                var setterModifiers = setter.Modifiers;
                propIsReadOnly = setterModifiers.Any(m => m.Kind() == SyntaxKind.PrivateKeyword);
            }

            var pd = new PropertyDetails
            {
                Name         = propertyName,
                PropertyType = propertyType,
                IsReadOnly   = propIsReadOnly ?? false,
            };

            foreach (var attribList in propertyDeclaration.AttributeLists)
            {
                foreach (var attrib in attribList.Attributes)
                {
                    var att = new AttributeDetails
                    {
                        Name = attrib.Name.ToString(),
                    };

                    var count = 1;
                    foreach (var arg in attrib.ArgumentList.Arguments)
                    {
                        string name  = null;
                        string value = null;

                        if (arg?.NameColon != null)
                        {
                            name  = arg.NameColon.Name.ToString();
                            value = ((arg.NameColon.Parent as AttributeArgumentSyntax).Expression as IdentifierNameSyntax).Identifier.Value.ToString();
                        }
                        else if (arg?.NameEquals != null)
                        {
                            name  = arg.NameEquals.Name.ToString();
                            value = ((arg.NameEquals.Parent as AttributeArgumentSyntax).Expression as IdentifierNameSyntax).Identifier.Value.ToString();
                        }
                        else
                        {
                            value = arg.ToString();
                        }

                        att.Arguments.Add(new AttributeArgumentDetails
                        {
                            Index = count++,
                            Name  = name,
                            Value = value,
                        });
                    }

                    pd.Attributes.Add(att);
                }
            }

            Logger?.RecordInfo(StringRes.Info_IdentifiedPropertySummary.WithParams(pd.Name, pd.PropertyType, pd.IsReadOnly));

            ITypeSymbol typeSymbol = this.GetTypeSymbol(semModel, propertyDeclaration, pd);

            pd.Symbol = typeSymbol;

            return(pd);
        }
        protected IEnumerable <AttributeDetails> GetAttributeDetails(SyntaxList <AttributeListSyntax> attributeList)
        {
            var result = new List <AttributeDetails>();

            foreach (var attribList in attributeList)
            {
                foreach (var attrib in attribList.Attributes)
                {
                    var att = new AttributeDetails
                    {
                        Name = attrib.Name.ToString(),
                    };

                    var count = 1;

                    if (attrib?.ArgumentList?.Arguments.Any() ?? false)
                    {
                        foreach (var arg in attrib?.ArgumentList.Arguments)
                        {
                            string name;
                            if (arg?.NameColon != null)
                            {
                                name = arg.NameColon.Name.Identifier.Text;
                            }
                            else if (arg?.NameEquals != null)
                            {
                                name = arg.NameEquals.Name.ToString();
                            }
                            else
                            {
                                name = string.Empty;
                            }

                            var expression = arg.Expression;

                            string value;
                            if (expression is IdentifierNameSyntax ins)
                            {
                                value = ins.Identifier.Value.ToString();
                            }
                            else if (expression is LiteralExpressionSyntax les)
                            {
                                value = les.ToString().Replace("\"", string.Empty);
                            }
                            else
                            {
                                value = arg.ToString();
                            }

                            Logger?.RecordInfo(StringRes.Info_FoundAttributeArgument.WithParams(name, value));

                            att.Arguments.Add(new AttributeArgumentDetails
                            {
                                Index = count++,
                                Name  = name,
                                Value = value,
                            });
                        }
                    }
                    else
                    {
                        Logger?.RecordInfo(StringRes.Info_NoArgumentsForAttribute);
                    }

                    result.Add(att);
                }
            }

            return(result);
        }