Created
January 28, 2014 18:20
-
-
Save bricelam/8673172 to your computer and use it in GitHub Desktop.
Roslyn syntax rewriter to remove internal doc comments
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
namespace RemoveInternalDocComments | |
{ | |
using System; | |
using System.IO; | |
using System.Linq; | |
using Roslyn.Compilers.CSharp; | |
class Program | |
{ | |
static void Main() | |
{ | |
var path = @"C:\Path\to\src"; | |
foreach (var file in Directory.EnumerateFiles(path, "*.cs", SearchOption.AllDirectories)) | |
{ | |
// TODO: Exclude all auto-generated files | |
if (file.EndsWith(".designer.cs", StringComparison.OrdinalIgnoreCase)) | |
{ | |
continue; | |
} | |
var rewriter = new Rewriter(); | |
var newRoot = rewriter.Visit(SyntaxTree.ParseFile(file).GetRoot()); | |
if (rewriter.ReplacedAnything) | |
{ | |
// TODO: Use original encoding | |
File.WriteAllText(file, newRoot.ToFullString()); | |
Console.Write("X"); | |
} | |
else | |
{ | |
Console.Write("."); | |
} | |
} | |
Console.WriteLine(); | |
Console.WriteLine(); | |
Console.Write("Press any key to continue . . . "); | |
Console.ReadKey(true); | |
} | |
class Rewriter : SyntaxRewriter | |
{ | |
public bool ReplacedAnything { get; set; } | |
public override SyntaxTrivia VisitTrivia(SyntaxTrivia trivia) | |
{ | |
if (trivia.Kind == SyntaxKind.DocumentationCommentTrivia | |
&& !IsPublic(trivia.Token.Parent)) | |
{ | |
ReplacedAnything = true; | |
return Syntax.Comment(trivia.ToFullString().Replace("///", "//")); | |
} | |
return base.VisitTrivia(trivia); | |
} | |
private bool IsPublic(SyntaxNode node) | |
{ | |
if (node is MemberDeclarationSyntax) | |
{ | |
if (node.Parent is BaseTypeDeclarationSyntax && !IsPublic(node.Parent)) | |
{ | |
return false; | |
} | |
if (node.Parent is InterfaceDeclarationSyntax || node.Parent is EnumDeclarationSyntax) | |
{ | |
return true; | |
} | |
var baseTypeDeclaration = node as BaseTypeDeclarationSyntax; | |
var baseFieldDeclaration = node as BaseFieldDeclarationSyntax; | |
var delegateDeclaration = node as DelegateDeclarationSyntax; | |
var baseMethodDeclaration = node as BaseMethodDeclarationSyntax; | |
var basePropertyDeclaration = node as BasePropertyDeclarationSyntax; | |
if (baseTypeDeclaration != null) | |
{ | |
if (!IsPublic(baseTypeDeclaration.Modifiers)) | |
{ | |
return false; | |
} | |
} | |
else if (baseFieldDeclaration != null) | |
{ | |
if (!IsPublic(baseFieldDeclaration.Modifiers)) | |
{ | |
return false; | |
} | |
} | |
else if (delegateDeclaration != null) | |
{ | |
if (!IsPublic(delegateDeclaration.Modifiers)) | |
{ | |
return false; | |
} | |
} | |
else if (baseMethodDeclaration != null) | |
{ | |
if (baseMethodDeclaration is DestructorDeclarationSyntax) | |
{ | |
return true; | |
} | |
var methodDeclaration = baseMethodDeclaration as MethodDeclarationSyntax; | |
if (methodDeclaration != null && methodDeclaration.ExplicitInterfaceSpecifier != null) | |
{ | |
// TODO: Only if interface is public | |
return true; | |
} | |
if (!IsPublic(baseMethodDeclaration.Modifiers)) | |
{ | |
return false; | |
} | |
} | |
else if (basePropertyDeclaration != null) | |
{ | |
var propertyDeclaration = basePropertyDeclaration as PropertyDeclarationSyntax; | |
if (propertyDeclaration != null && propertyDeclaration.ExplicitInterfaceSpecifier != null) | |
{ | |
// TODO: Only if interface is public | |
return true; | |
} | |
if (!IsPublic(basePropertyDeclaration.Modifiers)) | |
{ | |
return false; | |
} | |
} | |
else | |
{ | |
throw new Exception("Unexpected node."); | |
} | |
} | |
else if (node is AttributeListSyntax || node is TypeSyntax) | |
{ | |
return IsPublic(node.Parent); | |
} | |
else if (node is ExpressionSyntax || node is StatementSyntax || node is VariableDeclarationSyntax) | |
{ | |
return false; | |
} | |
else | |
{ | |
throw new Exception("Unexpected node."); | |
} | |
return true; | |
} | |
private static bool IsPublic(SyntaxTokenList modifiers) | |
{ | |
return modifiers.Any(m => m.Kind == SyntaxKind.PublicKeyword || m.Kind == SyntaxKind.ProtectedKeyword); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment