Ejemplo n.º 1
0
        public void Build(CodeFragmentBuilder builder)
        {
            builder.AppendLine("public enum {0}", Name);
            builder.AppendLine("{");
            builder.Indent();

            var names = new List<string>(FieldNames);

            names.Sort();

            int none = names.IndexOf("None");

            if (none != -1)
            {
                names.RemoveAt(none);
                names.Insert(0, "None");
            }

            for (int i = 0; i < names.Count; i++)
            {
                builder.Append(names[i]);
                if (i != names.Count - 1)
                    builder.Append(",");
                builder.AppendLine();
            }

            builder.Unindent();
            builder.AppendLine("}");
        }
 public void Build(CodeFragmentBuilder builder)
 {
     builder.AppendLine("if ({0} != null)", Name);
     builder.Indent();
     builder.AppendLine("yield return {0};", Name);
     builder.Unindent();
 }
        public void Build(CodeFragmentBuilder builder)
        {
            builder.AppendLine("[Flags]");
            builder.AppendLine("public enum {0}", Name);
            builder.AppendLine("{");
            builder.Indent();

            builder.AppendLine("None = 0,");

            for (int i = 0; i < FieldNames.Length; i++)
            {
                builder.Append(FieldNames[i]);
                builder.Append(" = 1 << ");
                builder.Append(i.ToString(CultureInfo.InvariantCulture));
                if (i != FieldNames.Length - 1 || AddAll)
                    builder.Append(",");
                builder.AppendLine();
            }

            if (AddAll)
            {
                builder.Append("All = (1 << ");
                builder.Append(FieldNames.Length.ToString(CultureInfo.InvariantCulture));
                builder.AppendLine(") - 1");
            }

            builder.Unindent();
            builder.AppendLine("}");
        }
Ejemplo n.º 4
0
        public void Build(CodeFragmentBuilder builder)
        {
            builder.AppendLine("public enum {0}", Name);
            builder.AppendLine("{");
            builder.Indent();

            var names = new List <string>(FieldNames);

            names.Sort();

            int none = names.IndexOf("None");

            if (none != -1)
            {
                names.RemoveAt(none);
                names.Insert(0, "None");
            }

            for (int i = 0; i < names.Count; i++)
            {
                builder.Append(names[i]);
                if (i != names.Count - 1)
                {
                    builder.Append(",");
                }
                builder.AppendLine();
            }

            builder.Unindent();
            builder.AppendLine("}");
        }
Ejemplo n.º 5
0
        public void Build(CodeFragmentBuilder builder)
        {
            builder.AppendLine("[Flags]");
            builder.AppendLine("public enum {0}", Name);
            builder.AppendLine("{");
            builder.Indent();

            builder.AppendLine("None = 0,");

            for (int i = 0; i < FieldNames.Length; i++)
            {
                builder.Append(FieldNames[i]);
                builder.Append(" = 1 << ");
                builder.Append(i.ToString(CultureInfo.InvariantCulture));
                if (i != FieldNames.Length - 1 || AddAll)
                {
                    builder.Append(",");
                }
                builder.AppendLine();
            }

            if (AddAll)
            {
                builder.Append("All = (1 << ");
                builder.Append(FieldNames.Length.ToString(CultureInfo.InvariantCulture));
                builder.AppendLine(") - 1");
            }

            builder.Unindent();
            builder.AppendLine("}");
        }
 public void Build(CodeFragmentBuilder builder)
 {
     builder.AppendLine("if ({0} != null)", Name);
     builder.Indent();
     builder.AppendLine("yield return {0};", Name);
     builder.Unindent();
 }
        public void Build(CodeFragmentBuilder builder)
        {
            builder.AppendLine("foreach (var item in {0})", Name);
            builder.AppendLine("{");
            builder.Indent();

            builder.AppendLine("yield return item;");

            builder.Unindent();
            builder.AppendLine("}");
        }
        public void Build(CodeFragmentBuilder builder)
        {
            builder.AppendLine("foreach (var item in {0})", Name);
            builder.AppendLine("{");
            builder.Indent();

            builder.AppendLine("yield return item;");

            builder.Unindent();
            builder.AppendLine("}");
        }
