Example #1
0
        private IEnumerable<Field> DetermineMinimalFactoryFields(Node nd)
        {
            // special case to allow a single optional argument if there would have been no arguments
            // and we can determine a best single argument.
            Field allowOptionalField = null;

            var optionalCount = OptionalFactoryArgumentCount(nd);
            if (optionalCount == 0)
            {
                return null; // no fields...
            }

            var requiredCount = RequiredFactoryArgumentCount(nd, includeKind: false);
            if (requiredCount == 0 && optionalCount > 1)
            {
                allowOptionalField = DetermineMinimalOptionalField(nd);
            }

            return nd.Fields.Where(f => IsRequiredFactoryField(nd, f) || allowOptionalField == f);
        }
Example #2
0
 private Field DetermineMinimalOptionalField(Node nd)
 {
     // first if there is a single list, then choose the list because it would not have been optional
     int listCount = nd.Fields.Count(f => IsAnyNodeList(f.Type));
     if (listCount == 1)
     {
         return nd.Fields.First(f => IsAnyNodeList(f.Type));
     }
     else
     {
         // otherwise, if there is a single optional node, use that..
         int nodeCount = nd.Fields.Count(f => IsNode(f.Type) && f.Type != "SyntaxToken");
         if (nodeCount == 1)
         {
             return nd.Fields.First(f => IsNode(f.Type) && f.Type != "SyntaxToken");
         }
         else
         {
             return null;
         }
     }
 }
Example #3
0
        private void WriteGreenUpdateMethod(Node node)
        {
            WriteLine();
            Write("    public {0} Update(", node.Name);

            // parameters
            for (int f = 0; f < node.Fields.Count; f++)
            {
                var field = node.Fields[f];
                if (f > 0)
                    Write(", ");

                var type =
                    field.Type == "SyntaxNodeOrTokenList" ? "Microsoft.CodeAnalysis.Syntax.InternalSyntax.SyntaxList<CSharpSyntaxNode>" :
                    field.Type == "SyntaxTokenList" ? "Microsoft.CodeAnalysis.Syntax.InternalSyntax.SyntaxList<SyntaxToken>" :
                    IsNodeList(field.Type) ? "Microsoft.CodeAnalysis.Syntax.InternalSyntax." + field.Type :
                    IsSeparatedNodeList(field.Type) ? "Microsoft.CodeAnalysis.Syntax.InternalSyntax." + field.Type :
                    field.Type;

                Write("{0} {1}", type, CamelCase(field.Name));
            }
            WriteLine(")");
            WriteLine("    {");

            Write("        if (");
            int nCompared = 0;
            for (int f = 0; f < node.Fields.Count; f++)
            {
                var field = node.Fields[f];
                if (IsDerivedOrListOfDerived("SyntaxNode", field.Type) || IsDerivedOrListOfDerived("SyntaxToken", field.Type) || field.Type == "SyntaxNodeOrTokenList")
                {
                    if (nCompared > 0)
                        Write(" || ");
                    Write("{0} != this.{1}", CamelCase(field.Name), field.Name);
                    nCompared++;
                }
            }
            if (nCompared > 0)
            {
                WriteLine(")");
                WriteLine("        {");
                Write("            var newNode = SyntaxFactory.{0}(", StripPost(node.Name, "Syntax"));
                if (node.Kinds.Count > 1)
                {
                    Write("this.Kind, ");
                }
                for (int f = 0; f < node.Fields.Count; f++)
                {
                    var field = node.Fields[f];
                    if (f > 0)
                        Write(", ");
                    Write(CamelCase(field.Name));
                }
                WriteLine(");");
                WriteLine("            var diags = this.GetDiagnostics();");
                WriteLine("            if (diags != null && diags.Length > 0)");
                WriteLine("               newNode = newNode.WithDiagnosticsGreen(diags);");
                WriteLine("            var annotations = this.GetAnnotations();");
                WriteLine("            if (annotations != null && annotations.Length > 0)");
                WriteLine("               newNode = newNode.WithAnnotationsGreen(annotations);");
                WriteLine("            return newNode;");
                WriteLine("        }");
            }

            WriteLine();
            WriteLine("        return this;");
            WriteLine("    }");
        }
Example #4
0
        private void WriteSetDiagnostics(Node node)
        {
            WriteLine();
            WriteLine("    internal override GreenNode SetDiagnostics(DiagnosticInfo[] diagnostics)");
            WriteLine("    {");

            Write("         return new {0}(", node.Name);
            Write("this.Kind, ");
            for (int f = 0; f < node.Fields.Count; f++)
            {
                var field = node.Fields[f];
                if (f > 0)
                    Write(", ");
                Write("this.{0}", CamelCase(field.Name));
            }
            WriteLine(", diagnostics, GetAnnotations());");
            WriteLine("    }");
        }
