Skip to content

Commit b893feb

Browse files
committed
support locations relative to search paths
#feat fix #798
1 parent d14cbb6 commit b893feb

File tree

5 files changed

+77
-124
lines changed

5 files changed

+77
-124
lines changed

include/mrdocs/Metadata/Source.hpp

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,6 @@ struct MRDOCS_DECL
6161
*/
6262
unsigned LineNumber = 0;
6363

64-
/** The kind of file this is
65-
*/
66-
FileKind Kind = FileKind::Source;
67-
6864
/** Whether this location has documentation.
6965
*/
7066
bool Documented = false;
@@ -75,12 +71,10 @@ struct MRDOCS_DECL
7571
std::string_view const filepath = {},
7672
std::string_view const filename = {},
7773
unsigned const line = 0,
78-
FileKind const kind = FileKind::Source,
7974
bool const documented = false)
8075
: Path(filepath)
8176
, Filename(filename)
8277
, LineNumber(line)
83-
, Kind(kind)
8478
, Documented(documented)
8579
{
8680
}

src/lib/AST/ASTVisitor.cpp

Lines changed: 62 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -36,82 +36,66 @@
3636
#include <llvm/Support/Error.h>
3737
#include <llvm/Support/Path.h>
3838
#include <llvm/Support/SHA1.h>
39+
#include <llvm/Support/Process.h>
3940
#include <memory>
4041
#include <optional>
4142
#include <ranges>
4243
#include <unordered_set>
4344

4445
namespace clang::mrdocs {
4546

46-
auto
47+
ASTVisitor::FileInfo
4748
ASTVisitor::FileInfo::build(
48-
std::span<std::pair<std::string, FileKind> const> /* search_dirs */,
49+
std::span<std::string> const search_dirs,
4950
std::string_view const file_path,
50-
std::string_view const sourceRoot) -> ASTVisitor::FileInfo {
51+
std::string_view const sourceRoot) {
5152
FileInfo file_info;
5253
file_info.full_path = std::string(file_path);
53-
file_info.short_path = file_info.full_path;
54+
file_info.short_path = std::string(file_path);
5455

55-
std::ptrdiff_t best_length = 0;
56-
auto check_dir = [&](
57-
std::string_view const dir_path,
58-
FileKind const kind)
56+
// Find the best match for the file path
57+
for (auto const& search_dir : search_dirs)
5958
{
60-
auto NI = llvm::sys::path::begin(file_path);
61-
auto const NE = llvm::sys::path::end(file_path);
62-
auto DI = llvm::sys::path::begin(dir_path);
63-
auto const DE = llvm::sys::path::end(dir_path);
64-
65-
for(; NI != NE; ++NI, ++DI)
59+
if (files::startsWith(file_path, search_dir))
6660
{
67-
// reached the end of the directory path
68-
if(DI == DE)
61+
file_info.short_path.erase(0, search_dir.size());
62+
if (file_info.short_path.starts_with('/'))
6963
{
70-
// update the best prefix length
71-
if(std::ptrdiff_t length =
72-
NI - llvm::sys::path::begin(file_path);
73-
length > best_length)
74-
{
75-
best_length = length;
76-
file_info.kind = kind;
77-
return true;
78-
}
79-
break;
64+
file_info.short_path.erase(0, 1);
8065
}
81-
// separators always match
82-
if(NI->size() == 1 && DI->size() == 1 &&
83-
llvm::sys::path::is_separator(NI->front()) &&
84-
llvm::sys::path::is_separator(DI->front()))
85-
continue;
86-
// components don't match
87-
if(*NI != *DI)
88-
break;
66+
return file_info;
8967
}
90-
return false;
91-
};
92-
93-
bool const in_sourceRoot = check_dir(
94-
sourceRoot, FileKind::Source);
95-
96-
// only use a sourceRoot relative path if we
97-
// don't find anything in the include search directories
98-
// bool any_match = false;
99-
// for (auto const& [dir_path, kind]: search_dirs)
100-
// {
101-
// any_match |= check_dir(dir_path, kind);
102-
// }
103-
104-
// KRYSTIAN TODO: if we don't find any matches,
105-
// make the path relative to sourceRoot and return it
68+
}
10669

107-
// override the file kind if
108-
// the file was found in sourceRoot
109-
if (in_sourceRoot)
70+
// Fallback to sourceRoot
71+
if (files::startsWith(file_path, sourceRoot))
11072
{
111-
file_info.kind = FileKind::Source;
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;
11279
}
11380

114-
file_info.short_path.erase(0, best_length);
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+
}
11599
return file_info;
116100
}
117101

@@ -140,63 +124,37 @@ ASTVisitor(
140124
MRDOCS_ASSERT(context_.getTraversalScope() ==
141125
std::vector<Decl*>{context_.getTranslationUnitDecl()});
142126

143-
auto make_posix_absolute = [&](std::string_view const old_path)
144-
{
145-
llvm::SmallString<128> new_path(old_path);
146-
if(! llvm::sys::path::is_absolute(new_path))
147-
{
148-
// KRYSTIAN FIXME: use FileManager::makeAbsolutePath?
149-
auto const& cwd = source_.getFileManager().
150-
getFileSystemOpts().WorkingDir;
151-
// we can't normalize a relative path
152-
// without a base directory
153-
// MRDOCS_ASSERT(! cwd.empty());
154-
llvm::sys::fs::make_absolute(cwd, new_path);
155-
}
156-
// remove ./ and ../
157-
llvm::sys::path::remove_dots(new_path, true, llvm::sys::path::Style::posix);
158-
// convert to posix style
159-
llvm::sys::path::native(new_path, llvm::sys::path::Style::posix);
160-
return std::string(new_path);
161-
};
162-
127+
// Store the search directories
128+
auto const& cwd = source_.getFileManager().getFileSystemOpts().WorkingDir;
163129
Preprocessor& PP = sema_.getPreprocessor();
164130
HeaderSearch& HS = PP.getHeaderSearchInfo();
165-
std::vector<std::pair<std::string, FileKind>> search_dirs;
166-
search_dirs.reserve(HS.search_dir_size());
131+
search_dirs_.reserve(HS.search_dir_size());
167132
// first, convert all the include search directories into POSIX style
168133
for (const DirectoryLookup& DL : HS.search_dir_range())
169134
{
170135
OptionalDirectoryEntryRef DR = DL.getDirRef();
171136
// only consider normal directories
172-
if(! DL.isNormalDir() || ! DR)
137+
if (!DL.isNormalDir() || !DR)
138+
{
173139
continue;
140+
}
174141
// store the normalized path
175-
search_dirs.emplace_back(
176-
make_posix_absolute(DR->getName()),
177-
DL.isSystemHeaderDirectory() ?
178-
FileKind::System : FileKind::Other);
179-
}
180-
181-
std::string const sourceRoot = make_posix_absolute(config_->sourceRoot);
182-
auto cacheFileInfo = [&](const FileEntry* entry)
183-
{
184-
// "try" implies this may fail, so fallback to getName
185-
// if an empty string is returned
186-
std::string_view file_path =
187-
entry->tryGetRealPathName();
188-
files_.emplace(
189-
entry,
190-
FileInfo::build(
191-
search_dirs,
192-
make_posix_absolute(file_path),
193-
sourceRoot));
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);
194155
};
195-
196-
// build the file info for the main file
197-
cacheFileInfo(source_.getFileEntryForID(source_.getMainFileID()));
198-
199-
// build the file info for all included files
156+
FileEntry const* mainFileEntry = source_.getFileEntryForID(source_.getMainFileID());
157+
cacheFileInfo(mainFileEntry);
200158
for(const FileEntry* file : PP.getIncludedFiles())
201159
{
202160
cacheFileInfo(file);
@@ -829,9 +787,7 @@ populate(
829787
{
830788
return;
831789
}
832-
I.DefLoc.emplace(file->full_path,
833-
file->short_path, line, file->kind,
834-
documented);
790+
I.DefLoc.emplace(file->full_path, file->short_path, line, documented);
835791
}
836792
else
837793
{
@@ -846,9 +802,7 @@ populate(
846802
{
847803
return;
848804
}
849-
I.Loc.emplace_back(file->full_path,
850-
file->short_path, line, file->kind,
851-
documented);
805+
I.Loc.emplace_back(file->full_path, file->short_path, line, documented);
852806
}
853807
}
854808

src/lib/AST/ASTVisitor.hpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,17 @@ class ASTVisitor
7979
// An unordered set of all extracted Info declarations
8080
InfoSet info_;
8181

82+
/* Preprocessed information about search directories
83+
84+
This vector stores information about the search directories
85+
used by the translation unit.
86+
87+
Whenever we extract information about where a symbol is located,
88+
we store the full path of the symbol and the path relative
89+
to the search directory in this vector.
90+
*/
91+
std::vector<std::string> search_dirs_;
92+
8293
/* Struct to hold pre-processed file information.
8394
8495
This struct stores information about a file, including its full path,
@@ -92,7 +103,7 @@ class ASTVisitor
92103
static
93104
FileInfo
94105
build(
95-
std::span<const std::pair<std::string, FileKind>> search_dirs,
106+
std::span<std::string> search_dirs,
96107
std::string_view file_path,
97108
std::string_view sourceRoot);
98109

@@ -102,9 +113,6 @@ class ASTVisitor
102113
// The file path relative to a search directory.
103114
std::string short_path;
104115

105-
// The kind of the file.
106-
FileKind kind = FileKind::Source;
107-
108116
// Whether this file passes the file filters
109117
std::optional<bool> passesFilters;
110118
};

src/lib/Metadata/Source.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ tag_invoke(
4242
io.map("path", loc.Path);
4343
io.map("file", loc.Filename);
4444
io.map("line", loc.LineNumber);
45-
io.map("kind", loc.Kind);
4645
io.map("documented", loc.Documented);
4746
}
4847

src/lib/Support/Path.cpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -266,11 +266,9 @@ std::string
266266
makePosixStyle(
267267
std::string_view pathName)
268268
{
269-
std::string result(pathName);
270-
for(auto& c : result)
271-
if(c == '\\')
272-
c = '/';
273-
return result;
269+
SmallPathString result(pathName);
270+
llvm::sys::path::native(result, llvm::sys::path::Style::posix);
271+
return std::string(result);
274272
}
275273

276274
std::string

0 commit comments

Comments
 (0)