public static ApiModel Parse(JObject root, IEnumerable <string> searchPaths) { var name = (string)root["name"]; var api = new ApiModel(name, ParseDependencies(root, searchPaths)); // Translations and enumerations only need a single processing phase. ParseTranslations(root, api); ParseEnumerations(root, api); // Structure and interface models must be declared first, and // then defined in a second pass to prevent definition order problems. DeclareStructures(root, api); DeclareInterfaces(root, api); DefineStructures(root, api); DefineInterfaces(root, api); // Functions may reference any of the above, but cannot be referenced themselves, // and so can be parsed in one pass at the end. ParseFunctions(root, api); return(api); }
/// <summary> /// Defines interfaces in an API model based on the contents of a JSON tree. /// </summary> /// <param name="root">The root of the JSON tree for the API.</param> /// <param name="api">The API model being constructed.</param> static void DefineInterfaces(JObject root, ApiModel api) { JToken items; if (root.TryGetValue("interfaces", out items)) { foreach (var item in items) { var key = (string)item["key"]; var model = (InterfaceModel)api.FindType(key); JToken parent = null; if ((item as JObject).TryGetValue("type", out parent)) { model.Parent = api.FindType((string)parent); } foreach (var method in ParseInterfaceMethods(item as JObject, api)) { model.AddMethod(method); } } } }
static void RunGenerator(ApiModel api, Configuration configuration) { var templateDirectory = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Templates"); var templateEngine = new TemplateEngine(new[] { templateDirectory }); templateEngine.RegisterCallback("ApiNamespace", (e, s) => api.Name); templateEngine.RegisterCallback("ApiName", (e, s) => TemplateCallbacks.GetApiClassName(api)); templateEngine.RegisterCallback("ApiDll", (e, s) => TemplateCallbacks.GetApiDllName(api)); templateEngine.RegisterCallbacks(typeof(TemplateCallbacks)); var outputDirectory = configuration.GeneratorOutputPath; if (!Directory.Exists(outputDirectory)) { Directory.CreateDirectory(outputDirectory); } ApplyTemplate(api, outputDirectory, templateEngine, "Api"); ApplyTemplate(api.Enumerations, outputDirectory, templateEngine, "Enumeration"); ApplyTemplate(api.Structures, outputDirectory, templateEngine, "Structure"); ApplyTemplate(api.Interfaces, outputDirectory, templateEngine, "Interface"); BuildTrampolineAssembly(api, outputDirectory, string.Format("{0}.Trampoline", api.Name)); }
static void BuildTrampolineAssembly(ApiModel api, string outputDirectory, string outputFile) { MarshallingService marshaller = new MarshallingService(); TrampolineAssemblyBuilder trampolineBuilder = new TrampolineAssemblyBuilder(); foreach (var interfaceModel in api.Interfaces) { foreach (var methodModel in interfaceModel.Methods) { var methodType = marshaller.ResolveType(methodModel.Type); if (methodType == null) { throw new InvalidOperationException(string.Format("Could not resolve return type for method '{0}.'", methodModel.Name)); } var parameters = new List <TrampolineParameter>(); foreach (var parameterModel in methodModel.Parameters) { var parameterType = marshaller.ResolveType(parameterModel); if (parameterType == null) { throw new InvalidOperationException(string.Format("Could not resolve type for parameter '{0}.'", parameterModel.Name)); } TrampolineParameterFlags flags = TrampolineParameterFlags.Default; if (parameterModel.Flags.HasFlag(ParameterModelFlags.IsOutput) && marshaller.ResolveBehavior(parameterModel) != MarshalBehavior.Structure && marshaller.ResolveBehavior(parameterModel) != MarshalBehavior.Enumeration && marshaller.ResolveBehavior(parameterModel) != MarshalBehavior.Array) { flags |= TrampolineParameterFlags.Reference; } parameters.Add(parameterModel.Type == ApiModel.VoidModel ? new TrampolineParameter(typeof(IntPtr), flags) : new TrampolineParameter(parameterType, flags)); } trampolineBuilder.Add(new Trampoline(true, methodType, parameters.ToArray())); } } foreach (var functionModel in api.Functions) { var methodType = marshaller.ResolveType(functionModel.Type); if (methodType == null) { throw new InvalidOperationException(string.Format("Could not resolve return type for method '{0}.'", functionModel.Name)); } var parameters = new List <TrampolineParameter>(); foreach (var parameterModel in functionModel.Parameters) { var parameterType = marshaller.ResolveType(parameterModel); if (parameterType == null) { throw new InvalidOperationException(string.Format("Could not resolve type for parameter '{0}.'", parameterModel.Name)); } TrampolineParameterFlags flags = TrampolineParameterFlags.Default; if (parameterModel.Flags.HasFlag(ParameterModelFlags.IsOutput)) { flags |= TrampolineParameterFlags.Reference; } parameters.Add(parameterModel.Type == ApiModel.VoidModel ? new TrampolineParameter(typeof(IntPtr), flags) : new TrampolineParameter(parameterType, flags)); } trampolineBuilder.Add(new Trampoline(false, methodType, parameters.ToArray())); } trampolineBuilder.CreateAssembly(outputDirectory, outputFile); }
protected TypeModel(ApiModel api, string key, string name) { Api = api; Key = key; Name = name; }
public FunctionModel(ApiModel api, string name, TypeModel returnType) { Api = api; Name = name; Type = returnType; }
internal EnumerationModel(ApiModel api, string key) : base(api, key, key) { }
internal StructureModel(ApiModel api, string key) : base(api, key, key) { }
public static string GetApiClassName(ApiModel api) { return(api.Name.Split('.').Last()); }
internal InterfaceModel(ApiModel api, string key, Guid guid) : base(api, key, key) { Guid = guid; }