0.6.0
C++ to UML diagram generator based on Clang
Loading...
Searching...
No Matches
Public Member Functions | Private Attributes | List of all members
clanguml::generators::clang_tool Class Reference

Custom ClangTool implementation to enable better error handling. More...

Detailed Description

Custom ClangTool implementation to enable better error handling.

Definition at line 71 of file clang_tool.h.

#include <clang_tool.h>

Public Member Functions

 clang_tool (common::model::diagram_t diagram_type, std::string diagram_name, const clanguml::common::compilation_database &compilations, const std::vector< std::string > &source_paths, std::filesystem::path relative_to, bool quiet)
 
 ~clang_tool ()
 
void append_arguments_adjuster (clang::tooling::ArgumentsAdjuster Adjuster)
 
void run (ToolAction *Action)
 

Private Attributes

const common::model::diagram_t diagram_type_
 
const std::string diagram_name_
 
const clanguml::common::compilation_databasecompilations_
 
std::vector< std::string > source_paths_
 
bool quiet_
 
std::shared_ptr< PCHContainerOperations > pch_container_ops_
 
llvm::IntrusiveRefCntPtr< llvm::vfs::OverlayFileSystem > overlay_fs_
 
llvm::IntrusiveRefCntPtr< llvm::vfs::InMemoryFileSystem > inmemory_fs_
 
llvm::IntrusiveRefCntPtr< FileManager > files_
 
std::vector< std::pair< StringRef, StringRef > > memory_mapped_files_
 
llvm::StringSet visited_working_directories_
 
ArgumentsAdjuster args_adjuster_
 
std::unique_ptr< diagnostic_consumerdiag_consumer_
 
llvm::IntrusiveRefCntPtr< clang::DiagnosticOptions > diag_opts_
 

Constructor & Destructor Documentation

◆ clang_tool()

clanguml::generators::clang_tool::clang_tool ( common::model::diagram_t  diagram_type,
std::string  diagram_name,
const clanguml::common::compilation_database compilations,
const std::vector< std::string > &  source_paths,
std::filesystem::path  relative_to,
bool  quiet 
)

Definition at line 108 of file clang_tool.cc.

113 : diagram_type_{diagram_type}
114 , diagram_name_{std::move(diagram_name)}
115 , compilations_{compilation_database}
116 , source_paths_{source_paths}
117 , quiet_{quiet}
118 , pch_container_ops_{std::make_shared<PCHContainerOperations>()}
119 , overlay_fs_{new llvm::vfs::OverlayFileSystem(
120 llvm::vfs::getRealFileSystem())}
121 , inmemory_fs_{new llvm::vfs::InMemoryFileSystem}
122 , files_{new FileManager(FileSystemOptions(), overlay_fs_)}
123 , diag_consumer_{std::make_unique<diagnostic_consumer>(relative_to)}
124 , diag_opts_{new clang::DiagnosticOptions}
125{
126 overlay_fs_->pushOverlay(inmemory_fs_);
127
128 append_arguments_adjuster(getClangStripOutputAdjuster());
129 append_arguments_adjuster(getClangSyntaxOnlyAdjuster());
130 append_arguments_adjuster(getClangStripDependencyFileAdjuster());
131}

◆ ~clang_tool()

clanguml::generators::clang_tool::~clang_tool ( )
default

Member Function Documentation

◆ append_arguments_adjuster()

void clanguml::generators::clang_tool::append_arguments_adjuster ( clang::tooling::ArgumentsAdjuster  Adjuster)

Definition at line 135 of file clang_tool.cc.

136{
138 combineAdjusters(std::move(args_adjuster_), std::move(Adjuster));
139}

◆ run()

void clanguml::generators::clang_tool::run ( ToolAction *  Action)

Definition at line 141 of file clang_tool.cc.