Ejemplo n.º 9
0
        private void BuildFactories(string target, Dictionary<SyntaxType, List<Factory>> factories, HashSet<SyntaxType> writtenTypes)
        {
            var builder = new CodeFragmentBuilder();

            builder.AppendLine("using System;");
            builder.AppendLine("using System.Collections.Generic;");
            builder.AppendLine("using System.Linq;");
            builder.AppendLine("using System.Text;");
            builder.AppendLine();
            builder.AppendLine("namespace CSharpSyntax");
            builder.AppendLine("{");
            builder.Indent();

            builder.AppendLine("public static partial class Syntax");
            builder.AppendLine("{");
            builder.Indent();

            bool hadOne = false;

            foreach (var item in factories.Where(p => writtenTypes.Contains(p.Key)).OrderBy(p => p.Key.Name))
            {
                foreach (var factory in item.Value)
                {
                    factory.Parameters.RemoveAll(p => p.Type == "SyntaxKind");
                }
            }

            SeedParamsFactories(factories);
            SeedParseNameFactories(factories);

            foreach (var item in factories.Where(p => writtenTypes.Contains(p.Key)).OrderBy(p => p.Key.Name))
            {
                for (int i = 0; i < item.Value.Count; i++)
                {
                    var factory = item.Value[i];
                    bool duplicate = false;

                    for (int j = i + 1; j < item.Value.Count; j++)
                    {
                        if (factory.Equals(item.Value[j]))
                        {
                            duplicate = true;
                            break;
                        }
                    }

                    if (duplicate)
                        continue;
                    if (factory.Parameters.Count == 0 && item.Value.Any(p => p.Parameters.Count > 0))
                        continue;
                    if (FactoryWithMoreParametersExists(factory, item.Value))
                        continue;

                    if (hadOne)
                        builder.AppendLine();
                    else
                        hadOne = true;

                    builder.Append(
                        "public static {0} {1}(",
                        item.Key.Name,
                        factory.Name
                    );

                    bool hadOneChild = false;

                    foreach (var parameter in factory.Parameters)
                    {
                        if (hadOneChild)
                            builder.Append(", ");
                        else
                            hadOneChild = true;

                        if (parameter.IsParams)
                            builder.Append("params ");

                        string type = parameter.Type;

                        switch (type)
                        {
                            case "String": type = "string"; break;
                            case "Object": type = "object"; break;
                        }

                        if (parameter.IsParams && !type.EndsWith("[]"))
                            type += "[]";

                        if (parameter.IsList)
                            builder.Append("IEnumerable<{0}> {1}", type, EscapeParameterName(parameter));
                        else
                            builder.Append("{0} {1}", type, EscapeParameterName(parameter));

                        if (
                            (parameter.IsOptional || true) && // All parameters are currently generated as default
                            !parameter.IsParams
                        )
                        {
                            if (
                                parameter.OriginalType.IsValueType ||
                                parameter.OriginalType == typeof(AttributeTargetSpecifierSyntax)
                            )
                                builder.Append(" = default({0})", parameter.Type);
                            else
                                builder.Append(" = null");
                        }
                    }

                    builder.AppendLine(")");
                    builder.AppendLine("{");
                    builder.Indent();

                    builder.AppendLine("var result = new {0}();", item.Key.Name);
                    builder.AppendLine();

                    foreach (var parameter in factory.Parameters)
                    {
                        if (parameter.Type == "SyntaxKind")
                            continue;

                        string propertyName = parameter.Name.Substring(0, 1).ToUpperInvariant() + parameter.Name.Substring(1);
                        string parameterName = EscapeParameterName(parameter);

                        string parseName = parameter.ParseNameType;

                        if (item.Key.Name == "AliasQualifiedNameSyntax")
                        {
                            if (parameter.Name == "alias" && parameter.Type == "String")
                                parseName = "IdentifierNameSyntax";
                        }
                        else if (item.Key.Name == "IdentifierNameSyntax")
                        {
                            if (parameter.Name == "name")
                                propertyName = "Identifier";
                        }
                        else if (new[] { "NameColonSyntax", "NameEqualsSyntax", "TypeParameterConstraintClauseSyntax" }.Contains(item.Key.Name))
                        {
                            if (parameter.Name == "name" && parameter.Type == "String")
                                parseName = "IdentifierNameSyntax";
                        }

                        if (parseName != null)
                        {
                            builder.AppendLine("if ({0} != null)", parameterName);
                            builder.Indent();

                            if (parseName == "TypeSyntax")
                            {
                                if (parameter.IsList || parameter.IsParams)
                                {
                                    builder.AppendLine(
                                        "result.{0}.AddRange(ParseNames<TypeSyntax>({1}));",
                                        propertyName,
                                        parameterName
                                    );
                                }
                                else
                                {
                                    builder.AppendLine(
                                        "result.{0} = ParseName({1});",
                                        propertyName,
                                        parameterName
                                    );
                                }
                            }
                            else
                            {
                                if (parameter.IsList || parameter.IsParams)
                                {
                                    builder.AppendLine(
                                        "result.{0}.AddRange(ParseNames<{2}>({1}));",
                                        propertyName,
                                        parameterName,
                                        parseName
                                    );
                                }
                                else
                                {
                                    builder.AppendLine(
                                        "result.{0} = ({2})ParseName({1});",
                                        propertyName,
                                        parameterName,
                                        parseName
                                    );
                                }
                            }

                            builder.Unindent();
                        }
                        else if (parameter.IsList || parameter.IsParams)
                        {
                            builder.AppendLine("if ({0} != null)", parameterName);
                            builder.Indent();
                            builder.AppendLine("result.{0}.AddRange({1});", propertyName, parameterName);
                            builder.Unindent();
                        }
                        else
                        {
                            builder.AppendLine(
                                "result.{0} = {1};",
                                propertyName,
                                parameterName
                            );
                        }
                    }

                    builder.AppendLine();
                    builder.AppendLine("return result;");

                    builder.Unindent();
                    builder.AppendLine("}");
                }
            }

            builder.Unindent();
            builder.AppendLine("}");

            builder.Unindent();
            builder.AppendLine("}");

            WriteFile(target, "Syntax", builder);
        }
Ejemplo n.º 10
0
        private void BuildBaseVisitor(string target, HashSet<string> visitors)
        {
            var builder = new CodeFragmentBuilder();

            builder.AppendLine("using System;");
            builder.AppendLine("using System.Collections.Generic;");
            builder.AppendLine("using System.Linq;");
            builder.AppendLine("using System.Text;");
            builder.AppendLine("using System.Diagnostics;");
            builder.AppendLine();
            builder.AppendLine("namespace CSharpSyntax");
            builder.AppendLine("{");
            builder.Indent();

            builder.AppendLine("public class SyntaxVisitorBase : ISyntaxVisitor");
            builder.AppendLine("{");
            builder.Indent();
            builder.AppendLine("public bool Done { get; protected set; }");

            foreach (string name in visitors.OrderBy(p => p))
            {
                builder.AppendLine();
                builder.AppendLine("[DebuggerStepThrough]");
                builder.AppendLine("public virtual void Visit{1}({0} node)", name, StripPostfix(name, "Syntax"));
                builder.AppendLine("{");
                builder.Indent();

                builder.AppendLine("DefaultVisit(node);");

                builder.Unindent();
                builder.AppendLine("}");
            }

            builder.AppendLine();
            builder.AppendLine("[DebuggerStepThrough]");
            builder.AppendLine("public virtual void Visit(SyntaxNode node)");
            builder.AppendLine("{");
            builder.Indent();

            builder.AppendLine("if (node != null)");
            builder.Indent();
            builder.AppendLine("node.Accept(this);");
            builder.Unindent();

            builder.Unindent();
            builder.AppendLine("}");

            builder.AppendLine();
            builder.AppendLine("[DebuggerStepThrough]");
            builder.AppendLine("public virtual void DefaultVisit(SyntaxNode node)");
            builder.AppendLine("{");
            builder.AppendLine("}");

            builder.Unindent();
            builder.AppendLine("}");
            builder.AppendLine();

            builder.AppendLine("public class SyntaxVisitorBase<T> : ISyntaxVisitor<T>");
            builder.AppendLine("{");
            builder.Indent();

            foreach (string name in visitors.OrderBy(p => p))
            {
                builder.AppendLine("[DebuggerStepThrough]");
                builder.AppendLine("public virtual T Visit{1}({0} node)", name, StripPostfix(name, "Syntax"));
                builder.AppendLine("{");
                builder.Indent();

                builder.AppendLine("return DefaultVisit(node);");

                builder.Unindent();
                builder.AppendLine("}");

                builder.AppendLine();
            }

            builder.AppendLine("[DebuggerStepThrough]");
            builder.AppendLine("public virtual T Visit(SyntaxNode node)");
            builder.AppendLine("{");
            builder.Indent();

            builder.AppendLine("if (node == null)");
            builder.Indent();
            builder.AppendLine("return default(T);");
            builder.Unindent();
            builder.AppendLine();
            builder.AppendLine("return node.Accept(this);");

            builder.Unindent();
            builder.AppendLine("}");

            builder.AppendLine();

            builder.AppendLine("[DebuggerStepThrough]");
            builder.AppendLine("public virtual T DefaultVisit(SyntaxNode node)");
            builder.AppendLine("{");
            builder.Indent();

            builder.AppendLine("return default(T);");

            builder.Unindent();
            builder.AppendLine("}");

            builder.Unindent();
            builder.AppendLine("}");

            builder.Unindent();
            builder.AppendLine("}");

            WriteFile(target, "SyntaxVisitorBase", builder);
        }
