Created
October 8, 2018 16:15
-
-
Save N-Dekker/0ec02c5c522c36fe00e0cd5ffd903aec to your computer and use it in GitHub Desktop.
Script to remove underscores in test names and convert them to CamelCase, for patch http://review.source.kitware.com/#/c/23788/1
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ | |
/* Script to remove underscores in test names and convert them to CamelCase. | |
* Used for patch "BUG: Removed underscores from GTest test names", | |
* http://review.source.kitware.com/#/c/23788/1 | |
* | |
* Initial version by Niels Dekker, LKEB, Leiden University Medical Center, 2018 | |
*/ | |
#include <cassert> | |
#include <cctype> | |
#include <deque> | |
#include <experimental/filesystem> | |
#include <fstream> | |
#include <iostream> | |
#include <cstring> | |
#include <string> | |
using namespace std::experimental::filesystem::v1; | |
namespace | |
{ | |
using Lines = std::deque<std::string>; | |
auto ReadFile(const path& filePath) | |
{ | |
Lines result; | |
std::ifstream inputFileStream{ filePath }; | |
std::string line; | |
while (std::getline(inputFileStream, line)) | |
{ | |
result.push_back(line); | |
} | |
return result; | |
} | |
void WriteFile(const path& filePath, const Lines& lines) | |
{ | |
std::ofstream outputFileStream{ filePath }; | |
for (const auto& line : lines) | |
{ | |
outputFileStream << line << '\n'; | |
} | |
} | |
struct Statistics | |
{ | |
unsigned numberOfModifiedLines; | |
}; | |
Statistics ModifyLines(Lines& lines) | |
{ | |
Statistics statistics = {}; | |
auto className = std::string{}; | |
auto publicLineNumber = Lines::size_type{}; | |
auto isInsideCodeSection = false; | |
for (auto lineNumber = Lines::size_type{}; lineNumber < lines.size(); ++lineNumber) | |
{ | |
bool isLineModified = false; | |
auto& line = lines[lineNumber]; | |
const auto numberOfChars = line.size(); | |
constexpr char testCodePrefix[] = "TEST("; | |
// For example, "TEST(ConnectedImageNeighborhoodShape, GetNumberOfOffsets_returns_expected_value)" | |
if ((numberOfChars > sizeof(testCodePrefix)) && | |
(line.back() == ')') && | |
std::equal(std::begin(testCodePrefix), std::end(testCodePrefix) - 1, line.cbegin()) && | |
(line.find('\"') == std::string::npos)) | |
{ | |
auto i = numberOfChars - 1; | |
while ( --i > 0 ) | |
{ | |
const char currentChar = line[i]; | |
if (currentChar == '_' || currentChar == ' ' || currentChar == ',') | |
{ | |
char& nextChar = line[i + 1]; | |
if ((nextChar >= 'a') && (nextChar <= 'z')) | |
{ | |
nextChar += ('A' - 'a'); | |
isLineModified = true; | |
} | |
if (currentChar == '_') | |
{ | |
line.erase(i, std::string::size_type{ 1u }); | |
isLineModified = true; | |
} | |
else | |
{ | |
// currentChar == ' ' or currentChar == ',' | |
break; | |
} | |
} | |
} | |
if (isLineModified) | |
{ | |
++statistics.numberOfModifiedLines; | |
} | |
} | |
} | |
return statistics; | |
} | |
auto ProcessFile(const path& filePath) | |
{ | |
auto lines = ReadFile(filePath); | |
const auto statistics = ModifyLines(lines); | |
if (statistics.numberOfModifiedLines > 0) | |
{ | |
WriteFile(filePath, lines); | |
} | |
return statistics; | |
} | |
void ProcessDirectory(const path& directoryPath) | |
{ | |
Statistics statistics = {}; | |
const recursive_directory_iterator end; | |
unsigned numberOfModifiedFiles = 0; | |
for (recursive_directory_iterator it{ directoryPath }; it != end; ++it) | |
{ | |
const auto& path = it->path(); | |
const auto& extension = path.extension(); | |
if ((!extension.empty()) && | |
(extension.string() == ".cxx") && | |
is_regular_file(path)) | |
{ | |
const auto statisticsPerFile = ProcessFile(path); | |
if (statisticsPerFile.numberOfModifiedLines > 0) | |
{ | |
++numberOfModifiedFiles; | |
statistics.numberOfModifiedLines += statisticsPerFile.numberOfModifiedLines; | |
std::cout << numberOfModifiedFiles << ' ' << statisticsPerFile.numberOfModifiedLines << ' ' << path << std::endl; | |
} | |
} | |
} | |
std::cout | |
<< "numberOfModifiedFiles:\t" << numberOfModifiedFiles | |
<< "\nNumberOfModifiedLines:\t" << statistics.numberOfModifiedLines | |
<< std::endl; | |
} | |
} | |
int main(int argc, char** argv) | |
{ | |
if (argc != 2) | |
{ | |
std::cout << | |
"Please specify the source directory path as command-line argument." | |
"\nNote: This program will modify the source files in-place!!!" | |
<< std::endl; | |
} | |
else | |
{ | |
if (argv == nullptr) | |
{ | |
return EXIT_FAILURE; | |
} | |
const char* const arg = argv[1]; | |
if (arg == nullptr) | |
{ | |
return EXIT_FAILURE; | |
} | |
ProcessDirectory(arg); | |
} | |
std::cout << "Press anything to continue" << std::endl; | |
std::cin.get(); | |
return EXIT_SUCCESS; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment