65.9K
CodeProject 正在变化。 阅读更多。
Home

JesTracePaster - 在源文件中添加方法入口日志的工具

starIconstarIconstarIconstarIconstarIcon

5.00/5 (4投票s)

2009年3月11日

CPOL

3分钟阅读

viewsIcon

22596

downloadIcon

238

这个简单的工具将在源代码文件中添加方法入口日志。

引言

JesTracePaster 是一个简单的应用程序,可用于在源代码文件中添加方法入口日志。当您有大量代码需要学习操作顺序时,这样的工具非常有用。手动在所有方法中添加跟踪信息将非常耗时。这个小工具 JesTracePaster 可以在这种情况下帮助您。

背景

我的一个朋友收到一个示例图像处理应用程序作为参考。虽然它只是一个示例,但代码相当复杂,而且他不太熟悉这项技术。所以他决定可以向大约 500 个源文件添加跟踪信息,并检查操作顺序,以便了解该应用程序的主要实体。但是,向 500 个文件添加跟踪信息本身就可能需要一周时间。当时,我正在努力开发 JesInclAnalyzer(一个从源文件中删除不需要的头文件包含的工具;已发布在 CodeProject 上),发现 JesInclAnalyzer 中的一些类(经过一些修改)可以用来开发一个简单的应用程序,该应用程序可以将方法入口日志添加到源文件中的类方法中。

使用工具/代码

简单的文件操作和文本处理用于实现 JesTracePaster。在“日志宏/函数/方法”编辑框中,输入用于记录的宏、函数或方法(例如:OutputDebugString)。如果此编辑框留空,将使用 OutputDebugString 进行记录。在“源文件”编辑框中,输入要更新的源文件的路径。多个路径可以用“;”分隔。单击“更新”按钮。该工具将通过添加方法入口日志来更新源文件。处理状态将在主对话框中更新。请注意,该工具不会处理“只读”文件。它将为“只读”文件提供“访问被拒绝”错误消息。此外,该工具不适用于 C 风格的函数和在头文件中定义的方法。

首先,该工具借助 JesCPPIterator 类创建给定路径中可用源文件的列表。方法 bool JesCPPIterator::PopulateFileList( const CStringArray& Paths_i, bool bSrcFiles_i ) 使用 CFileFind 创建源文件列表。源文件保存在 CStringArray 成员中,方法 bool JesCPPIterator::GetNextFile( CString& csSrcFile_o ) 逐个返回文件名。我没有充分的理由向您解释为什么我没有从 CStringArray 派生此类,而是将其包装起来。我所做的可能不是一个好的设计。

