Skip to content

Commit

Permalink
Add basic code generation structures, and the burrito API outline.
Browse files Browse the repository at this point in the history
  • Loading branch information
c272 committed Feb 24, 2020
1 parent f60900f commit e24c8c9
Show file tree
Hide file tree
Showing 19 changed files with 770 additions and 58 deletions.
6 changes: 3 additions & 3 deletions App.config
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.1"/>
</startup>
</configuration>
</configuration>
6 changes: 3 additions & 3 deletions ArgumentParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
using System.Text;
using System.Threading.Tasks;

namespace burrito
namespace burritocli
{
/// <summary>
/// Parses arguments passed into Burrito.
Expand All @@ -26,7 +26,7 @@ public ArgumentParser(string[] args)
if (Values.ContainsKey(args[i]))
{
//Error.
Error.Exit("Error parsing value argument '" + args[i] + "', a value already exists with that name.");
Logger.Exit("Error parsing value argument '" + args[i] + "', a value already exists with that name.");
return;
}

Expand All @@ -44,7 +44,7 @@ public ArgumentParser(string[] args)
}

//Invalid value.
Error.Exit("Invalid argument (argument " + (i + 1) + "), not a flag or a value.");
Logger.Exit("Invalid argument (argument " + (i + 1) + "), not a flag or a value.");
return;
}
}
Expand Down
17 changes: 0 additions & 17 deletions Error.cs

This file was deleted.

24 changes: 24 additions & 0 deletions Logger.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace burritocli
{
internal static class Logger
{
public static void Log(string msg)
{
if (msg.StartsWith("[ERR]")) { Console.ForegroundColor = ConsoleColor.Red; }
Console.WriteLine(msg);
Console.ResetColor();
}

public static void Exit(string msg)
{
Console.WriteLine(msg);
Environment.Exit(-1);
}
}
}
64 changes: 58 additions & 6 deletions Program.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Burrito;

namespace burrito
namespace burritocli
{
class Program
{
Expand All @@ -13,18 +16,67 @@ class Program
/// </summary>
static void Main(string[] args)
{
//Parse the arguments provided, set the runtime information.
//Create locals.
var argMan = new ArgumentParser(args);
RuntimeInformation.GenerationPath = argMan.GetValue("p") == null ? Environment.CurrentDirectory : argMan.GetValue("p");
RuntimeInformation.CompileAfterGeneration = argMan.GetFlag("c");
var burrito = new BurritoAPI();
burrito.SetLogger(Logger.Log);

//Parse the arguments provided, set the runtime information.
burrito.GenerationPath = argMan.GetValue("p") == null ? Environment.CurrentDirectory : argMan.GetValue("p");
burrito.CompileAfterGeneration = argMan.GetFlag("c");
burrito.APISchemaPath = argMan.GetValue("s");

//Validate arguments.
if (argMan.GetValue("s") == null)
{
Error.Exit("Missing an API schema definition to generate from (usage is '-s [path]').");
Logger.Log("Missing an API schema definition to generate from (usage is '-s [path]').");
Logger.Exit("For information on how to create a schema, see MANUAL.md.");
return;
}

//Schema exists?
if (!File.Exists(burrito.APISchemaPath))
{
Logger.Exit("Invalid file path given for schema, file does not exist.");
return;
}

//todo
//Generating directory exists?
if (!Directory.Exists(burrito.GenerationPath))
{
//Create it.
try
{
Directory.CreateDirectory(burrito.GenerationPath);
}
catch (Exception e)
{
Logger.Exit("Invalid directory path given, '" + e.Message + "'.");
return;
}
}

//Directory has any files in it?
if (Directory.GetFiles(burrito.GenerationPath).Count() != 0)
{
//Use a child directory of the name of the schema file.
string newDir = Path.Combine(burrito.GenerationPath, Path.GetFileNameWithoutExtension(burrito.APISchemaPath));
Directory.CreateDirectory(newDir);
burrito.GenerationPath = newDir;
}

//Run burrito.
var t = new Stopwatch();
t.Start();
int routesGenerated = burrito.Run();
t.Stop();

//Write the finish message.
Console.Write("Rolled up the API schema in ");
Console.ForegroundColor = ConsoleColor.Green;
Console.Write(t.ElapsedMilliseconds / 1000f + "s");
Console.ResetColor();
Console.Write(", " + routesGenerated + " routes generated.\n");
}
}
}
23 changes: 0 additions & 23 deletions RuntimeInformation.cs

