-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[clang-include-cleaner] Fix incorrect directory issue for writing files #111375
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
23b90bb
eef397c
2409d6f
0c9477d
dec9be8
b39f36e
3a0f02e
c65d828
11f78a3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -173,6 +173,7 @@ class Action : public clang::ASTFrontendAction { | |
| if (!HTMLReportPath.empty()) | ||
| writeHTML(); | ||
|
|
||
| // Source File's path relative to compilation database. | ||
| llvm::StringRef Path = | ||
| SM.getFileEntryRefForID(SM.getMainFileID())->getName(); | ||
| assert(!Path.empty() && "Main file path not known?"); | ||
|
|
@@ -280,6 +281,42 @@ std::function<bool(llvm::StringRef)> headerFilter() { | |
| }; | ||
| } | ||
|
|
||
| llvm::ErrorOr<std::string> getCurrentWorkingDirectory() { | ||
| llvm::SmallString<256> CurrentPath; | ||
| if (const std::error_code EC = llvm::sys::fs::current_path(CurrentPath)) | ||
| return llvm::ErrorOr<std::string>(EC); | ||
| return std::string(CurrentPath.str()); | ||
| } | ||
|
|
||
| std::optional<std::string> | ||
| adjustCompilationPath(const std::string &Filename, const std::string &Directory, | ||
| const std::string &CurrentWorkingDirectory) { | ||
| if (llvm::sys::path::is_absolute(Filename)) { | ||
| // If the file path is already absolute, use it as is. | ||
| return Filename; | ||
| } | ||
|
|
||
| auto Sept = llvm::sys::path::get_separator().str(); | ||
| // First, try to find the file based on the compilation database. | ||
| std::string FilePath = Directory + Sept + Filename; | ||
| // Check if it is writable. | ||
| if (llvm::sys::fs::access(FilePath, llvm::sys::fs::AccessMode::Write) != | ||
| std::error_code()) { | ||
| // If not, try to find the file based on the current working | ||
| // directory, as some Bazel invocations may not set the compilation | ||
| // invocation's filesystem as non-writable. In such cases, we can | ||
| // find the file based on the current working directory. | ||
| FilePath = | ||
| static_cast<std::string>(CurrentWorkingDirectory) + Sept + Filename; | ||
| if (llvm::sys::fs::access(FilePath, llvm::sys::fs::AccessMode::Write) != | ||
| std::error_code()) { | ||
| llvm::errs() << "Failed to find a writable path for " << Filename << "\n"; | ||
| return std::nullopt; | ||
| } | ||
| } | ||
| return FilePath; | ||
| } | ||
|
|
||
| } // namespace | ||
| } // namespace include_cleaner | ||
| } // namespace clang | ||
|
|
@@ -305,7 +342,32 @@ int main(int argc, const char **argv) { | |
| } | ||
| } | ||
|
|
||
| clang::tooling::ClangTool Tool(OptionsParser->getCompilations(), | ||
| auto &CompilationDatabase = OptionsParser->getCompilations(); | ||
|
||
| // Mapping of edited file paths to their actual paths. | ||
| std::map<std::string, std::string> EditedFilesToActualFiles; | ||
| if (Edit) { | ||
|
||
| std::vector<clang::tooling::CompileCommand> Commands = | ||
| CompilationDatabase.getAllCompileCommands(); | ||
| auto CurrentWorkingDirectory = getCurrentWorkingDirectory(); | ||
| // if (CurrentWorkingDirectory.get() | ||
| if (auto EC = CurrentWorkingDirectory.getError()) { | ||
| llvm::errs() << "Failed to get current working directory: " | ||
| << EC.message() << "\n"; | ||
| return 1; | ||
| } | ||
|
|
||
| for (const auto &Command : Commands) { | ||
| auto AdjustedFilePath = adjustCompilationPath( | ||
| Command.Filename, Command.Directory, CurrentWorkingDirectory.get()); | ||
| if (!AdjustedFilePath.has_value()) { | ||
| // We already printed an error message. | ||
| return 1; | ||
| } | ||
| EditedFilesToActualFiles[Command.Filename] = AdjustedFilePath.value(); | ||
| } | ||
| } | ||
|
|
||
| clang::tooling::ClangTool Tool(CompilationDatabase, | ||
| OptionsParser->getSourcePathList()); | ||
|
|
||
| auto HeaderFilter = headerFilter(); | ||
|
|
@@ -316,6 +378,15 @@ int main(int argc, const char **argv) { | |
| if (Edit) { | ||
| for (const auto &NameAndContent : Factory.editedFiles()) { | ||
| llvm::StringRef FileName = NameAndContent.first(); | ||
| auto AdjustedFilePathIter = EditedFilesToActualFiles.find(FileName.str()); | ||
| if (AdjustedFilePathIter != EditedFilesToActualFiles.end()) { | ||
| FileName = AdjustedFilePathIter->second; | ||
| } else { | ||
| llvm::errs() << "Failed to find the actual path for " << FileName | ||
| << "\n"; | ||
| ++Errors; | ||
| } | ||
|
|
||
| const std::string &FinalCode = NameAndContent.second; | ||
| if (auto Err = llvm::writeToOutput( | ||
| FileName, [&](llvm::raw_ostream &OS) -> llvm::Error { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we keep reporting with abs-paths here, i.e:
This way we can recognize these paths in main and perform the mapping accordingly.