Example #5
0
        // creates a factory with only the required arguments (everything else is defaulted)
        private void WriteRedMinimalFactory(Node nd, bool withStringNames = false)
        {
            var optionalCount = OptionalFactoryArgumentCount(nd);
            if (optionalCount == 0)
                return; // already handled w/ general factory method

            var minimalFactoryfields = new HashSet<Field>(DetermineMinimalFactoryFields(nd));

            if (withStringNames && minimalFactoryfields.Count(f => IsRequiredFactoryField(nd, f) && CanAutoConvertFromString(f)) == 0)
                return; // no string-name overload necessary

            this.WriteLine();

            WriteComment(string.Format("<summary>Creates a new {0} instance.</summary>", nd.Name), "    ");
            Write("    {0} static {1} {2}(", "public", nd.Name, StripPost(nd.Name, "Syntax"));

            bool hasPreviousParameter = false;
            if (nd.Kinds.Count > 1)
            {
                Write("SyntaxKind kind");
                hasPreviousParameter = true;
            }

            for (int i = 0, n = nd.Fields.Count; i < n; i++)
            {
                var field = nd.Fields[i];

                if (minimalFactoryfields.Contains(field))
                {
                    var type = GetRedPropertyType(field);

                    if (IsRequiredFactoryField(nd, field))
                    {
                        if (hasPreviousParameter)
                            Write(", ");

                        if (withStringNames && CanAutoConvertFromString(field))
                        {
                            type = "string";
                        }

                        Write("{0} {1}", type, CamelCase(field.Name));

                        hasPreviousParameter = true;
                    }
                    else
                    {
                        if (hasPreviousParameter)
                            Write(", ");

                        Write("{0} {1} = default({0})", type, CamelCase(field.Name));

                        hasPreviousParameter = true;
                    }
                }
            }
            WriteLine(")");

            WriteLine("    {");

            Write("      return SyntaxFactory.{0}(", StripPost(nd.Name, "Syntax"));

            bool hasPreviousArgument = false;
            if (nd.Kinds.Count > 1)
            {
                Write("kind");
                hasPreviousArgument = true;
            }

            for (int i = 0, n = nd.Fields.Count; i < n; i++)
            {
                var field = nd.Fields[i];

                if (hasPreviousArgument)
                    Write(", ");

                if (minimalFactoryfields.Contains(field))
                {
                    if (IsRequiredFactoryField(nd, field))
                    {
                        if (withStringNames && CanAutoConvertFromString(field))
                        {
                            Write("{0}({1})", GetStringConverterMethod(field), CamelCase(field.Name));
                        }
                        else
                        {
                            Write("{0}", CamelCase(field.Name));
                        }
                    }
                    else
                    {
                        if (IsOptional(field) || IsAnyList(field.Type))
                        {
                            Write("{0}", CamelCase(field.Name));
                        }
                        else
                        {
                            Write("{0} ?? {1}", CamelCase(field.Name), GetDefaultValue(nd, field));
                        }
                    }
                }
                else
                {
                    var defaultValue = GetDefaultValue(nd, field);
                    Write(defaultValue);
                }

                hasPreviousArgument = true;
            }

            WriteLine(");");

            WriteLine("    }");
        }
Example #6
0
 private IEnumerable<Field> DetermineRedFactoryWithNoAutoCreatableTokenFields(Node nd)
 {
     return nd.Fields.Where(f => !IsAutoCreatableToken(nd, f));
 }
Example #7
0
        private string GetDefaultValue(Node nd, Field field)
        {
            System.Diagnostics.Debug.Assert(!IsRequiredFactoryField(nd, field));

            if (IsOptional(field) || IsAnyList(field.Type))
            {
                return string.Format("default({0})", GetRedPropertyType(field));
            }
            else if (field.Type == "SyntaxToken")
            {
                // auto construct token?
                if (field.Kinds.Count == 1)
                {
                    return string.Format("SyntaxFactory.Token(SyntaxKind.{0})", field.Kinds[0].Name);
                }
                else
                {
                    return string.Format("SyntaxFactory.Token(Get{0}{1}Kind(kind))", StripPost(nd.Name, "Syntax"), StripPost(field.Name, "Opt"));
                }
            }
            else
            {
                var referencedNode = GetNode(field.Type);
                return string.Format("SyntaxFactory.{0}()", StripPost(referencedNode.Name, "Syntax"));
            }
        }
Example #8
0
        // full factory signature with nothing optional
        private void WriteRedFactory(Node nd)
        {
            this.WriteLine();

            var valueFields = nd.Fields.Where(n => IsValueField(n)).ToList();
            var nodeFields = nd.Fields.Where(n => !IsValueField(n)).ToList();

            WriteComment(string.Format("<summary>Creates a new {0} instance.</summary>", nd.Name), "    ");

            Write("    {0} static {1} {2}(", "public", nd.Name, StripPost(nd.Name, "Syntax"));
            WriteRedFactoryParameters(nd);

            WriteLine(")");
            WriteLine("    {");

            // validate kinds
            if (nd.Kinds.Count > 1)
            {
                WriteLine("      switch (kind)");
                WriteLine("      {");
                foreach (var kind in nd.Kinds)
                {
                    WriteLine("        case SyntaxKind.{0}:", kind.Name);
                }
                WriteLine("          break;");
                WriteLine("        default:");
                WriteLine("          throw new ArgumentException(\"kind\");");
                WriteLine("      }");
            }

            // validate parameters
            for (int i = 0, n = nodeFields.Count; i < n; i++)
            {
                var field = nodeFields[i];
                var pname = CamelCase(field.Name);

                if (field.Type == "SyntaxToken")
                {
                    if (field.Kinds != null && field.Kinds.Count > 0)
                    {
                        WriteLine("      switch ({0}.Kind())", pname);
                        WriteLine("      {");
                        foreach (var kind in field.Kinds)
                        {
                            WriteLine("        case SyntaxKind.{0}:", kind.Name);
                        }
                        if (IsOptional(field))
                        {
                            WriteLine("        case SyntaxKind.None:");
                        }
                        WriteLine("          break;");
                        WriteLine("        default:");
                        WriteLine("          throw new ArgumentException(\"{0}\");", pname);
                        WriteLine("      }");
                    }
                }
                else if (!IsAnyList(field.Type) && !IsOptional(field))
                {
                    WriteLine("      if ({0} == null)", CamelCase(field.Name));
                    WriteLine("        throw new ArgumentNullException(nameof({0}));", CamelCase(field.Name));
                }
            }

            Write("      return ({0})Microsoft.CodeAnalysis.CSharp.Syntax.InternalSyntax.SyntaxFactory.{1}(", nd.Name, StripPost(nd.Name, "Syntax"));
            if (nd.Kinds.Count > 1)
            {
                Write("kind, ");
            }
            for (int i = 0, n = nodeFields.Count; i < n; i++)
            {
                var field = nodeFields[i];
                if (i > 0)
                    Write(", ");
                if (field.Type == "SyntaxToken")
                {
                    Write("(Syntax.InternalSyntax.SyntaxToken){0}.Node", CamelCase(field.Name));
                }
                else if (field.Type == "SyntaxList<SyntaxToken>")
                {
                    Write("{0}.Node.ToGreenList<Microsoft.CodeAnalysis.CSharp.Syntax.InternalSyntax.SyntaxToken>()", CamelCase(field.Name));
                }
                else if (IsNodeList(field.Type))
                {
                    Write("{0}.Node.ToGreenList<Microsoft.CodeAnalysis.CSharp.Syntax.InternalSyntax.{1}>()", CamelCase(field.Name), GetElementType(field.Type));
                }
                else if (IsSeparatedNodeList(field.Type))
                {
                    Write("{0}.Node.ToGreenSeparatedList<Microsoft.CodeAnalysis.CSharp.Syntax.InternalSyntax.{1}>()", CamelCase(field.Name), GetElementType(field.Type));
                }
                else if (field.Type == "SyntaxNodeOrTokenList")
                {
                    Write("{0}.Node.ToGreenList<Microsoft.CodeAnalysis.CSharp.Syntax.InternalSyntax.CSharpSyntaxNode>()", CamelCase(field.Name));
                }
                else
                {
                    Write("{0} == null ? null : (Microsoft.CodeAnalysis.CSharp.Syntax.InternalSyntax.{1}){0}.Green", CamelCase(field.Name), field.Type);
                }
            }

            // values are at end
            for (int i = 0, n = valueFields.Count; i < n; i++)
            {
                var field = valueFields[i];
                Write(", ");
                Write(CamelCase(field.Name));
            }

            WriteLine(").CreateRed();");
            WriteLine("    }");

            this.WriteLine();
        }
