当公司要求你用统一的格式写函数注释时,这个小东西也许可以帮些忙。
设计目标:
1. 自动提取函数名称;2. 自动提取函数功能注释(假设在头文件中);3. 自动列出参数列表;4.自动提取返回值;5.自动填写作者及日期(作者名称可以设置)
例如:
//------------------------------------------------
// 名称:CDSAddIn::OnConnection
// 功能:
// 参数:[IApplication* pApp] ---
// [VARIANT_BOOL bFirstTime] ---
// [long dwCookie] ---
// [VARIANT_BOOL* OnConnection] ---
// 返回:STDMETHODIMP ---
// 作者:麻军 2002-3-4
//------------------------------------------------
STDMETHODIMP CDSAddIn::OnConnection(IApplication* pApp, VARIANT_BOOL bFirstTime, long dwCookie, VARIANT_BOOL* OnConnection)
设计思想:
1. 使用IDSAddIn接口;2. 设计CCmtBlock(COMMENT BLOCK)类维护注释中的各个字段,用来提供扩展灵活性。
实现:
//-----------------------------------------------------------------------------------------------------
// CmtBlock.h: interface for the CCmtBlock class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_CMTBLOCK_H__51B4002A_A935_4764_80B5_03103D5E716E__INCLUDED_)
#define AFX_CMTBLOCK_H__51B4002A_A935_4764_80B5_03103D5E716E__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include <vector>
class CCmtBlock
{
public:
CCmtBlock();
~CCmtBlock();
private:
CString m_szBegin; // 注释首行(hard coded)
CString m_szName; // 函数名称(auto)
CString m_szPurpose; // 函数功能(auto)
CString m_szParam; // 函数参数列表(auto)
CString m_szReturn; // 函数返回(can change)
CString m_szAuthor; // 函数作者(auto)
CString m_szEnd; // 注释尾行(hard coded)
CString m_szFuncDefine; // 函数定义(自动获得)
// CString m_szBlock; // 函数注释块
std::vector< CString* > m_arrSort; // 注释部分的排列顺序
private:
void ExtractName(); // 提取名称
void ExtractPurpose(); // 提取功能
void ExtractParam(); // 提取参数列表
void ExtractReturn(); // 提取返回类型
void ComposeAuthorAndDate(); // 编辑作者和日期时间
public:
void SetFunctionDefine( CString szFuncDefine ); // 设置函数定义(自动获得)
CString ComposeComment(); // 编辑函数注释
void SetPurpose( CString& szFuncPurpose ) {
m_szPurpose = szFuncPurpose; } // 设置函数头文件中的注释
};
#endif // !defined(AFX_CMTBLOCK_H__51B4002A_A935_4764_80B5_03103D5E716E__INCLUDED_)
//-----------------------------------------------------------------------------------------------------
// CmtBlock.cpp: implementation of the CCmtBlock class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "AutoComment.h"
#include "CmtBlock.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CCmtBlock::CCmtBlock()
{
m_szBegin = _T("//------------------------------------------------\r\n");
m_szEnd = _T("//------------------------------------------------\r\n");
m_arrSort.clear();
m_arrSort.push_back( &m_szBegin );
m_arrSort.push_back( &m_szName );
m_arrSort.push_back( &m_szPurpose );
m_arrSort.push_back( &m_szParam );
m_arrSort.push_back( &m_szReturn );
m_arrSort.push_back( &m_szAuthor );
m_arrSort.push_back( &m_szEnd );
}
CCmtBlock::~CCmtBlock()
{
m_arrSort.clear();
}
void CCmtBlock::ExtractName()
{
int iPosSpace = m_szFuncDefine.FindOneOf(_T(" "));
int iPosBracket = m_szFuncDefine.FindOneOf(_T("("));
CString szName = m_szFuncDefine.Mid( iPosSpace, iPosBracket-iPosSpace );
szName.TrimLeft();
szName.TrimRight();
m_szName = _T("// 名称:") + szName + _T("\r\n");
}
void CCmtBlock::ExtractPurpose()
{
CString szTemp = m_szPurpose;
m_szPurpose = _T("// 功能:") + szTemp + _T("\r\n");
}
void CCmtBlock::ExtractParam()
{
// 得到参数表
int iPosLeftBracket = m_szFuncDefine.FindOneOf(_T("("));
int iPosRightBracket = m_szFuncDefine.ReverseFind(_T(')'));
CString szParamTable = m_szFuncDefine.Mid( iPosLeftBracket+1, iPosRightBracket-iPosLeftBracket-1 );
// 分解参数
// 判断是否具有参数
szParamTable.TrimLeft();
szParamTable.TrimRight();
if( szParamTable == _T("") )
{
// 没有参数
m_szParam = _T("// 参数:无\r\n");
return;
}
m_szParam = _T("// 参数:");
int iPos1 = 0;
int iPos2 = 0;
CString szOneParam = _T("");
CString szOneLine;
int iLineCount = 0;
szParamTable += _T(",");
while( ( iPos2 = szParamTable.Find( _T(','), iPos1 ) ) != -1 )
{
iLineCount++;
// 找到参数
szOneParam = szParamTable.Mid( iPos1, iPos2-iPos1 );
szOneParam.TrimLeft();
szOneParam.TrimRight();
if( iLineCount == 1 )
szOneLine = _T("[") + szOneParam + _T("] --- ");
else
szOneLine = _T("// [") + szOneParam + _T("] --- ");
szOneLine += _T("\r\n");
// 添加到函数列表上
m_szParam += szOneLine;
iPos1 = iPos2 + 1;
}
// ::MessageBox( NULL, szParamTable, NULL, MB_OK );
}
void CCmtBlock::ExtractReturn()
{
CString szRet = m_szFuncDefine.Mid( 0, m_szFuncDefine.FindOneOf( _T(" ") ) );
m_szReturn = _T("// 返回:") + szRet + _T(" --- \r\n");
}
extern CString g_szAuthor; // 作者名称
void CCmtBlock::ComposeAuthorAndDate()
{
CString szAuthor = g_szAuthor;//_T("Author");
COleDateTime& date = COleDateTime::GetCurrentTime();
CString szDate = date.Format( VAR_DATEVALUEONLY );
m_szAuthor = _T("// 作者:") + szAuthor + _T(" ") + szDate + _T("\r\n");
}
void CCmtBlock::SetFunctionDefine( CString szFuncDefine )
{
m_szFuncDefine = szFuncDefine;
}
CString CCmtBlock::ComposeComment()
{
ExtractName(); // 提取名称
ExtractPurpose(); // 提取功能
ExtractParam(); // 提取参数列表
ExtractReturn(); // 提取返回类型
ComposeAuthorAndDate(); // 编辑作者和日期时间
CString szBlock = _T("");
for( int i=0;i<m_arrSort.size();i++)
szBlock += *m_arrSort[i];
return szBlock;
}
//-----------------------------------------------------------------------------------------------------
AutoCommentCommandMethod 函数是ADDIN向导自动建立的那个函数
/////////////////////////////////////////////////////////////////////////////
// CCommands methods
STDMETHODIMP CCommands::AutoCommentCommandMethod()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
// TODO: Replace this with the actual code to execute this command
// Use m_pApplication to access the Developer Studio Application object,
// and VERIFY_OK to see error strings in DEBUG builds of your add-in
// (see stdafx.h)
// VERIFY_OK(m_pApplication->EnableModeless(VARIANT_FALSE));
// ::MessageBox(NULL, "AutoComment Command invoked.", "AutoComment", MB_OK | MB_ICONINFORMATION);
// VERIFY_OK(m_pApplication->EnableModeless(VARIANT_TRUE));
// 得到当前文档
CComPtr<IDispatch> pDispActDocument = NULL;
m_pApplication->get_ActiveDocument( &pDispActDocument );
if( !pDispActDocument )
return E_FAIL;
CComQIPtr< ITextDocument, &IID_ITextDocument > pDoc( pDispActDocument );
// 得到选择对象
CComPtr< IDispatch > pDispSelection;
pDoc->get_Selection( &pDispSelection );
if( !pDispSelection )
return E_FAIL;
CComQIPtr< ITextSelection, &IID_ITextSelection > pSelection( pDispSelection );
// 得到函数定义(假设光标插在函数定义中)
// -- 寻找的标志是:头(NewLine),尾({)>> 将来实现
// 选择函数定义的第一行
CComBSTR bstrFuncDefine;
pSelection->SelectLine();
pSelection->get_Text( &bstrFuncDefine );
// 将光标插入行的起始位置
VARIANT var1,var2;
VariantInit( &var1 );
VariantInit( &var2 );
pSelection->StartOfLine( var1, var2 );
if( bstrFuncDefine.Length() == 0 )
return E_FAIL; // 不是函数定义
USES_CONVERSION;
CString szFuncDefine = W2A(bstrFuncDefine);
m_CmtBlock.SetFunctionDefine( szFuncDefine );
// 找到头文件中函数定义的注释
CString& szFuncComm = FindFunctionPurposeInHeader( szFuncDefine );
m_CmtBlock.SetPurpose( szFuncComm );
// 构成函数注释字符串
CString szBlock = m_CmtBlock.ComposeComment();
BSTR bstrBlock;
bstrBlock = A2W( szBlock );
pSelection->put_Text( bstrBlock );
return S_OK;
}
CString CCommands::FindFunctionPurposeInHeader( CString& szDefine )
{
CString szRet;
// 得到当前文档
CComPtr<IDispatch> pDispActDocument = NULL;
m_pApplication->get_ActiveDocument( &pDispActDocument );
if( !pDispActDocument )
return "";
CComQIPtr< ITextDocument, &IID_ITextDocument > pDoc( pDispActDocument );
if( !pDoc )
return "";
// 得到函数名称
CString szFuncName;
int iPosSpace = szDefine.FindOneOf(_T(":"));
int iPosBracket = szDefine.FindOneOf(_T("("));
szFuncName = szDefine.Mid( iPosSpace+2, iPosBracket-iPosSpace-2 );
szFuncName.TrimLeft();
szFuncName.TrimRight();
// 打开对应的.h文件
CComBSTR bstrFullName;
pDoc->get_FullName( &bstrFullName );
CString szFullName( bstrFullName );
szFullName.MakeLower();
CString szExt = szFullName.Right( 3 );
if( szExt != "cpp" ) // 不是.cpp
return "";
szFullName.TrimRight( "cpp" );
szFullName += "h"; // 转换成.h
CStdioFile file;
if( !file.Open( szFullName, CFile::modeRead ) )
return "";
CString szLine;
CString szPurpose;
int pos;
while( file.ReadString( szLine ) )
{
// 检查每一行是否有函数名称
if( (pos=szLine.Find( szFuncName )) != -1 )
{
// 检查szFuncName的前后字符是否为空格and'('
// 构造一个字符串在szFuncName的前后个加一个字符
CString szTemp = szLine.Mid( pos-1, szFuncName.GetLength()+2 );
if( szTemp.Left(1) != " " ||
( szTemp.Right(1) != " " && szTemp.Right(1) != "(" ) )
szRet = "";
else
{
// 找到函数声明
// 查看当前行的末尾有没有注释
int posSplash = 0;
if( ( posSplash = szLine.ReverseFind( '/' ) ) != -1 )
szRet = szLine.Right( szLine.GetLength() - posSplash - 1 );
else
{
// 查看下一行有没有注释
if( file.ReadString( szLine ) )
{
szLine.TrimLeft();
szLine.TrimRight();
if( szLine.Left(1) == "/" )
{
// 有注释
szLine.TrimLeft("//");
szRet = szLine;
}
else
szRet = "";
}
else
szRet = "";
}
}
}
}
file.Close();
szRet.TrimRight();
szRet.TrimLeft();
return szRet;
}
//-----------------------------------------------------------------------------------------------
// 在CDSAddIn::OnConnection函数中改写以下代码,注意:CParamDlg 类是一个输入作者名称的对话框类
if (bFirstTime == VARIANT_TRUE)
{
VERIFY_OK(pApplication->
AddCommandBarButton(dsGlyph, bszCmdName, m_dwCookie));
// 第一次使用让用户输入姓名
CParamDlg dlgParam;
if( dlgParam.DoModal() == IDOK )
{
g_szAuthor = dlgParam.m_szAuthor;
// 存入注册表
::WriteProfileString("DSAddIn_AutoComment","Author",g_szAuthor);
}
}
else
{
char szAuthor[255];
::GetProfileString("DSAddIn_AutoComment","Author","Author",szAuthor,sizeof(szAuthor));
g_szAuthor = CString(szAuthor);
}
//-------------------------------------------------------------------------------------------------
希望大家能提出宝贵意见 :-)
Ma Jun ----- ma2jun@sina.com Jurassic xian corp.
感谢Kamp Huang给这个东东找了个家: