private void WriteDeserializeObject(StringBuilder sb, DzObjectNode objNode)
        {
            string objectTypeStrValid = objNode.Type.Replace(".", "_");

            const string SPC = "    ";

            sb.Append($@"{SPC}{SPC}private static {objNode.Type} Deserialize_{objectTypeStrValid}(ref string content, ref ReadOnlySpan<char> json)
        {{
");
            DzTreeContext treeContext = new DzTreeContext();

            treeContext.IndentCSharp(+3);

            foreach (CSharpNode node in objNode.GetNodes(treeContext).OfType <CSharpNode>())
            {
                sb.Append(node.CSharpCode);
            }

            sb.Append($@"
        }}

");
        }
        private DzJsonNode BuildDzTree(ITypeSymbol symbol, string csObj)
        {
            if (symbol.Kind != SymbolKind.NamedType)
            {
                return(null);
            }

            // primitive types
            switch (symbol.SpecialType)
            {
            case SpecialType.System_Int32:
                _deserializeIntRequired = true;
                return(new DzCallNode("DeserializeInt(ref content, ref json)"));

            case SpecialType.System_String:
                _deserializeStringRequired = true;
                return(new DzCallNode("DeserializeString(ref content, ref json)"));

            default:
                break;
            }

            // if is serializable class
            string            invocationTypeStr = symbol.ToString();
            SerializableClass foundClass        = _knownClasses.FirstOrDefault(c => c.Type.ToString().Equals(invocationTypeStr));

            if (foundClass != null)
            {
                if (!_requiredTypeDeserializers.ContainsKey(invocationTypeStr))
                {
                    DzObjectNode objectNode = new DzObjectNode(invocationTypeStr);
                    foreach (SerializableProperty sp in foundClass.Properties)
                    {
                        DzJsonNode value = BuildDzTree(sp.Type, $"obj.{sp.Name}");
                        if (value is DzExpressionNode expr)
                        {
                            DzAssignmentNode assignment = new DzAssignmentNode($"obj.{sp.Name}", expr);
                            objectNode.Properties.Add((sp.Name, assignment));
                        }
                        else
                        {
                            throw new Exception("Expected expression for object property assignment!");
                        }
                    }

                    _requiredTypeDeserializers.Add(invocationTypeStr, objectNode);
                }
                string validName = invocationTypeStr.Replace(".", "_");
                return(new DzCallNode($"Deserialize_{validName}(ref content, ref json)"));
            }

            // list, dictionnary, ...

            // fallback on list
            INamedTypeSymbol enumerable = null;

            if (symbol.MetadataName.Equals("IList`1"))
            {
                enumerable = symbol as INamedTypeSymbol;
            }
            else
            {
                enumerable = symbol.AllInterfaces.FirstOrDefault(i => i.MetadataName.Equals("IList`1"));
            }
            if (enumerable != null)
            {
                ITypeSymbol listType = enumerable.TypeArguments.First();

                DzListNode listNode = new DzListNode(listType.ToString());
                DzJsonNode value    = BuildDzTree(listType, $"obj");
                if (value is DzExpressionNode expr)
                {
                    listNode.Property = new DzAppendListNode($"obj", expr);
                }
                else
                {
                    throw new Exception("Expected expression for object list append!");
                }

                _requiredTypeDeserializers.Add(invocationTypeStr, listNode);

                string objectTypeStrValid = listNode.Type.Replace(".", "_").Replace("<", "_").Replace(">", "");
                return(new DzCallNode($"DeserializeList_{objectTypeStrValid}(ref content, ref json)"));
            }

            // fallback on enumerables?

            // If reached here, type isn't supported
            _context.ReportDiagnostic(Diagnostic.Create(DiagnosticDescriptors.ClassNotSerializable, symbol.Locations.First(), invocationTypeStr));
            return(null);
        }