private void GenerateDeserializeMethodBody(StringBuilder sb, DeserializeInvocation invocation) { DzTreeContext treeContext = new DzTreeContext(); treeContext.IndentCSharp(+3); string ct = treeContext.CSharpIndent; List <MethodNode> nodes = new List <MethodNode>(); string invocationTypeStr = invocation.TypeArg.ToString(); DzJsonNode dzTree = BuildDzTree(invocation.TypeArg, "obj"); if (dzTree is null) { nodes.Add(new CSharpLineNode($"{ct}obj = default({invocationTypeStr});")); nodes.Add(new CSharpLineNode($"{ct}// Type '{invocationTypeStr}' isn't marked as serializable!")); } else { nodes.Add(new CSharpLineNode($"{ct}ReadOnlySpan<char> json = content.AsSpan().TrimStart();")); nodes.Add(new CSharpLineNode($"{ct}if (json.IsEmpty)")); nodes.Add(new CSharpLineNode($"{ct}{{")); ct = treeContext.IndentCSharp(+1); nodes.Add(new CSharpLineNode($"{ct}obj = default({invocationTypeStr});")); nodes.Add(new CSharpLineNode($"{ct}return;")); ct = treeContext.IndentCSharp(-1); nodes.Add(new CSharpLineNode($"{ct}}}")); nodes.Add(new CSharpNode($"{ct}obj = ")); nodes.AddRange(dzTree.GetNodes(treeContext)); nodes.Add(new CSharpLineNode($";")); } //nodes.Add(new CSharpLineNode($"{ct}return new {invocationTypeStr}();")); foreach (CSharpNode node in nodes.OfType <CSharpNode>()) { sb.Append(node.CSharpCode); } }
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); }