[PATCH] D117056: [clangd] Properly compute framework-style include spelling
Sam McCall via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Tue Jan 18 15:41:28 PST 2022
sammccall added a comment.
Nice!
================
Comment at: clang-tools-extra/clangd/index/SymbolCollector.cpp:197
+ llvm::StringMap<std::string> CachePathToFrameworkSpelling;
+ llvm::StringMap<std::string> CacheFrameworkToUmbrellaInclude;
----------------
...ToUmbrellaHeaderSpelling?
(Unclear to me what values "umbrella include" would take)
================
Comment at: clang-tools-extra/clangd/index/SymbolCollector.cpp:260
+
+ bool valid() { return !HeadersDir.empty() && !HeaderSubpath.empty(); }
+ };
----------------
return `Optional<FrameworkInfo>` instead of sentinel values
================
Comment at: clang-tools-extra/clangd/index/SymbolCollector.cpp:263
+
+ FrameworkInfo getHeaderFrameworkInfo(llvm::StringRef Path) {
+ using namespace llvm::sys;
----------------
This name is very vague: `splitFrameworkHeaderPath`?
Similarly FrameworkInfo -> FrameworkHeaderPath.
(I was confused why this wasn't cached until I understood this *isn't* per-framework information, it's per-header information)
================
Comment at: clang-tools-extra/clangd/index/SymbolCollector.cpp:285
+
+ llvm::StringRef getFrameworkIncludeSpelling(llvm::StringRef Path,
+ const FileEntry *FE,
----------------
Short doc comment here. In particular what `Framework` contains
================
Comment at: clang-tools-extra/clangd/index/SymbolCollector.cpp:285
+
+ llvm::StringRef getFrameworkIncludeSpelling(llvm::StringRef Path,
+ const FileEntry *FE,
----------------
sammccall wrote:
> Short doc comment here. In particular what `Framework` contains
no need to pass `Path`, it's FE->getName()
================
Comment at: clang-tools-extra/clangd/index/SymbolCollector.cpp:291
+ if (!SpellingR.second)
+ return SpellingR.first->second;
+
----------------
there are 7 references to SpellingR.first->second in this function, give it a name?
================
Comment at: clang-tools-extra/clangd/index/SymbolCollector.cpp:293
+
+ auto R = CacheFrameworkToUmbrellaInclude.try_emplace(Framework);
+ if (!R.second && !R.first->second.empty()) {
----------------
Having multiple caches managed by this function makes it hard to understand.
Pull out a function to get the (cached) umbrella header for a framework?
================
Comment at: clang-tools-extra/clangd/index/SymbolCollector.cpp:295
+ if (!R.second && !R.first->second.empty()) {
+ // Framework has known umbrella spelling, cache it for this header as
+ // well.
----------------
Why? Seems like just looking up the umbrella first would be simpler and just as efficient.
================
Comment at: clang-tools-extra/clangd/index/SymbolCollector.cpp:303
+ SpellingR.first->second = "";
+ R.first->second = "";
+ return R.first->second;
----------------
if the header we happened to see first is PrivateHeaders, then you're caching the fact that this framework has no umbrella header.
There's a design decision here: is the path of any single header sufficient to decide whether a framework has an umbrella? If not, the cache needs to work differently.
================
Comment at: clang-tools-extra/clangd/index/SymbolCollector.cpp:308
+
+ SmallString<256> UmbrellaPath(Info.HeadersDir);
+ llvm::sys::path::append(UmbrellaPath, Framework + ".h");
----------------
comment here on what an umbrella header is and why we care
================
Comment at: clang-tools-extra/clangd/index/SymbolCollector.cpp:351
}
+ // Special case framework headers since they have special framework-style
+ // include spelling. We also check if an umbrella header with the same name
----------------
This comment is most useful to people not very familiar with frameworks, but isn't specific enough. maybe:
`Framework headers are spelled as <Framework/Foo.h>, not "path/Framework.framework/Headers/Foo.h"`
The bit about umbrella headers should go where we do that, and mostly say *why* rather than what
================
Comment at: clang-tools-extra/clangd/index/SymbolCollector.cpp:356
+ if (const auto *HFI = HS.getExistingFileInfo(FE, /*WantExternal*/ false)) {
+ auto Framework = HFI->Framework;
+ if (!Framework.empty()) {
----------------
nit: inline, this var doesn't improve readability
================
Comment at: clang-tools-extra/clangd/index/SymbolCollector.cpp:358
+ if (!Framework.empty()) {
+ auto Spelling =
+ getFrameworkIncludeSpelling(Filename, FE, Framework, HS);
----------------
return Optional<StringRef> and initialize this in the if, rather than using the empty string as a sentinel value
================
Comment at: clang-tools-extra/clangd/index/SymbolCollector.cpp:360
+ getFrameworkIncludeSpelling(Filename, FE, Framework, HS);
+ if (!Spelling.empty()) {
+ return Spelling;
----------------
nit: no braces
================
Comment at: clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp:669
+ auto FrameworksPath = testPath("Frameworks/");
+ auto FrameworkHeaderPath =
+ testPath("Frameworks/Foundation.framework/Headers/NSObject.h");
----------------
nit: inline these filenames used once
================
Comment at: clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp:671
+ testPath("Frameworks/Foundation.framework/Headers/NSObject.h");
+ const std::string FrameworkHeader = R"(
+ __attribute((objc_root_class))
----------------
nit: no const on locals
================
Comment at: clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp:695
+
+TEST_F(SymbolCollectorTest, ObjCUmbrellaFrameworkIncludeHeader) {
+ CollectorOpts.CollectIncludePath = true;
----------------
Instead of copying the setup 3 times, can we:
- run the test, expect "Foundation/NSObject.h"
- add the umbrella file
- run the test, expect "Foundation/Foundation.h"
- run the test with -isysroot, expect <Foundation/Foundation.h>
?
================
Comment at: clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp:762
+ Header, Main,
+ {"-iframeworkwithsysroot", FrameworksPath, "-xobjective-c++"});
+ EXPECT_THAT(Symbols, UnorderedElementsAre(
----------------
OOC, is "withsysroot" needed here?
================
Comment at: clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp:1018
} TestCases[] = {
- {
- R"cpp(
+ {
+ R"cpp(
----------------
unrelated whitespace changes
================
Comment at: clang/lib/Lex/HeaderSearch.cpp:1052
HFI.IndexHeaderMapHeader = 1;
+ } else if (CurDir->isFramework()) {
+ size_t SlashPos = Filename.find('/');
----------------
This looks like a separate change, and should have a test in clang.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D117056/new/
https://reviews.llvm.org/D117056
More information about the cfe-commits
mailing list