0.6.3
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 116 of file clang_tool.cc.

121 : diagram_type_{diagram_type}
122 , diagram_name_{std::move(diagram_name)}
123 , compilations_{compilation_database}
124 , source_paths_{source_paths}
125 , quiet_{quiet}
126 , pch_container_ops_{std::make_shared<PCHContainerOperations>()}
127 , overlay_fs_{new llvm::vfs::OverlayFileSystem(
128 llvm::vfs::getRealFileSystem())}
129 , inmemory_fs_{new llvm::vfs::InMemoryFileSystem}
130 , files_{new FileManager(FileSystemOptions(), overlay_fs_)}
131 , diag_consumer_{std::make_unique<diagnostic_consumer>(relative_to)}
132 , diag_opts_{new clang::DiagnosticOptions}
133{
134 overlay_fs_->pushOverlay(inmemory_fs_);
135
136 append_arguments_adjuster(getClangStripOutputAdjuster());
137 append_arguments_adjuster(getClangSyntaxOnlyAdjuster());
138 append_arguments_adjuster(getClangStripDependencyFileAdjuster());
139}

◆ ~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 143 of file clang_tool.cc.

144{
146 combineAdjusters(std::move(args_adjuster_), std::move(Adjuster));
147}

◆ run()

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

Definition at line 149 of file clang_tool.cc.

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

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 107 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: