forked from OSchip/llvm-project
[clangd] Allow to override contents of the file during completion.
Reviewers: krasimir Reviewed By: krasimir Subscribers: klimek, cfe-commits Differential Revision: https://reviews.llvm.org/D34107 llvm-svn: 305280
This commit is contained in:
parent
e36035b121
commit
b23ff10c67
|
@ -184,17 +184,27 @@ void ClangdServer::forceReparse(PathRef File) {
|
||||||
addDocument(File, getDocument(File));
|
addDocument(File, getDocument(File));
|
||||||
}
|
}
|
||||||
|
|
||||||
Tagged<std::vector<CompletionItem>> ClangdServer::codeComplete(PathRef File,
|
Tagged<std::vector<CompletionItem>>
|
||||||
Position Pos) {
|
ClangdServer::codeComplete(PathRef File, Position Pos,
|
||||||
auto FileContents = DraftMgr.getDraft(File);
|
llvm::Optional<StringRef> OverridenContents) {
|
||||||
assert(FileContents.Draft && "codeComplete is called for non-added document");
|
if (!OverridenContents) {
|
||||||
|
auto FileContents = DraftMgr.getDraft(File);
|
||||||
|
assert(FileContents.Draft &&
|
||||||
|
"codeComplete is called for non-added document");
|
||||||
|
|
||||||
|
OverridenContents = *FileContents.Draft;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<CompletionItem> Result;
|
std::vector<CompletionItem> Result;
|
||||||
auto TaggedFS = FSProvider->getTaggedFileSystem();
|
auto TaggedFS = FSProvider->getTaggedFileSystem();
|
||||||
Units.runOnUnitWithoutReparse(
|
// It would be nice to use runOnUnitWithoutReparse here, but we can't
|
||||||
File, *FileContents.Draft, *CDB, PCHs, TaggedFS.Value, [&](ClangdUnit &Unit) {
|
// guarantee the correctness of code completion cache here if we don't do the
|
||||||
Result = Unit.codeComplete(*FileContents.Draft, Pos, TaggedFS.Value);
|
// reparse.
|
||||||
});
|
Units.runOnUnit(File, *OverridenContents, *CDB, PCHs, TaggedFS.Value,
|
||||||
|
[&](ClangdUnit &Unit) {
|
||||||
|
Result = Unit.codeComplete(*OverridenContents, Pos,
|
||||||
|
TaggedFS.Value);
|
||||||
|
});
|
||||||
return make_tagged(std::move(Result), TaggedFS.Tag);
|
return make_tagged(std::move(Result), TaggedFS.Tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -152,8 +152,15 @@ public:
|
||||||
/// Force \p File to be reparsed using the latest contents.
|
/// Force \p File to be reparsed using the latest contents.
|
||||||
void forceReparse(PathRef File);
|
void forceReparse(PathRef File);
|
||||||
|
|
||||||
/// Run code completion for \p File at \p Pos.
|
/// Run code completion for \p File at \p Pos. If \p OverridenContents is not
|
||||||
Tagged<std::vector<CompletionItem>> codeComplete(PathRef File, Position Pos);
|
/// None, they will used only for code completion, i.e. no diagnostics update
|
||||||
|
/// will be scheduled and a draft for \p File will not be updated.
|
||||||
|
/// If \p OverridenContents is None, contents of the current draft for \p File
|
||||||
|
/// will be used.
|
||||||
|
/// This method should only be called for currently tracked files.
|
||||||
|
Tagged<std::vector<CompletionItem>>
|
||||||
|
codeComplete(PathRef File, Position Pos,
|
||||||
|
llvm::Optional<StringRef> OverridenContents = llvm::None);
|
||||||
|
|
||||||
/// Run formatting for \p Rng inside \p File.
|
/// Run formatting for \p Rng inside \p File.
|
||||||
std::vector<tooling::Replacement> formatRange(PathRef File, Range Rng);
|
std::vector<tooling::Replacement> formatRange(PathRef File, Range Rng);
|
||||||
|
|
|
@ -398,5 +398,69 @@ TEST_F(ClangdVFSTest, CheckVersions) {
|
||||||
EXPECT_EQ(Server.codeComplete(FooCpp, Position{0, 0}).Tag, FS->Tag);
|
EXPECT_EQ(Server.codeComplete(FooCpp, Position{0, 0}).Tag, FS->Tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ClangdCompletionTest : public ClangdVFSTest {
|
||||||
|
protected:
|
||||||
|
bool ContainsItem(std::vector<CompletionItem> const &Items, StringRef Name) {
|
||||||
|
for (const auto &Item : Items) {
|
||||||
|
if (Item.insertText == Name)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(ClangdCompletionTest, CheckContentsOverride) {
|
||||||
|
MockFSProvider *FS;
|
||||||
|
|
||||||
|
ClangdServer Server(llvm::make_unique<MockCompilationDatabase>(),
|
||||||
|
llvm::make_unique<ErrorCheckingDiagConsumer>(),
|
||||||
|
getAndMove(llvm::make_unique<MockFSProvider>(), FS),
|
||||||
|
/*RunSynchronously=*/false);
|
||||||
|
|
||||||
|
auto FooCpp = getVirtualTestFilePath("foo.cpp");
|
||||||
|
const auto SourceContents = R"cpp(
|
||||||
|
int aba;
|
||||||
|
int b = ;
|
||||||
|
)cpp";
|
||||||
|
|
||||||
|
const auto OverridenSourceContents = R"cpp(
|
||||||
|
int cbc;
|
||||||
|
int b = ;
|
||||||
|
)cpp";
|
||||||
|
// Complete after '=' sign. We need to be careful to keep the SourceContents'
|
||||||
|
// size the same.
|
||||||
|
// We complete on the 3rd line (2nd in zero-based numbering), because raw
|
||||||
|
// string literal of the SourceContents starts with a newline(it's easy to
|
||||||
|
// miss).
|
||||||
|
Position CompletePos = {2, 8};
|
||||||
|
FS->Files[FooCpp] = SourceContents;
|
||||||
|
|
||||||
|
Server.addDocument(FooCpp, SourceContents);
|
||||||
|
|
||||||
|
{
|
||||||
|
auto CodeCompletionResults1 =
|
||||||
|
Server.codeComplete(FooCpp, CompletePos, None).Value;
|
||||||
|
EXPECT_TRUE(ContainsItem(CodeCompletionResults1, "aba"));
|
||||||
|
EXPECT_FALSE(ContainsItem(CodeCompletionResults1, "cbc"));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto CodeCompletionResultsOverriden =
|
||||||
|
Server
|
||||||
|
.codeComplete(FooCpp, CompletePos,
|
||||||
|
StringRef(OverridenSourceContents))
|
||||||
|
.Value;
|
||||||
|
EXPECT_TRUE(ContainsItem(CodeCompletionResultsOverriden, "cbc"));
|
||||||
|
EXPECT_FALSE(ContainsItem(CodeCompletionResultsOverriden, "aba"));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto CodeCompletionResults2 =
|
||||||
|
Server.codeComplete(FooCpp, CompletePos, None).Value;
|
||||||
|
EXPECT_TRUE(ContainsItem(CodeCompletionResults2, "aba"));
|
||||||
|
EXPECT_FALSE(ContainsItem(CodeCompletionResults2, "cbc"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace clangd
|
} // namespace clangd
|
||||||
} // namespace clang
|
} // namespace clang
|
||||||
|
|
Loading…
Reference in New Issue