Skip to content

Instantly share code, notes, and snippets.

@terrajobst
Created July 10, 2018 23:36
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save terrajobst/b5403d74b0511149a70d6b98eec53216 to your computer and use it in GitHub Desktop.
Save terrajobst/b5403d74b0511149a70d6b98eec53216 to your computer and use it in GitHub Desktop.
Split files by namespace
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Text;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace NetStandardCleanup
{
class Program
{
static void Main(string[] args)
{
var inputDirectory = @"P:\oss\standard\netstandard\ref";
var outputDirectory = @"P:\oss\standard\netstandard\ref2";
var copyrightHeaders = Path.Combine(inputDirectory, "license-header.txt");
var copyrightLines = File.ReadAllLines(copyrightHeaders);
Directory.CreateDirectory(outputDirectory);
var files = Directory.GetFiles(inputDirectory, "*.cs");
var syntaxTrees = ParseFiles(files);
var compilation = CSharpCompilation.Create("dymmy", syntaxTrees);
var types = new Dictionary<string, List<ITypeSymbol>>();
foreach (var m in compilation.Assembly.GlobalNamespace.GetMembers())
ProcessTypeOrNamespace(types, m);
foreach (var kv in types)
{
var ns = kv.Key;
var fileName = Path.Combine(outputDirectory, ns) + ".cs";
var declaringNodes = kv.Value.OrderBy(t => t.Name).ThenBy(t => t is INamedTypeSymbol nt ? nt.TypeParameters.Length : 0)
.SelectMany(t => t.DeclaringSyntaxReferences)
.Select(sr => sr.GetSyntax())
.Cast<MemberDeclarationSyntax>()
.ToArray();
var declaringTrees = declaringNodes.Select(s => s.SyntaxTree).Distinct().ToArray();
using (var writer = new StreamWriter(fileName))
{
foreach (var line in copyrightLines)
writer.WriteLine(line);
writer.WriteLine($"namespace {ns}");
writer.WriteLine("{");
foreach (var n in declaringNodes)
{
var sourceText = n.SyntaxTree.GetText();
var span = n.FullSpan;
var start = span.Start;
var end = span.End;
var lineSpan = TextSpan.FromBounds(start, end);
var text = sourceText.ToString(lineSpan);
writer.Write(text);
}
writer.WriteLine("}");
}
}
}
static void ProcessTypeOrNamespace(Dictionary<string, List<ITypeSymbol>> types, INamespaceOrTypeSymbol m)
{
if (m.IsType)
{
var type = (ITypeSymbol)m;
var nsName = m.ContainingNamespace.ToDisplayString();
if (!types.TryGetValue(nsName, out var typeList))
{
typeList = new List<ITypeSymbol>();
types.Add(nsName, typeList);
}
typeList.Add(type);
}
else
{
foreach (var n in m.GetMembers().OfType<INamespaceOrTypeSymbol>())
ProcessTypeOrNamespace(types, n);
}
}
static IEnumerable<SyntaxTree> ParseFiles(IEnumerable<string> paths)
{
foreach (var fileName in paths)
{
var content = File.ReadAllText(fileName);
yield return CSharpSyntaxTree.ParseText(content, path: fileName);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment