mirror of
https://github.com/MaskRay/ccls.git
synced 2024-11-22 07:35:08 +00:00
Remove ls
prefix from many LSP interfaces
Rename SymbolKind to Kind & lsSymbolKind to SymbolKind Use textDocumentSync: TextDocumentSyncOptions
This commit is contained in:
parent
9a6851c6a5
commit
0d4f4b68c0
@ -60,10 +60,9 @@ struct ProxyFileSystem : FileSystem {
|
|||||||
|
|
||||||
namespace ccls {
|
namespace ccls {
|
||||||
|
|
||||||
lsTextEdit ToTextEdit(const clang::SourceManager &SM,
|
TextEdit ToTextEdit(const clang::SourceManager &SM, const clang::LangOptions &L,
|
||||||
const clang::LangOptions &L,
|
const clang::FixItHint &FixIt) {
|
||||||
const clang::FixItHint &FixIt) {
|
TextEdit edit;
|
||||||
lsTextEdit edit;
|
|
||||||
edit.newText = FixIt.CodeToInsert;
|
edit.newText = FixIt.CodeToInsert;
|
||||||
auto r = FromCharSourceRange(SM, L, FixIt.RemoveRange);
|
auto r = FromCharSourceRange(SM, L, FixIt.RemoveRange);
|
||||||
edit.range =
|
edit.range =
|
||||||
@ -211,7 +210,7 @@ public:
|
|||||||
Flush();
|
Flush();
|
||||||
}
|
}
|
||||||
void HandleDiagnostic(DiagnosticsEngine::Level Level,
|
void HandleDiagnostic(DiagnosticsEngine::Level Level,
|
||||||
const Diagnostic &Info) override {
|
const clang::Diagnostic &Info) override {
|
||||||
DiagnosticConsumer::HandleDiagnostic(Level, Info);
|
DiagnosticConsumer::HandleDiagnostic(Level, Info);
|
||||||
SourceLocation L = Info.getLocation();
|
SourceLocation L = Info.getLocation();
|
||||||
if (!L.isValid()) return;
|
if (!L.isValid()) return;
|
||||||
@ -360,8 +359,8 @@ void *CompletionPreloadMain(void *manager_) {
|
|||||||
int debounce =
|
int debounce =
|
||||||
is_open ? g_config->diagnostics.onOpen : g_config->diagnostics.onSave;
|
is_open ? g_config->diagnostics.onOpen : g_config->diagnostics.onSave;
|
||||||
if (debounce >= 0) {
|
if (debounce >= 0) {
|
||||||
lsTextDocumentIdentifier document;
|
TextDocumentIdentifier document;
|
||||||
document.uri = lsDocumentUri::FromPath(request.path);
|
document.uri = DocumentUri::FromPath(request.path);
|
||||||
manager->DiagnosticsUpdate(request.path, debounce);
|
manager->DiagnosticsUpdate(request.path, debounce);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -491,24 +490,24 @@ void *DiagnosticMain(void *manager_) {
|
|||||||
for (auto &Buf : Bufs)
|
for (auto &Buf : Bufs)
|
||||||
Buf.release();
|
Buf.release();
|
||||||
|
|
||||||
auto Fill = [](const DiagBase &d, lsDiagnostic &ret) {
|
auto Fill = [](const DiagBase &d, Diagnostic &ret) {
|
||||||
ret.range = lsRange{{d.range.start.line, d.range.start.column},
|
ret.range = lsRange{{d.range.start.line, d.range.start.column},
|
||||||
{d.range.end.line, d.range.end.column}};
|
{d.range.end.line, d.range.end.column}};
|
||||||
switch (d.level) {
|
switch (d.level) {
|
||||||
case DiagnosticsEngine::Ignored:
|
case DiagnosticsEngine::Ignored:
|
||||||
// llvm_unreachable
|
// llvm_unreachable
|
||||||
case DiagnosticsEngine::Remark:
|
case DiagnosticsEngine::Remark:
|
||||||
ret.severity = lsDiagnosticSeverity::Hint;
|
ret.severity = DiagnosticSeverity::Hint;
|
||||||
break;
|
break;
|
||||||
case DiagnosticsEngine::Note:
|
case DiagnosticsEngine::Note:
|
||||||
ret.severity = lsDiagnosticSeverity::Information;
|
ret.severity = DiagnosticSeverity::Information;
|
||||||
break;
|
break;
|
||||||
case DiagnosticsEngine::Warning:
|
case DiagnosticsEngine::Warning:
|
||||||
ret.severity = lsDiagnosticSeverity::Warning;
|
ret.severity = DiagnosticSeverity::Warning;
|
||||||
break;
|
break;
|
||||||
case DiagnosticsEngine::Error:
|
case DiagnosticsEngine::Error:
|
||||||
case DiagnosticsEngine::Fatal:
|
case DiagnosticsEngine::Fatal:
|
||||||
ret.severity = lsDiagnosticSeverity::Error;
|
ret.severity = DiagnosticSeverity::Error;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ret.code = d.category;
|
ret.code = d.category;
|
||||||
@ -518,13 +517,13 @@ void *DiagnosticMain(void *manager_) {
|
|||||||
std::vector<Diag> diags = DC.Take();
|
std::vector<Diag> diags = DC.Take();
|
||||||
if (std::shared_ptr<PreambleData> preamble = session->GetPreamble())
|
if (std::shared_ptr<PreambleData> preamble = session->GetPreamble())
|
||||||
diags.insert(diags.end(), preamble->diags.begin(), preamble->diags.end());
|
diags.insert(diags.end(), preamble->diags.begin(), preamble->diags.end());
|
||||||
std::vector<lsDiagnostic> ls_diags;
|
std::vector<Diagnostic> ls_diags;
|
||||||
for (auto &d : diags) {
|
for (auto &d : diags) {
|
||||||
if (!d.concerned)
|
if (!d.concerned)
|
||||||
continue;
|
continue;
|
||||||
std::string buf;
|
std::string buf;
|
||||||
llvm::raw_string_ostream OS(buf);
|
llvm::raw_string_ostream OS(buf);
|
||||||
lsDiagnostic &ls_diag = ls_diags.emplace_back();
|
Diagnostic &ls_diag = ls_diags.emplace_back();
|
||||||
Fill(d, ls_diag);
|
Fill(d, ls_diag);
|
||||||
ls_diag.fixits_ = d.edits;
|
ls_diag.fixits_ = d.edits;
|
||||||
OS << d.message;
|
OS << d.message;
|
||||||
@ -537,7 +536,7 @@ void *DiagnosticMain(void *manager_) {
|
|||||||
for (auto &n : d.notes) {
|
for (auto &n : d.notes) {
|
||||||
if (!n.concerned)
|
if (!n.concerned)
|
||||||
continue;
|
continue;
|
||||||
lsDiagnostic &ls_diag1 = ls_diags.emplace_back();
|
Diagnostic &ls_diag1 = ls_diags.emplace_back();
|
||||||
Fill(n, ls_diag1);
|
Fill(n, ls_diag1);
|
||||||
OS << n.message << "\n\n";
|
OS << n.message << "\n\n";
|
||||||
printDiag(OS, d);
|
printDiag(OS, d);
|
||||||
|
@ -33,10 +33,10 @@ struct DiagBase {
|
|||||||
struct Note : DiagBase {};
|
struct Note : DiagBase {};
|
||||||
struct Diag : DiagBase {
|
struct Diag : DiagBase {
|
||||||
std::vector<Note> notes;
|
std::vector<Note> notes;
|
||||||
std::vector<lsTextEdit> edits;
|
std::vector<TextEdit> edits;
|
||||||
};
|
};
|
||||||
|
|
||||||
lsTextEdit ToTextEdit(const clang::SourceManager &SM,
|
TextEdit ToTextEdit(const clang::SourceManager &SM,
|
||||||
const clang::LangOptions &L,
|
const clang::LangOptions &L,
|
||||||
const clang::FixItHint &FixIt);
|
const clang::FixItHint &FixIt);
|
||||||
|
|
||||||
@ -63,18 +63,18 @@ struct CompletionSession
|
|||||||
|
|
||||||
struct CompletionManager {
|
struct CompletionManager {
|
||||||
using OnDiagnostic = std::function<void(
|
using OnDiagnostic = std::function<void(
|
||||||
std::string path, std::vector<lsDiagnostic> diagnostics)>;
|
std::string path, std::vector<Diagnostic> diagnostics)>;
|
||||||
// If OptConsumer is nullptr, the request has been cancelled.
|
// If OptConsumer is nullptr, the request has been cancelled.
|
||||||
using OnComplete =
|
using OnComplete =
|
||||||
std::function<void(clang::CodeCompleteConsumer *OptConsumer)>;
|
std::function<void(clang::CodeCompleteConsumer *OptConsumer)>;
|
||||||
using OnDropped = std::function<void(lsRequestId request_id)>;
|
using OnDropped = std::function<void(RequestId request_id)>;
|
||||||
|
|
||||||
struct PreloadRequest {
|
struct PreloadRequest {
|
||||||
std::string path;
|
std::string path;
|
||||||
};
|
};
|
||||||
struct CompletionRequest {
|
struct CompletionRequest {
|
||||||
CompletionRequest(const lsRequestId &id,
|
CompletionRequest(const RequestId &id,
|
||||||
const lsTextDocumentIdentifier &document,
|
const TextDocumentIdentifier &document,
|
||||||
const lsPosition &position,
|
const lsPosition &position,
|
||||||
std::unique_ptr<clang::CodeCompleteConsumer> Consumer,
|
std::unique_ptr<clang::CodeCompleteConsumer> Consumer,
|
||||||
clang::CodeCompleteOptions CCOpts,
|
clang::CodeCompleteOptions CCOpts,
|
||||||
@ -83,8 +83,8 @@ struct CompletionManager {
|
|||||||
Consumer(std::move(Consumer)), CCOpts(CCOpts),
|
Consumer(std::move(Consumer)), CCOpts(CCOpts),
|
||||||
on_complete(on_complete) {}
|
on_complete(on_complete) {}
|
||||||
|
|
||||||
lsRequestId id;
|
RequestId id;
|
||||||
lsTextDocumentIdentifier document;
|
TextDocumentIdentifier document;
|
||||||
lsPosition position;
|
lsPosition position;
|
||||||
std::unique_ptr<clang::CodeCompleteConsumer> Consumer;
|
std::unique_ptr<clang::CodeCompleteConsumer> Consumer;
|
||||||
clang::CodeCompleteOptions CCOpts;
|
clang::CodeCompleteOptions CCOpts;
|
||||||
|
@ -10,10 +10,10 @@
|
|||||||
|
|
||||||
namespace ccls {
|
namespace ccls {
|
||||||
template <typename Node>
|
template <typename Node>
|
||||||
std::vector<lsLocation> FlattenHierarchy(const std::optional<Node> &root) {
|
std::vector<Location> FlattenHierarchy(const std::optional<Node> &root) {
|
||||||
if (!root)
|
if (!root)
|
||||||
return {};
|
return {};
|
||||||
std::vector<lsLocation> ret;
|
std::vector<Location> ret;
|
||||||
std::queue<const Node *> q;
|
std::queue<const Node *> q;
|
||||||
for (auto &entry : root->children)
|
for (auto &entry : root->children)
|
||||||
q.push(&entry);
|
q.push(&entry);
|
||||||
|
@ -22,7 +22,7 @@ namespace {
|
|||||||
|
|
||||||
struct CompletionCandidate {
|
struct CompletionCandidate {
|
||||||
std::string absolute_path;
|
std::string absolute_path;
|
||||||
lsCompletionItem completion_item;
|
CompletionItem completion_item;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string ElideLongPath(const std::string &path) {
|
std::string ElideLongPath(const std::string &path) {
|
||||||
@ -74,15 +74,15 @@ bool TrimPath(Project *project, std::string &path) {
|
|||||||
return angle;
|
return angle;
|
||||||
}
|
}
|
||||||
|
|
||||||
lsCompletionItem BuildCompletionItem(const std::string &path,
|
CompletionItem BuildCompletionItem(const std::string &path,
|
||||||
bool use_angle_brackets) {
|
bool use_angle_brackets) {
|
||||||
lsCompletionItem item;
|
CompletionItem item;
|
||||||
item.label = ElideLongPath(path);
|
item.label = ElideLongPath(path);
|
||||||
item.detail = path; // the include path, used in de-duplicating
|
item.detail = path; // the include path, used in de-duplicating
|
||||||
item.textEdit.newText = path;
|
item.textEdit.newText = path;
|
||||||
item.insertTextFormat = lsInsertTextFormat::PlainText;
|
item.insertTextFormat = InsertTextFormat::PlainText;
|
||||||
item.use_angle_brackets_ = use_angle_brackets;
|
item.use_angle_brackets_ = use_angle_brackets;
|
||||||
item.kind = lsCompletionItemKind::File;
|
item.kind = CompletionItemKind::File;
|
||||||
item.priority_ = 0;
|
item.priority_ = 0;
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
@ -124,7 +124,7 @@ void IncludeComplete::Rescan() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void IncludeComplete::InsertCompletionItem(const std::string &absolute_path,
|
void IncludeComplete::InsertCompletionItem(const std::string &absolute_path,
|
||||||
lsCompletionItem &&item) {
|
CompletionItem &&item) {
|
||||||
if (inserted_paths.insert({item.detail, inserted_paths.size()}).second) {
|
if (inserted_paths.insert({item.detail, inserted_paths.size()}).second) {
|
||||||
completion_items.push_back(item);
|
completion_items.push_back(item);
|
||||||
// insert if not found or with shorter include path
|
// insert if not found or with shorter include path
|
||||||
@ -135,7 +135,7 @@ void IncludeComplete::InsertCompletionItem(const std::string &absolute_path,
|
|||||||
completion_items.size() - 1;
|
completion_items.size() - 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
lsCompletionItem &inserted_item =
|
CompletionItem &inserted_item =
|
||||||
completion_items[inserted_paths[item.detail]];
|
completion_items[inserted_paths[item.detail]];
|
||||||
// Update |use_angle_brackets_|, prefer quotes.
|
// Update |use_angle_brackets_|, prefer quotes.
|
||||||
if (!item.use_angle_brackets_)
|
if (!item.use_angle_brackets_)
|
||||||
@ -151,7 +151,7 @@ void IncludeComplete::AddFile(const std::string &path) {
|
|||||||
|
|
||||||
std::string trimmed_path = path;
|
std::string trimmed_path = path;
|
||||||
bool use_angle_brackets = TrimPath(project_, trimmed_path);
|
bool use_angle_brackets = TrimPath(project_, trimmed_path);
|
||||||
lsCompletionItem item = BuildCompletionItem(trimmed_path, use_angle_brackets);
|
CompletionItem item = BuildCompletionItem(trimmed_path, use_angle_brackets);
|
||||||
|
|
||||||
std::unique_lock<std::mutex> lock(completion_items_mutex, std::defer_lock);
|
std::unique_lock<std::mutex> lock(completion_items_mutex, std::defer_lock);
|
||||||
if (is_scanning)
|
if (is_scanning)
|
||||||
@ -190,7 +190,7 @@ void IncludeComplete::InsertIncludesFromDirectory(std::string directory,
|
|||||||
std::move(result.completion_item));
|
std::move(result.completion_item));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<lsCompletionItem>
|
std::optional<CompletionItem>
|
||||||
IncludeComplete::FindCompletionItemForAbsolutePath(
|
IncludeComplete::FindCompletionItemForAbsolutePath(
|
||||||
const std::string &absolute_path) {
|
const std::string &absolute_path) {
|
||||||
std::lock_guard<std::mutex> lock(completion_items_mutex);
|
std::lock_guard<std::mutex> lock(completion_items_mutex);
|
||||||
|
@ -26,18 +26,18 @@ struct IncludeComplete {
|
|||||||
void InsertIncludesFromDirectory(std::string directory,
|
void InsertIncludesFromDirectory(std::string directory,
|
||||||
bool use_angle_brackets);
|
bool use_angle_brackets);
|
||||||
|
|
||||||
std::optional<ccls::lsCompletionItem>
|
std::optional<ccls::CompletionItem>
|
||||||
FindCompletionItemForAbsolutePath(const std::string &absolute_path);
|
FindCompletionItemForAbsolutePath(const std::string &absolute_path);
|
||||||
|
|
||||||
// Insert item to |completion_items|.
|
// Insert item to |completion_items|.
|
||||||
// Update |absolute_path_to_completion_item| and |inserted_paths|.
|
// Update |absolute_path_to_completion_item| and |inserted_paths|.
|
||||||
void InsertCompletionItem(const std::string &absolute_path,
|
void InsertCompletionItem(const std::string &absolute_path,
|
||||||
ccls::lsCompletionItem &&item);
|
ccls::CompletionItem &&item);
|
||||||
|
|
||||||
// Guards |completion_items| when |is_scanning| is true.
|
// Guards |completion_items| when |is_scanning| is true.
|
||||||
std::mutex completion_items_mutex;
|
std::mutex completion_items_mutex;
|
||||||
std::atomic<bool> is_scanning;
|
std::atomic<bool> is_scanning;
|
||||||
std::vector<ccls::lsCompletionItem> completion_items;
|
std::vector<ccls::CompletionItem> completion_items;
|
||||||
|
|
||||||
// Absolute file path to the completion item in |completion_items|.
|
// Absolute file path to the completion item in |completion_items|.
|
||||||
// Keep the one with shortest include path.
|
// Keep the one with shortest include path.
|
||||||
|
170
src/indexer.cc
170
src/indexer.cc
@ -105,110 +105,110 @@ StringRef GetSourceInRange(const SourceManager &SM, const LangOptions &LangOpts,
|
|||||||
BInfo.second);
|
BInfo.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
SymbolKind GetSymbolKind(const Decl *D, lsSymbolKind &kind) {
|
Kind GetKind(const Decl *D, SymbolKind &kind) {
|
||||||
switch (D->getKind()) {
|
switch (D->getKind()) {
|
||||||
case Decl::LinkageSpec:
|
case Decl::LinkageSpec:
|
||||||
return SymbolKind::Invalid;
|
return Kind::Invalid;
|
||||||
case Decl::Namespace:
|
case Decl::Namespace:
|
||||||
kind = lsSymbolKind::Namespace;
|
kind = SymbolKind::Namespace;
|
||||||
return SymbolKind::Type;
|
return Kind::Type;
|
||||||
case Decl::NamespaceAlias:
|
case Decl::NamespaceAlias:
|
||||||
kind = lsSymbolKind::TypeAlias;
|
kind = SymbolKind::TypeAlias;
|
||||||
return SymbolKind::Type;
|
return Kind::Type;
|
||||||
case Decl::ObjCCategory:
|
case Decl::ObjCCategory:
|
||||||
case Decl::ObjCImplementation:
|
case Decl::ObjCImplementation:
|
||||||
case Decl::ObjCInterface:
|
case Decl::ObjCInterface:
|
||||||
case Decl::ObjCProtocol:
|
case Decl::ObjCProtocol:
|
||||||
kind = lsSymbolKind::Interface;
|
kind = SymbolKind::Interface;
|
||||||
return SymbolKind::Type;
|
return Kind::Type;
|
||||||
case Decl::ObjCMethod:
|
case Decl::ObjCMethod:
|
||||||
kind = lsSymbolKind::Method;
|
kind = SymbolKind::Method;
|
||||||
return SymbolKind::Func;
|
return Kind::Func;
|
||||||
case Decl::ObjCProperty:
|
case Decl::ObjCProperty:
|
||||||
kind = lsSymbolKind::Property;
|
kind = SymbolKind::Property;
|
||||||
return SymbolKind::Type;
|
return Kind::Type;
|
||||||
case Decl::ClassTemplate:
|
case Decl::ClassTemplate:
|
||||||
kind = lsSymbolKind::Class;
|
kind = SymbolKind::Class;
|
||||||
return SymbolKind::Type;
|
return Kind::Type;
|
||||||
case Decl::FunctionTemplate:
|
case Decl::FunctionTemplate:
|
||||||
kind = lsSymbolKind::Function;
|
kind = SymbolKind::Function;
|
||||||
return SymbolKind::Func;
|
return Kind::Func;
|
||||||
case Decl::TypeAliasTemplate:
|
case Decl::TypeAliasTemplate:
|
||||||
kind = lsSymbolKind::TypeAlias;
|
kind = SymbolKind::TypeAlias;
|
||||||
return SymbolKind::Type;
|
return Kind::Type;
|
||||||
case Decl::VarTemplate:
|
case Decl::VarTemplate:
|
||||||
kind = lsSymbolKind::Variable;
|
kind = SymbolKind::Variable;
|
||||||
return SymbolKind::Var;
|
return Kind::Var;
|
||||||
case Decl::TemplateTemplateParm:
|
case Decl::TemplateTemplateParm:
|
||||||
kind = lsSymbolKind::TypeParameter;
|
kind = SymbolKind::TypeParameter;
|
||||||
return SymbolKind::Type;
|
return Kind::Type;
|
||||||
case Decl::Enum:
|
case Decl::Enum:
|
||||||
kind = lsSymbolKind::Enum;
|
kind = SymbolKind::Enum;
|
||||||
return SymbolKind::Type;
|
return Kind::Type;
|
||||||
case Decl::CXXRecord:
|
case Decl::CXXRecord:
|
||||||
case Decl::Record:
|
case Decl::Record:
|
||||||
kind = lsSymbolKind::Class;
|
kind = SymbolKind::Class;
|
||||||
// spec has no Union, use Class
|
// spec has no Union, use Class
|
||||||
if (auto *RD = dyn_cast<RecordDecl>(D))
|
if (auto *RD = dyn_cast<RecordDecl>(D))
|
||||||
if (RD->getTagKind() == TTK_Struct)
|
if (RD->getTagKind() == TTK_Struct)
|
||||||
kind = lsSymbolKind::Struct;
|
kind = SymbolKind::Struct;
|
||||||
return SymbolKind::Type;
|
return Kind::Type;
|
||||||
case Decl::ClassTemplateSpecialization:
|
case Decl::ClassTemplateSpecialization:
|
||||||
case Decl::ClassTemplatePartialSpecialization:
|
case Decl::ClassTemplatePartialSpecialization:
|
||||||
kind = lsSymbolKind::Class;
|
kind = SymbolKind::Class;
|
||||||
return SymbolKind::Type;
|
return Kind::Type;
|
||||||
case Decl::TypeAlias:
|
case Decl::TypeAlias:
|
||||||
case Decl::Typedef:
|
case Decl::Typedef:
|
||||||
case Decl::UnresolvedUsingTypename:
|
case Decl::UnresolvedUsingTypename:
|
||||||
kind = lsSymbolKind::TypeAlias;
|
kind = SymbolKind::TypeAlias;
|
||||||
return SymbolKind::Type;
|
return Kind::Type;
|
||||||
case Decl::Binding:
|
case Decl::Binding:
|
||||||
kind = lsSymbolKind::Variable;
|
kind = SymbolKind::Variable;
|
||||||
return SymbolKind::Var;
|
return Kind::Var;
|
||||||
case Decl::Field:
|
case Decl::Field:
|
||||||
case Decl::ObjCIvar:
|
case Decl::ObjCIvar:
|
||||||
kind = lsSymbolKind::Field;
|
kind = SymbolKind::Field;
|
||||||
return SymbolKind::Var;
|
return Kind::Var;
|
||||||
case Decl::Function:
|
case Decl::Function:
|
||||||
kind = lsSymbolKind::Function;
|
kind = SymbolKind::Function;
|
||||||
return SymbolKind::Func;
|
return Kind::Func;
|
||||||
case Decl::CXXMethod: {
|
case Decl::CXXMethod: {
|
||||||
const auto *MD = cast<CXXMethodDecl>(D);
|
const auto *MD = cast<CXXMethodDecl>(D);
|
||||||
kind = MD->isStatic() ? lsSymbolKind::StaticMethod : lsSymbolKind::Method;
|
kind = MD->isStatic() ? SymbolKind::StaticMethod : SymbolKind::Method;
|
||||||
return SymbolKind::Func;
|
return Kind::Func;
|
||||||
}
|
}
|
||||||
case Decl::CXXConstructor:
|
case Decl::CXXConstructor:
|
||||||
kind = lsSymbolKind::Constructor;
|
kind = SymbolKind::Constructor;
|
||||||
return SymbolKind::Func;
|
return Kind::Func;
|
||||||
case Decl::CXXConversion:
|
case Decl::CXXConversion:
|
||||||
case Decl::CXXDestructor:
|
case Decl::CXXDestructor:
|
||||||
kind = lsSymbolKind::Method;
|
kind = SymbolKind::Method;
|
||||||
return SymbolKind::Func;
|
return Kind::Func;
|
||||||
case Decl::Var:
|
case Decl::Var:
|
||||||
case Decl::Decomposition:
|
case Decl::Decomposition:
|
||||||
kind = lsSymbolKind::Variable;
|
kind = SymbolKind::Variable;
|
||||||
return SymbolKind::Var;
|
return Kind::Var;
|
||||||
case Decl::ImplicitParam:
|
case Decl::ImplicitParam:
|
||||||
case Decl::ParmVar:
|
case Decl::ParmVar:
|
||||||
// ccls extension
|
// ccls extension
|
||||||
kind = lsSymbolKind::Parameter;
|
kind = SymbolKind::Parameter;
|
||||||
return SymbolKind::Var;
|
return Kind::Var;
|
||||||
case Decl::VarTemplateSpecialization:
|
case Decl::VarTemplateSpecialization:
|
||||||
case Decl::VarTemplatePartialSpecialization:
|
case Decl::VarTemplatePartialSpecialization:
|
||||||
kind = lsSymbolKind::Variable;
|
kind = SymbolKind::Variable;
|
||||||
return SymbolKind::Var;
|
return Kind::Var;
|
||||||
case Decl::EnumConstant:
|
case Decl::EnumConstant:
|
||||||
kind = lsSymbolKind::EnumMember;
|
kind = SymbolKind::EnumMember;
|
||||||
return SymbolKind::Var;
|
return Kind::Var;
|
||||||
case Decl::UnresolvedUsingValue:
|
case Decl::UnresolvedUsingValue:
|
||||||
kind = lsSymbolKind::Variable;
|
kind = SymbolKind::Variable;
|
||||||
return SymbolKind::Var;
|
return Kind::Var;
|
||||||
case Decl::TranslationUnit:
|
case Decl::TranslationUnit:
|
||||||
return SymbolKind::Invalid;
|
return Kind::Invalid;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
LOG_S(INFO) << "unhandled " << int(D->getKind());
|
LOG_S(INFO) << "unhandled " << int(D->getKind());
|
||||||
return SymbolKind::Invalid;
|
return Kind::Invalid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -605,7 +605,7 @@ public:
|
|||||||
return it->second.first;
|
return it->second.first;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddMacroUse(IndexFile *db, SourceManager &SM, Usr usr, SymbolKind kind,
|
void AddMacroUse(IndexFile *db, SourceManager &SM, Usr usr, Kind kind,
|
||||||
SourceLocation Spell) const {
|
SourceLocation Spell) const {
|
||||||
const FileEntry *FE = SM.getFileEntryForID(SM.getFileID(Spell));
|
const FileEntry *FE = SM.getFileEntryForID(SM.getFileID(Spell));
|
||||||
if (!FE)
|
if (!FE)
|
||||||
@ -617,13 +617,13 @@ public:
|
|||||||
FromTokenRange(SM, Ctx->getLangOpts(), SourceRange(Spell, Spell));
|
FromTokenRange(SM, Ctx->getLangOpts(), SourceRange(Spell, Spell));
|
||||||
Use use{{spell, Role::Dynamic}, lid};
|
Use use{{spell, Role::Dynamic}, lid};
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
case SymbolKind::Func:
|
case Kind::Func:
|
||||||
db->ToFunc(usr).uses.push_back(use);
|
db->ToFunc(usr).uses.push_back(use);
|
||||||
break;
|
break;
|
||||||
case SymbolKind::Type:
|
case Kind::Type:
|
||||||
db->ToType(usr).uses.push_back(use);
|
db->ToType(usr).uses.push_back(use);
|
||||||
break;
|
break;
|
||||||
case SymbolKind::Var:
|
case Kind::Var:
|
||||||
db->ToVar(usr).uses.push_back(use);
|
db->ToVar(usr).uses.push_back(use);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -738,8 +738,8 @@ public:
|
|||||||
IndexFunc *func = nullptr;
|
IndexFunc *func = nullptr;
|
||||||
IndexType *type = nullptr;
|
IndexType *type = nullptr;
|
||||||
IndexVar *var = nullptr;
|
IndexVar *var = nullptr;
|
||||||
lsSymbolKind ls_kind;
|
SymbolKind ls_kind;
|
||||||
SymbolKind kind = GetSymbolKind(D, ls_kind);
|
Kind kind = GetKind(D, ls_kind);
|
||||||
|
|
||||||
if (is_def)
|
if (is_def)
|
||||||
switch (D->getKind()) {
|
switch (D->getKind()) {
|
||||||
@ -773,8 +773,8 @@ public:
|
|||||||
SourceRange R = OrigD->getSourceRange();
|
SourceRange R = OrigD->getSourceRange();
|
||||||
entity->def.spell = {use,
|
entity->def.spell = {use,
|
||||||
FromTokenRangeDefaulted(SM, Lang, R, FE, loc)};
|
FromTokenRangeDefaulted(SM, Lang, R, FE, loc)};
|
||||||
entity->def.parent_kind = lsSymbolKind::File;
|
entity->def.parent_kind = SymbolKind::File;
|
||||||
GetSymbolKind(cast<Decl>(SemDC), entity->def.parent_kind);
|
GetKind(cast<Decl>(SemDC), entity->def.parent_kind);
|
||||||
} else if (is_decl) {
|
} else if (is_decl) {
|
||||||
SourceRange R = OrigD->getSourceRange();
|
SourceRange R = OrigD->getSourceRange();
|
||||||
entity->declarations.push_back(
|
entity->declarations.push_back(
|
||||||
@ -787,13 +787,13 @@ public:
|
|||||||
entity->def.comments = Intern(GetComment(OrigD));
|
entity->def.comments = Intern(GetComment(OrigD));
|
||||||
};
|
};
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
case SymbolKind::Invalid:
|
case Kind::Invalid:
|
||||||
LOG_S(INFO) << "Unhandled " << int(D->getKind()) << " " << info->qualified
|
LOG_S(INFO) << "Unhandled " << int(D->getKind()) << " " << info->qualified
|
||||||
<< " in " << db->path << ":" << loc.start.line + 1;
|
<< " in " << db->path << ":" << loc.start.line + 1;
|
||||||
return true;
|
return true;
|
||||||
case SymbolKind::File:
|
case Kind::File:
|
||||||
return true;
|
return true;
|
||||||
case SymbolKind::Func:
|
case Kind::Func:
|
||||||
func = &db->ToFunc(usr);
|
func = &db->ToFunc(usr);
|
||||||
func->def.kind = ls_kind;
|
func->def.kind = ls_kind;
|
||||||
// Mark as Role::Implicit to span one more column to the left/right.
|
// Mark as Role::Implicit to span one more column to the left/right.
|
||||||
@ -803,40 +803,40 @@ public:
|
|||||||
role = Role(role | Role::Implicit);
|
role = Role(role | Role::Implicit);
|
||||||
do_def_decl(func);
|
do_def_decl(func);
|
||||||
if (Spell != Loc)
|
if (Spell != Loc)
|
||||||
AddMacroUse(db, SM, usr, SymbolKind::Func, Spell);
|
AddMacroUse(db, SM, usr, Kind::Func, Spell);
|
||||||
if (func->def.detailed_name[0] == '\0')
|
if (func->def.detailed_name[0] == '\0')
|
||||||
SetName(D, info->short_name, info->qualified, func->def);
|
SetName(D, info->short_name, info->qualified, func->def);
|
||||||
if (is_def || is_decl) {
|
if (is_def || is_decl) {
|
||||||
const Decl *DC = cast<Decl>(SemDC);
|
const Decl *DC = cast<Decl>(SemDC);
|
||||||
if (GetSymbolKind(DC, ls_kind) == SymbolKind::Type)
|
if (GetKind(DC, ls_kind) == Kind::Type)
|
||||||
db->ToType(GetUsr(DC)).def.funcs.push_back(usr);
|
db->ToType(GetUsr(DC)).def.funcs.push_back(usr);
|
||||||
} else {
|
} else {
|
||||||
const Decl *DC = cast<Decl>(LexDC);
|
const Decl *DC = cast<Decl>(LexDC);
|
||||||
if (GetSymbolKind(DC, ls_kind) == SymbolKind::Func)
|
if (GetKind(DC, ls_kind) == Kind::Func)
|
||||||
db->ToFunc(GetUsr(DC))
|
db->ToFunc(GetUsr(DC))
|
||||||
.def.callees.push_back({loc, usr, SymbolKind::Func, role});
|
.def.callees.push_back({loc, usr, Kind::Func, role});
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SymbolKind::Type:
|
case Kind::Type:
|
||||||
type = &db->ToType(usr);
|
type = &db->ToType(usr);
|
||||||
type->def.kind = ls_kind;
|
type->def.kind = ls_kind;
|
||||||
do_def_decl(type);
|
do_def_decl(type);
|
||||||
if (Spell != Loc)
|
if (Spell != Loc)
|
||||||
AddMacroUse(db, SM, usr, SymbolKind::Type, Spell);
|
AddMacroUse(db, SM, usr, Kind::Type, Spell);
|
||||||
if (type->def.detailed_name[0] == '\0' && info->short_name.size())
|
if (type->def.detailed_name[0] == '\0' && info->short_name.size())
|
||||||
SetName(D, info->short_name, info->qualified, type->def);
|
SetName(D, info->short_name, info->qualified, type->def);
|
||||||
if (is_def || is_decl) {
|
if (is_def || is_decl) {
|
||||||
const Decl *DC = cast<Decl>(SemDC);
|
const Decl *DC = cast<Decl>(SemDC);
|
||||||
if (GetSymbolKind(DC, ls_kind) == SymbolKind::Type)
|
if (GetKind(DC, ls_kind) == Kind::Type)
|
||||||
db->ToType(GetUsr(DC)).def.types.push_back(usr);
|
db->ToType(GetUsr(DC)).def.types.push_back(usr);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SymbolKind::Var:
|
case Kind::Var:
|
||||||
var = &db->ToVar(usr);
|
var = &db->ToVar(usr);
|
||||||
var->def.kind = ls_kind;
|
var->def.kind = ls_kind;
|
||||||
do_def_decl(var);
|
do_def_decl(var);
|
||||||
if (Spell != Loc)
|
if (Spell != Loc)
|
||||||
AddMacroUse(db, SM, usr, SymbolKind::Var, Spell);
|
AddMacroUse(db, SM, usr, Kind::Var, Spell);
|
||||||
if (var->def.detailed_name[0] == '\0')
|
if (var->def.detailed_name[0] == '\0')
|
||||||
SetVarName(D, info->short_name, info->qualified, var->def);
|
SetVarName(D, info->short_name, info->qualified, var->def);
|
||||||
QualType T;
|
QualType T;
|
||||||
@ -844,10 +844,10 @@ public:
|
|||||||
T = VD->getType();
|
T = VD->getType();
|
||||||
if (is_def || is_decl) {
|
if (is_def || is_decl) {
|
||||||
const Decl *DC = cast<Decl>(SemDC);
|
const Decl *DC = cast<Decl>(SemDC);
|
||||||
SymbolKind kind = GetSymbolKind(DC, var->def.parent_kind);
|
Kind kind = GetKind(DC, var->def.parent_kind);
|
||||||
if (kind == SymbolKind::Func)
|
if (kind == Kind::Func)
|
||||||
db->ToFunc(GetUsr(DC)).def.vars.push_back(usr);
|
db->ToFunc(GetUsr(DC)).def.vars.push_back(usr);
|
||||||
else if (kind == SymbolKind::Type && !isa<RecordDecl>(SemDC))
|
else if (kind == Kind::Type && !isa<RecordDecl>(SemDC))
|
||||||
db->ToType(GetUsr(DC)).def.vars.emplace_back(usr, -1);
|
db->ToType(GetUsr(DC)).def.vars.emplace_back(usr, -1);
|
||||||
if (!T.isNull()) {
|
if (!T.isNull()) {
|
||||||
if (auto *BT = T->getAs<BuiltinType>()) {
|
if (auto *BT = T->getAs<BuiltinType>()) {
|
||||||
@ -871,8 +871,8 @@ public:
|
|||||||
FromTokenRange(SM, Lang, R1)};
|
FromTokenRange(SM, Lang, R1)};
|
||||||
type1.def.detailed_name = Intern(info1->short_name);
|
type1.def.detailed_name = Intern(info1->short_name);
|
||||||
type1.def.short_name_size = int16_t(info1->short_name.size());
|
type1.def.short_name_size = int16_t(info1->short_name.size());
|
||||||
type1.def.kind = lsSymbolKind::TypeParameter;
|
type1.def.kind = SymbolKind::TypeParameter;
|
||||||
type1.def.parent_kind = lsSymbolKind::Class;
|
type1.def.parent_kind = SymbolKind::Class;
|
||||||
var->def.type = usr1;
|
var->def.type = usr1;
|
||||||
type1.instances.push_back(usr);
|
type1.instances.push_back(usr);
|
||||||
break;
|
break;
|
||||||
@ -893,7 +893,7 @@ public:
|
|||||||
var->def.spell = {
|
var->def.spell = {
|
||||||
Use{{FromTokenRange(SM, Lang, {L, L}), Role::Definition}, lid},
|
Use{{FromTokenRange(SM, Lang, {L, L}), Role::Definition}, lid},
|
||||||
FromTokenRange(SM, Lang, D->getSourceRange())};
|
FromTokenRange(SM, Lang, D->getSourceRange())};
|
||||||
var->def.parent_kind = lsSymbolKind::Method;
|
var->def.parent_kind = SymbolKind::Method;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -962,7 +962,7 @@ public:
|
|||||||
break;
|
break;
|
||||||
case Decl::ClassTemplateSpecialization:
|
case Decl::ClassTemplateSpecialization:
|
||||||
case Decl::ClassTemplatePartialSpecialization:
|
case Decl::ClassTemplatePartialSpecialization:
|
||||||
type->def.kind = lsSymbolKind::Class;
|
type->def.kind = SymbolKind::Class;
|
||||||
if (is_def) {
|
if (is_def) {
|
||||||
if (auto *ORD = dyn_cast<RecordDecl>(OrigD))
|
if (auto *ORD = dyn_cast<RecordDecl>(OrigD))
|
||||||
CollectRecordMembers(*type, ORD);
|
CollectRecordMembers(*type, ORD);
|
||||||
@ -1090,8 +1090,8 @@ public:
|
|||||||
auto [Name, usr] = GetMacro(Tok);
|
auto [Name, usr] = GetMacro(Tok);
|
||||||
IndexVar &var = db->ToVar(usr);
|
IndexVar &var = db->ToVar(usr);
|
||||||
Range range = FromTokenRange(SM, Lang, {L, L}, &UniqueID);
|
Range range = FromTokenRange(SM, Lang, {L, L}, &UniqueID);
|
||||||
var.def.kind = lsSymbolKind::Macro;
|
var.def.kind = SymbolKind::Macro;
|
||||||
var.def.parent_kind = lsSymbolKind::File;
|
var.def.parent_kind = SymbolKind::File;
|
||||||
if (var.def.spell)
|
if (var.def.spell)
|
||||||
var.declarations.push_back(*var.def.spell);
|
var.declarations.push_back(*var.def.spell);
|
||||||
const MacroInfo *MI = MD->getMacroInfo();
|
const MacroInfo *MI = MD->getMacroInfo();
|
||||||
@ -1344,7 +1344,7 @@ void Reflect(Reader &vis, SymbolRef &v) {
|
|||||||
v.range = Range::FromString(s);
|
v.range = Range::FromString(s);
|
||||||
s = strchr(s, '|');
|
s = strchr(s, '|');
|
||||||
v.usr = strtoull(s + 1, &s, 10);
|
v.usr = strtoull(s + 1, &s, 10);
|
||||||
v.kind = static_cast<SymbolKind>(strtol(s + 1, &s, 10));
|
v.kind = static_cast<Kind>(strtol(s + 1, &s, 10));
|
||||||
v.role = static_cast<Role>(strtol(s + 1, &s, 10));
|
v.role = static_cast<Role>(strtol(s + 1, &s, 10));
|
||||||
} else {
|
} else {
|
||||||
Reflect(vis, v.range);
|
Reflect(vis, v.range);
|
||||||
|
@ -35,7 +35,7 @@ enum class LanguageId;
|
|||||||
|
|
||||||
struct SymbolIdx {
|
struct SymbolIdx {
|
||||||
Usr usr;
|
Usr usr;
|
||||||
SymbolKind kind;
|
Kind kind;
|
||||||
|
|
||||||
bool operator==(const SymbolIdx &o) const {
|
bool operator==(const SymbolIdx &o) const {
|
||||||
return usr == o.usr && kind == o.kind;
|
return usr == o.usr && kind == o.kind;
|
||||||
@ -50,10 +50,10 @@ MAKE_REFLECT_STRUCT(SymbolIdx, usr, kind);
|
|||||||
struct SymbolRef {
|
struct SymbolRef {
|
||||||
Range range;
|
Range range;
|
||||||
Usr usr;
|
Usr usr;
|
||||||
SymbolKind kind;
|
Kind kind;
|
||||||
Role role;
|
Role role;
|
||||||
operator SymbolIdx() const { return {usr, kind}; }
|
operator SymbolIdx() const { return {usr, kind}; }
|
||||||
std::tuple<Range, Usr, SymbolKind, Role> ToTuple() const {
|
std::tuple<Range, Usr, Kind, Role> ToTuple() const {
|
||||||
return std::make_tuple(range, usr, kind, role);
|
return std::make_tuple(range, usr, kind, role);
|
||||||
}
|
}
|
||||||
bool operator==(const SymbolRef &o) const { return ToTuple() == o.ToTuple(); }
|
bool operator==(const SymbolRef &o) const { return ToTuple() == o.ToTuple(); }
|
||||||
@ -62,7 +62,7 @@ struct SymbolRef {
|
|||||||
|
|
||||||
struct ExtentRef : SymbolRef {
|
struct ExtentRef : SymbolRef {
|
||||||
Range extent;
|
Range extent;
|
||||||
std::tuple<Range, Usr, SymbolKind, Role, Range> ToTuple() const {
|
std::tuple<Range, Usr, Kind, Role, Range> ToTuple() const {
|
||||||
return std::make_tuple(range, usr, kind, role, extent);
|
return std::make_tuple(range, usr, kind, role, extent);
|
||||||
}
|
}
|
||||||
bool operator==(const ExtentRef &o) const { return ToTuple() == o.ToTuple(); }
|
bool operator==(const ExtentRef &o) const { return ToTuple() == o.ToTuple(); }
|
||||||
@ -133,8 +133,8 @@ struct FuncDef : NameMixin<FuncDef> {
|
|||||||
int16_t qual_name_offset = 0;
|
int16_t qual_name_offset = 0;
|
||||||
int16_t short_name_offset = 0;
|
int16_t short_name_offset = 0;
|
||||||
int16_t short_name_size = 0;
|
int16_t short_name_size = 0;
|
||||||
lsSymbolKind kind = lsSymbolKind::Unknown;
|
SymbolKind kind = SymbolKind::Unknown;
|
||||||
lsSymbolKind parent_kind = lsSymbolKind::Unknown;
|
SymbolKind parent_kind = SymbolKind::Unknown;
|
||||||
uint8_t storage = clang::SC_None;
|
uint8_t storage = clang::SC_None;
|
||||||
|
|
||||||
std::vector<Usr> GetBases() const { return bases; }
|
std::vector<Usr> GetBases() const { return bases; }
|
||||||
@ -171,8 +171,8 @@ struct TypeDef : NameMixin<TypeDef> {
|
|||||||
int16_t qual_name_offset = 0;
|
int16_t qual_name_offset = 0;
|
||||||
int16_t short_name_offset = 0;
|
int16_t short_name_offset = 0;
|
||||||
int16_t short_name_size = 0;
|
int16_t short_name_size = 0;
|
||||||
lsSymbolKind kind = lsSymbolKind::Unknown;
|
SymbolKind kind = SymbolKind::Unknown;
|
||||||
lsSymbolKind parent_kind = lsSymbolKind::Unknown;
|
SymbolKind parent_kind = SymbolKind::Unknown;
|
||||||
|
|
||||||
std::vector<Usr> GetBases() const { return bases; }
|
std::vector<Usr> GetBases() const { return bases; }
|
||||||
};
|
};
|
||||||
@ -203,18 +203,18 @@ struct VarDef : NameMixin<VarDef> {
|
|||||||
int16_t qual_name_offset = 0;
|
int16_t qual_name_offset = 0;
|
||||||
int16_t short_name_offset = 0;
|
int16_t short_name_offset = 0;
|
||||||
int16_t short_name_size = 0;
|
int16_t short_name_size = 0;
|
||||||
lsSymbolKind kind = lsSymbolKind::Unknown;
|
SymbolKind kind = SymbolKind::Unknown;
|
||||||
lsSymbolKind parent_kind = lsSymbolKind::Unknown;
|
SymbolKind parent_kind = SymbolKind::Unknown;
|
||||||
// Note a variable may have instances of both |None| and |Extern|
|
// Note a variable may have instances of both |None| and |Extern|
|
||||||
// (declaration).
|
// (declaration).
|
||||||
uint8_t storage = clang::SC_None;
|
uint8_t storage = clang::SC_None;
|
||||||
|
|
||||||
bool is_local() const {
|
bool is_local() const {
|
||||||
return spell &&
|
return spell &&
|
||||||
(parent_kind == lsSymbolKind::Function ||
|
(parent_kind == SymbolKind::Function ||
|
||||||
parent_kind == lsSymbolKind::Method ||
|
parent_kind == SymbolKind::Method ||
|
||||||
parent_kind == lsSymbolKind::StaticMethod ||
|
parent_kind == SymbolKind::StaticMethod ||
|
||||||
parent_kind == lsSymbolKind::Constructor) &&
|
parent_kind == SymbolKind::Constructor) &&
|
||||||
storage == clang::SC_None;
|
storage == clang::SC_None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
37
src/lsp.cc
37
src/lsp.cc
@ -10,55 +10,48 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
namespace ccls {
|
namespace ccls {
|
||||||
void Reflect(Reader &visitor, lsRequestId &value) {
|
void Reflect(Reader &visitor, RequestId &value) {
|
||||||
if (visitor.IsInt64()) {
|
if (visitor.IsInt64()) {
|
||||||
value.type = lsRequestId::kInt;
|
value.type = RequestId::kInt;
|
||||||
value.value = int(visitor.GetInt64());
|
value.value = int(visitor.GetInt64());
|
||||||
} else if (visitor.IsInt()) {
|
} else if (visitor.IsInt()) {
|
||||||
value.type = lsRequestId::kInt;
|
value.type = RequestId::kInt;
|
||||||
value.value = visitor.GetInt();
|
value.value = visitor.GetInt();
|
||||||
} else if (visitor.IsString()) {
|
} else if (visitor.IsString()) {
|
||||||
value.type = lsRequestId::kString;
|
value.type = RequestId::kString;
|
||||||
value.value = atoll(visitor.GetString());
|
value.value = atoll(visitor.GetString());
|
||||||
} else {
|
} else {
|
||||||
value.type = lsRequestId::kNone;
|
value.type = RequestId::kNone;
|
||||||
value.value = -1;
|
value.value = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Reflect(Writer &visitor, lsRequestId &value) {
|
void Reflect(Writer &visitor, RequestId &value) {
|
||||||
switch (value.type) {
|
switch (value.type) {
|
||||||
case lsRequestId::kNone:
|
case RequestId::kNone:
|
||||||
visitor.Null();
|
visitor.Null();
|
||||||
break;
|
break;
|
||||||
case lsRequestId::kInt:
|
case RequestId::kInt:
|
||||||
visitor.Int(value.value);
|
visitor.Int(value.value);
|
||||||
break;
|
break;
|
||||||
case lsRequestId::kString:
|
case RequestId::kString:
|
||||||
auto s = std::to_string(value.value);
|
auto s = std::to_string(value.value);
|
||||||
visitor.String(s.c_str(), s.length());
|
visitor.String(s.c_str(), s.length());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lsTextDocumentIdentifier
|
DocumentUri DocumentUri::FromPath(const std::string &path) {
|
||||||
lsVersionedTextDocumentIdentifier::AsTextDocumentIdentifier() const {
|
DocumentUri result;
|
||||||
lsTextDocumentIdentifier result;
|
|
||||||
result.uri = uri;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
lsDocumentUri lsDocumentUri::FromPath(const std::string &path) {
|
|
||||||
lsDocumentUri result;
|
|
||||||
result.SetPath(path);
|
result.SetPath(path);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool lsDocumentUri::operator==(const lsDocumentUri &other) const {
|
bool DocumentUri::operator==(const DocumentUri &other) const {
|
||||||
return raw_uri == other.raw_uri;
|
return raw_uri == other.raw_uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
void lsDocumentUri::SetPath(const std::string &path) {
|
void DocumentUri::SetPath(const std::string &path) {
|
||||||
// file:///c%3A/Users/jacob/Desktop/superindex/indexer/full_tests
|
// file:///c%3A/Users/jacob/Desktop/superindex/indexer/full_tests
|
||||||
raw_uri = path;
|
raw_uri = path;
|
||||||
|
|
||||||
@ -99,7 +92,7 @@ void lsDocumentUri::SetPath(const std::string &path) {
|
|||||||
raw_uri = std::move(t);
|
raw_uri = std::move(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string lsDocumentUri::GetPath() const {
|
std::string DocumentUri::GetPath() const {
|
||||||
if (raw_uri.compare(0, 7, "file://")) {
|
if (raw_uri.compare(0, 7, "file://")) {
|
||||||
LOG_S(WARNING)
|
LOG_S(WARNING)
|
||||||
<< "Received potentially bad URI (not starting with file://): "
|
<< "Received potentially bad URI (not starting with file://): "
|
||||||
@ -136,7 +129,7 @@ std::string lsPosition::ToString() const {
|
|||||||
return std::to_string(line) + ":" + std::to_string(character);
|
return std::to_string(line) + ":" + std::to_string(character);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool lsTextEdit::operator==(const lsTextEdit &that) {
|
bool TextEdit::operator==(const TextEdit &that) {
|
||||||
return range == that.range && newText == that.newText;
|
return range == that.range && newText == that.newText;
|
||||||
}
|
}
|
||||||
} // namespace ccls
|
} // namespace ccls
|
||||||
|
126
src/lsp.hh
126
src/lsp.hh
@ -13,7 +13,7 @@
|
|||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
namespace ccls {
|
namespace ccls {
|
||||||
struct lsRequestId {
|
struct RequestId {
|
||||||
// The client can send the request id as an int or a string. We should output
|
// The client can send the request id as an int or a string. We should output
|
||||||
// the same format we received.
|
// the same format we received.
|
||||||
enum Type { kNone, kInt, kString };
|
enum Type { kNone, kInt, kString };
|
||||||
@ -23,17 +23,17 @@ struct lsRequestId {
|
|||||||
|
|
||||||
bool Valid() const { return type != kNone; }
|
bool Valid() const { return type != kNone; }
|
||||||
};
|
};
|
||||||
void Reflect(Reader &visitor, lsRequestId &value);
|
void Reflect(Reader &visitor, RequestId &value);
|
||||||
void Reflect(Writer &visitor, lsRequestId &value);
|
void Reflect(Writer &visitor, RequestId &value);
|
||||||
|
|
||||||
struct InMessage {
|
struct InMessage {
|
||||||
lsRequestId id;
|
RequestId id;
|
||||||
std::string method;
|
std::string method;
|
||||||
std::unique_ptr<char[]> message;
|
std::unique_ptr<char[]> message;
|
||||||
std::unique_ptr<rapidjson::Document> document;
|
std::unique_ptr<rapidjson::Document> document;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class lsErrorCodes {
|
enum class ErrorCode {
|
||||||
// Defined by JSON RPC
|
// Defined by JSON RPC
|
||||||
ParseError = -32700,
|
ParseError = -32700,
|
||||||
InvalidRequest = -32600,
|
InvalidRequest = -32600,
|
||||||
@ -48,11 +48,11 @@ enum class lsErrorCodes {
|
|||||||
// Defined by the protocol.
|
// Defined by the protocol.
|
||||||
RequestCancelled = -32800,
|
RequestCancelled = -32800,
|
||||||
};
|
};
|
||||||
MAKE_REFLECT_TYPE_PROXY(lsErrorCodes);
|
MAKE_REFLECT_TYPE_PROXY(ErrorCode);
|
||||||
|
|
||||||
struct lsResponseError {
|
struct ResponseError {
|
||||||
// A number indicating the error type that occurred.
|
// A number indicating the error type that occurred.
|
||||||
lsErrorCodes code;
|
ErrorCode code;
|
||||||
|
|
||||||
// A string providing a short description of the error.
|
// A string providing a short description of the error.
|
||||||
std::string message;
|
std::string message;
|
||||||
@ -61,7 +61,7 @@ struct lsResponseError {
|
|||||||
// information about the error. Can be omitted.
|
// information about the error. Can be omitted.
|
||||||
// std::optional<D> data;
|
// std::optional<D> data;
|
||||||
};
|
};
|
||||||
MAKE_REFLECT_STRUCT(lsResponseError, code, message);
|
MAKE_REFLECT_STRUCT(ResponseError, code, message);
|
||||||
|
|
||||||
constexpr char ccls_xref[] = "ccls.xref";
|
constexpr char ccls_xref[] = "ccls.xref";
|
||||||
constexpr char window_showMessage[] = "window/showMessage";
|
constexpr char window_showMessage[] = "window/showMessage";
|
||||||
@ -74,10 +74,10 @@ constexpr char window_showMessage[] = "window/showMessage";
|
|||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
struct lsDocumentUri {
|
struct DocumentUri {
|
||||||
static lsDocumentUri FromPath(const std::string &path);
|
static DocumentUri FromPath(const std::string &path);
|
||||||
|
|
||||||
bool operator==(const lsDocumentUri &other) const;
|
bool operator==(const DocumentUri &other) const;
|
||||||
|
|
||||||
void SetPath(const std::string &path);
|
void SetPath(const std::string &path);
|
||||||
std::string GetPath() const;
|
std::string GetPath() const;
|
||||||
@ -86,7 +86,7 @@ struct lsDocumentUri {
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <typename TVisitor>
|
template <typename TVisitor>
|
||||||
void Reflect(TVisitor &visitor, lsDocumentUri &value) {
|
void Reflect(TVisitor &visitor, DocumentUri &value) {
|
||||||
Reflect(visitor, value.raw_uri);
|
Reflect(visitor, value.raw_uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,20 +115,20 @@ struct lsRange {
|
|||||||
};
|
};
|
||||||
MAKE_REFLECT_STRUCT(lsRange, start, end);
|
MAKE_REFLECT_STRUCT(lsRange, start, end);
|
||||||
|
|
||||||
struct lsLocation {
|
struct Location {
|
||||||
lsDocumentUri uri;
|
DocumentUri uri;
|
||||||
lsRange range;
|
lsRange range;
|
||||||
bool operator==(const lsLocation &o) const {
|
bool operator==(const Location &o) const {
|
||||||
return uri == o.uri && range == o.range;
|
return uri == o.uri && range == o.range;
|
||||||
}
|
}
|
||||||
bool operator<(const lsLocation &o) const {
|
bool operator<(const Location &o) const {
|
||||||
return !(uri.raw_uri == o.uri.raw_uri) ? uri.raw_uri < o.uri.raw_uri
|
return !(uri.raw_uri == o.uri.raw_uri) ? uri.raw_uri < o.uri.raw_uri
|
||||||
: range < o.range;
|
: range < o.range;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
MAKE_REFLECT_STRUCT(lsLocation, uri, range);
|
MAKE_REFLECT_STRUCT(Location, uri, range);
|
||||||
|
|
||||||
enum class lsSymbolKind : uint8_t {
|
enum class SymbolKind : uint8_t {
|
||||||
Unknown = 0,
|
Unknown = 0,
|
||||||
|
|
||||||
File = 1,
|
File = 1,
|
||||||
@ -169,30 +169,28 @@ enum class lsSymbolKind : uint8_t {
|
|||||||
StaticMethod = 254,
|
StaticMethod = 254,
|
||||||
Macro = 255,
|
Macro = 255,
|
||||||
};
|
};
|
||||||
MAKE_REFLECT_TYPE_PROXY(lsSymbolKind);
|
MAKE_REFLECT_TYPE_PROXY(SymbolKind);
|
||||||
|
|
||||||
struct lsSymbolInformation {
|
struct SymbolInformation {
|
||||||
std::string_view name;
|
std::string_view name;
|
||||||
lsSymbolKind kind;
|
SymbolKind kind;
|
||||||
lsLocation location;
|
Location location;
|
||||||
std::optional<std::string_view> containerName;
|
std::optional<std::string_view> containerName;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct lsTextDocumentIdentifier {
|
struct TextDocumentIdentifier {
|
||||||
lsDocumentUri uri;
|
DocumentUri uri;
|
||||||
};
|
};
|
||||||
MAKE_REFLECT_STRUCT(lsTextDocumentIdentifier, uri);
|
MAKE_REFLECT_STRUCT(TextDocumentIdentifier, uri);
|
||||||
|
|
||||||
struct lsVersionedTextDocumentIdentifier {
|
struct VersionedTextDocumentIdentifier {
|
||||||
lsDocumentUri uri;
|
DocumentUri uri;
|
||||||
// The version number of this document. number | null
|
// The version number of this document. number | null
|
||||||
std::optional<int> version;
|
std::optional<int> version;
|
||||||
|
|
||||||
lsTextDocumentIdentifier AsTextDocumentIdentifier() const;
|
|
||||||
};
|
};
|
||||||
MAKE_REFLECT_STRUCT(lsVersionedTextDocumentIdentifier, uri, version);
|
MAKE_REFLECT_STRUCT(VersionedTextDocumentIdentifier, uri, version);
|
||||||
|
|
||||||
struct lsTextEdit {
|
struct TextEdit {
|
||||||
// The range of the text document to be manipulated. To insert
|
// The range of the text document to be manipulated. To insert
|
||||||
// text into a document create a range where start === end.
|
// text into a document create a range where start === end.
|
||||||
lsRange range;
|
lsRange range;
|
||||||
@ -201,13 +199,13 @@ struct lsTextEdit {
|
|||||||
// empty string.
|
// empty string.
|
||||||
std::string newText;
|
std::string newText;
|
||||||
|
|
||||||
bool operator==(const lsTextEdit &that);
|
bool operator==(const TextEdit &that);
|
||||||
};
|
};
|
||||||
MAKE_REFLECT_STRUCT(lsTextEdit, range, newText);
|
MAKE_REFLECT_STRUCT(TextEdit, range, newText);
|
||||||
|
|
||||||
struct lsTextDocumentItem {
|
struct TextDocumentItem {
|
||||||
// The text document's URI.
|
// The text document's URI.
|
||||||
lsDocumentUri uri;
|
DocumentUri uri;
|
||||||
|
|
||||||
// The text document's language identifier.
|
// The text document's language identifier.
|
||||||
std::string languageId;
|
std::string languageId;
|
||||||
@ -219,28 +217,21 @@ struct lsTextDocumentItem {
|
|||||||
// The content of the opened text document.
|
// The content of the opened text document.
|
||||||
std::string text;
|
std::string text;
|
||||||
};
|
};
|
||||||
MAKE_REFLECT_STRUCT(lsTextDocumentItem, uri, languageId, version, text);
|
MAKE_REFLECT_STRUCT(TextDocumentItem, uri, languageId, version, text);
|
||||||
|
|
||||||
struct lsTextDocumentEdit {
|
struct TextDocumentEdit {
|
||||||
// The text document to change.
|
// The text document to change.
|
||||||
lsVersionedTextDocumentIdentifier textDocument;
|
VersionedTextDocumentIdentifier textDocument;
|
||||||
|
|
||||||
// The edits to be applied.
|
// The edits to be applied.
|
||||||
std::vector<lsTextEdit> edits;
|
std::vector<TextEdit> edits;
|
||||||
};
|
};
|
||||||
MAKE_REFLECT_STRUCT(lsTextDocumentEdit, textDocument, edits);
|
MAKE_REFLECT_STRUCT(TextDocumentEdit, textDocument, edits);
|
||||||
|
|
||||||
struct lsWorkspaceEdit {
|
struct WorkspaceEdit {
|
||||||
// Holds changes to existing resources.
|
std::vector<TextDocumentEdit> documentChanges;
|
||||||
// changes ? : { [uri:string]: TextEdit[]; };
|
|
||||||
// std::unordered_map<lsDocumentUri, std::vector<lsTextEdit>> changes;
|
|
||||||
|
|
||||||
// An array of `TextDocumentEdit`s to express changes to specific a specific
|
|
||||||
// version of a text document. Whether a client supports versioned document
|
|
||||||
// edits is expressed via `WorkspaceClientCapabilites.versionedWorkspaceEdit`.
|
|
||||||
std::vector<lsTextDocumentEdit> documentChanges;
|
|
||||||
};
|
};
|
||||||
MAKE_REFLECT_STRUCT(lsWorkspaceEdit, documentChanges);
|
MAKE_REFLECT_STRUCT(WorkspaceEdit, documentChanges);
|
||||||
|
|
||||||
struct TextDocumentContentChangeEvent {
|
struct TextDocumentContentChangeEvent {
|
||||||
// The range of the document that changed.
|
// The range of the document that changed.
|
||||||
@ -252,12 +243,12 @@ struct TextDocumentContentChangeEvent {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct TextDocumentDidChangeParam {
|
struct TextDocumentDidChangeParam {
|
||||||
lsVersionedTextDocumentIdentifier textDocument;
|
VersionedTextDocumentIdentifier textDocument;
|
||||||
std::vector<TextDocumentContentChangeEvent> contentChanges;
|
std::vector<TextDocumentContentChangeEvent> contentChanges;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct WorkspaceFolder {
|
struct WorkspaceFolder {
|
||||||
lsDocumentUri uri;
|
DocumentUri uri;
|
||||||
std::string name;
|
std::string name;
|
||||||
};
|
};
|
||||||
MAKE_REFLECT_STRUCT(WorkspaceFolder, uri, name);
|
MAKE_REFLECT_STRUCT(WorkspaceFolder, uri, name);
|
||||||
@ -266,7 +257,7 @@ MAKE_REFLECT_STRUCT(WorkspaceFolder, uri, name);
|
|||||||
enum class MessageType : int { Error = 1, Warning = 2, Info = 3, Log = 4 };
|
enum class MessageType : int { Error = 1, Warning = 2, Info = 3, Log = 4 };
|
||||||
MAKE_REFLECT_TYPE_PROXY(MessageType)
|
MAKE_REFLECT_TYPE_PROXY(MessageType)
|
||||||
|
|
||||||
enum class lsDiagnosticSeverity {
|
enum class DiagnosticSeverity {
|
||||||
// Reports an error.
|
// Reports an error.
|
||||||
Error = 1,
|
Error = 1,
|
||||||
// Reports a warning.
|
// Reports a warning.
|
||||||
@ -276,15 +267,15 @@ enum class lsDiagnosticSeverity {
|
|||||||
// Reports a hint.
|
// Reports a hint.
|
||||||
Hint = 4
|
Hint = 4
|
||||||
};
|
};
|
||||||
MAKE_REFLECT_TYPE_PROXY(lsDiagnosticSeverity);
|
MAKE_REFLECT_TYPE_PROXY(DiagnosticSeverity);
|
||||||
|
|
||||||
struct lsDiagnostic {
|
struct Diagnostic {
|
||||||
// The range at which the message applies.
|
// The range at which the message applies.
|
||||||
lsRange range;
|
lsRange range;
|
||||||
|
|
||||||
// The diagnostic's severity. Can be omitted. If omitted it is up to the
|
// The diagnostic's severity. Can be omitted. If omitted it is up to the
|
||||||
// client to interpret diagnostics as error, warning, info or hint.
|
// client to interpret diagnostics as error, warning, info or hint.
|
||||||
std::optional<lsDiagnosticSeverity> severity;
|
std::optional<DiagnosticSeverity> severity;
|
||||||
|
|
||||||
// The diagnostic's code. Can be omitted.
|
// The diagnostic's code. Can be omitted.
|
||||||
int code = 0;
|
int code = 0;
|
||||||
@ -297,24 +288,15 @@ struct lsDiagnostic {
|
|||||||
std::string message;
|
std::string message;
|
||||||
|
|
||||||
// Non-serialized set of fixits.
|
// Non-serialized set of fixits.
|
||||||
std::vector<lsTextEdit> fixits_;
|
std::vector<TextEdit> fixits_;
|
||||||
};
|
};
|
||||||
MAKE_REFLECT_STRUCT(lsDiagnostic, range, severity, source, message);
|
MAKE_REFLECT_STRUCT(Diagnostic, range, severity, source, message);
|
||||||
|
|
||||||
struct lsPublishDiagnosticsParams {
|
struct ShowMessageParam {
|
||||||
// The URI for which diagnostic information is reported.
|
|
||||||
lsDocumentUri uri;
|
|
||||||
|
|
||||||
// An array of diagnostic information items.
|
|
||||||
std::vector<lsDiagnostic> diagnostics;
|
|
||||||
};
|
|
||||||
MAKE_REFLECT_STRUCT(lsPublishDiagnosticsParams, uri, diagnostics);
|
|
||||||
|
|
||||||
struct lsShowMessageParams {
|
|
||||||
MessageType type = MessageType::Error;
|
MessageType type = MessageType::Error;
|
||||||
std::string message;
|
std::string message;
|
||||||
};
|
};
|
||||||
MAKE_REFLECT_STRUCT(lsShowMessageParams, type, message);
|
MAKE_REFLECT_STRUCT(ShowMessageParam, type, message);
|
||||||
|
|
||||||
// Used to identify the language at a file level. The ordering is important, as
|
// Used to identify the language at a file level. The ordering is important, as
|
||||||
// a file previously identified as `C`, will be changed to `Cpp` if it
|
// a file previously identified as `C`, will be changed to `Cpp` if it
|
||||||
@ -324,8 +306,8 @@ MAKE_REFLECT_TYPE_PROXY(LanguageId);
|
|||||||
|
|
||||||
// The order matters. In FindSymbolsAtLocation, we want Var/Func ordered in
|
// The order matters. In FindSymbolsAtLocation, we want Var/Func ordered in
|
||||||
// front of others.
|
// front of others.
|
||||||
enum class SymbolKind : uint8_t { Invalid, File, Type, Func, Var };
|
enum class Kind : uint8_t { Invalid, File, Type, Func, Var };
|
||||||
MAKE_REFLECT_TYPE_PROXY(SymbolKind);
|
MAKE_REFLECT_TYPE_PROXY(Kind);
|
||||||
|
|
||||||
enum class Role : uint16_t {
|
enum class Role : uint16_t {
|
||||||
None = 0,
|
None = 0,
|
||||||
|
@ -18,7 +18,7 @@ std::optional<Matcher> Matcher::Create(const std::string &search) {
|
|||||||
);
|
);
|
||||||
return m;
|
return m;
|
||||||
} catch (const std::exception &e) {
|
} catch (const std::exception &e) {
|
||||||
lsShowMessageParams params;
|
ShowMessageParam params;
|
||||||
params.type = MessageType::Error;
|
params.type = MessageType::Error;
|
||||||
params.message =
|
params.message =
|
||||||
"failed to parse EMCAScript regex " + search + " : " + e.what();
|
"failed to parse EMCAScript regex " + search + " : " + e.what();
|
||||||
|
@ -31,9 +31,9 @@ MAKE_REFLECT_STRUCT(CodeActionParam::Context, diagnostics);
|
|||||||
MAKE_REFLECT_STRUCT(CodeActionParam, textDocument, range, context);
|
MAKE_REFLECT_STRUCT(CodeActionParam, textDocument, range, context);
|
||||||
|
|
||||||
// completion
|
// completion
|
||||||
MAKE_REFLECT_TYPE_PROXY(lsCompletionTriggerKind);
|
MAKE_REFLECT_TYPE_PROXY(CompletionTriggerKind);
|
||||||
MAKE_REFLECT_STRUCT(lsCompletionContext, triggerKind, triggerCharacter);
|
MAKE_REFLECT_STRUCT(CompletionContext, triggerKind, triggerCharacter);
|
||||||
MAKE_REFLECT_STRUCT(lsCompletionParams, textDocument, position, context);
|
MAKE_REFLECT_STRUCT(CompletionParam, textDocument, position, context);
|
||||||
|
|
||||||
// formatting
|
// formatting
|
||||||
MAKE_REFLECT_STRUCT(FormattingOptions, tabSize, insertSpaces);
|
MAKE_REFLECT_STRUCT(FormattingOptions, tabSize, insertSpaces);
|
||||||
@ -53,8 +53,8 @@ MAKE_REFLECT_STRUCT(WorkspaceSymbolParam, query, folders);
|
|||||||
namespace {
|
namespace {
|
||||||
struct CclsSemanticHighlightSymbol {
|
struct CclsSemanticHighlightSymbol {
|
||||||
int id = 0;
|
int id = 0;
|
||||||
lsSymbolKind parentKind;
|
SymbolKind parentKind;
|
||||||
lsSymbolKind kind;
|
SymbolKind kind;
|
||||||
uint8_t storage;
|
uint8_t storage;
|
||||||
std::vector<std::pair<int, int>> ranges;
|
std::vector<std::pair<int, int>> ranges;
|
||||||
|
|
||||||
@ -63,7 +63,7 @@ struct CclsSemanticHighlightSymbol {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct CclsSemanticHighlightParams {
|
struct CclsSemanticHighlightParams {
|
||||||
lsDocumentUri uri;
|
DocumentUri uri;
|
||||||
std::vector<CclsSemanticHighlightSymbol> symbols;
|
std::vector<CclsSemanticHighlightSymbol> symbols;
|
||||||
};
|
};
|
||||||
MAKE_REFLECT_STRUCT(CclsSemanticHighlightSymbol, id, parentKind, kind, storage,
|
MAKE_REFLECT_STRUCT(CclsSemanticHighlightSymbol, id, parentKind, kind, storage,
|
||||||
@ -71,7 +71,7 @@ MAKE_REFLECT_STRUCT(CclsSemanticHighlightSymbol, id, parentKind, kind, storage,
|
|||||||
MAKE_REFLECT_STRUCT(CclsSemanticHighlightParams, uri, symbols);
|
MAKE_REFLECT_STRUCT(CclsSemanticHighlightParams, uri, symbols);
|
||||||
|
|
||||||
struct CclsSetSkippedRangesParams {
|
struct CclsSetSkippedRangesParams {
|
||||||
lsDocumentUri uri;
|
DocumentUri uri;
|
||||||
std::vector<lsRange> skippedRanges;
|
std::vector<lsRange> skippedRanges;
|
||||||
};
|
};
|
||||||
MAKE_REFLECT_STRUCT(CclsSetSkippedRangesParams, uri, skippedRanges);
|
MAKE_REFLECT_STRUCT(CclsSetSkippedRangesParams, uri, skippedRanges);
|
||||||
@ -194,19 +194,19 @@ void MessageHandler::Run(InMessage &msg) {
|
|||||||
try {
|
try {
|
||||||
it->second(reader, reply);
|
it->second(reader, reply);
|
||||||
} catch (std::invalid_argument &ex) {
|
} catch (std::invalid_argument &ex) {
|
||||||
lsResponseError err;
|
ResponseError err;
|
||||||
err.code = lsErrorCodes::InvalidParams;
|
err.code = ErrorCode::InvalidParams;
|
||||||
err.message = "invalid params of " + msg.method + ": " + ex.what();
|
err.message = "invalid params of " + msg.method + ": " + ex.what();
|
||||||
reply.Error(err);
|
reply.Error(err);
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
lsResponseError err;
|
ResponseError err;
|
||||||
err.code = lsErrorCodes::InternalError;
|
err.code = ErrorCode::InternalError;
|
||||||
err.message = "failed to process " + msg.method;
|
err.message = "failed to process " + msg.method;
|
||||||
reply.Error(err);
|
reply.Error(err);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
lsResponseError err;
|
ResponseError err;
|
||||||
err.code = lsErrorCodes::MethodNotFound;
|
err.code = ErrorCode::MethodNotFound;
|
||||||
err.message = "unknown request " + msg.method;
|
err.message = "unknown request " + msg.method;
|
||||||
reply.Error(err);
|
reply.Error(err);
|
||||||
}
|
}
|
||||||
@ -246,12 +246,12 @@ QueryFile *MessageHandler::FindFile(ReplyOnce &reply,
|
|||||||
for (auto &[root, folder] : project->root2folder)
|
for (auto &[root, folder] : project->root2folder)
|
||||||
has_entry |= folder.path2entry_index.count(path);
|
has_entry |= folder.path2entry_index.count(path);
|
||||||
}
|
}
|
||||||
lsResponseError err;
|
ResponseError err;
|
||||||
if (has_entry) {
|
if (has_entry) {
|
||||||
err.code = lsErrorCodes::ServerNotInitialized;
|
err.code = ErrorCode::ServerNotInitialized;
|
||||||
err.message = path + " is being indexed";
|
err.message = path + " is being indexed";
|
||||||
} else {
|
} else {
|
||||||
err.code = lsErrorCodes::InternalError;
|
err.code = ErrorCode::InternalError;
|
||||||
err.message = "unable to find " + path;
|
err.message = "unable to find " + path;
|
||||||
}
|
}
|
||||||
reply.Error(err);
|
reply.Error(err);
|
||||||
@ -262,7 +262,7 @@ QueryFile *MessageHandler::FindFile(ReplyOnce &reply,
|
|||||||
|
|
||||||
void EmitSkippedRanges(WorkingFile *wfile, QueryFile &file) {
|
void EmitSkippedRanges(WorkingFile *wfile, QueryFile &file) {
|
||||||
CclsSetSkippedRangesParams params;
|
CclsSetSkippedRangesParams params;
|
||||||
params.uri = lsDocumentUri::FromPath(wfile->filename);
|
params.uri = DocumentUri::FromPath(wfile->filename);
|
||||||
for (Range skipped : file.def->skipped_ranges)
|
for (Range skipped : file.def->skipped_ranges)
|
||||||
if (auto ls_skipped = GetLsRange(wfile, skipped))
|
if (auto ls_skipped = GetLsRange(wfile, skipped))
|
||||||
params.skippedRanges.push_back(*ls_skipped);
|
params.skippedRanges.push_back(*ls_skipped);
|
||||||
@ -282,13 +282,13 @@ void EmitSemanticHighlight(DB *db, WorkingFile *wfile, QueryFile &file) {
|
|||||||
for (auto [sym, refcnt] : file.symbol2refcnt) {
|
for (auto [sym, refcnt] : file.symbol2refcnt) {
|
||||||
if (refcnt <= 0) continue;
|
if (refcnt <= 0) continue;
|
||||||
std::string_view detailed_name;
|
std::string_view detailed_name;
|
||||||
lsSymbolKind parent_kind = lsSymbolKind::Unknown;
|
SymbolKind parent_kind = SymbolKind::Unknown;
|
||||||
lsSymbolKind kind = lsSymbolKind::Unknown;
|
SymbolKind kind = SymbolKind::Unknown;
|
||||||
uint8_t storage = SC_None;
|
uint8_t storage = SC_None;
|
||||||
int idx;
|
int idx;
|
||||||
// This switch statement also filters out symbols that are not highlighted.
|
// This switch statement also filters out symbols that are not highlighted.
|
||||||
switch (sym.kind) {
|
switch (sym.kind) {
|
||||||
case SymbolKind::Func: {
|
case Kind::Func: {
|
||||||
idx = db->func_usr[sym.usr];
|
idx = db->func_usr[sym.usr];
|
||||||
const QueryFunc &func = db->funcs[idx];
|
const QueryFunc &func = db->funcs[idx];
|
||||||
const QueryFunc::Def *def = func.AnyDef();
|
const QueryFunc::Def *def = func.AnyDef();
|
||||||
@ -322,7 +322,7 @@ void EmitSemanticHighlight(DB *db, WorkingFile *wfile, QueryFile &file) {
|
|||||||
sym.range.end.column = start_col + concise_name.size();
|
sym.range.end.column = start_col + concise_name.size();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SymbolKind::Type: {
|
case Kind::Type: {
|
||||||
idx = db->type_usr[sym.usr];
|
idx = db->type_usr[sym.usr];
|
||||||
const QueryType &type = db->types[idx];
|
const QueryType &type = db->types[idx];
|
||||||
for (auto &def : type.def) {
|
for (auto &def : type.def) {
|
||||||
@ -335,7 +335,7 @@ void EmitSemanticHighlight(DB *db, WorkingFile *wfile, QueryFile &file) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SymbolKind::Var: {
|
case Kind::Var: {
|
||||||
idx = db->var_usr[sym.usr];
|
idx = db->var_usr[sym.usr];
|
||||||
const QueryVar &var = db->vars[idx];
|
const QueryVar &var = db->vars[idx];
|
||||||
for (auto &def : var.def) {
|
for (auto &def : var.def) {
|
||||||
@ -410,7 +410,7 @@ void EmitSemanticHighlight(DB *db, WorkingFile *wfile, QueryFile &file) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
CclsSemanticHighlightParams params;
|
CclsSemanticHighlightParams params;
|
||||||
params.uri = lsDocumentUri::FromPath(wfile->filename);
|
params.uri = DocumentUri::FromPath(wfile->filename);
|
||||||
// Transform lsRange into pair<int, int> (offset pairs)
|
// Transform lsRange into pair<int, int> (offset pairs)
|
||||||
if (!g_config->highlight.lsRanges) {
|
if (!g_config->highlight.lsRanges) {
|
||||||
std::vector<std::pair<lsRange, CclsSemanticHighlightSymbol *>> scratch;
|
std::vector<std::pair<lsRange, CclsSemanticHighlightSymbol *>> scratch;
|
||||||
|
@ -20,54 +20,54 @@ struct WorkingFile;
|
|||||||
struct WorkingFiles;
|
struct WorkingFiles;
|
||||||
|
|
||||||
namespace pipeline {
|
namespace pipeline {
|
||||||
void Reply(lsRequestId id, const std::function<void(Writer &)> &fn);
|
void Reply(RequestId id, const std::function<void(Writer &)> &fn);
|
||||||
void ReplyError(lsRequestId id, const std::function<void(Writer &)> &fn);
|
void ReplyError(RequestId id, const std::function<void(Writer &)> &fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct EmptyParam {
|
struct EmptyParam {
|
||||||
bool placeholder;
|
bool placeholder;
|
||||||
};
|
};
|
||||||
struct TextDocumentParam {
|
struct TextDocumentParam {
|
||||||
lsTextDocumentIdentifier textDocument;
|
TextDocumentIdentifier textDocument;
|
||||||
};
|
};
|
||||||
struct DidOpenTextDocumentParam {
|
struct DidOpenTextDocumentParam {
|
||||||
lsTextDocumentItem textDocument;
|
TextDocumentItem textDocument;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TextDocumentPositionParam {
|
struct TextDocumentPositionParam {
|
||||||
lsTextDocumentIdentifier textDocument;
|
TextDocumentIdentifier textDocument;
|
||||||
lsPosition position;
|
lsPosition position;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RenameParam {
|
struct RenameParam {
|
||||||
lsTextDocumentIdentifier textDocument;
|
TextDocumentIdentifier textDocument;
|
||||||
lsPosition position;
|
lsPosition position;
|
||||||
std::string newName;
|
std::string newName;
|
||||||
};
|
};
|
||||||
|
|
||||||
// code*
|
// code*
|
||||||
struct CodeActionParam {
|
struct CodeActionParam {
|
||||||
lsTextDocumentIdentifier textDocument;
|
TextDocumentIdentifier textDocument;
|
||||||
lsRange range;
|
lsRange range;
|
||||||
struct Context {
|
struct Context {
|
||||||
std::vector<lsDiagnostic> diagnostics;
|
std::vector<Diagnostic> diagnostics;
|
||||||
} context;
|
} context;
|
||||||
};
|
};
|
||||||
|
|
||||||
// completion
|
// completion
|
||||||
enum class lsCompletionTriggerKind {
|
enum class CompletionTriggerKind {
|
||||||
Invoked = 1,
|
Invoked = 1,
|
||||||
TriggerCharacter = 2,
|
TriggerCharacter = 2,
|
||||||
TriggerForIncompleteCompletions = 3,
|
TriggerForIncompleteCompletions = 3,
|
||||||
};
|
};
|
||||||
struct lsCompletionContext {
|
struct CompletionContext {
|
||||||
lsCompletionTriggerKind triggerKind = lsCompletionTriggerKind::Invoked;
|
CompletionTriggerKind triggerKind = CompletionTriggerKind::Invoked;
|
||||||
std::optional<std::string> triggerCharacter;
|
std::optional<std::string> triggerCharacter;
|
||||||
};
|
};
|
||||||
struct lsCompletionParams : TextDocumentPositionParam {
|
struct CompletionParam : TextDocumentPositionParam {
|
||||||
lsCompletionContext context;
|
CompletionContext context;
|
||||||
};
|
};
|
||||||
enum class lsCompletionItemKind {
|
enum class CompletionItemKind {
|
||||||
Text = 1,
|
Text = 1,
|
||||||
Method = 2,
|
Method = 2,
|
||||||
Function = 3,
|
Function = 3,
|
||||||
@ -94,21 +94,21 @@ enum class lsCompletionItemKind {
|
|||||||
Operator = 24,
|
Operator = 24,
|
||||||
TypeParameter = 25,
|
TypeParameter = 25,
|
||||||
};
|
};
|
||||||
enum class lsInsertTextFormat {
|
enum class InsertTextFormat {
|
||||||
PlainText = 1,
|
PlainText = 1,
|
||||||
Snippet = 2
|
Snippet = 2
|
||||||
};
|
};
|
||||||
struct lsCompletionItem {
|
struct CompletionItem {
|
||||||
std::string label;
|
std::string label;
|
||||||
lsCompletionItemKind kind = lsCompletionItemKind::Text;
|
CompletionItemKind kind = CompletionItemKind::Text;
|
||||||
std::string detail;
|
std::string detail;
|
||||||
std::optional<std::string> documentation;
|
std::optional<std::string> documentation;
|
||||||
std::string sortText;
|
std::string sortText;
|
||||||
std::optional<std::string> filterText;
|
std::optional<std::string> filterText;
|
||||||
std::string insertText;
|
std::string insertText;
|
||||||
lsInsertTextFormat insertTextFormat = lsInsertTextFormat::PlainText;
|
InsertTextFormat insertTextFormat = InsertTextFormat::PlainText;
|
||||||
lsTextEdit textEdit;
|
TextEdit textEdit;
|
||||||
std::vector<lsTextEdit> additionalTextEdits;
|
std::vector<TextEdit> additionalTextEdits;
|
||||||
|
|
||||||
std::vector<std::string> parameters_;
|
std::vector<std::string> parameters_;
|
||||||
int score_;
|
int score_;
|
||||||
@ -122,17 +122,17 @@ struct FormattingOptions {
|
|||||||
bool insertSpaces;
|
bool insertSpaces;
|
||||||
};
|
};
|
||||||
struct DocumentFormattingParam {
|
struct DocumentFormattingParam {
|
||||||
lsTextDocumentIdentifier textDocument;
|
TextDocumentIdentifier textDocument;
|
||||||
FormattingOptions options;
|
FormattingOptions options;
|
||||||
};
|
};
|
||||||
struct DocumentOnTypeFormattingParam {
|
struct DocumentOnTypeFormattingParam {
|
||||||
lsTextDocumentIdentifier textDocument;
|
TextDocumentIdentifier textDocument;
|
||||||
lsPosition position;
|
lsPosition position;
|
||||||
std::string ch;
|
std::string ch;
|
||||||
FormattingOptions options;
|
FormattingOptions options;
|
||||||
};
|
};
|
||||||
struct DocumentRangeFormattingParam {
|
struct DocumentRangeFormattingParam {
|
||||||
lsTextDocumentIdentifier textDocument;
|
TextDocumentIdentifier textDocument;
|
||||||
lsRange range;
|
lsRange range;
|
||||||
FormattingOptions options;
|
FormattingOptions options;
|
||||||
};
|
};
|
||||||
@ -145,7 +145,7 @@ enum class FileChangeType {
|
|||||||
};
|
};
|
||||||
struct DidChangeWatchedFilesParam {
|
struct DidChangeWatchedFilesParam {
|
||||||
struct Event {
|
struct Event {
|
||||||
lsDocumentUri uri;
|
DocumentUri uri;
|
||||||
FileChangeType type;
|
FileChangeType type;
|
||||||
};
|
};
|
||||||
std::vector<Event> changes;
|
std::vector<Event> changes;
|
||||||
@ -167,7 +167,7 @@ template <typename Res>
|
|||||||
using Callback = std::function<void(Res*)>;
|
using Callback = std::function<void(Res*)>;
|
||||||
|
|
||||||
struct ReplyOnce {
|
struct ReplyOnce {
|
||||||
lsRequestId id;
|
RequestId id;
|
||||||
template <typename Res> void operator()(Res &result) const {
|
template <typename Res> void operator()(Res &result) const {
|
||||||
if (id.Valid())
|
if (id.Valid())
|
||||||
pipeline::Reply(id, [&](Writer &w) { Reflect(w, result); });
|
pipeline::Reply(id, [&](Writer &w) { Reflect(w, result); });
|
||||||
@ -217,7 +217,7 @@ private:
|
|||||||
void shutdown(EmptyParam &, ReplyOnce &);
|
void shutdown(EmptyParam &, ReplyOnce &);
|
||||||
void textDocument_codeAction(CodeActionParam &, ReplyOnce &);
|
void textDocument_codeAction(CodeActionParam &, ReplyOnce &);
|
||||||
void textDocument_codeLens(TextDocumentParam &, ReplyOnce &);
|
void textDocument_codeLens(TextDocumentParam &, ReplyOnce &);
|
||||||
void textDocument_completion(lsCompletionParams &, ReplyOnce &);
|
void textDocument_completion(CompletionParam &, ReplyOnce &);
|
||||||
void textDocument_definition(TextDocumentPositionParam &, ReplyOnce &);
|
void textDocument_definition(TextDocumentPositionParam &, ReplyOnce &);
|
||||||
void textDocument_didChange(TextDocumentDidChangeParam &);
|
void textDocument_didChange(TextDocumentDidChangeParam &);
|
||||||
void textDocument_didClose(TextDocumentParam &);
|
void textDocument_didClose(TextDocumentParam &);
|
||||||
|
@ -47,7 +47,7 @@ struct Out_cclsCall {
|
|||||||
Usr usr;
|
Usr usr;
|
||||||
std::string id;
|
std::string id;
|
||||||
std::string_view name;
|
std::string_view name;
|
||||||
lsLocation location;
|
Location location;
|
||||||
CallType callType = CallType::Direct;
|
CallType callType = CallType::Direct;
|
||||||
int numChildren;
|
int numChildren;
|
||||||
// Empty if the |levels| limit is reached.
|
// Empty if the |levels| limit is reached.
|
||||||
@ -85,15 +85,14 @@ bool Expand(MessageHandler *m, Out_cclsCall *entry, bool callee,
|
|||||||
if (callee) {
|
if (callee) {
|
||||||
if (const auto *def = func.AnyDef())
|
if (const auto *def = func.AnyDef())
|
||||||
for (SymbolRef sym : def->callees)
|
for (SymbolRef sym : def->callees)
|
||||||
if (sym.kind == SymbolKind::Func)
|
if (sym.kind == Kind::Func)
|
||||||
handle(sym, def->file_id, call_type);
|
handle(sym, def->file_id, call_type);
|
||||||
} else {
|
} else {
|
||||||
for (Use use : func.uses) {
|
for (Use use : func.uses) {
|
||||||
const QueryFile &file1 = m->db->files[use.file_id];
|
const QueryFile &file1 = m->db->files[use.file_id];
|
||||||
Maybe<ExtentRef> best;
|
Maybe<ExtentRef> best;
|
||||||
for (auto [sym, refcnt] : file1.symbol2refcnt)
|
for (auto [sym, refcnt] : file1.symbol2refcnt)
|
||||||
if (refcnt > 0 && sym.extent.Valid() &&
|
if (refcnt > 0 && sym.extent.Valid() && sym.kind == Kind::Func &&
|
||||||
sym.kind == SymbolKind::Func &&
|
|
||||||
sym.extent.start <= use.range.start &&
|
sym.extent.start <= use.range.start &&
|
||||||
use.range.end <= sym.extent.end &&
|
use.range.end <= sym.extent.end &&
|
||||||
(!best || best->extent.start < sym.extent.start))
|
(!best || best->extent.start < sym.extent.start))
|
||||||
@ -195,7 +194,7 @@ void MessageHandler::ccls_call(Reader &reader, ReplyOnce &reply) {
|
|||||||
WorkingFile *working_file = wfiles->GetFileByFilename(file->def->path);
|
WorkingFile *working_file = wfiles->GetFileByFilename(file->def->path);
|
||||||
for (SymbolRef sym :
|
for (SymbolRef sym :
|
||||||
FindSymbolsAtLocation(working_file, file, param.position)) {
|
FindSymbolsAtLocation(working_file, file, param.position)) {
|
||||||
if (sym.kind == SymbolKind::Func) {
|
if (sym.kind == Kind::Func) {
|
||||||
result = BuildInitial(this, sym.usr, param.callee, param.callType,
|
result = BuildInitial(this, sym.usr, param.callee, param.callType,
|
||||||
param.qualified, param.levels);
|
param.qualified, param.levels);
|
||||||
break;
|
break;
|
||||||
|
@ -15,7 +15,7 @@ struct Param : TextDocumentPositionParam {
|
|||||||
// should be specified for building the root and |levels| of nodes below.
|
// should be specified for building the root and |levels| of nodes below.
|
||||||
Usr usr;
|
Usr usr;
|
||||||
std::string id;
|
std::string id;
|
||||||
SymbolKind kind = SymbolKind::Invalid;
|
Kind kind = Kind::Invalid;
|
||||||
|
|
||||||
// true: derived classes/functions; false: base classes/functions
|
// true: derived classes/functions; false: base classes/functions
|
||||||
bool derived = false;
|
bool derived = false;
|
||||||
@ -30,9 +30,9 @@ MAKE_REFLECT_STRUCT(Param, textDocument, position, id, kind, derived, qualified,
|
|||||||
struct Out_cclsInheritance {
|
struct Out_cclsInheritance {
|
||||||
Usr usr;
|
Usr usr;
|
||||||
std::string id;
|
std::string id;
|
||||||
SymbolKind kind;
|
Kind kind;
|
||||||
std::string_view name;
|
std::string_view name;
|
||||||
lsLocation location;
|
Location location;
|
||||||
// For unexpanded nodes, this is an upper bound because some entities may be
|
// For unexpanded nodes, this is an upper bound because some entities may be
|
||||||
// undefined. If it is 0, there are no members.
|
// undefined. If it is 0, there are no members.
|
||||||
int numChildren;
|
int numChildren;
|
||||||
@ -99,7 +99,7 @@ bool ExpandHelper(MessageHandler *m, Out_cclsInheritance *entry, bool derived,
|
|||||||
|
|
||||||
bool Expand(MessageHandler *m, Out_cclsInheritance *entry, bool derived,
|
bool Expand(MessageHandler *m, Out_cclsInheritance *entry, bool derived,
|
||||||
bool qualified, int levels) {
|
bool qualified, int levels) {
|
||||||
if (entry->kind == SymbolKind::Func)
|
if (entry->kind == Kind::Func)
|
||||||
return ExpandHelper(m, entry, derived, qualified, levels,
|
return ExpandHelper(m, entry, derived, qualified, levels,
|
||||||
m->db->Func(entry->usr));
|
m->db->Func(entry->usr));
|
||||||
else
|
else
|
||||||
@ -129,10 +129,9 @@ void Inheritance(MessageHandler *m, Param ¶m, ReplyOnce &reply) {
|
|||||||
result->id = std::to_string(param.usr);
|
result->id = std::to_string(param.usr);
|
||||||
result->usr = param.usr;
|
result->usr = param.usr;
|
||||||
result->kind = param.kind;
|
result->kind = param.kind;
|
||||||
if (!(((param.kind == SymbolKind::Func && m->db->HasFunc(param.usr)) ||
|
if (!(((param.kind == Kind::Func && m->db->HasFunc(param.usr)) ||
|
||||||
(param.kind == SymbolKind::Type && m->db->HasType(param.usr))) &&
|
(param.kind == Kind::Type && m->db->HasType(param.usr))) &&
|
||||||
Expand(m, &*result, param.derived, param.qualified,
|
Expand(m, &*result, param.derived, param.qualified, param.levels)))
|
||||||
param.levels)))
|
|
||||||
result.reset();
|
result.reset();
|
||||||
} else {
|
} else {
|
||||||
QueryFile *file = m->FindFile(reply, param.textDocument.uri.GetPath());
|
QueryFile *file = m->FindFile(reply, param.textDocument.uri.GetPath());
|
||||||
@ -141,7 +140,7 @@ void Inheritance(MessageHandler *m, Param ¶m, ReplyOnce &reply) {
|
|||||||
WorkingFile *wfile = m->wfiles->GetFileByFilename(file->def->path);
|
WorkingFile *wfile = m->wfiles->GetFileByFilename(file->def->path);
|
||||||
|
|
||||||
for (SymbolRef sym : FindSymbolsAtLocation(wfile, file, param.position))
|
for (SymbolRef sym : FindSymbolsAtLocation(wfile, file, param.position))
|
||||||
if (sym.kind == SymbolKind::Func || sym.kind == SymbolKind::Type) {
|
if (sym.kind == Kind::Func || sym.kind == Kind::Type) {
|
||||||
result = BuildInitial(m, sym, param.derived, param.qualified,
|
result = BuildInitial(m, sym, param.derived, param.qualified,
|
||||||
param.levels);
|
param.levels);
|
||||||
break;
|
break;
|
||||||
|
@ -24,9 +24,9 @@ struct Param : TextDocumentPositionParam {
|
|||||||
|
|
||||||
bool qualified = false;
|
bool qualified = false;
|
||||||
int levels = 1;
|
int levels = 1;
|
||||||
// If SymbolKind::Func and the point is at a type, list member functions
|
// If Kind::Func and the point is at a type, list member functions instead of
|
||||||
// instead of member variables.
|
// member variables.
|
||||||
SymbolKind kind = SymbolKind::Var;
|
Kind kind = Kind::Var;
|
||||||
bool hierarchy = false;
|
bool hierarchy = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -38,7 +38,7 @@ struct Out_cclsMember {
|
|||||||
std::string id;
|
std::string id;
|
||||||
std::string_view name;
|
std::string_view name;
|
||||||
std::string fieldName;
|
std::string fieldName;
|
||||||
lsLocation location;
|
Location location;
|
||||||
// For unexpanded nodes, this is an upper bound because some entities may be
|
// For unexpanded nodes, this is an upper bound because some entities may be
|
||||||
// undefined. If it is 0, there are no members.
|
// undefined. If it is 0, there are no members.
|
||||||
int numChildren = 0;
|
int numChildren = 0;
|
||||||
@ -49,7 +49,7 @@ MAKE_REFLECT_STRUCT(Out_cclsMember, id, name, fieldName, location, numChildren,
|
|||||||
children);
|
children);
|
||||||
|
|
||||||
bool Expand(MessageHandler *m, Out_cclsMember *entry, bool qualified,
|
bool Expand(MessageHandler *m, Out_cclsMember *entry, bool qualified,
|
||||||
int levels, SymbolKind memberKind);
|
int levels, Kind memberKind);
|
||||||
|
|
||||||
// Add a field to |entry| which is a Func/Type.
|
// Add a field to |entry| which is a Func/Type.
|
||||||
void DoField(MessageHandler *m, Out_cclsMember *entry, const QueryVar &var,
|
void DoField(MessageHandler *m, Out_cclsMember *entry, const QueryVar &var,
|
||||||
@ -77,14 +77,14 @@ void DoField(MessageHandler *m, Out_cclsMember *entry, const QueryVar &var,
|
|||||||
entry1.fieldName += def1->Name(false);
|
entry1.fieldName += def1->Name(false);
|
||||||
}
|
}
|
||||||
if (def1->spell) {
|
if (def1->spell) {
|
||||||
if (std::optional<lsLocation> loc =
|
if (std::optional<Location> loc =
|
||||||
GetLsLocation(m->db, m->wfiles, *def1->spell))
|
GetLsLocation(m->db, m->wfiles, *def1->spell))
|
||||||
entry1.location = *loc;
|
entry1.location = *loc;
|
||||||
}
|
}
|
||||||
if (def1->type) {
|
if (def1->type) {
|
||||||
entry1.id = std::to_string(def1->type);
|
entry1.id = std::to_string(def1->type);
|
||||||
entry1.usr = def1->type;
|
entry1.usr = def1->type;
|
||||||
if (Expand(m, &entry1, qualified, levels, SymbolKind::Var))
|
if (Expand(m, &entry1, qualified, levels, Kind::Var))
|
||||||
entry->children.push_back(std::move(entry1));
|
entry->children.push_back(std::move(entry1));
|
||||||
} else {
|
} else {
|
||||||
entry1.id = "0";
|
entry1.id = "0";
|
||||||
@ -95,7 +95,7 @@ void DoField(MessageHandler *m, Out_cclsMember *entry, const QueryVar &var,
|
|||||||
|
|
||||||
// Expand a type node by adding members recursively to it.
|
// Expand a type node by adding members recursively to it.
|
||||||
bool Expand(MessageHandler *m, Out_cclsMember *entry, bool qualified,
|
bool Expand(MessageHandler *m, Out_cclsMember *entry, bool qualified,
|
||||||
int levels, SymbolKind memberKind) {
|
int levels, Kind memberKind) {
|
||||||
if (0 < entry->usr && entry->usr <= BuiltinType::LastKind) {
|
if (0 < entry->usr && entry->usr <= BuiltinType::LastKind) {
|
||||||
entry->name = ClangBuiltinTypeName(int(entry->usr));
|
entry->name = ClangBuiltinTypeName(int(entry->usr));
|
||||||
return true;
|
return true;
|
||||||
@ -117,7 +117,7 @@ bool Expand(MessageHandler *m, Out_cclsMember *entry, bool qualified,
|
|||||||
const auto *def = type->AnyDef();
|
const auto *def = type->AnyDef();
|
||||||
if (!def)
|
if (!def)
|
||||||
continue;
|
continue;
|
||||||
if (def->kind != lsSymbolKind::Namespace)
|
if (def->kind != SymbolKind::Namespace)
|
||||||
for (Usr usr : def->bases) {
|
for (Usr usr : def->bases) {
|
||||||
auto &type1 = m->db->Type(usr);
|
auto &type1 = m->db->Type(usr);
|
||||||
if (type1.def.size()) {
|
if (type1.def.size()) {
|
||||||
@ -132,13 +132,13 @@ bool Expand(MessageHandler *m, Out_cclsMember *entry, bool qualified,
|
|||||||
entry1.usr = def->alias_of;
|
entry1.usr = def->alias_of;
|
||||||
if (def1 && def1->spell) {
|
if (def1 && def1->spell) {
|
||||||
// The declaration of target type.
|
// The declaration of target type.
|
||||||
if (std::optional<lsLocation> loc =
|
if (std::optional<Location> loc =
|
||||||
GetLsLocation(m->db, m->wfiles, *def1->spell))
|
GetLsLocation(m->db, m->wfiles, *def1->spell))
|
||||||
entry1.location = *loc;
|
entry1.location = *loc;
|
||||||
} else if (def->spell) {
|
} else if (def->spell) {
|
||||||
// Builtin types have no declaration but the typedef declaration
|
// Builtin types have no declaration but the typedef declaration
|
||||||
// itself is useful.
|
// itself is useful.
|
||||||
if (std::optional<lsLocation> loc =
|
if (std::optional<Location> loc =
|
||||||
GetLsLocation(m->db, m->wfiles, *def->spell))
|
GetLsLocation(m->db, m->wfiles, *def->spell))
|
||||||
entry1.location = *loc;
|
entry1.location = *loc;
|
||||||
}
|
}
|
||||||
@ -150,7 +150,7 @@ bool Expand(MessageHandler *m, Out_cclsMember *entry, bool qualified,
|
|||||||
entry1.fieldName = std::string(entry1.name);
|
entry1.fieldName = std::string(entry1.name);
|
||||||
entry->children.push_back(std::move(entry1));
|
entry->children.push_back(std::move(entry1));
|
||||||
}
|
}
|
||||||
} else if (memberKind == SymbolKind::Func) {
|
} else if (memberKind == Kind::Func) {
|
||||||
llvm::DenseSet<Usr, DenseMapInfoForUsr> seen1;
|
llvm::DenseSet<Usr, DenseMapInfoForUsr> seen1;
|
||||||
for (auto &def : type->def)
|
for (auto &def : type->def)
|
||||||
for (Usr usr : def.funcs)
|
for (Usr usr : def.funcs)
|
||||||
@ -170,7 +170,7 @@ bool Expand(MessageHandler *m, Out_cclsMember *entry, bool qualified,
|
|||||||
entry->children.push_back(std::move(entry1));
|
entry->children.push_back(std::move(entry1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (memberKind == SymbolKind::Type) {
|
} else if (memberKind == Kind::Type) {
|
||||||
llvm::DenseSet<Usr, DenseMapInfoForUsr> seen1;
|
llvm::DenseSet<Usr, DenseMapInfoForUsr> seen1;
|
||||||
for (auto &def : type->def)
|
for (auto &def : type->def)
|
||||||
for (Usr usr : def.types)
|
for (Usr usr : def.types)
|
||||||
@ -207,13 +207,13 @@ bool Expand(MessageHandler *m, Out_cclsMember *entry, bool qualified,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<Out_cclsMember> BuildInitial(MessageHandler *m, SymbolKind kind,
|
std::optional<Out_cclsMember> BuildInitial(MessageHandler *m, Kind kind,
|
||||||
Usr root_usr, bool qualified,
|
Usr root_usr, bool qualified,
|
||||||
int levels, SymbolKind memberKind) {
|
int levels, Kind memberKind) {
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
default:
|
default:
|
||||||
return {};
|
return {};
|
||||||
case SymbolKind::Func: {
|
case Kind::Func: {
|
||||||
const auto *def = m->db->Func(root_usr).AnyDef();
|
const auto *def = m->db->Func(root_usr).AnyDef();
|
||||||
if (!def)
|
if (!def)
|
||||||
return {};
|
return {};
|
||||||
@ -232,7 +232,7 @@ std::optional<Out_cclsMember> BuildInitial(MessageHandler *m, SymbolKind kind,
|
|||||||
}
|
}
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
case SymbolKind::Type: {
|
case Kind::Type: {
|
||||||
const auto *def = m->db->Type(root_usr).AnyDef();
|
const auto *def = m->db->Type(root_usr).AnyDef();
|
||||||
if (!def)
|
if (!def)
|
||||||
return {};
|
return {};
|
||||||
@ -276,15 +276,15 @@ void MessageHandler::ccls_member(Reader &reader, ReplyOnce &reply) {
|
|||||||
for (SymbolRef sym :
|
for (SymbolRef sym :
|
||||||
FindSymbolsAtLocation(wfile, file, param.position)) {
|
FindSymbolsAtLocation(wfile, file, param.position)) {
|
||||||
switch (sym.kind) {
|
switch (sym.kind) {
|
||||||
case SymbolKind::Func:
|
case Kind::Func:
|
||||||
case SymbolKind::Type:
|
case Kind::Type:
|
||||||
result = BuildInitial(this, sym.kind, sym.usr, param.qualified,
|
result = BuildInitial(this, sym.kind, sym.usr, param.qualified,
|
||||||
param.levels, param.kind);
|
param.levels, param.kind);
|
||||||
break;
|
break;
|
||||||
case SymbolKind::Var: {
|
case Kind::Var: {
|
||||||
const QueryVar::Def *def = db->GetVar(sym).AnyDef();
|
const QueryVar::Def *def = db->GetVar(sym).AnyDef();
|
||||||
if (def && def->type)
|
if (def && def->type)
|
||||||
result = BuildInitial(this, SymbolKind::Type, def->type, param.qualified,
|
result = BuildInitial(this, Kind::Type, def->type, param.qualified,
|
||||||
param.levels, param.kind);
|
param.levels, param.kind);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
namespace ccls {
|
namespace ccls {
|
||||||
namespace {
|
namespace {
|
||||||
struct Param {
|
struct Param {
|
||||||
lsTextDocumentIdentifier textDocument;
|
TextDocumentIdentifier textDocument;
|
||||||
lsPosition position;
|
lsPosition position;
|
||||||
std::string direction;
|
std::string direction;
|
||||||
};
|
};
|
||||||
@ -83,10 +83,10 @@ void MessageHandler::ccls_navigate(Reader &reader,
|
|||||||
res = sym.extent;
|
res = sym.extent;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
std::vector<lsLocation> result;
|
std::vector<Location> result;
|
||||||
if (res)
|
if (res)
|
||||||
if (auto ls_range = GetLsRange(wfile, *res)) {
|
if (auto ls_range = GetLsRange(wfile, *res)) {
|
||||||
lsLocation &ls_loc = result.emplace_back();
|
Location &ls_loc = result.emplace_back();
|
||||||
ls_loc.uri = param.textDocument.uri;
|
ls_loc.uri = param.textDocument.uri;
|
||||||
ls_loc.range = *ls_range;
|
ls_loc.range = *ls_range;
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ void MessageHandler::ccls_reload(Reader &reader) {
|
|||||||
if (param.whitelist.empty() && param.blacklist.empty()) {
|
if (param.whitelist.empty() && param.blacklist.empty()) {
|
||||||
vfs->Clear();
|
vfs->Clear();
|
||||||
db->clear();
|
db->clear();
|
||||||
project->Index(wfiles, lsRequestId());
|
project->Index(wfiles, RequestId());
|
||||||
clang_complete->FlushAllSessions();
|
clang_complete->FlushAllSessions();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -24,21 +24,21 @@ void MessageHandler::ccls_vars(Reader &reader, ReplyOnce &reply) {
|
|||||||
return;
|
return;
|
||||||
WorkingFile *working_file = wfiles->GetFileByFilename(file->def->path);
|
WorkingFile *working_file = wfiles->GetFileByFilename(file->def->path);
|
||||||
|
|
||||||
std::vector<lsLocation> result;
|
std::vector<Location> result;
|
||||||
for (SymbolRef sym :
|
for (SymbolRef sym :
|
||||||
FindSymbolsAtLocation(working_file, file, param.position)) {
|
FindSymbolsAtLocation(working_file, file, param.position)) {
|
||||||
Usr usr = sym.usr;
|
Usr usr = sym.usr;
|
||||||
switch (sym.kind) {
|
switch (sym.kind) {
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
case SymbolKind::Var: {
|
case Kind::Var: {
|
||||||
const QueryVar::Def *def = db->GetVar(sym).AnyDef();
|
const QueryVar::Def *def = db->GetVar(sym).AnyDef();
|
||||||
if (!def || !def->type)
|
if (!def || !def->type)
|
||||||
continue;
|
continue;
|
||||||
usr = def->type;
|
usr = def->type;
|
||||||
[[fallthrough]];
|
[[fallthrough]];
|
||||||
}
|
}
|
||||||
case SymbolKind::Type:
|
case Kind::Type:
|
||||||
result = GetLsLocations(
|
result = GetLsLocations(
|
||||||
db, wfiles,
|
db, wfiles,
|
||||||
GetVarDeclarations(db, db->Type(usr).instances, param.kind));
|
GetVarDeclarations(db, db->Type(usr).instances, param.kind));
|
||||||
|
@ -26,105 +26,37 @@ using namespace llvm;
|
|||||||
extern std::string g_init_options;
|
extern std::string g_init_options;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
enum class TextDocumentSyncKind { None = 0, Full = 1, Incremental = 2 };
|
||||||
|
MAKE_REFLECT_TYPE_PROXY(TextDocumentSyncKind)
|
||||||
|
|
||||||
// Code Lens options.
|
struct ServerCap {
|
||||||
struct lsCodeLensOptions {
|
struct SaveOptions {
|
||||||
// Code lens has a resolve provider as well.
|
bool includeText = false;
|
||||||
bool resolveProvider = false;
|
};
|
||||||
};
|
struct TextDocumentSyncOptions {
|
||||||
MAKE_REFLECT_STRUCT(lsCodeLensOptions, resolveProvider);
|
bool openClose = true;
|
||||||
|
TextDocumentSyncKind change = TextDocumentSyncKind::Incremental;
|
||||||
// Completion options.
|
bool willSave = false;
|
||||||
struct lsCompletionOptions {
|
bool willSaveWaitUntil = false;
|
||||||
// The server provides support to resolve additional
|
SaveOptions save;
|
||||||
// information for a completion item.
|
} textDocumentSync;
|
||||||
bool resolveProvider = false;
|
|
||||||
|
|
||||||
// The characters that trigger completion automatically.
|
|
||||||
// vscode doesn't support trigger character sequences, so we use ':'
|
|
||||||
// for
|
|
||||||
// '::' and '>' for '->'. See
|
|
||||||
// https://github.com/Microsoft/language-server-protocol/issues/138.
|
|
||||||
std::vector<std::string> triggerCharacters = {".", ":", ">", "#",
|
|
||||||
"<", "\"", "/"};
|
|
||||||
};
|
|
||||||
MAKE_REFLECT_STRUCT(lsCompletionOptions, resolveProvider, triggerCharacters);
|
|
||||||
|
|
||||||
// Format document on type options
|
|
||||||
struct lsDocumentOnTypeFormattingOptions {
|
|
||||||
// A character on which formatting should be triggered, like `}`.
|
|
||||||
std::string firstTriggerCharacter = "}";
|
|
||||||
|
|
||||||
// More trigger characters.
|
|
||||||
std::vector<std::string> moreTriggerCharacter;
|
|
||||||
};
|
|
||||||
MAKE_REFLECT_STRUCT(lsDocumentOnTypeFormattingOptions, firstTriggerCharacter,
|
|
||||||
moreTriggerCharacter);
|
|
||||||
|
|
||||||
|
|
||||||
// Save options.
|
|
||||||
struct lsSaveOptions {
|
|
||||||
// The client is supposed to include the content on save.
|
|
||||||
bool includeText = false;
|
|
||||||
};
|
|
||||||
MAKE_REFLECT_STRUCT(lsSaveOptions, includeText);
|
|
||||||
|
|
||||||
// Signature help options.
|
|
||||||
struct lsSignatureHelpOptions {
|
|
||||||
// The characters that trigger signature help automatically.
|
|
||||||
// NOTE: If updating signature help tokens make sure to also update
|
|
||||||
// WorkingFile::FindClosestCallNameInBuffer.
|
|
||||||
std::vector<std::string> triggerCharacters = {"(", ","};
|
|
||||||
};
|
|
||||||
MAKE_REFLECT_STRUCT(lsSignatureHelpOptions, triggerCharacters);
|
|
||||||
|
|
||||||
// Defines how the host (editor) should sync document changes to the language
|
|
||||||
// server.
|
|
||||||
enum class lsTextDocumentSyncKind {
|
|
||||||
// Documents should not be synced at all.
|
|
||||||
None = 0,
|
|
||||||
|
|
||||||
// Documents are synced by always sending the full content
|
|
||||||
// of the document.
|
|
||||||
Full = 1,
|
|
||||||
|
|
||||||
// Documents are synced by sending the full content on open.
|
|
||||||
// After that only incremental updates to the document are
|
|
||||||
// send.
|
|
||||||
Incremental = 2
|
|
||||||
};
|
|
||||||
MAKE_REFLECT_TYPE_PROXY(lsTextDocumentSyncKind)
|
|
||||||
|
|
||||||
struct lsTextDocumentSyncOptions {
|
|
||||||
// Open and close notifications are sent to the server.
|
|
||||||
bool openClose = false;
|
|
||||||
// Change notificatins are sent to the server. See TextDocumentSyncKind.None,
|
|
||||||
// TextDocumentSyncKind.Full and TextDocumentSyncKindIncremental.
|
|
||||||
lsTextDocumentSyncKind change = lsTextDocumentSyncKind::Incremental;
|
|
||||||
// Will save notifications are sent to the server.
|
|
||||||
std::optional<bool> willSave;
|
|
||||||
// Will save wait until requests are sent to the server.
|
|
||||||
std::optional<bool> willSaveWaitUntil;
|
|
||||||
// Save notifications are sent to the server.
|
|
||||||
std::optional<lsSaveOptions> save;
|
|
||||||
};
|
|
||||||
MAKE_REFLECT_STRUCT(lsTextDocumentSyncOptions, openClose, change, willSave,
|
|
||||||
willSaveWaitUntil, save);
|
|
||||||
|
|
||||||
struct lsServerCapabilities {
|
|
||||||
// Defines how text documents are synced. Is either a detailed structure
|
|
||||||
// defining each notification or for backwards compatibility the
|
|
||||||
// TextDocumentSyncKind number.
|
|
||||||
// TODO: It seems like the new API is broken and doesn't work.
|
|
||||||
// std::optional<lsTextDocumentSyncOptions> textDocumentSync;
|
|
||||||
lsTextDocumentSyncKind textDocumentSync = lsTextDocumentSyncKind::Incremental;
|
|
||||||
|
|
||||||
// The server provides hover support.
|
// The server provides hover support.
|
||||||
bool hoverProvider = true;
|
bool hoverProvider = true;
|
||||||
// The server provides completion support.
|
struct CompletionOptions {
|
||||||
lsCompletionOptions completionProvider;
|
bool resolveProvider = false;
|
||||||
// The server provides signature help support.
|
|
||||||
lsSignatureHelpOptions signatureHelpProvider;
|
// The characters that trigger completion automatically.
|
||||||
|
// vscode doesn't support trigger character sequences, so we use ':'
|
||||||
|
// for
|
||||||
|
// '::' and '>' for '->'. See
|
||||||
|
// https://github.com/Microsoft/language-server-protocol/issues/138.
|
||||||
|
std::vector<std::string> triggerCharacters = {".", ":", ">", "#",
|
||||||
|
"<", "\"", "/"};
|
||||||
|
} completionProvider;
|
||||||
|
struct SignatureHelpOptions {
|
||||||
|
std::vector<std::string> triggerCharacters = {"(", ","};
|
||||||
|
} signatureHelpProvider;
|
||||||
bool definitionProvider = true;
|
bool definitionProvider = true;
|
||||||
bool typeDefinitionProvider = true;
|
bool typeDefinitionProvider = true;
|
||||||
bool implementationProvider = true;
|
bool implementationProvider = true;
|
||||||
@ -133,10 +65,15 @@ struct lsServerCapabilities {
|
|||||||
bool documentSymbolProvider = true;
|
bool documentSymbolProvider = true;
|
||||||
bool workspaceSymbolProvider = true;
|
bool workspaceSymbolProvider = true;
|
||||||
bool codeActionProvider = true;
|
bool codeActionProvider = true;
|
||||||
lsCodeLensOptions codeLensProvider;
|
struct CodeLensOptions {
|
||||||
|
bool resolveProvider = false;
|
||||||
|
} codeLensProvider;
|
||||||
bool documentFormattingProvider = true;
|
bool documentFormattingProvider = true;
|
||||||
bool documentRangeFormattingProvider = true;
|
bool documentRangeFormattingProvider = true;
|
||||||
lsDocumentOnTypeFormattingOptions documentOnTypeFormattingProvider;
|
struct DocumentOnTypeFormattingOptions {
|
||||||
|
std::string firstTriggerCharacter = "}";
|
||||||
|
std::vector<std::string> moreTriggerCharacter;
|
||||||
|
} documentOnTypeFormattingProvider;
|
||||||
bool renameProvider = true;
|
bool renameProvider = true;
|
||||||
struct DocumentLinkOptions {
|
struct DocumentLinkOptions {
|
||||||
bool resolveProvider = true;
|
bool resolveProvider = true;
|
||||||
@ -153,12 +90,21 @@ struct lsServerCapabilities {
|
|||||||
} workspaceFolders;
|
} workspaceFolders;
|
||||||
} workspace;
|
} workspace;
|
||||||
};
|
};
|
||||||
MAKE_REFLECT_STRUCT(lsServerCapabilities::DocumentLinkOptions, resolveProvider);
|
MAKE_REFLECT_STRUCT(ServerCap::CompletionOptions, resolveProvider,
|
||||||
MAKE_REFLECT_STRUCT(lsServerCapabilities::ExecuteCommandOptions, commands);
|
triggerCharacters);
|
||||||
MAKE_REFLECT_STRUCT(lsServerCapabilities::Workspace::WorkspaceFolders,
|
MAKE_REFLECT_STRUCT(ServerCap::CodeLensOptions, resolveProvider);
|
||||||
supported, changeNotifications);
|
MAKE_REFLECT_STRUCT(ServerCap::DocumentLinkOptions, resolveProvider);
|
||||||
MAKE_REFLECT_STRUCT(lsServerCapabilities::Workspace, workspaceFolders);
|
MAKE_REFLECT_STRUCT(ServerCap::DocumentOnTypeFormattingOptions,
|
||||||
MAKE_REFLECT_STRUCT(lsServerCapabilities, textDocumentSync, hoverProvider,
|
firstTriggerCharacter, moreTriggerCharacter);
|
||||||
|
MAKE_REFLECT_STRUCT(ServerCap::ExecuteCommandOptions, commands);
|
||||||
|
MAKE_REFLECT_STRUCT(ServerCap::SaveOptions, includeText);
|
||||||
|
MAKE_REFLECT_STRUCT(ServerCap::SignatureHelpOptions, triggerCharacters);
|
||||||
|
MAKE_REFLECT_STRUCT(ServerCap::TextDocumentSyncOptions, openClose, change,
|
||||||
|
willSave, willSaveWaitUntil, save);
|
||||||
|
MAKE_REFLECT_STRUCT(ServerCap::Workspace::WorkspaceFolders, supported,
|
||||||
|
changeNotifications);
|
||||||
|
MAKE_REFLECT_STRUCT(ServerCap::Workspace, workspaceFolders);
|
||||||
|
MAKE_REFLECT_STRUCT(ServerCap, textDocumentSync, hoverProvider,
|
||||||
completionProvider, signatureHelpProvider,
|
completionProvider, signatureHelpProvider,
|
||||||
definitionProvider, implementationProvider,
|
definitionProvider, implementationProvider,
|
||||||
typeDefinitionProvider, referencesProvider,
|
typeDefinitionProvider, referencesProvider,
|
||||||
@ -170,72 +116,38 @@ MAKE_REFLECT_STRUCT(lsServerCapabilities, textDocumentSync, hoverProvider,
|
|||||||
documentLinkProvider, foldingRangeProvider,
|
documentLinkProvider, foldingRangeProvider,
|
||||||
executeCommandProvider, workspace);
|
executeCommandProvider, workspace);
|
||||||
|
|
||||||
|
struct DynamicReg {
|
||||||
|
bool dynamicRegistration = false;
|
||||||
|
};
|
||||||
|
MAKE_REFLECT_STRUCT(DynamicReg, dynamicRegistration);
|
||||||
|
|
||||||
// Workspace specific client capabilities.
|
// Workspace specific client capabilities.
|
||||||
struct lsWorkspaceClientCapabilites {
|
struct WorkspaceClientCap {
|
||||||
// The client supports applying batch edits to the workspace.
|
// The client supports applying batch edits to the workspace.
|
||||||
std::optional<bool> applyEdit;
|
std::optional<bool> applyEdit;
|
||||||
|
|
||||||
struct lsWorkspaceEdit {
|
struct WorkspaceEdit {
|
||||||
// The client supports versioned document changes in `WorkspaceEdit`s
|
// The client supports versioned document changes in `WorkspaceEdit`s
|
||||||
std::optional<bool> documentChanges;
|
std::optional<bool> documentChanges;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Capabilities specific to `WorkspaceEdit`s
|
// Capabilities specific to `WorkspaceEdit`s
|
||||||
std::optional<lsWorkspaceEdit> workspaceEdit;
|
std::optional<WorkspaceEdit> workspaceEdit;
|
||||||
|
DynamicReg didChangeConfiguration;
|
||||||
struct lsGenericDynamicReg {
|
DynamicReg didChangeWatchedFiles;
|
||||||
// Did foo notification supports dynamic registration.
|
DynamicReg symbol;
|
||||||
std::optional<bool> dynamicRegistration;
|
DynamicReg executeCommand;
|
||||||
};
|
|
||||||
|
|
||||||
// Capabilities specific to the `workspace/didChangeConfiguration`
|
|
||||||
// notification.
|
|
||||||
std::optional<lsGenericDynamicReg> didChangeConfiguration;
|
|
||||||
|
|
||||||
// Capabilities specific to the `workspace/didChangeWatchedFiles`
|
|
||||||
// notification.
|
|
||||||
std::optional<lsGenericDynamicReg> didChangeWatchedFiles;
|
|
||||||
|
|
||||||
// Capabilities specific to the `workspace/symbol` request.
|
|
||||||
std::optional<lsGenericDynamicReg> symbol;
|
|
||||||
|
|
||||||
// Capabilities specific to the `workspace/executeCommand` request.
|
|
||||||
std::optional<lsGenericDynamicReg> executeCommand;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
MAKE_REFLECT_STRUCT(lsWorkspaceClientCapabilites::lsWorkspaceEdit,
|
MAKE_REFLECT_STRUCT(WorkspaceClientCap::WorkspaceEdit, documentChanges);
|
||||||
documentChanges);
|
MAKE_REFLECT_STRUCT(WorkspaceClientCap, applyEdit, workspaceEdit,
|
||||||
MAKE_REFLECT_STRUCT(lsWorkspaceClientCapabilites::lsGenericDynamicReg,
|
|
||||||
dynamicRegistration);
|
|
||||||
MAKE_REFLECT_STRUCT(lsWorkspaceClientCapabilites, applyEdit, workspaceEdit,
|
|
||||||
didChangeConfiguration, didChangeWatchedFiles, symbol,
|
didChangeConfiguration, didChangeWatchedFiles, symbol,
|
||||||
executeCommand);
|
executeCommand);
|
||||||
|
|
||||||
// Text document specific client capabilities.
|
// Text document specific client capabilities.
|
||||||
struct lsTextDocumentClientCapabilities {
|
struct TextDocumentClientCap {
|
||||||
struct lsSynchronization {
|
struct Completion {
|
||||||
// Whether text document synchronization supports dynamic registration.
|
struct CompletionItem {
|
||||||
std::optional<bool> dynamicRegistration;
|
|
||||||
|
|
||||||
// The client supports sending will save notifications.
|
|
||||||
std::optional<bool> willSave;
|
|
||||||
|
|
||||||
// The client supports sending a will save request and
|
|
||||||
// waits for a response providing text edits which will
|
|
||||||
// be applied to the document before it is saved.
|
|
||||||
std::optional<bool> willSaveWaitUntil;
|
|
||||||
|
|
||||||
// The client supports did save notifications.
|
|
||||||
std::optional<bool> didSave;
|
|
||||||
};
|
|
||||||
|
|
||||||
lsSynchronization synchronization;
|
|
||||||
|
|
||||||
struct lsCompletion {
|
|
||||||
// Whether completion supports dynamic registration.
|
|
||||||
std::optional<bool> dynamicRegistration;
|
|
||||||
|
|
||||||
struct lsCompletionItem {
|
|
||||||
// Client supports snippets as insert text.
|
// Client supports snippets as insert text.
|
||||||
//
|
//
|
||||||
// A snippet can define tab stops and placeholders with `$1`, `$2`
|
// A snippet can define tab stops and placeholders with `$1`, `$2`
|
||||||
@ -246,99 +158,65 @@ struct lsTextDocumentClientCapabilities {
|
|||||||
} completionItem;
|
} completionItem;
|
||||||
} completion;
|
} completion;
|
||||||
|
|
||||||
struct lsDocumentSymbol {
|
struct DocumentSymbol {
|
||||||
bool hierarchicalDocumentSymbolSupport = false;
|
bool hierarchicalDocumentSymbolSupport = false;
|
||||||
} documentSymbol;
|
} documentSymbol;
|
||||||
|
|
||||||
struct lsGenericDynamicReg {
|
|
||||||
// Whether foo supports dynamic registration.
|
|
||||||
std::optional<bool> dynamicRegistration;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct CodeLensRegistrationOptions : public lsGenericDynamicReg {
|
|
||||||
// Code lens has a resolve provider as well.
|
|
||||||
bool resolveProvider;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Capabilities specific to the `textDocument/codeLens`
|
|
||||||
std::optional<CodeLensRegistrationOptions> codeLens;
|
|
||||||
|
|
||||||
// Capabilities specific to the `textDocument/rename`
|
|
||||||
std::optional<lsGenericDynamicReg> rename;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
MAKE_REFLECT_STRUCT(lsTextDocumentClientCapabilities::lsSynchronization,
|
MAKE_REFLECT_STRUCT(TextDocumentClientCap::Completion::CompletionItem,
|
||||||
dynamicRegistration, willSave, willSaveWaitUntil, didSave);
|
snippetSupport);
|
||||||
MAKE_REFLECT_STRUCT(lsTextDocumentClientCapabilities::lsCompletion,
|
MAKE_REFLECT_STRUCT(TextDocumentClientCap::Completion, completionItem);
|
||||||
dynamicRegistration, completionItem);
|
MAKE_REFLECT_STRUCT(TextDocumentClientCap::DocumentSymbol,
|
||||||
MAKE_REFLECT_STRUCT(lsTextDocumentClientCapabilities::lsDocumentSymbol,
|
|
||||||
hierarchicalDocumentSymbolSupport);
|
hierarchicalDocumentSymbolSupport);
|
||||||
MAKE_REFLECT_STRUCT(
|
MAKE_REFLECT_STRUCT(TextDocumentClientCap, completion, documentSymbol);
|
||||||
lsTextDocumentClientCapabilities::lsCompletion::lsCompletionItem,
|
|
||||||
snippetSupport);
|
|
||||||
MAKE_REFLECT_STRUCT(lsTextDocumentClientCapabilities::lsGenericDynamicReg,
|
|
||||||
dynamicRegistration);
|
|
||||||
MAKE_REFLECT_STRUCT(
|
|
||||||
lsTextDocumentClientCapabilities::CodeLensRegistrationOptions,
|
|
||||||
dynamicRegistration, resolveProvider);
|
|
||||||
MAKE_REFLECT_STRUCT(lsTextDocumentClientCapabilities, completion,
|
|
||||||
documentSymbol, rename, synchronization);
|
|
||||||
|
|
||||||
struct lsClientCapabilities {
|
struct ClientCap {
|
||||||
// Workspace specific client capabilities.
|
WorkspaceClientCap workspace;
|
||||||
lsWorkspaceClientCapabilites workspace;
|
TextDocumentClientCap textDocument;
|
||||||
|
|
||||||
// Text document specific client capabilities.
|
|
||||||
lsTextDocumentClientCapabilities textDocument;
|
|
||||||
};
|
};
|
||||||
MAKE_REFLECT_STRUCT(lsClientCapabilities, workspace, textDocument);
|
MAKE_REFLECT_STRUCT(ClientCap, workspace, textDocument);
|
||||||
|
|
||||||
struct lsInitializeParams {
|
struct InitializeParam {
|
||||||
// The rootUri of the workspace. Is null if no
|
// The rootUri of the workspace. Is null if no
|
||||||
// folder is open. If both `rootPath` and `rootUri` are set
|
// folder is open. If both `rootPath` and `rootUri` are set
|
||||||
// `rootUri` wins.
|
// `rootUri` wins.
|
||||||
std::optional<lsDocumentUri> rootUri;
|
std::optional<DocumentUri> rootUri;
|
||||||
|
|
||||||
// User provided initialization options.
|
|
||||||
Config initializationOptions;
|
Config initializationOptions;
|
||||||
|
ClientCap capabilities;
|
||||||
|
|
||||||
// The capabilities provided by the client (editor or tool)
|
enum class Trace {
|
||||||
lsClientCapabilities capabilities;
|
|
||||||
|
|
||||||
enum class lsTrace {
|
|
||||||
// NOTE: serialized as a string, one of 'off' | 'messages' | 'verbose';
|
// NOTE: serialized as a string, one of 'off' | 'messages' | 'verbose';
|
||||||
Off, // off
|
Off, // off
|
||||||
Messages, // messages
|
Messages, // messages
|
||||||
Verbose // verbose
|
Verbose // verbose
|
||||||
};
|
};
|
||||||
|
Trace trace = Trace::Off;
|
||||||
// The initial trace setting. If omitted trace is disabled ('off').
|
|
||||||
lsTrace trace = lsTrace::Off;
|
|
||||||
|
|
||||||
std::vector<WorkspaceFolder> workspaceFolders;
|
std::vector<WorkspaceFolder> workspaceFolders;
|
||||||
};
|
};
|
||||||
|
|
||||||
void Reflect(Reader &reader, lsInitializeParams::lsTrace &value) {
|
void Reflect(Reader &reader, InitializeParam::Trace &value) {
|
||||||
if (!reader.IsString()) {
|
if (!reader.IsString()) {
|
||||||
value = lsInitializeParams::lsTrace::Off;
|
value = InitializeParam::Trace::Off;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
std::string v = reader.GetString();
|
std::string v = reader.GetString();
|
||||||
if (v == "off")
|
if (v == "off")
|
||||||
value = lsInitializeParams::lsTrace::Off;
|
value = InitializeParam::Trace::Off;
|
||||||
else if (v == "messages")
|
else if (v == "messages")
|
||||||
value = lsInitializeParams::lsTrace::Messages;
|
value = InitializeParam::Trace::Messages;
|
||||||
else if (v == "verbose")
|
else if (v == "verbose")
|
||||||
value = lsInitializeParams::lsTrace::Verbose;
|
value = InitializeParam::Trace::Verbose;
|
||||||
}
|
}
|
||||||
|
|
||||||
MAKE_REFLECT_STRUCT(lsInitializeParams, rootUri, initializationOptions,
|
MAKE_REFLECT_STRUCT(InitializeParam, rootUri, initializationOptions,
|
||||||
capabilities, trace, workspaceFolders);
|
capabilities, trace, workspaceFolders);
|
||||||
|
|
||||||
struct lsInitializeResult {
|
struct InitializeResult {
|
||||||
lsServerCapabilities capabilities;
|
ServerCap capabilities;
|
||||||
};
|
};
|
||||||
MAKE_REFLECT_STRUCT(lsInitializeResult, capabilities);
|
MAKE_REFLECT_STRUCT(InitializeResult, capabilities);
|
||||||
|
|
||||||
void *Indexer(void *arg_) {
|
void *Indexer(void *arg_) {
|
||||||
MessageHandler *h;
|
MessageHandler *h;
|
||||||
@ -353,7 +231,7 @@ void *Indexer(void *arg_) {
|
|||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void Initialize(MessageHandler *m, lsInitializeParams ¶m, ReplyOnce &reply) {
|
void Initialize(MessageHandler *m, InitializeParam ¶m, ReplyOnce &reply) {
|
||||||
std::string project_path = NormalizePath(param.rootUri->GetPath());
|
std::string project_path = NormalizePath(param.rootUri->GetPath());
|
||||||
LOG_S(INFO) << "initialize in directory " << project_path << " with uri "
|
LOG_S(INFO) << "initialize in directory " << project_path << " with uri "
|
||||||
<< param.rootUri->raw_uri;
|
<< param.rootUri->raw_uri;
|
||||||
@ -401,7 +279,7 @@ void Initialize(MessageHandler *m, lsInitializeParams ¶m, ReplyOnce &reply)
|
|||||||
// Send initialization before starting indexers, so we don't send a
|
// Send initialization before starting indexers, so we don't send a
|
||||||
// status update too early.
|
// status update too early.
|
||||||
{
|
{
|
||||||
lsInitializeResult result;
|
InitializeResult result;
|
||||||
reply(result);
|
reply(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -448,7 +326,7 @@ void Initialize(MessageHandler *m, lsInitializeParams ¶m, ReplyOnce &reply)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MessageHandler::initialize(Reader &reader, ReplyOnce &reply) {
|
void MessageHandler::initialize(Reader &reader, ReplyOnce &reply) {
|
||||||
lsInitializeParams param;
|
InitializeParam param;
|
||||||
Reflect(reader, param);
|
Reflect(reader, param);
|
||||||
if (!param.rootUri)
|
if (!param.rootUri)
|
||||||
return;
|
return;
|
||||||
@ -456,8 +334,8 @@ void MessageHandler::initialize(Reader &reader, ReplyOnce &reply) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void StandaloneInitialize(MessageHandler &handler, const std::string &root) {
|
void StandaloneInitialize(MessageHandler &handler, const std::string &root) {
|
||||||
lsInitializeParams param;
|
InitializeParam param;
|
||||||
param.rootUri = lsDocumentUri::FromPath(root);
|
param.rootUri = DocumentUri::FromPath(root);
|
||||||
ReplyOnce reply;
|
ReplyOnce reply;
|
||||||
Initialize(&handler, param, reply);
|
Initialize(&handler, param, reply);
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ namespace {
|
|||||||
struct CodeAction {
|
struct CodeAction {
|
||||||
std::string title;
|
std::string title;
|
||||||
const char *kind = "quickfix";
|
const char *kind = "quickfix";
|
||||||
lsWorkspaceEdit edit;
|
WorkspaceEdit edit;
|
||||||
};
|
};
|
||||||
MAKE_REFLECT_STRUCT(CodeAction, title, kind, edit);
|
MAKE_REFLECT_STRUCT(CodeAction, title, kind, edit);
|
||||||
}
|
}
|
||||||
@ -27,9 +27,9 @@ void MessageHandler::textDocument_codeAction(CodeActionParam ¶m,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
std::vector<CodeAction> result;
|
std::vector<CodeAction> result;
|
||||||
std::vector<lsDiagnostic> diagnostics;
|
std::vector<Diagnostic> diagnostics;
|
||||||
wfiles->DoAction([&]() { diagnostics = wfile->diagnostics_; });
|
wfiles->DoAction([&]() { diagnostics = wfile->diagnostics_; });
|
||||||
for (lsDiagnostic &diag : diagnostics)
|
for (Diagnostic &diag : diagnostics)
|
||||||
if (diag.fixits_.size()) {
|
if (diag.fixits_.size()) {
|
||||||
CodeAction &cmd = result.emplace_back();
|
CodeAction &cmd = result.emplace_back();
|
||||||
cmd.title = "FixIt: " + diag.message;
|
cmd.title = "FixIt: " + diag.message;
|
||||||
@ -44,21 +44,21 @@ void MessageHandler::textDocument_codeAction(CodeActionParam ¶m,
|
|||||||
namespace {
|
namespace {
|
||||||
struct Cmd_xref {
|
struct Cmd_xref {
|
||||||
Usr usr;
|
Usr usr;
|
||||||
SymbolKind kind;
|
Kind kind;
|
||||||
std::string field;
|
std::string field;
|
||||||
};
|
};
|
||||||
struct lsCommand {
|
struct Command {
|
||||||
std::string title;
|
std::string title;
|
||||||
std::string command;
|
std::string command;
|
||||||
std::vector<std::string> arguments;
|
std::vector<std::string> arguments;
|
||||||
};
|
};
|
||||||
struct lsCodeLens {
|
struct CodeLens {
|
||||||
lsRange range;
|
lsRange range;
|
||||||
std::optional<lsCommand> command;
|
std::optional<Command> command;
|
||||||
};
|
};
|
||||||
MAKE_REFLECT_STRUCT(Cmd_xref, usr, kind, field);
|
MAKE_REFLECT_STRUCT(Cmd_xref, usr, kind, field);
|
||||||
MAKE_REFLECT_STRUCT(lsCommand, title, command, arguments);
|
MAKE_REFLECT_STRUCT(Command, title, command, arguments);
|
||||||
MAKE_REFLECT_STRUCT(lsCodeLens, range, command);
|
MAKE_REFLECT_STRUCT(CodeLens, range, command);
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
std::string ToString(T &v) {
|
std::string ToString(T &v) {
|
||||||
@ -70,7 +70,7 @@ std::string ToString(T &v) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct CommonCodeLensParams {
|
struct CommonCodeLensParams {
|
||||||
std::vector<lsCodeLens> *result;
|
std::vector<CodeLens> *result;
|
||||||
DB *db;
|
DB *db;
|
||||||
WorkingFile *wfile;
|
WorkingFile *wfile;
|
||||||
};
|
};
|
||||||
@ -78,7 +78,7 @@ struct CommonCodeLensParams {
|
|||||||
|
|
||||||
void MessageHandler::textDocument_codeLens(TextDocumentParam ¶m,
|
void MessageHandler::textDocument_codeLens(TextDocumentParam ¶m,
|
||||||
ReplyOnce &reply) {
|
ReplyOnce &reply) {
|
||||||
std::vector<lsCodeLens> result;
|
std::vector<CodeLens> result;
|
||||||
std::string path = param.textDocument.uri.GetPath();
|
std::string path = param.textDocument.uri.GetPath();
|
||||||
|
|
||||||
QueryFile *file = FindFile(reply, path);
|
QueryFile *file = FindFile(reply, path);
|
||||||
@ -95,9 +95,9 @@ void MessageHandler::textDocument_codeLens(TextDocumentParam ¶m,
|
|||||||
std::optional<lsRange> ls_range = GetLsRange(wfile, range);
|
std::optional<lsRange> ls_range = GetLsRange(wfile, range);
|
||||||
if (!ls_range)
|
if (!ls_range)
|
||||||
return;
|
return;
|
||||||
lsCodeLens &code_lens = result.emplace_back();
|
CodeLens &code_lens = result.emplace_back();
|
||||||
code_lens.range = *ls_range;
|
code_lens.range = *ls_range;
|
||||||
code_lens.command = lsCommand();
|
code_lens.command = Command();
|
||||||
code_lens.command->command = std::string(ccls_xref);
|
code_lens.command->command = std::string(ccls_xref);
|
||||||
bool plural = num > 1 && singular[strlen(singular) - 1] != 'd';
|
bool plural = num > 1 && singular[strlen(singular) - 1] != 'd';
|
||||||
code_lens.command->title =
|
code_lens.command->title =
|
||||||
@ -110,49 +110,49 @@ void MessageHandler::textDocument_codeLens(TextDocumentParam ¶m,
|
|||||||
if (refcnt <= 0 || !sym.extent.Valid() || !seen.insert(sym.range).second)
|
if (refcnt <= 0 || !sym.extent.Valid() || !seen.insert(sym.range).second)
|
||||||
continue;
|
continue;
|
||||||
switch (sym.kind) {
|
switch (sym.kind) {
|
||||||
case SymbolKind::Func: {
|
case Kind::Func: {
|
||||||
QueryFunc &func = db->GetFunc(sym);
|
QueryFunc &func = db->GetFunc(sym);
|
||||||
const QueryFunc::Def *def = func.AnyDef();
|
const QueryFunc::Def *def = func.AnyDef();
|
||||||
if (!def)
|
if (!def)
|
||||||
continue;
|
continue;
|
||||||
std::vector<Use> base_uses = GetUsesForAllBases(db, func);
|
std::vector<Use> base_uses = GetUsesForAllBases(db, func);
|
||||||
std::vector<Use> derived_uses = GetUsesForAllDerived(db, func);
|
std::vector<Use> derived_uses = GetUsesForAllDerived(db, func);
|
||||||
Add("ref", {sym.usr, SymbolKind::Func, "uses"}, sym.range,
|
Add("ref", {sym.usr, Kind::Func, "uses"}, sym.range, func.uses.size(),
|
||||||
func.uses.size(), base_uses.empty());
|
base_uses.empty());
|
||||||
if (base_uses.size())
|
if (base_uses.size())
|
||||||
Add("b.ref", {sym.usr, SymbolKind::Func, "bases uses"}, sym.range,
|
Add("b.ref", {sym.usr, Kind::Func, "bases uses"}, sym.range,
|
||||||
base_uses.size());
|
base_uses.size());
|
||||||
if (derived_uses.size())
|
if (derived_uses.size())
|
||||||
Add("d.ref", {sym.usr, SymbolKind::Func, "derived uses"}, sym.range,
|
Add("d.ref", {sym.usr, Kind::Func, "derived uses"}, sym.range,
|
||||||
derived_uses.size());
|
derived_uses.size());
|
||||||
if (base_uses.empty())
|
if (base_uses.empty())
|
||||||
Add("base", {sym.usr, SymbolKind::Func, "bases"}, sym.range,
|
Add("base", {sym.usr, Kind::Func, "bases"}, sym.range,
|
||||||
def->bases.size());
|
def->bases.size());
|
||||||
Add("derived", {sym.usr, SymbolKind::Func, "derived"}, sym.range,
|
Add("derived", {sym.usr, Kind::Func, "derived"}, sym.range,
|
||||||
func.derived.size());
|
func.derived.size());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SymbolKind::Type: {
|
case Kind::Type: {
|
||||||
QueryType &type = db->GetType(sym);
|
QueryType &type = db->GetType(sym);
|
||||||
Add("ref", {sym.usr, SymbolKind::Type, "uses"}, sym.range,
|
Add("ref", {sym.usr, Kind::Type, "uses"}, sym.range, type.uses.size(),
|
||||||
type.uses.size(), true);
|
true);
|
||||||
Add("derived", {sym.usr, SymbolKind::Type, "derived"}, sym.range,
|
Add("derived", {sym.usr, Kind::Type, "derived"}, sym.range,
|
||||||
type.derived.size());
|
type.derived.size());
|
||||||
Add("var", {sym.usr, SymbolKind::Type, "instances"}, sym.range,
|
Add("var", {sym.usr, Kind::Type, "instances"}, sym.range,
|
||||||
type.instances.size());
|
type.instances.size());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SymbolKind::Var: {
|
case Kind::Var: {
|
||||||
QueryVar &var = db->GetVar(sym);
|
QueryVar &var = db->GetVar(sym);
|
||||||
const QueryVar::Def *def = var.AnyDef();
|
const QueryVar::Def *def = var.AnyDef();
|
||||||
if (!def || (def->is_local() && !g_config->codeLens.localVariables))
|
if (!def || (def->is_local() && !g_config->codeLens.localVariables))
|
||||||
continue;
|
continue;
|
||||||
Add("ref", {sym.usr, SymbolKind::Var, "uses"}, sym.range, var.uses.size(),
|
Add("ref", {sym.usr, Kind::Var, "uses"}, sym.range, var.uses.size(),
|
||||||
def->kind != lsSymbolKind::Macro);
|
def->kind != SymbolKind::Macro);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SymbolKind::File:
|
case Kind::File:
|
||||||
case SymbolKind::Invalid:
|
case Kind::Invalid:
|
||||||
llvm_unreachable("");
|
llvm_unreachable("");
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -162,7 +162,7 @@ void MessageHandler::textDocument_codeLens(TextDocumentParam ¶m,
|
|||||||
|
|
||||||
void MessageHandler::workspace_executeCommand(Reader &reader,
|
void MessageHandler::workspace_executeCommand(Reader &reader,
|
||||||
ReplyOnce &reply) {
|
ReplyOnce &reply) {
|
||||||
lsCommand param;
|
Command param;
|
||||||
Reflect(reader, param);
|
Reflect(reader, param);
|
||||||
if (param.arguments.empty()) {
|
if (param.arguments.empty()) {
|
||||||
return;
|
return;
|
||||||
@ -173,14 +173,14 @@ void MessageHandler::workspace_executeCommand(Reader &reader,
|
|||||||
if (param.command == ccls_xref) {
|
if (param.command == ccls_xref) {
|
||||||
Cmd_xref cmd;
|
Cmd_xref cmd;
|
||||||
Reflect(json_reader, cmd);
|
Reflect(json_reader, cmd);
|
||||||
std::vector<lsLocation> result;
|
std::vector<Location> result;
|
||||||
auto Map = [&](auto &&uses) {
|
auto Map = [&](auto &&uses) {
|
||||||
for (auto &use : uses)
|
for (auto &use : uses)
|
||||||
if (auto loc = GetLsLocation(db, wfiles, use))
|
if (auto loc = GetLsLocation(db, wfiles, use))
|
||||||
result.push_back(std::move(*loc));
|
result.push_back(std::move(*loc));
|
||||||
};
|
};
|
||||||
switch (cmd.kind) {
|
switch (cmd.kind) {
|
||||||
case SymbolKind::Func: {
|
case Kind::Func: {
|
||||||
QueryFunc &func = db->Func(cmd.usr);
|
QueryFunc &func = db->Func(cmd.usr);
|
||||||
if (cmd.field == "bases") {
|
if (cmd.field == "bases") {
|
||||||
if (auto *def = func.AnyDef())
|
if (auto *def = func.AnyDef())
|
||||||
@ -196,7 +196,7 @@ void MessageHandler::workspace_executeCommand(Reader &reader,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SymbolKind::Type: {
|
case Kind::Type: {
|
||||||
QueryType &type = db->Type(cmd.usr);
|
QueryType &type = db->Type(cmd.usr);
|
||||||
if (cmd.field == "derived") {
|
if (cmd.field == "derived") {
|
||||||
Map(GetTypeDeclarations(db, type.derived));
|
Map(GetTypeDeclarations(db, type.derived));
|
||||||
@ -207,7 +207,7 @@ void MessageHandler::workspace_executeCommand(Reader &reader,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SymbolKind::Var: {
|
case Kind::Var: {
|
||||||
QueryVar &var = db->Var(cmd.usr);
|
QueryVar &var = db->Var(cmd.usr);
|
||||||
if (cmd.field == "uses")
|
if (cmd.field == "uses")
|
||||||
Map(var.uses);
|
Map(var.uses);
|
||||||
|
@ -18,21 +18,21 @@ namespace ccls {
|
|||||||
using namespace clang;
|
using namespace clang;
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
struct lsCompletionList {
|
MAKE_REFLECT_TYPE_PROXY(InsertTextFormat);
|
||||||
bool isIncomplete = false;
|
MAKE_REFLECT_TYPE_PROXY(CompletionItemKind);
|
||||||
std::vector<lsCompletionItem> items;
|
MAKE_REFLECT_STRUCT(CompletionItem, label, kind, detail, documentation,
|
||||||
};
|
|
||||||
|
|
||||||
MAKE_REFLECT_TYPE_PROXY(lsInsertTextFormat);
|
|
||||||
MAKE_REFLECT_TYPE_PROXY(lsCompletionItemKind);
|
|
||||||
MAKE_REFLECT_STRUCT(lsCompletionItem, label, kind, detail, documentation,
|
|
||||||
sortText, filterText, insertText, insertTextFormat,
|
sortText, filterText, insertText, insertTextFormat,
|
||||||
textEdit, additionalTextEdits);
|
textEdit, additionalTextEdits);
|
||||||
MAKE_REFLECT_STRUCT(lsCompletionList, isIncomplete, items);
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
struct CompletionList {
|
||||||
|
bool isIncomplete = false;
|
||||||
|
std::vector<CompletionItem> items;
|
||||||
|
};
|
||||||
|
MAKE_REFLECT_STRUCT(CompletionList, isIncomplete, items);
|
||||||
|
|
||||||
void DecorateIncludePaths(const std::smatch &match,
|
void DecorateIncludePaths(const std::smatch &match,
|
||||||
std::vector<lsCompletionItem> *items) {
|
std::vector<CompletionItem> *items) {
|
||||||
std::string spaces_after_include = " ";
|
std::string spaces_after_include = " ";
|
||||||
if (match[3].compare("include") == 0 && match[5].length())
|
if (match[3].compare("include") == 0 && match[5].length())
|
||||||
spaces_after_include = match[4].str();
|
spaces_after_include = match[4].str();
|
||||||
@ -41,7 +41,7 @@ void DecorateIncludePaths(const std::smatch &match,
|
|||||||
match[1].str() + '#' + match[2].str() + "include" + spaces_after_include;
|
match[1].str() + '#' + match[2].str() + "include" + spaces_after_include;
|
||||||
std::string suffix = match[7].str();
|
std::string suffix = match[7].str();
|
||||||
|
|
||||||
for (lsCompletionItem &item : *items) {
|
for (CompletionItem &item : *items) {
|
||||||
char quote0, quote1;
|
char quote0, quote1;
|
||||||
if (match[5].compare("<") == 0 ||
|
if (match[5].compare("<") == 0 ||
|
||||||
(match[5].length() == 0 && item.use_angle_brackets_))
|
(match[5].length() == 0 && item.use_angle_brackets_))
|
||||||
@ -82,9 +82,9 @@ ParseIncludeLineResult ParseIncludeLine(const std::string &line) {
|
|||||||
// Pre-filters completion responses before sending to vscode. This results in a
|
// Pre-filters completion responses before sending to vscode. This results in a
|
||||||
// significantly snappier completion experience as vscode is easily overloaded
|
// significantly snappier completion experience as vscode is easily overloaded
|
||||||
// when given 1000+ completion items.
|
// when given 1000+ completion items.
|
||||||
void FilterCandidates(lsCompletionList &result,
|
void FilterCandidates(CompletionList &result, const std::string &complete_text,
|
||||||
const std::string &complete_text, lsPosition begin_pos,
|
lsPosition begin_pos, lsPosition end_pos,
|
||||||
lsPosition end_pos, const std::string &buffer_line) {
|
const std::string &buffer_line) {
|
||||||
assert(begin_pos.line == end_pos.line);
|
assert(begin_pos.line == end_pos.line);
|
||||||
auto &items = result.items;
|
auto &items = result.items;
|
||||||
|
|
||||||
@ -155,12 +155,12 @@ void FilterCandidates(lsCompletionList &result,
|
|||||||
: FuzzyMatcher::kMinScore;
|
: FuzzyMatcher::kMinScore;
|
||||||
}
|
}
|
||||||
items.erase(std::remove_if(items.begin(), items.end(),
|
items.erase(std::remove_if(items.begin(), items.end(),
|
||||||
[](const lsCompletionItem &item) {
|
[](const CompletionItem &item) {
|
||||||
return item.score_ <= FuzzyMatcher::kMinScore;
|
return item.score_ <= FuzzyMatcher::kMinScore;
|
||||||
}),
|
}),
|
||||||
items.end());
|
items.end());
|
||||||
std::sort(items.begin(), items.end(),
|
std::sort(items.begin(), items.end(),
|
||||||
[](const lsCompletionItem &lhs, const lsCompletionItem &rhs) {
|
[](const CompletionItem &lhs, const CompletionItem &rhs) {
|
||||||
int t = int(lhs.additionalTextEdits.size() -
|
int t = int(lhs.additionalTextEdits.size() -
|
||||||
rhs.additionalTextEdits.size());
|
rhs.additionalTextEdits.size());
|
||||||
if (t)
|
if (t)
|
||||||
@ -178,45 +178,45 @@ void FilterCandidates(lsCompletionList &result,
|
|||||||
finalize();
|
finalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
lsCompletionItemKind GetCompletionKind(CXCursorKind cursor_kind) {
|
CompletionItemKind GetCompletionKind(CXCursorKind cursor_kind) {
|
||||||
switch (cursor_kind) {
|
switch (cursor_kind) {
|
||||||
case CXCursor_UnexposedDecl:
|
case CXCursor_UnexposedDecl:
|
||||||
return lsCompletionItemKind::Text;
|
return CompletionItemKind::Text;
|
||||||
|
|
||||||
case CXCursor_StructDecl:
|
case CXCursor_StructDecl:
|
||||||
case CXCursor_UnionDecl:
|
case CXCursor_UnionDecl:
|
||||||
return lsCompletionItemKind::Struct;
|
return CompletionItemKind::Struct;
|
||||||
case CXCursor_ClassDecl:
|
case CXCursor_ClassDecl:
|
||||||
return lsCompletionItemKind::Class;
|
return CompletionItemKind::Class;
|
||||||
case CXCursor_EnumDecl:
|
case CXCursor_EnumDecl:
|
||||||
return lsCompletionItemKind::Enum;
|
return CompletionItemKind::Enum;
|
||||||
case CXCursor_FieldDecl:
|
case CXCursor_FieldDecl:
|
||||||
return lsCompletionItemKind::Field;
|
return CompletionItemKind::Field;
|
||||||
case CXCursor_EnumConstantDecl:
|
case CXCursor_EnumConstantDecl:
|
||||||
return lsCompletionItemKind::EnumMember;
|
return CompletionItemKind::EnumMember;
|
||||||
case CXCursor_FunctionDecl:
|
case CXCursor_FunctionDecl:
|
||||||
return lsCompletionItemKind::Function;
|
return CompletionItemKind::Function;
|
||||||
case CXCursor_VarDecl:
|
case CXCursor_VarDecl:
|
||||||
case CXCursor_ParmDecl:
|
case CXCursor_ParmDecl:
|
||||||
return lsCompletionItemKind::Variable;
|
return CompletionItemKind::Variable;
|
||||||
case CXCursor_ObjCInterfaceDecl:
|
case CXCursor_ObjCInterfaceDecl:
|
||||||
return lsCompletionItemKind::Interface;
|
return CompletionItemKind::Interface;
|
||||||
|
|
||||||
case CXCursor_ObjCInstanceMethodDecl:
|
case CXCursor_ObjCInstanceMethodDecl:
|
||||||
case CXCursor_CXXMethod:
|
case CXCursor_CXXMethod:
|
||||||
case CXCursor_ObjCClassMethodDecl:
|
case CXCursor_ObjCClassMethodDecl:
|
||||||
return lsCompletionItemKind::Method;
|
return CompletionItemKind::Method;
|
||||||
|
|
||||||
case CXCursor_FunctionTemplate:
|
case CXCursor_FunctionTemplate:
|
||||||
return lsCompletionItemKind::Function;
|
return CompletionItemKind::Function;
|
||||||
|
|
||||||
case CXCursor_Constructor:
|
case CXCursor_Constructor:
|
||||||
case CXCursor_Destructor:
|
case CXCursor_Destructor:
|
||||||
case CXCursor_ConversionFunction:
|
case CXCursor_ConversionFunction:
|
||||||
return lsCompletionItemKind::Constructor;
|
return CompletionItemKind::Constructor;
|
||||||
|
|
||||||
case CXCursor_ObjCIvarDecl:
|
case CXCursor_ObjCIvarDecl:
|
||||||
return lsCompletionItemKind::Variable;
|
return CompletionItemKind::Variable;
|
||||||
|
|
||||||
case CXCursor_ClassTemplate:
|
case CXCursor_ClassTemplate:
|
||||||
case CXCursor_ClassTemplatePartialSpecialization:
|
case CXCursor_ClassTemplatePartialSpecialization:
|
||||||
@ -228,50 +228,43 @@ lsCompletionItemKind GetCompletionKind(CXCursorKind cursor_kind) {
|
|||||||
case CXCursor_ObjCProtocolDecl:
|
case CXCursor_ObjCProtocolDecl:
|
||||||
case CXCursor_ObjCImplementationDecl:
|
case CXCursor_ObjCImplementationDecl:
|
||||||
case CXCursor_ObjCCategoryImplDecl:
|
case CXCursor_ObjCCategoryImplDecl:
|
||||||
return lsCompletionItemKind::Class;
|
return CompletionItemKind::Class;
|
||||||
|
|
||||||
case CXCursor_ObjCPropertyDecl:
|
case CXCursor_ObjCPropertyDecl:
|
||||||
return lsCompletionItemKind::Property;
|
return CompletionItemKind::Property;
|
||||||
|
|
||||||
case CXCursor_MacroInstantiation:
|
case CXCursor_MacroInstantiation:
|
||||||
case CXCursor_MacroDefinition:
|
case CXCursor_MacroDefinition:
|
||||||
return lsCompletionItemKind::Interface;
|
return CompletionItemKind::Interface;
|
||||||
|
|
||||||
case CXCursor_Namespace:
|
case CXCursor_Namespace:
|
||||||
case CXCursor_NamespaceAlias:
|
case CXCursor_NamespaceAlias:
|
||||||
case CXCursor_NamespaceRef:
|
case CXCursor_NamespaceRef:
|
||||||
return lsCompletionItemKind::Module;
|
return CompletionItemKind::Module;
|
||||||
|
|
||||||
case CXCursor_MemberRef:
|
case CXCursor_MemberRef:
|
||||||
case CXCursor_TypeRef:
|
case CXCursor_TypeRef:
|
||||||
case CXCursor_ObjCSuperClassRef:
|
case CXCursor_ObjCSuperClassRef:
|
||||||
case CXCursor_ObjCProtocolRef:
|
case CXCursor_ObjCProtocolRef:
|
||||||
case CXCursor_ObjCClassRef:
|
case CXCursor_ObjCClassRef:
|
||||||
return lsCompletionItemKind::Reference;
|
return CompletionItemKind::Reference;
|
||||||
|
|
||||||
// return lsCompletionItemKind::Unit;
|
|
||||||
// return lsCompletionItemKind::Value;
|
|
||||||
// return lsCompletionItemKind::Keyword;
|
|
||||||
// return lsCompletionItemKind::Snippet;
|
|
||||||
// return lsCompletionItemKind::Color;
|
|
||||||
// return lsCompletionItemKind::File;
|
|
||||||
|
|
||||||
case CXCursor_NotImplemented:
|
case CXCursor_NotImplemented:
|
||||||
case CXCursor_OverloadCandidate:
|
case CXCursor_OverloadCandidate:
|
||||||
return lsCompletionItemKind::Text;
|
return CompletionItemKind::Text;
|
||||||
|
|
||||||
case CXCursor_TemplateTypeParameter:
|
case CXCursor_TemplateTypeParameter:
|
||||||
case CXCursor_TemplateTemplateParameter:
|
case CXCursor_TemplateTemplateParameter:
|
||||||
return lsCompletionItemKind::TypeParameter;
|
return CompletionItemKind::TypeParameter;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
LOG_S(WARNING) << "Unhandled completion kind " << cursor_kind;
|
LOG_S(WARNING) << "Unhandled completion kind " << cursor_kind;
|
||||||
return lsCompletionItemKind::Text;
|
return CompletionItemKind::Text;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BuildItem(const CodeCompletionResult &R, const CodeCompletionString &CCS,
|
void BuildItem(const CodeCompletionResult &R, const CodeCompletionString &CCS,
|
||||||
std::vector<lsCompletionItem> &out) {
|
std::vector<CompletionItem> &out) {
|
||||||
assert(!out.empty());
|
assert(!out.empty());
|
||||||
auto first = out.size() - 1;
|
auto first = out.size() - 1;
|
||||||
bool ignore = false;
|
bool ignore = false;
|
||||||
@ -330,7 +323,7 @@ void BuildItem(const CodeCompletionResult &R, const CodeCompletionString &CCS,
|
|||||||
}
|
}
|
||||||
out[i].textEdit.newText +=
|
out[i].textEdit.newText +=
|
||||||
"${" + std::to_string(out[i].parameters_.size()) + ":" + text + "}";
|
"${" + std::to_string(out[i].parameters_.size()) + ":" + text + "}";
|
||||||
out[i].insertTextFormat = lsInsertTextFormat::Snippet;
|
out[i].insertTextFormat = InsertTextFormat::Snippet;
|
||||||
} else if (Kind != CodeCompletionString::CK_Informative) {
|
} else if (Kind != CodeCompletionString::CK_Informative) {
|
||||||
out[i].textEdit.newText += text;
|
out[i].textEdit.newText += text;
|
||||||
}
|
}
|
||||||
@ -352,7 +345,7 @@ class CompletionConsumer : public CodeCompleteConsumer {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
bool from_cache;
|
bool from_cache;
|
||||||
std::vector<lsCompletionItem> ls_items;
|
std::vector<CompletionItem> ls_items;
|
||||||
|
|
||||||
CompletionConsumer(const CodeCompleteOptions &Opts, bool from_cache)
|
CompletionConsumer(const CodeCompleteOptions &Opts, bool from_cache)
|
||||||
: CodeCompleteConsumer(Opts, false),
|
: CodeCompleteConsumer(Opts, false),
|
||||||
@ -384,7 +377,7 @@ public:
|
|||||||
CodeCompletionString *CCS = R.CreateCodeCompletionString(
|
CodeCompletionString *CCS = R.CreateCodeCompletionString(
|
||||||
S, Context, getAllocator(), getCodeCompletionTUInfo(),
|
S, Context, getAllocator(), getCodeCompletionTUInfo(),
|
||||||
includeBriefComments());
|
includeBriefComments());
|
||||||
lsCompletionItem ls_item;
|
CompletionItem ls_item;
|
||||||
ls_item.kind = GetCompletionKind(R.CursorKind);
|
ls_item.kind = GetCompletionKind(R.CursorKind);
|
||||||
if (const char *brief = CCS->getBriefComment())
|
if (const char *brief = CCS->getBriefComment())
|
||||||
ls_item.documentation = brief;
|
ls_item.documentation = brief;
|
||||||
@ -396,7 +389,7 @@ public:
|
|||||||
|
|
||||||
for (size_t j = first_idx; j < ls_items.size(); j++) {
|
for (size_t j = first_idx; j < ls_items.size(); j++) {
|
||||||
if (g_config->client.snippetSupport &&
|
if (g_config->client.snippetSupport &&
|
||||||
ls_items[j].insertTextFormat == lsInsertTextFormat::Snippet)
|
ls_items[j].insertTextFormat == InsertTextFormat::Snippet)
|
||||||
ls_items[j].textEdit.newText += "$0";
|
ls_items[j].textEdit.newText += "$0";
|
||||||
ls_items[j].priority_ = CCS->getPriority();
|
ls_items[j].priority_ = CCS->getPriority();
|
||||||
if (!g_config->completion.detailedLabel) {
|
if (!g_config->completion.detailedLabel) {
|
||||||
@ -407,7 +400,7 @@ public:
|
|||||||
#if LLVM_VERSION_MAJOR >= 7
|
#if LLVM_VERSION_MAJOR >= 7
|
||||||
for (const FixItHint &FixIt : R.FixIts) {
|
for (const FixItHint &FixIt : R.FixIts) {
|
||||||
auto &AST = S.getASTContext();
|
auto &AST = S.getASTContext();
|
||||||
lsTextEdit ls_edit =
|
TextEdit ls_edit =
|
||||||
ccls::ToTextEdit(AST.getSourceManager(), AST.getLangOpts(), FixIt);
|
ccls::ToTextEdit(AST.getSourceManager(), AST.getLangOpts(), FixIt);
|
||||||
for (size_t j = first_idx; j < ls_items.size(); j++)
|
for (size_t j = first_idx; j < ls_items.size(); j++)
|
||||||
ls_items[j].additionalTextEdits.push_back(ls_edit);
|
ls_items[j].additionalTextEdits.push_back(ls_edit);
|
||||||
@ -421,10 +414,10 @@ public:
|
|||||||
};
|
};
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void MessageHandler::textDocument_completion(lsCompletionParams ¶m,
|
void MessageHandler::textDocument_completion(CompletionParam ¶m,
|
||||||
ReplyOnce &reply) {
|
ReplyOnce &reply) {
|
||||||
static CompleteConsumerCache<std::vector<lsCompletionItem>> cache;
|
static CompleteConsumerCache<std::vector<CompletionItem>> cache;
|
||||||
lsCompletionList result;
|
CompletionList result;
|
||||||
std::string path = param.textDocument.uri.GetPath();
|
std::string path = param.textDocument.uri.GetPath();
|
||||||
WorkingFile *file = wfiles->GetFileByFilename(path);
|
WorkingFile *file = wfiles->GetFileByFilename(path);
|
||||||
if (!file) {
|
if (!file) {
|
||||||
@ -440,7 +433,7 @@ void MessageHandler::textDocument_completion(lsCompletionParams ¶m,
|
|||||||
|
|
||||||
// Check for - and : before completing -> or ::, since vscode does not
|
// Check for - and : before completing -> or ::, since vscode does not
|
||||||
// support multi-character trigger characters.
|
// support multi-character trigger characters.
|
||||||
if (param.context.triggerKind == lsCompletionTriggerKind::TriggerCharacter &&
|
if (param.context.triggerKind == CompletionTriggerKind::TriggerCharacter &&
|
||||||
param.context.triggerCharacter) {
|
param.context.triggerCharacter) {
|
||||||
bool did_fail_check = false;
|
bool did_fail_check = false;
|
||||||
|
|
||||||
@ -484,7 +477,7 @@ void MessageHandler::textDocument_completion(lsCompletionParams ¶m,
|
|||||||
ParseIncludeLineResult preprocess = ParseIncludeLine(buffer_line);
|
ParseIncludeLineResult preprocess = ParseIncludeLine(buffer_line);
|
||||||
|
|
||||||
if (preprocess.ok && preprocess.keyword.compare("include") == 0) {
|
if (preprocess.ok && preprocess.keyword.compare("include") == 0) {
|
||||||
lsCompletionList result;
|
CompletionList result;
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lock(
|
std::unique_lock<std::mutex> lock(
|
||||||
include_complete->completion_items_mutex, std::defer_lock);
|
include_complete->completion_items_mutex, std::defer_lock);
|
||||||
@ -509,7 +502,7 @@ void MessageHandler::textDocument_completion(lsCompletionParams ¶m,
|
|||||||
if (!OptConsumer)
|
if (!OptConsumer)
|
||||||
return;
|
return;
|
||||||
auto *Consumer = static_cast<CompletionConsumer *>(OptConsumer);
|
auto *Consumer = static_cast<CompletionConsumer *>(OptConsumer);
|
||||||
lsCompletionList result;
|
CompletionList result;
|
||||||
result.items = Consumer->ls_items;
|
result.items = Consumer->ls_items;
|
||||||
|
|
||||||
FilterCandidates(result, completion_text, begin_pos, end_pos,
|
FilterCandidates(result, completion_text, begin_pos, end_pos,
|
||||||
|
@ -12,14 +12,14 @@ namespace ccls {
|
|||||||
namespace {
|
namespace {
|
||||||
std::vector<DeclRef> GetNonDefDeclarationTargets(DB *db, SymbolRef sym) {
|
std::vector<DeclRef> GetNonDefDeclarationTargets(DB *db, SymbolRef sym) {
|
||||||
switch (sym.kind) {
|
switch (sym.kind) {
|
||||||
case SymbolKind::Var: {
|
case Kind::Var: {
|
||||||
std::vector<DeclRef> ret = GetNonDefDeclarations(db, sym);
|
std::vector<DeclRef> ret = GetNonDefDeclarations(db, sym);
|
||||||
// If there is no declaration, jump to its type.
|
// If there is no declaration, jump to its type.
|
||||||
if (ret.empty()) {
|
if (ret.empty()) {
|
||||||
for (auto &def : db->GetVar(sym).def)
|
for (auto &def : db->GetVar(sym).def)
|
||||||
if (def.type) {
|
if (def.type) {
|
||||||
if (Maybe<DeclRef> use = GetDefinitionSpell(
|
if (Maybe<DeclRef> use =
|
||||||
db, SymbolIdx{def.type, SymbolKind::Type})) {
|
GetDefinitionSpell(db, SymbolIdx{def.type, Kind::Type})) {
|
||||||
ret.push_back(*use);
|
ret.push_back(*use);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -40,7 +40,7 @@ void MessageHandler::textDocument_definition(TextDocumentPositionParam ¶m,
|
|||||||
if (!file)
|
if (!file)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
std::vector<lsLocation> result;
|
std::vector<Location> result;
|
||||||
Maybe<Use> on_def;
|
Maybe<Use> on_def;
|
||||||
WorkingFile *wfile = wfiles->GetFileByFilename(file->def->path);
|
WorkingFile *wfile = wfiles->GetFileByFilename(file->def->path);
|
||||||
lsPosition &ls_pos = param.position;
|
lsPosition &ls_pos = param.position;
|
||||||
@ -88,7 +88,7 @@ void MessageHandler::textDocument_definition(TextDocumentPositionParam ¶m,
|
|||||||
for (const IndexInclude &include : file->def->includes) {
|
for (const IndexInclude &include : file->def->includes) {
|
||||||
if (include.line == ls_pos.line) {
|
if (include.line == ls_pos.line) {
|
||||||
result.push_back(
|
result.push_back(
|
||||||
lsLocation{lsDocumentUri::FromPath(include.resolved_path)});
|
Location{DocumentUri::FromPath(include.resolved_path)});
|
||||||
range = {{0, 0}, {0, 0}};
|
range = {{0, 0}, {0, 0}};
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -110,7 +110,7 @@ void MessageHandler::textDocument_definition(TextDocumentPositionParam ¶m,
|
|||||||
// not in the same file, line distance> to find the best match.
|
// not in the same file, line distance> to find the best match.
|
||||||
std::tuple<int, int, bool, int> best_score{INT_MAX, 0, true, 0};
|
std::tuple<int, int, bool, int> best_score{INT_MAX, 0, true, 0};
|
||||||
SymbolIdx best_sym;
|
SymbolIdx best_sym;
|
||||||
best_sym.kind = SymbolKind::Invalid;
|
best_sym.kind = Kind::Invalid;
|
||||||
auto fn = [&](SymbolIdx sym) {
|
auto fn = [&](SymbolIdx sym) {
|
||||||
std::string_view short_name = db->GetSymbolName(sym, false),
|
std::string_view short_name = db->GetSymbolName(sym, false),
|
||||||
name = short_query.size() < query.size()
|
name = short_query.size() < query.size()
|
||||||
@ -136,14 +136,14 @@ void MessageHandler::textDocument_definition(TextDocumentPositionParam ¶m,
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
for (auto &func : db->funcs)
|
for (auto &func : db->funcs)
|
||||||
fn({func.usr, SymbolKind::Func});
|
fn({func.usr, Kind::Func});
|
||||||
for (auto &type : db->types)
|
for (auto &type : db->types)
|
||||||
fn({type.usr, SymbolKind::Type});
|
fn({type.usr, Kind::Type});
|
||||||
for (auto &var : db->vars)
|
for (auto &var : db->vars)
|
||||||
if (var.def.size() && !var.def[0].is_local())
|
if (var.def.size() && !var.def[0].is_local())
|
||||||
fn({var.usr, SymbolKind::Var});
|
fn({var.usr, Kind::Var});
|
||||||
|
|
||||||
if (best_sym.kind != SymbolKind::Invalid) {
|
if (best_sym.kind != Kind::Invalid) {
|
||||||
Maybe<DeclRef> dr = GetDefinitionSpell(db, best_sym);
|
Maybe<DeclRef> dr = GetDefinitionSpell(db, best_sym);
|
||||||
assert(dr);
|
assert(dr);
|
||||||
if (auto loc = GetLsLocation(db, wfiles, *dr))
|
if (auto loc = GetLsLocation(db, wfiles, *dr))
|
||||||
@ -162,7 +162,7 @@ void MessageHandler::textDocument_typeDefinition(
|
|||||||
return;
|
return;
|
||||||
WorkingFile *working_file = wfiles->GetFileByFilename(file->def->path);
|
WorkingFile *working_file = wfiles->GetFileByFilename(file->def->path);
|
||||||
|
|
||||||
std::vector<lsLocation> result;
|
std::vector<Location> result;
|
||||||
auto Add = [&](const QueryType &type) {
|
auto Add = [&](const QueryType &type) {
|
||||||
for (const auto &def : type.def)
|
for (const auto &def : type.def)
|
||||||
if (def.spell) {
|
if (def.spell) {
|
||||||
@ -177,13 +177,13 @@ void MessageHandler::textDocument_typeDefinition(
|
|||||||
for (SymbolRef sym :
|
for (SymbolRef sym :
|
||||||
FindSymbolsAtLocation(working_file, file, param.position)) {
|
FindSymbolsAtLocation(working_file, file, param.position)) {
|
||||||
switch (sym.kind) {
|
switch (sym.kind) {
|
||||||
case SymbolKind::Var: {
|
case Kind::Var: {
|
||||||
const QueryVar::Def *def = db->GetVar(sym).AnyDef();
|
const QueryVar::Def *def = db->GetVar(sym).AnyDef();
|
||||||
if (def && def->type)
|
if (def && def->type)
|
||||||
Add(db->Type(def->type));
|
Add(db->Type(def->type));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SymbolKind::Type: {
|
case Kind::Type: {
|
||||||
for (auto &def : db->GetType(sym).def)
|
for (auto &def : db->GetType(sym).def)
|
||||||
if (def.alias_of) {
|
if (def.alias_of) {
|
||||||
Add(db->Type(def.alias_of));
|
Add(db->Type(def.alias_of));
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
MAKE_HASHABLE(ccls::SymbolIdx, t.usr, t.kind);
|
MAKE_HASHABLE(ccls::SymbolIdx, t.usr, t.kind);
|
||||||
|
|
||||||
namespace ccls {
|
namespace ccls {
|
||||||
MAKE_REFLECT_STRUCT(lsSymbolInformation, name, kind, location, containerName);
|
MAKE_REFLECT_STRUCT(SymbolInformation, name, kind, location, containerName);
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
struct DocumentHighlight {
|
struct DocumentHighlight {
|
||||||
@ -45,7 +45,7 @@ void MessageHandler::textDocument_documentHighlight(
|
|||||||
if (refcnt <= 0)
|
if (refcnt <= 0)
|
||||||
continue;
|
continue;
|
||||||
Usr usr = sym.usr;
|
Usr usr = sym.usr;
|
||||||
SymbolKind kind = sym.kind;
|
Kind kind = sym.kind;
|
||||||
if (std::none_of(syms.begin(), syms.end(), [&](auto &sym1) {
|
if (std::none_of(syms.begin(), syms.end(), [&](auto &sym1) {
|
||||||
return usr == sym1.usr && kind == sym1.kind;
|
return usr == sym1.usr && kind == sym1.kind;
|
||||||
}))
|
}))
|
||||||
@ -68,11 +68,11 @@ void MessageHandler::textDocument_documentHighlight(
|
|||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
struct lsDocumentLink {
|
struct DocumentLink {
|
||||||
lsRange range;
|
lsRange range;
|
||||||
lsDocumentUri target;
|
DocumentUri target;
|
||||||
};
|
};
|
||||||
MAKE_REFLECT_STRUCT(lsDocumentLink, range, target);
|
MAKE_REFLECT_STRUCT(DocumentLink, range, target);
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void MessageHandler::textDocument_documentLink(TextDocumentParam ¶m,
|
void MessageHandler::textDocument_documentLink(TextDocumentParam ¶m,
|
||||||
@ -81,10 +81,10 @@ void MessageHandler::textDocument_documentLink(TextDocumentParam ¶m,
|
|||||||
if (!file)
|
if (!file)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
std::vector<lsDocumentLink> result;
|
std::vector<DocumentLink> result;
|
||||||
for (const IndexInclude &include : file->def->includes)
|
for (const IndexInclude &include : file->def->includes)
|
||||||
result.push_back({lsRange{{include.line, 0}, {include.line + 1, 0}},
|
result.push_back({lsRange{{include.line, 0}, {include.line + 1, 0}},
|
||||||
lsDocumentUri::FromPath(include.resolved_path)});
|
DocumentUri::FromPath(include.resolved_path)});
|
||||||
reply(result);
|
reply(result);
|
||||||
} // namespace ccls
|
} // namespace ccls
|
||||||
|
|
||||||
@ -98,18 +98,18 @@ struct DocumentSymbolParam : TextDocumentParam {
|
|||||||
};
|
};
|
||||||
MAKE_REFLECT_STRUCT(DocumentSymbolParam, textDocument, all, startLine, endLine);
|
MAKE_REFLECT_STRUCT(DocumentSymbolParam, textDocument, all, startLine, endLine);
|
||||||
|
|
||||||
struct lsDocumentSymbol {
|
struct DocumentSymbol {
|
||||||
std::string name;
|
std::string name;
|
||||||
std::string detail;
|
std::string detail;
|
||||||
lsSymbolKind kind;
|
SymbolKind kind;
|
||||||
lsRange range;
|
lsRange range;
|
||||||
lsRange selectionRange;
|
lsRange selectionRange;
|
||||||
std::vector<std::unique_ptr<lsDocumentSymbol>> children;
|
std::vector<std::unique_ptr<DocumentSymbol>> children;
|
||||||
};
|
};
|
||||||
void Reflect(Writer &vis, std::unique_ptr<lsDocumentSymbol> &v);
|
void Reflect(Writer &vis, std::unique_ptr<DocumentSymbol> &v);
|
||||||
MAKE_REFLECT_STRUCT(lsDocumentSymbol, name, detail, kind, range, selectionRange,
|
MAKE_REFLECT_STRUCT(DocumentSymbol, name, detail, kind, range, selectionRange,
|
||||||
children);
|
children);
|
||||||
void Reflect(Writer &vis, std::unique_ptr<lsDocumentSymbol> &v) {
|
void Reflect(Writer &vis, std::unique_ptr<DocumentSymbol> &v) {
|
||||||
Reflect(vis, *v);
|
Reflect(vis, *v);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,7 +119,7 @@ bool Ignore(const Def *def) {
|
|||||||
}
|
}
|
||||||
template <>
|
template <>
|
||||||
bool Ignore(const QueryType::Def *def) {
|
bool Ignore(const QueryType::Def *def) {
|
||||||
return !def || def->kind == lsSymbolKind::TypeParameter;
|
return !def || def->kind == SymbolKind::TypeParameter;
|
||||||
}
|
}
|
||||||
template<>
|
template<>
|
||||||
bool Ignore(const QueryVar::Def *def) {
|
bool Ignore(const QueryVar::Def *def) {
|
||||||
@ -151,8 +151,8 @@ void MessageHandler::textDocument_documentSymbol(Reader &reader,
|
|||||||
std::sort(result.begin(), result.end());
|
std::sort(result.begin(), result.end());
|
||||||
reply(result);
|
reply(result);
|
||||||
} else if (g_config->client.hierarchicalDocumentSymbolSupport) {
|
} else if (g_config->client.hierarchicalDocumentSymbolSupport) {
|
||||||
std::unordered_map<SymbolIdx, std::unique_ptr<lsDocumentSymbol>> sym2ds;
|
std::unordered_map<SymbolIdx, std::unique_ptr<DocumentSymbol>> sym2ds;
|
||||||
std::vector<std::pair<std::vector<const void *>, lsDocumentSymbol *>> funcs,
|
std::vector<std::pair<std::vector<const void *>, DocumentSymbol *>> funcs,
|
||||||
types;
|
types;
|
||||||
for (auto [sym, refcnt] : file->symbol2refcnt) {
|
for (auto [sym, refcnt] : file->symbol2refcnt) {
|
||||||
if (refcnt <= 0 || !sym.extent.Valid())
|
if (refcnt <= 0 || !sym.extent.Valid())
|
||||||
@ -161,7 +161,7 @@ void MessageHandler::textDocument_documentSymbol(Reader &reader,
|
|||||||
if (!r.second)
|
if (!r.second)
|
||||||
continue;
|
continue;
|
||||||
auto &ds = r.first->second;
|
auto &ds = r.first->second;
|
||||||
ds = std::make_unique<lsDocumentSymbol>();
|
ds = std::make_unique<DocumentSymbol>();
|
||||||
std::vector<const void *> def_ptrs;
|
std::vector<const void *> def_ptrs;
|
||||||
WithEntity(db, sym, [&, sym = sym](const auto &entity) {
|
WithEntity(db, sym, [&, sym = sym](const auto &entity) {
|
||||||
auto *def = entity.AnyDef();
|
auto *def = entity.AnyDef();
|
||||||
@ -180,25 +180,25 @@ void MessageHandler::textDocument_documentSymbol(Reader &reader,
|
|||||||
for (auto &def : entity.def)
|
for (auto &def : entity.def)
|
||||||
if (def.file_id == file_id && !Ignore(&def)) {
|
if (def.file_id == file_id && !Ignore(&def)) {
|
||||||
ds->kind = def.kind;
|
ds->kind = def.kind;
|
||||||
if (def.spell || def.kind == lsSymbolKind::Namespace)
|
if (def.spell || def.kind == SymbolKind::Namespace)
|
||||||
def_ptrs.push_back(&def);
|
def_ptrs.push_back(&def);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (def_ptrs.empty() || !(param.all || sym.role & Role::Definition ||
|
if (def_ptrs.empty() || !(param.all || sym.role & Role::Definition ||
|
||||||
ds->kind == lsSymbolKind::Namespace)) {
|
ds->kind == SymbolKind::Namespace)) {
|
||||||
ds.reset();
|
ds.reset();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (sym.kind == SymbolKind::Func)
|
if (sym.kind == Kind::Func)
|
||||||
funcs.emplace_back(std::move(def_ptrs), ds.get());
|
funcs.emplace_back(std::move(def_ptrs), ds.get());
|
||||||
else if (sym.kind == SymbolKind::Type)
|
else if (sym.kind == Kind::Type)
|
||||||
types.emplace_back(std::move(def_ptrs), ds.get());
|
types.emplace_back(std::move(def_ptrs), ds.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto &[def_ptrs, ds] : funcs)
|
for (auto &[def_ptrs, ds] : funcs)
|
||||||
for (const void *def_ptr : def_ptrs)
|
for (const void *def_ptr : def_ptrs)
|
||||||
for (Usr usr1 : ((const QueryFunc::Def *)def_ptr)->vars) {
|
for (Usr usr1 : ((const QueryFunc::Def *)def_ptr)->vars) {
|
||||||
auto it = sym2ds.find(SymbolIdx{usr1, SymbolKind::Var});
|
auto it = sym2ds.find(SymbolIdx{usr1, Kind::Var});
|
||||||
if (it != sym2ds.end() && it->second)
|
if (it != sym2ds.end() && it->second)
|
||||||
ds->children.push_back(std::move(it->second));
|
ds->children.push_back(std::move(it->second));
|
||||||
}
|
}
|
||||||
@ -206,37 +206,36 @@ void MessageHandler::textDocument_documentSymbol(Reader &reader,
|
|||||||
for (const void *def_ptr : def_ptrs) {
|
for (const void *def_ptr : def_ptrs) {
|
||||||
auto *def = (const QueryType::Def *)def_ptr;
|
auto *def = (const QueryType::Def *)def_ptr;
|
||||||
for (Usr usr1 : def->funcs) {
|
for (Usr usr1 : def->funcs) {
|
||||||
auto it = sym2ds.find(SymbolIdx{usr1, SymbolKind::Func});
|
auto it = sym2ds.find(SymbolIdx{usr1, Kind::Func});
|
||||||
if (it != sym2ds.end() && it->second)
|
if (it != sym2ds.end() && it->second)
|
||||||
ds->children.push_back(std::move(it->second));
|
ds->children.push_back(std::move(it->second));
|
||||||
}
|
}
|
||||||
for (Usr usr1 : def->types) {
|
for (Usr usr1 : def->types) {
|
||||||
auto it = sym2ds.find(SymbolIdx{usr1, SymbolKind::Type});
|
auto it = sym2ds.find(SymbolIdx{usr1, Kind::Type});
|
||||||
if (it != sym2ds.end() && it->second)
|
if (it != sym2ds.end() && it->second)
|
||||||
ds->children.push_back(std::move(it->second));
|
ds->children.push_back(std::move(it->second));
|
||||||
}
|
}
|
||||||
for (auto [usr1, _] : def->vars) {
|
for (auto [usr1, _] : def->vars) {
|
||||||
auto it = sym2ds.find(SymbolIdx{usr1, SymbolKind::Var});
|
auto it = sym2ds.find(SymbolIdx{usr1, Kind::Var});
|
||||||
if (it != sym2ds.end() && it->second)
|
if (it != sym2ds.end() && it->second)
|
||||||
ds->children.push_back(std::move(it->second));
|
ds->children.push_back(std::move(it->second));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::vector<std::unique_ptr<lsDocumentSymbol>> result;
|
std::vector<std::unique_ptr<DocumentSymbol>> result;
|
||||||
for (auto &[_, ds] : sym2ds)
|
for (auto &[_, ds] : sym2ds)
|
||||||
if (ds)
|
if (ds)
|
||||||
result.push_back(std::move(ds));
|
result.push_back(std::move(ds));
|
||||||
reply(result);
|
reply(result);
|
||||||
} else {
|
} else {
|
||||||
std::vector<lsSymbolInformation> result;
|
std::vector<SymbolInformation> result;
|
||||||
for (auto [sym, refcnt] : file->symbol2refcnt) {
|
for (auto [sym, refcnt] : file->symbol2refcnt) {
|
||||||
if (refcnt <= 0 || !sym.extent.Valid() ||
|
if (refcnt <= 0 || !sym.extent.Valid() ||
|
||||||
!(param.all || sym.role & Role::Definition))
|
!(param.all || sym.role & Role::Definition))
|
||||||
continue;
|
continue;
|
||||||
if (std::optional<lsSymbolInformation> info =
|
if (std::optional<SymbolInformation> info =
|
||||||
GetSymbolInfo(db, sym, false)) {
|
GetSymbolInfo(db, sym, false)) {
|
||||||
if ((sym.kind == SymbolKind::Type &&
|
if ((sym.kind == Kind::Type && Ignore(db->GetType(sym).AnyDef())) ||
|
||||||
Ignore(db->GetType(sym).AnyDef())) ||
|
(sym.kind == Kind::Var && Ignore(db->GetVar(sym).AnyDef())))
|
||||||
(sym.kind == SymbolKind::Var && Ignore(db->GetVar(sym).AnyDef())))
|
|
||||||
continue;
|
continue;
|
||||||
if (auto loc = GetLsLocation(db, wfiles, sym, file_id)) {
|
if (auto loc = GetLsLocation(db, wfiles, sym, file_id)) {
|
||||||
info->location = *loc;
|
info->location = *loc;
|
||||||
|
@ -30,7 +30,7 @@ void MessageHandler::textDocument_foldingRange(TextDocumentParam ¶m,
|
|||||||
|
|
||||||
for (auto [sym, refcnt] : file->symbol2refcnt)
|
for (auto [sym, refcnt] : file->symbol2refcnt)
|
||||||
if (refcnt > 0 && sym.extent.Valid() &&
|
if (refcnt > 0 && sym.extent.Valid() &&
|
||||||
(sym.kind == SymbolKind::Func || sym.kind == SymbolKind::Type) &&
|
(sym.kind == Kind::Func || sym.kind == Kind::Type) &&
|
||||||
(ls_range = GetLsRange(wfile, sym.extent))) {
|
(ls_range = GetLsRange(wfile, sym.extent))) {
|
||||||
FoldingRange &fold = result.emplace_back();
|
FoldingRange &fold = result.emplace_back();
|
||||||
fold.startLine = ls_range->start.line;
|
fold.startLine = ls_range->start.line;
|
||||||
|
@ -29,9 +29,9 @@ FormatCode(std::string_view code, std::string_view file, tooling::Range Range) {
|
|||||||
File));
|
File));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<lsTextEdit>
|
std::vector<TextEdit> ReplacementsToEdits(std::string_view code,
|
||||||
ReplacementsToEdits(std::string_view code, const tooling::Replacements &Repls) {
|
const tooling::Replacements &Repls) {
|
||||||
std::vector<lsTextEdit> ret;
|
std::vector<TextEdit> ret;
|
||||||
int i = 0, line = 0, col = 0;
|
int i = 0, line = 0, col = 0;
|
||||||
auto move = [&](int p) {
|
auto move = [&](int p) {
|
||||||
for (; i < p; i++)
|
for (; i < p; i++)
|
||||||
@ -62,8 +62,8 @@ void Format(ReplyOnce &reply, WorkingFile *wfile, tooling::Range range) {
|
|||||||
auto result = ReplacementsToEdits(code, *ReplsOrErr);
|
auto result = ReplacementsToEdits(code, *ReplsOrErr);
|
||||||
reply(result);
|
reply(result);
|
||||||
} else {
|
} else {
|
||||||
lsResponseError err;
|
ResponseError err;
|
||||||
err.code = lsErrorCodes::UnknownErrorCode;
|
err.code = ErrorCode::UnknownErrorCode;
|
||||||
err.message = llvm::toString(ReplsOrErr.takeError());
|
err.message = llvm::toString(ReplsOrErr.takeError());
|
||||||
reply.Error(err);
|
reply.Error(err);
|
||||||
}
|
}
|
||||||
|
@ -6,16 +6,16 @@
|
|||||||
|
|
||||||
namespace ccls {
|
namespace ccls {
|
||||||
namespace {
|
namespace {
|
||||||
struct lsMarkedString {
|
struct MarkedString {
|
||||||
std::optional<std::string> language;
|
std::optional<std::string> language;
|
||||||
std::string value;
|
std::string value;
|
||||||
};
|
};
|
||||||
struct Hover {
|
struct Hover {
|
||||||
std::vector<lsMarkedString> contents;
|
std::vector<MarkedString> contents;
|
||||||
std::optional<lsRange> range;
|
std::optional<lsRange> range;
|
||||||
};
|
};
|
||||||
|
|
||||||
void Reflect(Writer &visitor, lsMarkedString &value) {
|
void Reflect(Writer &visitor, MarkedString &value) {
|
||||||
// If there is a language, emit a `{language:string, value:string}` object. If
|
// If there is a language, emit a `{language:string, value:string}` object. If
|
||||||
// not, emit a string.
|
// not, emit a string.
|
||||||
if (value.language) {
|
if (value.language) {
|
||||||
@ -42,10 +42,10 @@ const char *LanguageIdentifier(LanguageId lang) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Returns the hover or detailed name for `sym`, if any.
|
// Returns the hover or detailed name for `sym`, if any.
|
||||||
std::pair<std::optional<lsMarkedString>, std::optional<lsMarkedString>>
|
std::pair<std::optional<MarkedString>, std::optional<MarkedString>>
|
||||||
GetHover(DB *db, LanguageId lang, SymbolRef sym, int file_id) {
|
GetHover(DB *db, LanguageId lang, SymbolRef sym, int file_id) {
|
||||||
const char *comments = nullptr;
|
const char *comments = nullptr;
|
||||||
std::optional<lsMarkedString> ls_comments, hover;
|
std::optional<MarkedString> ls_comments, hover;
|
||||||
WithEntity(db, sym, [&](const auto &entity) {
|
WithEntity(db, sym, [&](const auto &entity) {
|
||||||
std::remove_reference_t<decltype(entity.def[0])> *def = nullptr;
|
std::remove_reference_t<decltype(entity.def[0])> *def = nullptr;
|
||||||
for (auto &d : entity.def) {
|
for (auto &d : entity.def) {
|
||||||
@ -62,7 +62,7 @@ GetHover(DB *db, LanguageId lang, SymbolRef sym, int file_id) {
|
|||||||
comments = def->comments;
|
comments = def->comments;
|
||||||
}
|
}
|
||||||
if (def) {
|
if (def) {
|
||||||
lsMarkedString m;
|
MarkedString m;
|
||||||
m.language = LanguageIdentifier(lang);
|
m.language = LanguageIdentifier(lang);
|
||||||
if (def->hover[0]) {
|
if (def->hover[0]) {
|
||||||
m.value = def->hover;
|
m.value = def->hover;
|
||||||
@ -72,7 +72,7 @@ GetHover(DB *db, LanguageId lang, SymbolRef sym, int file_id) {
|
|||||||
hover = m;
|
hover = m;
|
||||||
}
|
}
|
||||||
if (comments)
|
if (comments)
|
||||||
ls_comments = lsMarkedString{std::nullopt, comments};
|
ls_comments = MarkedString{std::nullopt, comments};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return {hover, ls_comments};
|
return {hover, ls_comments};
|
||||||
|
@ -41,7 +41,7 @@ void MessageHandler::textDocument_references(Reader &reader, ReplyOnce &reply) {
|
|||||||
for (auto &folder : param.folders)
|
for (auto &folder : param.folders)
|
||||||
EnsureEndsInSlash(folder);
|
EnsureEndsInSlash(folder);
|
||||||
std::vector<uint8_t> file_set = db->GetFileSet(param.folders);
|
std::vector<uint8_t> file_set = db->GetFileSet(param.folders);
|
||||||
std::vector<lsLocation> result;
|
std::vector<Location> result;
|
||||||
|
|
||||||
std::unordered_set<Use> seen_uses;
|
std::unordered_set<Use> seen_uses;
|
||||||
int line = param.position.line;
|
int line = param.position.line;
|
||||||
@ -51,12 +51,12 @@ void MessageHandler::textDocument_references(Reader &reader, ReplyOnce &reply) {
|
|||||||
std::unordered_set<Usr> seen;
|
std::unordered_set<Usr> seen;
|
||||||
seen.insert(sym.usr);
|
seen.insert(sym.usr);
|
||||||
std::vector<Usr> stack{sym.usr};
|
std::vector<Usr> stack{sym.usr};
|
||||||
if (sym.kind != SymbolKind::Func)
|
if (sym.kind != Kind::Func)
|
||||||
param.base = false;
|
param.base = false;
|
||||||
while (stack.size()) {
|
while (stack.size()) {
|
||||||
sym.usr = stack.back();
|
sym.usr = stack.back();
|
||||||
stack.pop_back();
|
stack.pop_back();
|
||||||
auto fn = [&](Use use, lsSymbolKind parent_kind) {
|
auto fn = [&](Use use, SymbolKind parent_kind) {
|
||||||
if (file_set[use.file_id] &&
|
if (file_set[use.file_id] &&
|
||||||
Role(use.role & param.role) == param.role &&
|
Role(use.role & param.role) == param.role &&
|
||||||
!(use.role & param.excludeRole) && seen_uses.insert(use).second)
|
!(use.role & param.excludeRole) && seen_uses.insert(use).second)
|
||||||
@ -64,7 +64,7 @@ void MessageHandler::textDocument_references(Reader &reader, ReplyOnce &reply) {
|
|||||||
result.push_back(*loc);
|
result.push_back(*loc);
|
||||||
};
|
};
|
||||||
WithEntity(db, sym, [&](const auto &entity) {
|
WithEntity(db, sym, [&](const auto &entity) {
|
||||||
lsSymbolKind parent_kind = lsSymbolKind::Unknown;
|
SymbolKind parent_kind = SymbolKind::Unknown;
|
||||||
for (auto &def : entity.def)
|
for (auto &def : entity.def)
|
||||||
if (def.spell) {
|
if (def.spell) {
|
||||||
parent_kind = GetSymbolKind(db, sym);
|
parent_kind = GetSymbolKind(db, sym);
|
||||||
@ -108,8 +108,8 @@ void MessageHandler::textDocument_references(Reader &reader, ReplyOnce &reply) {
|
|||||||
for (const IndexInclude &include : file1.def->includes)
|
for (const IndexInclude &include : file1.def->includes)
|
||||||
if (include.resolved_path == path) {
|
if (include.resolved_path == path) {
|
||||||
// Another file |file1| has the same include line.
|
// Another file |file1| has the same include line.
|
||||||
lsLocation &loc = result.emplace_back();
|
Location &loc = result.emplace_back();
|
||||||
loc.uri = lsDocumentUri::FromPath(file1.def->path);
|
loc.uri = DocumentUri::FromPath(file1.def->path);
|
||||||
loc.range.start.line = loc.range.end.line = include.line;
|
loc.range.start.line = loc.range.end.line = include.line;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -6,32 +6,32 @@
|
|||||||
|
|
||||||
namespace ccls {
|
namespace ccls {
|
||||||
namespace {
|
namespace {
|
||||||
lsWorkspaceEdit BuildWorkspaceEdit(DB *db, WorkingFiles *wfiles, SymbolRef sym,
|
WorkspaceEdit BuildWorkspaceEdit(DB *db, WorkingFiles *wfiles, SymbolRef sym,
|
||||||
const std::string &new_text) {
|
const std::string &new_text) {
|
||||||
std::unordered_map<int, lsTextDocumentEdit> path_to_edit;
|
std::unordered_map<int, TextDocumentEdit> path_to_edit;
|
||||||
|
|
||||||
EachOccurrence(db, sym, true, [&](Use use) {
|
EachOccurrence(db, sym, true, [&](Use use) {
|
||||||
std::optional<lsLocation> ls_location = GetLsLocation(db, wfiles, use);
|
std::optional<Location> ls_location = GetLsLocation(db, wfiles, use);
|
||||||
if (!ls_location)
|
if (!ls_location)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int file_id = use.file_id;
|
int file_id = use.file_id;
|
||||||
if (path_to_edit.find(file_id) == path_to_edit.end()) {
|
if (path_to_edit.find(file_id) == path_to_edit.end()) {
|
||||||
path_to_edit[file_id] = lsTextDocumentEdit();
|
path_to_edit[file_id] = TextDocumentEdit();
|
||||||
|
|
||||||
QueryFile &file = db->files[file_id];
|
QueryFile &file = db->files[file_id];
|
||||||
if (!file.def)
|
if (!file.def)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const std::string &path = file.def->path;
|
const std::string &path = file.def->path;
|
||||||
path_to_edit[file_id].textDocument.uri = lsDocumentUri::FromPath(path);
|
path_to_edit[file_id].textDocument.uri = DocumentUri::FromPath(path);
|
||||||
|
|
||||||
WorkingFile *working_file = wfiles->GetFileByFilename(path);
|
WorkingFile *working_file = wfiles->GetFileByFilename(path);
|
||||||
if (working_file)
|
if (working_file)
|
||||||
path_to_edit[file_id].textDocument.version = working_file->version;
|
path_to_edit[file_id].textDocument.version = working_file->version;
|
||||||
}
|
}
|
||||||
|
|
||||||
lsTextEdit edit;
|
TextEdit edit;
|
||||||
edit.range = ls_location->range;
|
edit.range = ls_location->range;
|
||||||
edit.newText = new_text;
|
edit.newText = new_text;
|
||||||
|
|
||||||
@ -41,7 +41,7 @@ lsWorkspaceEdit BuildWorkspaceEdit(DB *db, WorkingFiles *wfiles, SymbolRef sym,
|
|||||||
edits.push_back(edit);
|
edits.push_back(edit);
|
||||||
});
|
});
|
||||||
|
|
||||||
lsWorkspaceEdit edit;
|
WorkspaceEdit edit;
|
||||||
for (const auto &changes : path_to_edit)
|
for (const auto &changes : path_to_edit)
|
||||||
edit.documentChanges.push_back(changes.second);
|
edit.documentChanges.push_back(changes.second);
|
||||||
return edit;
|
return edit;
|
||||||
@ -55,7 +55,7 @@ void MessageHandler::textDocument_rename(RenameParam ¶m, ReplyOnce &reply) {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
WorkingFile *wfile = wfiles->GetFileByFilename(file->def->path);
|
WorkingFile *wfile = wfiles->GetFileByFilename(file->def->path);
|
||||||
lsWorkspaceEdit result;
|
WorkspaceEdit result;
|
||||||
for (SymbolRef sym : FindSymbolsAtLocation(wfile, file, param.position)) {
|
for (SymbolRef sym : FindSymbolsAtLocation(wfile, file, param.position)) {
|
||||||
result = BuildWorkspaceEdit(db, wfiles, sym, param.newName);
|
result = BuildWorkspaceEdit(db, wfiles, sym, param.newName);
|
||||||
break;
|
break;
|
||||||
|
@ -19,14 +19,14 @@ struct SignatureInformation {
|
|||||||
std::optional<std::string> documentation;
|
std::optional<std::string> documentation;
|
||||||
std::vector<ParameterInformation> parameters;
|
std::vector<ParameterInformation> parameters;
|
||||||
};
|
};
|
||||||
struct lsSignatureHelp {
|
struct SignatureHelp {
|
||||||
std::vector<SignatureInformation> signatures;
|
std::vector<SignatureInformation> signatures;
|
||||||
int activeSignature = 0;
|
int activeSignature = 0;
|
||||||
int activeParameter = 0;
|
int activeParameter = 0;
|
||||||
};
|
};
|
||||||
MAKE_REFLECT_STRUCT(ParameterInformation, label);
|
MAKE_REFLECT_STRUCT(ParameterInformation, label);
|
||||||
MAKE_REFLECT_STRUCT(SignatureInformation, label, documentation, parameters);
|
MAKE_REFLECT_STRUCT(SignatureInformation, label, documentation, parameters);
|
||||||
MAKE_REFLECT_STRUCT(lsSignatureHelp, signatures, activeSignature,
|
MAKE_REFLECT_STRUCT(SignatureHelp, signatures, activeSignature,
|
||||||
activeParameter);
|
activeParameter);
|
||||||
|
|
||||||
std::string BuildOptional(const CodeCompletionString &CCS,
|
std::string BuildOptional(const CodeCompletionString &CCS,
|
||||||
@ -64,7 +64,7 @@ class SignatureHelpConsumer : public CodeCompleteConsumer {
|
|||||||
CodeCompletionTUInfo CCTUInfo;
|
CodeCompletionTUInfo CCTUInfo;
|
||||||
public:
|
public:
|
||||||
bool from_cache;
|
bool from_cache;
|
||||||
lsSignatureHelp ls_sighelp;
|
SignatureHelp ls_sighelp;
|
||||||
SignatureHelpConsumer(const clang::CodeCompleteOptions &CCOpts,
|
SignatureHelpConsumer(const clang::CodeCompleteOptions &CCOpts,
|
||||||
bool from_cache)
|
bool from_cache)
|
||||||
: CodeCompleteConsumer(CCOpts, false),
|
: CodeCompleteConsumer(CCOpts, false),
|
||||||
@ -140,7 +140,7 @@ public:
|
|||||||
|
|
||||||
void MessageHandler::textDocument_signatureHelp(
|
void MessageHandler::textDocument_signatureHelp(
|
||||||
TextDocumentPositionParam ¶m, ReplyOnce &reply) {
|
TextDocumentPositionParam ¶m, ReplyOnce &reply) {
|
||||||
static CompleteConsumerCache<lsSignatureHelp> cache;
|
static CompleteConsumerCache<SignatureHelp> cache;
|
||||||
|
|
||||||
std::string path = param.textDocument.uri.GetPath();
|
std::string path = param.textDocument.uri.GetPath();
|
||||||
lsPosition begin_pos = param.position;
|
lsPosition begin_pos = param.position;
|
||||||
|
@ -18,12 +18,12 @@
|
|||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
|
||||||
namespace ccls {
|
namespace ccls {
|
||||||
MAKE_REFLECT_STRUCT(lsSymbolInformation, name, kind, location, containerName);
|
MAKE_REFLECT_STRUCT(SymbolInformation, name, kind, location, containerName);
|
||||||
|
|
||||||
void MessageHandler::workspace_didChangeConfiguration(EmptyParam &) {
|
void MessageHandler::workspace_didChangeConfiguration(EmptyParam &) {
|
||||||
for (const std::string &folder : g_config->workspaceFolders)
|
for (const std::string &folder : g_config->workspaceFolders)
|
||||||
project->Load(folder);
|
project->Load(folder);
|
||||||
project->Index(wfiles, lsRequestId());
|
project->Index(wfiles, RequestId());
|
||||||
|
|
||||||
clang_complete->FlushAllSessions();
|
clang_complete->FlushAllSessions();
|
||||||
};
|
};
|
||||||
@ -77,7 +77,7 @@ void MessageHandler::workspace_didChangeWorkspaceFolders(
|
|||||||
project->Load(root);
|
project->Load(root);
|
||||||
}
|
}
|
||||||
|
|
||||||
project->Index(wfiles, lsRequestId());
|
project->Index(wfiles, RequestId());
|
||||||
|
|
||||||
clang_complete->FlushAllSessions();
|
clang_complete->FlushAllSessions();
|
||||||
}
|
}
|
||||||
@ -87,8 +87,8 @@ namespace {
|
|||||||
bool AddSymbol(
|
bool AddSymbol(
|
||||||
DB *db, WorkingFiles *wfiles, const std::vector<uint8_t> &file_set,
|
DB *db, WorkingFiles *wfiles, const std::vector<uint8_t> &file_set,
|
||||||
SymbolIdx sym, bool use_detailed,
|
SymbolIdx sym, bool use_detailed,
|
||||||
std::vector<std::tuple<lsSymbolInformation, int, SymbolIdx>> *result) {
|
std::vector<std::tuple<SymbolInformation, int, SymbolIdx>> *result) {
|
||||||
std::optional<lsSymbolInformation> info = GetSymbolInfo(db, sym, true);
|
std::optional<SymbolInformation> info = GetSymbolInfo(db, sym, true);
|
||||||
if (!info)
|
if (!info)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -113,7 +113,7 @@ bool AddSymbol(
|
|||||||
if (!in_folder)
|
if (!in_folder)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
std::optional<lsLocation> ls_location = GetLsLocation(db, wfiles, *dr);
|
std::optional<Location> ls_location = GetLsLocation(db, wfiles, *dr);
|
||||||
if (!ls_location)
|
if (!ls_location)
|
||||||
return false;
|
return false;
|
||||||
info->location = *ls_location;
|
info->location = *ls_location;
|
||||||
@ -124,14 +124,14 @@ bool AddSymbol(
|
|||||||
|
|
||||||
void MessageHandler::workspace_symbol(WorkspaceSymbolParam ¶m,
|
void MessageHandler::workspace_symbol(WorkspaceSymbolParam ¶m,
|
||||||
ReplyOnce &reply) {
|
ReplyOnce &reply) {
|
||||||
std::vector<lsSymbolInformation> result;
|
std::vector<SymbolInformation> result;
|
||||||
const std::string &query = param.query;
|
const std::string &query = param.query;
|
||||||
for (auto &folder : param.folders)
|
for (auto &folder : param.folders)
|
||||||
EnsureEndsInSlash(folder);
|
EnsureEndsInSlash(folder);
|
||||||
std::vector<uint8_t> file_set = db->GetFileSet(param.folders);
|
std::vector<uint8_t> file_set = db->GetFileSet(param.folders);
|
||||||
|
|
||||||
// {symbol info, matching detailed_name or short_name, index}
|
// {symbol info, matching detailed_name or short_name, index}
|
||||||
std::vector<std::tuple<lsSymbolInformation, int, SymbolIdx>> cands;
|
std::vector<std::tuple<SymbolInformation, int, SymbolIdx>> cands;
|
||||||
bool sensitive = g_config->workspaceSymbol.caseSensitivity;
|
bool sensitive = g_config->workspaceSymbol.caseSensitivity;
|
||||||
|
|
||||||
// Find subsequence matches.
|
// Find subsequence matches.
|
||||||
@ -151,14 +151,13 @@ void MessageHandler::workspace_symbol(WorkspaceSymbolParam ¶m,
|
|||||||
cands.size() >= g_config->workspaceSymbol.maxNum;
|
cands.size() >= g_config->workspaceSymbol.maxNum;
|
||||||
};
|
};
|
||||||
for (auto &func : db->funcs)
|
for (auto &func : db->funcs)
|
||||||
if (Add({func.usr, SymbolKind::Func}))
|
if (Add({func.usr, Kind::Func}))
|
||||||
goto done_add;
|
goto done_add;
|
||||||
for (auto &type : db->types)
|
for (auto &type : db->types)
|
||||||
if (Add({type.usr, SymbolKind::Type}))
|
if (Add({type.usr, Kind::Type}))
|
||||||
goto done_add;
|
goto done_add;
|
||||||
for (auto &var : db->vars)
|
for (auto &var : db->vars)
|
||||||
if (var.def.size() && !var.def[0].is_local() &&
|
if (var.def.size() && !var.def[0].is_local() && Add({var.usr, Kind::Var}))
|
||||||
Add({var.usr, SymbolKind::Var}))
|
|
||||||
goto done_add;
|
goto done_add;
|
||||||
done_add:
|
done_add:
|
||||||
|
|
||||||
|
@ -33,6 +33,14 @@ using namespace llvm;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace ccls {
|
namespace ccls {
|
||||||
|
namespace {
|
||||||
|
struct PublishDiagnosticParam {
|
||||||
|
DocumentUri uri;
|
||||||
|
std::vector<Diagnostic> diagnostics;
|
||||||
|
};
|
||||||
|
MAKE_REFLECT_STRUCT(PublishDiagnosticParam, uri, diagnostics);
|
||||||
|
} // namespace
|
||||||
|
|
||||||
void VFS::Clear() {
|
void VFS::Clear() {
|
||||||
std::lock_guard lock(mutex);
|
std::lock_guard lock(mutex);
|
||||||
state.clear();
|
state.clear();
|
||||||
@ -69,7 +77,7 @@ struct Index_Request {
|
|||||||
std::string path;
|
std::string path;
|
||||||
std::vector<const char *> args;
|
std::vector<const char *> args;
|
||||||
IndexMode mode;
|
IndexMode mode;
|
||||||
lsRequestId id;
|
RequestId id;
|
||||||
int64_t ts = tick++;
|
int64_t ts = tick++;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -291,8 +299,8 @@ bool Indexer_Parse(CompletionManager *completion, WorkingFiles *wfiles,
|
|||||||
|
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
if (request.id.Valid()) {
|
if (request.id.Valid()) {
|
||||||
lsResponseError err;
|
ResponseError err;
|
||||||
err.code = lsErrorCodes::InternalError;
|
err.code = ErrorCode::InternalError;
|
||||||
err.message = "failed to index " + path_to_index;
|
err.message = "failed to index " + path_to_index;
|
||||||
pipeline::ReplyError(request.id, err);
|
pipeline::ReplyError(request.id, err);
|
||||||
}
|
}
|
||||||
@ -441,7 +449,7 @@ void LaunchStdin() {
|
|||||||
if (!reader.HasMember("jsonrpc") ||
|
if (!reader.HasMember("jsonrpc") ||
|
||||||
std::string(reader["jsonrpc"]->GetString()) != "2.0")
|
std::string(reader["jsonrpc"]->GetString()) != "2.0")
|
||||||
return;
|
return;
|
||||||
lsRequestId id;
|
RequestId id;
|
||||||
std::string method;
|
std::string method;
|
||||||
ReflectMember(reader, "id", id);
|
ReflectMember(reader, "id", id);
|
||||||
ReflectMember(reader, "method", method);
|
ReflectMember(reader, "method", method);
|
||||||
@ -479,16 +487,16 @@ void MainLoop() {
|
|||||||
|
|
||||||
CompletionManager clang_complete(
|
CompletionManager clang_complete(
|
||||||
&project, &wfiles,
|
&project, &wfiles,
|
||||||
[&](std::string path, std::vector<lsDiagnostic> diagnostics) {
|
[&](std::string path, std::vector<Diagnostic> diagnostics) {
|
||||||
lsPublishDiagnosticsParams params;
|
PublishDiagnosticParam params;
|
||||||
params.uri = lsDocumentUri::FromPath(path);
|
params.uri = DocumentUri::FromPath(path);
|
||||||
params.diagnostics = diagnostics;
|
params.diagnostics = diagnostics;
|
||||||
Notify("textDocument/publishDiagnostics", params);
|
Notify("textDocument/publishDiagnostics", params);
|
||||||
},
|
},
|
||||||
[](lsRequestId id) {
|
[](RequestId id) {
|
||||||
if (id.Valid()) {
|
if (id.Valid()) {
|
||||||
lsResponseError err;
|
ResponseError err;
|
||||||
err.code = lsErrorCodes::InternalError;
|
err.code = ErrorCode::InternalError;
|
||||||
err.message = "drop older completion request";
|
err.message = "drop older completion request";
|
||||||
ReplyError(id, err);
|
ReplyError(id, err);
|
||||||
}
|
}
|
||||||
@ -572,7 +580,7 @@ void Standalone(const std::string &root) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Index(const std::string &path, const std::vector<const char *> &args,
|
void Index(const std::string &path, const std::vector<const char *> &args,
|
||||||
IndexMode mode, lsRequestId id) {
|
IndexMode mode, RequestId id) {
|
||||||
pending_index_requests++;
|
pending_index_requests++;
|
||||||
index_request->PushBack({path, args, mode, id}, mode != IndexMode::NonInteractive);
|
index_request->PushBack({path, args, mode, id}, mode != IndexMode::NonInteractive);
|
||||||
}
|
}
|
||||||
@ -603,7 +611,7 @@ void Notify(const char *method, const std::function<void(Writer &)> &fn) {
|
|||||||
for_stdout->PushBack(output.GetString());
|
for_stdout->PushBack(output.GetString());
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Reply(lsRequestId id, const char *key,
|
static void Reply(RequestId id, const char *key,
|
||||||
const std::function<void(Writer &)> &fn) {
|
const std::function<void(Writer &)> &fn) {
|
||||||
rapidjson::StringBuffer output;
|
rapidjson::StringBuffer output;
|
||||||
rapidjson::Writer<rapidjson::StringBuffer> w(output);
|
rapidjson::Writer<rapidjson::StringBuffer> w(output);
|
||||||
@ -612,13 +620,13 @@ static void Reply(lsRequestId id, const char *key,
|
|||||||
w.String("2.0");
|
w.String("2.0");
|
||||||
w.Key("id");
|
w.Key("id");
|
||||||
switch (id.type) {
|
switch (id.type) {
|
||||||
case lsRequestId::kNone:
|
case RequestId::kNone:
|
||||||
w.Null();
|
w.Null();
|
||||||
break;
|
break;
|
||||||
case lsRequestId::kInt:
|
case RequestId::kInt:
|
||||||
w.Int(id.value);
|
w.Int(id.value);
|
||||||
break;
|
break;
|
||||||
case lsRequestId::kString:
|
case RequestId::kString:
|
||||||
auto s = std::to_string(id.value);
|
auto s = std::to_string(id.value);
|
||||||
w.String(s.c_str(), s.length());
|
w.String(s.c_str(), s.length());
|
||||||
break;
|
break;
|
||||||
@ -630,11 +638,11 @@ static void Reply(lsRequestId id, const char *key,
|
|||||||
for_stdout->PushBack(output.GetString());
|
for_stdout->PushBack(output.GetString());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Reply(lsRequestId id, const std::function<void(Writer &)> &fn) {
|
void Reply(RequestId id, const std::function<void(Writer &)> &fn) {
|
||||||
Reply(id, "result", fn);
|
Reply(id, "result", fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReplyError(lsRequestId id, const std::function<void(Writer &)> &fn) {
|
void ReplyError(RequestId id, const std::function<void(Writer &)> &fn) {
|
||||||
Reply(id, "error", fn);
|
Reply(id, "error", fn);
|
||||||
}
|
}
|
||||||
} // namespace pipeline
|
} // namespace pipeline
|
||||||
|
@ -50,7 +50,7 @@ void MainLoop();
|
|||||||
void Standalone(const std::string &root);
|
void Standalone(const std::string &root);
|
||||||
|
|
||||||
void Index(const std::string &path, const std::vector<const char *> &args,
|
void Index(const std::string &path, const std::vector<const char *> &args,
|
||||||
IndexMode mode, lsRequestId id = {});
|
IndexMode mode, RequestId id = {});
|
||||||
|
|
||||||
std::optional<std::string> LoadIndexedContent(const std::string& path);
|
std::optional<std::string> LoadIndexedContent(const std::string& path);
|
||||||
|
|
||||||
@ -59,10 +59,10 @@ template <typename T> void Notify(const char *method, T &result) {
|
|||||||
Notify(method, [&](Writer &w) { Reflect(w, result); });
|
Notify(method, [&](Writer &w) { Reflect(w, result); });
|
||||||
}
|
}
|
||||||
|
|
||||||
void Reply(lsRequestId id, const std::function<void(Writer &)> &fn);
|
void Reply(RequestId id, const std::function<void(Writer &)> &fn);
|
||||||
|
|
||||||
void ReplyError(lsRequestId id, const std::function<void(Writer &)> &fn);
|
void ReplyError(RequestId id, const std::function<void(Writer &)> &fn);
|
||||||
template <typename T> void ReplyError(lsRequestId id, T &result) {
|
template <typename T> void ReplyError(RequestId id, T &result) {
|
||||||
ReplyError(id, [&](Writer &w) { Reflect(w, result); });
|
ReplyError(id, [&](Writer &w) { Reflect(w, result); });
|
||||||
}
|
}
|
||||||
} // namespace pipeline
|
} // namespace pipeline
|
||||||
|
@ -451,7 +451,7 @@ Project::Entry Project::FindEntry(const std::string &path,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Project::Index(WorkingFiles *wfiles, lsRequestId id) {
|
void Project::Index(WorkingFiles *wfiles, RequestId id) {
|
||||||
auto &gi = g_config->index;
|
auto &gi = g_config->index;
|
||||||
GroupMatch match(gi.whitelist, gi.blacklist),
|
GroupMatch match(gi.whitelist, gi.blacklist),
|
||||||
match_i(gi.initialWhitelist, gi.initialBlacklist);
|
match_i(gi.initialWhitelist, gi.initialBlacklist);
|
||||||
|
@ -63,6 +63,6 @@ struct Project {
|
|||||||
void SetArgsForFile(const std::vector<const char *> &args,
|
void SetArgsForFile(const std::vector<const char *> &args,
|
||||||
const std::string &path);
|
const std::string &path);
|
||||||
|
|
||||||
void Index(WorkingFiles *wfiles, lsRequestId id);
|
void Index(WorkingFiles *wfiles, RequestId id);
|
||||||
};
|
};
|
||||||
} // namespace ccls
|
} // namespace ccls
|
||||||
|
62
src/query.cc
62
src/query.cc
@ -146,10 +146,10 @@ void DB::clear() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename Def>
|
template <typename Def>
|
||||||
void DB::RemoveUsrs(SymbolKind kind, int file_id,
|
void DB::RemoveUsrs(Kind kind, int file_id,
|
||||||
const std::vector<std::pair<Usr, Def>> &to_remove) {
|
const std::vector<std::pair<Usr, Def>> &to_remove) {
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
case SymbolKind::Func: {
|
case Kind::Func: {
|
||||||
for (auto &[usr, _] : to_remove) {
|
for (auto &[usr, _] : to_remove) {
|
||||||
// FIXME
|
// FIXME
|
||||||
if (!HasFunc(usr))
|
if (!HasFunc(usr))
|
||||||
@ -163,7 +163,7 @@ void DB::RemoveUsrs(SymbolKind kind, int file_id,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SymbolKind::Type: {
|
case Kind::Type: {
|
||||||
for (auto &[usr, _] : to_remove) {
|
for (auto &[usr, _] : to_remove) {
|
||||||
// FIXME
|
// FIXME
|
||||||
if (!HasType(usr))
|
if (!HasType(usr))
|
||||||
@ -177,7 +177,7 @@ void DB::RemoveUsrs(SymbolKind kind, int file_id,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SymbolKind::Var: {
|
case Kind::Var: {
|
||||||
for (auto &[usr, _] : to_remove) {
|
for (auto &[usr, _] : to_remove) {
|
||||||
// FIXME
|
// FIXME
|
||||||
if (!HasVar(usr))
|
if (!HasVar(usr))
|
||||||
@ -220,8 +220,8 @@ void DB::ApplyIndexUpdate(IndexUpdate *u) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// References (Use &use) in this function are important to update file_id.
|
// References (Use &use) in this function are important to update file_id.
|
||||||
auto Ref = [&](std::unordered_map<int, int> &lid2fid, Usr usr,
|
auto Ref = [&](std::unordered_map<int, int> &lid2fid, Usr usr, Kind kind,
|
||||||
SymbolKind kind, Use &use, int delta) {
|
Use &use, int delta) {
|
||||||
use.file_id =
|
use.file_id =
|
||||||
use.file_id == -1 ? u->file_id : lid2fid.find(use.file_id)->second;
|
use.file_id == -1 ? u->file_id : lid2fid.find(use.file_id)->second;
|
||||||
ExtentRef sym{{use.range, usr, kind, use.role}};
|
ExtentRef sym{{use.range, usr, kind, use.role}};
|
||||||
@ -231,8 +231,8 @@ void DB::ApplyIndexUpdate(IndexUpdate *u) {
|
|||||||
if (!v)
|
if (!v)
|
||||||
files[use.file_id].symbol2refcnt.erase(sym);
|
files[use.file_id].symbol2refcnt.erase(sym);
|
||||||
};
|
};
|
||||||
auto RefDecl = [&](std::unordered_map<int, int> &lid2fid, Usr usr,
|
auto RefDecl = [&](std::unordered_map<int, int> &lid2fid, Usr usr, Kind kind,
|
||||||
SymbolKind kind, DeclRef &dr, int delta) {
|
DeclRef &dr, int delta) {
|
||||||
dr.file_id =
|
dr.file_id =
|
||||||
dr.file_id == -1 ? u->file_id : lid2fid.find(dr.file_id)->second;
|
dr.file_id == -1 ? u->file_id : lid2fid.find(dr.file_id)->second;
|
||||||
ExtentRef sym{{dr.range, usr, kind, dr.role}, dr.extent};
|
ExtentRef sym{{dr.range, usr, kind, dr.role}, dr.extent};
|
||||||
@ -244,7 +244,7 @@ void DB::ApplyIndexUpdate(IndexUpdate *u) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
auto UpdateUses =
|
auto UpdateUses =
|
||||||
[&](Usr usr, SymbolKind kind,
|
[&](Usr usr, Kind kind,
|
||||||
llvm::DenseMap<Usr, int, DenseMapInfoForUsr> &entity_usr,
|
llvm::DenseMap<Usr, int, DenseMapInfoForUsr> &entity_usr,
|
||||||
auto &entities, auto &p, bool hint_implicit) {
|
auto &entities, auto &p, bool hint_implicit) {
|
||||||
auto R = entity_usr.try_emplace(usr, entity_usr.size());
|
auto R = entity_usr.try_emplace(usr, entity_usr.size());
|
||||||
@ -291,19 +291,19 @@ void DB::ApplyIndexUpdate(IndexUpdate *u) {
|
|||||||
}
|
}
|
||||||
for (auto &[usr, def] : u->funcs_removed)
|
for (auto &[usr, def] : u->funcs_removed)
|
||||||
if (def.spell)
|
if (def.spell)
|
||||||
RefDecl(prev_lid2file_id, usr, SymbolKind::Func, *def.spell, -1);
|
RefDecl(prev_lid2file_id, usr, Kind::Func, *def.spell, -1);
|
||||||
RemoveUsrs(SymbolKind::Func, u->file_id, u->funcs_removed);
|
RemoveUsrs(Kind::Func, u->file_id, u->funcs_removed);
|
||||||
Update(lid2file_id, u->file_id, std::move(u->funcs_def_update));
|
Update(lid2file_id, u->file_id, std::move(u->funcs_def_update));
|
||||||
for (auto &[usr, del_add]: u->funcs_declarations) {
|
for (auto &[usr, del_add]: u->funcs_declarations) {
|
||||||
for (DeclRef &dr : del_add.first)
|
for (DeclRef &dr : del_add.first)
|
||||||
RefDecl(prev_lid2file_id, usr, SymbolKind::Func, dr, -1);
|
RefDecl(prev_lid2file_id, usr, Kind::Func, dr, -1);
|
||||||
for (DeclRef &dr : del_add.second)
|
for (DeclRef &dr : del_add.second)
|
||||||
RefDecl(lid2file_id, usr, SymbolKind::Func, dr, 1);
|
RefDecl(lid2file_id, usr, Kind::Func, dr, 1);
|
||||||
}
|
}
|
||||||
REMOVE_ADD(func, declarations);
|
REMOVE_ADD(func, declarations);
|
||||||
REMOVE_ADD(func, derived);
|
REMOVE_ADD(func, derived);
|
||||||
for (auto &[usr, p] : u->funcs_uses)
|
for (auto &[usr, p] : u->funcs_uses)
|
||||||
UpdateUses(usr, SymbolKind::Func, func_usr, funcs, p, true);
|
UpdateUses(usr, Kind::Func, func_usr, funcs, p, true);
|
||||||
|
|
||||||
if ((t = types.size() + u->types_hint) > types.capacity()) {
|
if ((t = types.size() + u->types_hint) > types.capacity()) {
|
||||||
t = size_t(t * grow);
|
t = size_t(t * grow);
|
||||||
@ -312,20 +312,20 @@ void DB::ApplyIndexUpdate(IndexUpdate *u) {
|
|||||||
}
|
}
|
||||||
for (auto &[usr, def] : u->types_removed)
|
for (auto &[usr, def] : u->types_removed)
|
||||||
if (def.spell)
|
if (def.spell)
|
||||||
RefDecl(prev_lid2file_id, usr, SymbolKind::Type, *def.spell, -1);
|
RefDecl(prev_lid2file_id, usr, Kind::Type, *def.spell, -1);
|
||||||
RemoveUsrs(SymbolKind::Type, u->file_id, u->types_removed);
|
RemoveUsrs(Kind::Type, u->file_id, u->types_removed);
|
||||||
Update(lid2file_id, u->file_id, std::move(u->types_def_update));
|
Update(lid2file_id, u->file_id, std::move(u->types_def_update));
|
||||||
for (auto &[usr, del_add]: u->types_declarations) {
|
for (auto &[usr, del_add]: u->types_declarations) {
|
||||||
for (DeclRef &dr : del_add.first)
|
for (DeclRef &dr : del_add.first)
|
||||||
RefDecl(prev_lid2file_id, usr, SymbolKind::Type, dr, -1);
|
RefDecl(prev_lid2file_id, usr, Kind::Type, dr, -1);
|
||||||
for (DeclRef &dr : del_add.second)
|
for (DeclRef &dr : del_add.second)
|
||||||
RefDecl(lid2file_id, usr, SymbolKind::Type, dr, 1);
|
RefDecl(lid2file_id, usr, Kind::Type, dr, 1);
|
||||||
}
|
}
|
||||||
REMOVE_ADD(type, declarations);
|
REMOVE_ADD(type, declarations);
|
||||||
REMOVE_ADD(type, derived);
|
REMOVE_ADD(type, derived);
|
||||||
REMOVE_ADD(type, instances);
|
REMOVE_ADD(type, instances);
|
||||||
for (auto &[usr, p] : u->types_uses)
|
for (auto &[usr, p] : u->types_uses)
|
||||||
UpdateUses(usr, SymbolKind::Type, type_usr, types, p, false);
|
UpdateUses(usr, Kind::Type, type_usr, types, p, false);
|
||||||
|
|
||||||
if ((t = vars.size() + u->vars_hint) > vars.capacity()) {
|
if ((t = vars.size() + u->vars_hint) > vars.capacity()) {
|
||||||
t = size_t(t * grow);
|
t = size_t(t * grow);
|
||||||
@ -334,18 +334,18 @@ void DB::ApplyIndexUpdate(IndexUpdate *u) {
|
|||||||
}
|
}
|
||||||
for (auto &[usr, def] : u->vars_removed)
|
for (auto &[usr, def] : u->vars_removed)
|
||||||
if (def.spell)
|
if (def.spell)
|
||||||
RefDecl(prev_lid2file_id, usr, SymbolKind::Var, *def.spell, -1);
|
RefDecl(prev_lid2file_id, usr, Kind::Var, *def.spell, -1);
|
||||||
RemoveUsrs(SymbolKind::Var, u->file_id, u->vars_removed);
|
RemoveUsrs(Kind::Var, u->file_id, u->vars_removed);
|
||||||
Update(lid2file_id, u->file_id, std::move(u->vars_def_update));
|
Update(lid2file_id, u->file_id, std::move(u->vars_def_update));
|
||||||
for (auto &[usr, del_add]: u->vars_declarations) {
|
for (auto &[usr, del_add]: u->vars_declarations) {
|
||||||
for (DeclRef &dr : del_add.first)
|
for (DeclRef &dr : del_add.first)
|
||||||
RefDecl(prev_lid2file_id, usr, SymbolKind::Var, dr, -1);
|
RefDecl(prev_lid2file_id, usr, Kind::Var, dr, -1);
|
||||||
for (DeclRef &dr : del_add.second)
|
for (DeclRef &dr : del_add.second)
|
||||||
RefDecl(lid2file_id, usr, SymbolKind::Var, dr, 1);
|
RefDecl(lid2file_id, usr, Kind::Var, dr, 1);
|
||||||
}
|
}
|
||||||
REMOVE_ADD(var, declarations);
|
REMOVE_ADD(var, declarations);
|
||||||
for (auto &[usr, p] : u->vars_uses)
|
for (auto &[usr, p] : u->vars_uses)
|
||||||
UpdateUses(usr, SymbolKind::Var, var_usr, vars, p, false);
|
UpdateUses(usr, Kind::Var, var_usr, vars, p, false);
|
||||||
|
|
||||||
#undef REMOVE_ADD
|
#undef REMOVE_ADD
|
||||||
}
|
}
|
||||||
@ -374,7 +374,7 @@ void DB::Update(const Lid2file_id &lid2file_id, int file_id,
|
|||||||
if (def.spell) {
|
if (def.spell) {
|
||||||
AssignFileId(lid2file_id, file_id, *def.spell);
|
AssignFileId(lid2file_id, file_id, *def.spell);
|
||||||
files[def.spell->file_id].symbol2refcnt[{
|
files[def.spell->file_id].symbol2refcnt[{
|
||||||
{def.spell->range, u.first, SymbolKind::Func, def.spell->role},
|
{def.spell->range, u.first, Kind::Func, def.spell->role},
|
||||||
def.spell->extent}]++;
|
def.spell->extent}]++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -397,7 +397,7 @@ void DB::Update(const Lid2file_id &lid2file_id, int file_id,
|
|||||||
if (def.spell) {
|
if (def.spell) {
|
||||||
AssignFileId(lid2file_id, file_id, *def.spell);
|
AssignFileId(lid2file_id, file_id, *def.spell);
|
||||||
files[def.spell->file_id].symbol2refcnt[{
|
files[def.spell->file_id].symbol2refcnt[{
|
||||||
{def.spell->range, u.first, SymbolKind::Type, def.spell->role},
|
{def.spell->range, u.first, Kind::Type, def.spell->role},
|
||||||
def.spell->extent}]++;
|
def.spell->extent}]++;
|
||||||
}
|
}
|
||||||
auto R = type_usr.try_emplace({u.first}, type_usr.size());
|
auto R = type_usr.try_emplace({u.first}, type_usr.size());
|
||||||
@ -419,7 +419,7 @@ void DB::Update(const Lid2file_id &lid2file_id, int file_id,
|
|||||||
if (def.spell) {
|
if (def.spell) {
|
||||||
AssignFileId(lid2file_id, file_id, *def.spell);
|
AssignFileId(lid2file_id, file_id, *def.spell);
|
||||||
files[def.spell->file_id].symbol2refcnt[{
|
files[def.spell->file_id].symbol2refcnt[{
|
||||||
{def.spell->range, u.first, SymbolKind::Var, def.spell->role},
|
{def.spell->range, u.first, Kind::Var, def.spell->role},
|
||||||
def.spell->extent}]++;
|
def.spell->extent}]++;
|
||||||
}
|
}
|
||||||
auto R = var_usr.try_emplace({u.first}, var_usr.size());
|
auto R = var_usr.try_emplace({u.first}, var_usr.size());
|
||||||
@ -437,19 +437,19 @@ std::string_view DB::GetSymbolName(SymbolIdx sym, bool qualified) {
|
|||||||
switch (sym.kind) {
|
switch (sym.kind) {
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
case SymbolKind::File:
|
case Kind::File:
|
||||||
if (files[usr].def)
|
if (files[usr].def)
|
||||||
return files[usr].def->path;
|
return files[usr].def->path;
|
||||||
break;
|
break;
|
||||||
case SymbolKind::Func:
|
case Kind::Func:
|
||||||
if (const auto *def = Func(usr).AnyDef())
|
if (const auto *def = Func(usr).AnyDef())
|
||||||
return def->Name(qualified);
|
return def->Name(qualified);
|
||||||
break;
|
break;
|
||||||
case SymbolKind::Type:
|
case Kind::Type:
|
||||||
if (const auto *def = Type(usr).AnyDef())
|
if (const auto *def = Type(usr).AnyDef())
|
||||||
return def->Name(qualified);
|
return def->Name(qualified);
|
||||||
break;
|
break;
|
||||||
case SymbolKind::Var:
|
case Kind::Var:
|
||||||
if (const auto *def = Var(usr).AnyDef())
|
if (const auto *def = Var(usr).AnyDef())
|
||||||
return def->Name(qualified);
|
return def->Name(qualified);
|
||||||
break;
|
break;
|
||||||
|
@ -157,7 +157,7 @@ struct DB {
|
|||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
template <typename Def>
|
template <typename Def>
|
||||||
void RemoveUsrs(SymbolKind kind, int file_id,
|
void RemoveUsrs(Kind kind, int file_id,
|
||||||
const std::vector<std::pair<Usr, Def>> &to_remove);
|
const std::vector<std::pair<Usr, Def>> &to_remove);
|
||||||
// Insert the contents of |update| into |db|.
|
// Insert the contents of |update| into |db|.
|
||||||
void ApplyIndexUpdate(IndexUpdate *update);
|
void ApplyIndexUpdate(IndexUpdate *update);
|
||||||
|
@ -64,13 +64,13 @@ std::vector<Use> GetVarDeclarations(DB *db, const std::vector<Usr> &usrs,
|
|||||||
if (def.spell) {
|
if (def.spell) {
|
||||||
has_def = true;
|
has_def = true;
|
||||||
// See messages/ccls_vars.cc
|
// See messages/ccls_vars.cc
|
||||||
if (def.kind == lsSymbolKind::Field) {
|
if (def.kind == SymbolKind::Field) {
|
||||||
if (!(kind & 1))
|
if (!(kind & 1))
|
||||||
break;
|
break;
|
||||||
} else if (def.kind == lsSymbolKind::Variable) {
|
} else if (def.kind == SymbolKind::Variable) {
|
||||||
if (!(kind & 2))
|
if (!(kind & 2))
|
||||||
break;
|
break;
|
||||||
} else if (def.kind == lsSymbolKind::Parameter) {
|
} else if (def.kind == SymbolKind::Parameter) {
|
||||||
if (!(kind & 4))
|
if (!(kind & 4))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -86,11 +86,11 @@ std::vector<Use> GetVarDeclarations(DB *db, const std::vector<Usr> &usrs,
|
|||||||
std::vector<DeclRef> &GetNonDefDeclarations(DB *db, SymbolIdx sym) {
|
std::vector<DeclRef> &GetNonDefDeclarations(DB *db, SymbolIdx sym) {
|
||||||
static std::vector<DeclRef> empty;
|
static std::vector<DeclRef> empty;
|
||||||
switch (sym.kind) {
|
switch (sym.kind) {
|
||||||
case SymbolKind::Func:
|
case Kind::Func:
|
||||||
return db->GetFunc(sym).declarations;
|
return db->GetFunc(sym).declarations;
|
||||||
case SymbolKind::Type:
|
case Kind::Type:
|
||||||
return db->GetType(sym).declarations;
|
return db->GetType(sym).declarations;
|
||||||
case SymbolKind::Var:
|
case Kind::Var:
|
||||||
return db->GetVar(sym).declarations;
|
return db->GetVar(sym).declarations;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -169,45 +169,44 @@ std::optional<lsRange> GetLsRange(WorkingFile *wfile,
|
|||||||
lsPosition{*end, end_column}};
|
lsPosition{*end, end_column}};
|
||||||
}
|
}
|
||||||
|
|
||||||
lsDocumentUri GetLsDocumentUri(DB *db, int file_id, std::string *path) {
|
DocumentUri GetLsDocumentUri(DB *db, int file_id, std::string *path) {
|
||||||
QueryFile &file = db->files[file_id];
|
QueryFile &file = db->files[file_id];
|
||||||
if (file.def) {
|
if (file.def) {
|
||||||
*path = file.def->path;
|
*path = file.def->path;
|
||||||
return lsDocumentUri::FromPath(*path);
|
return DocumentUri::FromPath(*path);
|
||||||
} else {
|
} else {
|
||||||
*path = "";
|
*path = "";
|
||||||
return lsDocumentUri::FromPath("");
|
return DocumentUri::FromPath("");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lsDocumentUri GetLsDocumentUri(DB *db, int file_id) {
|
DocumentUri GetLsDocumentUri(DB *db, int file_id) {
|
||||||
QueryFile &file = db->files[file_id];
|
QueryFile &file = db->files[file_id];
|
||||||
if (file.def) {
|
if (file.def) {
|
||||||
return lsDocumentUri::FromPath(file.def->path);
|
return DocumentUri::FromPath(file.def->path);
|
||||||
} else {
|
} else {
|
||||||
return lsDocumentUri::FromPath("");
|
return DocumentUri::FromPath("");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<lsLocation> GetLsLocation(DB *db, WorkingFiles *wfiles,
|
std::optional<Location> GetLsLocation(DB *db, WorkingFiles *wfiles, Use use) {
|
||||||
Use use) {
|
|
||||||
std::string path;
|
std::string path;
|
||||||
lsDocumentUri uri = GetLsDocumentUri(db, use.file_id, &path);
|
DocumentUri uri = GetLsDocumentUri(db, use.file_id, &path);
|
||||||
std::optional<lsRange> range =
|
std::optional<lsRange> range =
|
||||||
GetLsRange(wfiles->GetFileByFilename(path), use.range);
|
GetLsRange(wfiles->GetFileByFilename(path), use.range);
|
||||||
if (!range)
|
if (!range)
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
return lsLocation{uri, *range};
|
return Location{uri, *range};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<lsLocation> GetLsLocation(DB *db, WorkingFiles *wfiles,
|
std::optional<Location> GetLsLocation(DB *db, WorkingFiles *wfiles,
|
||||||
SymbolRef sym, int file_id) {
|
SymbolRef sym, int file_id) {
|
||||||
return GetLsLocation(db, wfiles, Use{{sym.range, sym.role}, file_id});
|
return GetLsLocation(db, wfiles, Use{{sym.range, sym.role}, file_id});
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<lsLocation> GetLsLocations(DB *db, WorkingFiles *wfiles,
|
std::vector<Location> GetLsLocations(DB *db, WorkingFiles *wfiles,
|
||||||
const std::vector<Use> &uses) {
|
const std::vector<Use> &uses) {
|
||||||
std::vector<lsLocation> ret;
|
std::vector<Location> ret;
|
||||||
for (Use use : uses)
|
for (Use use : uses)
|
||||||
if (auto loc = GetLsLocation(db, wfiles, use))
|
if (auto loc = GetLsLocation(db, wfiles, use))
|
||||||
ret.push_back(*loc);
|
ret.push_back(*loc);
|
||||||
@ -218,12 +217,12 @@ std::vector<lsLocation> GetLsLocations(DB *db, WorkingFiles *wfiles,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
lsSymbolKind GetSymbolKind(DB *db, SymbolIdx sym) {
|
SymbolKind GetSymbolKind(DB *db, SymbolIdx sym) {
|
||||||
lsSymbolKind ret;
|
SymbolKind ret;
|
||||||
if (sym.kind == SymbolKind::File)
|
if (sym.kind == Kind::File)
|
||||||
ret = lsSymbolKind::File;
|
ret = SymbolKind::File;
|
||||||
else {
|
else {
|
||||||
ret = lsSymbolKind::Unknown;
|
ret = SymbolKind::Unknown;
|
||||||
WithEntity(db, sym, [&](const auto &entity) {
|
WithEntity(db, sym, [&](const auto &entity) {
|
||||||
for (auto &def : entity.def) {
|
for (auto &def : entity.def) {
|
||||||
ret = def.kind;
|
ret = def.kind;
|
||||||
@ -234,23 +233,23 @@ lsSymbolKind GetSymbolKind(DB *db, SymbolIdx sym) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<lsSymbolInformation> GetSymbolInfo(DB *db, SymbolIdx sym,
|
std::optional<SymbolInformation> GetSymbolInfo(DB *db, SymbolIdx sym,
|
||||||
bool detailed) {
|
bool detailed) {
|
||||||
switch (sym.kind) {
|
switch (sym.kind) {
|
||||||
case SymbolKind::Invalid:
|
case Kind::Invalid:
|
||||||
break;
|
break;
|
||||||
case SymbolKind::File: {
|
case Kind::File: {
|
||||||
QueryFile &file = db->GetFile(sym);
|
QueryFile &file = db->GetFile(sym);
|
||||||
if (!file.def)
|
if (!file.def)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
lsSymbolInformation info;
|
SymbolInformation info;
|
||||||
info.name = file.def->path;
|
info.name = file.def->path;
|
||||||
info.kind = lsSymbolKind::File;
|
info.kind = SymbolKind::File;
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
lsSymbolInformation info;
|
SymbolInformation info;
|
||||||
EachEntityDef(db, sym, [&](const auto &def) {
|
EachEntityDef(db, sym, [&](const auto &def) {
|
||||||
if (detailed)
|
if (detailed)
|
||||||
info.name = def.detailed_name;
|
info.name = def.detailed_name;
|
||||||
@ -290,10 +289,10 @@ std::vector<SymbolRef> FindSymbolsAtLocation(WorkingFile *wfile,
|
|||||||
// important for macros which generate code so that we can resolving the
|
// important for macros which generate code so that we can resolving the
|
||||||
// macro argument takes priority over the entire macro body.
|
// macro argument takes priority over the entire macro body.
|
||||||
//
|
//
|
||||||
// Order SymbolKind::Var before SymbolKind::Type. Macro calls are treated as
|
// Order Kind::Var before Kind::Type. Macro calls are treated as Var
|
||||||
// Var currently. If a macro expands to tokens led by a SymbolKind::Type, the
|
// currently. If a macro expands to tokens led by a Kind::Type, the macro and
|
||||||
// macro and the Type have the same range. We want to find the macro
|
// the Type have the same range. We want to find the macro definition instead
|
||||||
// definition instead of the Type definition.
|
// of the Type definition.
|
||||||
//
|
//
|
||||||
// Then order functions before other types, which makes goto definition work
|
// Then order functions before other types, which makes goto definition work
|
||||||
// better on constructors.
|
// better on constructors.
|
||||||
|
@ -24,16 +24,16 @@ std::vector<Use> GetUsesForAllBases(DB *db, QueryFunc &root);
|
|||||||
std::vector<Use> GetUsesForAllDerived(DB *db, QueryFunc &root);
|
std::vector<Use> GetUsesForAllDerived(DB *db, QueryFunc &root);
|
||||||
std::optional<lsRange> GetLsRange(WorkingFile *working_file,
|
std::optional<lsRange> GetLsRange(WorkingFile *working_file,
|
||||||
const Range &location);
|
const Range &location);
|
||||||
lsDocumentUri GetLsDocumentUri(DB *db, int file_id, std::string *path);
|
DocumentUri GetLsDocumentUri(DB *db, int file_id, std::string *path);
|
||||||
lsDocumentUri GetLsDocumentUri(DB *db, int file_id);
|
DocumentUri GetLsDocumentUri(DB *db, int file_id);
|
||||||
|
|
||||||
std::optional<lsLocation> GetLsLocation(DB *db, WorkingFiles *wfiles, Use use);
|
std::optional<Location> GetLsLocation(DB *db, WorkingFiles *wfiles, Use use);
|
||||||
std::optional<lsLocation> GetLsLocation(DB *db, WorkingFiles *wfiles,
|
std::optional<Location> GetLsLocation(DB *db, WorkingFiles *wfiles,
|
||||||
SymbolRef sym, int file_id);
|
SymbolRef sym, int file_id);
|
||||||
std::vector<lsLocation> GetLsLocations(DB *db, WorkingFiles *wfiles,
|
std::vector<Location> GetLsLocations(DB *db, WorkingFiles *wfiles,
|
||||||
const std::vector<Use> &uses);
|
const std::vector<Use> &uses);
|
||||||
// Returns a symbol. The symbol will *NOT* have a location assigned.
|
// Returns a symbol. The symbol will *NOT* have a location assigned.
|
||||||
std::optional<lsSymbolInformation> GetSymbolInfo(DB *db, SymbolIdx sym,
|
std::optional<SymbolInformation> GetSymbolInfo(DB *db, SymbolIdx sym,
|
||||||
bool detailed);
|
bool detailed);
|
||||||
|
|
||||||
std::vector<SymbolRef> FindSymbolsAtLocation(WorkingFile *working_file,
|
std::vector<SymbolRef> FindSymbolsAtLocation(WorkingFile *working_file,
|
||||||
@ -43,16 +43,16 @@ std::vector<SymbolRef> FindSymbolsAtLocation(WorkingFile *working_file,
|
|||||||
|
|
||||||
template <typename Fn> void WithEntity(DB *db, SymbolIdx sym, Fn &&fn) {
|
template <typename Fn> void WithEntity(DB *db, SymbolIdx sym, Fn &&fn) {
|
||||||
switch (sym.kind) {
|
switch (sym.kind) {
|
||||||
case SymbolKind::Invalid:
|
case Kind::Invalid:
|
||||||
case SymbolKind::File:
|
case Kind::File:
|
||||||
break;
|
break;
|
||||||
case SymbolKind::Func:
|
case Kind::Func:
|
||||||
fn(db->GetFunc(sym));
|
fn(db->GetFunc(sym));
|
||||||
break;
|
break;
|
||||||
case SymbolKind::Type:
|
case Kind::Type:
|
||||||
fn(db->GetType(sym));
|
fn(db->GetType(sym));
|
||||||
break;
|
break;
|
||||||
case SymbolKind::Var:
|
case Kind::Var:
|
||||||
fn(db->GetVar(sym));
|
fn(db->GetVar(sym));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -81,7 +81,7 @@ void EachOccurrence(DB *db, SymbolIdx sym, bool include_decl, Fn &&fn) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
lsSymbolKind GetSymbolKind(DB *db, SymbolIdx sym);
|
SymbolKind GetSymbolKind(DB *db, SymbolIdx sym);
|
||||||
|
|
||||||
template <typename Fn>
|
template <typename Fn>
|
||||||
void EachDefinedFunc(DB *db, const std::vector<Usr> &usrs, Fn &&fn) {
|
void EachDefinedFunc(DB *db, const std::vector<Usr> &usrs, Fn &&fn) {
|
||||||
|
@ -255,10 +255,10 @@ bool RunIndexTests(const std::string &filter_path, bool enable_update) {
|
|||||||
bool success = true;
|
bool success = true;
|
||||||
bool update_all = false;
|
bool update_all = false;
|
||||||
// FIXME: show diagnostics in STL/headers when running tests. At the moment
|
// FIXME: show diagnostics in STL/headers when running tests. At the moment
|
||||||
// this can be done by constructing ClangIndex index(1, 1);
|
// this can be done by conRequestIdex index(1, 1);
|
||||||
CompletionManager completion(
|
CompletionManager completion(nullptr, nullptr,
|
||||||
nullptr, nullptr, [&](std::string, std::vector<lsDiagnostic>) {},
|
[&](std::string, std::vector<Diagnostic>) {},
|
||||||
[](lsRequestId id) {});
|
[](RequestId id) {});
|
||||||
GetFilesInFolder(
|
GetFilesInFolder(
|
||||||
"index_tests", true /*recursive*/, true /*add_folder_to_path*/,
|
"index_tests", true /*recursive*/, true /*add_folder_to_path*/,
|
||||||
[&](const std::string &path) {
|
[&](const std::string &path) {
|
||||||
|
@ -439,7 +439,7 @@ void WorkingFiles::DoActionOnFile(
|
|||||||
action(file);
|
action(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
WorkingFile *WorkingFiles::OnOpen(const lsTextDocumentItem &open) {
|
WorkingFile *WorkingFiles::OnOpen(const TextDocumentItem &open) {
|
||||||
std::lock_guard<std::mutex> lock(files_mutex);
|
std::lock_guard<std::mutex> lock(files_mutex);
|
||||||
|
|
||||||
std::string filename = open.uri.GetPath();
|
std::string filename = open.uri.GetPath();
|
||||||
@ -493,7 +493,7 @@ void WorkingFiles::OnChange(const TextDocumentDidChangeParam &change) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorkingFiles::OnClose(const lsTextDocumentIdentifier &close) {
|
void WorkingFiles::OnClose(const TextDocumentIdentifier &close) {
|
||||||
std::lock_guard<std::mutex> lock(files_mutex);
|
std::lock_guard<std::mutex> lock(files_mutex);
|
||||||
|
|
||||||
std::string filename = close.uri.GetPath();
|
std::string filename = close.uri.GetPath();
|
||||||
|
@ -31,7 +31,7 @@ struct WorkingFile {
|
|||||||
// A set of diagnostics that have been reported for this file.
|
// A set of diagnostics that have been reported for this file.
|
||||||
// NOTE: _ is appended because it must be accessed under the WorkingFiles
|
// NOTE: _ is appended because it must be accessed under the WorkingFiles
|
||||||
// lock!
|
// lock!
|
||||||
std::vector<lsDiagnostic> diagnostics_;
|
std::vector<Diagnostic> diagnostics_;
|
||||||
|
|
||||||
WorkingFile(const std::string &filename, const std::string &buffer_content);
|
WorkingFile(const std::string &filename, const std::string &buffer_content);
|
||||||
|
|
||||||
@ -105,9 +105,9 @@ struct WorkingFiles {
|
|||||||
void DoActionOnFile(const std::string &filename,
|
void DoActionOnFile(const std::string &filename,
|
||||||
const std::function<void(WorkingFile *file)> &action);
|
const std::function<void(WorkingFile *file)> &action);
|
||||||
|
|
||||||
WorkingFile *OnOpen(const lsTextDocumentItem &open);
|
WorkingFile *OnOpen(const TextDocumentItem &open);
|
||||||
void OnChange(const TextDocumentDidChangeParam &change);
|
void OnChange(const TextDocumentDidChangeParam &change);
|
||||||
void OnClose(const lsTextDocumentIdentifier &close);
|
void OnClose(const TextDocumentIdentifier &close);
|
||||||
|
|
||||||
// If |filter_paths| is non-empty, only files which contain any of the given
|
// If |filter_paths| is non-empty, only files which contain any of the given
|
||||||
// strings. For example, {"foo", "bar"} means that every result has either the
|
// strings. For example, {"foo", "bar"} means that every result has either the
|
||||||
|
Loading…
Reference in New Issue
Block a user