Вы можете использовать систему преобразования программ от источника к источнику. Такой инструмент анализирует код, строит и AST, позволяет применять преобразования, а затем восстанавливает текст из AST. Что делает систему «источник-источник» приятной, так это то, что вы можете писать преобразования с точки зрения синтаксиса исходного языка, а не фрактальной детализации AST, что делает их намного проще для написания и понимания позже.
То, что вы хотите сделать, было бы смоделировано довольно простым программным преобразованием
используя наш DMS Software Reingineering Toolkit :
rule insert_post_statement_call(s: stmt): stmt -> stmt =
" \s " -> " { \s ; MyAdditionalMethod(); }";
Это правило не является "текстовой" заменой; скорее он анализируется синтаксическим анализатором, который обрабатывает целевой код, и, таким образом, фактически представляет два AST, слева и справа (разделенные синтаксисом «->». Кавычки не являются строковыми кавычками; они это кавычки вокруг синтаксиса целевого языка, чтобы отличить его от синтаксиса самого языка правил. Внутри кавычек находится текст целевого языка (например, C #) с экранированными символами типа \ s, которые представляют целые языковые элементы (в данном случае, stmt в соответствии с грамматикой целевого языка (например, C #). В левой части написано «соответствует любому утверждению s», поскольку s определено как «stmt» в грамматике. В правой части написано «замените выражение на блок, содержащий исходный оператор \ s и новый код, который вы хотите вставить ". Все это делается с точки зрения синтаксических деревьев с использованием грамматики в качестве руководства; он не может применить преобразование к чему-либо, что не является оператором. [ Причина, по которой оператор переписывается как блок, заключается в том, что в этом случае правая сторона равна val. ID, где утверждения действительны, иди проверьте свою грамматику.]
На практике вам нужно будет написать правила для обработки других особых случаев, но в основном это написание большего количества правил. Вам также необходимо упаковать анализатор / transformer / prettyprinter в пакет, который требует некоторого процедурного клея. Это по-прежнему гораздо проще, чем пытаться писать код, чтобы надежно взбираться по дереву вверх, вниз по узлам, а затем разбивать эти узлы, чтобы получить то, что вы хотите. Лучше, когда ваша грамматика (неизменно) должна быть скорректирована, правила переписывания переопределяются в соответствии с пересмотренной грамматикой и продолжают работать; Какое бы процедурное лазание по деревьям вы ни делали, оно почти наверняка сломается.
По мере того, как вы пишете все больше и больше преобразований, эта возможность становится все более и более ценной. И когда вы успешно справляетесь с небольшим количеством преобразований, добавление большего количества становится быстро привлекательным.
См. этот технический документ для более подробного обсуждения того, как работает DMS и как она используется для применения инструментальных преобразований, как вы хотите, в реальных инструментах. В этой статье описываются основные идеи, лежащие в основе инструментов тестового покрытия, продаваемых Semantic Designs.