2017-05-16 17:38:59 +08:00
|
|
|
//===--- DraftStore.cpp - File contents container ---------------*- C++ -*-===//
|
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2017-05-16 17:38:59 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "DraftStore.h"
|
[clangd] Support incremental document syncing
Summary:
This patch adds support for incremental document syncing, as described
in the LSP spec. The protocol specifies ranges in terms of Position (a
line and a character), and our drafts are stored as plain strings. So I
see two things that may not be super efficient for very large files:
- Converting a Position to an offset (the positionToOffset function)
requires searching for end of lines until we reach the desired line.
- When we update a range, we construct a new string, which implies
copying the whole document.
However, for the typical size of a C++ document and the frequency of
update (at which a user types), it may not be an issue. This patch aims
at getting the basic feature in, and we can always improve it later if
we find it's too slow.
Signed-off-by: Simon Marchi <simon.marchi@ericsson.com>
Reviewers: malaperle, ilya-biryukov
Reviewed By: ilya-biryukov
Subscribers: MaskRay, klimek, mgorny, ilya-biryukov, jkorous-apple, ioeric, cfe-commits
Differential Revision: https://reviews.llvm.org/D44272
llvm-svn: 328500
2018-03-26 22:41:40 +08:00
|
|
|
#include "SourceCode.h"
|
[clangd] Move non-clang base pieces into separate support/ lib. NFCI
Summary:
This enforces layering, reduces a sprawling clangd/ directory, and makes life
easier for embedders.
Reviewers: kbobyrev
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D79014
2020-04-28 23:49:17 +08:00
|
|
|
#include "support/Logger.h"
|
[clangd] Support incremental document syncing
Summary:
This patch adds support for incremental document syncing, as described
in the LSP spec. The protocol specifies ranges in terms of Position (a
line and a character), and our drafts are stored as plain strings. So I
see two things that may not be super efficient for very large files:
- Converting a Position to an offset (the positionToOffset function)
requires searching for end of lines until we reach the desired line.
- When we update a range, we construct a new string, which implies
copying the whole document.
However, for the typical size of a C++ document and the frequency of
update (at which a user types), it may not be an issue. This patch aims
at getting the basic feature in, and we can always improve it later if
we find it's too slow.
Signed-off-by: Simon Marchi <simon.marchi@ericsson.com>
Reviewers: malaperle, ilya-biryukov
Reviewed By: ilya-biryukov
Subscribers: MaskRay, klimek, mgorny, ilya-biryukov, jkorous-apple, ioeric, cfe-commits
Differential Revision: https://reviews.llvm.org/D44272
llvm-svn: 328500
2018-03-26 22:41:40 +08:00
|
|
|
#include "llvm/Support/Errc.h"
|
2017-05-16 17:38:59 +08:00
|
|
|
|
2018-10-20 23:30:37 +08:00
|
|
|
namespace clang {
|
|
|
|
namespace clangd {
|
2017-05-16 17:38:59 +08:00
|
|
|
|
2020-03-03 22:57:39 +08:00
|
|
|
llvm::Optional<DraftStore::Draft> DraftStore::getDraft(PathRef File) const {
|
2017-05-16 17:38:59 +08:00
|
|
|
std::lock_guard<std::mutex> Lock(Mutex);
|
|
|
|
|
|
|
|
auto It = Drafts.find(File);
|
|
|
|
if (It == Drafts.end())
|
2018-10-20 23:30:37 +08:00
|
|
|
return None;
|
2018-03-16 22:30:42 +08:00
|
|
|
|
2017-05-16 17:38:59 +08:00
|
|
|
return It->second;
|
|
|
|
}
|
|
|
|
|
[clangd] DidChangeConfiguration Notification
Summary:
Implementation of DidChangeConfiguration notification handling in
clangd. This currently only supports changing one setting: the path of
the compilation database to be used for the current project. In other
words, it is no longer necessary to restart clangd with a different
command line argument in order to change the compilation database.
Reviewers: malaperle, krasimir, bkramer, ilya-biryukov
Subscribers: jkorous-apple, ioeric, simark, klimek, ilya-biryukov, arphaman, rwols, cfe-commits
Differential Revision: https://reviews.llvm.org/D39571
Signed-off-by: Simon Marchi <simon.marchi@ericsson.com>
Signed-off-by: William Enright <william.enright@polymtl.ca>
llvm-svn: 325784
2018-02-22 22:00:39 +08:00
|
|
|
std::vector<Path> DraftStore::getActiveFiles() const {
|
|
|
|
std::lock_guard<std::mutex> Lock(Mutex);
|
|
|
|
std::vector<Path> ResultVector;
|
|
|
|
|
|
|
|
for (auto DraftIt = Drafts.begin(); DraftIt != Drafts.end(); DraftIt++)
|
2020-01-29 03:23:46 +08:00
|
|
|
ResultVector.push_back(std::string(DraftIt->getKey()));
|
[clangd] DidChangeConfiguration Notification
Summary:
Implementation of DidChangeConfiguration notification handling in
clangd. This currently only supports changing one setting: the path of
the compilation database to be used for the current project. In other
words, it is no longer necessary to restart clangd with a different
command line argument in order to change the compilation database.
Reviewers: malaperle, krasimir, bkramer, ilya-biryukov
Subscribers: jkorous-apple, ioeric, simark, klimek, ilya-biryukov, arphaman, rwols, cfe-commits
Differential Revision: https://reviews.llvm.org/D39571
Signed-off-by: Simon Marchi <simon.marchi@ericsson.com>
Signed-off-by: William Enright <william.enright@polymtl.ca>
llvm-svn: 325784
2018-02-22 22:00:39 +08:00
|
|
|
|
|
|
|
return ResultVector;
|
|
|
|
}
|
|
|
|
|
2020-03-03 22:57:39 +08:00
|
|
|
static void updateVersion(DraftStore::Draft &D,
|
|
|
|
llvm::Optional<int64_t> Version) {
|
|
|
|
if (Version) {
|
|
|
|
// We treat versions as opaque, but the protocol says they increase.
|
|
|
|
if (*Version <= D.Version)
|
|
|
|
log("File version went from {0} to {1}", D.Version, Version);
|
|
|
|
D.Version = *Version;
|
|
|
|
} else {
|
|
|
|
// Note that if D was newly-created, this will bump D.Version from -1 to 0.
|
|
|
|
++D.Version;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int64_t DraftStore::addDraft(PathRef File, llvm::Optional<int64_t> Version,
|
|
|
|
llvm::StringRef Contents) {
|
2017-05-16 17:38:59 +08:00
|
|
|
std::lock_guard<std::mutex> Lock(Mutex);
|
|
|
|
|
2020-03-03 22:57:39 +08:00
|
|
|
Draft &D = Drafts[File];
|
|
|
|
updateVersion(D, Version);
|
|
|
|
D.Contents = Contents.str();
|
|
|
|
return D.Version;
|
2017-05-16 17:38:59 +08:00
|
|
|
}
|
|
|
|
|
2020-03-03 22:57:39 +08:00
|
|
|
llvm::Expected<DraftStore::Draft> DraftStore::updateDraft(
|
|
|
|
PathRef File, llvm::Optional<int64_t> Version,
|
|
|
|
llvm::ArrayRef<TextDocumentContentChangeEvent> Changes) {
|
[clangd] Support incremental document syncing
Summary:
This patch adds support for incremental document syncing, as described
in the LSP spec. The protocol specifies ranges in terms of Position (a
line and a character), and our drafts are stored as plain strings. So I
see two things that may not be super efficient for very large files:
- Converting a Position to an offset (the positionToOffset function)
requires searching for end of lines until we reach the desired line.
- When we update a range, we construct a new string, which implies
copying the whole document.
However, for the typical size of a C++ document and the frequency of
update (at which a user types), it may not be an issue. This patch aims
at getting the basic feature in, and we can always improve it later if
we find it's too slow.
Signed-off-by: Simon Marchi <simon.marchi@ericsson.com>
Reviewers: malaperle, ilya-biryukov
Reviewed By: ilya-biryukov
Subscribers: MaskRay, klimek, mgorny, ilya-biryukov, jkorous-apple, ioeric, cfe-commits
Differential Revision: https://reviews.llvm.org/D44272
llvm-svn: 328500
2018-03-26 22:41:40 +08:00
|
|
|
std::lock_guard<std::mutex> Lock(Mutex);
|
|
|
|
|
|
|
|
auto EntryIt = Drafts.find(File);
|
|
|
|
if (EntryIt == Drafts.end()) {
|
[clangd] Add error() function for creating formatv-style llvm::Errors. NFC
Summary:
This is considerably terser than the makeStringError and friends, and
avoids verbosity cliffs that discourage adding log information.
It follows the syntax used in log/elog/vlog/dlog that have been successful.
The main caveats are:
- it's strictly out-of-place in logger.h, though kind of fits thematically and
in implementation
- it claims the "error" identifier, which seems a bit too opinionated
to put higher up in llvm
I've updated some users of StringError mostly at random - there are lots
more mechanical changes but I'd like to get this reviewed before making
them all.
Reviewers: kbobyrev, hokein
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, kadircet, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D83419
2020-07-09 03:49:38 +08:00
|
|
|
return error(llvm::errc::invalid_argument,
|
|
|
|
"Trying to do incremental update on non-added document: {0}",
|
|
|
|
File);
|
[clangd] Support incremental document syncing
Summary:
This patch adds support for incremental document syncing, as described
in the LSP spec. The protocol specifies ranges in terms of Position (a
line and a character), and our drafts are stored as plain strings. So I
see two things that may not be super efficient for very large files:
- Converting a Position to an offset (the positionToOffset function)
requires searching for end of lines until we reach the desired line.
- When we update a range, we construct a new string, which implies
copying the whole document.
However, for the typical size of a C++ document and the frequency of
update (at which a user types), it may not be an issue. This patch aims
at getting the basic feature in, and we can always improve it later if
we find it's too slow.
Signed-off-by: Simon Marchi <simon.marchi@ericsson.com>
Reviewers: malaperle, ilya-biryukov
Reviewed By: ilya-biryukov
Subscribers: MaskRay, klimek, mgorny, ilya-biryukov, jkorous-apple, ioeric, cfe-commits
Differential Revision: https://reviews.llvm.org/D44272
llvm-svn: 328500
2018-03-26 22:41:40 +08:00
|
|
|
}
|
2020-03-03 22:57:39 +08:00
|
|
|
Draft &D = EntryIt->second;
|
|
|
|
std::string Contents = EntryIt->second.Contents;
|
[clangd] Support incremental document syncing
Summary:
This patch adds support for incremental document syncing, as described
in the LSP spec. The protocol specifies ranges in terms of Position (a
line and a character), and our drafts are stored as plain strings. So I
see two things that may not be super efficient for very large files:
- Converting a Position to an offset (the positionToOffset function)
requires searching for end of lines until we reach the desired line.
- When we update a range, we construct a new string, which implies
copying the whole document.
However, for the typical size of a C++ document and the frequency of
update (at which a user types), it may not be an issue. This patch aims
at getting the basic feature in, and we can always improve it later if
we find it's too slow.
Signed-off-by: Simon Marchi <simon.marchi@ericsson.com>
Reviewers: malaperle, ilya-biryukov
Reviewed By: ilya-biryukov
Subscribers: MaskRay, klimek, mgorny, ilya-biryukov, jkorous-apple, ioeric, cfe-commits
Differential Revision: https://reviews.llvm.org/D44272
llvm-svn: 328500
2018-03-26 22:41:40 +08:00
|
|
|
|
|
|
|
for (const TextDocumentContentChangeEvent &Change : Changes) {
|
|
|
|
if (!Change.range) {
|
|
|
|
Contents = Change.text;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
const Position &Start = Change.range->start;
|
2019-01-07 23:45:19 +08:00
|
|
|
llvm::Expected<size_t> StartIndex =
|
|
|
|
positionToOffset(Contents, Start, false);
|
[clangd] Support incremental document syncing
Summary:
This patch adds support for incremental document syncing, as described
in the LSP spec. The protocol specifies ranges in terms of Position (a
line and a character), and our drafts are stored as plain strings. So I
see two things that may not be super efficient for very large files:
- Converting a Position to an offset (the positionToOffset function)
requires searching for end of lines until we reach the desired line.
- When we update a range, we construct a new string, which implies
copying the whole document.
However, for the typical size of a C++ document and the frequency of
update (at which a user types), it may not be an issue. This patch aims
at getting the basic feature in, and we can always improve it later if
we find it's too slow.
Signed-off-by: Simon Marchi <simon.marchi@ericsson.com>
Reviewers: malaperle, ilya-biryukov
Reviewed By: ilya-biryukov
Subscribers: MaskRay, klimek, mgorny, ilya-biryukov, jkorous-apple, ioeric, cfe-commits
Differential Revision: https://reviews.llvm.org/D44272
llvm-svn: 328500
2018-03-26 22:41:40 +08:00
|
|
|
if (!StartIndex)
|
|
|
|
return StartIndex.takeError();
|
|
|
|
|
|
|
|
const Position &End = Change.range->end;
|
2019-01-07 23:45:19 +08:00
|
|
|
llvm::Expected<size_t> EndIndex = positionToOffset(Contents, End, false);
|
[clangd] Support incremental document syncing
Summary:
This patch adds support for incremental document syncing, as described
in the LSP spec. The protocol specifies ranges in terms of Position (a
line and a character), and our drafts are stored as plain strings. So I
see two things that may not be super efficient for very large files:
- Converting a Position to an offset (the positionToOffset function)
requires searching for end of lines until we reach the desired line.
- When we update a range, we construct a new string, which implies
copying the whole document.
However, for the typical size of a C++ document and the frequency of
update (at which a user types), it may not be an issue. This patch aims
at getting the basic feature in, and we can always improve it later if
we find it's too slow.
Signed-off-by: Simon Marchi <simon.marchi@ericsson.com>
Reviewers: malaperle, ilya-biryukov
Reviewed By: ilya-biryukov
Subscribers: MaskRay, klimek, mgorny, ilya-biryukov, jkorous-apple, ioeric, cfe-commits
Differential Revision: https://reviews.llvm.org/D44272
llvm-svn: 328500
2018-03-26 22:41:40 +08:00
|
|
|
if (!EndIndex)
|
|
|
|
return EndIndex.takeError();
|
|
|
|
|
|
|
|
if (*EndIndex < *StartIndex)
|
[clangd] Add error() function for creating formatv-style llvm::Errors. NFC
Summary:
This is considerably terser than the makeStringError and friends, and
avoids verbosity cliffs that discourage adding log information.
It follows the syntax used in log/elog/vlog/dlog that have been successful.
The main caveats are:
- it's strictly out-of-place in logger.h, though kind of fits thematically and
in implementation
- it claims the "error" identifier, which seems a bit too opinionated
to put higher up in llvm
I've updated some users of StringError mostly at random - there are lots
more mechanical changes but I'd like to get this reviewed before making
them all.
Reviewers: kbobyrev, hokein
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, kadircet, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D83419
2020-07-09 03:49:38 +08:00
|
|
|
return error(llvm::errc::invalid_argument,
|
|
|
|
"Range's end position ({0}) is before start position ({1})",
|
|
|
|
End, Start);
|
[clangd] Support incremental document syncing
Summary:
This patch adds support for incremental document syncing, as described
in the LSP spec. The protocol specifies ranges in terms of Position (a
line and a character), and our drafts are stored as plain strings. So I
see two things that may not be super efficient for very large files:
- Converting a Position to an offset (the positionToOffset function)
requires searching for end of lines until we reach the desired line.
- When we update a range, we construct a new string, which implies
copying the whole document.
However, for the typical size of a C++ document and the frequency of
update (at which a user types), it may not be an issue. This patch aims
at getting the basic feature in, and we can always improve it later if
we find it's too slow.
Signed-off-by: Simon Marchi <simon.marchi@ericsson.com>
Reviewers: malaperle, ilya-biryukov
Reviewed By: ilya-biryukov
Subscribers: MaskRay, klimek, mgorny, ilya-biryukov, jkorous-apple, ioeric, cfe-commits
Differential Revision: https://reviews.llvm.org/D44272
llvm-svn: 328500
2018-03-26 22:41:40 +08:00
|
|
|
|
2018-10-23 19:51:53 +08:00
|
|
|
// Since the range length between two LSP positions is dependent on the
|
|
|
|
// contents of the buffer we compute the range length between the start and
|
|
|
|
// end position ourselves and compare it to the range length of the LSP
|
|
|
|
// message to verify the buffers of the client and server are in sync.
|
|
|
|
|
|
|
|
// EndIndex and StartIndex are in bytes, but Change.rangeLength is in UTF-16
|
|
|
|
// code units.
|
|
|
|
ssize_t ComputedRangeLength =
|
|
|
|
lspLength(Contents.substr(*StartIndex, *EndIndex - *StartIndex));
|
|
|
|
|
|
|
|
if (Change.rangeLength && ComputedRangeLength != *Change.rangeLength)
|
[clangd] Add error() function for creating formatv-style llvm::Errors. NFC
Summary:
This is considerably terser than the makeStringError and friends, and
avoids verbosity cliffs that discourage adding log information.
It follows the syntax used in log/elog/vlog/dlog that have been successful.
The main caveats are:
- it's strictly out-of-place in logger.h, though kind of fits thematically and
in implementation
- it claims the "error" identifier, which seems a bit too opinionated
to put higher up in llvm
I've updated some users of StringError mostly at random - there are lots
more mechanical changes but I'd like to get this reviewed before making
them all.
Reviewers: kbobyrev, hokein
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, kadircet, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D83419
2020-07-09 03:49:38 +08:00
|
|
|
return error(llvm::errc::invalid_argument,
|
|
|
|
"Change's rangeLength ({0}) doesn't match the "
|
|
|
|
"computed range length ({1}).",
|
|
|
|
*Change.rangeLength, ComputedRangeLength);
|
[clangd] Support incremental document syncing
Summary:
This patch adds support for incremental document syncing, as described
in the LSP spec. The protocol specifies ranges in terms of Position (a
line and a character), and our drafts are stored as plain strings. So I
see two things that may not be super efficient for very large files:
- Converting a Position to an offset (the positionToOffset function)
requires searching for end of lines until we reach the desired line.
- When we update a range, we construct a new string, which implies
copying the whole document.
However, for the typical size of a C++ document and the frequency of
update (at which a user types), it may not be an issue. This patch aims
at getting the basic feature in, and we can always improve it later if
we find it's too slow.
Signed-off-by: Simon Marchi <simon.marchi@ericsson.com>
Reviewers: malaperle, ilya-biryukov
Reviewed By: ilya-biryukov
Subscribers: MaskRay, klimek, mgorny, ilya-biryukov, jkorous-apple, ioeric, cfe-commits
Differential Revision: https://reviews.llvm.org/D44272
llvm-svn: 328500
2018-03-26 22:41:40 +08:00
|
|
|
|
|
|
|
std::string NewContents;
|
|
|
|
NewContents.reserve(*StartIndex + Change.text.length() +
|
|
|
|
(Contents.length() - *EndIndex));
|
|
|
|
|
|
|
|
NewContents = Contents.substr(0, *StartIndex);
|
|
|
|
NewContents += Change.text;
|
|
|
|
NewContents += Contents.substr(*EndIndex);
|
|
|
|
|
|
|
|
Contents = std::move(NewContents);
|
|
|
|
}
|
|
|
|
|
2020-03-03 22:57:39 +08:00
|
|
|
updateVersion(D, Version);
|
|
|
|
D.Contents = std::move(Contents);
|
|
|
|
return D;
|
[clangd] Support incremental document syncing
Summary:
This patch adds support for incremental document syncing, as described
in the LSP spec. The protocol specifies ranges in terms of Position (a
line and a character), and our drafts are stored as plain strings. So I
see two things that may not be super efficient for very large files:
- Converting a Position to an offset (the positionToOffset function)
requires searching for end of lines until we reach the desired line.
- When we update a range, we construct a new string, which implies
copying the whole document.
However, for the typical size of a C++ document and the frequency of
update (at which a user types), it may not be an issue. This patch aims
at getting the basic feature in, and we can always improve it later if
we find it's too slow.
Signed-off-by: Simon Marchi <simon.marchi@ericsson.com>
Reviewers: malaperle, ilya-biryukov
Reviewed By: ilya-biryukov
Subscribers: MaskRay, klimek, mgorny, ilya-biryukov, jkorous-apple, ioeric, cfe-commits
Differential Revision: https://reviews.llvm.org/D44272
llvm-svn: 328500
2018-03-26 22:41:40 +08:00
|
|
|
}
|
|
|
|
|
2018-03-16 22:30:42 +08:00
|
|
|
void DraftStore::removeDraft(PathRef File) {
|
2017-05-16 17:38:59 +08:00
|
|
|
std::lock_guard<std::mutex> Lock(Mutex);
|
|
|
|
|
2018-03-16 22:30:42 +08:00
|
|
|
Drafts.erase(File);
|
2017-05-16 17:38:59 +08:00
|
|
|
}
|
2018-10-20 23:30:37 +08:00
|
|
|
|
|
|
|
} // namespace clangd
|
|
|
|
} // namespace clang
|