|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable disable
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace CSharpSyntaxGenerator
{
internal class SignatureWriter
{
private readonly TextWriter _writer;
private readonly Tree _tree;
private readonly Dictionary<string, string> _typeMap;
private SignatureWriter(TextWriter writer, Tree tree)
{
_writer = writer;
_tree = tree;
_typeMap = tree.Types.ToDictionary(n => n.Name, n => n.Base);
_typeMap.Add(tree.Root, null);
}
public static void Write(TextWriter writer, Tree tree)
{
new SignatureWriter(writer, tree).WriteFile();
}
private void WriteFile()
{
_writer.WriteLine("using System;");
_writer.WriteLine("using System.Collections;");
_writer.WriteLine("using System.Collections.Generic;");
_writer.WriteLine("using System.Linq;");
_writer.WriteLine("using System.Threading;");
_writer.WriteLine();
_writer.WriteLine("namespace Microsoft.CodeAnalysis.CSharp");
_writer.WriteLine("{");
this.WriteTypes();
_writer.WriteLine("}");
}
private void WriteTypes()
{
var nodes = _tree.Types.Where(n => n is not PredefinedNode).ToList();
for (int i = 0, n = nodes.Count; i < n; i++)
{
var node = nodes[i];
_writer.WriteLine();
this.WriteType(node);
}
}
private void WriteType(TreeType node)
{
if (node is AbstractNode)
{
AbstractNode nd = (AbstractNode)node;
_writer.WriteLine(" public abstract partial class {0} : {1}", node.Name, node.Base);
_writer.WriteLine(" {");
for (int i = 0, n = nd.Fields.Count; i < n; i++)
{
var field = nd.Fields[i];
if (IsNodeOrNodeList(field.Type))
{
_writer.WriteLine(" public abstract {0}{1} {2} {{ get; }}", "", field.Type, field.Name);
}
}
_writer.WriteLine(" }");
}
else if (node is Node)
{
Node nd = (Node)node;
_writer.WriteLine(" public partial class {0} : {1}", node.Name, node.Base);
_writer.WriteLine(" {");
WriteKinds(nd.Kinds);
var valueFields = nd.Fields.Where(n => !IsNodeOrNodeList(n.Type)).ToList();
var nodeFields = nd.Fields.Where(n => IsNodeOrNodeList(n.Type)).ToList();
for (int i = 0, n = nodeFields.Count; i < n; i++)
{
var field = nodeFields[i];
_writer.WriteLine(" public {0}{1}{2} {3} {{ get; }}", "", "", field.Type, field.Name);
}
for (int i = 0, n = valueFields.Count; i < n; i++)
{
var field = valueFields[i];
_writer.WriteLine(" public {0}{1}{2} {3} {{ get; }}", "", "", field.Type, field.Name);
}
_writer.WriteLine(" }");
}
}
private void WriteKinds(List<Kind> kinds)
{
if (kinds.Count > 1)
{
foreach (var kind in kinds)
{
_writer.WriteLine(" // {0}", kind.Name);
}
}
}
private bool IsSeparatedNodeList(string typeName)
{
return typeName.StartsWith("SeparatedSyntaxList<", StringComparison.Ordinal);
}
private bool IsNodeList(string typeName)
{
return typeName.StartsWith("SyntaxList<", StringComparison.Ordinal);
}
public bool IsNodeOrNodeList(string typeName)
{
return IsNode(typeName) || IsNodeList(typeName) || IsSeparatedNodeList(typeName);
}
private bool IsNode(string typeName)
{
return _typeMap.ContainsKey(typeName);
}
}
}
|