2017-12-19 20:23:48 +08:00
|
|
|
//===--- SourceCode.h - Manipulating source code as strings -----*- C++ -*-===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// Various code that examines C++ source code without using heavy AST machinery
|
|
|
|
// (and often not even the lexer). To be used sparingly!
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_SOURCECODE_H
|
|
|
|
#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_SOURCECODE_H
|
|
|
|
#include "Protocol.h"
|
2018-08-08 16:59:29 +08:00
|
|
|
#include "clang/Basic/Diagnostic.h"
|
2018-02-21 10:39:08 +08:00
|
|
|
#include "clang/Basic/SourceLocation.h"
|
2018-05-11 20:12:08 +08:00
|
|
|
#include "clang/Tooling/Core/Replacement.h"
|
2017-12-19 20:23:48 +08:00
|
|
|
|
|
|
|
namespace clang {
|
2018-02-21 10:39:08 +08:00
|
|
|
class SourceManager;
|
|
|
|
|
2017-12-19 20:23:48 +08:00
|
|
|
namespace clangd {
|
|
|
|
|
|
|
|
/// Turn a [line, column] pair into an offset in Code.
|
Make positionToOffset return llvm::Expected<size_t>
Summary:
To implement incremental document syncing, we want to verify that the
ranges provided by the front-end are valid. Currently, positionToOffset
deals with invalid Positions by returning 0 or Code.size(), which are
two valid offsets. Instead, return an llvm:Expected<size_t> with an
error if the position is invalid.
According to the LSP, if the character value exceeds the number of
characters of the given line, it should default back to the end of the
line. It makes sense in some contexts to have this behavior, and does
not in other contexts. The AllowColumnsBeyondLineLength parameter
allows to decide what to do in that case, default back to the end of the
line, or return an error.
Reviewers: ilya-biryukov
Subscribers: klimek, ilya-biryukov, jkorous-apple, ioeric, cfe-commits
Differential Revision: https://reviews.llvm.org/D44673
llvm-svn: 328100
2018-03-21 22:36:46 +08:00
|
|
|
///
|
[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
2018-04-27 19:59:28 +08:00
|
|
|
/// 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.
|
Make positionToOffset return llvm::Expected<size_t>
Summary:
To implement incremental document syncing, we want to verify that the
ranges provided by the front-end are valid. Currently, positionToOffset
deals with invalid Positions by returning 0 or Code.size(), which are
two valid offsets. Instead, return an llvm:Expected<size_t> with an
error if the position is invalid.
According to the LSP, if the character value exceeds the number of
characters of the given line, it should default back to the end of the
line. It makes sense in some contexts to have this behavior, and does
not in other contexts. The AllowColumnsBeyondLineLength parameter
allows to decide what to do in that case, default back to the end of the
line, or return an error.
Reviewers: ilya-biryukov
Subscribers: klimek, ilya-biryukov, jkorous-apple, ioeric, cfe-commits
Differential Revision: https://reviews.llvm.org/D44673
llvm-svn: 328100
2018-03-21 22:36:46 +08:00
|
|
|
///
|
|
|
|
/// The returned value is in the range [0, Code.size()].
|
|
|
|
llvm::Expected<size_t>
|
|
|
|
positionToOffset(llvm::StringRef Code, Position P,
|
|
|
|
bool AllowColumnsBeyondLineLength = true);
|
2017-12-19 20:23:48 +08:00
|
|
|
|
|
|
|
/// Turn an offset in Code into a [line, column] pair.
|
[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
2018-04-27 19:59:28 +08:00
|
|
|
/// The offset must be in range [0, Code.size()].
|
2017-12-19 20:23:48 +08:00
|
|
|
Position offsetToPosition(llvm::StringRef Code, size_t Offset);
|
|
|
|
|
2018-02-21 10:39:08 +08:00
|
|
|
/// Turn a SourceLocation into a [line, column] pair.
|
Make positionToOffset return llvm::Expected<size_t>
Summary:
To implement incremental document syncing, we want to verify that the
ranges provided by the front-end are valid. Currently, positionToOffset
deals with invalid Positions by returning 0 or Code.size(), which are
two valid offsets. Instead, return an llvm:Expected<size_t> with an
error if the position is invalid.
According to the LSP, if the character value exceeds the number of
characters of the given line, it should default back to the end of the
line. It makes sense in some contexts to have this behavior, and does
not in other contexts. The AllowColumnsBeyondLineLength parameter
allows to decide what to do in that case, default back to the end of the
line, or return an error.
Reviewers: ilya-biryukov
Subscribers: klimek, ilya-biryukov, jkorous-apple, ioeric, cfe-commits
Differential Revision: https://reviews.llvm.org/D44673
llvm-svn: 328100
2018-03-21 22:36:46 +08:00
|
|
|
/// FIXME: This should return an error if the location is invalid.
|
2018-02-21 10:39:08 +08:00
|
|
|
Position sourceLocToPosition(const SourceManager &SM, SourceLocation Loc);
|
|
|
|
|
2018-03-12 23:28:22 +08:00
|
|
|
// Converts a half-open clang source range to an LSP range.
|
|
|
|
// Note that clang also uses closed source ranges, which this can't handle!
|
|
|
|
Range halfOpenToRange(const SourceManager &SM, CharSourceRange R);
|
|
|
|
|
[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
2018-04-27 19:59:28 +08:00
|
|
|
// 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);
|
|
|
|
|
[clangd] Implementation of workspace/symbol request
Summary:
This is a basic implementation of the "workspace/symbol" request which is
used to find symbols by a string query. Since this is similar to code completion
in terms of result, this implementation reuses the "fuzzyFind" in order to get
matches. For now, the scoring algorithm is the same as code completion and
improvements could be done in the future.
The index model doesn't contain quite enough symbols for this to cover
common symbols like methods, enum class enumerators, functions in unamed
namespaces, etc. The index model will be augmented separately to achieve this.
Reviewers: sammccall, ilya-biryukov
Reviewed By: sammccall
Subscribers: jkorous, hokein, simark, sammccall, klimek, mgorny, ilya-biryukov, mgrang, jkorous-apple, ioeric, MaskRay, cfe-commits
Differential Revision: https://reviews.llvm.org/D44882
llvm-svn: 330637
2018-04-24 04:00:52 +08:00
|
|
|
/// From "a::b::c", return {"a::b::", "c"}. Scope is empty if there's no
|
|
|
|
/// qualifier.
|
|
|
|
std::pair<llvm::StringRef, llvm::StringRef>
|
|
|
|
splitQualifiedName(llvm::StringRef QName);
|
|
|
|
|
2018-05-11 20:12:08 +08:00
|
|
|
TextEdit replacementToEdit(StringRef Code, const tooling::Replacement &R);
|
|
|
|
|
|
|
|
std::vector<TextEdit> replacementsToEdits(StringRef Code,
|
|
|
|
const tooling::Replacements &Repls);
|
|
|
|
|
2018-08-08 16:59:29 +08:00
|
|
|
TextEdit toTextEdit(const FixItHint &FixIt, const SourceManager &M,
|
|
|
|
const LangOptions &L);
|
|
|
|
|
[clangd] Avoid duplicates in findDefinitions response
Summary:
When compile_commands.json contains some source files expressed as
relative paths, we can get duplicate responses to findDefinitions. The
responses only differ by the URI, which are different versions of the
same file:
"result": [
{
...
"uri": "file:///home/emaisin/src/ls-interact/cpp-test/build/../src/first.h"
},
{
...
"uri": "file:///home/emaisin/src/ls-interact/cpp-test/src/first.h"
}
]
In getAbsoluteFilePath, we try to obtain the realpath of the FileEntry
by calling tryGetRealPathName. However, this can fail and return an
empty string. It may be bug a bug in clang, but in any case we should
fall back to computing it ourselves if it happens.
I changed getAbsoluteFilePath so that if tryGetRealPathName succeeds, we
return right away (a real path is always absolute). Otherwise, we try
to build an absolute path, as we did before, but we also call
VFS->getRealPath to make sure to get the canonical path (e.g. without
any ".." in it).
Reviewers: malaperle
Subscribers: hokein, ilya-biryukov, ioeric, MaskRay, jkorous, cfe-commits
Differential Revision: https://reviews.llvm.org/D48687
llvm-svn: 339483
2018-08-11 06:27:53 +08:00
|
|
|
/// Get the real/canonical path of \p F. This means:
|
|
|
|
///
|
|
|
|
/// - Absolute path
|
|
|
|
/// - Symlinks resolved
|
|
|
|
/// - No "." or ".." component
|
|
|
|
/// - No duplicate or trailing directory separator
|
|
|
|
///
|
|
|
|
/// This function should be used when sending paths to clients, so that paths
|
|
|
|
/// are normalized as much as possible.
|
|
|
|
llvm::Optional<std::string> getRealPath(const FileEntry *F,
|
|
|
|
const SourceManager &SourceMgr);
|
2018-08-13 16:23:01 +08:00
|
|
|
|
|
|
|
bool IsRangeConsecutive(const Range &Left, const Range &Right);
|
2017-12-19 20:23:48 +08:00
|
|
|
} // namespace clangd
|
|
|
|
} // namespace clang
|
|
|
|
#endif
|