Я ищу инструмент Windows GUI/командной строки или подключаемый модуль Visual Studio, где я могу автоматизировать извлечение блоков кода C++, добавить некоторые шаги рефакторинга/переименования и вставить его в какой-либо другой файл C++. После того, как это настроено, я хочу синхронизировать источник/назначение блоков кода и/или проверять различия.
РЕДАКТИРОВАТЬ : я стараюсь, чтобы в моем проекте все было как можно проще. Поэтому я надеюсь на решение с низким уровнем сложности. Я бы предпочел решение, использующее несколько однозадачных инструментов (возможно, уже поставляемых с моей ОС/IDE/SCM), а не многофункциональный многозадачный инструмент, созданный для обработки гораздо большего количества задач.
Чтобы привести очень простой пример - и я не уверен, что рассматриваемому инструменту даже нужно понимать синтаксис C++ для выполнения чего-то подобного:
OldClass.cpp
class OldClass
{
public:
...
void MyFunctionToReuse()
{
...
// Start OldClass::MyFunctionToReuse() block
mVarOldName = ...;
// End OldClass::MyFunctionToReuse() block
...
}
};
NewClass.cpp
class NewClass
{
public:
...
void SomeFunction()
{
...
// Start OldClass::MyFunctionToReuse() block
// file OldClass.cpp, line 100 - 110
// renamed mVarOldName to mVarNewName
mVarNewName = ...;
// End OldClass::MyFunctionToReuse() block
...
}
};
Я вижу четыре возможных способа сделать это:
OldClass
вNewClass
У меня есть длительный проект C++ модели/представления/контроллера, в котором часть представления теперь должна быть заменена/перемещена в отдельное приложение. Старая кодовая база может использоваться повторно на 80%, но я не могу использовать классы в том виде, в каком они есть сейчас. Итак, я сейчас нахожусь в точке, где я отхожу от своего старого проекта, чтобы начать новый код.
Но старый проект все равно будет поддерживаться в течение нескольких лет. Поэтому, если я начну с необходимых изменений для / рефакторинга нового проекта, я ищу что-то, чтобы синхронизировать оба потока/ветви кода (в основном для исправления ошибок).
И огромные изменения в старом продукте — это только крайняя мера, потому что это означало бы — даже при хорошем покрытии кода модульными тестами — повторное тестирование основных частей поставляемого в настоящее время продукта.
Списки функций
В итоге я использовал предварительный компилятор Visual Studio для перевода моих исходных файлов с помощью определений макросов. На втором этапе я использую PowerShell для замены/добавления некоторых специальных символов форматирования, которые прекомпилятор удалит/проигнорирует.
Поскольку я использую CMake, вот протестированный мной скрипт:
cmake_minimum_required(VERSION 2.8.9)
project(CppTranslationDemo)
if(NOT MSVC_VERSION GREATER 1699)
message(FATAL_ERROR "Only tested with VS2012 or above")
endif()
set(
inFiles
OldClass.cpp
)
unset(outFiles)
find_program(
POWERSHELL_EXE
NAMES powershell.exe
PATHS C:/Windows/System32
PATH_SUFFIXES WindowsPowerShell/v1.0
)
if (NOT POWERSHELL_EXE)
message(FATAL_ERROR "Couldn't find powershell.exe")
endif()
foreach(_file IN ITEMS ${inFiles})
file(TO_NATIVE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/${_file}" _file_native_path)
file(TO_NATIVE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/TranslationMacros.h" _macro_file_native_path)
file(TO_NATIVE_PATH "${CMAKE_CXX_COMPILER}" _compiler_native_path)
get_filename_component(_file_name "${_file}" NAME)
get_filename_component(_file_ext "${_file}" EXT)
string(REPLACE "Old" "New" _file_name "${_file_name}")
set(_out_file "${CMAKE_BINARY_DIR}/${_file_name}")
set(
_powershell_cmd_list
"$i = 1;"
# NOTE: increase column width to prevent word wrap after 80 chararcters
"$Host.UI.RawUI.BufferSize = New-Object Management.Automation.Host.Size (500, 25);"
"$nl = [Environment]::NewLine;"
"& '${_compiler_native_path}' /nologo /EP /C /FI${_macro_file_native_path} ${_file_native_path}"
"|"
"Foreach-Object"
"{"
"$_"
"-replace '@NL@', $nl"
"-replace '@TAB@', ' '"
"-replace '@H@', '#'"
"-replace '@C@', '//'"
"-replace '@CB@', '/*'"
"-replace '@CE@', '*/'"
"-replace '@.*@', ''"
"}"
"|"
"where"
"{"
"if ($_ -eq '')"
"{"
"$i++;"
"}"
"else"
"{"
"$i = 0;"
"}"
"($i -lt 2)"
"};"
"exit $LASTEXITCODE"
)
string(REGEX REPLACE ";([^;])" " \\1" _powershell_cmd "${_powershell_cmd_list}")
add_custom_command(
OUTPUT ${_out_file}
COMMAND "${POWERSHELL_EXE}" -Command "${_powershell_cmd}" 1> "${_out_file}"
DEPENDS ${_file}
TranslationMacros.h
COMMENT "${_out_file}"
)
list(APPEND outFiles "${_out_file}")
endforeach()
add_custom_target(
${PROJECT_NAME}
DEPENDS ${outFiles}
SOURCES
TranslationMacros.h
${inFiles}
)
set_source_files_properties(${outFiles} PROPERTIES GENERATED 1)
add_library(
${PROJECT_NAME}Test
${outFiles}
)
add_dependencies(
${PROJECT_NAME}Test
${PROJECT_NAME}
)
В сочетании с
ПереводMacros.h
#define OldClass NewClass
#define MyFunctionToReuse SomeFunction
#define mVarOldName mVarNewName
Переводит
OldClass.cpp
class OldClass
{
public:
OldClass() : mVarOldName(0) {}
void MyFunctionToReuse()
{
// Some test comment
mVarOldName = 1;
}
int mVarOldName;
};
В
NewClass.cpp
class NewClass
{
public:
NewClass() : mVarNewName(0) {}
void SomeFunction()
{
// Some test comment
mVarNewName = 1;
}
int mVarNewName;
};
использованная литература
Визуальная студия
PowerShell
Ира Бакстер
Флориан
Ира Бакстер
Флориан
Томас Веллер