44
44
45
45
namespace clang ::mrdocs {
46
46
47
- ASTVisitor::FileInfo
48
- ASTVisitor::FileInfo::build (
49
- std::span<std::string> const search_dirs,
50
- std::string_view const file_path,
51
- std::string_view const sourceRoot) {
52
- FileInfo file_info;
53
- file_info.full_path = std::string (file_path);
54
- file_info.short_path = std::string (file_path);
55
-
56
- // Find the best match for the file path
57
- for (auto const & search_dir : search_dirs)
58
- {
59
- if (files::startsWith (file_path, search_dir))
60
- {
61
- file_info.short_path .erase (0 , search_dir.size ());
62
- if (file_info.short_path .starts_with (' /' ))
63
- {
64
- file_info.short_path .erase (0 , 1 );
65
- }
66
- return file_info;
67
- }
68
- }
69
-
70
- // Fallback to sourceRoot
71
- if (files::startsWith (file_path, sourceRoot))
72
- {
73
- file_info.short_path .erase (0 , sourceRoot.size ());
74
- if (file_info.short_path .starts_with (' /' ))
75
- {
76
- file_info.short_path .erase (0 , 1 );
77
- }
78
- return file_info;
79
- }
80
-
81
- // Fallback to system search paths in PATH
82
- std::optional<std::string> const optEnvPathsStr = llvm::sys::Process::GetEnv (" PATH" );
83
- MRDOCS_CHECK_OR (optEnvPathsStr, file_info);
84
- std::string const & envPathsStr = *optEnvPathsStr;
85
- for (auto const envPaths = llvm::split (envPathsStr, llvm::sys::EnvPathSeparator);
86
- auto envPath: envPaths)
87
- {
88
- auto normEnvPath = files::makePosixStyle (envPath);
89
- if (files::startsWith (file_path, normEnvPath))
90
- {
91
- file_info.short_path .erase (0 , normEnvPath.size ());
92
- if (file_info.short_path .starts_with (' /' ))
93
- {
94
- file_info.short_path .erase (0 , 1 );
95
- }
96
- return file_info;
97
- }
98
- }
99
- return file_info;
100
- }
101
-
102
47
ASTVisitor::
103
48
ASTVisitor (
104
49
const ConfigImpl& config,
@@ -123,42 +68,6 @@ ASTVisitor(
123
68
// used somewhere
124
69
MRDOCS_ASSERT (context_.getTraversalScope () ==
125
70
std::vector<Decl*>{context_.getTranslationUnitDecl ()});
126
-
127
- // Store the search directories
128
- auto const & cwd = source_.getFileManager ().getFileSystemOpts ().WorkingDir ;
129
- Preprocessor& PP = sema_.getPreprocessor ();
130
- HeaderSearch& HS = PP.getHeaderSearchInfo ();
131
- search_dirs_.reserve (HS.search_dir_size ());
132
- // first, convert all the include search directories into POSIX style
133
- for (const DirectoryLookup& DL : HS.search_dir_range ())
134
- {
135
- OptionalDirectoryEntryRef DR = DL.getDirRef ();
136
- // only consider normal directories
137
- if (!DL.isNormalDir () || !DR)
138
- {
139
- continue ;
140
- }
141
- // store the normalized path
142
- auto normPath = files::makePosixStyle (files::makeAbsolute (DR->getName (), cwd));
143
- search_dirs_.push_back (std::move (normPath));
144
- }
145
-
146
- // Store preprocessed information about all file entries
147
- std::string const sourceRoot = files::makePosixStyle (files::makeAbsolute (config_->sourceRoot , cwd));
148
- auto cacheFileInfo = [&](FileEntry const * entry) {
149
- std::string_view const file_path = entry->tryGetRealPathName ();
150
- MRDOCS_CHECK_OR (!file_path.empty ());
151
- auto const normPath = files::makePosixStyle (
152
- files::makeAbsolute (file_path, cwd));
153
- auto FI = FileInfo::build (search_dirs_, normPath, sourceRoot);
154
- files_.emplace (entry, FI);
155
- };
156
- FileEntry const * mainFileEntry = source_.getFileEntryForID (source_.getMainFileID ());
157
- cacheFileInfo (mainFileEntry);
158
- for (const FileEntry* file : PP.getIncludedFiles ())
159
- {
160
- cacheFileInfo (file);
161
- }
162
71
}
163
72
164
73
void
@@ -2514,26 +2423,26 @@ shouldExtract(
2514
2423
// This is not a scoped promotion because
2515
2424
// parents and members should also assume
2516
2425
// the same base extraction mode.
2517
- if (checkFileFilters (D) &&
2518
- checkSymbolFilters (D))
2426
+ if (checkSymbolFilters (D) &&
2427
+ checkFileFilters (D))
2519
2428
{
2520
2429
mode_ = ExtractionMode::Regular;
2521
2430
}
2522
2431
// But we return true either way
2523
2432
return true ;
2524
2433
}
2525
2434
2435
+ // Check if this symbol should be extracted according
2436
+ // to its qualified name. This checks if it matches
2437
+ // the symbol patterns and if it's not excluded.
2438
+ MRDOCS_CHECK_OR (checkSymbolFilters (D), false );
2439
+
2526
2440
// Check if this symbol should be extracted according
2527
2441
// to its location. This checks if it's in one of the
2528
2442
// input directories, if it matches the file patterns,
2529
2443
// and it's not in an excluded file.
2530
2444
MRDOCS_CHECK_OR (checkFileFilters (D), false );
2531
2445
2532
- // Check if this symbol should be extracted according
2533
- // to its qualified name. This checks if it matches
2534
- // the symbol patterns and if it's not excluded.
2535
- MRDOCS_CHECK_OR (checkSymbolFilters (D), false );
2536
-
2537
2446
return true ;
2538
2447
}
2539
2448
@@ -2776,36 +2685,132 @@ ASTVisitor::FileInfo*
2776
2685
ASTVisitor::
2777
2686
findFileInfo (clang::SourceLocation const loc)
2778
2687
{
2779
- if (loc.isInvalid ())
2780
- {
2781
- return nullptr ;
2782
- }
2783
- // KRYSTIAN FIXME: we really should not be
2784
- // calling getPresumedLoc this often,
2688
+ MRDOCS_CHECK_OR (!loc.isInvalid (), nullptr );
2689
+
2690
+ // KRYSTIAN FIXME: we really should not be calling getPresumedLoc this often,
2785
2691
// it's quite expensive
2786
2692
auto const presumed = source_.getPresumedLoc (loc, false );
2787
- if (presumed.isInvalid ())
2693
+ MRDOCS_CHECK_OR (!presumed.isInvalid (), nullptr );
2694
+
2695
+ const FileEntry* entry = source_.getFileEntryForID ( presumed.getFileID ());
2696
+ MRDOCS_CHECK_OR (entry, nullptr );
2697
+
2698
+ // Find in the cache
2699
+ if (auto const it = files_.find (entry); it != files_.end ())
2788
2700
{
2789
- return nullptr ;
2701
+ return std::addressof (it-> second ) ;
2790
2702
}
2791
- const FileEntry* file =
2792
- source_.getFileEntryForID (
2793
- presumed.getFileID ());
2794
- // KRYSTIAN NOTE: i have no idea under what
2795
- // circumstances the file entry would be null
2796
- if (!file)
2703
+
2704
+ // Build FileInfo
2705
+ auto const FI = buildFileInfo (entry);
2706
+ MRDOCS_CHECK_OR (FI, nullptr );
2707
+ auto [it, inserted] = files_.try_emplace (entry, std::move (*FI));
2708
+ return std::addressof (it->second );
2709
+ }
2710
+
2711
+ std::optional<ASTVisitor::FileInfo>
2712
+ ASTVisitor::
2713
+ buildFileInfo (FileEntry const * entry)
2714
+ {
2715
+ std::string_view const file_path = entry->tryGetRealPathName ();
2716
+ MRDOCS_CHECK_OR (!file_path.empty (), std::nullopt);
2717
+ return buildFileInfo (file_path);
2718
+ }
2719
+
2720
+ ASTVisitor::FileInfo
2721
+ ASTVisitor::
2722
+ buildFileInfo (std::string_view const file_path)
2723
+ {
2724
+ FileInfo file_info;
2725
+ file_info.full_path = file_path;
2726
+ if (!files::isPosixStyle (file_info.full_path ))
2797
2727
{
2798
- return nullptr ;
2728
+ file_info. full_path = files::makePosixStyle (file_info. full_path ) ;
2799
2729
}
2800
- // KRYSTIAN NOTE: i have no idea under what
2801
- // circumstances the file would not be in either
2802
- // the main file, or an included file
2803
- auto const it = files_.find (file);
2804
- if (it == files_.end ())
2730
+
2731
+ // Attempts to get a relative path for the prefix
2732
+ auto tryGetRelativePosixPath = [&file_info](std::string_view const prefix)
2733
+ -> std::optional<std::string_view>
2805
2734
{
2806
- return nullptr ;
2735
+ if (files::startsWith (file_info.full_path , prefix))
2736
+ {
2737
+ std::string_view res = file_info.full_path ;
2738
+ res.remove_prefix (prefix.size ());
2739
+ if (res.starts_with (' /' ))
2740
+ {
2741
+ res.remove_prefix (1 );
2742
+ }
2743
+ return res;
2744
+ }
2745
+ return std::nullopt;
2746
+ };
2747
+
2748
+ auto tryGetRelativePath = [&tryGetRelativePosixPath](std::string_view const prefix)
2749
+ -> std::optional<std::string_view>
2750
+ {
2751
+ if (!files::isAbsolute (prefix))
2752
+ {
2753
+ return std::nullopt;
2754
+ }
2755
+ if (files::isPosixStyle (prefix))
2756
+ {
2757
+ // If already posix, we use the string view directly
2758
+ // to avoid creating a new string for the check
2759
+ return tryGetRelativePosixPath (prefix);
2760
+ }
2761
+ std::string const posixPrefix = files::makePosixStyle (prefix);
2762
+ return tryGetRelativePosixPath (posixPrefix);
2763
+ };
2764
+
2765
+ // Find the best match for the file path in the search directories
2766
+ for (HeaderSearch& HS = sema_.getPreprocessor ().getHeaderSearchInfo ();
2767
+ DirectoryLookup const & DL : HS.search_dir_range ())
2768
+ {
2769
+ OptionalDirectoryEntryRef DR = DL.getDirRef ();
2770
+ if (!DL.isNormalDir () || !DR)
2771
+ {
2772
+ // Only consider normal directories
2773
+ continue ;
2774
+ }
2775
+ StringRef searchDir = DR->getName ();
2776
+ if (auto shortPath = tryGetRelativePath (searchDir))
2777
+ {
2778
+ file_info.short_path = std::string (*shortPath);
2779
+ return file_info;
2780
+ }
2781
+ }
2782
+
2783
+ // Fallback to sourceRoot
2784
+ if (files::isAbsolute (config_->sourceRoot ))
2785
+ {
2786
+ if (auto shortPath = tryGetRelativePath (config_->sourceRoot ))
2787
+ {
2788
+ file_info.short_path = std::string (*shortPath);
2789
+ return file_info;
2790
+ }
2807
2791
}
2808
- return &it->second ;
2792
+
2793
+ // Fallback to system search paths in PATH
2794
+ std::optional<std::string> const optEnvPathsStr = llvm::sys::Process::GetEnv (" PATH" );
2795
+ MRDOCS_CHECK_OR (optEnvPathsStr, file_info);
2796
+ std::string const & envPathsStr = *optEnvPathsStr;
2797
+ for (auto const envPaths = llvm::split (envPathsStr, llvm::sys::EnvPathSeparator);
2798
+ auto envPath: envPaths)
2799
+ {
2800
+ if (!files::isAbsolute (envPath))
2801
+ {
2802
+ continue ;
2803
+ }
2804
+ if (auto shortPath = tryGetRelativePath (envPath))
2805
+ {
2806
+ file_info.short_path = std::string (*shortPath);
2807
+ return file_info;
2808
+ }
2809
+ }
2810
+
2811
+ // Fallback to the full path
2812
+ file_info.short_path = file_info.full_path ;
2813
+ return file_info;
2809
2814
}
2810
2815
2811
2816
template <std::derived_from<Info> InfoTy>
@@ -2840,9 +2845,10 @@ ASTVisitor::
2840
2845
upsert (DeclType* D)
2841
2846
{
2842
2847
AccessSpecifier access = getAccess (D);
2843
- MRDOCS_CHECK_MSG (
2844
- shouldExtract (D, access ),
2845
- " Symbol should not be extracted" );
2848
+ if (!shouldExtract (D, access ))
2849
+ {
2850
+ return Unexpected (Error (" Symbol should not be extracted" ));
2851
+ }
2846
2852
2847
2853
SymbolID const id = generateID (D);
2848
2854
MRDOCS_CHECK_MSG (id, " Failed to extract symbol ID" );
0 commit comments