1919#include < map>
2020#include < ranges>
2121#include < set>
22+ #include < string>
23+ #include < unordered_set>
2224#include < vector>
2325
2426#include " converter/converter_lib.h"
2527#include " logging.h"
2628
2729namespace cpp2rust ::RulesLoader {
2830
29- namespace fs = std::filesystem;
30-
3131namespace {
3232
3333class RuleUsageCollector
3434 : public clang::RecursiveASTVisitor<RuleUsageCollector> {
3535public:
36- RuleUsageCollector (clang::Sema &sema, std::set<fs::path > &paths )
37- : ctx_(sema.Context), sema_(sema), paths_(paths ) {}
36+ RuleUsageCollector (clang::Sema &sema, std::unordered_set<std::string > &keys )
37+ : ctx_(sema.Context), sema_(sema), keys_(keys ) {}
3838
3939 bool shouldVisitTemplateInstantiations () const { return true ; }
4040
@@ -118,9 +118,9 @@ class RuleUsageCollector
118118 }
119119
120120private:
121- void AddKey (const fs::path &key) {
121+ void AddKey (const std::string &key) {
122122 if (!key.empty ()) {
123- paths_ .insert (key);
123+ keys_ .insert (key);
124124 }
125125 }
126126
@@ -216,12 +216,12 @@ class RuleUsageCollector
216216
217217 clang::ASTContext &ctx_;
218218 clang::Sema &sema_;
219- std::set<fs::path > &paths_ ;
219+ std::unordered_set<std::string > &keys_ ;
220220 llvm::DenseSet<const void *> seen_;
221221};
222222
223- const llvm::json::Object &LoadIndex (const fs ::path &path) {
224- static std::map<fs ::path, llvm::json::Object> indexes;
223+ const llvm::json::Object &LoadIndex (const std::filesystem ::path &path) {
224+ static std::map<std::filesystem ::path, llvm::json::Object> indexes;
225225 if (auto it = indexes.find (path); it != indexes.end ()) {
226226 return it->second ;
227227 }
@@ -244,8 +244,9 @@ const llvm::json::Object &LoadIndex(const fs::path &path) {
244244 return indexes.emplace (path, std::move (*index)).first ->second ;
245245}
246246
247- std::string BuildRulesBuffer (const fs::path &index_dir,
248- const std::set<fs::path> &paths, bool is_cxx) {
247+ std::string BuildRulesBuffer (const std::filesystem::path &index_dir,
248+ const std::unordered_set<std::string> &keys,
249+ bool is_cxx) {
249250 std::string out;
250251 for (const char *lang : {" c" , " cpp" }) {
251252 if (!is_cxx && lang == std::string (" cpp" )) {
@@ -255,8 +256,8 @@ std::string BuildRulesBuffer(const fs::path &index_dir,
255256 auto common = index.getString (" common" );
256257 auto rules = index.getObject (" rules" );
257258 std::set<std::string> namespaces;
258- for (const auto &path : paths ) {
259- auto entries = rules->getArray (path. generic_string () );
259+ for (const auto &key : keys ) {
260+ auto entries = rules->getArray (key );
260261 if (!entries) {
261262 continue ;
262263 }
@@ -275,12 +276,12 @@ std::string BuildRulesBuffer(const fs::path &index_dir,
275276
276277} // namespace
277278
278- static fs::path Component (std::string name) {
279+ static std::string Component (std::string name) {
279280 std::ranges::replace (name, ' /' , ' _' );
280281 return name;
281282}
282283
283- static fs::path NamePath (const clang::NamedDecl *decl) {
284+ static std::string NameKey (const clang::NamedDecl *decl) {
284285 std::vector<std::string> scopes;
285286 for (auto scope = decl->getDeclContext (); scope; scope = scope->getParent ()) {
286287 if (auto ns = llvm::dyn_cast<clang::NamespaceDecl>(scope)) {
@@ -294,14 +295,14 @@ static fs::path NamePath(const clang::NamedDecl *decl) {
294295 scopes.push_back (enum_decl->getNameAsString ());
295296 }
296297 }
297- fs::path path ;
298+ std::string key ;
298299 for (const auto &scope : scopes | std::views::reverse) {
299- path / = Component (scope);
300+ key + = Component (scope) + ' / ' ;
300301 }
301- return path / Component (decl->getNameAsString ());
302+ return key + Component (decl->getNameAsString ());
302303}
303304
304- fs::path ClassKey (const clang::NamedDecl *decl) {
305+ std::string ClassKey (const clang::NamedDecl *decl) {
305306 if (auto alias = llvm::dyn_cast<clang::TypedefNameDecl>(decl)) {
306307 auto tag = alias->getUnderlyingType ()->getAsTagDecl ();
307308 if (!tag) {
@@ -320,7 +321,7 @@ fs::path ClassKey(const clang::NamedDecl *decl) {
320321 return {};
321322 }
322323 }
323- return NamePath (decl);
324+ return NameKey (decl);
324325}
325326
326327std::string MemberName (clang::DeclarationName name) {
@@ -330,35 +331,39 @@ std::string MemberName(clang::DeclarationName name) {
330331 return name.getAsString ();
331332}
332333
333- fs::path MemberKey (const fs::path &class_key, const std::string &name) {
334+ std::string MemberKey (const std::string &class_key, const std::string &name) {
334335 if (class_key.empty ()) {
335336 return {};
336337 }
337- return class_key / Component (name);
338+ return class_key + ' /' + Component (name);
339+ }
340+
341+ std::string ConstructorKey (const std::string &class_key) {
342+ return MemberKey (class_key, class_key.substr (class_key.rfind (' /' ) + 1 ));
338343}
339344
340- fs::path FunctionKey (const clang::FunctionDecl *decl) {
345+ std::string FunctionKey (const clang::FunctionDecl *decl) {
341346 if (auto method = llvm::dyn_cast<clang::CXXMethodDecl>(decl)) {
342347 auto class_key = ClassKey (method->getParent ());
343348 if (llvm::isa<clang::CXXConstructorDecl>(method)) {
344- return MemberKey (class_key, class_key. filename (). string () );
349+ return ConstructorKey (class_key);
345350 }
346351 return MemberKey (class_key, MemberName (method->getDeclName ()));
347352 }
348- return NamePath (decl);
353+ return NameKey (decl);
349354}
350355
351- fs::path DeclKey (const clang::NamedDecl *decl) {
356+ std::string DeclKey (const clang::NamedDecl *decl) {
352357 if (auto fn = decl->getAsFunction ()) {
353358 return FunctionKey (fn);
354359 }
355360 if (auto record = llvm::dyn_cast<clang::RecordDecl>(decl->getDeclContext ())) {
356361 return MemberKey (ClassKey (record), MemberName (decl->getDeclName ()));
357362 }
358- return NamePath (decl);
363+ return NameKey (decl);
359364}
360365
361- fs::path ExprKey (clang::ASTContext &ctx, const clang::Expr *expr) {
366+ std::string ExprKey (clang::ASTContext &ctx, const clang::Expr *expr) {
362367 expr = expr->IgnoreParenImpCasts ();
363368 if (llvm::isa<clang::IntegerLiteral>(expr) &&
364369 expr->getBeginLoc ().isMacroID ()) {
@@ -388,7 +393,7 @@ fs::path ExprKey(clang::ASTContext &ctx, const clang::Expr *expr) {
388393 return {};
389394}
390395
391- fs::path TypeKey (clang::QualType type) {
396+ std::string TypeKey (clang::QualType type) {
392397 if (auto decltype_type =
393398 llvm::dyn_cast<clang::DecltypeType>(type.getTypePtr ())) {
394399 type = decltype_type->getUnderlyingType ();
@@ -429,17 +434,16 @@ void PragmaHandler::HandlePragma(clang::Preprocessor &PP,
429434 }
430435 }
431436 ctx.setTraversalScope (user_decls);
432- std::set<fs::path> selected ;
433- RuleUsageCollector collector (CI_ .getSema (), selected );
437+ std::unordered_set<std::string> keys ;
438+ RuleUsageCollector collector (CI_ .getSema (), keys );
434439 for (auto *decl : user_decls) {
435440 collector.TraverseDecl (decl);
436441 }
437442 ctx.setTraversalScope ({ctx.getTranslationUnitDecl ()});
438443
439- auto index_dir =
440- fs::weakly_canonical (rules_dir_).parent_path () / kIndexDirName ;
441- auto text =
442- BuildRulesBuffer (index_dir, selected, ctx.getLangOpts ().CPlusPlus );
444+ auto index_dir = std::filesystem::weakly_canonical (rules_dir_).parent_path () /
445+ kIndexDirName ;
446+ auto text = BuildRulesBuffer (index_dir, keys, ctx.getLangOpts ().CPlusPlus );
443447 log () << " rules loaded for this translation unit:\n " << text;
444448 auto rules_file = src_mgr.createFileID (
445449 llvm::MemoryBuffer::getMemBufferCopy (text, " <cpp2rust-rules>" ),
0 commit comments