mirror of
https://github.com/MaskRay/ccls.git
synced 2024-11-26 09:31:59 +00:00
Reduce structs in language_server_api.h and clarify query_utils.h
This commit is contained in:
parent
b98c9a4575
commit
411d49951d
@ -3,7 +3,7 @@
|
|||||||
#include "atomic_object.h"
|
#include "atomic_object.h"
|
||||||
#include "clang_index.h"
|
#include "clang_index.h"
|
||||||
#include "clang_translation_unit.h"
|
#include "clang_translation_unit.h"
|
||||||
#include "language_server_api.h"
|
#include "language_server_api_completion.h"
|
||||||
#include "lru_cache.h"
|
#include "lru_cache.h"
|
||||||
#include "project.h"
|
#include "project.h"
|
||||||
#include "threaded_queue.h"
|
#include "threaded_queue.h"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "language_server_api.h"
|
#include "language_server_api_completion.h"
|
||||||
|
|
||||||
#include <optional.h>
|
#include <optional.h>
|
||||||
|
|
||||||
|
@ -23,6 +23,27 @@
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
struct Out_Progress : public lsOutMessage<Out_Progress> {
|
||||||
|
struct Params {
|
||||||
|
int indexRequestCount = 0;
|
||||||
|
int doIdMapCount = 0;
|
||||||
|
int loadPreviousIndexCount = 0;
|
||||||
|
int onIdMappedCount = 0;
|
||||||
|
int onIndexedCount = 0;
|
||||||
|
int activeThreads = 0;
|
||||||
|
};
|
||||||
|
std::string method = "$cquery/progress";
|
||||||
|
Params params;
|
||||||
|
};
|
||||||
|
MAKE_REFLECT_STRUCT(Out_Progress::Params,
|
||||||
|
indexRequestCount,
|
||||||
|
doIdMapCount,
|
||||||
|
loadPreviousIndexCount,
|
||||||
|
onIdMappedCount,
|
||||||
|
onIndexedCount,
|
||||||
|
activeThreads);
|
||||||
|
MAKE_REFLECT_STRUCT(Out_Progress, jsonrpc, method, params);
|
||||||
|
|
||||||
struct IModificationTimestampFetcher {
|
struct IModificationTimestampFetcher {
|
||||||
virtual ~IModificationTimestampFetcher() = default;
|
virtual ~IModificationTimestampFetcher() = default;
|
||||||
virtual optional<int64_t> GetModificationTime(const std::string& path) = 0;
|
virtual optional<int64_t> GetModificationTime(const std::string& path) = 0;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "language_server_api.h"
|
#include "language_server_api_completion.h"
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
@ -322,14 +322,6 @@ bool lsTextEdit::operator==(const lsTextEdit& that) {
|
|||||||
return range == that.range && newText == that.newText;
|
return range == that.range && newText == that.newText;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& lsCompletionItem::InsertedContent() const {
|
|
||||||
if (textEdit)
|
|
||||||
return textEdit->newText;
|
|
||||||
if (!insertText.empty())
|
|
||||||
return insertText;
|
|
||||||
return label;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Out_ShowLogMessage::method() {
|
std::string Out_ShowLogMessage::method() {
|
||||||
if (display_type == DisplayType::Log)
|
if (display_type == DisplayType::Log)
|
||||||
return "window/logMessage";
|
return "window/logMessage";
|
||||||
|
@ -247,136 +247,6 @@ struct lsTextEdit {
|
|||||||
};
|
};
|
||||||
MAKE_REFLECT_STRUCT(lsTextEdit, range, newText);
|
MAKE_REFLECT_STRUCT(lsTextEdit, range, newText);
|
||||||
|
|
||||||
// Defines whether the insert text in a completion item should be interpreted as
|
|
||||||
// plain text or a snippet.
|
|
||||||
enum class lsInsertTextFormat {
|
|
||||||
// The primary text to be inserted is treated as a plain string.
|
|
||||||
PlainText = 1,
|
|
||||||
|
|
||||||
// The primary text to be inserted is treated as a snippet.
|
|
||||||
//
|
|
||||||
// A snippet can define tab stops and placeholders with `$1`, `$2`
|
|
||||||
// and `${3:foo}`. `$0` defines the final tab stop, it defaults to
|
|
||||||
// the end of the snippet. Placeholders with equal identifiers are linked,
|
|
||||||
// that is typing in one will update others too.
|
|
||||||
//
|
|
||||||
// See also:
|
|
||||||
// https://github.com/Microsoft/vscode/blob/master/src/vs/editor/contrib/snippet/common/snippet.md
|
|
||||||
Snippet = 2
|
|
||||||
};
|
|
||||||
MAKE_REFLECT_TYPE_PROXY(lsInsertTextFormat);
|
|
||||||
|
|
||||||
// The kind of a completion entry.
|
|
||||||
enum class lsCompletionItemKind {
|
|
||||||
Text = 1,
|
|
||||||
Method = 2,
|
|
||||||
Function = 3,
|
|
||||||
Constructor = 4,
|
|
||||||
Field = 5,
|
|
||||||
Variable = 6,
|
|
||||||
Class = 7,
|
|
||||||
Interface = 8,
|
|
||||||
Module = 9,
|
|
||||||
Property = 10,
|
|
||||||
Unit = 11,
|
|
||||||
Value = 12,
|
|
||||||
Enum = 13,
|
|
||||||
Keyword = 14,
|
|
||||||
Snippet = 15,
|
|
||||||
Color = 16,
|
|
||||||
File = 17,
|
|
||||||
Reference = 18,
|
|
||||||
Folder = 19,
|
|
||||||
EnumMember = 20,
|
|
||||||
Constant = 21,
|
|
||||||
Struct = 22,
|
|
||||||
Event = 23,
|
|
||||||
Operator = 24,
|
|
||||||
TypeParameter = 25,
|
|
||||||
};
|
|
||||||
MAKE_REFLECT_TYPE_PROXY(lsCompletionItemKind);
|
|
||||||
|
|
||||||
struct lsCompletionItem {
|
|
||||||
// A set of function parameters. Used internally for signature help. Not sent
|
|
||||||
// to vscode.
|
|
||||||
std::vector<std::string> parameters_;
|
|
||||||
|
|
||||||
// The label of this completion item. By default
|
|
||||||
// also the text that is inserted when selecting
|
|
||||||
// this completion.
|
|
||||||
std::string label;
|
|
||||||
|
|
||||||
// The kind of this completion item. Based of the kind
|
|
||||||
// an icon is chosen by the editor.
|
|
||||||
lsCompletionItemKind kind = lsCompletionItemKind::Text;
|
|
||||||
|
|
||||||
// A human-readable string with additional information
|
|
||||||
// about this item, like type or symbol information.
|
|
||||||
std::string detail;
|
|
||||||
|
|
||||||
// A human-readable string that represents a doc-comment.
|
|
||||||
optional<std::string> documentation;
|
|
||||||
|
|
||||||
// Internal information to order candidates.
|
|
||||||
bool found_;
|
|
||||||
std::string::size_type skip_;
|
|
||||||
unsigned priority_;
|
|
||||||
|
|
||||||
// Use <> or "" by default as include path.
|
|
||||||
bool use_angle_brackets_ = false;
|
|
||||||
|
|
||||||
// A string that shoud be used when comparing this item
|
|
||||||
// with other items. When `falsy` the label is used.
|
|
||||||
std::string sortText;
|
|
||||||
|
|
||||||
// A string that should be used when filtering a set of
|
|
||||||
// completion items. When `falsy` the label is used.
|
|
||||||
optional<std::string> filterText;
|
|
||||||
|
|
||||||
// A string that should be inserted a document when selecting
|
|
||||||
// this completion. When `falsy` the label is used.
|
|
||||||
std::string insertText;
|
|
||||||
|
|
||||||
// The format of the insert text. The format applies to both the `insertText`
|
|
||||||
// property and the `newText` property of a provided `textEdit`.
|
|
||||||
lsInsertTextFormat insertTextFormat = lsInsertTextFormat::PlainText;
|
|
||||||
|
|
||||||
// An edit which is applied to a document when selecting this completion. When
|
|
||||||
// an edit is provided the value of `insertText` is ignored.
|
|
||||||
//
|
|
||||||
// *Note:* The range of the edit must be a single line range and it must
|
|
||||||
// contain the position at which completion has been requested.
|
|
||||||
optional<lsTextEdit> textEdit;
|
|
||||||
|
|
||||||
// An optional array of additional text edits that are applied when
|
|
||||||
// selecting this completion. Edits must not overlap with the main edit
|
|
||||||
// nor with themselves.
|
|
||||||
// std::vector<TextEdit> additionalTextEdits;
|
|
||||||
|
|
||||||
// An optional command that is executed *after* inserting this completion.
|
|
||||||
// *Note* that additional modifications to the current document should be
|
|
||||||
// described with the additionalTextEdits-property. Command command;
|
|
||||||
|
|
||||||
// An data entry field that is preserved on a completion item between
|
|
||||||
// a completion and a completion resolve request.
|
|
||||||
// data ? : any
|
|
||||||
|
|
||||||
// Use this helper to figure out what content the completion item will insert
|
|
||||||
// into the document, as it could live in either |textEdit|, |insertText|, or
|
|
||||||
// |label|.
|
|
||||||
const std::string& InsertedContent() const;
|
|
||||||
};
|
|
||||||
MAKE_REFLECT_STRUCT(lsCompletionItem,
|
|
||||||
label,
|
|
||||||
kind,
|
|
||||||
detail,
|
|
||||||
documentation,
|
|
||||||
sortText,
|
|
||||||
insertText,
|
|
||||||
filterText,
|
|
||||||
insertTextFormat,
|
|
||||||
textEdit);
|
|
||||||
|
|
||||||
struct lsTextDocumentItem {
|
struct lsTextDocumentItem {
|
||||||
// The text document's URI.
|
// The text document's URI.
|
||||||
lsDocumentUri uri;
|
lsDocumentUri uri;
|
||||||
@ -589,39 +459,6 @@ void Reflect(TVisitor& visitor, Out_ShowLogMessage& value) {
|
|||||||
REFLECT_MEMBER_END();
|
REFLECT_MEMBER_END();
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Out_Progress : public lsOutMessage<Out_Progress> {
|
|
||||||
struct Params {
|
|
||||||
int indexRequestCount = 0;
|
|
||||||
int doIdMapCount = 0;
|
|
||||||
int loadPreviousIndexCount = 0;
|
|
||||||
int onIdMappedCount = 0;
|
|
||||||
int onIndexedCount = 0;
|
|
||||||
int activeThreads = 0;
|
|
||||||
};
|
|
||||||
std::string method = "$cquery/progress";
|
|
||||||
Params params;
|
|
||||||
};
|
|
||||||
MAKE_REFLECT_STRUCT(Out_Progress::Params,
|
|
||||||
indexRequestCount,
|
|
||||||
doIdMapCount,
|
|
||||||
loadPreviousIndexCount,
|
|
||||||
onIdMappedCount,
|
|
||||||
onIndexedCount,
|
|
||||||
activeThreads);
|
|
||||||
MAKE_REFLECT_STRUCT(Out_Progress, jsonrpc, method, params);
|
|
||||||
|
|
||||||
struct Out_CquerySetInactiveRegion
|
|
||||||
: public lsOutMessage<Out_CquerySetInactiveRegion> {
|
|
||||||
struct Params {
|
|
||||||
lsDocumentUri uri;
|
|
||||||
std::vector<lsRange> inactiveRegions;
|
|
||||||
};
|
|
||||||
std::string method = "$cquery/setInactiveRegions";
|
|
||||||
Params params;
|
|
||||||
};
|
|
||||||
MAKE_REFLECT_STRUCT(Out_CquerySetInactiveRegion::Params, uri, inactiveRegions);
|
|
||||||
MAKE_REFLECT_STRUCT(Out_CquerySetInactiveRegion, jsonrpc, method, params);
|
|
||||||
|
|
||||||
struct Out_LocationList : public lsOutMessage<Out_LocationList> {
|
struct Out_LocationList : public lsOutMessage<Out_LocationList> {
|
||||||
lsRequestId id;
|
lsRequestId id;
|
||||||
std::vector<lsLocationEx> result;
|
std::vector<lsLocationEx> result;
|
||||||
|
138
src/language_server_api_completion.h
Normal file
138
src/language_server_api_completion.h
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "language_server_api.h"
|
||||||
|
|
||||||
|
// The kind of a completion entry.
|
||||||
|
enum class lsCompletionItemKind {
|
||||||
|
Text = 1,
|
||||||
|
Method = 2,
|
||||||
|
Function = 3,
|
||||||
|
Constructor = 4,
|
||||||
|
Field = 5,
|
||||||
|
Variable = 6,
|
||||||
|
Class = 7,
|
||||||
|
Interface = 8,
|
||||||
|
Module = 9,
|
||||||
|
Property = 10,
|
||||||
|
Unit = 11,
|
||||||
|
Value = 12,
|
||||||
|
Enum = 13,
|
||||||
|
Keyword = 14,
|
||||||
|
Snippet = 15,
|
||||||
|
Color = 16,
|
||||||
|
File = 17,
|
||||||
|
Reference = 18,
|
||||||
|
Folder = 19,
|
||||||
|
EnumMember = 20,
|
||||||
|
Constant = 21,
|
||||||
|
Struct = 22,
|
||||||
|
Event = 23,
|
||||||
|
Operator = 24,
|
||||||
|
TypeParameter = 25,
|
||||||
|
};
|
||||||
|
MAKE_REFLECT_TYPE_PROXY(lsCompletionItemKind);
|
||||||
|
|
||||||
|
// Defines whether the insert text in a completion item should be interpreted as
|
||||||
|
// plain text or a snippet.
|
||||||
|
enum class lsInsertTextFormat {
|
||||||
|
// The primary text to be inserted is treated as a plain string.
|
||||||
|
PlainText = 1,
|
||||||
|
|
||||||
|
// The primary text to be inserted is treated as a snippet.
|
||||||
|
//
|
||||||
|
// A snippet can define tab stops and placeholders with `$1`, `$2`
|
||||||
|
// and `${3:foo}`. `$0` defines the final tab stop, it defaults to
|
||||||
|
// the end of the snippet. Placeholders with equal identifiers are linked,
|
||||||
|
// that is typing in one will update others too.
|
||||||
|
//
|
||||||
|
// See also:
|
||||||
|
// https://github.com/Microsoft/vscode/blob/master/src/vs/editor/contrib/snippet/common/snippet.md
|
||||||
|
Snippet = 2
|
||||||
|
};
|
||||||
|
MAKE_REFLECT_TYPE_PROXY(lsInsertTextFormat);
|
||||||
|
|
||||||
|
struct lsCompletionItem {
|
||||||
|
// A set of function parameters. Used internally for signature help. Not sent
|
||||||
|
// to vscode.
|
||||||
|
std::vector<std::string> parameters_;
|
||||||
|
|
||||||
|
// The label of this completion item. By default
|
||||||
|
// also the text that is inserted when selecting
|
||||||
|
// this completion.
|
||||||
|
std::string label;
|
||||||
|
|
||||||
|
// The kind of this completion item. Based of the kind
|
||||||
|
// an icon is chosen by the editor.
|
||||||
|
lsCompletionItemKind kind = lsCompletionItemKind::Text;
|
||||||
|
|
||||||
|
// A human-readable string with additional information
|
||||||
|
// about this item, like type or symbol information.
|
||||||
|
std::string detail;
|
||||||
|
|
||||||
|
// A human-readable string that represents a doc-comment.
|
||||||
|
optional<std::string> documentation;
|
||||||
|
|
||||||
|
// Internal information to order candidates.
|
||||||
|
bool found_;
|
||||||
|
std::string::size_type skip_;
|
||||||
|
unsigned priority_;
|
||||||
|
|
||||||
|
// Use <> or "" by default as include path.
|
||||||
|
bool use_angle_brackets_ = false;
|
||||||
|
|
||||||
|
// A string that shoud be used when comparing this item
|
||||||
|
// with other items. When `falsy` the label is used.
|
||||||
|
std::string sortText;
|
||||||
|
|
||||||
|
// A string that should be used when filtering a set of
|
||||||
|
// completion items. When `falsy` the label is used.
|
||||||
|
optional<std::string> filterText;
|
||||||
|
|
||||||
|
// A string that should be inserted a document when selecting
|
||||||
|
// this completion. When `falsy` the label is used.
|
||||||
|
std::string insertText;
|
||||||
|
|
||||||
|
// The format of the insert text. The format applies to both the `insertText`
|
||||||
|
// property and the `newText` property of a provided `textEdit`.
|
||||||
|
lsInsertTextFormat insertTextFormat = lsInsertTextFormat::PlainText;
|
||||||
|
|
||||||
|
// An edit which is applied to a document when selecting this completion. When
|
||||||
|
// an edit is provided the value of `insertText` is ignored.
|
||||||
|
//
|
||||||
|
// *Note:* The range of the edit must be a single line range and it must
|
||||||
|
// contain the position at which completion has been requested.
|
||||||
|
optional<lsTextEdit> textEdit;
|
||||||
|
|
||||||
|
// An optional array of additional text edits that are applied when
|
||||||
|
// selecting this completion. Edits must not overlap with the main edit
|
||||||
|
// nor with themselves.
|
||||||
|
// std::vector<TextEdit> additionalTextEdits;
|
||||||
|
|
||||||
|
// An optional command that is executed *after* inserting this completion.
|
||||||
|
// *Note* that additional modifications to the current document should be
|
||||||
|
// described with the additionalTextEdits-property. Command command;
|
||||||
|
|
||||||
|
// An data entry field that is preserved on a completion item between
|
||||||
|
// a completion and a completion resolve request.
|
||||||
|
// data ? : any
|
||||||
|
|
||||||
|
// Use this helper to figure out what content the completion item will insert
|
||||||
|
// into the document, as it could live in either |textEdit|, |insertText|, or
|
||||||
|
// |label|.
|
||||||
|
const std::string& InsertedContent() const {
|
||||||
|
if (textEdit)
|
||||||
|
return textEdit->newText;
|
||||||
|
if (!insertText.empty())
|
||||||
|
return insertText;
|
||||||
|
return label;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
MAKE_REFLECT_STRUCT(lsCompletionItem,
|
||||||
|
label,
|
||||||
|
kind,
|
||||||
|
detail,
|
||||||
|
documentation,
|
||||||
|
sortText,
|
||||||
|
insertText,
|
||||||
|
filterText,
|
||||||
|
insertTextFormat,
|
||||||
|
textEdit);
|
@ -63,31 +63,6 @@ ParseIncludeLineResult ParseIncludeLine(const std::string& line) {
|
|||||||
return {ok, text, match};
|
return {ok, text, match};
|
||||||
}
|
}
|
||||||
|
|
||||||
void DecorateIncludePaths(const std::smatch& match,
|
|
||||||
std::vector<lsCompletionItem>* items) {
|
|
||||||
std::string spaces_after_include = " ";
|
|
||||||
if (match[3].compare("include") == 0 && match[5].length())
|
|
||||||
spaces_after_include = match[4].str();
|
|
||||||
|
|
||||||
std::string prefix =
|
|
||||||
match[1].str() + '#' + match[2].str() + "include" + spaces_after_include;
|
|
||||||
std::string suffix = match[7].str();
|
|
||||||
|
|
||||||
for (lsCompletionItem& item : *items) {
|
|
||||||
char quote0, quote1;
|
|
||||||
if (match[5].compare("<") == 0 ||
|
|
||||||
(match[5].length() == 0 && item.use_angle_brackets_))
|
|
||||||
quote0 = '<', quote1 = '>';
|
|
||||||
else
|
|
||||||
quote0 = quote1 = '"';
|
|
||||||
|
|
||||||
item.textEdit->newText =
|
|
||||||
prefix + quote0 + item.textEdit->newText + quote1 + suffix;
|
|
||||||
item.label = prefix + quote0 + item.label + quote1 + suffix;
|
|
||||||
item.filterText = nullopt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: eliminate |line_number| param.
|
// TODO: eliminate |line_number| param.
|
||||||
optional<lsRange> ExtractQuotedRange(int line_number, const std::string& line) {
|
optional<lsRange> ExtractQuotedRange(int line_number, const std::string& line) {
|
||||||
// Find starting and ending quote.
|
// Find starting and ending quote.
|
||||||
|
@ -23,9 +23,6 @@ struct ParseIncludeLineResult {
|
|||||||
|
|
||||||
ParseIncludeLineResult ParseIncludeLine(const std::string& line);
|
ParseIncludeLineResult ParseIncludeLine(const std::string& line);
|
||||||
|
|
||||||
void DecorateIncludePaths(const std::smatch& match,
|
|
||||||
std::vector<lsCompletionItem>* items);
|
|
||||||
|
|
||||||
// TODO: eliminate |line_number| param.
|
// TODO: eliminate |line_number| param.
|
||||||
optional<lsRange> ExtractQuotedRange(int line_number, const std::string& line);
|
optional<lsRange> ExtractQuotedRange(int line_number, const std::string& line);
|
||||||
|
|
||||||
|
@ -11,6 +11,19 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
struct Out_CquerySetInactiveRegion
|
||||||
|
: public lsOutMessage<Out_CquerySetInactiveRegion> {
|
||||||
|
struct Params {
|
||||||
|
lsDocumentUri uri;
|
||||||
|
std::vector<lsRange> inactiveRegions;
|
||||||
|
};
|
||||||
|
std::string method = "$cquery/setInactiveRegions";
|
||||||
|
Params params;
|
||||||
|
};
|
||||||
|
MAKE_REFLECT_STRUCT(Out_CquerySetInactiveRegion::Params, uri, inactiveRegions);
|
||||||
|
MAKE_REFLECT_STRUCT(Out_CquerySetInactiveRegion, jsonrpc, method, params);
|
||||||
|
|
||||||
struct ScanLineEvent {
|
struct ScanLineEvent {
|
||||||
lsPosition pos;
|
lsPosition pos;
|
||||||
lsPosition end_pos; // Second key when there is a tie for insertion events.
|
lsPosition end_pos; // Second key when there is a tie for insertion events.
|
||||||
|
@ -28,13 +28,13 @@ struct CqueryBaseHandler : BaseMessageHandler<Ipc_CqueryBase> {
|
|||||||
if (sym.kind == SymbolKind::Type) {
|
if (sym.kind == SymbolKind::Type) {
|
||||||
if (const auto* def = db->GetType(sym).AnyDef())
|
if (const auto* def = db->GetType(sym).AnyDef())
|
||||||
out.result =
|
out.result =
|
||||||
GetLsLocationExs(db, working_files, ToUses(db, def->parents),
|
GetLsLocationExs(db, working_files, GetDeclarations(db, def->parents),
|
||||||
config->xref.container, config->xref.maxNum);
|
config->xref.container, config->xref.maxNum);
|
||||||
break;
|
break;
|
||||||
} else if (sym.kind == SymbolKind::Func) {
|
} else if (sym.kind == SymbolKind::Func) {
|
||||||
if (const auto* def = db->GetFunc(sym).AnyDef())
|
if (const auto* def = db->GetFunc(sym).AnyDef())
|
||||||
out.result =
|
out.result =
|
||||||
GetLsLocationExs(db, working_files, ToUses(db, def->base),
|
GetLsLocationExs(db, working_files, GetDeclarations(db, def->base),
|
||||||
config->xref.container, config->xref.maxNum);
|
config->xref.container, config->xref.maxNum);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -28,13 +28,13 @@ struct CqueryDerivedHandler : BaseMessageHandler<Ipc_CqueryDerived> {
|
|||||||
if (sym.kind == SymbolKind::Type) {
|
if (sym.kind == SymbolKind::Type) {
|
||||||
QueryType& type = db->GetType(sym);
|
QueryType& type = db->GetType(sym);
|
||||||
out.result =
|
out.result =
|
||||||
GetLsLocationExs(db, working_files, ToUses(db, type.derived),
|
GetLsLocationExs(db, working_files, GetDeclarations(db, type.derived),
|
||||||
config->xref.container, config->xref.maxNum);
|
config->xref.container, config->xref.maxNum);
|
||||||
break;
|
break;
|
||||||
} else if (sym.kind == SymbolKind::Func) {
|
} else if (sym.kind == SymbolKind::Func) {
|
||||||
QueryFunc& func = db->GetFunc(sym);
|
QueryFunc& func = db->GetFunc(sym);
|
||||||
out.result =
|
out.result =
|
||||||
GetLsLocationExs(db, working_files, ToUses(db, func.derived),
|
GetLsLocationExs(db, working_files, GetDeclarations(db, func.derived),
|
||||||
config->xref.container, config->xref.maxNum);
|
config->xref.container, config->xref.maxNum);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -38,9 +38,9 @@ struct CqueryVarsHandler : BaseMessageHandler<Ipc_CqueryVars> {
|
|||||||
// fallthrough
|
// fallthrough
|
||||||
case SymbolKind::Type: {
|
case SymbolKind::Type: {
|
||||||
QueryType& type = db->types[id.id];
|
QueryType& type = db->types[id.id];
|
||||||
out.result =
|
out.result = GetLsLocationExs(
|
||||||
GetLsLocationExs(db, working_files, ToUses(db, type.instances),
|
db, working_files, GetDeclarations(db, type.instances),
|
||||||
config->xref.container, config->xref.maxNum);
|
config->xref.container, config->xref.maxNum);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -160,9 +160,9 @@ struct TextDocumentCodeLensHandler
|
|||||||
AddCodeLens("ref", "refs", &common, OffsetStartColumn(use, 0),
|
AddCodeLens("ref", "refs", &common, OffsetStartColumn(use, 0),
|
||||||
type.uses, true /*force_display*/);
|
type.uses, true /*force_display*/);
|
||||||
AddCodeLens("derived", "derived", &common, OffsetStartColumn(use, 1),
|
AddCodeLens("derived", "derived", &common, OffsetStartColumn(use, 1),
|
||||||
ToUses(db, type.derived), false /*force_display*/);
|
GetDeclarations(db, type.derived), false /*force_display*/);
|
||||||
AddCodeLens("var", "vars", &common, OffsetStartColumn(use, 2),
|
AddCodeLens("var", "vars", &common, OffsetStartColumn(use, 2),
|
||||||
ToUses(db, type.instances), false /*force_display*/);
|
GetDeclarations(db, type.instances), false /*force_display*/);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SymbolKind::Func: {
|
case SymbolKind::Func: {
|
||||||
@ -210,7 +210,7 @@ struct TextDocumentCodeLensHandler
|
|||||||
|
|
||||||
AddCodeLens("derived", "derived", &common,
|
AddCodeLens("derived", "derived", &common,
|
||||||
OffsetStartColumn(use, offset++),
|
OffsetStartColumn(use, offset++),
|
||||||
ToUses(db, func.derived), false /*force_display*/);
|
GetDeclarations(db, func.derived), false /*force_display*/);
|
||||||
|
|
||||||
// "Base"
|
// "Base"
|
||||||
if (def->base.size() == 1) {
|
if (def->base.size() == 1) {
|
||||||
@ -237,7 +237,7 @@ struct TextDocumentCodeLensHandler
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
AddCodeLens("base", "base", &common, OffsetStartColumn(use, 1),
|
AddCodeLens("base", "base", &common, OffsetStartColumn(use, 1),
|
||||||
ToUses(db, def->base), false /*force_display*/);
|
GetDeclarations(db, def->base), false /*force_display*/);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -81,6 +81,31 @@ bool CompareLsCompletionItem(const lsCompletionItem& lhs,
|
|||||||
return *lhs.filterText < *rhs.filterText;
|
return *lhs.filterText < *rhs.filterText;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DecorateIncludePaths(const std::smatch& match,
|
||||||
|
std::vector<lsCompletionItem>* items) {
|
||||||
|
std::string spaces_after_include = " ";
|
||||||
|
if (match[3].compare("include") == 0 && match[5].length())
|
||||||
|
spaces_after_include = match[4].str();
|
||||||
|
|
||||||
|
std::string prefix =
|
||||||
|
match[1].str() + '#' + match[2].str() + "include" + spaces_after_include;
|
||||||
|
std::string suffix = match[7].str();
|
||||||
|
|
||||||
|
for (lsCompletionItem& item : *items) {
|
||||||
|
char quote0, quote1;
|
||||||
|
if (match[5].compare("<") == 0 ||
|
||||||
|
(match[5].length() == 0 && item.use_angle_brackets_))
|
||||||
|
quote0 = '<', quote1 = '>';
|
||||||
|
else
|
||||||
|
quote0 = quote1 = '"';
|
||||||
|
|
||||||
|
item.textEdit->newText =
|
||||||
|
prefix + quote0 + item.textEdit->newText + quote1 + suffix;
|
||||||
|
item.label = prefix + quote0 + item.label + quote1 + suffix;
|
||||||
|
item.filterText = nullopt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
char* tofixedbase64(T input, char* out) {
|
char* tofixedbase64(T input, char* out) {
|
||||||
const char* digits =
|
const char* digits =
|
||||||
|
@ -27,7 +27,7 @@ MAKE_REFLECT_STRUCT(Out_TextDocumentDefinition, jsonrpc, id, result);
|
|||||||
std::vector<Use> GetGotoDefinitionTargets(QueryDatabase* db, SymbolRef sym) {
|
std::vector<Use> GetGotoDefinitionTargets(QueryDatabase* db, SymbolRef sym) {
|
||||||
switch (sym.kind) {
|
switch (sym.kind) {
|
||||||
case SymbolKind::Var: {
|
case SymbolKind::Var: {
|
||||||
std::vector<Use> ret = GetDeclarationsOfSymbolForGotoDefinition(db, sym);
|
std::vector<Use> ret = GetNonDefDeclarations(db, sym);
|
||||||
// If there is no declaration, jump the its type.
|
// If there is no declaration, jump the its type.
|
||||||
if (ret.empty()) {
|
if (ret.empty()) {
|
||||||
for (auto& def : db->GetVar(sym).def)
|
for (auto& def : db->GetVar(sym).def)
|
||||||
@ -42,7 +42,7 @@ std::vector<Use> GetGotoDefinitionTargets(QueryDatabase* db, SymbolRef sym) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return GetDeclarationsOfSymbolForGotoDefinition(db, sym);
|
return GetNonDefDeclarations(db, sym);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ struct TextDocumentDocumentHighlightHandler
|
|||||||
for (SymbolRef sym :
|
for (SymbolRef sym :
|
||||||
FindSymbolsAtLocation(working_file, file, request->params.position)) {
|
FindSymbolsAtLocation(working_file, file, request->params.position)) {
|
||||||
// Found symbol. Return references to highlight.
|
// Found symbol. Return references to highlight.
|
||||||
EachUse(db, sym, true, [&](Use use) {
|
EachOccurrence(db, sym, true, [&](Use use) {
|
||||||
if (use.file != file_id)
|
if (use.file != file_id)
|
||||||
return;
|
return;
|
||||||
if (optional<lsLocation> ls_loc =
|
if (optional<lsLocation> ls_loc =
|
||||||
|
@ -57,13 +57,13 @@ struct TextDocumentReferencesHandler
|
|||||||
for (const SymbolRef& sym :
|
for (const SymbolRef& sym :
|
||||||
FindSymbolsAtLocation(working_file, file, request->params.position)) {
|
FindSymbolsAtLocation(working_file, file, request->params.position)) {
|
||||||
// Found symbol. Return references.
|
// Found symbol. Return references.
|
||||||
EachUse(db, sym, request->params.context.includeDeclaration,
|
EachOccurrence(
|
||||||
[&](Use use) {
|
db, sym, request->params.context.includeDeclaration, [&](Use use) {
|
||||||
if (use.role & request->params.context.role)
|
if (use.role & request->params.context.role)
|
||||||
if (optional<lsLocationEx> ls_loc = GetLsLocationEx(
|
if (optional<lsLocationEx> ls_loc = GetLsLocationEx(
|
||||||
db, working_files, use, config->xref.container))
|
db, working_files, use, config->xref.container))
|
||||||
out.result.push_back(*ls_loc);
|
out.result.push_back(*ls_loc);
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ lsWorkspaceEdit BuildWorkspaceEdit(QueryDatabase* db,
|
|||||||
const std::string& new_text) {
|
const std::string& new_text) {
|
||||||
std::unordered_map<QueryFileId, lsTextDocumentEdit> path_to_edit;
|
std::unordered_map<QueryFileId, lsTextDocumentEdit> path_to_edit;
|
||||||
|
|
||||||
EachUse(db, sym, true, [&](Use use) {
|
EachOccurrence(db, sym, true, [&](Use use) {
|
||||||
optional<lsLocation> ls_location = GetLsLocation(db, working_files, use);
|
optional<lsLocation> ls_location = GetLsLocation(db, working_files, use);
|
||||||
if (!ls_location)
|
if (!ls_location)
|
||||||
return;
|
return;
|
||||||
|
@ -28,7 +28,7 @@ bool InsertSymbolIntoResult(QueryDatabase* db,
|
|||||||
if (location)
|
if (location)
|
||||||
loc = *location;
|
loc = *location;
|
||||||
else {
|
else {
|
||||||
auto decls = GetDeclarationsOfSymbolForGotoDefinition(db, symbol);
|
auto decls = GetNonDefDeclarations(db, symbol);
|
||||||
if (decls.empty())
|
if (decls.empty())
|
||||||
return false;
|
return false;
|
||||||
loc = decls[0];
|
loc = decls[0];
|
||||||
|
@ -19,8 +19,8 @@ int ComputeRangeSize(const Range& range) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename Q>
|
template <typename Q>
|
||||||
std::vector<Use> ToUsesHelper(std::vector<Q>& entities,
|
std::vector<Use> GetDeclarations(std::vector<Q>& entities,
|
||||||
const std::vector<Id<Q>>& ids) {
|
const std::vector<Id<Q>>& ids) {
|
||||||
std::vector<Use> ret;
|
std::vector<Use> ret;
|
||||||
ret.reserve(ids.size());
|
ret.reserve(ids.size());
|
||||||
for (auto id : ids) {
|
for (auto id : ids) {
|
||||||
@ -87,22 +87,23 @@ Maybe<QueryFileId> GetDeclarationFileForSymbol(QueryDatabase* db,
|
|||||||
return nullopt;
|
return nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Use> ToUses(QueryDatabase* db,
|
std::vector<Use> GetDeclarations(QueryDatabase* db,
|
||||||
const std::vector<QueryFuncId>& ids) {
|
const std::vector<QueryFuncId>& ids) {
|
||||||
return ToUsesHelper(db->funcs, ids);
|
return GetDeclarations(db->funcs, ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Use> ToUses(QueryDatabase* db,
|
std::vector<Use> GetDeclarations(QueryDatabase* db,
|
||||||
const std::vector<QueryTypeId>& ids) {
|
const std::vector<QueryTypeId>& ids) {
|
||||||
return ToUsesHelper(db->types, ids);
|
return GetDeclarations(db->types, ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Use> ToUses(QueryDatabase* db, const std::vector<QueryVarId>& ids) {
|
std::vector<Use> GetDeclarations(QueryDatabase* db,
|
||||||
return ToUsesHelper(db->vars, ids);
|
const std::vector<QueryVarId>& ids) {
|
||||||
|
return GetDeclarations(db->vars, ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Use> GetDeclarationsOfSymbolForGotoDefinition(QueryDatabase* db,
|
std::vector<Use> GetNonDefDeclarations(QueryDatabase* db,
|
||||||
SymbolIdx sym) {
|
SymbolIdx sym) {
|
||||||
switch (sym.kind) {
|
switch (sym.kind) {
|
||||||
case SymbolKind::Func:
|
case SymbolKind::Func:
|
||||||
return db->GetFunc(sym).declarations;
|
return db->GetFunc(sym).declarations;
|
||||||
@ -334,7 +335,6 @@ optional<lsSymbolInformation> GetSymbolInfo(QueryDatabase* db,
|
|||||||
return nullopt;
|
return nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Sort only by range length, not |kind| or |idx|
|
|
||||||
std::vector<SymbolRef> FindSymbolsAtLocation(WorkingFile* working_file,
|
std::vector<SymbolRef> FindSymbolsAtLocation(WorkingFile* working_file,
|
||||||
QueryFile* file,
|
QueryFile* file,
|
||||||
lsPosition position) {
|
lsPosition position) {
|
||||||
|
@ -10,12 +10,13 @@ Maybe<Use> GetDefinitionExtentOfSymbol(QueryDatabase* db, SymbolIdx sym);
|
|||||||
Maybe<QueryFileId> GetDeclarationFileForSymbol(QueryDatabase* db,
|
Maybe<QueryFileId> GetDeclarationFileForSymbol(QueryDatabase* db,
|
||||||
SymbolIdx sym);
|
SymbolIdx sym);
|
||||||
|
|
||||||
std::vector<Use> ToUses(QueryDatabase* db, const std::vector<QueryFuncId>& ids);
|
// Get defining declaration (if exists) or an arbitrary declaration (otherwise) for each id.
|
||||||
std::vector<Use> ToUses(QueryDatabase* db, const std::vector<QueryTypeId>& ids);
|
std::vector<Use> GetDeclarations(QueryDatabase* db, const std::vector<QueryFuncId>& ids);
|
||||||
std::vector<Use> ToUses(QueryDatabase* db, const std::vector<QueryVarId>& ids);
|
std::vector<Use> GetDeclarations(QueryDatabase* db, const std::vector<QueryTypeId>& ids);
|
||||||
|
std::vector<Use> GetDeclarations(QueryDatabase* db, const std::vector<QueryVarId>& ids);
|
||||||
|
|
||||||
std::vector<Use> GetDeclarationsOfSymbolForGotoDefinition(QueryDatabase* db,
|
// Get non-defining declarations.
|
||||||
SymbolIdx sym);
|
std::vector<Use> GetNonDefDeclarations(QueryDatabase* db, SymbolIdx sym);
|
||||||
|
|
||||||
bool HasCallersOnSelfOrBaseOrDerived(QueryDatabase* db, QueryFunc& root);
|
bool HasCallersOnSelfOrBaseOrDerived(QueryDatabase* db, QueryFunc& root);
|
||||||
std::vector<Use> GetCallersForAllBaseFunctions(QueryDatabase* db,
|
std::vector<Use> GetCallersForAllBaseFunctions(QueryDatabase* db,
|
||||||
@ -84,7 +85,7 @@ void EachEntityDef(QueryDatabase* db, SymbolIdx sym, Fn&& fn) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename Fn>
|
template <typename Fn>
|
||||||
void EachUse(QueryDatabase* db, SymbolIdx sym, bool include_decl, Fn&& fn) {
|
void EachOccurrence(QueryDatabase* db, SymbolIdx sym, bool include_decl, Fn&& fn) {
|
||||||
WithEntity(db, sym, [&](const auto& entity) {
|
WithEntity(db, sym, [&](const auto& entity) {
|
||||||
for (Use use : entity.uses)
|
for (Use use : entity.uses)
|
||||||
fn(use);
|
fn(use);
|
||||||
|
Loading…
Reference in New Issue
Block a user