Introduction

In part 1 of trying to move the classes to their own files, I made sure I got the classes I needed. Now I’m going to Write out those classes and remove them from where they were before.

Writing the classes to their own file

The easy bit is writing out class3 and partial class 1 to their own files.

Option Strict Off

Imports System.IO

Module Module1

    Sub Main()
        Const foldername As String = "F:MyDocumentsVisual Studio 2010ProjectsConsoleApplication5"
        Dim sourcetext As String
        Using streamReader = New StreamReader(Path.Combine(foldername, "Class1.vb"))
            sourcetext = streamReader.ReadToEnd
        End Using

        Dim tree = SyntaxTree.ParseCompilationUnit(sourcetext)

        Dim root As CompilationUnitSyntax = tree.Root

        Dim classes =
                From e In root.DescendentNodes.OfType(Of ClassStatementSyntax)()
                Where (From f In e.Modifiers Select f.Kind.GetText).Contains("Public")
                Select e

        For Each classstatement In classes
            Console.WriteLine("Class: " & classstatement.Identifier.GetText)
            Dim tree2 = SyntaxTree.ParseCompilationUnit(classstatement.GetFullText)
            Dim filename = Path.Combine(foldername, classstatement.Identifier.GetText & ".vb")
            For Each modifier1 In classstatement.Modifiers
                Console.WriteLine(modifier1.Kind)
                Console.WriteLine(modifier1.Kind.GetText)
                If modifier1.Kind.GetText = "Partial" Then
                    filename = Path.Combine(foldername, classstatement.Identifier.GetText & "_partial.vb")
                End If
            Next
            File.WriteAllText(filename, classstatement.Parent.GetText)
        Next


        Console.ReadLine()
    End Sub

End Module

With this as the result.

I just create a new syntaxtree Dim tree2 = SyntaxTree.ParseCompilationUnit(classstatement.GetFullText) and then add a File.WriteAllText(filename, classstatement.Parent.GetText) and I’m done. Of course this is the easy option since I don’t have to deal with namespaces or imports or options.

Adding the namespace

So let’s say all these classes belong to the same namespace, how would I make sure my resulting syntaxes also all have the same namespace.

Namespace Test
    Public Class Class1
        Public Property string1 As String
        Public Property string2 As String

        Private Class Class2
            Public Property string3 As String
            Public Property string4 As String
        End Class
    End Class

    Public Class Class3
        Public Property string5 As String
        Public Property string6 As String
    End Class

    Partial Public Class Class1
        Public Property string7 As String
        Public Property string8 As String
    End Class
End Namespace

You cannot just add something to a syntaxtree since syntaxtrees are imutable.

So we will have to make sure we get the namespace out of our original syntaxtree and then just add that to our sourcetext.

Something like this.

Option Strict Off

Imports System.IO

Module Module1

    Sub Main()
        Const foldername As String = "F:MyDocumentsVisual Studio 2010ProjectsConsoleApplication5"
        Dim sourcetext As String
        Using streamReader = New StreamReader(Path.Combine(foldername, "Class1.vb"))
            sourcetext = streamReader.ReadToEnd
        End Using

        Dim tree = SyntaxTree.ParseCompilationUnit(sourcetext)

        Dim root As CompilationUnitSyntax = tree.Root

        Dim classes =
                From e In root.DescendentNodes.OfType(Of ClassStatementSyntax)()
                Where (From f In e.Modifiers Select f.Kind.GetText).Contains("Public")
                Select e
        Dim _namespace = From e In root.DescendentNodes.OfType(Of NamespaceStatementSyntax)() Select e

        For Each classstatement In classes
            Console.WriteLine("Class: " & classstatement.Identifier.GetText)
            Dim classandnamespace = _namespace(0).GetText & Environment.NewLine & classstatement.Parent.GetText & Environment.NewLine & "End NameSpace"

            Dim tree2 = SyntaxTree.ParseCompilationUnit(classandnamespace)

            Dim filename = Path.Combine(foldername, classstatement.Identifier.GetText & ".vb")
            For Each modifier1 In classstatement.Modifiers
                Console.WriteLine(modifier1.Kind)
                Console.WriteLine(modifier1.Kind.GetText)
                If modifier1.Kind.GetText = "Partial" Then
                    filename = Path.Combine(foldername, classstatement.Identifier.GetText & "_partial.vb")
                End If
            Next
            File.WriteAllText(filename, classandnamespace)
        Next


        Console.ReadLine()
    End Sub

End Module

This is now our result.

Conclusion

You can do a lot of cool stuff with Roslyn and I’m only scratching the surface here. And I bet there are lots of different ways to do the above.