Ejemplo n.º 11
0
        public void Generate(string target)
        {
            var enums = new EnumDeclarationCollection();
            var nonAbstractTypes = new HashSet<string>();

            var factories = GetFactories();
            var writtenTypes = new HashSet<SyntaxType>();

            foreach (var type in GetTypes())
            {
                if (!type.IsAbstract)
                    nonAbstractTypes.Add(type.Name);

                var builder = new CodeFragmentBuilder();
                var initializeLists = new Dictionary<string, string>();
                var getChildrenGenerators = new List<IGetChildrenGenerator>();

                builder.AppendLine("using System;");
                builder.AppendLine("using System.Collections.Generic;");
                builder.AppendLine("using System.Linq;");
                builder.AppendLine("using System.Text;");

                // We only need this when we're implementing an Accept.
                if (!type.IsAbstract)
                    builder.AppendLine("using System.Diagnostics;");

                builder.AppendLine();
                builder.AppendLine("namespace CSharpSyntax");
                builder.AppendLine("{");
                builder.Indent();

                string baseType = type.BaseType.Name;

                if (_allowTriviaTypes.Any(p => p.Name == type.Name))
                {
                    Debug.Assert(baseType == "SyntaxNode");

                    baseType = "SyntaxTriviaNode";
                }

                builder.AppendLine("public {0} partial class {1} : {2}", type.IsAbstract ? "abstract" : "sealed", type.Name, baseType);
                builder.AppendLine("{");
                builder.Indent();

                foreach (var property in
                    from property in type.Properties
                    where property.DeclaringType == type
                    orderby property.Name
                    select property)
                {
                    if (
                        type.BaseType.Properties.Contains(property.Name) ||
                        property.Name == "ParentTrivia" ||
                        property.Name == "AllowsAnyExpression" ||
                        property.Name == "IsConst" ||
                        property.Name == "IsFixed"
                    )
                        continue;

                    // These are not supported because they are associated with errors.

                    //if (typeof(BracketedArgumentListSyntax).IsAssignableFrom(property.PropertyType))
                    //    continue;

                    string propertyType = CodeUtil.Encode(property.PropertyType);
                    string propertyName = property.Name;

                    // These are hand coded to keep the complexity of the generator down.

                    if (new[] { "Arity", "IsVar", "Rank" }.Contains(property.Name))
                        continue;

                    if (property.Name == "Target")
                    {
                        propertyType = "AttributeTarget";
                        enums.Add(new EnumDeclaration(
                            propertyType,
                            new[] { "None", "Assembly", "Field", "Event", "Method", "Module", "Param", "Property", "Return", "Type" }
                        ));
                    }
                    else if (
                        property.PropertyType == typeof(SyntaxTrivia) ||
                        property.PropertyType == typeof(SyntaxToken) ||
                        property.PropertyType == typeof(SyntaxTokenList)
                    )
                    {
                        if (property.Name == "TextTokens")
                        {
                            propertyName = "Text";
                            propertyType = "string";
                        }
                        else if (property.Name == "Modifiers")
                        {
                            if (type.Name == "ParameterSyntax")
                            {
                                propertyType = "ParameterModifier";
                                propertyName = "Modifier";
                            }
                            else
                            {
                                propertyType = "Modifiers";
                                if (!enums.Contains(propertyType))
                                {
                                    enums.Add(new FlagsEnumDeclaration(
                                        propertyType,
                                        new[] { "Async", "Abstract", "Const", "Extern", "Internal", "New", "Override", "Partial", "Private", "Protected", "Public", "ReadOnly", "Sealed", "Static", "Virtual", "Volatile" },
                                        true
                                    ));
                                }
                            }
                        }
                        else if (property.Name == "Keyword")
                        {
                            propertyType = null;
                            var items = new List<string>();

                            switch (type.Name)
                            {
                                case "PredefinedTypeSyntax":
                                    propertyName = "Type";
                                    propertyType = "PredefinedType";
                                    items.AddRange(new[] { "Bool", "Byte", "SByte", "Short", "UShort", "Int", "UInt", "Long", "ULong", "Double", "Float", "Decimal", "String", "Char", "Void", "Object" });
                                    break;

                                case "TypeDeclarationSyntax":
                                case "MakeRefExpressionSyntax":
                                case "RefTypeExpressionSyntax":
                                case "RefValueExpressionSyntax":
                                case "DefaultExpressionSyntax":
                                case "TypeOfExpressionSyntax":
                                case "SizeOfExpressionSyntax":
                                    break;

                                case "CheckedExpressionSyntax":
                                case "CheckedStatementSyntax":
                                    propertyName = "Kind";
                                    propertyType = "CheckedOrUnchecked";
                                    items.AddRange(new[] { "Checked", "Unchecked" });
                                    break;

                                case "AccessorDeclarationSyntax":
                                    propertyName = "Kind";
                                    propertyType = "AccessorDeclarationKind";
                                    items.AddRange(new[] { "Get", "Set", "Add", "Remove" });
                                    break;

                                default:
                                    throw new NotSupportedException();
                            }

                            if (propertyType == null)
                                continue;
                            else if (!enums.Contains(propertyType))
                                enums.Add(new EnumDeclaration(propertyType, items.ToArray()));
                        }
                        else if (property.Name == "OperatorToken")
                        {
                            propertyType = null;
                            propertyName = "Operator";
                            var items = new List<string>();

                            if (type.Name == "OperatorDeclarationSyntax")
                            {
                                propertyType = "Operator";
                                items.AddRange(new[] { "Plus", "Minus", "Exclamation", "Tilde", "PlusPlus", "MinusMinus", "Asterisk", "Slash", "Percent", "LessThanLessThan", "GreaterThanGreaterThan", "Bar", "Ampersand", "Caret", "EqualsEquals", "ExclamationEquals", "LessThan", "LessThanEquals", "GreaterThan", "GreaterThanEquals", "False", "True" });
                            }
                            else
                            {
                                switch (type.Name)
                                {
                                    case "BinaryExpressionSyntax":
                                        propertyType = "BinaryOperator";
                                        items.AddRange(new[] { "Percent", "Caret", "Ampersand", "Asterisk", "Minus", "Plus", "Equals", "Bar", "LessThan", "GreaterThan", "Slash", "BarBar", "AmpersandAmpersand", "QuestionQuestion", "ExclamationEquals", "EqualsEquals", "LessThanEquals", "LessThanLessThan", "LessThanLessThanEquals", "GreaterThanEquals", "GreaterThanGreaterThan", "GreaterThanGreaterThanEquals", "SlashEquals", "AsteriskEquals", "BarEquals", "AmpersandEquals", "PlusEquals", "MinusEquals", "CaretEquals", "PercentEquals", "IsKeyword", "AsKeyword" });
                                        break;

                                    case "PrefixUnaryExpressionSyntax":
                                        propertyType = "PrefixUnaryOperator";
                                        items.AddRange(new[] { "Tilde", "Exclamation", "Ampersand", "Asterisk", "Minus", "Plus", "MinusMinus", "PlusPlus" });
                                        break;

                                    case "PostfixUnaryExpressionSyntax":
                                        propertyType = "PostfixUnaryOperator";
                                        items.AddRange(new[] { "MinusMinus", "PlusPlus" });
                                        break;

                                    case "MemberAccessExpressionSyntax":
                                        // The operator token on this is ignored.
                                        break;

                                    default:
                                        throw new InvalidOperationException();
                                }
                            }

                            if (propertyType == null)
                                continue;
                            else if (!enums.Contains(propertyType))
                                enums.Add(new EnumDeclaration(propertyType, items.ToArray()));
                        }
                        else if (
                            type.Name == "LiteralExpressionSyntax" &&
                            property.Name == "Token"
                        )
                        {
                            propertyType = "object";
                            propertyName = "Value";
                        }
                        else if (
                            property.Name.EndsWith("Token") ||
                            property.Name == "EndOfComment" || // DocumentationComment
                            property.Name == "Comma" // RefValueExpression
                        )
                        {
                            continue;
                        }
                        else if (property.Name.EndsWith("Keyword"))
                        {
                            string trimmedName = StripPostfix(property.Name, "Keyword");

                            string[] items;

                            if (trimmedName == "Variance")
                            {
                                propertyName = trimmedName;
                                items = new[] { "None", "In", "Out" };
                            }
                            else if (SplitNames(trimmedName).Contains("Or"))
                            {
                                if (trimmedName == "RefOrOut")
                                {
                                    propertyName = "Modifier";
                                    trimmedName = "ParameterModifier";
                                    items = new[] { "None", "Ref", "Out" };
                                }
                                else
                                {
                                    propertyName = "Kind";
                                    items = trimmedName.Split(new[] { "Or" }, StringSplitOptions.None);
                                }
                            }
                            else
                            {
                                continue;
                            }

                            propertyType = trimmedName;

                            if (!enums.Contains(propertyType))
                                enums.Add(new EnumDeclaration(propertyType, items.ToArray()));
                        }
                        else
                        {
                            propertyType = null;

                            switch (property.Name)
                            {
                                case "Guid":
                                case "File":
                                case "Line":
                                case "Bytes":
                                case "Identifier":
                                case "LocalName":
                                case "Name":
                                case "Prefix":
                                    propertyType = "string";
                                    break;

                                case "Commas":
                                    propertyType = "int?";
                                    break;
                            }

                            if (propertyType == null)
                                throw new InvalidOperationException();
                        }
                    }

                    if (
                        type.Name == "GotoStatementSyntax" &&
                        propertyType == "CaseOrDefault"
                    )
                        propertyType += "?";

                    if (
                        property.PropertyType.Name.StartsWith("SyntaxList`") ||
                        property.PropertyType.Name.StartsWith("SeparatedSyntaxList`")
                    )
                    {
                        if (propertyType.StartsWith("Separated"))
                            propertyType = propertyType.Substring("Separated".Length);

                        getChildrenGenerators.Add(new ListGetChildrenGenerator(propertyName));

                        builder.AppendLine("public {0} {1} {{ get; private set; }}", propertyType, propertyName);

                        initializeLists.Add(propertyName, propertyType);
                    }
                    else if (
                        typeof(SyntaxNode).IsAssignableFrom(property.PropertyType) &&
                        propertyType == property.PropertyType.Name
                    )
                    {
                        getChildrenGenerators.Add(new SimpleGetChildrenGenerator(propertyName));

                        string fieldName = MakeFieldName(propertyName);

                        builder.AppendLine("private {0} {1};", propertyType, fieldName);
                        builder.AppendLine("public {0} {1}", propertyType, propertyName);
                        builder.AppendLine("{");
                        builder.Indent();

                        builder.AppendLine("get {{ return {0}; }}", fieldName);
                        builder.AppendLine("set");
                        builder.AppendLine("{");
                        builder.Indent();

                        builder.AppendLine("if ({0} != null)", fieldName);
                        builder.Indent();
                        builder.AppendLine("RemoveChild({0});", fieldName);
                        builder.Unindent();
                        builder.AppendLine();
                        builder.AppendLine("{0} = value;", fieldName);
                        builder.AppendLine();

                        builder.AppendLine("if ({0} != null)", fieldName);
                        builder.Indent();
                        builder.AppendLine("AddChild({0});", fieldName);
                        builder.Unindent();

                        builder.Unindent();
                        builder.AppendLine("}");

                        builder.Unindent();
                        builder.AppendLine("}");
                    }
                    else
                    {
                        builder.AppendLine("public {0} {1} {{ get; set; }}", propertyType, propertyName);
                    }

                    foreach (var item in factories.Where(p => type.IsAssignableFrom(p.Key)))
                    {
                        FixupFactories(item.Value, property, propertyName, propertyType);
                    }

                    builder.AppendLine();
                }

                if (type.IsAbstract)
                {
                    builder.AppendLine("internal {0}(SyntaxKind syntaxKind)", type.Name);
                    builder.Indent();
                    builder.AppendLine(": base(syntaxKind)");
                    builder.Unindent();
                }
                else
                {
                    builder.AppendLine("public {0}()", type.Name);
                    builder.Indent();
                    builder.AppendLine(": base(SyntaxKind.{0})", StripPostfix(type.Name, "Syntax"));
                    builder.Unindent();
                }

                builder.AppendLine("{");
                builder.Indent();

                foreach (var item in initializeLists.OrderBy(p => p.Key))
                {
                    builder.AppendLine("{0} = new {1}(this);", item.Key, item.Value);
                }

                builder.Unindent();
                builder.AppendLine("}");

                if (getChildrenGenerators.Count > 0)
                {
                    builder.AppendLine();

                    builder.AppendLine("public override IEnumerable<SyntaxNode> ChildNodes()");
                    builder.AppendLine("{");
                    builder.Indent();

                    bool hadOneChild = false;

                    if (baseType != "SyntaxNode" && baseType != "SyntaxTriviaNode")
                    {
                        builder.AppendLine("foreach (var child in base.ChildNodes())");
                        builder.AppendLine("{");
                        builder.Indent();
                        builder.AppendLine("yield return child;");
                        builder.Unindent();
                        builder.AppendLine("}");

                        hadOneChild = true;
                    }

                    foreach (var generator in getChildrenGenerators)
                    {
                        if (hadOneChild)
                            builder.AppendLine();
                        else
                            hadOneChild = true;

                        generator.Build(builder);
                    }

                    builder.Unindent();
                    builder.AppendLine("}");
                }

                if (!type.IsAbstract)
                {
                    builder.AppendLine();

                    builder.AppendLine("[DebuggerStepThrough]");
                    builder.AppendLine("public override void Accept(ISyntaxVisitor visitor)");
                    builder.AppendLine("{");
                    builder.Indent();

                    builder.AppendLine("if (!visitor.Done)");
                    builder.Indent();
                    builder.AppendLine("visitor.Visit{0}(this);", StripPostfix(type.Name, "Syntax"));
                    builder.Unindent();

                    builder.Unindent();
                    builder.AppendLine("}");

                    builder.AppendLine();

                    builder.AppendLine("[DebuggerStepThrough]");
                    builder.AppendLine("public override T Accept<T>(ISyntaxVisitor<T> visitor)");
                    builder.AppendLine("{");
                    builder.Indent();

                    builder.AppendLine("return visitor.Visit{0}(this);", StripPostfix(type.Name, "Syntax"));

                    builder.Unindent();
                    builder.AppendLine("}");
                }

                builder.Unindent();
                builder.AppendLine("}");

                builder.Unindent();
                builder.AppendLine("}");

                writtenTypes.Add(type);

                WriteFile(target, type.Name, builder);
            }

            var syntaxKinds = new List<string>();

            syntaxKinds.Add("UserDefined");
            syntaxKinds.AddRange(nonAbstractTypes.OrderBy(p => p).Select(p => StripPostfix(p, "Syntax")));

            enums.Add(new EnumDeclaration("SyntaxKind", syntaxKinds.ToArray()));

            foreach (var enumType in enums.OrderBy(p => p.Name))
            {
                var builder = new CodeFragmentBuilder();

                builder.AppendLine("using System;");
                builder.AppendLine("using System.Collections.Generic;");
                builder.AppendLine("using System.Linq;");
                builder.AppendLine("using System.Text;");
                builder.AppendLine();
                builder.AppendLine("namespace CSharpSyntax");
                builder.AppendLine("{");
                builder.Indent();

                enumType.Build(builder);

                builder.Unindent();
                builder.AppendLine("}");

                WriteFile(target, enumType.Name, builder);
            }

            BuildVisitor(target, nonAbstractTypes);
            BuildBaseVisitor(target, nonAbstractTypes);
            BuildFactories(target, factories, writtenTypes);
        }