This file was deleted.

146 changes: 146 additions & 0 deletions burrito-api/BurritoAPI.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace Burrito
{
/// <summary>
/// Represents a single instance of the Burrito API.
/// </summary>
public class BurritoAPI
{
//Whether to compile the library after generating it.
public bool CompileAfterGeneration { get; set; } = false;

//What path to generate the library at.
public string GenerationPath { get; set; } = Environment.CurrentDirectory;

//Where to draw the API schema from to use.
public string APISchemaPath { get; set; } = null;

//The verbosity level of the generator.
//0 - No logging.
//1 - Critical logging only (errors).
//2 - Normal logging (status updates & errors).
//3 - Debug logging.
public int VerbosityLevel
{
get { return Logger.Verbosity; }
set { Logger.Verbosity = value; }
}

public int Run()
{
//Try and deserialize the schema.
APISchema schema;
try
{
schema = JsonConvert.DeserializeObject<APISchema>(File.ReadAllText(APISchemaPath));
}
catch (Exception e)
{
Logger.Write("[ERR] - Failed to load API schema, '" + e.Message + "'.", 1);
return 0;
}

//All relevant properties exist?
if (schema.Sections == null || schema.Name == null || schema.RootPath == null)
{
Logger.Write("[ERR] - Required chema property missing (one of 'name', 'root' or 'sections').", 1);
return 0;
}

//Valid schema name?
if (!Regex.IsMatch(schema.Name, "^[A-Za-z0-9_]+$"))
{
Logger.Write("[ERR] - Invalid schema name given. Must only be alphanumeric or underscores.", 1);
return 0;
}

//Create a project module with the given schema and namespaces.
var project = new ProjectModule(schema.Name);
project.AddNamespace("Data");
project.AddNamespace("@");

//Check all the sections in the schema have unique names.
var sectionNames = new List<string>();
foreach (var module in schema.Sections)
{
if (sectionNames.Contains(module.Name))
{
Logger.Write("[ERR] - Duplicate section name '" + module.Name + "' detected.", 1);
return 0;
}
sectionNames.Add(module.Name);
}

//Loop through the routes and generate code modules for each of them.
foreach (var module in schema.Sections)
{
var moduleClass = new ClassModule(project);
foreach (var route in module.Routes)
{
//URL exists?
if (route.RelativeURL == null)
{
Logger.Write("[ERR] - No URL provided for route in sectoin '" + module.Name + "'.", 1);
return 0;
}

//What method does this route use?
switch (route.HTTPMethod)
{
case null:
Logger.Write("[ERR] - No HTTP method defined for route '" + route.RelativeURL + "'.", 1);
return 0;
case "GET":
case "get":
//Figure out a data type from the API endpoint.


//Add the method.
moduleClass.Methods.Add(new GETMethodModule()
{
Async = route.Async,
Route = route.RelativeURL,
XMLSummary = route.GetSummary(),
Name = route.GetMethodName()
});
break;
case "POST":
case "post":
//Add the method.
moduleClass.Methods.Add(new POSTMethodModule()
{
Async = route.Async,
Route = route.RelativeURL,
XMLSummary = route.GetSummary(),
DataType = route.SentDataName,
Name = route.GetMethodName()
});
break;

}
}

//Add the class to root namespace.
project.Namespaces["@"].Add(moduleClass);
}

return -1;
}

/// <summary>
/// Sets the logger used by Burrito to the provided method.
/// </summary>
public void SetLogger(Action<string> logger)
{
Logger.Log = logger;
}
}
}
37 changes: 37 additions & 0 deletions burrito-api/Data Structures/APIMethodModule.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
namespace Burrito
{
/// <summary>
/// Represents a single API method within a class.
/// </summary>
public abstract class APIMethodModule
{
//The XML comment summary for this method.
public string XMLSummary;

//Whether this method is asynchronous or not.
public bool Async;

//The route for this method to call.
public string Route;

//The name of this method.
public string Name;

//Name of the data type that is received back.
public ClassModule ReceivedDataType;
}

/// <summary>
/// A single POST API method.
/// </summary>
public class POSTMethodModule : APIMethodModule
{
//The data type to POST.
public string DataType;
}

/// <summary>
/// A single GET API method.
/// </summary>
public class GETMethodModule : APIMethodModule { }
}
Loading

0 comments on commit e24c8c9

Please sign in to comment.