Created
July 10, 2018 23:36
-
-
Save terrajobst/b5403d74b0511149a70d6b98eec53216 to your computer and use it in GitHub Desktop.
Split files by namespace
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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