JesFileProcessor 负责使用跟踪信息更新文件。方法 void JesFileProcessor::UpdateTraces( const CString& csLogMethod_i ) 跳过单行和多行注释以提高效率。此方法检查“::[方法名](”模式以修复方法起始位置;检查“{”以修复日志插入点。一旦写入入口日志,将跳过代码行,直到方法块终止。这是基于大括号的配对完成的。以下代码片段实现了此逻辑:

while( m_SrcFile.ReadString( csLine ))
{
    // Mark and skip Multi-line comment start
    static const CString MULTI_LINE_COMMENT_END_SYMBOL = _T( "*/" );
    if( !bMultiLineComment )
    {
        static const CString MULTI_LINE_COMMENT_SYMBOL = _T( "/*" );
        csLine.TrimLeft();
        csLine.TrimRight();
        int nMLCmntStartIdx = csLine.Find( MULTI_LINE_COMMENT_SYMBOL );
        int nMLCmntEndIdx = csLine.Find( MULTI_LINE_COMMENT_END_SYMBOL );
        if( ( -1 != nMLCmntStartIdx ) &&
            ( -1 == nMLCmntEndIdx ))
        {
            bMultiLineComment = true;
            continue;
        }
        else if( ( 0 == nMLCmntStartIdx ) &&
                 (( csLine.GetLength() - 1 ) == nMLCmntEndIdx ))
        {
            continue;
        }
        else
        {
            // Do nothing
        }
    }
    else
    {
        if( -1 != csLine.Find( MULTI_LINE_COMMENT_END_SYMBOL ))
        {
            bMultiLineComment = false;
            continue;
        }
        else
        {
            continue;
        }
    }
     // Skip single line comments
    static const CString SINGLE_LINE_COMMENT_SYMBOL = _T( "//" );
    if( -1 != csLine.Find( SINGLE_LINE_COMMENT_SYMBOL ))
    {
        continue;
    }
     const static TCHAR EXP_LINE_END = _T( ';' );
    static const TCHAR BLOCK_START = _T( '{' );
    if( nBraceCnt )
    {
        static const TCHAR BLOCK_END = _T( '}' );
        int nBlockStartIdx = csLine.Find( BLOCK_START );
        int nBlockEndIdx = csLine.Find( BLOCK_END );
        bool bBracePairs = (( -1 != nBlockStartIdx ) && ( -1 != nBlockEndIdx )) ||
                           (( -1 == nBlockStartIdx ) && ( -1 == nBlockEndIdx ));
        if( !bBracePairs )
        {
            if( -1 != nBlockStartIdx )
            {
                ++nBraceCnt;
            }
            else if( -1 != nBlockEndIdx )
            {
                --nBraceCnt;
            }
            else
            {
                // Do nothing
            }
        }
         continue;
    }
     if( bLogMsgCreated )
    {
        if( -1 != csLine.Find( BLOCK_START ))
        {
            DWORD dwLinePos = m_SrcFile.GetPosition();
            UpdateLine( dwLinePos, csLogMsg );
            csLogMsg.Empty();
            m_SrcFile.Seek( m_dwCurPos, CFile::begin );
            bLogMsgCreated = false;
            nBraceCnt = 1;
        }
         continue;
    }
     // Check method start
    const static CString SCOPE_SYMBOL = _T( "::" );
    int nScopeStartIdx = csLine.Find( SCOPE_SYMBOL );
    if( ( -1 != nScopeStartIdx ) &&
        ( -1 == csLine.Find( EXP_LINE_END )))
    {
        static const TCHAR METHOD_START = _T( '(' );
        int nMethodStartIdx = csLine.Find( METHOD_START );
        if( nScopeStartIdx > nMethodStartIdx )
        {
            continue;
        }
         static const TCHAR DATA_TYPE_DELIMITER = _T( ' ' );
        static const TCHAR METHOD_END = _T( ')' );
        static const TCHAR DOUBLE_INVERTED_QUOTE = _T( '\"' );
        static const CString BLOCK_INDENTATION = _T( "    " );
        int nMethodNameStartIdx = csLine.Find( DATA_TYPE_DELIMITER );
         // For constructors
        if( ( -1 == nMethodNameStartIdx ) ||
            ( nMethodNameStartIdx > nMethodStartIdx ))
        {
            nMethodNameStartIdx = 0;
        }
        else
        {
            nMethodNameStartIdx += 1;
        }
        CString csMethodName = csLine.Mid( nMethodNameStartIdx,
                                           nMethodStartIdx - nMethodNameStartIdx );
        csLogMsg.Format( _T( "%s%s%c %s %c%s%c %c%c%c" ), 
			BLOCK_INDENTATION, csLogMethod_i, METHOD_START,
                         	_T( "_T(" ), DOUBLE_INVERTED_QUOTE, 
			csMethodName, DOUBLE_INVERTED_QUOTE,
                         	METHOD_END, METHOD_END, EXP_LINE_END );
        bLogMsgCreated = true;
    }
}

关注点

我花了很多时间来检查一个错误。当我用自己的源文件测试 JesTracePaster 时,我发现了这个错误。在 JesFileProcessor.cpp 中,方法...

void JesFileProcessor::UpdateTraces( const CString& csLogMethod_i ) 

...后面跟着方法...

void JesFileProcessor::UpdateLine( DWORD dwLinePos_i, const CString& csUpdateLine_i ) 

... 和...

void JesFileProcessor::ShowFileException()

这个错误的表现是,入口日志永远不会插入最后两个方法中。 出现错误的原因是以下代码行

static const CString MULTI_LINE_COMMENT_SYMBOL = _T( "/*" );

我没有修复这个错误,因为我认为这在正常情况下是一种非常罕见的可能性。 留给读者作为练习。

历史

  • 版本 1.0 - 2009 年 3 月 11 日
© . All rights reserved.