Ejemplo n.º 12
0
        private void WriteFile(string target, string fileName, CodeFragmentBuilder builder)
        {
            Directory.CreateDirectory(target);

            File.WriteAllText(
                Path.Combine(target, fileName + ".cs"),
                builder.GetFragment().ToString(0),
                new UTF8Encoding(false)
            );
        }
Ejemplo n.º 13
0
        private void BuildVisitor(string target, HashSet<string> visitors)
        {
            var builder = new CodeFragmentBuilder();

            builder.AppendLine("using System;");
            builder.AppendLine("using System.Collections.Generic;");
            builder.AppendLine("using System.Linq;");
            builder.AppendLine("using System.Text;");
            builder.AppendLine();
            builder.AppendLine("namespace CSharpSyntax");
            builder.AppendLine("{");
            builder.Indent();

            builder.AppendLine("public interface ISyntaxVisitor");
            builder.AppendLine("{");
            builder.Indent();
            builder.AppendLine("bool Done { get; }");

            foreach (string name in visitors.OrderBy(p => p))
            {
                builder.AppendLine();
                builder.AppendLine("void Visit{1}({0} node);", name, StripPostfix(name, "Syntax"));
            }

            builder.Unindent();
            builder.AppendLine("}");
            builder.AppendLine();

            builder.AppendLine("public interface ISyntaxVisitor<T>");
            builder.AppendLine("{");
            builder.Indent();

            bool hadOne = false;

            foreach (string name in visitors.OrderBy(p => p))
            {
                if (hadOne)
                    builder.AppendLine();
                else
                    hadOne = true;

                builder.AppendLine("T Visit{1}({0} node);", name, StripPostfix(name, "Syntax"));
            }

            builder.Unindent();
            builder.AppendLine("}");

            builder.Unindent();
            builder.AppendLine("}");

            WriteFile(target, "ISyntaxVisitor", builder);
        }