С масштабом, подобным размеру кодовой базы OP, необходима система преобразования программ (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 } ";
Здесь объясняется синтаксис этих правил/шаблонов для нашего набора инструментов для реинжиниринга программного обеспечения DMS. а>. DMS — это единственная известная мне PTS с преобразованием исходного кода, которая может работать с C++; он даже поддерживает диалект MSVS].
Я пропустил возможно необходимую проверку "if условие", что имя члена действительно является членом класса, при условии, что ваши конструкторы не являются оскорбительными.
Поскольку ваши конструкторы могут не иметь никакого списка инициализаторов, вам нужно вспомогательное правило, чтобы ввести его, когда это необходимо:
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);
который требует вспомогательного мета-предиката, проверяющего порядок и жалующегося на неправильный порядок. Вам нужно имя_конструктора, чтобы предикат мог искать соответствующий класс и проверять порядок членов. [DMS предоставляет средства для доступа к таблице символов с помощью этого Информация].
В качестве альтернативы вы можете просто изменить их порядок, используя другое правило перезаписи:
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);
Это правило по существу сортирует инициализаторы. [Обратите внимание, что это пузырьковая сортировка: но списки инициализаторов, как правило, не длинные, и вы в любом случае будете запускать это только один раз для каждого конструктора.] Вы должны запустить это правило после того, как вы подняли все инициализаторы из тела конструктора, используя правила, показанные ранее.
person
Ira Baxter
schedule
20.11.2016
-Wreorder
. - person Biffen   schedule 14.11.2016