public static void Make(ISymbol member, ITypeSymbol type, CodeWriter code, string name, Location location, ScopeTracker scope = null) { var disposable = scope = scope == null?code.Encapsulate() : scope.Reference(); using (disposable) { var nullable = type.NullableAnnotation == NullableAnnotation.Annotated; var hasUnderlying = false; if (nullable) { var underlying = GenerationEngine.GetNamedTypeSymbol(type).TypeArguments.FirstOrDefault(); hasUnderlying = underlying != null; type = underlying ?? type.WithNullableAnnotation(NullableAnnotation.None); var check = hasUnderlying ? ".HasValue" : " is not null"; code.AppendLine($"writer.Write({name}{check});"); code.AppendLine($"if ({name}{check})"); code.Open(); } name = nullable && hasUnderlying ? $"{name}.Value" : name; if (GenerationEngine.DefaultSerialization.TryGetValue(GenerationEngine.GetQualifiedName(type), out var serialization)) { serialization.Serialize(member, type, code, name, GenerationEngine.GetIdentifierWithArguments(type), location); return; } if (GenerationEngine.IsPrimitive(type)) { if (!type.IsValueType) { using (code.BeginScope($"if ({name} is default({GenerationEngine.GetIdentifierWithArguments(type)}))")) { code.AppendLine( $"throw new Exception(\"Member '{name}' is a primitive and has no value (null). If this is not an issue, please declare it as nullable.\");"); } } code.AppendLine($"writer.Write({name});"); } else { if (type.TypeKind != TypeKind.Struct && type.TypeKind != TypeKind.Enum && !nullable) { code.AppendLine($"writer.Write({name} is not null);"); code.AppendLine($"if ({name} is not null)"); code.Open(); } switch (type.TypeKind) { case TypeKind.Enum: code.AppendLine($"writer.Write((int) {name});"); break; case TypeKind.Interface: case TypeKind.Struct: case TypeKind.Class: var enumerable = GenerationEngine.GetQualifiedName(type) == GenerationEngine.EnumerableQualifiedName ? GenerationEngine.GetNamedTypeSymbol(type) : type.AllInterfaces.FirstOrDefault(self => GenerationEngine.GetQualifiedName(self) == GenerationEngine.EnumerableQualifiedName); if (enumerable != null) { var elementType = enumerable.TypeArguments.First(); using (code.BeginScope()) { var countTechnique = GenerationEngine.GetAllMembers(type) .Where(self => self is IPropertySymbol) .Aggregate("Count()", (current, symbol) => symbol.Name switch { "Count" => "Count", "Length" => "Length", _ => current }); var prefix = GenerationEngine.GetVariableName(name); code.AppendLine($"var {prefix}Count = {name}.{countTechnique};"); code.AppendLine($"writer.Write({prefix}Count);"); using (code.BeginScope($"foreach (var {prefix}Entry in {name})")) { Make(member, elementType, code, $"{prefix}Entry", location, scope); } } }