Изменение ссылок на устаревшие методы C++

У меня есть некоторые методы, которые устарели в моей кодовой базе, и я знаю, как я должен их заменить, есть ли способ сделать это автоматически? Я использую Visual Studio 2015, обновление 3, но я открыт для использования других текстовых редакторов...

Код выглядит так:

// Deprecated method
myFunction(char* firstParam, char* secondParam = NULL);

// New method, same name, different params
myFunction(char* firstParam, bool flag, char* secondParam = NULL);

Я просто хочу что-то, что могло бы заменить все ссылки на первую функцию ссылкой на вторую. то есть:

myFunction( "hello", "world");
// Replace with
myFunction( "hello", true, "world");

а также

myFunction("hello");
// Replace with
myFunction("hello", true);

а также

myFunction("hello", isTrue); // isTrue is a bool here
// Do not replace with anything

а также

myFunction("hello", world); //world is a char* here
// Replace with
myFunction("hello", true, world);

Я открыт для решений с использованием Visual Studio или даже других текстовых редакторов. Причина, по которой я не делаю этого вручную, заключается в том, что кодовая база слишком велика.


person Michel Jiang    schedule 04.10.2017    source источник
comment
использовать функцию поиска и замены вашего редактора? Не уверен, что понял вопрос   -  person 463035818_is_not_a_number    schedule 04.10.2017
comment
Я не уверен, понимаю ли я, потому что это совершенно разные методы с разными сигнатурами. Вам нужно будет не только изменить сигнатуры, но и в каждом месте, где вы вызываете исходный метод, вам нужно будет обновить код для поддержки новой сигнатуры.   -  person Daniel Lee    schedule 04.10.2017
comment
Как использовать регулярное выражение? потому что трудно поймать типы переменных с помощью регулярных выражений. (Или, может быть, я просто не знаю, как)   -  person Michel Jiang    schedule 04.10.2017
comment
Старая функция просто вызывает новую функцию? И используйте атрибут, чтобы пометить старую функцию как [[deprecated]] (чтобы компилятор мог предупредить об использовании и помочь найти звонки)?   -  person Some programmer dude    schedule 04.10.2017
comment
Идея состоит в том, что старые функции в какой-то момент будут стерты, а не просто объявлены устаревшими. Так что я не могу просто сказать myFunction(Hello, true); в реализации устаревшей функции.   -  person Michel Jiang    schedule 04.10.2017
comment
В основном это то, что означает устаревание, что чего-то следует избегать, потому что это может быть удалено в будущем. С помощью атрибута компилятор должен добавлять предупреждение всякий раз, когда вызывается устаревшая функция, и помогать пользователям этой функции находить эти местоположения и заменять вызовы до того, как старая функция будет удалена. Если это какой-то публичный API, то в документации также должно быть указано, что функция будет удалена в этой версии или к этой дате. Эта информация также может быть включена в атрибут причины устаревания.   -  person Some programmer dude    schedule 04.10.2017
comment
Да, я это понимаю, я прошу способ заменить мои старые вызовы функций новыми, потому что предупреждений слишком много, и я не хочу делать их все вручную, я прошу эффективный способ заменить устаревшие методы на новые   -  person Michel Jiang    schedule 04.10.2017
comment
И для этого единственным возможным ответом является функция поиска-замены в вашем редакторе.   -  person Some programmer dude    schedule 04.10.2017
comment
Вы можете выполнить замену автоматически с помощью clang-tidy.   -  person Jarod42    schedule 04.10.2017
comment
@ Jarod42 Спасибо, я посмотрю на это.   -  person Michel Jiang    schedule 04.10.2017


Ответы (3)


Измените старую функцию, чтобы она вызывала новую с этим аргументом, равным true (конечно, объявите новую над старой):

 // Deprecated method
 myFunction(char* firstParam, char* secondParam = NULL)
 {
     myFunction(firstParam, true, secondParam);
 }

Вероятно, вы также можете встроить его, чтобы компилятор буквально изменил код для вас, где это уместно :)