Example #9
0
        private int RequiredFactoryArgumentCount(Node nd, bool includeKind = true)
        {
            int count = 0;

            // kind must be specified in factory
            if (nd.Kinds.Count > 1 && includeKind)
            {
                count++;
            }

            for (int i = 0, n = nd.Fields.Count; i < n; i++)
            {
                var field = nd.Fields[i];
                if (IsRequiredFactoryField(nd, field))
                {
                    count++;
                }
            }

            return count;
        }
Example #10
0
        private void WriteRedUpdateMethod(Node node)
        {
            WriteLine();
            Write("    {0} {1} Update(", "public", node.Name);

            // parameters
            for (int f = 0; f < node.Fields.Count; f++)
            {
                var field = node.Fields[f];
                if (f > 0)
                    Write(", ");
                var type = field.Type == "SyntaxList<SyntaxToken>" ? "SyntaxTokenList" : field.Type;
                Write("{0} {1}", type, CamelCase(field.Name));
            }
            WriteLine(")");
            WriteLine("    {");

            Write("        if (");
            int nCompared = 0;
            for (int f = 0; f < node.Fields.Count; f++)
            {
                var field = node.Fields[f];
                if (IsDerivedOrListOfDerived("SyntaxNode", field.Type) || IsDerivedOrListOfDerived("SyntaxToken", field.Type) || field.Type == "SyntaxNodeOrTokenList")
                {
                    if (nCompared > 0)
                        Write(" || ");
                    Write("{0} != this.{1}", CamelCase(field.Name), field.Name);
                    nCompared++;
                }
            }
            if (nCompared > 0)
            {
                WriteLine(")");
                WriteLine("        {");
                Write("            var newNode = SyntaxFactory.{0}(", StripPost(node.Name, "Syntax"));
                if (node.Kinds.Count > 1)
                {
                    Write("this.Kind(), ");
                }
                for (int f = 0; f < node.Fields.Count; f++)
                {
                    var field = node.Fields[f];
                    if (f > 0)
                        Write(", ");
                    Write(CamelCase(field.Name));
                }
                WriteLine(");");
                WriteLine("            var annotations = this.GetAnnotations();");
                WriteLine("            if (annotations != null && annotations.Length > 0)");
                WriteLine("               return newNode.WithAnnotations(annotations);");
                WriteLine("            return newNode;");
                WriteLine("        }");
            }

            WriteLine();
            WriteLine("        return this;");
            WriteLine("    }");
        }
Example #11
0
 private void WriteRedAcceptMethod(Node node, bool genericArgument, bool genericResult)
 {
     string genericArgs =
         (genericResult && genericArgument) ? "<TArgument, TResult>" :
         genericResult ? "<TResult>" : "";
     WriteLine();
     WriteLine("    public override " + (genericResult ? "TResult" : "void") + " Accept" + genericArgs + "(CSharpSyntaxVisitor" + genericArgs + " visitor{0})", genericArgument ? ", TArgument argument" : "");
     WriteLine("    {");
     WriteLine("        " + (genericResult ? "return " : "") + "visitor.Visit{0}(this{1});", StripPost(node.Name, "Syntax"), genericArgument ? ", argument" : "");
     WriteLine("    }");
 }
Example #12
0
 private void WriteRedAcceptMethods(Node node)
 {
     //WriteRedAcceptMethod(node, true, true);
     WriteRedAcceptMethod(node, false, true);
     WriteRedAcceptMethod(node, false, false);
 }
Example #13
0
        private void WriteNodeGenerator(Node node, bool isGreen)
        {
            var valueFields = node.Fields.Where(n => !IsNodeOrNodeList(n.Type));
            var nodeFields  = node.Fields.Where(n => IsNodeOrNodeList(n.Type));

            var internalNamespace = isGreen ? "Microsoft.CodeAnalysis.Syntax.InternalSyntax." : "";
            var csharpNamespace   = isGreen ? "Syntax.InternalSyntax." : "";
            var syntaxFactory     = isGreen ? "InternalSyntaxFactory" : "SyntaxFactory";

            var strippedName = StripPost(node.Name, "Syntax");

            WriteLine($"private static {csharpNamespace}{node.Name} Generate{strippedName}()");

            Write($"    => {syntaxFactory}.{strippedName}(");
            //instantiate node

            bool first = true;

            if (node.Kinds.Count > 1)
            {
                Write($"SyntaxKind.{node.Kinds[0].Name}"); //TODO: other kinds?
                first = false;
            }

            foreach (var field in nodeFields)
            {
                if (!first)
                {
                    Write(", ");
                }
                first = false;

                if (IsOptional(field))
                {
                    if (isGreen)
                    {
                        Write("null");
                    }
                    else
                    {
                        Write($"default({field.Type})");
                    }
                }
                else if (IsAnyList(field.Type))
                {
                    string typeName;
                    if (isGreen)
                    {
                        typeName = internalNamespace + field.Type.Replace("<", "<" + csharpNamespace);
                    }
                    else
                    {
                        typeName = (field.Type == "SyntaxList<SyntaxToken>") ? "SyntaxTokenList" : field.Type;
                    }
                    Write($"new {typeName}()");
                }
                else if (field.Type == "SyntaxToken")
                {
                    var kind           = ChooseValidKind(field);
                    var leadingTrivia  = isGreen ? "null, " : string.Empty;
                    var trailingTrivia = isGreen ? ", null" : string.Empty;
                    if (kind == "IdentifierToken")
                    {
                        Write($"{syntaxFactory}.Identifier(\"{field.Name}\")");
                    }
                    else if (kind == "StringLiteralToken")
                    {
                        Write($"{syntaxFactory}.Literal({leadingTrivia}\"string\", \"string\"{trailingTrivia})");
                    }
                    else if (kind == "CharacterLiteralToken")
                    {
                        Write($"{syntaxFactory}.Literal({leadingTrivia}\"a\", 'a'{trailingTrivia})");
                    }
                    else if (kind == "NumericLiteralToken")
                    {
                        Write($"{syntaxFactory}.Literal({leadingTrivia}\"1\", 1{trailingTrivia})");
                    }
                    else
                    {
                        Write($"{syntaxFactory}.Token(SyntaxKind.{ChooseValidKind(field)})");
                    }
                }
                else if (field.Type == "CSharpSyntaxNode")
                {
                    Write($"{syntaxFactory}.IdentifierName({syntaxFactory}.Identifier(\"{field.Name}\"))");
                }
                else
                {
                    //drill down to a concrete type
                    var type = field.Type;
                    while (true)
                    {
                        var subTypes = ChildMap[type];
                        if (!subTypes.Any())
                        {
                            break;
                        }
                        type = subTypes.First();
                    }
                    Write($"Generate{StripPost(type, "Syntax")}()");
                }
            }

            foreach (var field in valueFields)
            {
                if (!first)
                {
                    Write(", ");
                }
                first = false;

                Write($"new {field.Type}()");
            }

            WriteLine(");");
        }
Example #14
0
        private void WriteFactoryPropertyTest(Node node, bool isGreen)
        {
            var valueFields = node.Fields.Where(n => !IsNodeOrNodeList(n.Type));
            var nodeFields  = node.Fields.Where(n => IsNodeOrNodeList(n.Type));

            var strippedName = StripPost(node.Name, "Syntax");

            WriteLine("[Fact]");
            WriteLine($"public void Test{strippedName}FactoryAndProperties()");
            OpenBlock();

            WriteLine($"var node = Generate{strippedName}();");

            WriteLine();

            //check properties
            {
                string withStat = null;
                foreach (var field in nodeFields)
                {
                    if (IsOptional(field))
                    {
                        if (!isGreen && field.Type == "SyntaxToken")
                        {
                            WriteLine($"Assert.Equal(SyntaxKind.None, node.{field.Name}.Kind());");
                        }
                        else
                        {
                            WriteLine($"Assert.Null(node.{field.Name});");
                        }
                    }
                    else if (field.Type == "SyntaxToken")
                    {
                        if (!isGreen)
                        {
                            WriteLine($"Assert.Equal(SyntaxKind.{ChooseValidKind(field)}, node.{field.Name}.Kind());");
                        }
                        else
                        {
                            WriteLine($"Assert.Equal(SyntaxKind.{ChooseValidKind(field)}, node.{field.Name}.Kind);");
                        }
                    }
                    else
                    {
                        if (field.Type == "SyntaxToken")
                        {
                            WriteLine($"Assert.NotEqual(default, node.{field.Name});");
                        }
                        else if (
                            field.Type == "SyntaxTokenList" ||
                            field.Type.StartsWith("SyntaxList<") ||
                            field.Type.StartsWith("SeparatedSyntaxList<"))
                        {
                            WriteLine($"Assert.Equal(default, node.{field.Name});");
                        }
                        else
                        {
                            WriteLine($"Assert.NotNull(node.{field.Name});");
                        }
                    }

                    if (!isGreen)
                    {
                        withStat += $".With{field.Name}(node.{field.Name})";
                    }
                }

                foreach (var field in valueFields)
                {
                    WriteLine($"Assert.Equal(new {field.Type}(), node.{field.Name});");
                    if (!isGreen)
                    {
                        withStat += $".With{field.Name}(node.{field.Name})";
                    }
                }

                if (!isGreen && withStat != null)
                {
                    WriteLine($"var newNode = node{withStat};");
                    WriteLine("Assert.Equal(node, newNode);");
                }
            }

            if (isGreen)
            {
                WriteLine();
                WriteLine("AttachAndCheckDiagnostics(node);");
            }

            CloseBlock();
        }
Example #15
0
 private void WriteGreenFactoryParameters(Node nd)
 {
     if (nd.Kinds.Count > 1)
     {
         Write("SyntaxKind kind, ");
     }
     for (int i = 0, n = nd.Fields.Count; i < n; i++)
     {
         var field = nd.Fields[i];
         if (i > 0)
             Write(", ");
         var type = field.Type;
         if (type == "SyntaxNodeOrTokenList")
         {
             type = "Microsoft.CodeAnalysis.Syntax.InternalSyntax.SyntaxList<CSharpSyntaxNode>";
         }
         else if (IsSeparatedNodeList(field.Type) ||
                  IsNodeList(field.Type))
         {
             type = "Microsoft.CodeAnalysis.Syntax.InternalSyntax." + type;
         }
         Write("{0} {1}", type, CamelCase(field.Name));
     }
 }
Example #16
0
        private void WriteRedWithMethod(Node node)
        {
            WriteLine();
            Write("    public {0} With(", node.Name);

            // parameters
            for (int f = 0; f < node.Fields.Count; f++)
            {
                var field = node.Fields[f];
                var type = this.GetRedPropertyType(field);
                Write("Optional<{0}> {1} = default(Optional<{0}>)", type, CamelCase(field.Name));
                if (f < node.Fields.Count - 1)
                    Write(", ");
            }
            WriteLine(")");
            WriteLine("    {");

            Write("        return this.Update(");

            for (int f = 0; f < node.Fields.Count; f++)
            {
                var field = node.Fields[f];
                var parameterName = CamelCase(field.Name);
                WriteLine();
                Write("                    {0}.HasValue ? {0}.Value : this.{1}", parameterName, field.Name);
                if (f < node.Fields.Count - 1)
                    Write(",");
            }

            WriteLine();
            WriteLine("                    );");

            WriteLine("    }");
        }
Example #17
0
        private void WriteNodeGenerator(Node node, bool isGreen)
        {
            var valueFields = node.Fields.Where(n => !IsNodeOrNodeList(n.Type));
            var nodeFields  = node.Fields.Where(n => IsNodeOrNodeList(n.Type));

            var namespaceQualification = isGreen ? "Microsoft.CodeAnalysis.CSharp.Syntax.InternalSyntax." : "";

            var strippedName = StripPost(node.Name, "Syntax");

            WriteLine("private static {0}{1} Generate{2}()", namespaceQualification, node.Name, strippedName);
            OpenBlock();

            //instantiate node
            {
                Write("return {0}SyntaxFactory.{1}(", namespaceQualification, strippedName);

                bool first = true;

                if (node.Kinds.Count > 1)
                {
                    Write("SyntaxKind.{0}", node.Kinds[0].Name);                     //TODO: other kinds?
                    first = false;
                }

                foreach (var field in nodeFields)
                {
                    if (!first)
                    {
                        Write(", ");
                    }
                    first = false;

                    if (IsOptional(field))
                    {
                        if (isGreen)
                        {
                            Write("null");
                        }
                        else
                        {
                            Write("default({0})", field.Type);
                        }
                    }
                    else if (IsAnyList(field.Type))
                    {
                        string typeName;
                        if (isGreen)
                        {
                            typeName = namespaceQualification + field.Type.Replace("<", "<" + namespaceQualification);
                        }
                        else
                        {
                            typeName = (field.Type == "SyntaxList<SyntaxToken>") ? "SyntaxTokenList" : field.Type;
                        }
                        Write("new {0}()", typeName);
                    }
                    else if (field.Type == "SyntaxToken")
                    {
                        var kind           = ChooseValidKind(field);
                        var leadingTrivia  = isGreen ? "null, " : "";
                        var trailingTrivia = isGreen ? ", null" : "";
                        if (kind == "IdentifierToken")
                        {
                            Write("{0}SyntaxFactory.Identifier(\"{1}\")", namespaceQualification, field.Name);
                        }
                        else if (kind == "StringLiteralToken")
                        {
                            Write("{0}SyntaxFactory.Literal({1}\"string\", \"string\"{2})", namespaceQualification, leadingTrivia, trailingTrivia);
                        }
                        else if (kind == "CharacterLiteralToken")
                        {
                            Write("{0}SyntaxFactory.Literal({1}\"a\", 'a'{2})", namespaceQualification, leadingTrivia, trailingTrivia);
                        }
                        else if (kind == "NumericLiteralToken")
                        {
                            Write("{0}SyntaxFactory.Literal({1}\"1\", 1{2})", namespaceQualification, leadingTrivia, trailingTrivia);
                        }
                        else
                        {
                            Write("{0}SyntaxFactory.Token(SyntaxKind.{1})", namespaceQualification, ChooseValidKind(field));
                        }
                    }
                    else if (field.Type == "CSharpSyntaxNode")
                    {
                        Write("{0}SyntaxFactory.IdentifierName({0}SyntaxFactory.Identifier(\"{1}\"))", namespaceQualification, field.Name);
                    }
                    else
                    {
                        //drill down to a concrete type
                        var type = field.Type;
                        while (true)
                        {
                            var subTypes = ChildMap[type];
                            if (!subTypes.Any())
                            {
                                break;
                            }
                            type = subTypes.First();
                        }
                        Write("Generate{0}()", StripPost(type, "Syntax"));
                    }
                }

                foreach (var field in valueFields)
                {
                    if (!first)
                    {
                        Write(", ");
                    }
                    first = false;

                    Write("new {0}()", field.Type);
                }

                WriteLine(");");
            }

            CloseBlock();
        }
Example #18
0
        private void WriteRedSetters(Node node)
        {
            for (int f = 0; f < node.Fields.Count; f++)
            {
                var field = node.Fields[f];
                var type = this.GetRedPropertyType(field);

                WriteLine();
                WriteLine("    {0} {1} With{2}({3} {4})", "public", node.Name, StripPost(field.Name, "Opt"), type, CamelCase(field.Name));
                WriteLine("    {");

                // call update inside each setter
                Write("        return this.Update(");
                for (int f2 = 0; f2 < node.Fields.Count; f2++)
                {
                    var field2 = node.Fields[f2];
                    if (f2 > 0)
                        Write(", ");

                    if (field2 == field)
                    {
                        this.Write("{0}", CamelCase(field2.Name));
                    }
                    else
                    {
                        this.Write("this.{0}", field2.Name);
                    }
                }
                WriteLine(");");

                WriteLine("    }");
            }
        }
Example #19
0
        private int OptionalFactoryArgumentCount(Node nd)
        {
            int count = 0;
            for (int i = 0, n = nd.Fields.Count; i < n; i++)
            {
                var field = nd.Fields[i];
                if (IsOptional(field) || CanBeAutoCreated(nd, field) || IsAnyList(field.Type))
                {
                    count++;
                }
            }

            return count;
        }
Example #20
0
 private void WriteRedListHelperMethods(Node node)
 {
     for (int f = 0; f < node.Fields.Count; f++)
     {
         var field = node.Fields[f];
         if (IsAnyList(field.Type))
         {
             // write list helper methods for list properties
             WriteRedListHelperMethods(node, field);
         }
         else
         {
             Node referencedNode = GetNode(field.Type);
             if (referencedNode != null && (!IsOptional(field) || RequiredFactoryArgumentCount(referencedNode) == 0))
             {
                 // look for list members...
                 for (int rf = 0; rf < referencedNode.Fields.Count; rf++)
                 {
                     var referencedNodeField = referencedNode.Fields[rf];
                     if (IsAnyList(referencedNodeField.Type))
                     {
                         WriteRedNestedListHelperMethods(node, field, referencedNode, referencedNodeField);
                     }
                 }
             }
         }
     }
 }
