Index namespace alias and MSVC __interface; add --enable-assert to waf; add lexical container to xref requests

This commit is contained in:
Fangrui Song 2018-02-20 20:26:17 -08:00
parent 909c2e247a
commit 1a4da727da
14 changed files with 156 additions and 205 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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