protected override void EnterUnionDefinition(PrinterContext context, UnionDefinition unionDefinition) { context.Append(' '); context.AppendDescription(unionDefinition.Description); context.Append("union "); context.Append(unionDefinition.Name); context.Append(" "); }
/// <summary> /// Generate the body of the <c>encode</c> function for the given <see cref="Definition"/>. /// </summary> /// <param name="definition">The definition to generate code for.</param> /// <returns>The generated TypeScript <c>encode</c> function body.</returns> public string CompileEncode(Definition definition) { return(definition switch { MessageDefinition d => CompileEncodeMessage(d), StructDefinition d => CompileEncodeStruct(d), UnionDefinition d => CompileEncodeUnion(d), _ => throw new InvalidOperationException($"invalid CompileEncode value: {definition}"), });
private void VisitUnionDefinition(UnionDefinition node) { EnterNode(node); Visit(node.Directives); Visit(node.Members); ExitNode(node); }
public void FromString() { /* Given */ /* When */ UnionDefinition original = "union Name = MemberA | MemberB"; /* Then */ Assert.Equal("Name", original.Name); Assert.Equal(2, original.Members?.Count); }
public void FromBytes() { /* Given */ /* When */ UnionDefinition original = Encoding.UTF8.GetBytes("union Name = MemberA | MemberB") .AsReadOnlySpan(); /* Then */ Assert.Equal("Name", original.Name); Assert.Equal(2, original.Members?.Count); }
public void WithName() { /* Given */ UnionDefinition original = "union Name = MemberA | MemberB"; /* When */ var modified = original .WithName("Renamed"); /* Then */ Assert.Equal("Name", original.Name); Assert.Equal("Renamed", modified.Name); }
public void WithDescription() { /* Given */ UnionDefinition original = "union Name = MemberA | MemberB"; /* When */ var modified = original .WithDescription("Description"); /* Then */ Assert.Null(original.Description); Assert.Equal("Description", modified.Description); }
private static List <UnionDefinition> Parse(TextReader inputReader) { List <UnionDefinition> result = new List <UnionDefinition>(); string allText = inputReader.ReadToEnd(); // Remove comments and newlines allText = new Regex(@"/\*.*?\*/", RegexOptions.Multiline).Replace(allText, ""); allText = new Regex(@"//.*$", RegexOptions.Multiline).Replace(allText, ""); allText = new Regex(@"[\r\n]+").Replace(allText, ""); string identifier = @"[A-Za-z][A-Za-z0-9]*"; foreach (Match matchDef in new Regex(@"datatype\s+(" + identifier + @")\s*(:\s*([^ ]+)\s*)?{([^}%]*)(%%(.*?)%%)?}").Matches(allText)) { UnionDefinition definition = new UnionDefinition(); definition.Name = matchDef.Groups[1].Value; definition.Alternatives = new List <UnionAlternative>(); definition.BaseClass = matchDef.Groups[3].Success ? matchDef.Groups[3].Value : ""; definition.RawText = matchDef.Groups[5].Success ? matchDef.Groups[6].Value : ""; string alternatives = matchDef.Groups[4].Value; foreach (Match matchAlt in new Regex(@"\b(" + identifier + @")\s*(\((.*?)\))?").Matches(alternatives)) { UnionAlternative alternative = new UnionAlternative(); alternative.Name = matchAlt.Groups[1].Value; alternative.Contents = new List <UnionAlternativeMember>(); string[] contents = matchAlt.Groups[3].Value.Split(new char[] { ' ', ',' }, StringSplitOptions.RemoveEmptyEntries); if ((contents.Length % 2) != 0) { throw new Exception("Must specify type and name for each alternative data field. Types cannot contain spaces."); } for (int i = 0; i < contents.Length; i += 2) { UnionAlternativeMember member = new UnionAlternativeMember(); member.Type = contents[i]; member.Name = contents[i + 1]; alternative.Contents.Add(member); } definition.Alternatives.Add(alternative); } result.Add(definition); } return(result); }
public static TypeDefinition Extend( this TypeDefinition typeDefinition, params TypeExtension[] typeExtensions) { return(typeDefinition switch { EnumDefinition enumDefinition => Extend(enumDefinition, typeExtensions), InputObjectDefinition inputObjectDefinition => Extend(inputObjectDefinition, typeExtensions), InterfaceDefinition interfaceDefinition => Extend(interfaceDefinition, typeExtensions), ObjectDefinition objectDefinition => Extend(objectDefinition, typeExtensions), ScalarDefinition scalarDefinition => Extend(scalarDefinition, typeExtensions), UnionDefinition unionDefinition => Extend(unionDefinition, typeExtensions), _ => throw new ArgumentOutOfRangeException(nameof(typeDefinition)) });
private string PrintUnionTypeDefinition(UnionDefinition node) { var name = PrintName(node.Name); var directives = node.Directives?.Select(PrintDirective) ?? Array.Empty <string>(); var types = node.Members?.Select(PrintNamedType).ToArray() ?? Array.Empty <string>(); return(Join(new[] { "union", name, Join(directives, " "), types?.Any() == true ? "= " + Join(types, " | ") : string.Empty }, " ")); }
public void WithMembers() { /* Given */ UnionDefinition original = "union Name = MemberA | MemberB"; /* When */ var modified = original .WithMembers(new List <NamedType> { "a" }); /* Then */ Assert.NotNull(modified.Members); var a = Assert.Single(modified.Members); Assert.Equal("a", a?.Name); }
private static void OutputUnionClass(TextWriter outputWriter, UnionDefinition definition, int indent) { outputWriter.Write(new string(' ', indent * 1) + "public class " + definition.Name); if (definition.BaseClass != "") { outputWriter.Write(" : " + definition.BaseClass); } outputWriter.WriteLine(); outputWriter.WriteLine(new string(' ', indent * 1) + "{"); // // Tag stuff // outputWriter.WriteLine(new string(' ', indent * 2) + "public enum TagValue"); outputWriter.WriteLine(new string(' ', indent * 2) + "{"); foreach (UnionAlternative alternative in definition.Alternatives) { outputWriter.WriteLine(new string(' ', indent * 3) + alternative.Name + ","); } outputWriter.WriteLine(new string(' ', indent * 2) + "}\r\n"); outputWriter.WriteLine(new string(' ', indent * 2) + "private TagValue tag;\r\n"); outputWriter.WriteLine(new string(' ', indent * 2) + "public TagValue Tag"); outputWriter.WriteLine(new string(' ', indent * 2) + "{"); outputWriter.WriteLine(new string(' ', indent * 3) + "get {"); outputWriter.WriteLine(new string(' ', indent * 4) + "return tag;"); outputWriter.WriteLine(new string(' ', indent * 3) + "}"); outputWriter.WriteLine(new string(' ', indent * 2) + "}"); outputWriter.WriteLine(""); // // Generate subclasses for alternatives with contents // foreach (UnionAlternative alternative in definition.Alternatives) { if (alternative.Contents.Count > 1) { outputWriter.WriteLine(new string(' ', indent * 2) + "public class " + alternative.Name); outputWriter.WriteLine(new string(' ', indent * 2) + "{"); foreach (UnionAlternativeMember member in alternative.Contents) { outputWriter.WriteLine(new string(' ', indent * 3) + "public " + member.Type + " " + Capitalize(member.Name) + ";"); } outputWriter.WriteLine(""); outputWriter.Write(new string(' ', indent * 3) + "public " + alternative.Name + "("); outputWriter.Write(String.Join(", ", alternative.Contents.ConvertAll <string>(delegate(UnionAlternativeMember member) { return(member.Type + " " + member.Name); }).ToArray())); outputWriter.WriteLine(") {"); foreach (UnionAlternativeMember member in alternative.Contents) { outputWriter.WriteLine(new string(' ', indent * 4) + "this." + Capitalize(member.Name) + " = " + member.Name + ";"); } outputWriter.WriteLine(new string(' ', indent * 3) + "}"); outputWriter.WriteLine(new string(' ', indent * 2) + "}\r\n"); } } // // Value field and private constructor // outputWriter.WriteLine(new string(' ', indent * 2) + "private object value;\r\n"); outputWriter.WriteLine(new string(' ', indent * 2) + "private " + definition.Name + "(TagValue tag, object value) {"); outputWriter.WriteLine(new string(' ', indent * 3) + "this.tag = tag;"); outputWriter.WriteLine(new string(' ', indent * 3) + "this.value = value;"); outputWriter.WriteLine(new string(' ', indent * 2) + "}\r\n"); // // Generate static constructors // foreach (UnionAlternative alternative in definition.Alternatives) { outputWriter.Write(new string(' ', indent * 2) + "public static " + definition.Name + " Create" + Capitalize(alternative.Name) + "("); outputWriter.Write(String.Join(", ", alternative.Contents.ConvertAll <string>(delegate(UnionAlternativeMember member) { return(member.Type + " " + member.Name); }).ToArray())); outputWriter.WriteLine(")"); outputWriter.WriteLine(new string(' ', indent * 2) + "{"); outputWriter.Write(new string(' ', indent * 3) + "return new " + definition.Name + "(TagValue." + alternative.Name + ", "); if (alternative.Contents.Count == 0) { outputWriter.Write("null"); } else if (alternative.Contents.Count == 1) { outputWriter.Write(alternative.Contents[0].Name); } else { outputWriter.Write("new " + alternative.Name + "("); outputWriter.Write(String.Join(", ", alternative.Contents.ConvertAll <string>(delegate(UnionAlternativeMember member) { return(member.Name); }).ToArray())); outputWriter.Write(")"); } outputWriter.WriteLine(");"); outputWriter.WriteLine(new string(' ', indent * 2) + "}\r\n"); } // // Read-only accessors // foreach (UnionAlternative alternative in definition.Alternatives) { if (alternative.Contents.Count > 0) { string returnType; if (alternative.Contents.Count == 1) { returnType = alternative.Contents[0].Type; } else { returnType = alternative.Name; } outputWriter.WriteLine(new string(' ', indent * 2) + "public " + returnType + " GetAs" + Capitalize(alternative.Name) + "()"); outputWriter.WriteLine(new string(' ', indent * 2) + "{"); outputWriter.WriteLine(new string(' ', indent * 3) + "Debug.Assert(Tag == TagValue." + alternative.Name + ", \"Type error: tried to access disjoint union as '" + alternative.Name + "' but tag does not match\");"); outputWriter.WriteLine(new string(' ', indent * 3) + "return (" + returnType + ")value;"); outputWriter.WriteLine(new string(' ', indent * 2) + "}\r\n"); } } // // Example usage template // outputWriter.WriteLine("#if false"); outputWriter.WriteLine(new string(' ', indent * 2) + "// Example usage template for this disjoint union type"); outputWriter.WriteLine(new string(' ', indent * 2) + "public static void ExampleUsage(" + definition.Name + " " + Uncapitalize(definition.Name) + ")"); outputWriter.WriteLine(new string(' ', indent * 2) + "{"); outputWriter.WriteLine(new string(' ', indent * 3) + "switch (" + Uncapitalize(definition.Name) + ".Tag) {"); foreach (UnionAlternative alternative in definition.Alternatives) { outputWriter.WriteLine(new string(' ', indent * 4) + "case " + definition.Name + ".TagValue." + alternative.Name + ":"); if (alternative.Contents.Count > 0) { string returnType; if (alternative.Contents.Count == 1) { returnType = alternative.Contents[0].Type; } else { returnType = definition.Name + "." + alternative.Name; } outputWriter.WriteLine(new string(' ', indent * 5) + returnType + " " + Uncapitalize(alternative.Name) + " = " + Uncapitalize(definition.Name) + ".GetAs" + Capitalize(alternative.Name) + "();"); } outputWriter.WriteLine(new string(' ', indent * 5) + "break;"); } outputWriter.WriteLine(new string(' ', indent * 4) + "default:"); outputWriter.WriteLine(new string(' ', indent * 5) + "Debug.Assert(false, \"Unhandled alternative in switch over '" + definition.Name + "'\");"); outputWriter.WriteLine(new string(' ', indent * 5) + "break;"); outputWriter.WriteLine(new string(' ', indent * 3) + "}"); outputWriter.WriteLine(new string(' ', indent * 2) + "}"); outputWriter.WriteLine("#endif"); outputWriter.WriteLine(definition.RawText); outputWriter.WriteLine(new string(' ', indent * 1) + "}\r\n"); }
public static UnionDefinition WithDescription(this UnionDefinition definition, in StringValue?description)
public virtual TResult VisitUnionDefinition(UnionDefinition node) { return(DefaultVisit(node)); }
public static bool HasMember( this UnionDefinition definition, Name name) { return(definition.Members?.Any(m => m.Name == name) == true); }
public IEnumerable<ObjectDefinition> GetPossibleTypes(UnionDefinition abstractType) { return QueryTypes<ObjectDefinition>(ob => abstractType.HasMember(ob.Name)); }
protected virtual void ExitUnionDefinition(TContext context, UnionDefinition unionDefinition) { }