Search code examples
c#code-generationicsharpcode

How to generate C# code from ICompilationUnit (ICSharpCode)


I'm trying to update an existing C# code. The code is parsed using ICSharpCode.NRefactory.IParser. My system is using widely ICompilationUnit to explore existing code.

Now, I want to add a method to an existing file and save it back to disk as C# code. So far I have:

CompilationUnit compilationUnit = GetCompilationUnit();
var visitor = new NRefactoryASTConvertVisitor(new ParseProjectContent());
compilationUnit.AcceptVisitor(visitor, null);
IMethod method = //GetMethod from otherplace
visitor.Cu.Classes[0].Methods.Add(method);
// How the updated visitor.Cu be transformed to C# code

What I'd like to do is to generate C# code from visitor.Cu. Is there a way to generate C# code from ICompilationUnit?


Solution

  • You're adding the method as an IMethod - an IMethod just represents a method as a DOM entity along with some information about its signature (without any code) - so I don't see how you would be able to generate C# code from it...

    (unless you mean generating code just for the method's signature? in which case you should look into the class ICSharpCode.SharpDevelop.Dom.Refactoring.CodeGenerator for the DOM->AST conversion, specifically the ConvertMember(IMethod m, ClassFinder targetContext) method).

    Your CompilationUnit, however, is the Abstract Syntax Tree of the code file, and can easily be converted back to C#/VB.NET code using the CSharpOutputVisitor and VBNetOutputVisitor classes.

    You could add a MethodDeclaration that represents your method's code to a TypeDefinition which represents some class in the original file, and then use the aforementioned output visitors to generate the code with your new method inserted.

    For your convinience I'm attaching a PrettyPrint extension method that is useful when working on converting INodes to code:

        public static string PrettyPrint(this INode code, LanguageProperties language)
        {
            if (code == null) return string.Empty;
            IOutputAstVisitor csOutVisitor = CreateCodePrinter(language);
            code.AcceptVisitor(csOutVisitor, null);
            return csOutVisitor.Text;
        }
    
        private static IOutputAstVisitor CreateCodePrinter(LanguageProperties language)
        {
            if (language == LanguageProperties.CSharp) return new CSharpOutputVisitor();
            if (language == LanguageProperties.VBNet) return new VBNetOutputVisitor();
            throw new NotSupportedException();
        }
    
        public static string ToCSharpCode(this INode code)
        {
            return code.PrettyPrint(LanguageProperties.CSharp);
        }