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); }