Example #21
0
        private void WriteRedFactoryParameters(Node nd)
        {
            if (nd.Kinds.Count > 1)
            {
                Write("SyntaxKind kind, ");
            }

            for (int i = 0, n = nd.Fields.Count; i < n; i++)
            {
                var field = nd.Fields[i];
                if (i > 0)
                    Write(", ");
                var type = this.GetRedPropertyType(field);

                Write("{0} {1}", type, CamelCase(field.Name));
            }
        }
Example #22
0
 private void WriteRedListHelperMethods(Node node, Field field)
 {
     var argType = GetElementType(field.Type);
     WriteLine();
     WriteLine("    public {0} Add{1}(params {2}[] items)", node.Name, field.Name, argType);
     WriteLine("    {");
     WriteLine("        return this.With{0}(this.{1}.AddRange(items));", StripPost(field.Name, "Opt"), field.Name);
     WriteLine("    }");
 }
Example #23
0
        // Writes Get<Property>Kind() methods for converting between node kind and member token kinds...
        private void WriteKindConverters(Node nd)
        {
            for (int f = 0; f < nd.Fields.Count; f++)
            {
                var field = nd.Fields[f];

                if (field.Type == "SyntaxToken" && CanBeAutoCreated(nd, field) && field.Kinds.Count > 1)
                {
                    WriteLine();
                    WriteLine("    private static SyntaxKind Get{0}{1}Kind(SyntaxKind kind)", StripPost(nd.Name, "Syntax"), StripPost(field.Name, "Opt"));
                    WriteLine("    {");

                    WriteLine("      switch (kind)");
                    WriteLine("      {");

                    for (int k = 0; k < field.Kinds.Count; k++)
                    {
                        var nKind = nd.Kinds[k];
                        var pKind = field.Kinds[k];
                        WriteLine("        case SyntaxKind.{0}:", nKind.Name);
                        WriteLine("          return SyntaxKind.{0};", pKind.Name);
                    }

                    WriteLine("        default:");
                    WriteLine("          throw new ArgumentOutOfRangeException();");
                    WriteLine("      }");
                    WriteLine("    }");
                }
            }
        }
Example #24
0
        private void WriteRedNestedListHelperMethods(Node node, Field field, Node referencedNode, Field referencedNodeField)
        {
            var argType = GetElementType(referencedNodeField.Type);

            // AddBaseListTypes
            WriteLine();
            WriteLine("    public {0} Add{1}{2}(params {3}[] items)", node.Name, StripPost(field.Name, "Opt"), referencedNodeField.Name, argType);
            WriteLine("    {");

            if (IsOptional(field))
            {
                var factoryName = StripPost(referencedNode.Name, "Syntax");
                var varName = StripPost(CamelCase(field.Name), "Opt");
                WriteLine("        var {0} = this.{1} ?? SyntaxFactory.{2}();", varName, field.Name, factoryName);
                WriteLine("        return this.With{0}({1}.With{2}({1}.{3}.AddRange(items)));", StripPost(field.Name, "Opt"), varName, StripPost(referencedNodeField.Name, "Opt"), referencedNodeField.Name);
            }
            else
            {
                WriteLine("        return this.With{0}(this.{1}.With{2}(this.{1}.{3}.AddRange(items)));", StripPost(field.Name, "Opt"), field.Name, StripPost(referencedNodeField.Name, "Opt"), referencedNodeField.Name);
            }

            WriteLine("    }");
        }
Example #25
0
        // creates a factory without auto-creatable token arguments
        private void WriteRedFactoryWithNoAutoCreatableTokens(Node nd)
        {
            var nAutoCreatableTokens = nd.Fields.Count(f => IsAutoCreatableToken(nd, f));
            if (nAutoCreatableTokens == 0)
                return; // already handled by general factory

            var factoryWithNoAutoCreatableTokenFields = new HashSet<Field>(DetermineRedFactoryWithNoAutoCreatableTokenFields(nd));
            var minimalFactoryFields = DetermineMinimalFactoryFields(nd);
            if (minimalFactoryFields != null && factoryWithNoAutoCreatableTokenFields.SetEquals(minimalFactoryFields))
            {
                return; // will be handled in minimal factory case
            }

            this.WriteLine();

            WriteComment(string.Format("<summary>Creates a new {0} instance.</summary>", nd.Name), "    ");
            Write("    {0} static {1} {2}(", "public", nd.Name, StripPost(nd.Name, "Syntax"));

            bool hasPreviousParameter = false;
            if (nd.Kinds.Count > 1)
            {
                Write("SyntaxKind kind");
                hasPreviousParameter = true;
            }

            for (int i = 0, n = nd.Fields.Count; i < n; i++)
            {
                var field = nd.Fields[i];

                if (factoryWithNoAutoCreatableTokenFields.Contains(field))
                {
                    if (hasPreviousParameter)
                        Write(", ");

                    Write("{0} {1}", GetRedPropertyType(field), CamelCase(field.Name));

                    hasPreviousParameter = true;
                }
            }
            WriteLine(")");

            WriteLine("    {");

            Write("      return SyntaxFactory.{0}(", StripPost(nd.Name, "Syntax"));

            bool hasPreviousArgument = false;
            if (nd.Kinds.Count > 1)
            {
                Write("kind");
                hasPreviousArgument = true;
            }

            for (int i = 0, n = nd.Fields.Count; i < n; i++)
            {
                var field = nd.Fields[i];

                if (hasPreviousArgument)
                    Write(", ");

                if (factoryWithNoAutoCreatableTokenFields.Contains(field))
                {
                    // pass supplied parameter on to general factory
                    Write("{0}", CamelCase(field.Name));
                }
                else
                {
                    // pass an auto-created token to the general factory
                    Write("{0}", GetDefaultValue(nd, field));
                }

                hasPreviousArgument = true;
            }

            WriteLine(");");

            WriteLine("    }");
        }
Example #26
0
 protected bool CanBeAutoCreated(Node node, Field field)
 {
     return IsAutoCreatableToken(node, field) || IsAutoCreatableNode(node, field);
 }
