示例#1
0
 protected override void EnterUnionDefinition(PrinterContext context, UnionDefinition unionDefinition)
 {
     context.Append(' ');
     context.AppendDescription(unionDefinition.Description);
     context.Append("union ");
     context.Append(unionDefinition.Name);
     context.Append(" ");
 }
示例#2
0
 /// <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);
    }
示例#4
0
        public void FromString()
        {
            /* Given */
            /* When */
            UnionDefinition original = "union Name = MemberA | MemberB";

            /* Then */
            Assert.Equal("Name", original.Name);
            Assert.Equal(2, original.Members?.Count);
        }
示例#5
0
        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);
        }
示例#6
0
        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);
        }
示例#7
0
        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);
        }
示例#8
0
        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);
        }
示例#9
0
 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))
     });
示例#10
0
        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
            },
                        " "));
        }
示例#11
0
        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);
        }
示例#12
0
        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)
示例#14
0
 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);
 }
示例#16
0
 public IEnumerable<ObjectDefinition> GetPossibleTypes(UnionDefinition abstractType)
 {
     return QueryTypes<ObjectDefinition>(ob => abstractType.HasMember(ob.Name));
 }
 protected virtual void ExitUnionDefinition(TContext context, UnionDefinition unionDefinition)
 {
 }