December 22, 2014
Hot Topics:

Prime Programming Proficiency, Part 3: Lines-of-code Counter

  • August 12, 2004
  • By Paul Kimmel
  • Send Email »
  • More Articles »

Listing 6 is the SolutionElement. It implements IHost and is initialized with a Projects collection when the constructor—Sub New—is called. The Accept method implements IHost and accepts a visitor. The Iterate method does the interesting work. Iterate clears the Output device (see the Implementing the Output Window section later in this article), writes the name of the current solution, and then iterates over each Project in the Projects collection.

Notice that I create only one instance of ProjectElement and reuse it inside the For Each loop. Because it is a wrapper and its state is transient, this conservative code will reduce memory chunking. Within the loop, the ProjectElement is told which ProjectItem it currently represents and then the ProjectElement is visited.

Listing 6: The ProjectElement.

Imports EnvDTE
Imports System
Imports System.Diagnostics

Public Class ProjectElement
   Implements IHost

   Private FProject As Project
   Private FVisitor As IVisitor

   Public Sub New()

   End Sub

   Public Sub New(ByVal Project As Project)
      FProject = Project
   End Sub

   Public Sub Accept(ByVal visitor As IVisitor) _
          Implements IHost.Accept
      FVisitor = visitor
      visitor.Visit(Me)
   End Sub

   Public Property CurrentProject() As Project
      Get
         Return FProject
      End Get
      Set(ByVal Value As Project)
         FProject = Value
      End Set
   End Property

   Public Sub Iterate()
      Debug.Assert(FProject Is Nothing = False)

      Try
         Output.WriteLine("Project: " & FProject.Name)
      Catch
         Output.WriteLine("Project: <no name>")
      End Try

      If (FProject.ProjectItems Is Nothing) Then Return
      FVisitor.ProjectCount += 1

      Dim item As ProjectItem
      Dim itemElement As ItemElement = New ItemElement

      For Each item In FProject.ProjectItems
         itemElement.CurrentItem = item
         itemElement.Accept(FVisitor)
      Next
   End Sub
End Class

The ProjectElement represents an extensibility object model Project. Again, we implement IHost and call Accept to visit our host. The ProjectElement host also implements Iterate. At this level of granularity, we have more work to do. We output the project name, increment the visitor's ProjectCount, and then examine each ProjectItem using the ItemElement wrapper.

Listing 7: The ItemElement.

Imports EnvDTE
Imports System
Imports System.Diagnostics

Public Class ItemElement
   Implements IHost

   Private FProjectItem As ProjectItem
   Private FVisitor As IVisitor

   Public Sub New()

   End Sub

   Public Sub New(ByVal item As ProjectItem)
      FProjectItem = item
   End Sub

   Public Property CurrentItem() As ProjectItem
      Get
         Return FProjectItem
      End Get
      Set(ByVal Value As ProjectItem)
         FProjectItem = Value
      End Set
   End Property

   Public Sub Accept(ByVal visitor As IVisitor) _
          Implements IHost.Accept
      FVisitor = visitor
      visitor.Visit(Me)
   End Sub

   Public Sub Iterate(Optional ByVal Indent As String = "  ")
      Iterate(FProjectItem, Indent)
   End Sub

   Private Sub Iterate(ByVal item As ProjectItem, _
      Optional ByVal Indent As String = "  ")
         Try
            Output.Write(Indent & "Name: " & item.Name)
            UpdateLineCount(item)
            FVisitor.ItemCount += 1

            If (FProjectItem.ProjectItems Is Nothing = False _
               Or FProjectItem.ProjectItems.Count > 0) Then

               Dim child As ProjectItem

               For Each child In item.ProjectItems
                  Iterate(child, New String(" ", Indent.Length + 2))
               Next
            End If
         Catch e As Exception
            Debug.WriteLine(e.Message)
         End Try
   End Sub

   Private Function GetLineCount(ByVal item As ProjectItem)
      ' "{6BB5F8EE-4483-11D3-8BCF-00C04F8EC28C}"
      If (item.Kind = EnvDTE.Constants.vsProjectItemKindPhysicalFile) _
         Then
         Return LineCounter.GetLineCount(item)
      Else
         Return 0
      End If
   End Function

   Private Sub UpdateLineCount(ByVal item As ProjectItem)
      Try
         Dim count As Long = GetLineCount(item)
         Output.WriteLine(String.Format("({0})", count))
         FVisitor.LineCount += count
      Catch
         Output.WriteLine("(0)")
      End Try
   End Sub
End Class

ItemElement performs the most work. Again, it is a host with an Accept method and we want to iterate the ItemElement. Keep in mind that projects may have folders (sub-projects), so we have to look out for nested project items.

Iterate writes the ProjectItem name and updates the line count to include the ProjectItem contained in the ItemElement wrapper. Next, we update the visitor's ItemCount. After we have performed the information-gathering steps, we need to see whether this element has sub-elements. If the ProjectItem has sub-projects, we use recursion to examine those elements.

Two more methods are important to note: GetLineCount and UpdateLineCount. UpdateLineCount calls GetLineCount to get the actual number of lines, output that result, and add the count to the visitor's tally. GetLineCount uses the LineCounter class I implemented, which I cover in the next section.





Page 4 of 6



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

Sitemap | Contact Us

Rocket Fuel