Example #27
0
        private void WriteGreenSerialization(Node node)
        {
            var valueFields = node.Fields.Where(n => !IsNodeOrNodeList(n.Type)).ToList();
            var nodeFields = node.Fields.Where(n => IsNodeOrNodeList(n.Type)).ToList();

            // object reader constructor
            WriteLine();
            WriteLine("    internal {0}(ObjectReader reader)", node.Name);
            WriteLine("        : base(reader)");
            WriteLine("    {");

            WriteLine("      this.SlotCount = {0};", nodeFields.Count);

            for (int i = 0, n = nodeFields.Count; i < n; i++)
            {
                var field = nodeFields[i];
                string type = GetFieldType(field, green: true);
                WriteLine("      var {0} = ({1})reader.ReadValue();", CamelCase(field.Name), type);
                WriteLine("      if ({0} != null)", CamelCase(field.Name));
                WriteLine("      {");
                WriteLine("         AdjustFlagsAndWidth({0});", CamelCase(field.Name));
                WriteLine("         this.{0} = {0};", CamelCase(field.Name), type);
                WriteLine("      }");
            }

            for (int i = 0, n = valueFields.Count; i < n; i++)
            {
                var field = valueFields[i];
                string type = GetFieldType(field, green: true);
                WriteLine("      this.{0} = ({1})reader.{2}();", CamelCase(field.Name), type, GetReaderMethod(type));
            }

            WriteLine("    }");

            // IWritable 
            WriteLine();
            WriteLine("    internal override void WriteTo(ObjectWriter writer)");
            WriteLine("    {");
            WriteLine("      base.WriteTo(writer);");

            for (int i = 0, n = nodeFields.Count; i < n; i++)
            {
                var field = nodeFields[i];
                string type = GetFieldType(field, green: true);
                WriteLine("      writer.WriteValue(this.{0});", CamelCase(field.Name));
            }

            for (int i = 0, n = valueFields.Count; i < n; i++)
            {
                var field = valueFields[i];
                var type = GetFieldType(field, green: true);
                WriteLine("      writer.{0}(this.{1});", GetWriterMethod(type), CamelCase(field.Name));
            }

            WriteLine("    }");

            // IReadable
            WriteLine();
            WriteLine("    internal override Func<ObjectReader, object> GetReader()");
            WriteLine("    {");
            WriteLine("       return r => new {0}(r);", node.Name);
            WriteLine("    }");
        }
Example #28
0
 private bool IsAutoCreatableToken(Node node, Field field)
 {
     return field.Type == "SyntaxToken"
         && field.Kinds != null
         && ((field.Kinds.Count == 1 && field.Kinds[0].Name != "IdentifierToken" && !field.Kinds[0].Name.EndsWith("LiteralToken", StringComparison.Ordinal)) || (field.Kinds.Count > 1 && field.Kinds.Count == node.Kinds.Count));
 }
Example #29
0
 private void WriteGreenAcceptMethods(Node node)
 {
     //WriteLine();
     //WriteLine("    public override TResult Accept<TArgument, TResult>(SyntaxVisitor<TArgument, TResult> visitor, TArgument argument)");
     //WriteLine("    {");
     //WriteLine("        return visitor.Visit{0}(this, argument);", StripPost(node.Name, "Syntax"));
     //WriteLine("    }");
     WriteLine();
     WriteLine("    public override TResult Accept<TResult>(CSharpSyntaxVisitor<TResult> visitor)");
     WriteLine("    {");
     WriteLine("        return visitor.Visit{0}(this);", StripPost(node.Name, "Syntax"));
     WriteLine("    }");
     WriteLine();
     WriteLine("    public override void Accept(CSharpSyntaxVisitor visitor)");
     WriteLine("    {");
     WriteLine("        visitor.Visit{0}(this);", StripPost(node.Name, "Syntax"));
     WriteLine("    }");
 }
Example #30
0
 private bool IsAutoCreatableNode(Node node, Field field)
 {
     var referencedNode = GetNode(field.Type);
     return (referencedNode != null && RequiredFactoryArgumentCount(referencedNode) == 0);
 }
