using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using Newtonsoft.Json.Linq; namespace Generators.Output { public static class ValueFormatter { public static object Format(object val) { switch (val) { case string str: return str.Format(); case double dbl: return dbl.Format(); case float flt: return flt.Format(); case ulong ulng: return ulng.Format(); case char c: return c.Format(); case Enum enumeration: return enumeration.Format(); case Tuple tuple: return tuple.Format(); case IEnumerable ints: return ints.Format(); case IEnumerable strings: return strings.Format(); case IEnumerable unescapedValues when unescapedValues.Any(): return unescapedValues.Format(); case IDictionary dict: return dict.Format(); case IDictionary dict: return dict.Format(); case IDictionary dict: return dict.Format(); case JArray jArray: return jArray.Format(); case int[,] multidimensionalArray: return multidimensionalArray.Format(); case IEnumerable> tuples: return tuples.Format(); default: return val; } } public static string[] FormatVariables(IReadOnlyDictionary dict) => dict.Keys.SelectMany(key => FormatVariable(dict[key], key.ToVariableName())).ToArray(); public static string[] FormatVariable(object val, string name) { switch (val) { case string str when str.Contains("\n"): return FormatMultiLineString(name, str); case IDictionary dict: return FormatMultiLineEnumerable(dict.Keys.Select((key, i) => $"[{Format(key)}] = {Format(dict[key])}" + (i < dict.Keys.Count - 1 ? "," : "")), name, "new Dictionary"); case IDictionary dict: return FormatMultiLineEnumerable(dict.Keys.Select((key, i) => $"[{Format(key)}] = {Format(dict[key])}" + (i < dict.Keys.Count - 1 ? "," : "")), name, "new Dictionary"); default: return new[] { $"var {name} = {Format(val)};" }; } } private static string Format(this string s) => s.EscapeSpecialCharacters().Quote(); private static string Format(this char c) => $"'{c}'"; private static string Format(this double dbl) => dbl.ToString(CultureInfo.InvariantCulture); private static string Format(this float flt) => flt.ToString(CultureInfo.InvariantCulture); private static string Format(this ulong ulng) => $"{ulng}UL"; private static string Format(this Enum @enumeration) => $"{enumeration.GetType().Name}.{enumeration}"; private static string Format(this Tuple tuple) => $"Tuple.Create({tuple.Item1}, {tuple.Item2})"; private static string Format(this IEnumerable ints) => ints.Any() ? $"new[] {{ {string.Join(", ", ints)} }}" : "new int[0]"; private static string Format(this IEnumerable strings) => strings.Any() ? $"new[] {{ {string.Join(", ", strings.Select(Format))} }}" : "new string[0]"; private static string Format(this IEnumerable unescapedValues) => $"new[] {{ {string.Join(", ", unescapedValues.Select(Format))} }}"; private static string Format(this IDictionary dict) => string.Join(", ", dict.Values.Select(Format)); private static string Format(this IDictionary dict) => $"new Dictionary {{ {string.Join(", ", dict.Keys.Select(key => $"[{Format(key)}] = {Format(dict[key])}"))} }}"; private static string Format(this IDictionary dict) => $"new Dictionary {{ {string.Join(", ", dict.Keys.Select(key => $"[{Format(key)}] = {Format(dict[key])}"))} }}"; private static string Format(this JArray jArray) => $"new[] {{ {string.Join(", ", jArray.Select(Format))} }}"; private static string Format(this int[,] multidimensionalArray) { return multidimensionalArray.GetLength(0) > 1 ? $"new[,]\r\n{{\r\n {string.Join(",\r\n ", Enumerable.Range(0, multidimensionalArray.GetUpperBound(0) + 1).Select(x => multidimensionalArray.SliceRow(x).ToNestedArray()))}\r\n}}" : "new int[,] { }"; } private static string Format(this IEnumerable> tuples) => $"new[] {{ {string.Join(", ", tuples.Select(Format))} }}"; private static string ToNestedArray(this IEnumerable enumerable) => enumerable.Any() ? $"{{ {string.Join(", ", enumerable)} }}" : string.Empty; private static string[] FormatMultiLineString(string name, string str) { var strings = str.Split('\n'); var formattedStrings = strings .Select((t, i) => i < strings.Length - 1 ? $"{Format(t + "\n")} +" : $"{Format(t)}"); return FormatMultiLineVariable(formattedStrings, name); } private static string[] FormatMultiLineEnumerable(IEnumerable enumerable, string name, string constructor = null) => FormatMultiLineVariable(enumerable.Prepend("{").Append("}"), name, constructor); private static string[] FormatMultiLineVariable(IEnumerable enumerable, string name, string constructor = null) => enumerable.Select(line => line == "{" || line == "}" ? line : line.Indent()) .AddTrailingSemicolon() .Prepend($"var {name} = {constructor}") .ToArray(); } }