forked from OSchip/llvm-project
156 lines
4.9 KiB
C++
156 lines
4.9 KiB
C++
//===-- Core/ReplacementHandling.cpp --------------------------------------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
///
|
|
/// \file
|
|
/// \brief This file provides implementations for the ReplacementHandling class.
|
|
///
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "Core/ReplacementHandling.h"
|
|
#include "clang/Tooling/ReplacementsYaml.h"
|
|
#include "llvm/ADT/SmallString.h"
|
|
#include "llvm/Support/FileSystem.h"
|
|
#include "llvm/Support/Path.h"
|
|
#include "llvm/Support/Program.h"
|
|
#include <system_error>
|
|
|
|
using namespace llvm;
|
|
using namespace llvm::sys;
|
|
using namespace clang::tooling;
|
|
|
|
bool ReplacementHandling::findClangApplyReplacements(const char *Argv0) {
|
|
ErrorOr<std::string> CARPathOrErr =
|
|
findProgramByName("clang-apply-replacements");
|
|
if (!CARPathOrErr)
|
|
return true;
|
|
|
|
CARPath = *CARPathOrErr;
|
|
static int StaticSymbol;
|
|
std::string ClangModernizePath = fs::getMainExecutable(Argv0, &StaticSymbol);
|
|
SmallString<128> TestPath = path::parent_path(ClangModernizePath);
|
|
path::append(TestPath, "clang-apply-replacements");
|
|
if (fs::can_execute(Twine(TestPath)))
|
|
CARPath = TestPath.str();
|
|
|
|
return !CARPath.empty();
|
|
}
|
|
|
|
StringRef ReplacementHandling::useTempDestinationDir() {
|
|
DestinationDir = generateTempDir();
|
|
return DestinationDir;
|
|
}
|
|
|
|
void ReplacementHandling::enableFormatting(StringRef Style,
|
|
StringRef StyleConfigDir) {
|
|
DoFormat = true;
|
|
FormatStyle = Style;
|
|
this->StyleConfigDir = StyleConfigDir;
|
|
}
|
|
|
|
bool ReplacementHandling::serializeReplacements(
|
|
const TUReplacementsMap &Replacements) {
|
|
assert(!DestinationDir.empty() && "Destination directory not set");
|
|
|
|
bool Errors = false;
|
|
|
|
for (TUReplacementsMap::const_iterator I = Replacements.begin(),
|
|
E = Replacements.end();
|
|
I != E; ++I) {
|
|
SmallString<128> ReplacementsFileName;
|
|
SmallString<64> Error;
|
|
bool Result = generateReplacementsFileName(DestinationDir,
|
|
I->getValue().MainSourceFile,
|
|
ReplacementsFileName, Error);
|
|
if (!Result) {
|
|
errs() << "Failed to generate replacements filename:" << Error << "\n";
|
|
Errors = true;
|
|
continue;
|
|
}
|
|
|
|
std::error_code EC;
|
|
raw_fd_ostream ReplacementsFile(ReplacementsFileName, EC, fs::F_None);
|
|
if (EC) {
|
|
errs() << "Error opening file: " << EC.message() << "\n";
|
|
Errors = true;
|
|
continue;
|
|
}
|
|
yaml::Output YAML(ReplacementsFile);
|
|
YAML << const_cast<TranslationUnitReplacements &>(I->getValue());
|
|
}
|
|
return !Errors;
|
|
}
|
|
|
|
bool ReplacementHandling::applyReplacements() {
|
|
SmallVector<const char *, 8> Argv;
|
|
Argv.push_back(CARPath.c_str());
|
|
std::string Style = "--style=" + FormatStyle;
|
|
std::string StyleConfig = "--style-config=" + StyleConfigDir;
|
|
if (DoFormat) {
|
|
Argv.push_back("--format");
|
|
Argv.push_back(Style.c_str());
|
|
if (!StyleConfigDir.empty())
|
|
Argv.push_back(StyleConfig.c_str());
|
|
}
|
|
Argv.push_back("--remove-change-desc-files");
|
|
Argv.push_back(DestinationDir.c_str());
|
|
|
|
// Argv array needs to be null terminated.
|
|
Argv.push_back(nullptr);
|
|
|
|
std::string ErrorMsg;
|
|
bool ExecutionFailed = false;
|
|
int ReturnCode = ExecuteAndWait(CARPath.c_str(), Argv.data(),
|
|
/* env */ nullptr, /* redirects */ nullptr,
|
|
/* secondsToWait */ 0, /* memoryLimit */ 0,
|
|
&ErrorMsg, &ExecutionFailed);
|
|
if (ExecutionFailed || !ErrorMsg.empty()) {
|
|
errs() << "Failed to launch clang-apply-replacements: " << ErrorMsg << "\n";
|
|
errs() << "Command Line:\n";
|
|
for (const char **I = Argv.begin(), **E = Argv.end(); I != E; ++I) {
|
|
if (*I)
|
|
errs() << *I << "\n";
|
|
}
|
|
return false;
|
|
}
|
|
|
|
if (ReturnCode != 0) {
|
|
errs() << "clang-apply-replacements failed with return code " << ReturnCode
|
|
<< "\n";
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
std::string ReplacementHandling::generateTempDir() {
|
|
SmallString<128> Prefix;
|
|
path::system_temp_directory(true, Prefix);
|
|
path::append(Prefix, "clang-modernize");
|
|
SmallString<128> Result;
|
|
fs::createUniqueDirectory(Twine(Prefix), Result);
|
|
return Result.str();
|
|
}
|
|
|
|
bool ReplacementHandling::generateReplacementsFileName(
|
|
StringRef DestinationDir, StringRef MainSourceFile,
|
|
SmallVectorImpl<char> &Result, SmallVectorImpl<char> &Error) {
|
|
|
|
Error.clear();
|
|
SmallString<128> Prefix = DestinationDir;
|
|
path::append(Prefix, path::filename(MainSourceFile));
|
|
if (std::error_code EC =
|
|
fs::createUniqueFile(Prefix + "_%%_%%_%%_%%_%%_%%.yaml", Result)) {
|
|
const std::string &Msg = EC.message();
|
|
Error.append(Msg.begin(), Msg.end());
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|