Example #31
0
        private void WriteGreenFactory(Node nd, bool withSyntaxFactoryContext = false)
        {
            var valueFields = nd.Fields.Where(n => !IsNodeOrNodeList(n.Type)).ToList();
            var nodeFields = nd.Fields.Where(n => IsNodeOrNodeList(n.Type)).ToList();

            Write("    public {0}{1} {2}(", withSyntaxFactoryContext ? "" : "static ", nd.Name, StripPost(nd.Name, "Syntax"));
            WriteGreenFactoryParameters(nd);
            WriteLine(")");
            WriteLine("    {");

            // validate kind
            if (nd.Kinds.Count > 1)
            {
                WriteLine("      switch (kind)");
                WriteLine("      {");
                foreach (var k in nd.Kinds)
                {
                    WriteLine("        case SyntaxKind.{0}:", k.Name);
                }
                WriteLine("          break;");
                WriteLine("        default:");
                WriteLine("          throw new ArgumentException(\"kind\");");
                WriteLine("      }");
            }

            // validate parameters
            WriteLine("#if DEBUG");
            for (int i = 0, n = nodeFields.Count; i < n; i++)
            {
                var field = nodeFields[i];
                var pname = CamelCase(field.Name);

                if (!IsAnyList(field.Type) && !IsOptional(field))
                {
                    WriteLine("      if ({0} == null)", CamelCase(field.Name));
                    WriteLine("        throw new ArgumentNullException(nameof({0}));", CamelCase(field.Name));
                }
                if (field.Type == "SyntaxToken" && field.Kinds != null && field.Kinds.Count > 0)
                {
                    if (IsOptional(field))
                    {
                        WriteLine("      if ({0} != null)", CamelCase(field.Name));
                        WriteLine("      {");
                    }
                    WriteLine("      switch ({0}.Kind)", pname);
                    WriteLine("      {");
                    foreach (var kind in field.Kinds)
                    {
                        WriteLine("        case SyntaxKind.{0}:", kind.Name);
                    }
                    //we need to check for Kind=None as well as node == null because that's what the red factory will pass
                    if (IsOptional(field))
                    {
                        WriteLine("        case SyntaxKind.None:");
                    }
                    WriteLine("          break;");
                    WriteLine("        default:");
                    WriteLine("          throw new ArgumentException(\"{0}\");", pname);
                    WriteLine("      }");
                    if (IsOptional(field))
                    {
                        WriteLine("      }");
                    }
                }
            }

            WriteLine("#endif");

            if (nd.Name != "SkippedTokensTriviaSyntax" &&
                nd.Name != "DocumentationCommentTriviaSyntax" &&
                nd.Name != "IncompleteMemberSyntax" &&
                valueFields.Count + nodeFields.Count <= 3)
            {
                //int hash;
                //var cached = SyntaxNodeCache.TryGetNode((int)SyntaxKind.IdentifierName, identifier, this.context, out hash);
                //if (cached != null) return (IdentifierNameSyntax)cached;

                //var result = new IdentifierNameSyntax(SyntaxKind.IdentifierName, identifier, this.context);
                //if (hash >= 0)
                //{
                //    SyntaxNodeCache.AddNode(result, hash);
                //}

                //return result;

                WriteLine();
                //int hash;
                WriteLine("      int hash;");
                //SyntaxNode cached = SyntaxNodeCache.TryGetNode(SyntaxKind.IdentifierName, identifier, this.context, out hash);
                if (withSyntaxFactoryContext)
                {
                    Write("      var cached = CSharpSyntaxNodeCache.TryGetNode((int)");
                }
                else
                {
                    Write("      var cached = SyntaxNodeCache.TryGetNode((int)");
                }

                WriteCtorArgList(nd, withSyntaxFactoryContext, valueFields, nodeFields);
                WriteLine(", out hash);");
                //    if (cached != null) return (IdentifierNameSyntax)cached;
                WriteLine("      if (cached != null) return ({0})cached;", nd.Name);
                WriteLine();

                //var result = new IdentifierNameSyntax(SyntaxKind.IdentifierName, identifier);
                Write("      var result = new {0}(", nd.Name);
                WriteCtorArgList(nd, withSyntaxFactoryContext, valueFields, nodeFields);
                WriteLine(");");
                //if (hash >= 0)
                WriteLine("      if (hash >= 0)");
                //{
                WriteLine("      {");
                //    SyntaxNodeCache.AddNode(result, hash);
                WriteLine("          SyntaxNodeCache.AddNode(result, hash);");
                //}
                WriteLine("      }");
                WriteLine();

                //return result;
                WriteLine("      return result;");
            }
            else
            {
                WriteLine();
                Write("      return new {0}(", nd.Name);
                WriteCtorArgList(nd, withSyntaxFactoryContext, valueFields, nodeFields);
                WriteLine(");");
            }

            WriteLine("    }");
        }
Example #32
0
 private bool IsRequiredFactoryField(Node node, Field field)
 {
     return (!IsOptional(field) && !IsAnyList(field.Type) && !CanBeAutoCreated(node, field)) || IsValueField(field);
 }
Example #33
0
 private void WriteCtorArgList(Node nd, bool withSyntaxFactoryContext, List<Field> valueFields, List<Field> nodeFields)
 {
     if (nd.Kinds.Count == 1)
     {
         Write("SyntaxKind.");
         Write(nd.Kinds[0].Name);
     }
     else
     {
         Write("kind");
     }
     for (int i = 0, n = nodeFields.Count; i < n; i++)
     {
         var field = nodeFields[i];
         Write(", ");
         if (field.Type == "SyntaxList<SyntaxToken>" || IsAnyList(field.Type))
         {
             Write("{0}.Node", CamelCase(field.Name));
         }
         else
         {
             Write(CamelCase(field.Name));
         }
     }
     // values are at end
     for (int i = 0, n = valueFields.Count; i < n; i++)
     {
         var field = valueFields[i];
         Write(", ");
         Write(CamelCase(field.Name));
     }
     if (withSyntaxFactoryContext)
     {
         Write(", this.context");
     }
 }
Example #34
0
        private void WriteFactoryPropertyTest(Node node, bool isGreen)
        {
            var valueFields = node.Fields.Where(n => !IsNodeOrNodeList(n.Type));
            var nodeFields  = node.Fields.Where(n => IsNodeOrNodeList(n.Type));

            var strippedName = StripPost(node.Name, "Syntax");

            WriteLine("[Fact]");
            WriteLine("public void Test{0}FactoryAndProperties()", strippedName);
            OpenBlock();

            WriteLine("var node = Generate{0}();", strippedName);

            WriteLine();

            //check properties
            {
                string withStat = null;
                foreach (var field in nodeFields)
                {
                    if (IsOptional(field))
                    {
                        if (!isGreen && field.Type == "SyntaxToken")
                        {
                            WriteLine("Assert.Equal(SyntaxKind.None, node.{0}.CSharpKind());", field.Name);
                        }
                        else
                        {
                            WriteLine("Assert.Null(node.{0});", field.Name);
                        }
                    }
                    else if (field.Type == "SyntaxToken")
                    {
                        if (!isGreen)
                        {
                            WriteLine("Assert.Equal(SyntaxKind.{0}, node.{1}.CSharpKind());", ChooseValidKind(field), field.Name);
                        }
                        else
                        {
                            WriteLine("Assert.Equal(SyntaxKind.{0}, node.{1}.Kind);", ChooseValidKind(field), field.Name);
                        }
                    }
                    else
                    {
                        WriteLine("Assert.NotNull(node.{0});", field.Name);
                    }

                    if (!isGreen)
                    {
                        withStat += string.Format(".With{0}(node.{0})", field.Name);
                    }
                }

                foreach (var field in valueFields)
                {
                    WriteLine("Assert.Equal(new {0}(), node.{1});", field.Type, field.Name);
                    if (!isGreen)
                    {
                        withStat += string.Format(".With{0}(node.{0})", field.Name);
                    }
                }

                if (!isGreen && withStat != null)
                {
                    WriteLine("var newNode = node{0};", withStat);
                    WriteLine("Assert.Equal(node, newNode);");
                }
            }

            if (isGreen)
            {
                WriteLine();
                WriteLine("AttachAndCheckDiagnostics(node);");
            }

            CloseBlock();
        }