summaryrefslogtreecommitdiffstats
path: root/clang-tools-extra/clangd/SourceCode.h
diff options
context:
space:
mode:
authorSam McCall <sam.mccall@gmail.com>2018-04-27 11:59:28 +0000
committerSam McCall <sam.mccall@gmail.com>2018-04-27 11:59:28 +0000
commita4962cce49d5f993c49e072a72992d523fdcda27 (patch)
tree6c5c61de2b59646931af3251850c25298bf05bb7 /clang-tools-extra/clangd/SourceCode.h
parentf5800a2aa06fb51a99a873bf7c8d84952480f3ce (diff)
downloadbcm5719-llvm-a4962cce49d5f993c49e072a72992d523fdcda27.tar.gz
bcm5719-llvm-a4962cce49d5f993c49e072a72992d523fdcda27.zip
[clangd] Fix unicode handling, using UTF-16 where LSP requires it.
Summary: The Language Server Protocol unfortunately mandates that locations in files be represented by line/column pairs, where the "column" is actually an index into the UTF-16-encoded text of the line. (This is because VSCode is written in JavaScript, which is UTF-16-native). Internally clangd treats source files at UTF-8, the One True Encoding, and generally deals with byte offsets (though there are exceptions). Before this patch, conversions between offsets and LSP Position pretended that Position.character was UTF-8 bytes, which is only true for ASCII lines. Now we examine the text to convert correctly (but don't actually need to transcode it, due to some nice details of the encodings). The updated functions in SourceCode are the blessed way to interact with the Position.character field, and anything else is likely to be wrong. So I also updated the other accesses: - CodeComplete needs a "clang-style" line/column, with column in utf-8 bytes. This is now converted via Position -> offset -> clang line/column (a new function is added to SourceCode.h for the second conversion). - getBeginningOfIdentifier skipped backwards in UTF-16 space, which is will behave badly when it splits a surrogate pair. Skipping backwards in UTF-8 coordinates gives the lexer a fighting chance of getting this right. While here, I clarified(?) the logic comments, fixed a bug with identifiers containing digits, simplified the signature slightly and added a test. This seems likely to cause problems with editors that have the same bug, and treat the protocol as if columns are UTF-8 bytes. But we can find and fix those. Reviewers: hokein Subscribers: klimek, ilya-biryukov, ioeric, MaskRay, jkorous, cfe-commits Differential Revision: https://reviews.llvm.org/D46035 llvm-svn: 331029
Diffstat (limited to 'clang-tools-extra/clangd/SourceCode.h')
-rw-r--r--clang-tools-extra/clangd/SourceCode.h19
1 files changed, 10 insertions, 9 deletions
diff --git a/clang-tools-extra/clangd/SourceCode.h b/clang-tools-extra/clangd/SourceCode.h
index 43fd07015ec..8867b90c3c7 100644
--- a/clang-tools-extra/clangd/SourceCode.h
+++ b/clang-tools-extra/clangd/SourceCode.h
@@ -23,14 +23,9 @@ namespace clangd {
/// Turn a [line, column] pair into an offset in Code.
///
-/// If the character value is greater than the line length, the behavior depends
-/// on AllowColumnsBeyondLineLength:
-///
-/// - if true: default back to the end of the line
-/// - if false: return an error
-///
-/// If the line number is greater than the number of lines in the document,
-/// always return an error.
+/// If P.character exceeds the line length, returns the offset at end-of-line.
+/// (If !AllowColumnsBeyondLineLength, then returns an error instead).
+/// If the line number is out of range, returns an error.
///
/// The returned value is in the range [0, Code.size()].
llvm::Expected<size_t>
@@ -38,7 +33,7 @@ positionToOffset(llvm::StringRef Code, Position P,
bool AllowColumnsBeyondLineLength = true);
/// Turn an offset in Code into a [line, column] pair.
-/// FIXME: This should return an error if the offset is invalid.
+/// The offset must be in range [0, Code.size()].
Position offsetToPosition(llvm::StringRef Code, size_t Offset);
/// Turn a SourceLocation into a [line, column] pair.
@@ -49,6 +44,12 @@ Position sourceLocToPosition(const SourceManager &SM, SourceLocation Loc);
// Note that clang also uses closed source ranges, which this can't handle!
Range halfOpenToRange(const SourceManager &SM, CharSourceRange R);
+// Converts an offset to a clang line/column (1-based, columns are bytes).
+// The offset must be in range [0, Code.size()].
+// Prefer to use SourceManager if one is available.
+std::pair<size_t, size_t> offsetToClangLineColumn(llvm::StringRef Code,
+ size_t Offset);
+
/// From "a::b::c", return {"a::b::", "c"}. Scope is empty if there's no
/// qualifier.
std::pair<llvm::StringRef, llvm::StringRef>
OpenPOWER on IntegriCloud