Remove ls prefix from many LSP interfaces

Rename SymbolKind to Kind & lsSymbolKind to SymbolKind
Use textDocumentSync: TextDocumentSyncOptions
This commit is contained in:
Fangrui Song 2018-11-03 13:52:43 -07:00
parent 9a6851c6a5
commit 0d4f4b68c0
41 changed files with 681 additions and 833 deletions

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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.

View File

@ -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);

View File

@ -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;
} }

View File

@ -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

View File

@ -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,

View File

@ -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();

View File

@ -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;

View File

@ -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 &);

View File

@ -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;

View File

@ -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 &param, 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 &param, 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;

View File

@ -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;
} }

View File

@ -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;
} }

View File

@ -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;
} }

View File

@ -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));

View File

@ -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 &param, ReplyOnce &reply) { void Initialize(MessageHandler *m, InitializeParam &param, 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 &param, 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 &param, 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);
} }

View File

@ -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 &param,
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 &param,
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 &param, void MessageHandler::textDocument_codeLens(TextDocumentParam &param,
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 &param,
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 &param,
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 &param,
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);

View File

@ -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 &param, void MessageHandler::textDocument_completion(CompletionParam &param,
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 &param,
// 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 &param,
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 &param,
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,

View File

@ -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 &param,
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 &param,
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 &param,
// 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 &param,
} }
}; };
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));

View File

@ -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 &param, void MessageHandler::textDocument_documentLink(TextDocumentParam &param,
@ -81,10 +81,10 @@ void MessageHandler::textDocument_documentLink(TextDocumentParam &param,
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;

View File

@ -30,7 +30,7 @@ void MessageHandler::textDocument_foldingRange(TextDocumentParam &param,
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;

View File

@ -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);
} }

View File

@ -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};

View File

@ -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;
} }

View File

@ -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 &param, 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;

View File

@ -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 &param, ReplyOnce &reply) { TextDocumentPositionParam &param, 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;

View File

@ -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 &param, void MessageHandler::workspace_symbol(WorkspaceSymbolParam &param,
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 &param,
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:

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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.

View File

@ -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) {

View File

@ -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) {

View File

@ -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();

View File

@ -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