diff --git a/ArgumentParser.cs b/ArgumentParser.cs index 7c85a59..46d0b4e 100644 --- a/ArgumentParser.cs +++ b/ArgumentParser.cs @@ -24,7 +24,7 @@ public ArgumentParser(string[] args) { for (int i=0; i RouteParams { get; set; } = new List(); + + //Whether this method returns a list or not. + public bool ReturnsList { get; set; } + + /// + /// Clones this API method module. + /// + public APIMethodModule Clone() + { + return (APIMethodModule)this.MemberwiseClone(); + } + + /// + /// Gets a string representation of this method's return type. + /// + public string GetReturnType() + { + if (ReturnsList) + { + return "List<" + ReceivedDataType.Name + ">"; + } + else + { + return ReceivedDataType.Name; + } + } } /// diff --git a/burrito-api/Data Structures/APISchema.cs b/burrito-api/Data Structures/APISchema.cs index 7a7e442..94a032f 100644 --- a/burrito-api/Data Structures/APISchema.cs +++ b/burrito-api/Data Structures/APISchema.cs @@ -167,9 +167,9 @@ public bool Validate() } //Is the route relative URL even valid? - if (!Regex.IsMatch(RelativeURL, "^[A-Za-z_\\-\\.0-9\\?\\=%#@/\\{\\}]+$")) + if (!Regex.IsMatch(RelativeURL, "^[A-Za-z_\\-\\.0-9\\?\\=%#&@/\\{\\}]+$")) { - Logger.Write("[ERR] - Invalid relative route provided ('" + RelativeURL + "'.", 1); + Logger.Write("[ERR] - Invalid relative route provided ('" + RelativeURL + "').", 1); return false; } diff --git a/burrito-api/Data Structures/ClassModule.cs b/burrito-api/Data Structures/ClassModule.cs index 58884a7..718e9cd 100644 --- a/burrito-api/Data Structures/ClassModule.cs +++ b/burrito-api/Data Structures/ClassModule.cs @@ -116,7 +116,7 @@ public string GenerateCode(string ns, params string[] extraIncludes) } catch (Exception e) { - Logger.Write("[WARN] - Failed to beautify code, could not parse as C#: '" + e.Message + "'.", 1); + Logger.Write("[WARN] - Failed to beautify code, could not parse as C#: '" + e.Message + "'.", 2); } return code; } @@ -132,7 +132,9 @@ private void GenerateMethods(ref string code, List methods) //If generate async and sync is on, and async, generate the synchronous method first. if (method.Async && BurritoAPI.GenerateAsyncAndSync) { - GenerateMethods(ref code, new List() { method }); + var methodCopy = method.Clone(); + methodCopy.Async = false; + GenerateMethods(ref code, new List() { methodCopy }); } //XML summary. @@ -147,7 +149,7 @@ private void GenerateMethods(ref string code, List methods) } else { - code += "public static " + method.ReceivedDataType.Name + " "; + code += "public static " + method.GetReturnType() + " "; } //Open parameters. @@ -162,7 +164,7 @@ private void GenerateMethods(ref string code, List methods) } if (method.Async) { - params_.Add("BurritoCore.APICallReturnDelegate<" + method.ReceivedDataType.Name + "> callback"); + params_.Add("BurritoCore.APICallReturnDelegate<" + method.GetReturnType() + "> callback"); } //Optional template params Templates are replaced by blank by default. @@ -196,7 +198,7 @@ private void GenerateMethods(ref string code, List methods) { code += "Async"; } - code += "<" + method.ReceivedDataType.Name + ">("; + code += "<" + method.GetReturnType() + ">("; //Required URL parameter, post data and async. code += "_globals.RootURL + $\"" + method.Route + "\", "; diff --git a/burrito-api/Data Structures/ProjectCode.cs b/burrito-api/Data Structures/ProjectCode.cs index e950afa..5d06636 100644 --- a/burrito-api/Data Structures/ProjectCode.cs +++ b/burrito-api/Data Structures/ProjectCode.cs @@ -164,7 +164,7 @@ public void CompileToDLL(string generationPath) } catch { - Logger.Write("[WARN] - Failed renaming packed (.dll.packed) to normal (.dll), insufficient permissions. Job still completed.", 1); + Logger.Write("[WARN] - Failed renaming packed (.dll.packed) to normal (.dll), insufficient permissions. Job still completed.", 2); } } @@ -198,7 +198,7 @@ public void CompileToProject(string generationPath) catch (Exception e) { if (dll == "System") { continue; } //ignore missing system.dll - Logger.Write("[WARN] - Failed to copy dependency DLL '" + dll + "'. Reference left.", 1); + Logger.Write("[WARN] - Failed to copy dependency DLL '" + dll + "'. Reference left.", 2); } } diff --git a/burrito-api/Object Generation/DataTypeCreator.cs b/burrito-api/Object Generation/DataTypeCreator.cs index ddd5ae3..562c3e5 100644 --- a/burrito-api/Object Generation/DataTypeCreator.cs +++ b/burrito-api/Object Generation/DataTypeCreator.cs @@ -12,7 +12,7 @@ class DataTypeCreator /// /// Derives an API data type from a given HTTP GET/POST route. /// - public static ClassModule DeriveFromRoute(string baseURI, Route route, JObject postData=null) + public static ClassModule DeriveFromRoute(string baseURI, Route route, ref bool isList, JObject postData=null) { //Attempt to ping the route for a response. string response; @@ -47,16 +47,42 @@ public static ClassModule DeriveFromRoute(string baseURI, Route route, JObject p JObject jobj; try { + //Is it an object? jobj = JObject.Parse(response); + isList = false; + + //Construct a class from it. + return FromJObject(jobj, route.ReturnedDataName); } catch { - Logger.Write("[ERR] - Failed to derive data from route '" + route.RelativeURL + "', invalid JSON response.", 1); - return null; - } + //Maybe it's an array? + try + { + var jarr = JArray.Parse(response); + + //Yes, set method return type as array. + isList = true; + + //An array of what? + if (jarr.Count == 0) + { + Logger.Write("[WARN] - Cannot derive type from empty array, assuming as an empty. (route '" + route.RelativeURL + "')", 2); + return BurritoAPI.Project.Namespaces["@"].Find(x => x.Name == "_empty"); + } - //Construct a class from it. - return FromJObject(jobj, route.ReturnedDataName); + //Deriving type. + var field = GenerateField(route.ReturnedDataName, "", jarr[0]); + + //Return a dummy class with the right typename. + return new ClassModule(field.TypeName); + } + catch + { + Logger.Write("[ERR] - Failed to derive data from route '" + route.RelativeURL + "', invalid JSON response. (route '" + route.RelativeURL + "')", 1); + return null; + } + } } /// @@ -70,12 +96,12 @@ public static ClassModule FromJObject(JObject jobj, string name) //If the name or JObject is null, invalid. if (jobj == null) { - Logger.Write("[ERR] - Invalid JSON data given to create a class module from, no data.", 1); + Logger.Write("[ERR] - Invalid JSON data given to create a class module from, no data. ('" + name + "')", 1); return null; } if (name == null) { - Logger.Write("[ERR] - No name provided for creating returned data from a route.", 1); + Logger.Write("[ERR] - No name provided for creating returned data from a route. ('" + name + "')", 1); return null; } @@ -88,6 +114,9 @@ public static ClassModule FromJObject(JObject jobj, string name) return module; } + /// + /// Generates a field to use in a generated class. + /// private static Field GenerateField(string rootName, string name, JToken value) { switch (value.Type) @@ -98,7 +127,7 @@ private static Field GenerateField(string rootName, string name, JToken value) var arr = (JArray)value; if (arr.Count == 0) { - Logger.Log("[WARN] - Cannot generate a type from an empty array. Leaving an empty list type here."); + Logger.Log("[WARN] - Cannot generate a type from an empty array. Leaving an empty list type here. ('" + name + "')"); return new Field(name, ClassModule.Empty()); } @@ -138,11 +167,11 @@ private static Field GenerateField(string rootName, string name, JToken value) case JTokenType.String: return new Field(name, "string"); case JTokenType.Null: - Logger.Write("[WARN] - Null type in JSON at property '" + name + "', assumed as an object.", 1); + Logger.Write("[WARN] - Null type in JSON at property '" + name + "', assumed as an object. ('" + name + "')", 2); return new Field(name, "object "); default: - Logger.Write("[WARN] - Unsupported type in JSON to create a class from: '" + value.Type.ToString() + "' for generated data class '" + name + "'. Skipped property.", 1); + Logger.Write("[WARN] - Unsupported type in JSON to create a class from: '" + value.Type.ToString() + "' for generated data class '" + name + "'. Skipped property.", 2); return null; } }