person Rob    schedule 04.10.2017
comment
Мне нравится этот ответ, но устаревшие методы в какой-то момент будут удалены, и тогда это больше не будет работать. - person Michel Jiang; 04.10.2017
comment
@MichelJiang, это удалит старый метод, поскольку вы бы заменили его. но, как было предложено выше, вы можете добавить к нему маркер [[deprecated]] или в MSDEV __declspec(deprecated), чтобы предупредить во время компиляции, где код использует старый способ, и заменить его по мере продвижения. - person Rob; 04.10.2017
comment
Спасибо, я думаю, что могу плохо объясняться в вопросе, но я хочу избежать замены функций вручную, мой компилятор уже предупреждает меня о том, что функции устарели и что я должен их изменить, я больше ищу способ автоматически заменить их в коде :) Но я попробую то, что вы предлагаете, и посмотрю, поможет ли это - person Michel Jiang; 04.10.2017

Вы можете сделать это с помощью нашего набора инструментов для реинжиниринга программного обеспечения DMS, используя преобразования источника в источник DMS.

DMS выполняет синтаксический анализ (C++17/VisualStudio2015) исходного кода в AST, применяет преобразования между исходными кодами, которые изменяют дерево, и результирующий AST распечатывается для повторной генерации (модифицированного) исходного кода. Это позволяет надежно автоматизировать изменения кода в больших базах кода.

Правила перезаписи DMS для примеров OP будут выглядеть так:

rule add_true_to_hello_world()
    :functioncall->functioncall
    = "myFunction( \"hello\", \"world\");"
    -> "myFunction( \"hello\", true, \"world\");";

rule add_true_to_call_with_literal_string(s: STRING)
    : functioncall->functioncall
    = "myFunction(\s)"
    -> "myFunction(\s, true);"

rule add_true_when_char_star(i:IDENTIFIER,s:STRING, a:argument):
     :functioncall->functioncall
     = "\i(\s,\a);"
     -> "\i(\s, true, \a)"
     if IsCharStart(a);

ruleset replace_deprecated_calls =
    { add_true_to_hello_world,
      add_true_to_call_with_literal_string,
      add_true_when_char_star
    }

Краткое пояснение: правила имеют вид

rule name(metavariable): syntaxclass->syntaxclass
  lefthandside -> righthandside  if condition ;

У правил есть имена, поэтому люди и наборы правил могут удобно обращаться к ним; иногда могут быть тысячи правил для выполнения очень сложных преобразований. У правила есть параметры, указывающие, какие метапеременные (обозначаемые как \v) разрешены внутри правила. Обозначение «вызов функции->вызов функции» означает, что мы преобразуем вызовы функций в вызовы функций, а не во что-то еще. Кавычки вокруг текста C++ — это метакавычки, отделяющие текст C++ от текста правил DMS, из-за чего нам приходится экранировать кавычки фактических литеральных строк C++ с помощью \". [Да, возможно, мы разработали DMS для этого случай без экранирования; не всегда может быть достаточно умным].

Набор правил просто группирует правила, чтобы все они могли применяться как группа. Не показан тривиальный вызов DMS для применения набора правил.

Подробнее о синтаксисе правил можно прочитать по ссылке выше.

Я реализовал его правила иначе, чем выразился ОП. Его примеры показывают только вызов функции как оператор (обратите внимание на «;» в его примерах), который изменяется, но он пишет в тексте, что хочет заменить все вызовы функций. Таким образом, эти правила касаются изменений вызовов функций, а не операторов. Первое правило OP, которое я закодировал точно так же, как он показал в своем примере; это будет работать только в том случае, если вызов функции имеет буквально эти литера строки аргумента. Его второе правило я обобщил, чтобы разрешить произвольную литеральную строку, а не просто «мир». Третье правило я обобщил, разрешив произвольное имя функции, и добавил проверку типа, как он указал.

Обратите внимание, что совпадения шаблонов на самом деле происходят в синтаксических деревьях, а не в необработанном тексте. DMS нельзя обмануть вызовами функций внутри комментариев или другими пробелами/форматированием.

person Ira Baxter    schedule 11.10.2017

Как насчет использования «Редактировать | Найти и заменить | Заменить в файлах»? Замените "Hello", world на "Hello", true, world

person René AD    schedule 04.10.2017
comment
Это не сработает в случае, когда он уже использует новую сигнатуру функции... - person Michel Jiang; 04.10.2017
comment
Я добавлю, что это не будет работать, если другой объект, который может иметь похожие имена функций, тоже. Лучше использовать IDE, которая имеет функцию рефакторинга, где она будет соответствовать только символам, которые компилируются, чтобы быть вызовом этой функции с или без необязательный/по умолчанию аргумент. - person Rob; 04.10.2017