Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Replacing the body of a method removes the following line break

Tags:

c#

roslyn

I'm using the following code to replace the body of methods by Roslyn;

/* method is instance of MethodDeclarationSyntax */
BlockSyntax newBody = SyntaxFactory.Block(SyntaxFactory.ParseStatement("throw new NotImplementedException();"));
BlockSyntax body = method.Body;
var modifiedMethod = method.ReplaceNode(body, newBody);

But when I do this, line breaks after the methods are removed and if there is a #region or #endregion tag after the method an error will occur.

For example

    #region
    static void RemoveRegions(string str)
    {
        return;
    }
    #endregion

And after replacing the body

    #region
    static void RemoveRegions(string str)
    {
        throw new NotImplementedException();
    }        #endregion    // This cause to compiling error
like image 242
Ali Sepehri.Kh Avatar asked Sep 09 '14 05:09

Ali Sepehri.Kh


People also ask

How do you remove a line break in a string?

Remove All Line Breaks from a String We can remove all line breaks by using a regex to match all the line breaks by writing: str = str. replace(/(\r\n|\n|\r)/gm, ""); \r\n is the CRLF line break used by Windows.


1 Answers

The original BlockSyntax body contained some "Trailing Trivia" in the form of whitespace (a newline) after the close curly brace. Your constructed BlockSyntax newBody will contain a close curly brace as well, but that curly brace doesn't know whether or not it should have any whitespace after it.

You could do one of three things. I think #1 is the best option but I'm listing the others for completeness:

  1. Reuse the trailing trivia from the original node. You can make use of the trailing trivia from the original node by using GetTrailingTrivia and WithTrailingTrivia:

    var originalTrailingTrivia = body.GetTrailingTrivia();
    newBody = newBody.WithTrailingTrivia(originalTrailingTrivia);
    

    In my opinion, this is your best bet. It will preserve the layout of the code by keeping around any trailing trivia (whether it be one blank line, five blank lines, zero blank lines and two spaces, one space and a comment, etc.) and will be more generally suited to other scenarios you haven't dreamed up yet.

  2. Format the new node. Let the built-in Formatter decide how to handle the whitespace by using WithAdditionalAnnotations to add the Formatter.Annotation and perform a Formatter.FormatAsync on the tree containing the newBody:

    newBody = newBody.WithAdditionalAnnotation(Formatter.Annotation)
    // Code that replaces this node back into the document
    var formattedDocument = Formatter.Format(document, Formatter.Annotation);
    

    Note that this will also format the contents of the method. You could format only the close curly brace and tokens around it by adding the Formatter.Annotation directly to the close curly brace itself instead of the entire BlockSyntax and following the same steps. This approach may lay things out in a reasonable way, but it will remove any comments or intentionally strange whitespace attached to the close curly brace.

  3. Add a trailing newline manually. Create a newline manually and add it to newBody with WithTrailingTrivia:

    newBody = newBody.WithTrailingTrivia(SyntaxFactory.CarriageReturnLineFeed);
    

    This will also remove any comments or intentionally strange whitespace attached to the close curly brace. It also ignores all context and will not honor any user-specified formatting settings that might change the desired layout of method blocks.

like image 178
David Poeschl Avatar answered Sep 30 '22 05:09

David Poeschl