none
How to remove all comments in a .cs textfile with Roslyn?

    Question

  • How to remove all comments and all trailing whitespaces in a .cs textfile with Roslyn?

    Can anyone provide a sample?

    Thanks.


    • Modifié Enih vendredi 23 décembre 2011 08:27
    vendredi 23 décembre 2011 07:18

Réponses

  • [ExportCodeRefactoringProvider("RemoveComments", LanguageNames.CSharp)]
    class RemoveCommentsCodeRefactoringProvider : ICodeRefactoringProvider
    {
        ICodeActionEditFactory editFactory;
    
        [ImportingConstructor]
        public RemoveCommentsCodeRefactoringProvider(ICodeActionEditFactory editFactory)
        {
            this.editFactory = editFactory;
        }
    
        public CodeRefactoring GetRefactoring(IDocument document, TextSpan textSpan, CancellationToken cancellationToken)
        {
            return new CodeRefactoring(new ICodeAction[] { new RemoveCommentsCodeAction(editFactory, document) });
        }
    }
    
    class RemoveCommentsCodeAction : ICodeAction
    {
        ICodeActionEditFactory editFactory;
        IDocument document;
    
        public RemoveCommentsCodeAction(ICodeActionEditFactory editFactory, IDocument document)
        {
            this.editFactory = editFactory;
            this.document = document;
        }
    
        public string Description
        {
            get { return "Remove all comments"; }
        }
    
        public ICodeActionEdit GetEdit(CancellationToken cancellationToken)
        {
            var tree = (SyntaxTree)document.GetSyntaxTree(cancellationToken);
    
            var commentTrivia = from t in tree.Root.DescendentTrivia()
                                where t.Kind == SyntaxKind.SingleLineCommentTrivia ||
                                      t.Kind == SyntaxKind.MultiLineCommentTrivia
                                select t;
    
            var newRoot = tree.Root.ReplaceTrivia(commentTrivia, (t1, t2) => SyntaxTriviaList.Empty);
    
            return editFactory.CreateTreeTransformEdit(document.Project.Solution, tree, newRoot);
        }
    
        public ImageSource Icon
        {
            get { return null; }
        }
    }
    
    This is a code action I had written that should remove single and multiline comments in a selected piece of text. To remove trailing whitespace it is probably easier to directly manipulate the document as a string or array of lines than to remove whitespace trivia through Roslyn.
    vendredi 23 décembre 2011 22:01
  • Hi - The ICodeAction code posted by Chrysler above should work if you are trying this from within a Roslyn VS Extension. You can also write code that works outside VS (in a Roslyn Console Application for example) as shown below. The below examples use SyntaxRewriters and the .Format() extension method to remove comments and redundant trailing whitespaces.

    using System;
    using System.Linq;
    using Roslyn.Compilers.CSharp;
    using System.Collections.Generic;


    class Program
    {
        static void Main(string[] args)
        {
            var tree = SyntaxTree.ParseCompilationUnit(
    @"class Program   
    {   
    // SingleLineComment   
        public static void Main()            
        {   
    /*
       MultiLineComment
       MultiLineComment
       MultiLineComment
    */   
        }      
    }");

            // Solution 1 - Use a SyntaxRewriter to remove
            // redundant trailing whitespace and comments
            SyntaxRewriter rewriter = new Rewriter1();
            var newRoot = rewriter.Visit(tree.Root);
            Console.WriteLine(newRoot.GetFullText());

            // Solution 2 - Use a SyntaxRewriter to remove comments
            // and call .Format() extension method which will pretty-format
            // the source code and remove any redundant trailing whitesepace
            rewriter = new Rewriter2();
            newRoot = rewriter.Visit(tree.Root).Format();
            Console.WriteLine(newRoot.GetFullText());

            // Solution 3 - Use ReplaceTrivia() to remove comments as Chrysler pointed out above
            // and call .Format() extension method which will pretty-format
            // the source code and remove any redundant trailing whitesepace
            var commentTrivia = from t in tree.Root.DescendentTrivia()
                                where t.Kind == SyntaxKind.SingleLineCommentTrivia ||
                                      t.Kind == SyntaxKind.MultiLineCommentTrivia
                                select t;
            newRoot = tree.Root.ReplaceTrivia(commentTrivia, (t1, t2) => SyntaxTriviaList.Empty).Format();
            Console.WriteLine(newRoot.GetFullText());
        }

        class Rewriter1 : SyntaxRewriter
        {
            protected override SyntaxToken VisitToken(SyntaxToken token)
            {
                return token
                    .WithLeadingTrivia(RemoveCommentsAndRedundantTrailingWhitespace(token.LeadingTrivia))
                    .WithTrailingTrivia(RemoveCommentsAndRedundantTrailingWhitespace(token.TrailingTrivia));
            }

            private SyntaxTriviaList RemoveCommentsAndRedundantTrailingWhitespace(SyntaxTriviaList oldTriviaList)
            {
                var newTriviaList = new List<SyntaxTrivia>();
                for (var i = 0; i < oldTriviaList.Count; ++i)
                {
                    var isComment =
                        oldTriviaList[i].Kind == SyntaxKind.SingleLineCommentTrivia ||
                        oldTriviaList[i].Kind == SyntaxKind.MultiLineCommentTrivia;

                    var isRedundantWhitespace =
                        i + 1 < oldTriviaList.Count &&
                        oldTriviaList[i].Kind == SyntaxKind.WhitespaceTrivia &&
                        oldTriviaList[i + 1].Kind == SyntaxKind.EndOfLineTrivia;

                    if (!isComment && !isRedundantWhitespace)
                    {
                        newTriviaList.Add(oldTriviaList[i]);
                    }
                }
                return Syntax.TriviaList(newTriviaList);
            }
        }

        class Rewriter2 : SyntaxRewriter
        {
            protected override SyntaxTrivia VisitTrivia(SyntaxTrivia trivia)
            {
                var newTrivia = trivia;
                if (trivia.Kind == SyntaxKind.SingleLineCommentTrivia ||
                    trivia.Kind == SyntaxKind.MultiLineCommentTrivia)
                {
                    newTrivia = default(SyntaxTrivia);
                }
                return newTrivia;
            }
        }
    }

    Shyam Namboodiripad | Software Development Engineer in Test | Roslyn Compilers Team
    mardi 27 décembre 2011 22:19

Toutes les réponses

  • [ExportCodeRefactoringProvider("RemoveComments", LanguageNames.CSharp)]
    class RemoveCommentsCodeRefactoringProvider : ICodeRefactoringProvider
    {
        ICodeActionEditFactory editFactory;
    
        [ImportingConstructor]
        public RemoveCommentsCodeRefactoringProvider(ICodeActionEditFactory editFactory)
        {
            this.editFactory = editFactory;
        }
    
        public CodeRefactoring GetRefactoring(IDocument document, TextSpan textSpan, CancellationToken cancellationToken)
        {
            return new CodeRefactoring(new ICodeAction[] { new RemoveCommentsCodeAction(editFactory, document) });
        }
    }
    
    class RemoveCommentsCodeAction : ICodeAction
    {
        ICodeActionEditFactory editFactory;
        IDocument document;
    
        public RemoveCommentsCodeAction(ICodeActionEditFactory editFactory, IDocument document)
        {
            this.editFactory = editFactory;
            this.document = document;
        }
    
        public string Description
        {
            get { return "Remove all comments"; }
        }
    
        public ICodeActionEdit GetEdit(CancellationToken cancellationToken)
        {
            var tree = (SyntaxTree)document.GetSyntaxTree(cancellationToken);
    
            var commentTrivia = from t in tree.Root.DescendentTrivia()
                                where t.Kind == SyntaxKind.SingleLineCommentTrivia ||
                                      t.Kind == SyntaxKind.MultiLineCommentTrivia
                                select t;
    
            var newRoot = tree.Root.ReplaceTrivia(commentTrivia, (t1, t2) => SyntaxTriviaList.Empty);
    
            return editFactory.CreateTreeTransformEdit(document.Project.Solution, tree, newRoot);
        }
    
        public ImageSource Icon
        {
            get { return null; }
        }
    }
    
    This is a code action I had written that should remove single and multiline comments in a selected piece of text. To remove trailing whitespace it is probably easier to directly manipulate the document as a string or array of lines than to remove whitespace trivia through Roslyn.
    vendredi 23 décembre 2011 22:01
  • Hi - The ICodeAction code posted by Chrysler above should work if you are trying this from within a Roslyn VS Extension. You can also write code that works outside VS (in a Roslyn Console Application for example) as shown below. The below examples use SyntaxRewriters and the .Format() extension method to remove comments and redundant trailing whitespaces.

    using System;
    using System.Linq;
    using Roslyn.Compilers.CSharp;
    using System.Collections.Generic;


    class Program
    {
        static void Main(string[] args)
        {
            var tree = SyntaxTree.ParseCompilationUnit(
    @"class Program   
    {   
    // SingleLineComment   
        public static void Main()            
        {   
    /*
       MultiLineComment
       MultiLineComment
       MultiLineComment
    */   
        }      
    }");

            // Solution 1 - Use a SyntaxRewriter to remove
            // redundant trailing whitespace and comments
            SyntaxRewriter rewriter = new Rewriter1();
            var newRoot = rewriter.Visit(tree.Root);
            Console.WriteLine(newRoot.GetFullText());

            // Solution 2 - Use a SyntaxRewriter to remove comments
            // and call .Format() extension method which will pretty-format
            // the source code and remove any redundant trailing whitesepace
            rewriter = new Rewriter2();
            newRoot = rewriter.Visit(tree.Root).Format();
            Console.WriteLine(newRoot.GetFullText());

            // Solution 3 - Use ReplaceTrivia() to remove comments as Chrysler pointed out above
            // and call .Format() extension method which will pretty-format
            // the source code and remove any redundant trailing whitesepace
            var commentTrivia = from t in tree.Root.DescendentTrivia()
                                where t.Kind == SyntaxKind.SingleLineCommentTrivia ||
                                      t.Kind == SyntaxKind.MultiLineCommentTrivia
                                select t;
            newRoot = tree.Root.ReplaceTrivia(commentTrivia, (t1, t2) => SyntaxTriviaList.Empty).Format();
            Console.WriteLine(newRoot.GetFullText());
        }

        class Rewriter1 : SyntaxRewriter
        {
            protected override SyntaxToken VisitToken(SyntaxToken token)
            {
                return token
                    .WithLeadingTrivia(RemoveCommentsAndRedundantTrailingWhitespace(token.LeadingTrivia))
                    .WithTrailingTrivia(RemoveCommentsAndRedundantTrailingWhitespace(token.TrailingTrivia));
            }

            private SyntaxTriviaList RemoveCommentsAndRedundantTrailingWhitespace(SyntaxTriviaList oldTriviaList)
            {
                var newTriviaList = new List<SyntaxTrivia>();
                for (var i = 0; i < oldTriviaList.Count; ++i)
                {
                    var isComment =
                        oldTriviaList[i].Kind == SyntaxKind.SingleLineCommentTrivia ||
                        oldTriviaList[i].Kind == SyntaxKind.MultiLineCommentTrivia;

                    var isRedundantWhitespace =
                        i + 1 < oldTriviaList.Count &&
                        oldTriviaList[i].Kind == SyntaxKind.WhitespaceTrivia &&
                        oldTriviaList[i + 1].Kind == SyntaxKind.EndOfLineTrivia;

                    if (!isComment && !isRedundantWhitespace)
                    {
                        newTriviaList.Add(oldTriviaList[i]);
                    }
                }
                return Syntax.TriviaList(newTriviaList);
            }
        }

        class Rewriter2 : SyntaxRewriter
        {
            protected override SyntaxTrivia VisitTrivia(SyntaxTrivia trivia)
            {
                var newTrivia = trivia;
                if (trivia.Kind == SyntaxKind.SingleLineCommentTrivia ||
                    trivia.Kind == SyntaxKind.MultiLineCommentTrivia)
                {
                    newTrivia = default(SyntaxTrivia);
                }
                return newTrivia;
            }
        }
    }

    Shyam Namboodiripad | Software Development Engineer in Test | Roslyn Compilers Team
    mardi 27 décembre 2011 22:19