與OP的代碼庫大小一樣,需要的是program transformation system (PTS)。這是一個將目標語言源文件解析爲編譯器數據結構(通常是AST)的工具,允許您將轉換應用到AST,然後可以重新生成有效的源代碼,包括修改程序的原始註釋。把PST看作在大型中重構的工具。
一個很好的PTS將讓你寫源到源轉換形式的:
when you see *this*, replace it by *that* if *condition*
其中這和是在目標語言的語法表達,其中這僅當源代碼與顯式語法匹配時才匹配。 [這些不是字符串匹配;他們在AST上工作,所以佈局不會影響他們匹配的能力]。
你需要鑰匙規則看起來是這樣的:
rule move_to_initializer(constructor_name:IDENTIFIER,
arguments: argument_list,
initializer_list: initializer,
member_name:IDENTIFIER,
initializer_expression: expression,
statements: statement_list
): constructor -> constructor =
" \constructor_name(\arguments): \initializer_list
{ \member_name = \initializer_expression ;
\statements } "
-> " \constructor_name(\arguments): \initializer_list, \member_name(\initializer_expression)
{ \statements } ";
The syntax of these rules/patterns for our DMS Software Reengineering Toolkit is explained here。 DMS是唯一可以處理C++的源碼到源碼PTS;它甚至可以處理MSVS方言]。
我忽略了可能必要的「如果條件」檢查成員名稱確實是類的成員,假設您的構造函數不是濫用。
因爲你的構造可能沒有任何初始化列表,你需要一個幫手規則介紹一個在必要時:
rule move_to_initializer(constructor_name:IDENTIFIER,
arguments: argument_list,
member_name:IDENTIFIER,
initializer_expression: expression,
statements: statement_list
): constructor -> constructor =
" \constructor_name(\arguments)
{ \member_name = \initializer_expression ;
\statements } "
-> " \constructor_name(\arguments): \member_name(\initializer_expression)
{ \statements } ";
{ \member_name = \e ; } "
不變的是你需要額外的規則,以涵蓋其他特殊情況,但它不應該超過一些。
關於對訂單的初始化檢查,則可以使用(DMS)圖案觸發這樣的檢查:
pattern check_initializer_order(constructor_name:IDENTIFIER,
initializer_list: initializer,
statements: statement_list
): constructor =
" \constructor_name(): \initializer_list,
{ \statements } "
if complain_if_not_ordered(constructor_name,initializer_list);
這需要一個輔助的元謂詞檢查順序,如果它們是抱怨亂序。您需要constructor_name來使謂詞能夠查找相應的類並檢查成員的順序。 [DMS向means to access a symbol table提供這些信息]。
或者,你可能只是簡單地重新排列它們使用不同的重寫規則:
rule order_initializers(constructor_name:IDENTIFIER,
arguments: argument_list,
initializer_list_prefix: initializer,
initializer_list_suffix: initializer,
member1_name:IDENTIFIER,
initializer1_expression: expression,
member2_name:IDENTIFIER,
initializer2_expression:expression,
statements: statement_list
): constructor -> constructor =
" \constructor_name(\arguments):
\initializer_list_prefix,
\member1_name(\initializer1),
\member2_name(\initializer2),
\initialize_list_suffix
{ \statements } "
->
" \constructor_name(\arguments):
\initializer_list_prefix,
\member2_name(\initializer2),
\member1_name(\initializer1),
\initialize_list_suffix
{ \statements } "
if is_wrong_order(constructor_name,member1_name,member2_name);
這個規則基本上排序初始化。 [請注意,這是一個冒泡排序:但是初始化列表通常不會很長,並且您只需要爲每個構造函數運行一次。]在將所有初始化器從構造函數體中提取出來之後,您將運行此規則前面顯示的規則。
至於第二部分:GCC有'-Wreorder'。 – Biffen
@Biffen是不是Visual Studio 2012?這就是我正在使用的。 – fwgx
不是我所知道的,一個快速的谷歌沒有給任何東西。我會留給你做更多的研究。 – Biffen