Exemplo n.º 1
0
        /// <summary>
        /// Extract the data that will be needed for source generation from the syntax tree provided
        /// </summary>
        /// <param name="extractionContext">The definition extraction context in which the extraction is being performed</param>
        /// <param name="targetTypeDeclaration">The TypeDeclarationSyntax from which to extract the necessary data</param>
        /// <returns>ExtractedTypeDefinition containing the data extracted from the syntax tree</returns>
        public static ExtractedTypeDefinition ExtractTypeDefinition(DefinitionExtractionContext extractionContext, TypeDeclarationSyntax targetTypeDeclaration)
        {
            ExtractedTypeDefinition definition = new ExtractedTypeDefinition();
            StringBuilder           fullyQualifiedNameBuilder = new StringBuilder();

            definition.TypeName  = GetTypeName(extractionContext, targetTypeDeclaration);
            definition.TypeKind  = GetTypeKind(extractionContext, targetTypeDeclaration);
            definition.Namespace = GetNamespace(extractionContext, targetTypeDeclaration);
            definition.Scope     = GetScopeDefinition(extractionContext, targetTypeDeclaration);

            foreach (ExtractedContainerDefinition containerDefinition in ContainerDefinitionsExtractor.GetContainerDefinitions(extractionContext, targetTypeDeclaration))
            {
                definition.ContainerDefinitions.Add(containerDefinition);
                fullyQualifiedNameBuilder.Append(containerDefinition.Name);
                fullyQualifiedNameBuilder.Append(".");
            }

            foreach (ExtractedPropertyDefinition propertyDefinition in PropertyDefinitionsExtractor.ExtractPropertyDefinitions(extractionContext, targetTypeDeclaration))
            {
                definition.Properties.Add(propertyDefinition);
            }

            foreach (ExtractedFieldDefinition fieldDefinition in FieldDefinitionsExtractor.ExtractFieldDefinitions(extractionContext, targetTypeDeclaration))
            {
                definition.Fields.Add(fieldDefinition);
            }

            fullyQualifiedNameBuilder.Append(definition.TypeName);
            definition.FullyQualifiedName = fullyQualifiedNameBuilder.ToString();

            return(definition);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Extract the scope of the type for which we will be generating code
        /// </summary>
        /// <param name="extractionContext">The definition extraction context in which the extraction is being performed</param>
        /// <param name="targetTypeDeclaration">The TypeDeclarationSyntax from which to extract the necessary information</param>
        /// <returns>The scope of the type for which generation is being performed</returns>
        private static string GetScopeDefinition(DefinitionExtractionContext extractionContext, TypeDeclarationSyntax targetTypeDeclaration)
        {
            StringBuilder scopeNameBuilder = new StringBuilder();

            foreach (SyntaxToken modifier in targetTypeDeclaration.Modifiers)
            {
                if (modifier.IsKind(Microsoft.CodeAnalysis.CSharp.SyntaxKind.PublicKeyword))
                {
                    AppendScopeName(scopeNameBuilder, modifier.ValueText);
                    continue;
                }
                if (modifier.IsKind(Microsoft.CodeAnalysis.CSharp.SyntaxKind.InternalKeyword))
                {
                    AppendScopeName(scopeNameBuilder, modifier.ValueText);
                    continue;
                }
                if (modifier.IsKind(Microsoft.CodeAnalysis.CSharp.SyntaxKind.ProtectedKeyword))
                {
                    AppendScopeName(scopeNameBuilder, modifier.ValueText);
                    continue;
                }
                if (modifier.IsKind(Microsoft.CodeAnalysis.CSharp.SyntaxKind.PrivateKeyword))
                {
                    AppendScopeName(scopeNameBuilder, modifier.ValueText);
                    continue;
                }
            }

            if (scopeNameBuilder.Length < 1)
            {
                scopeNameBuilder.Append("internal");
            }

            return(scopeNameBuilder.ToString().Trim());
        }
Exemplo n.º 3
0
        /// <summary>
        /// Determine if a property has one of the scopes requested by a caller
        /// </summary>
        /// <param name="context">The definition extraction context for this extraction</param>
        /// <param name="propertyDeclaration">The declaration of the property being tested</param>
        /// <param name="scopes">The list of scopes in which the caller is interested</param>
        /// <returns>Boolean true if the property has one of the scopes requested by the caller, else false</returns>
        private static bool HasOneOfScopes(DefinitionExtractionContext context, PropertyDeclarationSyntax propertyDeclaration, params string[] scopes)
        {
            foreach (string scope in scopes)
            {
                if (propertyDeclaration.Modifiers.Any(m => m.ValueText.Equals(scope, StringComparison.InvariantCultureIgnoreCase)))
                {
                    return(true);
                }
            }

            return(false);
        }
Exemplo n.º 4
0
        /// <summary>
        /// Extract information about a single property from its declaration in the syntax tree
        /// </summary>
        /// <param name="extractionContext">The definition extraction context in which the extraction is being performed</param>
        /// <param name="targetTypeDeclaration">The PropertyDeclarationSyntax from which to extract the necessary data</param>
        /// <returns>A readonly list of ExtractedPropertyDefinition containing the data extracted from the syntax tree</returns>
        public static ExtractedPropertyDefinition ExtractPropertyDefinition(DefinitionExtractionContext extractionContext, PropertyDeclarationSyntax propertyDeclaration)
        {
            ExtractedPropertyDefinition propertyDefinition = new ExtractedPropertyDefinition();

            propertyDefinition.PropertyName                           = GetPropertyName(extractionContext, propertyDeclaration);
            propertyDefinition.TypeDefinition.TypeName                = GetPropertyTypeName(extractionContext, propertyDeclaration);
            propertyDefinition.TypeDefinition.TypeNamespace           = extractionContext.GetTypeNamespace(propertyDeclaration.Type);
            propertyDefinition.TypeDefinition.IsAutoSerializable      = extractionContext.IsTypeAutoSerializable(propertyDeclaration.Type);
            propertyDefinition.TypeDefinition.ImplementsIMobileObject = extractionContext.DoesTypeImplementIMobileObject(propertyDeclaration.Type);

            return(propertyDefinition);
        }
        /// <summary>
        /// Extract information about a single field from its declaration in the syntax tree
        /// </summary>
        /// <param name="extractionContext">The definition extraction context in which the extraction is being performed</param>
        /// <param name="fieldDeclaration">The FieldDeclarationSyntax from which to extract the necessary data</param>
        /// <returns>A readonly list of ExtractedFieldDefinition containing the data extracted from the syntax tree</returns>
        public static ExtractedFieldDefinition ExtractFieldDefinition(DefinitionExtractionContext extractionContext, FieldDeclarationSyntax fieldDeclaration)
        {
            ExtractedFieldDefinition fieldDefinition = new ExtractedFieldDefinition();

            fieldDefinition.FieldName = GetFieldName(extractionContext, fieldDeclaration);
            fieldDefinition.TypeDefinition.TypeName                = GetFieldTypeName(extractionContext, fieldDeclaration);
            fieldDefinition.TypeDefinition.TypeNamespace           = extractionContext.GetTypeNamespace(fieldDeclaration.Declaration.Type);
            fieldDefinition.TypeDefinition.IsAutoSerializable      = extractionContext.IsTypeAutoSerializable(fieldDeclaration.Declaration.Type);
            fieldDefinition.TypeDefinition.ImplementsIMobileObject = extractionContext.DoesTypeImplementIMobileObject(fieldDeclaration.Declaration.Type);

            return(fieldDefinition);
        }
        /// <summary>
        /// Get the field declarations for all fields which have been explicitly included in serialization
        /// </summary>
        /// <param name="extractionContext">The definition extraction context in which the extraction is being performed</param>
        /// <param name="targetTypeDeclaration">The TypeDeclarationSyntax from which to extract the necessary data</param>
        /// <returns>A readonly list of field declarations to be included in serialization</returns>
        private static List <FieldDeclarationSyntax> GetAllIncludedFields(DefinitionExtractionContext extractionContext, TypeDeclarationSyntax targetTypeDeclaration)
        {
            List <FieldDeclarationSyntax> serializableFields;

            // Get any private or protected fields that are opted in with the use of the [AutoSerialized] attribute
            serializableFields = targetTypeDeclaration.Members.Where(
                m => m is FieldDeclarationSyntax fieldDeclaration &&
                extractionContext.IsFieldDecoratedWithAutoSerialized(fieldDeclaration))
                                 .Cast <FieldDeclarationSyntax>()
                                 .ToList();

            return(serializableFields);
        }
        /// <summary>
        /// Get the field declarations for all public fields which are not explicitly excluded from serialization
        /// </summary>
        /// <param name="extractionContext">The definition extraction context in which the extraction is being performed</param>
        /// <param name="targetTypeDeclaration">The TypeDeclarationSyntax from which to extract the necessary data</param>
        /// <returns>A readonly list of field declarations to be included in serialization</returns>
        private static List <FieldDeclarationSyntax> GetPublicNonExcludedFields(DefinitionExtractionContext extractionContext, TypeDeclarationSyntax targetTypeDeclaration)
        {
            List <FieldDeclarationSyntax> serializableFields;

            // Get all fields that are not specifically opted out with the [AutoNonSerialized] attribute
            serializableFields = targetTypeDeclaration.Members.Where(
                m => m is FieldDeclarationSyntax fieldDeclaration &&
                HasOneOfScopes(extractionContext, fieldDeclaration, "public") &&
                !extractionContext.IsFieldDecoratedWithAutoNonSerialized(fieldDeclaration))
                                 .Cast <FieldDeclarationSyntax>()
                                 .ToList();

            return(serializableFields);
        }
Exemplo n.º 8
0
        /// <summary>
        /// Extract the namespace of the type for which we will be generating code
        /// </summary>
        /// <param name="extractionContext">The definition extraction context in which the extraction is being performed</param>
        /// <param name="targetTypeDeclaration">The TypeDeclarationSyntax from which to extract the necessary information</param>
        /// <returns>The namespace of the type for which generation is being performed</returns>
        private static string GetNamespace(DefinitionExtractionContext extractionContext, TypeDeclarationSyntax targetTypeDeclaration)
        {
            string namespaceName = string.Empty;
            NamespaceDeclarationSyntax namespaceDeclaration;
            TypeDeclarationSyntax      containingTypeDeclaration;

            // Iterate through the containing types should the target type be nested inside other types
            containingTypeDeclaration = targetTypeDeclaration;
            while (containingTypeDeclaration.Parent is TypeDeclarationSyntax)
            {
                containingTypeDeclaration = (TypeDeclarationSyntax)containingTypeDeclaration.Parent;
            }

            namespaceDeclaration = containingTypeDeclaration.Parent as NamespaceDeclarationSyntax;
            if (namespaceDeclaration is not null)
            {
                namespaceName = namespaceDeclaration.Name.ToString();
            }

            return(namespaceName);
        }
Exemplo n.º 9
0
        /// <summary>
        /// Test syntax nodes to see if they represent a type for which we must generate code
        /// </summary>
        /// <param name="context">The generator context supplied by Roslyn</param>
        public void OnVisitSyntaxNode(GeneratorSyntaxContext generatorSyntaxContext)
        {
            SyntaxNode    syntaxNode;
            SemanticModel model;
            DefinitionExtractionContext context;
            ExtractedTypeDefinition     typeDefinition;

            syntaxNode = generatorSyntaxContext.Node;
            model      = generatorSyntaxContext.SemanticModel;

            if (syntaxNode is not TypeDeclarationSyntax typeDeclarationSyntax)
            {
                return;
            }
            context = new DefinitionExtractionContext(generatorSyntaxContext);

            if (context.IsTypeAutoSerializable(typeDeclarationSyntax))
            {
                typeDefinition = TypeDefinitionExtractor.ExtractTypeDefinition(context, typeDeclarationSyntax);
                Targets.Add(typeDefinition);
            }
        }
Exemplo n.º 10
0
        private static ExtractedContainerDefinition GetContainerDefinition(DefinitionExtractionContext extractionContext, NamespaceDeclarationSyntax namespaceDeclarationSyntax)
        {
            StringBuilder containerDefinitionBuilder = new StringBuilder();
            ExtractedContainerDefinition containerDefinition;

            foreach (SyntaxToken modifier in namespaceDeclarationSyntax.Modifiers)
            {
                containerDefinitionBuilder.Append(modifier.ToString());
                containerDefinitionBuilder.Append(" ");
            }

            containerDefinitionBuilder.Append("namespace ");
            containerDefinitionBuilder.Append(namespaceDeclarationSyntax.Name.ToString());

            containerDefinition = new ExtractedContainerDefinition()
            {
                Name           = namespaceDeclarationSyntax.Name.ToString(),
                FullDefinition = containerDefinitionBuilder.ToString()
            };

            return(containerDefinition);
        }
Exemplo n.º 11
0
        private static ExtractedContainerDefinition GetContainerDefinition(DefinitionExtractionContext extractionContext, TypeDeclarationSyntax typeDeclarationSyntax)
        {
            StringBuilder containerDefinitionBuilder = new StringBuilder();
            ExtractedContainerDefinition containerDefinition;

            foreach (SyntaxToken modifier in typeDeclarationSyntax.Modifiers)
            {
                containerDefinitionBuilder.Append(modifier.ToString());
                containerDefinitionBuilder.Append(" ");
            }

            containerDefinitionBuilder.Append(typeDeclarationSyntax.Keyword.ToString());
            containerDefinitionBuilder.Append(" ");
            containerDefinitionBuilder.Append(typeDeclarationSyntax.Identifier.ToString());

            containerDefinition = new ExtractedContainerDefinition()
            {
                Name           = typeDeclarationSyntax.Identifier.ToString(),
                FullDefinition = containerDefinitionBuilder.ToString()
            };

            return(containerDefinition);
        }
Exemplo n.º 12
0
        /// <summary>
        /// Determine if a property has both a getter and a setter
        /// </summary>
        /// <param name="context">The definition extraction context for this extraction</param>
        /// <param name="propertyDeclaration">The declaration of the property being tested</param>
        /// <returns>Boolean true if the property has both a getter and setter (of any scope), else false</returns>
        private static bool HasGetterAndSetter(DefinitionExtractionContext context, PropertyDeclarationSyntax propertyDeclaration)
        {
            bool hasGetter = false;
            bool hasSetter = false;

            if (propertyDeclaration.AccessorList is null)
            {
                return(false);
            }

            foreach (AccessorDeclarationSyntax accessorDeclaration in propertyDeclaration.AccessorList.Accessors)
            {
                if (accessorDeclaration.Kind() == Microsoft.CodeAnalysis.CSharp.SyntaxKind.GetAccessorDeclaration)
                {
                    hasGetter = true;
                }
                if (accessorDeclaration.Kind() == Microsoft.CodeAnalysis.CSharp.SyntaxKind.SetAccessorDeclaration)
                {
                    hasSetter = true;
                }
            }

            return(hasGetter && hasSetter);
        }
Exemplo n.º 13
0
        /// <summary>
        /// Get the property declarations for all fields which are to be serialized
        /// </summary>
        /// <param name="extractionContext">The definition extraction context in which the extraction is being performed</param>
        /// <param name="targetTypeDeclaration">The TypeDeclarationSyntax from which to extract the necessary data</param>
        /// <returns>A readonly list of field declarations to be included in serialization</returns>
        private static IReadOnlyList <FieldDeclarationSyntax> GetSerializableFieldDeclarations(DefinitionExtractionContext extractionContext, TypeDeclarationSyntax targetTypeDeclaration)
        {
            List <FieldDeclarationSyntax> serializableFields;
            List <FieldDeclarationSyntax> optedInSerializableFields;

            // Get all fields that are not specifically opted out with the [AutoNonSerialized] attribute
            serializableFields = GetPublicNonExcludedFields(extractionContext, targetTypeDeclaration);

            // Add any pfields that are opted in with the use of the [AutoSerialized] attribute
            optedInSerializableFields = GetNonPublicIncludedFields(extractionContext, targetTypeDeclaration);
            serializableFields.AddRange(optedInSerializableFields);
            // serializableFields = GetAllIncludedFields(extractionContext, targetTypeDeclaration);

            return(serializableFields);
        }
Exemplo n.º 14
0
 /// <summary>
 /// Extract the textual definition of the kind that this type represents
 /// </summary>
 /// <param name="extractionContext">The definition extraction context in which the extraction is being performed</param>
 /// <param name="targetTypeDeclaration">The TypeDeclarationSyntax from which to extract the necessary information</param>
 /// <returns>The kind of the type for which generation is being performed</returns>
 private static string GetTypeKind(DefinitionExtractionContext extractionContext, TypeDeclarationSyntax targetTypeDeclaration)
 {
     return(targetTypeDeclaration.Keyword.ToString());
 }
Exemplo n.º 15
0
 /// <summary>
 /// Extract the name of the type for which we will be generating code
 /// </summary>
 /// <param name="extractionContext">The definition extraction context in which the extraction is being performed</param>
 /// <param name="targetTypeDeclaration">The TypeDeclarationSyntax from which to extract the necessary information</param>
 /// <returns>The name of the type for which generation is being performed</returns>
 private static string GetTypeName(DefinitionExtractionContext extractionContext, TypeDeclarationSyntax targetTypeDeclaration)
 {
     return(targetTypeDeclaration.Identifier.ToString());
 }
Exemplo n.º 16
0
 /// <summary>
 /// Extract the type name of the property for which we are building information
 /// </summary>
 /// <param name="extractionContext">The definition extraction context in which the extraction is being performed</param>
 /// <param name="targetTypeDeclaration">The PropertyDeclarationSyntax from which to extract the necessary information</param>
 /// <returns>The type name of the property for which we are extracting information</returns>
 private static string GetPropertyTypeName(DefinitionExtractionContext extractionContext, PropertyDeclarationSyntax propertyDeclaration)
 {
     return(propertyDeclaration.Type.ToString());
 }
Exemplo n.º 17
0
 /// <summary>
 /// Extract the name of the property for which we are building information
 /// </summary>
 /// <param name="extractionContext">The definition extraction context in which the extraction is being performed</param>
 /// <param name="targetTypeDeclaration">The PropertyDeclarationSyntax from which to extract the necessary information</param>
 /// <returns>The name of the property for which we are extracting information</returns>
 private static string GetPropertyName(DefinitionExtractionContext extractionContext, PropertyDeclarationSyntax propertyDeclaration)
 {
     return(propertyDeclaration.Identifier.ValueText);
 }
Exemplo n.º 18
0
        /// <summary>
        /// Get the property declarations for all properties which are to be serialized
        /// </summary>
        /// <param name="extractionContext">The definition extraction context in which the extraction is being performed</param>
        /// <param name="targetTypeDeclaration">The TypeDeclarationSyntax from which to extract the necessary data</param>
        /// <returns>A readonly list of property declarations to be included in serialization</returns>
        private static IReadOnlyList <PropertyDeclarationSyntax> GetSerializablePropertyDeclarations(DefinitionExtractionContext extractionContext, TypeDeclarationSyntax targetTypeDeclaration)
        {
            List <PropertyDeclarationSyntax> serializableProperties;
            List <PropertyDeclarationSyntax> optedInSerializableProperties;

            // Get public or internal properties that are not specifically opted out with the [AutoNonSerialized] attribute
            serializableProperties = GetPublicNonExcludedProperties(extractionContext, targetTypeDeclaration);

            // Add any private or protected properties that are opted in with the use of the [AutoSerialized] attribute
            optedInSerializableProperties = GetNonPublicIncludedProperties(extractionContext, targetTypeDeclaration);
            serializableProperties.AddRange(optedInSerializableProperties);

            return(serializableProperties);
        }
Exemplo n.º 19
0
 /// <summary>
 /// Extract the name of the field for which we are building information
 /// </summary>
 /// <param name="extractionContext">The definition extraction context in which the extraction is being performed</param>
 /// <param name="targetTypeDeclaration">The FieldDeclarationSyntax from which to extract the necessary information</param>
 /// <returns>The name of the field for which we are extracting information</returns>
 private static string GetFieldName(DefinitionExtractionContext extractionContext, FieldDeclarationSyntax fieldDeclaration)
 {
     return(fieldDeclaration.Declaration.Variables[0].Identifier.ToString());
 }
Exemplo n.º 20
0
        /// <summary>
        /// Extract information about the fields which must be serialized from a part of the syntax tree
        /// </summary>
        /// <param name="extractionContext">The definition extraction context in which the extraction is being performed</param>
        /// <param name="targetTypeDeclaration">The TypeDeclarationSyntax from which to extract the necessary data</param>
        /// <returns>A readonly list of ExtractedFieldDefinition containing the data extracted from the syntax tree</returns>
        public static IReadOnlyList <ExtractedFieldDefinition> ExtractFieldDefinitions(DefinitionExtractionContext extractionContext, TypeDeclarationSyntax targetTypeDeclaration)
        {
            List <ExtractedFieldDefinition>        propertyDefinitions = new List <ExtractedFieldDefinition>();
            ExtractedFieldDefinition               fieldDefinition;
            IReadOnlyList <FieldDeclarationSyntax> serializableFields;

            serializableFields = GetSerializableFieldDeclarations(extractionContext, targetTypeDeclaration);
            foreach (FieldDeclarationSyntax fieldDeclaration in serializableFields)
            {
                fieldDefinition = FieldDefinitionExtractor.ExtractFieldDefinition(extractionContext, fieldDeclaration);
                propertyDefinitions.Add(fieldDefinition);
            }

            return(propertyDefinitions);
        }
Exemplo n.º 21
0
        /// <summary>
        /// Extract the definitions of the containers of the type for which we will be generating code
        /// </summary>
        /// <param name="extractionContext">The definition extraction context in which the extraction is being performed</param>
        /// <param name="targetTypeDeclaration">The TypeDeclarationSyntax from which to extract the necessary information</param>
        /// <returns>The definitions of all of the containers of the type for which generation is being performed</returns>
        public static IReadOnlyList <ExtractedContainerDefinition> GetContainerDefinitions(DefinitionExtractionContext extractionContext, TypeDeclarationSyntax targetTypeDeclaration)
        {
            NamespaceDeclarationSyntax          namespaceDeclaration;
            TypeDeclarationSyntax               containingTypeDeclaration;
            List <ExtractedContainerDefinition> containers = new List <ExtractedContainerDefinition>();

            // Iterate through the containing types should the target type be nested inside other types
            containingTypeDeclaration = targetTypeDeclaration;
            while (containingTypeDeclaration.Parent is TypeDeclarationSyntax)
            {
                containingTypeDeclaration = (TypeDeclarationSyntax)containingTypeDeclaration.Parent;
                containers.Add(GetContainerDefinition(extractionContext, containingTypeDeclaration));
            }

            namespaceDeclaration = containingTypeDeclaration.Parent as NamespaceDeclarationSyntax;
            if (namespaceDeclaration is not null)
            {
                containers.Add(GetContainerDefinition(extractionContext, namespaceDeclaration));
            }

            containers.Reverse();

            return(containers);
        }
Exemplo n.º 22
0
        /// <summary>
        /// Get the property declarations for all non-public properties which have been explicitly included in serialization
        /// </summary>
        /// <param name="extractionContext">The definition extraction context in which the extraction is being performed</param>
        /// <param name="targetTypeDeclaration">The TypeDeclarationSyntax from which to extract the necessary data</param>
        /// <returns>A readonly list of property declarations to be included in serialization</returns>
        private static List <PropertyDeclarationSyntax> GetNonPublicIncludedProperties(DefinitionExtractionContext extractionContext, TypeDeclarationSyntax targetTypeDeclaration)
        {
            List <PropertyDeclarationSyntax> serializableProperties;

            // Get private or protected properties that are specifically opted in with the [AutoSerialized] attribute
            serializableProperties = targetTypeDeclaration.Members.Where(
                m => m is PropertyDeclarationSyntax propertyDeclaration &&
                !HasOneOfScopes(extractionContext, propertyDeclaration, "public") &&
                HasGetterAndSetter(extractionContext, propertyDeclaration) &&
                extractionContext.IsPropertyDecoratedWithAutoSerialized(propertyDeclaration))
                                     .Cast <PropertyDeclarationSyntax>()
                                     .ToList();

            return(serializableProperties);
        }
Exemplo n.º 23
0
 /// <summary>
 /// Extract the type name of the field for which we are building information
 /// </summary>
 /// <param name="extractionContext">The definition extraction context in which the extraction is being performed</param>
 /// <param name="targetTypeDeclaration">The FieldDeclarationSyntax from which to extract the necessary information</param>
 /// <returns>The type name of the field for which we are extracting information</returns>
 private static string GetFieldTypeName(DefinitionExtractionContext extractionContext, FieldDeclarationSyntax fieldDeclaration)
 {
     return(fieldDeclaration.Declaration.Type.ToString());
 }
Exemplo n.º 24
0
        /// <summary>
        /// Extract information about the properties which must be serialized from a part of the syntax tree
        /// </summary>
        /// <param name="extractionContext">The definition extraction context in which the extraction is being performed</param>
        /// <param name="targetTypeDeclaration">The TypeDeclarationSyntax from which to extract the necessary data</param>
        /// <returns>A readonly list of ExtractedPropertyDefinition containing the data extracted from the syntax tree</returns>
        public static IReadOnlyList <ExtractedPropertyDefinition> ExtractPropertyDefinitions(DefinitionExtractionContext extractionContext, TypeDeclarationSyntax targetTypeDeclaration)
        {
            List <ExtractedPropertyDefinition>        propertyDefinitions = new List <ExtractedPropertyDefinition>();
            ExtractedPropertyDefinition               propertyDefinition;
            IReadOnlyList <PropertyDeclarationSyntax> serializableProperties;

            serializableProperties = GetSerializablePropertyDeclarations(extractionContext, targetTypeDeclaration);
            foreach (PropertyDeclarationSyntax propertyDeclaration in serializableProperties)
            {
                propertyDefinition = PropertyDefinitionExtractor.ExtractPropertyDefinition(extractionContext, propertyDeclaration);
                propertyDefinitions.Add(propertyDefinition);
            }

            return(propertyDefinitions);
        }