Welcome to MSDN Blogs Sign in | Join | Help

Code Model & its Interop with Text Editor Object Model

The Visual Studio Code Model can be used to read and edit the structure of the code in a file. The model gives you the ability to interact with files from different langauges in a common way without parsing the code. With this model, an automation client (e.g. add-in/macro) would start from a solution or project to get to a project item, and from the project item to get to the code model. Specifically, from a ProjectItem, you get to a FileCodeModel object that gets you to a CodeElements collection. At the FileCodeModel level, it contains a CodeElement object for each top-level code element in the file (e.g.  Implements statement, WithEvents declaration, etc).  At the class level, the CodeElements collection contains a CodeElement for each member of the class (e.g. a code function). You can QI (or cast in C# and VB) to get to more powerful language-specific interfaces.
A key functionality of code model is the ability to interop with the Text Editor OM. In other words, an automation client can go from the editor's automation model to a code model object and from a code model object to the start and end point of the code as text in the editor (for example, you have a Method object in hand, get its StartPoint, and inject a few lines of code, or you handle the LineChanged event, get the EditPoint in the event, and map it to a Method code object).
Following are some macro samples that demonstrate how to walk through the code model hierarchy of a solution and how to inteop with Text Editor Object Model.

    Sub walkThroughFileCodeModel()
        Dim projectItems As ProjectItems
        Dim projectItem As ProjectItem
        Dim fileCodeModel As FileCodeModel
        Dim codeElements As CodeElements
        Dim sRes As String = ""
        Dim level As Integer

        For Each proj As Project In DTE.Solution
            projectItems = proj.ProjectItems
            For Each projectItem In projectItems
                'Debug.WriteLine(projectItem.Name)
                fileCodeModel = projectItem.FileCodeModel
                level = -1
                If Not fileCodeModel Is Nothing Then
                    codeElements = fileCodeModel.CodeElements
                    codeElementChildren(codeElements, sRes, level)
                End If
                sRes += vbNewLine
            Next
        Next
        MsgBox(sRes)
    End Sub

    Sub codeElementChildren(ByVal codeElements As CodeElements, ByRef sRes As String, ByVal level As Integer)
        Dim i As Integer
        level += 1
        For Each clt As CodeElement In codeElements
            For i = 1 To level
                sRes += vbTab
            Next
            Try
                sRes += String.Format("{0}, Kind = {1}  Line:{2} ~ {3} ", clt.Name, clt.Kind, clt.StartPoint.Line, clt.EndPoint.Line)
            Catch ex As System.Exception
                If TypeOf clt Is EnvDTE80.CodeImport Then
                    Dim ci As EnvDTE80.CodeImport = CType(clt, EnvDTE80.CodeImport)
                    sRes += String.Format("{0}, Kind = {1}  Line:{2} ~ {3} ", ci.Namespace, clt.Kind, clt.StartPoint.Line, clt.EndPoint.Line)
                Else
                    sRes += String.Format("     , Kind = {0}  Line:{1} ~ {2} ", clt.Kind, clt.StartPoint.Line, clt.EndPoint.Line)
                End If
            End Try
            sRes += vbNewLine
            Try
                If Not clt.Children Is Nothing Then
                    codeElementChildren(clt.Children, sRes, level)
                End If
            Catch ex As System.Exception
                Debug.WriteLine(ex.Message)
            End Try
        Next
    End Sub

    Sub fromCodelModel2TextEditor()
        Dim fcm As FileCodeModel = DTE.ActiveDocument.ProjectItem.FileCodeModel
        Dim cns As CodeNamespace = fcm.CodeElements.Item("ClassLibraryCS")
        Dim cc As CodeClass = cns.Children.Item("Class1")
        Dim tp As TextPoint = cc.GetEndPoint 'cc.GetStartPoint
        Dim ep As EditPoint = tp.CreateEditPoint
        ep.Insert("blah")
    End Sub

    Sub fromTextEditor2CodeModel()
        Dim td As TextDocument = DTE.ActiveDocument.Object
        Dim cc As CodeClass = td.Selection.ActivePoint.CodeElement(vsCMElement.vsCMElementClass)
        Debug.WriteLine(cc.Name)
    End Sub

Published Monday, October 03, 2005 6:07 PM by hlong

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

# re: Code Model & its Interop with Text Editor Object Model

Hiya,

Any tips to find out what the current project type is (console app, Service, etc).
ProjectItem Properties doesn't appear to give anything useful.
Tuesday, February 14, 2006 4:25 AM by David Ashwood

# re: Code Model & its Interop with Text Editor Object Model

Great article.  This has saved me a ton of experimentation time.

Thursday, May 24, 2007 12:13 PM by AMG

# tribal tattoo » Code Model & its Interop with Text Editor Object Model

Leave a Comment

(required) 
required 
(required) 

  
Enter Code Here: Required
 
Page view tracker