forked from OSchip/llvm-project
[clangd] Improve global code completion when scope specifier is unresolved.
Summary: Suppose `clangd::` is unresolved in the following example. Currently, we simply use "clangd::" as the query scope. We can do better by combining with accessible scopes in the context. The query scopes can be `{clangd::, clang::clangd::}`. ``` namespace clang { clangd::^ } ``` Reviewers: ilya-biryukov, sammccall, hokein, kadircet Reviewed By: kadircet Subscribers: MaskRay, jkorous, arphaman, kadircet, jdoerfert, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D58448 llvm-svn: 354963
This commit is contained in:
parent
79fb858053
commit
e98b86cbe8
|
@ -48,6 +48,7 @@
|
|||
#include "llvm/ADT/None.h"
|
||||
#include "llvm/ADT/Optional.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include "llvm/Support/Format.h"
|
||||
#include "llvm/Support/FormatVariadic.h"
|
||||
|
@ -526,7 +527,7 @@ struct SpecifiedScope {
|
|||
std::set<std::string> Results;
|
||||
for (llvm::StringRef AS : AccessibleScopes)
|
||||
Results.insert(
|
||||
((UnresolvedQualifier ? *UnresolvedQualifier : "") + AS).str());
|
||||
(AS + (UnresolvedQualifier ? *UnresolvedQualifier : "")).str());
|
||||
return {Results.begin(), Results.end()};
|
||||
}
|
||||
};
|
||||
|
@ -570,16 +571,15 @@ getQueryScopes(CodeCompletionContext &CCContext, const Sema &CCSema,
|
|||
}
|
||||
|
||||
// Unresolved qualifier.
|
||||
// FIXME: When Sema can resolve part of a scope chain (e.g.
|
||||
// "known::unknown::id"), we should expand the known part ("known::") rather
|
||||
// than treating the whole thing as unknown.
|
||||
SpecifiedScope Info;
|
||||
Info.AccessibleScopes.push_back(""); // global namespace
|
||||
SpecifiedScope Info = GetAllAccessibleScopes(CCContext);
|
||||
Info.AccessibleScopes.push_back(""); // Make sure global scope is included.
|
||||
|
||||
Info.UnresolvedQualifier =
|
||||
llvm::StringRef SpelledSpecifier =
|
||||
Lexer::getSourceText(CharSourceRange::getCharRange((*SS)->getRange()),
|
||||
CCSema.SourceMgr, clang::LangOptions())
|
||||
.ltrim("::");
|
||||
CCSema.SourceMgr, clang::LangOptions());
|
||||
if (SpelledSpecifier.consume_front("::"))
|
||||
Info.AccessibleScopes = {""};
|
||||
Info.UnresolvedQualifier = SpelledSpecifier;
|
||||
// Sema excludes the trailing "::".
|
||||
if (!Info.UnresolvedQualifier->empty())
|
||||
*Info.UnresolvedQualifier += "::";
|
||||
|
|
|
@ -1095,8 +1095,10 @@ TEST(CompletionTest, UnresolvedQualifierIdQuery) {
|
|||
} // namespace ns
|
||||
)cpp");
|
||||
|
||||
EXPECT_THAT(Requests, ElementsAre(Field(&FuzzyFindRequest::Scopes,
|
||||
UnorderedElementsAre("bar::"))));
|
||||
EXPECT_THAT(Requests,
|
||||
ElementsAre(Field(
|
||||
&FuzzyFindRequest::Scopes,
|
||||
UnorderedElementsAre("a::bar::", "ns::bar::", "bar::"))));
|
||||
}
|
||||
|
||||
TEST(CompletionTest, UnresolvedNestedQualifierIdQuery) {
|
||||
|
@ -2335,6 +2337,35 @@ TEST(CompletionTest, UsingDecl) {
|
|||
Kind(CompletionItemKind::Reference))));
|
||||
}
|
||||
|
||||
TEST(CompletionTest, ScopeIsUnresolved) {
|
||||
clangd::CodeCompleteOptions Opts = {};
|
||||
Opts.AllScopes = true;
|
||||
|
||||
auto Results = completions(R"cpp(
|
||||
namespace a {
|
||||
void f() { b::X^ }
|
||||
}
|
||||
)cpp",
|
||||
{cls("a::b::XYZ")}, Opts);
|
||||
EXPECT_THAT(Results.Completions,
|
||||
UnorderedElementsAre(AllOf(Qualifier(""), Named("XYZ"))));
|
||||
}
|
||||
|
||||
TEST(CompletionTest, NestedScopeIsUnresolved) {
|
||||
clangd::CodeCompleteOptions Opts = {};
|
||||
Opts.AllScopes = true;
|
||||
|
||||
auto Results = completions(R"cpp(
|
||||
namespace a {
|
||||
namespace b {}
|
||||
void f() { b::c::X^ }
|
||||
}
|
||||
)cpp",
|
||||
{cls("a::b::c::XYZ")}, Opts);
|
||||
EXPECT_THAT(Results.Completions,
|
||||
UnorderedElementsAre(AllOf(Qualifier(""), Named("XYZ"))));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace clangd
|
||||
} // namespace clang
|
||||
|
|
Loading…
Reference in New Issue