I guess people put todo’s in their code for different reasons, it can be lazyness (I’ll write this hard/boring piece of code later), unclear requirements or maybe a debate is needed before a certain choice can be made.

Be that as it may, some todo’s need to be solved more urgently than others: “TODO: implement database logic” could be more urgent than “TODO: remove obsolete method”, but removing an obsolete method will probably be easier to do, so it might make sense to do it right away.

Visual Studio 2003 gave you a nice list of all the todo’s in your solution, but for some reason Visual Studio 2005 only does this for currently opened files. In the project I am current working on, we wanted a clear report of all todo’s in our code to make sure that they are solved as soon as possible. Since we already have a CruiseControl.NET server running, we decided to have our continuous integration build generate the TODO report for us. The samples in this post are valid for CruiseControl 1.1.

1. Gathering the todo’s

To generate the report, we’ll need to look through our codebase for lines that have a todo comment in them. This can be done using the RegexFinder NAnt task described in a previous post. We’ll add the exact same target from the RegexFinder example (which looks for matches to the expression “//\s*TO\s*DO.*”) and add it to the NAnt build file used by our continuous integration build.

The target that we should call in the build file looks like this:

<target name="find_todos">
  <regexfinder pattern="//\s*TO\s*DO.*" 
               outputfile="c:\todos.xml" 
               ignorecase="true">
    <fileset basedir="C:\Project\MySources">
      <include name="**/*.cs"/>
    </fileset>
  </regexfinder>
</target>

The output of this task will be a file that looks like this:

<regexFinder basedir="C:\Project\MySources">
  <match>
    <fileName>Business\DefaultFacade.cs</fileName>
    <lineNumber>57</lineNumber>
    <lineData>// TODO: add transaction logic</lineData>
  </match>
  <match>
    <fileName>Presentation\BaseDetailsView.cs</fileName>
    <lineNumber>103</lineNumber>
    <lineData>// TO do: validate user input</lineData>
  </match>
</regexFinder>

2. Integrating with CruiseControl.NET build output

Ok, we have a list with all our todo’s, but to make CruiseControl aware of this file it needs to be merged into the main build output xml. This can be done easily by editing the ccnet.config file, make sure you have a merge entry for the xml file containing the todo’s as follows:

<cruisecontrol>
  <project name="MyProject">
    <publishers>
      <merge>
        <files>
          <!-- ... -->
          <!-- Merge the todo output with the ccnet output file -->
          <file>C:\Project\Builds\Artifacts\todos.xml</file>
        </files>
      </merge>
    </publishers>
  </project>
</cruisecontrol>

3. Display TODO’s on the CruiseControl.NET web dashboard

Now we just need to get it displayed on the ccnet dashboard webpage. To do this, we’ll need to transform the xml output of the RegexFinder to html. Also, we’d like a summary with the number of todo’s in the main page and a complete of all todo’s in a detailed report. To perform these transformations, I created two xslt files: TodosSummary.xsl and TodosReport.xsl.

Now we’ll have to configure the ccnet webdashboard to include these into the build report webpage. This can be done by putting the two xsl files in the xsl folder of the webdashboard and editing the dashboard.config file as follows:

<dashboard><plugins><buildPlugins>
<!-- Add the following elements to include TODO reports -->
    <buildReportBuildPlugin>
        <xslFileNames>
            <xslFile>xsl\TodosSummary.xsl</xslFile>
        </xslFileNames>
    </buildReportBuildPlugin>
    <xslReportBuildPlugin 
        description="TODO's Report" 
        actionName="TodosBuildReport" 
        xslFileName="xsl\TodosReport.xsl"/>
<!-- End of changes for TODO report -->
</buildPlugins><plugins></dashboard>

All done! Just build your project, point your browser to the CruiseControl webdashboard and you should see your TODO’s!