Dec 15 2009

Report on your code base for TODO comments via CruiseControl.NET

Category: Continuous Integrationryancmartin1976 @ 20:59

First Strategy:

  • a
  • b
  • c

Second Strategy:

Everyone has to do's in their code comments, so here is an easy way to to check how many you have left in your project

STEP 1

Add a new project to your solution called BuildTasks. Add a new class called ParseCodeDebt.cs

Here is the class code

using System.Diagnostics;
using System.IO;
using NAnt.Core;
using NAnt.Core.Attributes;
 
[TaskName("ParseCodeDebt")]
public class ParseCodeDebt : Task
{
    private string CurrentFolder { get; set; }
 
    public void PerformTest()
    {
        ExecuteTask();    
    }
 
    [TaskAttribute("PathToParse", Required = true)]
    [StringValidator (AllowEmpty = false)]
    public string PathToParse { get; set; }
    protected override void ExecuteTask()
    {
        Stopwatch sw = new Stopwatch();
        sw.Start();
        Log(Level.Warning,"---------------------------------------------------------------------------");
        Log(Level.Warning, "CODE DEBT CHECK for " + PathToParse);
 
        //iterate through all the files in a directory recursively
        System.IO.DirectoryInfo root = new DirectoryInfo(PathToParse);
        WalkDirectoryTree(root);
 
        Log(Level.Warning, "");
        Log(Level.Warning, "Completed in " + sw.ElapsedMilliseconds + "ms");
        Log(Level.Warning, "---------------------------------------------------------------------------");
        Log(Level.Warning, "");
    }
 
    private void WalkDirectoryTree(System.IO.DirectoryInfo root)
    {
        System.IO.FileInfo[] files = null;
        System.IO.DirectoryInfo[] subDirs = null;
 
        // First, process all the files directly under this folder
        try
        {
            files = root.GetFiles("*.*");
        }
            // This is thrown if even one of the files requires permissions greater
            // than the application provides.
        catch (UnauthorizedAccessException e)
        {
            // This code just writes out the message and continues to recurse.
            Log(Level.Warning, e.Message);
        }
 
        catch (System.IO.DirectoryNotFoundException e)
        {
            Log(Level.Warning, e.Message);
        }
 
        if (files != null)
        {
            foreach (System.IO.FileInfo fi in files)
            {
                if (fi.Name.ToLower().EndsWith(".cs") && fi.Name.ToLower() != "parsecodedebt.cs")
                {
                    try
                    {
                        //look for code debt in this file
                        ParseFile(fi);
                    }
                    catch (FileNotFoundException e)
                    {
                        Log(Level.Warning, e.Message);
                    }
                }
            }
 
            // Now find all the subdirectories under this directory.
            subDirs = root.GetDirectories();
 
            foreach (System.IO.DirectoryInfo dirInfo in subDirs)
            {
                if (dirInfo.Name != ".svn")
                {
                    // Resursive call for each subdirectory.
                    WalkDirectoryTree(dirInfo);
                }
            }
        }
    }
 
    private void ParseFile(FileInfo file)
    {
        StreamReader sr = file.OpenText();
        int lineNumber = 1;
        string line = "";
        line = sr.ReadLine();
        while(line!=null)
        {
            if(line.ToLower().Contains("//codedebt"))
            {
                if (CurrentFolder != file.DirectoryName)
                {
                    CurrentFolder = file.DirectoryName;
                    Log(Level.Warning, "");
                    Log(Level.Warning, CurrentFolder);
                }
                Log(Level.Warning, "\t" + file.Name);
                string[] attributes = line.ToLower().Replace("//codedebt","").Trim().Split('|');
                Log(Level.Warning, "\tLine " + lineNumber.ToString());
                foreach (string s in attributes)
                {
                    Log(Level.Warning, "\t" + s.Trim());
                }
            }
            lineNumber++;
            line = sr.ReadLine();
        }
        sr.Close();
    }
}

STEP 2

Next you need to create a new NAnt build task, here is the code

<?xml version="1.0" encoding="utf-8"?>
<project name="ProjectNameWeb" default="build" xmlns="http://nant.sf.net/release/0.85/nant.xsd">
  <!-- Properties -->
  <property name="trunk.dir" value="..\" />
  <property name="dependencies.dir" value="${trunk.dir}\dependencies" />
 
  <!-- Custom Assemblies -->
  <loadtasks assembly="${dependencies.dir}\CustomBuildTasks\CustomBuildTasks.dll"/>
  <loadtasks assembly="${dependencies.dir}\NCover\NCover.NAntTasks.dll"/>
  <loadtasks assembly="${dependencies.dir}\NCover\NCoverExplorer.NAntTasks.dll"/>
 
  <!-- Called Externally -->
  <target name="findToDo" depends="compile, parseCodeDebt" />
 
  <!-- Coding Tasks -->
  <target name="parseCodeDebt">
  <ParseCodeDebt RootPathToParse="${ProjectNameWeb.dir}" 
    DirectoriesToIgnore=".svn,_ReSharper.ProjectNameWeb" 
    FileTypeToProcess=".cs" />
  <ParseCodeDebt RootPathToParse="${ProjectNameWebTests.dir}" 
    DirectoriesToIgnore=".svn,_ReSharper.ProjectNameWeb" 
    FileTypeToProcess=".cs" />
  </target>
</project>

STEP 3

Go to your log4net output directory and open up the file and your Custom NAnt Build task should of dumped all of the data there

some more text here

Tags: , , , ,