142{
143 static int static_symbol;
144
145 std::vector<std::string> absolute_tu_paths;
146 absolute_tu_paths.reserve(source_paths_.size());
147 for (const auto &source_path : source_paths_) {
148 auto absolute_tu_path =
149 clang::tooling::getAbsolutePath(*overlay_fs_, source_path);
150 if (!absolute_tu_path) {
151 if (!quiet_) {
152 LOG_WARN("Skipping file {} in diagram {}. Could not resolve "
153 "absolute path for translation unit: {}",
154 source_path, diagram_name_,
155 llvm::toString(absolute_tu_path.takeError()));
156 }
157 continue;
158 }
159 absolute_tu_paths.emplace_back(std::move(*absolute_tu_path));
160 }
161
162 // Remember the working directory in case we need to restore it.
163 std::string initial_workdir;
164 if (auto current_workdir = overlay_fs_->getCurrentWorkingDirectory()) {
165 initial_workdir = std::move(*current_workdir);
166 }
167 else {
168 if (!quiet_)
169 LOG_ERROR("Could not get current working directory when generating "
170 "diagram '{}': {}",
171 diagram_name_, current_workdir.getError().message());
172 }
173
174 for (const auto &file : absolute_tu_paths) {
175 if (!quiet_)
176 LOG_INFO("Processing diagram '{}' translation unit: {}",
177 diagram_name_, file);
178
179 auto compile_commands_for_file = compilations_.getCompileCommands(file);
180
181 if (compile_commands_for_file.empty()) {
182 if (!quiet_)
183 LOG_WARN(
184 "Skipping file {} for diagram '{}'. Compilation command "
185 "not found.",
186 file, diagram_name_);
187 continue;
188 }
189
190 if (compile_commands_for_file.size() > 1 &&
192 LOG_WARN("Multiple compile commands detected for file '{}' in "
193 "diagram '{}' - using only the first one...",
194 file, diagram_name_);
195 }
196
197 for (auto &compile_command : compile_commands_for_file) {
198 if (overlay_fs_->setCurrentWorkingDirectory(
199 compile_command.Directory))
200 llvm::report_fatal_error("Cannot chdir into \"" +
201 Twine(compile_command.Directory) + "\"!");
202
203 // Now fill the in-memory VFS with the relative file mappings so it
204 // will have the correct relative paths. We never remove mappings
205 // but that should be fine.
206 if (visited_working_directories_.insert(compile_command.Directory)
207 .second) {
208 for (const auto &[file_name, file_content] :
210 if (!llvm::sys::path::is_absolute(file_name))
211 inmemory_fs_->addFile(file_name, 0,
212 llvm::MemoryBuffer::getMemBuffer(file_content));
213 }
214
215 auto command_line = compile_command.CommandLine;
216 if (args_adjuster_)
217 command_line =
218 args_adjuster_(command_line, compile_command.Filename);
219
220 assert(!command_line.empty());
221
222 inject_resource_dir(command_line, "clang_tool", &static_symbol);
223
224 ToolInvocation invocation(std::move(command_line), Action,
226 invocation.setDiagnosticConsumer(diag_consumer_.get());
227#if LLVM_VERSION_MAJOR > 13
228 invocation.setDiagnosticOptions(diag_opts_.get());
229#endif
230
231 if (!invocation.run() || diag_consumer_->failed) {
232 if (!initial_workdir.empty()) {
233 if (const auto ec = overlay_fs_->setCurrentWorkingDirectory(
234 initial_workdir);
235 ec)
236 if (!quiet_)
237 LOG_ERROR("Error when trying to restore working "
238 "directory: {}",
239 ec.message());
240 }
241
242 if (diag_consumer_ && diag_consumer_->failed) {
243 if (!(diag_consumer_->diagnostics.empty())) {
244 throw clang_tool_exception(diagram_type_, diagram_name_,
245 diag_consumer_->diagnostics,
246 to_string(diag_consumer_->diagnostics.back()));
247 }
248
249 throw clang_tool_exception(diagram_type_, diagram_name_,
250 diag_consumer_->diagnostics);
251 }
252
253 throw std::runtime_error(
254 fmt::format("Unknown error while processing {}", file));
255 }
256
258 break;
259 }
260 }
261
262 if (!initial_workdir.empty()) {
263 if (const auto ec =
264 overlay_fs_->setCurrentWorkingDirectory(initial_workdir))
265 if (!quiet_)
266 LOG_ERROR("Error when trying to restore working dir: {}",
267 ec.message());
268 }
269}

Member Data Documentation

◆ args_adjuster_

ArgumentsAdjuster clanguml::generators::clang_tool::args_adjuster_
private

Definition at line 103 of file clang_tool.h.

◆ compilations_

const clanguml::common::compilation_database& clanguml::generators::clang_tool::compilations_
private

Definition at line 87 of file clang_tool.h.

◆ diag_consumer_

std::unique_ptr<diagnostic_consumer> clanguml::generators::clang_tool::diag_consumer_
private

Definition at line 105 of file clang_tool.h.

◆ diag_opts_

llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> clanguml::generators::clang_tool::diag_opts_
private

Definition at line 106 of file clang_tool.h.

◆ diagram_name_

const std::string clanguml::generators::clang_tool::diagram_name_
private

Definition at line 86 of file clang_tool.h.

◆ diagram_type_

const common::model::diagram_t clanguml::generators::clang_tool::diagram_type_
private

Definition at line 85 of file clang_tool.h.

◆ files_

llvm::IntrusiveRefCntPtr<FileManager> clanguml::generators::clang_tool::files_
private

Definition at line 95 of file clang_tool.h.

◆ inmemory_fs_

llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> clanguml::generators::clang_tool::inmemory_fs_
private

Definition at line 94 of file clang_tool.h.

◆ memory_mapped_files_

std::vector< std::pair<StringRef , StringRef > > clanguml::generators::clang_tool::memory_mapped_files_
private

Definition at line 99 of file clang_tool.h.

◆ overlay_fs_

llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> clanguml::generators::clang_tool::overlay_fs_
private

Definition at line 93 of file clang_tool.h.

◆ pch_container_ops_

std::shared_ptr<PCHContainerOperations> clanguml::generators::clang_tool::pch_container_ops_
private

Definition at line 91 of file clang_tool.h.

◆ quiet_

bool clanguml::generators::clang_tool::quiet_
private

Definition at line 89 of file clang_tool.h.

◆ source_paths_

std::vector<std::string> clanguml::generators::clang_tool::source_paths_
private

Definition at line 88 of file clang_tool.h.

◆ visited_working_directories_

llvm::StringSet clanguml::generators::clang_tool::visited_working_directories_
private

Definition at line 101 of file clang_tool.h.


The documentation for this class was generated from the following files: