Click here to Skip to main content
Licence CPOL
First Posted 16 Oct 2010
Views 19,846
Downloads 329
Bookmarked 23 times

XLineCounter, Count Number of Source Code Lines

By | 25 Nov 2010 | Article
XLineCounter, count number of source code lines, support VB, C#, C++ and Delphi
XLineCounter_Snapshot.jpg

Introduction

XLineCounter is a open source C# program to analyze source code files and count the number of source code lines. It can count number of source lines, comment lines and blank lines.

Background

Millions of programmers work hard year after year, and write many source codes in C++, C#, VB or Delphi. Sometimes, they want know how many lines are there of that source code. Of course, they cannot count line by line, so they need a tool to count the source lines.

XLineCounter

Today, source code files are not alone, many source code files construct a project, and the compiler handles the project and generates a program file.

For example, in VS.NET 2005, people create a C# project whose file name’s extension is csproj, and add many C# source files to the C# project.

XLineCounter needs to analyze develop project file and get a list of source code file, also equip source code analyzer which can analyze source code like VB , C# or Pascal. So I design XLineCounter structure as the following shape:

XLineCounter_Structure.gif

There are two stresses in XLineCounter: first, analyze project file and get file list; second, analyze source file use specify syntax.

For example, a C# .NET2005 project file in XML format. There is a sample.

<Project DefaultTargets="Build"
    xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <AssemblyName>CellViewLib</AssemblyName>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="System">
      <Name>System</Name>
    </Reference>
  </ItemGroup>
  <ItemGroup>
    <Content Include="App.ico" />
    <Compile Include="frmTestCellView.cs">
      <SubType>Form</SubType>
    </Compile>
    <EmbeddedResource Include="frmTestCellView.resx">
      <DependentUpon>frmTestCellView.cs</DependentUpon>
      <SubType>Designer</SubType>
    </EmbeddedResource>
  </ItemGroup>
</Project>

To this XML document, I can execute XPath “Project/ItemGroup/Compile” and get a list of C# source file names. So I write the following C# code:

