mirror of
https://github.com/MaskRay/ccls.git
synced 2024-12-01 11:57:09 +00:00
Index namespace alias and MSVC __interface; add --enable-assert to waf; add lexical container to xref requests
This commit is contained in:
parent
909c2e247a
commit
1a4da727da
@ -23,7 +23,6 @@
|
|||||||
#include "serializer.h"
|
#include "serializer.h"
|
||||||
#include "serializers/json.h"
|
#include "serializers/json.h"
|
||||||
#include "test.h"
|
#include "test.h"
|
||||||
#include "threaded_queue.h"
|
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
#include "timestamp_manager.h"
|
#include "timestamp_manager.h"
|
||||||
#include "work_thread.h"
|
#include "work_thread.h"
|
||||||
|
17
src/config.h
17
src/config.h
@ -162,13 +162,13 @@ struct Config {
|
|||||||
};
|
};
|
||||||
Completion completion;
|
Completion completion;
|
||||||
|
|
||||||
// Maximum number of definition/reference/... results.
|
struct Xref {
|
||||||
int maxXrefResults = 500;
|
// If true, |Location[]| response will include lexical container.
|
||||||
struct Extension {
|
bool container = false;
|
||||||
// If true, reference results will include "containerName".
|
// Maximum number of definition/reference/... results.
|
||||||
bool referenceContainer = false;
|
int maxNum = 300;
|
||||||
};
|
};
|
||||||
Extension extension;
|
Xref xref;
|
||||||
|
|
||||||
struct Index {
|
struct Index {
|
||||||
// 0: none, 1: doxygen, 2: all comments
|
// 0: none, 1: doxygen, 2: all comments
|
||||||
@ -195,7 +195,7 @@ struct Config {
|
|||||||
};
|
};
|
||||||
MAKE_REFLECT_STRUCT(Config::ClientCapability, snippetSupport);
|
MAKE_REFLECT_STRUCT(Config::ClientCapability, snippetSupport);
|
||||||
MAKE_REFLECT_STRUCT(Config::Completion, filterAndSort, detailedLabel);
|
MAKE_REFLECT_STRUCT(Config::Completion, filterAndSort, detailedLabel);
|
||||||
MAKE_REFLECT_STRUCT(Config::Extension, referenceContainer);
|
MAKE_REFLECT_STRUCT(Config::Xref, container, maxNum);
|
||||||
MAKE_REFLECT_STRUCT(Config::Index, comments, attributeMakeCallsToCtor);
|
MAKE_REFLECT_STRUCT(Config::Index, comments, attributeMakeCallsToCtor);
|
||||||
MAKE_REFLECT_STRUCT(Config,
|
MAKE_REFLECT_STRUCT(Config,
|
||||||
compilationDatabaseCommand,
|
compilationDatabaseCommand,
|
||||||
@ -233,8 +233,7 @@ MAKE_REFLECT_STRUCT(Config,
|
|||||||
|
|
||||||
client,
|
client,
|
||||||
completion,
|
completion,
|
||||||
maxXrefResults,
|
xref,
|
||||||
extension,
|
|
||||||
index,
|
index,
|
||||||
|
|
||||||
dumpAST);
|
dumpAST);
|
||||||
|
@ -1510,20 +1510,24 @@ void OnIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
|
|||||||
ClangCursor lex_parent(fromContainer(decl->lexicalContainer));
|
ClangCursor lex_parent(fromContainer(decl->lexicalContainer));
|
||||||
SetUsePreflight(db, sem_parent);
|
SetUsePreflight(db, sem_parent);
|
||||||
SetUsePreflight(db, lex_parent);
|
SetUsePreflight(db, lex_parent);
|
||||||
|
ClangCursor cursor = decl->cursor;
|
||||||
|
|
||||||
switch (decl->entityInfo->kind) {
|
switch (decl->entityInfo->kind) {
|
||||||
|
case CXIdxEntity_Unexposed:
|
||||||
|
LOG_S(INFO) << "CXIdxEntity_Unexposed " << cursor.get_spell_name();
|
||||||
|
break;
|
||||||
|
|
||||||
case CXIdxEntity_CXXNamespace: {
|
case CXIdxEntity_CXXNamespace: {
|
||||||
ClangCursor decl_cursor = decl->cursor;
|
Range spell = cursor.get_spell();
|
||||||
Range spell = decl_cursor.get_spell();
|
|
||||||
IndexTypeId ns_id = db->ToTypeId(HashUsr(decl->entityInfo->USR));
|
IndexTypeId ns_id = db->ToTypeId(HashUsr(decl->entityInfo->USR));
|
||||||
IndexType* ns = db->Resolve(ns_id);
|
IndexType* ns = db->Resolve(ns_id);
|
||||||
ns->def.kind = GetSymbolKind(decl->entityInfo->kind);
|
ns->def.kind = GetSymbolKind(decl->entityInfo->kind);
|
||||||
if (ns->def.detailed_name.empty()) {
|
if (ns->def.detailed_name.empty()) {
|
||||||
SetTypeName(ns, decl_cursor, decl->semanticContainer,
|
SetTypeName(ns, cursor, decl->semanticContainer,
|
||||||
decl->entityInfo->name, param);
|
decl->entityInfo->name, param);
|
||||||
ns->def.spell = SetUse(db, spell, sem_parent, Role::Definition);
|
ns->def.spell = SetUse(db, spell, sem_parent, Role::Definition);
|
||||||
ns->def.extent =
|
ns->def.extent =
|
||||||
SetUse(db, decl_cursor.get_extent(), lex_parent, Role::None);
|
SetUse(db, cursor.get_extent(), lex_parent, Role::None);
|
||||||
if (decl->semanticContainer) {
|
if (decl->semanticContainer) {
|
||||||
IndexTypeId parent_id = db->ToTypeId(
|
IndexTypeId parent_id = db->ToTypeId(
|
||||||
ClangCursor(decl->semanticContainer->cursor).get_usr_hash());
|
ClangCursor(decl->semanticContainer->cursor).get_usr_hash());
|
||||||
@ -1537,6 +1541,10 @@ void OnIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case CXIdxEntity_CXXNamespaceAlias:
|
||||||
|
assert(false && "CXXNamespaceAlias");
|
||||||
|
break;
|
||||||
|
|
||||||
case CXIdxEntity_ObjCProperty:
|
case CXIdxEntity_ObjCProperty:
|
||||||
case CXIdxEntity_ObjCIvar:
|
case CXIdxEntity_ObjCIvar:
|
||||||
case CXIdxEntity_EnumConstant:
|
case CXIdxEntity_EnumConstant:
|
||||||
@ -1804,6 +1812,7 @@ void OnIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
|
|||||||
case CXIdxEntity_Enum:
|
case CXIdxEntity_Enum:
|
||||||
case CXIdxEntity_Union:
|
case CXIdxEntity_Union:
|
||||||
case CXIdxEntity_Struct:
|
case CXIdxEntity_Struct:
|
||||||
|
case CXIdxEntity_CXXInterface:
|
||||||
case CXIdxEntity_CXXClass: {
|
case CXIdxEntity_CXXClass: {
|
||||||
ClangCursor decl_cursor = decl->cursor;
|
ClangCursor decl_cursor = decl->cursor;
|
||||||
Range spell = decl_cursor.get_spell();
|
Range spell = decl_cursor.get_spell();
|
||||||
@ -1919,30 +1928,6 @@ void OnIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
|
||||||
std::cerr
|
|
||||||
<< "!! Unhandled indexDeclaration: "
|
|
||||||
<< ClangCursor(decl->cursor).ToString() << " at "
|
|
||||||
<< ClangCursor(decl->cursor).get_spell().start.ToString()
|
|
||||||
<< std::endl;
|
|
||||||
std::cerr << " entityInfo->kind = " << decl->entityInfo->kind
|
|
||||||
<< std::endl;
|
|
||||||
std::cerr << " entityInfo->USR = " << decl->entityInfo->USR
|
|
||||||
<< std::endl;
|
|
||||||
if (decl->declAsContainer)
|
|
||||||
std::cerr << " declAsContainer = "
|
|
||||||
<< ClangCursor(decl->declAsContainer->cursor).ToString()
|
|
||||||
<< std::endl;
|
|
||||||
if (decl->semanticContainer)
|
|
||||||
std::cerr << " semanticContainer = "
|
|
||||||
<< ClangCursor(decl->semanticContainer->cursor).ToString()
|
|
||||||
<< std::endl;
|
|
||||||
if (decl->lexicalContainer)
|
|
||||||
std::cerr << " lexicalContainer = "
|
|
||||||
<< ClangCursor(decl->lexicalContainer->cursor).get_usr_hash()
|
|
||||||
<< std::endl;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1990,17 +1975,38 @@ void OnIndexReference(CXClientData client_data, const CXIdxEntityRefInfo* ref) {
|
|||||||
|
|
||||||
ClangCursor cursor(ref->cursor);
|
ClangCursor cursor(ref->cursor);
|
||||||
ClangCursor lex_parent(fromContainer(ref->container));
|
ClangCursor lex_parent(fromContainer(ref->container));
|
||||||
|
ClangCursor referenced;
|
||||||
|
if (ref->referencedEntity)
|
||||||
|
referenced = ref->referencedEntity->cursor;
|
||||||
SetUsePreflight(db, lex_parent);
|
SetUsePreflight(db, lex_parent);
|
||||||
|
|
||||||
switch (ref->referencedEntity->kind) {
|
switch (ref->referencedEntity->kind) {
|
||||||
case CXIdxEntity_CXXNamespaceAlias:
|
case CXIdxEntity_Unexposed:
|
||||||
|
LOG_S(INFO) << "CXIdxEntity_Unexposed " << cursor.get_spell_name();
|
||||||
|
break;
|
||||||
|
|
||||||
case CXIdxEntity_CXXNamespace: {
|
case CXIdxEntity_CXXNamespace: {
|
||||||
ClangCursor referenced = ref->referencedEntity->cursor;
|
|
||||||
IndexType* ns = db->Resolve(db->ToTypeId(referenced.get_usr_hash()));
|
IndexType* ns = db->Resolve(db->ToTypeId(referenced.get_usr_hash()));
|
||||||
AddUse(db, ns->uses, cursor.get_spell(), fromContainer(ref->container));
|
AddUse(db, ns->uses, cursor.get_spell(), fromContainer(ref->container));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case CXIdxEntity_CXXNamespaceAlias: {
|
||||||
|
IndexType* ns = db->Resolve(db->ToTypeId(referenced.get_usr_hash()));
|
||||||
|
AddUse(db, ns->uses, cursor.get_spell(), fromContainer(ref->container));
|
||||||
|
if (!ns->def.spell) {
|
||||||
|
ClangCursor sem_parent = referenced.get_semantic_parent();
|
||||||
|
ClangCursor lex_parent = referenced.get_lexical_parent();
|
||||||
|
SetUsePreflight(db, sem_parent);
|
||||||
|
SetUsePreflight(db, lex_parent);
|
||||||
|
ns->def.spell = SetUse(db, referenced.get_spell(), sem_parent, Role::Definition);
|
||||||
|
ns->def.extent = SetUse(db, referenced.get_extent(), lex_parent, Role::None);
|
||||||
|
std::string name = referenced.get_spell_name();
|
||||||
|
SetTypeName(ns, referenced, nullptr, name.c_str(), param);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case CXIdxEntity_ObjCProperty:
|
case CXIdxEntity_ObjCProperty:
|
||||||
case CXIdxEntity_ObjCIvar:
|
case CXIdxEntity_ObjCIvar:
|
||||||
case CXIdxEntity_EnumConstant:
|
case CXIdxEntity_EnumConstant:
|
||||||
@ -2146,6 +2152,7 @@ void OnIndexReference(CXClientData client_data, const CXIdxEntityRefInfo* ref) {
|
|||||||
case CXIdxEntity_ObjCProtocol:
|
case CXIdxEntity_ObjCProtocol:
|
||||||
case CXIdxEntity_ObjCClass:
|
case CXIdxEntity_ObjCClass:
|
||||||
case CXIdxEntity_Typedef:
|
case CXIdxEntity_Typedef:
|
||||||
|
case CXIdxEntity_CXXInterface: // MSVC __interface
|
||||||
case CXIdxEntity_CXXTypeAlias:
|
case CXIdxEntity_CXXTypeAlias:
|
||||||
case CXIdxEntity_Enum:
|
case CXIdxEntity_Enum:
|
||||||
case CXIdxEntity_Union:
|
case CXIdxEntity_Union:
|
||||||
@ -2176,36 +2183,6 @@ void OnIndexReference(CXClientData client_data, const CXIdxEntityRefInfo* ref) {
|
|||||||
UniqueAddUseSpell(db, ref_type->uses, ref->cursor);
|
UniqueAddUseSpell(db, ref_type->uses, ref->cursor);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
|
||||||
std::cerr
|
|
||||||
<< "!! Unhandled indexEntityReference: " << cursor.ToString()
|
|
||||||
<< " at "
|
|
||||||
<< ClangCursor(ref->cursor).get_spell().start.ToString()
|
|
||||||
<< std::endl;
|
|
||||||
std::cerr << " ref->referencedEntity->kind = "
|
|
||||||
<< ref->referencedEntity->kind << std::endl;
|
|
||||||
if (ref->parentEntity)
|
|
||||||
std::cerr << " ref->parentEntity->kind = "
|
|
||||||
<< ref->parentEntity->kind << std::endl;
|
|
||||||
std::cerr
|
|
||||||
<< " ref->loc = "
|
|
||||||
<< ClangCursor(ref->cursor).get_spell().start.ToString()
|
|
||||||
<< std::endl;
|
|
||||||
std::cerr << " ref->kind = " << ref->kind << std::endl;
|
|
||||||
if (ref->parentEntity)
|
|
||||||
std::cerr << " parentEntity = "
|
|
||||||
<< ClangCursor(ref->parentEntity->cursor).ToString()
|
|
||||||
<< std::endl;
|
|
||||||
if (ref->referencedEntity)
|
|
||||||
std::cerr << " referencedEntity = "
|
|
||||||
<< ClangCursor(ref->referencedEntity->cursor).ToString()
|
|
||||||
<< std::endl;
|
|
||||||
if (ref->container)
|
|
||||||
std::cerr << " container = "
|
|
||||||
<< ClangCursor(ref->container->cursor).ToString()
|
|
||||||
<< std::endl;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -638,6 +638,6 @@ MAKE_REFLECT_STRUCT(Out_CquerySetInactiveRegion, jsonrpc, method, params);
|
|||||||
|
|
||||||
struct Out_LocationList : public lsOutMessage<Out_LocationList> {
|
struct Out_LocationList : public lsOutMessage<Out_LocationList> {
|
||||||
lsRequestId id;
|
lsRequestId id;
|
||||||
std::vector<lsLocation> result;
|
std::vector<lsLocationEx> result;
|
||||||
};
|
};
|
||||||
MAKE_REFLECT_STRUCT(Out_LocationList, jsonrpc, id, result);
|
MAKE_REFLECT_STRUCT(Out_LocationList, jsonrpc, id, result);
|
||||||
|
@ -27,13 +27,15 @@ struct CqueryBaseHandler : BaseMessageHandler<Ipc_CqueryBase> {
|
|||||||
FindSymbolsAtLocation(working_file, file, request->params.position)) {
|
FindSymbolsAtLocation(working_file, file, request->params.position)) {
|
||||||
if (sym.kind == SymbolKind::Type) {
|
if (sym.kind == SymbolKind::Type) {
|
||||||
if (const auto* def = db->GetType(sym).AnyDef())
|
if (const auto* def = db->GetType(sym).AnyDef())
|
||||||
out.result = GetLsLocations(db, working_files,
|
out.result =
|
||||||
ToUses(db, def->parents), config->maxXrefResults);
|
GetLsLocationExs(db, working_files, ToUses(db, def->parents),
|
||||||
|
config->xref.container, config->xref.maxNum);
|
||||||
break;
|
break;
|
||||||
} else if (sym.kind == SymbolKind::Func) {
|
} else if (sym.kind == SymbolKind::Func) {
|
||||||
if (const auto* def = db->GetFunc(sym).AnyDef())
|
if (const auto* def = db->GetFunc(sym).AnyDef())
|
||||||
out.result = GetLsLocations(db, working_files, ToUses(db, def->base),
|
out.result =
|
||||||
config->maxXrefResults);
|
GetLsLocationExs(db, working_files, ToUses(db, def->base),
|
||||||
|
config->xref.container, config->xref.maxNum);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,9 @@ struct CqueryCallersHandler : BaseMessageHandler<Ipc_CqueryCallers> {
|
|||||||
uses.push_back(func_ref);
|
uses.push_back(func_ref);
|
||||||
for (Use func_ref : GetCallersForAllDerivedFunctions(db, func))
|
for (Use func_ref : GetCallersForAllDerivedFunctions(db, func))
|
||||||
uses.push_back(func_ref);
|
uses.push_back(func_ref);
|
||||||
out.result = GetLsLocations(db, working_files, uses, config->maxXrefResults);
|
out.result =
|
||||||
|
GetLsLocationExs(db, working_files, uses, config->xref.container,
|
||||||
|
config->xref.maxNum);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,13 +27,14 @@ struct CqueryDerivedHandler : BaseMessageHandler<Ipc_CqueryDerived> {
|
|||||||
FindSymbolsAtLocation(working_file, file, request->params.position)) {
|
FindSymbolsAtLocation(working_file, file, request->params.position)) {
|
||||||
if (sym.kind == SymbolKind::Type) {
|
if (sym.kind == SymbolKind::Type) {
|
||||||
QueryType& type = db->GetType(sym);
|
QueryType& type = db->GetType(sym);
|
||||||
out.result = GetLsLocations(db, working_files, ToUses(db, type.derived),
|
out.result =
|
||||||
config->maxXrefResults);
|
GetLsLocationExs(db, working_files, ToUses(db, type.derived),
|
||||||
|
config->xref.container, config->xref.maxNum);
|
||||||
break;
|
break;
|
||||||
} else if (sym.kind == SymbolKind::Func) {
|
} else if (sym.kind == SymbolKind::Func) {
|
||||||
QueryFunc& func = db->GetFunc(sym);
|
QueryFunc& func = db->GetFunc(sym);
|
||||||
out.result = GetLsLocations(db, working_files, ToUses(db, func.derived),
|
out.result = GetLsLocationExs(db, working_files, ToUses(db, func.derived),
|
||||||
config->maxXrefResults);
|
config->xref.container, config->xref.maxNum);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -101,7 +101,7 @@ struct CqueryRandomHandler : BaseMessageHandler<Ipc_CqueryRandom> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::vector<double> x(n, 1), y;
|
std::vector<double> x(n, 1), y;
|
||||||
for (int j = 0; j < 30; j++) {
|
for (int j = 0; j < 8; j++) {
|
||||||
y.assign(n, kDamping);
|
y.assign(n, kDamping);
|
||||||
for (int i = 0; i < n; i++)
|
for (int i = 0; i < n; i++)
|
||||||
for (auto& it : adj[i])
|
for (auto& it : adj[i])
|
||||||
@ -124,8 +124,8 @@ struct CqueryRandomHandler : BaseMessageHandler<Ipc_CqueryRandom> {
|
|||||||
Maybe<Use> use = GetDefinitionExtentOfSymbol(db, syms[i]);
|
Maybe<Use> use = GetDefinitionExtentOfSymbol(db, syms[i]);
|
||||||
if (!use)
|
if (!use)
|
||||||
continue;
|
continue;
|
||||||
optional<lsLocation> ls_loc = GetLsLocation(db, working_files, *use);
|
if (auto ls_loc = GetLsLocationEx(db, working_files, *use,
|
||||||
if (ls_loc)
|
config->xref.container))
|
||||||
out.result.push_back(*ls_loc);
|
out.result.push_back(*ls_loc);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -39,8 +39,8 @@ struct CqueryVarsHandler : BaseMessageHandler<Ipc_CqueryVars> {
|
|||||||
case SymbolKind::Type: {
|
case SymbolKind::Type: {
|
||||||
QueryType& type = db->types[id.id];
|
QueryType& type = db->types[id.id];
|
||||||
out.result =
|
out.result =
|
||||||
GetLsLocations(db, working_files, ToUses(db, type.instances),
|
GetLsLocationExs(db, working_files, ToUses(db, type.instances),
|
||||||
config->maxXrefResults);
|
config->xref.container, config->xref.maxNum);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
#include "fuzzy_match.h"
|
|
||||||
#include "lex_utils.h"
|
#include "lex_utils.h"
|
||||||
#include "message_handler.h"
|
#include "message_handler.h"
|
||||||
#include "query_utils.h"
|
#include "query_utils.h"
|
||||||
@ -21,18 +20,17 @@ REGISTER_IPC_MESSAGE(Ipc_TextDocumentDefinition);
|
|||||||
struct Out_TextDocumentDefinition
|
struct Out_TextDocumentDefinition
|
||||||
: public lsOutMessage<Out_TextDocumentDefinition> {
|
: public lsOutMessage<Out_TextDocumentDefinition> {
|
||||||
lsRequestId id;
|
lsRequestId id;
|
||||||
std::vector<lsLocation> result;
|
std::vector<lsLocationEx> result;
|
||||||
};
|
};
|
||||||
MAKE_REFLECT_STRUCT(Out_TextDocumentDefinition, jsonrpc, id, result);
|
MAKE_REFLECT_STRUCT(Out_TextDocumentDefinition, jsonrpc, id, result);
|
||||||
|
|
||||||
std::vector<Use> GetGotoDefinitionTargets(QueryDatabase* db,
|
std::vector<Use> GetGotoDefinitionTargets(QueryDatabase* db,
|
||||||
SymbolRef sym) {
|
SymbolRef sym) {
|
||||||
switch (sym.kind) {
|
switch (sym.kind) {
|
||||||
// Returns GetDeclarationsOfSymbolForGotoDefinition and
|
|
||||||
// variable type definition.
|
|
||||||
case SymbolKind::Var: {
|
case SymbolKind::Var: {
|
||||||
std::vector<Use> ret =
|
std::vector<Use> ret =
|
||||||
GetDeclarationsOfSymbolForGotoDefinition(db, sym);
|
GetDeclarationsOfSymbolForGotoDefinition(db, sym);
|
||||||
|
// If there is no declaration, jump the its type.
|
||||||
if (ret.empty()) {
|
if (ret.empty()) {
|
||||||
for (auto& def : db->GetVar(sym).def)
|
for (auto& def : db->GetVar(sym).def)
|
||||||
if (def.type) {
|
if (def.type) {
|
||||||
@ -67,6 +65,7 @@ struct TextDocumentDefinitionHandler
|
|||||||
Out_TextDocumentDefinition out;
|
Out_TextDocumentDefinition out;
|
||||||
out.id = request->id;
|
out.id = request->id;
|
||||||
|
|
||||||
|
Maybe<Use> on_def;
|
||||||
bool has_symbol = false;
|
bool has_symbol = false;
|
||||||
int target_line = request->params.position.line;
|
int target_line = request->params.position.line;
|
||||||
int target_column = request->params.position.character;
|
int target_column = request->params.position.character;
|
||||||
@ -87,6 +86,7 @@ struct TextDocumentDefinitionHandler
|
|||||||
// If on a definition, clear |uses| to find declarations below.
|
// If on a definition, clear |uses| to find declarations below.
|
||||||
if (spell.file == file_id &&
|
if (spell.file == file_id &&
|
||||||
spell.range.Contains(target_line, target_column)) {
|
spell.range.Contains(target_line, target_column)) {
|
||||||
|
on_def = spell;
|
||||||
uses.clear();
|
uses.clear();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -99,10 +99,16 @@ struct TextDocumentDefinitionHandler
|
|||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (uses.empty())
|
if (uses.empty()) {
|
||||||
|
// The symbol has no definition or the cursor is on a definition.
|
||||||
uses = GetGotoDefinitionTargets(db, sym);
|
uses = GetGotoDefinitionTargets(db, sym);
|
||||||
|
// There is no declaration but the cursor is on a definition.
|
||||||
|
if (uses.empty() && on_def)
|
||||||
|
uses.push_back(*on_def);
|
||||||
|
}
|
||||||
AddRange(&out.result,
|
AddRange(&out.result,
|
||||||
GetLsLocations(db, working_files, uses, config->maxXrefResults));
|
GetLsLocationExs(db, working_files, uses, config->xref.container,
|
||||||
|
config->xref.maxNum));
|
||||||
if (!out.result.empty())
|
if (!out.result.empty())
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -111,7 +117,7 @@ struct TextDocumentDefinitionHandler
|
|||||||
if (out.result.empty()) {
|
if (out.result.empty()) {
|
||||||
for (const IndexInclude& include : file->def->includes) {
|
for (const IndexInclude& include : file->def->includes) {
|
||||||
if (include.line == target_line) {
|
if (include.line == target_line) {
|
||||||
lsLocation result;
|
lsLocationEx result;
|
||||||
result.uri = lsDocumentUri::FromPath(include.resolved_path);
|
result.uri = lsDocumentUri::FromPath(include.resolved_path);
|
||||||
out.result.push_back(result);
|
out.result.push_back(result);
|
||||||
has_symbol = true;
|
has_symbol = true;
|
||||||
@ -154,8 +160,8 @@ struct TextDocumentDefinitionHandler
|
|||||||
if (best_i != -1) {
|
if (best_i != -1) {
|
||||||
Maybe<Use> use = GetDefinitionSpellingOfSymbol(db, db->symbols[best_i]);
|
Maybe<Use> use = GetDefinitionSpellingOfSymbol(db, db->symbols[best_i]);
|
||||||
assert(use);
|
assert(use);
|
||||||
optional<lsLocation> ls_loc = GetLsLocation(db, working_files, *use);
|
if (auto ls_loc = GetLsLocationEx(db, working_files, *use,
|
||||||
if (ls_loc)
|
config->xref.container))
|
||||||
out.result.push_back(*ls_loc);
|
out.result.push_back(*ls_loc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,9 +56,8 @@ struct TextDocumentReferencesHandler
|
|||||||
// Found symbol. Return references.
|
// Found symbol. Return references.
|
||||||
EachUse(db, sym, request->params.context.includeDeclaration,
|
EachUse(db, sym, request->params.context.includeDeclaration,
|
||||||
[&](Use use) {
|
[&](Use use) {
|
||||||
if (optional<lsLocationEx> ls_loc =
|
if (optional<lsLocationEx> ls_loc = GetLsLocationEx(
|
||||||
GetLsLocationEx(db, working_files, use,
|
db, working_files, use, config->xref.container))
|
||||||
config->extension.referenceContainer))
|
|
||||||
out.result.push_back(*ls_loc);
|
out.result.push_back(*ls_loc);
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include <climits>
|
#include <climits>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
#include <stack>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@ -118,25 +119,25 @@ std::vector<Use> GetDeclarationsOfSymbolForGotoDefinition(
|
|||||||
|
|
||||||
bool HasCallersOnSelfOrBaseOrDerived(QueryDatabase* db, QueryFunc& root) {
|
bool HasCallersOnSelfOrBaseOrDerived(QueryDatabase* db, QueryFunc& root) {
|
||||||
std::unordered_set<Usr> seen;
|
std::unordered_set<Usr> seen;
|
||||||
std::queue<QueryFunc*> queue;
|
std::stack<QueryFunc*> stack;
|
||||||
seen.insert(root.usr);
|
seen.insert(root.usr);
|
||||||
queue.push(&root);
|
stack.push(&root);
|
||||||
while (!queue.empty()) {
|
while (!stack.empty()) {
|
||||||
QueryFunc& func = *queue.front();
|
QueryFunc& func = *stack.top();
|
||||||
queue.pop();
|
stack.pop();
|
||||||
if (!func.uses.empty())
|
if (!func.uses.empty())
|
||||||
return true;
|
return true;
|
||||||
if (auto* def = func.AnyDef()) {
|
if (auto* def = func.AnyDef()) {
|
||||||
EachDefinedEntity(db->funcs, def->base, [&](QueryFunc& func1) {
|
EachDefinedEntity(db->funcs, def->base, [&](QueryFunc& func1) {
|
||||||
if (!seen.count(func1.usr)) {
|
if (!seen.count(func1.usr)) {
|
||||||
seen.insert(func1.usr);
|
seen.insert(func1.usr);
|
||||||
queue.push(&func1);
|
stack.push(&func1);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
EachDefinedEntity(db->funcs, func.derived, [&](QueryFunc& func1) {
|
EachDefinedEntity(db->funcs, func.derived, [&](QueryFunc& func1) {
|
||||||
if (!seen.count(func1.usr)) {
|
if (!seen.count(func1.usr)) {
|
||||||
seen.insert(func1.usr);
|
seen.insert(func1.usr);
|
||||||
queue.push(&func1);
|
stack.push(&func1);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -147,22 +148,20 @@ bool HasCallersOnSelfOrBaseOrDerived(QueryDatabase* db, QueryFunc& root) {
|
|||||||
std::vector<Use> GetCallersForAllBaseFunctions(QueryDatabase* db,
|
std::vector<Use> GetCallersForAllBaseFunctions(QueryDatabase* db,
|
||||||
QueryFunc& root) {
|
QueryFunc& root) {
|
||||||
std::vector<Use> callers;
|
std::vector<Use> callers;
|
||||||
const QueryFunc::Def* def = root.AnyDef();
|
std::unordered_set<Usr> seen;
|
||||||
if (!def)
|
std::stack<QueryFunc*> stack;
|
||||||
return callers;
|
seen.insert(root.usr);
|
||||||
|
stack.push(&root);
|
||||||
std::queue<QueryFunc*> queue;
|
while (!stack.empty()) {
|
||||||
EachDefinedEntity(db->funcs, def->base, [&](QueryFunc& func1) {
|
QueryFunc& func = *stack.top();
|
||||||
queue.push(&func1);
|
stack.pop();
|
||||||
});
|
|
||||||
while (!queue.empty()) {
|
|
||||||
QueryFunc& func = *queue.front();
|
|
||||||
queue.pop();
|
|
||||||
|
|
||||||
AddRange(&callers, func.uses);
|
AddRange(&callers, func.uses);
|
||||||
if (const QueryFunc::Def* def1 = func.AnyDef()) {
|
if (auto* def = func.AnyDef()) {
|
||||||
EachDefinedEntity(db->funcs, def1->base, [&](QueryFunc& func1) {
|
EachDefinedEntity(db->funcs, def->base, [&](QueryFunc& func1) {
|
||||||
queue.push(&func1);
|
if (!seen.count(func1.usr)) {
|
||||||
|
seen.insert(func1.usr);
|
||||||
|
stack.push(&func1);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -173,20 +172,20 @@ std::vector<Use> GetCallersForAllBaseFunctions(QueryDatabase* db,
|
|||||||
std::vector<Use> GetCallersForAllDerivedFunctions(QueryDatabase* db,
|
std::vector<Use> GetCallersForAllDerivedFunctions(QueryDatabase* db,
|
||||||
QueryFunc& root) {
|
QueryFunc& root) {
|
||||||
std::vector<Use> callers;
|
std::vector<Use> callers;
|
||||||
|
std::unordered_set<Usr> seen;
|
||||||
std::queue<QueryFunc*> queue;
|
std::stack<QueryFunc*> stack;
|
||||||
EachDefinedEntity(db->funcs, root.derived, [&](QueryFunc& func) {
|
seen.insert(root.usr);
|
||||||
queue.push(&func);
|
stack.push(&root);
|
||||||
});
|
while (!stack.empty()) {
|
||||||
|
QueryFunc& func = *stack.top();
|
||||||
while (!queue.empty()) {
|
stack.pop();
|
||||||
QueryFunc& func = *queue.front();
|
|
||||||
queue.pop();
|
|
||||||
|
|
||||||
EachDefinedEntity(db->funcs, func.derived, [&](QueryFunc& func1) {
|
|
||||||
queue.push(&func1);
|
|
||||||
});
|
|
||||||
AddRange(&callers, func.uses);
|
AddRange(&callers, func.uses);
|
||||||
|
EachDefinedEntity(db->funcs, func.derived, [&](QueryFunc& func1) {
|
||||||
|
if (!seen.count(func1.usr)) {
|
||||||
|
seen.insert(func1.usr);
|
||||||
|
stack.push(&func1);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return callers;
|
return callers;
|
||||||
@ -198,12 +197,10 @@ optional<lsPosition> GetLsPosition(WorkingFile* working_file,
|
|||||||
return lsPosition(position.line, position.column);
|
return lsPosition(position.line, position.column);
|
||||||
|
|
||||||
int column = position.column;
|
int column = position.column;
|
||||||
optional<int> start =
|
if (optional<int> start =
|
||||||
working_file->GetBufferPosFromIndexPos(position.line, &column, false);
|
working_file->GetBufferPosFromIndexPos(position.line, &column, false))
|
||||||
if (!start)
|
return lsPosition(*start, column);
|
||||||
return nullopt;
|
return nullopt;
|
||||||
|
|
||||||
return lsPosition(*start, column);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
optional<lsRange> GetLsRange(WorkingFile* working_file, const Range& location) {
|
optional<lsRange> GetLsRange(WorkingFile* working_file, const Range& location) {
|
||||||
@ -272,13 +269,13 @@ optional<lsLocation> GetLsLocation(QueryDatabase* db,
|
|||||||
optional<lsLocationEx> GetLsLocationEx(QueryDatabase* db,
|
optional<lsLocationEx> GetLsLocationEx(QueryDatabase* db,
|
||||||
WorkingFiles* working_files,
|
WorkingFiles* working_files,
|
||||||
Use use,
|
Use use,
|
||||||
bool extension) {
|
bool container) {
|
||||||
optional<lsLocation> ls_loc = GetLsLocation(db, working_files, use);
|
optional<lsLocation> ls_loc = GetLsLocation(db, working_files, use);
|
||||||
if (!ls_loc)
|
if (!ls_loc)
|
||||||
return nullopt;
|
return nullopt;
|
||||||
lsLocationEx ret;
|
lsLocationEx ret;
|
||||||
ret.lsLocation::operator=(*ls_loc);
|
ret.lsLocation::operator=(*ls_loc);
|
||||||
if (extension) {
|
if (container) {
|
||||||
EachEntityDef(db, use, [&](const auto& def) {
|
EachEntityDef(db, use, [&](const auto& def) {
|
||||||
ret.containerName = std::string_view(def.detailed_name);
|
ret.containerName = std::string_view(def.detailed_name);
|
||||||
return false;
|
return false;
|
||||||
@ -287,17 +284,15 @@ optional<lsLocationEx> GetLsLocationEx(QueryDatabase* db,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<lsLocation> GetLsLocations(QueryDatabase* db,
|
std::vector<lsLocationEx> GetLsLocationExs(QueryDatabase* db,
|
||||||
WorkingFiles* working_files,
|
WorkingFiles* working_files,
|
||||||
const std::vector<Use>& uses,
|
const std::vector<Use>& uses,
|
||||||
int limit) {
|
bool container,
|
||||||
std::vector<lsLocation> ret;
|
int limit) {
|
||||||
for (Use use : uses) {
|
std::vector<lsLocationEx> ret;
|
||||||
optional<lsLocation> location =
|
for (Use use : uses)
|
||||||
GetLsLocation(db, working_files, use);
|
if (auto loc = GetLsLocationEx(db, working_files, use, container))
|
||||||
if (location)
|
ret.push_back(*loc);
|
||||||
ret.push_back(*location);
|
|
||||||
}
|
|
||||||
std::sort(ret.begin(), ret.end());
|
std::sort(ret.begin(), ret.end());
|
||||||
ret.erase(std::unique(ret.begin(), ret.end()), ret.end());
|
ret.erase(std::unique(ret.begin(), ret.end()), ret.end());
|
||||||
if (ret.size() > limit)
|
if (ret.size() > limit)
|
||||||
@ -311,6 +306,8 @@ optional<lsSymbolInformation> GetSymbolInfo(QueryDatabase* db,
|
|||||||
SymbolIdx sym,
|
SymbolIdx sym,
|
||||||
bool use_short_name) {
|
bool use_short_name) {
|
||||||
switch (sym.kind) {
|
switch (sym.kind) {
|
||||||
|
case SymbolKind::Invalid:
|
||||||
|
break;
|
||||||
case SymbolKind::File: {
|
case SymbolKind::File: {
|
||||||
QueryFile& file = db->GetFile(sym);
|
QueryFile& file = db->GetFile(sym);
|
||||||
if (!file.def)
|
if (!file.def)
|
||||||
@ -321,51 +318,19 @@ optional<lsSymbolInformation> GetSymbolInfo(QueryDatabase* db,
|
|||||||
info.kind = lsSymbolKind::File;
|
info.kind = lsSymbolKind::File;
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
case SymbolKind::Type: {
|
default: {
|
||||||
const QueryType::Def* def = db->GetType(sym).AnyDef();
|
|
||||||
if (!def)
|
|
||||||
break;
|
|
||||||
|
|
||||||
lsSymbolInformation info;
|
lsSymbolInformation info;
|
||||||
if (use_short_name)
|
EachEntityDef(db, sym, [&](const auto& def) {
|
||||||
info.name = def->ShortName();
|
if (use_short_name)
|
||||||
else
|
info.name = def.ShortName();
|
||||||
info.name = def->detailed_name;
|
else
|
||||||
info.kind = def->kind;
|
info.name = def.detailed_name;
|
||||||
if (def->detailed_name.c_str() != def->ShortName())
|
info.kind = def.kind;
|
||||||
info.containerName = def->detailed_name;
|
info.containerName = def.detailed_name;
|
||||||
|
return false;
|
||||||
|
});
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
case SymbolKind::Func: {
|
|
||||||
const QueryFunc::Def* def = db->GetFunc(sym).AnyDef();
|
|
||||||
if (!def)
|
|
||||||
break;
|
|
||||||
|
|
||||||
lsSymbolInformation info;
|
|
||||||
if (use_short_name)
|
|
||||||
info.name = def->ShortName();
|
|
||||||
else
|
|
||||||
info.name = def->detailed_name;
|
|
||||||
info.kind = def->kind;
|
|
||||||
info.containerName = def->detailed_name;
|
|
||||||
return info;
|
|
||||||
}
|
|
||||||
case SymbolKind::Var: {
|
|
||||||
const QueryVar::Def* def = db->GetVar(sym).AnyDef();
|
|
||||||
if (!def)
|
|
||||||
break;
|
|
||||||
|
|
||||||
lsSymbolInformation info;
|
|
||||||
if (use_short_name)
|
|
||||||
info.name = def->ShortName();
|
|
||||||
else
|
|
||||||
info.name = def->detailed_name;
|
|
||||||
info.kind = def->kind;
|
|
||||||
info.containerName = def->detailed_name;
|
|
||||||
return info;
|
|
||||||
}
|
|
||||||
case SymbolKind::Invalid:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullopt;
|
return nullopt;
|
||||||
|
@ -41,11 +41,12 @@ optional<lsLocation> GetLsLocation(QueryDatabase* db,
|
|||||||
optional<lsLocationEx> GetLsLocationEx(QueryDatabase* db,
|
optional<lsLocationEx> GetLsLocationEx(QueryDatabase* db,
|
||||||
WorkingFiles* working_files,
|
WorkingFiles* working_files,
|
||||||
Use use,
|
Use use,
|
||||||
bool extension);
|
bool container);
|
||||||
std::vector<lsLocation> GetLsLocations(QueryDatabase* db,
|
std::vector<lsLocationEx> GetLsLocationExs(QueryDatabase* db,
|
||||||
WorkingFiles* working_files,
|
WorkingFiles* working_files,
|
||||||
const std::vector<Use>& refs,
|
const std::vector<Use>& refs,
|
||||||
int limit);
|
bool container,
|
||||||
|
int limit);
|
||||||
// Returns a symbol. The symbol will have *NOT* have a location assigned.
|
// Returns a symbol. The symbol will have *NOT* have a location assigned.
|
||||||
optional<lsSymbolInformation> GetSymbolInfo(QueryDatabase* db,
|
optional<lsSymbolInformation> GetSymbolInfo(QueryDatabase* db,
|
||||||
WorkingFiles* working_files,
|
WorkingFiles* working_files,
|
||||||
|
14
wscript
14
wscript
@ -83,8 +83,7 @@ def patch_byte_in_libclang(filename, offset, old, new):
|
|||||||
def options(opt):
|
def options(opt):
|
||||||
opt.load('compiler_cxx')
|
opt.load('compiler_cxx')
|
||||||
grp = opt.add_option_group('Configuration options related to use of clang from the system (not recommended)')
|
grp = opt.add_option_group('Configuration options related to use of clang from the system (not recommended)')
|
||||||
grp.add_option('--use-system-clang', dest='use_system_clang', default=False, action='store_true',
|
grp.add_option('--enable-assert', action='store_true')
|
||||||
help='deprecated. Please specify --llvm-config, e.g. /usr/bin/llvm-config llvm-config-6.0')
|
|
||||||
grp.add_option('--use-clang-cxx', dest='use_clang_cxx', default=False, action='store_true',
|
grp.add_option('--use-clang-cxx', dest='use_clang_cxx', default=False, action='store_true',
|
||||||
help='use clang C++ API')
|
help='use clang C++ API')
|
||||||
grp.add_option('--bundled-clang', dest='bundled_clang', default='5.0.1',
|
grp.add_option('--bundled-clang', dest='bundled_clang', default='5.0.1',
|
||||||
@ -188,6 +187,12 @@ def configure(ctx):
|
|||||||
if 'release' in ctx.options.variant:
|
if 'release' in ctx.options.variant:
|
||||||
cxxflags.append('-O' if 'asan' in ctx.options.variant else '-O3')
|
cxxflags.append('-O' if 'asan' in ctx.options.variant else '-O3')
|
||||||
|
|
||||||
|
if ctx.options.enable_assert is None:
|
||||||
|
if 'debug' in ctx.options.variant:
|
||||||
|
ctx.options.enable_assert = True
|
||||||
|
if not ctx.options.enable_assert:
|
||||||
|
ctx.define('NDEBUG', 1)
|
||||||
|
|
||||||
if ctx.env.CXX_NAME == 'clang' and 'debug' in ctx.options.variant:
|
if ctx.env.CXX_NAME == 'clang' and 'debug' in ctx.options.variant:
|
||||||
cxxflags.append('-fno-limit-debug-info')
|
cxxflags.append('-fno-limit-debug-info')
|
||||||
|
|
||||||
@ -208,11 +213,6 @@ def configure(ctx):
|
|||||||
return 'lib' + lib
|
return 'lib' + lib
|
||||||
return lib
|
return lib
|
||||||
|
|
||||||
# TODO remove
|
|
||||||
if ctx.options.use_system_clang:
|
|
||||||
print((('!' * 50)+'\n')*3)
|
|
||||||
print('--use-system-clang is deprecated. Please specify --llvm-config, e.g. /usr/bin/llvm-config llvm-config-6.0')
|
|
||||||
|
|
||||||
# Do not use bundled clang+llvm
|
# Do not use bundled clang+llvm
|
||||||
if ctx.options.llvm_config is not None or ctx.options.clang_prefix is not None:
|
if ctx.options.llvm_config is not None or ctx.options.clang_prefix is not None:
|
||||||
if ctx.options.llvm_config is not None:
|
if ctx.options.llvm_config is not None:
|
||||||
|
Loading…
Reference in New Issue
Block a user