Skip to content

Instantly share code, notes, and snippets.

@N-Dekker
Created October 8, 2018 16:15
Show Gist options
  • Save N-Dekker/0ec02c5c522c36fe00e0cd5ffd903aec to your computer and use it in GitHub Desktop.
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
/* 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