private void GenerateComponent(IndentingTextWriter writer, ComponentCatalog.ComponentInfo component, ComponentCatalog catalog) { GenerateEnums(writer, component.ArgumentType, "Runtime"); writer.WriteLine(); GenerateClasses(writer, component.ArgumentType, catalog, "Runtime"); writer.WriteLine(); CSharpGeneratorUtils.GenerateSummary(writer, component.Description); writer.WriteLine($"public sealed class {CSharpGeneratorUtils.GetComponentName(component)} : {component.Kind}"); writer.WriteLine("{"); writer.Indent(); GenerateInputFields(writer, component.ArgumentType, catalog, "Runtime"); writer.WriteLine($"internal override string ComponentName => \"{component.Name}\";"); writer.Outdent(); writer.WriteLine("}"); writer.WriteLine(); }
private static JObject BuildComponentManifest(IExceptionContext ectx, ComponentCatalog.ComponentInfo componentInfo, ComponentCatalog catalog) { Contracts.AssertValueOrNull(ectx); ectx.AssertValue(componentInfo); ectx.AssertValue(catalog); var result = new JObject(); result[FieldNames.Name] = componentInfo.Name; result[FieldNames.Desc] = componentInfo.Description; result[FieldNames.FriendlyName] = componentInfo.FriendlyName; if (Utils.Size(componentInfo.Aliases) > 0) { result[FieldNames.Aliases] = new JArray(componentInfo.Aliases); } result[FieldNames.Settings] = BuildInputManifest(ectx, componentInfo.ArgumentType, catalog); return(result); }
public JObject GetJsonObject(object instance, Dictionary <string, List <ParameterBinding> > inputBindingMap, Dictionary <ParameterBinding, VariableBinding> inputMap) { Contracts.CheckValue(instance, nameof(instance)); Contracts.Check(instance.GetType() == _type); var result = new JObject(); var defaults = Activator.CreateInstance(_type); for (int i = 0; i < _fields.Length; i++) { var field = _fields[i]; var attr = _attrs[i]; var instanceVal = field.GetValue(instance); var defaultsVal = field.GetValue(defaults); if (inputBindingMap.TryGetValue(field.Name, out List <ParameterBinding> bindings)) { // Handle variables. Contracts.Assert(bindings.Count > 0); VariableBinding varBinding; var paramBinding = bindings[0]; if (paramBinding is SimpleParameterBinding) { Contracts.Assert(bindings.Count == 1); bool success = inputMap.TryGetValue(paramBinding, out varBinding); Contracts.Assert(success); Contracts.AssertValue(varBinding); result.Add(field.Name, new JValue(varBinding.ToJson())); } else if (paramBinding is ArrayIndexParameterBinding) { // Array parameter bindings. var array = new JArray(); foreach (var parameterBinding in bindings) { Contracts.Assert(parameterBinding is ArrayIndexParameterBinding); bool success = inputMap.TryGetValue(parameterBinding, out varBinding); Contracts.Assert(success); Contracts.AssertValue(varBinding); array.Add(new JValue(varBinding.ToJson())); } result.Add(field.Name, array); } else { // Dictionary parameter bindings. Not supported yet. Contracts.Assert(paramBinding is DictionaryKeyParameterBinding); throw Contracts.ExceptNotImpl("Dictionary of variables not yet implemented."); } } else if (instanceVal == null && defaultsVal != null) { // Handle null values. result.Add(field.Name, new JValue(instanceVal)); } else if (instanceVal != null && (attr.Input.IsRequired || !instanceVal.Equals(defaultsVal))) { // A required field will be serialized regardless of whether or not its value is identical to the default. var type = instanceVal.GetType(); if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Optional <>)) { var isExplicit = ExtractOptional(ref instanceVal, ref type); if (!isExplicit) { continue; } } if (type == typeof(JArray)) { result.Add(field.Name, (JArray)instanceVal); } else if (type.IsGenericType && ((type.GetGenericTypeDefinition() == typeof(Var <>)) || type.GetGenericTypeDefinition() == typeof(ArrayVar <>) || type.GetGenericTypeDefinition() == typeof(DictionaryVar <>))) { result.Add(field.Name, new JValue($"${((IVarSerializationHelper)instanceVal).VarName}")); } else if (type == typeof(bool) || type == typeof(string) || type == typeof(char) || type == typeof(double) || type == typeof(float) || type == typeof(int) || type == typeof(long) || type == typeof(uint) || type == typeof(ulong)) { // Handle simple types. result.Add(field.Name, new JValue(instanceVal)); } else if (type.IsEnum) { // Handle enums. result.Add(field.Name, new JValue(instanceVal.ToString())); } else if (type.IsArray) { // Handle arrays. var array = (Array)instanceVal; var jarray = new JArray(); var elementType = type.GetElementType(); if (elementType == typeof(bool) || elementType == typeof(string) || elementType == typeof(char) || elementType == typeof(double) || elementType == typeof(float) || elementType == typeof(int) || elementType == typeof(long) || elementType == typeof(uint) || elementType == typeof(ulong)) { foreach (object item in array) { jarray.Add(new JValue(item)); } } else { var builder = new InputBuilder(_ectx, elementType, _catalog); foreach (object item in array) { jarray.Add(builder.GetJsonObject(item, inputBindingMap, inputMap)); } } result.Add(field.Name, jarray); } else if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Dictionary <,>) && type.GetGenericArguments()[0] == typeof(string)) { // Handle dictionaries. // REVIEW: Needs to be implemented when we will have entry point arguments that contain dictionaries. } else if (typeof(IComponentFactory).IsAssignableFrom(type)) { // Handle component factories. bool success = _catalog.TryFindComponent(type, out ComponentCatalog.ComponentInfo instanceInfo); Contracts.Assert(success); var builder = new InputBuilder(_ectx, type, _catalog); var instSettings = builder.GetJsonObject(instanceVal, inputBindingMap, inputMap); ComponentCatalog.ComponentInfo defaultInfo = null; JObject defSettings = new JObject(); if (defaultsVal != null) { var deftype = defaultsVal.GetType(); if (deftype.IsGenericType && deftype.GetGenericTypeDefinition() == typeof(Optional <>)) { ExtractOptional(ref defaultsVal, ref deftype); } success = _catalog.TryFindComponent(deftype, out defaultInfo); Contracts.Assert(success); builder = new InputBuilder(_ectx, deftype, _catalog); defSettings = builder.GetJsonObject(defaultsVal, inputBindingMap, inputMap); } if (instanceInfo.Name != defaultInfo?.Name || instSettings.ToString() != defSettings.ToString()) { var jcomponent = new JObject { { FieldNames.Name, new JValue(instanceInfo.Name) } }; if (instSettings.ToString() != defSettings.ToString()) { jcomponent.Add(FieldNames.Settings, instSettings); } result.Add(field.Name, jcomponent); } } else { // REVIEW: pass in the bindings once we support variables in inner fields. // Handle structs. var builder = new InputBuilder(_ectx, type, _catalog); result.Add(field.Name, builder.GetJsonObject(instanceVal, new Dictionary <string, List <ParameterBinding> >(), new Dictionary <ParameterBinding, VariableBinding>())); } } } return(result); }
public static string GetComponentName(ComponentCatalog.ComponentInfo component) { return($"{Capitalize(component.Name)}{component.Kind}"); }