System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
doc.LoadXml(txt);
if (doc.DocumentElement.Name == "Project"
    && doc.DocumentElement.GetAttribute("xmlns") == 
	"http://schemas.microsoft.com/developer/msbuild/2003")
{
    project.ProjectFileName = strFileName;
    project.RootPath = System.IO.Path.GetDirectoryName(strFileName);
    ProjectFile ProjFile = new ProjectFile();
    ProjFile.FileName = System.IO.Path.GetFileName(strFileName);
    ProjFile.FullFileName = strFileName;
    ProjFile.Style = FileStyle.None;
    project.Files.Add(ProjFile);
 
    System.Xml.XmlNamespaceManager ns = 
	new System.Xml.XmlNamespaceManager(doc.NameTable);
    ns.AddNamespace("a", "http://schemas.microsoft.com/developer/msbuild/2003");
 
    System.Xml.XmlNode NameNode = doc.SelectSingleNode
		("a:Project/a:PropertyGroup/a:AssemblyName", ns);
    if (NameNode != null)
    {
        project.Name = NameNode.InnerText;
    }
    foreach (System.Xml.XmlElement element in doc.SelectNodes
	("a:Project/a:ItemGroup/*[name()='Compile' or name()='None' or 
	name()='EmbeddedResource' or name()='Content']", ns))
    {
        string file = element.GetAttribute("Include");
        ProjectFile NewFile = new ProjectFile();
        NewFile.FileName = project.FixFileName(file);
        if (System.IO.Path.IsPathRooted(file))
        {
            NewFile.FullFileName = file;
        }
        else
        {
            NewFile.FullFileName = System.IO.Path.Combine(project.RootPath, file);
        }
        if (element.Name == "Compile")
        {
            NewFile.Style = FileStyle.SourceCode;
        }
        else if (element.Name == "EmbeddedResource")
        {
            NewFile.Style = FileStyle.Resource;
        }
        else
        {
            NewFile.Style = FileStyle.None;
        }
        project.Files.Add(NewFile);
    }//foreach
}

Using this code, XLineCounter can get a file list from C#2005 project file. In the same way, XLineCounter can analyze VB.NET 2005, VB6.0, Delphi project file and get source code file list.

Next, XLineCounter needs to analyze source code with some kind of syntax. For example, there are some C# source code as follows:

// Single line comment
string str = "abc";
string str2 = @"abc
efg";
/*
 Multi-line comment
 */

In C# syntax, there are 5 characters:

  1. Single line comment starts with // .
  2. Multi-line comment starts with /* and end with */ .
  3. String data starts with double quotes and ends with double quotes.
  4. In string data , \” define a double quotes characters.
  5. Multi-line string data starts with @” .

So I write the following C# code to analyze C# source code text:

// string define flag 
// 0:It is not define string
// 1:It is a singleline string
// 2:It is a multi-line string
int DefineString = 0;
// Comment flag
bool DefineComment = false ;
foreach( LineInfo info in myLines )
{
	info.CodeFlag = false;
	if( info.LineText.Length == 0 && DefineString == 2)
		info.BlankLine = false;
	for(int iCount = 0 ; iCount < info.LineText.Length ; iCount ++)
	{
		// Get current character
		char c = info.LineText[iCount] ;
		// Get next character
		char c2 = (char)0;
		if( iCount < info.LineText.Length - 1 )
			c2 = info.LineText[ iCount + 1 ];

		if(! char.IsWhiteSpace( c ))
			info.BlankLine = false;

		// Defining Comment
		if( DefineComment )
		{
			info.BlankLine = false;
			info.CommentFlag = true;
			// Finish when meet */
			if( c == '*' &&  c2 == '/' )
			{
				DefineComment = false;
				iCount ++ ;
			}
			continue ;
		}
		if( DefineString == 0 )
		{
			// Is not defining string
			if( c == '/' && c2 != 0 )
			{
				if( c2 == '/' )
				{
					// Single line comment when meet //
					info.CommentFlag = true;
					DefineComment = false;
					goto NextLine ;
				}
				if( c2 == '*' )
				{
					// Start multi-line comment when meet /*
					if( iCount > 0 )
						info.CodeFlag = true;
					info.CommentFlag = true;
					DefineComment = true;
					iCount ++ ;
					continue;
				}
			}
			if( c == '\"')
			{
				if( iCount < 0 && info.LineText[iCount-1] == '@')
					// Start multi-line string when meet @"
					DefineString = 2 ;
				else
					// Start single line string when meet "
					DefineString = 1 ;
			}
		}
		else
		{
			info.BlankLine = false;
			// Defining string
			if( c == '\"'  )
			{
				// Finish string when meet "
				if( iCount < 0 && info.LineText[iCount-1] !='\\' )
					DefineString = 0 ;
			}
		}
		if( ! char.IsWhiteSpace( c ))
			info.CodeFlag = true;
	}//for(int iCount = 0 ; iCount < info.LineText.Length ; iCount ++)
NextLine:;
}//foreach( LineInfo info in myLines )

LineInfo type is a class which contains information of a source code line. It is defined as  follows:

/// <summary>
/// source code line information
/// </summary>
public class LineInfo
{
    /// <summary>
    /// Whether a text line
    /// </summary>
    public string LineText = null;
    /// <summary>
    /// Whether is a comment line
    /// </summary>
    public bool CommentFlag = false;
    /// <summary>
    /// Whether is a blank line , without any content
    /// </summary>
    public bool BlankLine = true;
    /// <summary>
    /// Whether is a source code line
    /// </summary>
    public bool CodeFlag = false;
}

By using upper code, XLineCounter can analyze C#.NET 2005 project file and C# source code, count number of C# source code. In the same way, XLineCounter can count number of source code of VB.NET, Delphi and C++.

Points of Interest

None.

History

  • 2010-11-26 Added line count result report

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

fu yuans

Web Developer
sinosoft
China China

Member

yfyuan of Sinosoft , come from CHINA , 2008 Microsoft MVP,Use GDI+,XML/XSLT, site:http://www.sinoreport.net/

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
GeneralThoughts PinmvpPIEBALDconsult6:37 26 Nov '10  
GeneralMy vote of 5 PinmemberTony's Toy19:14 25 Nov '10  
GeneralMy vote of 5 Pinmemberyufb1218:04 25 Nov '10  
GeneralWell done, but there's a free tool for VS that does this and more. PinmemberKChandos5:17 25 Oct '10  
GeneralMy vote of 3 PinmemberS.H.Bouwhuis23:38 20 Oct '10  
GeneralSome suggestions for new features Pinmemberkaveh0969:28 18 Oct '10  
GeneralMy vote of 4 Pinmembersalonent9:05 18 Oct '10  
QuestionSupport for Visual Studio solutions Pinmembersalonent9:02 18 Oct '10  
GeneralNice Pinmembervictorbos8:21 18 Oct '10  
GeneralGood Idea PinmemberAnt21001:48 17 Oct '10  

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Mobile
Web01 | 2.5.120517.1 | Last Updated 26 Nov 2010
Article Copyright 2010 by fu yuans
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid