[indexer] Make hover optional (#176)

On textDocument/hover requests, return `detailed_name` if `hover` is unavailable
Don't include leading `type_name` in `detailed_name` for CXIdxEntityEnumConstant, i.e. `Foo Foo::a` -> `Foo::a`
This commit is contained in:
Fangrui Song 2017-12-22 14:48:55 -08:00 committed by GitHub
parent ba4a5e91cb
commit c3c0feecb2
3 changed files with 34 additions and 18 deletions

View File

@ -61,6 +61,9 @@ bool IsLocalSemanticContainer(CXCursorKind kind) {
case CXCursor_UnionDecl: case CXCursor_UnionDecl:
case CXCursor_ClassDecl: case CXCursor_ClassDecl:
case CXCursor_EnumDecl: case CXCursor_EnumDecl:
// TODO Add more Objective-C containers
case CXCursor_ObjCInterfaceDecl:
case CXCursor_ObjCImplementationDecl:
return false; return false;
default: default:
return true; return true;
@ -87,7 +90,8 @@ struct NamespaceHelper {
ClangCursor cursor = container->cursor; ClangCursor cursor = container->cursor;
std::vector<ClangCursor> namespaces; std::vector<ClangCursor> namespaces;
std::string qualifier; std::string qualifier;
while (cursor.get_kind() != CXCursor_TranslationUnit) { while (cursor.get_kind() != CXCursor_TranslationUnit &&
!IsLocalSemanticContainer(cursor.get_kind())) {
auto it = container_cursor_to_qualified_name.find(cursor); auto it = container_cursor_to_qualified_name.find(cursor);
if (it != container_cursor_to_qualified_name.end()) { if (it != container_cursor_to_qualified_name.end()) {
qualifier = it->second; qualifier = it->second;
@ -99,6 +103,8 @@ struct NamespaceHelper {
for (size_t i = namespaces.size(); i > 0; ) { for (size_t i = namespaces.size(); i > 0; ) {
i--; i--;
std::string name = namespaces[i].get_spelling(); std::string name = namespaces[i].get_spelling();
// Empty name indicates unnamed namespace, anonymous struct, anonymous
// union, ...
qualifier += name.empty() ? "(anon)" : name; qualifier += name.empty() ? "(anon)" : name;
qualifier += "::"; qualifier += "::";
container_cursor_to_qualified_name[namespaces[i]] = qualifier; container_cursor_to_qualified_name[namespaces[i]] = qualifier;
@ -1031,10 +1037,14 @@ void OnIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
if (type_name.find("(lambda at") != std::string::npos) if (type_name.find("(lambda at") != std::string::npos)
type_name = "lambda"; type_name = "lambda";
var->def.detailed_name = {
type_name + " " + std::string qualified_name =
ns->QualifiedName(decl->semanticContainer, var->def.short_name); ns->QualifiedName(decl->semanticContainer, var->def.short_name);
var->def.hover = type_name; if (decl->entityInfo->kind == CXIdxEntity_EnumConstant)
var->def.detailed_name = std::move(qualified_name);
else
var->def.detailed_name = type_name + " " + std::move(qualified_name);
}
var->def.is_local = var->def.is_local =
!decl->semanticContainer || !decl->semanticContainer ||
@ -1258,11 +1268,10 @@ void OnIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
type->def.detailed_name = type->def.detailed_name =
ns->QualifiedName(decl->semanticContainer, type->def.short_name); ns->QualifiedName(decl->semanticContainer, type->def.short_name);
type->def.hover = type->def.detailed_name;
// For Typedef/CXXTypeAlias spanning a few lines, display the declaration line, // For Typedef/CXXTypeAlias spanning a few lines, display the declaration line,
// with spelling name replaced with qualified name. // with spelling name replaced with qualified name.
// TODO Think how to display multi-line declaration like `typedef struct { ... } foo;` // TODO Think how to display multi-line declaration like `typedef struct { ... } foo;`
// https://github.com/jacobdufault/cquery/issues/29
if (extent.end.line - extent.start.line < if (extent.end.line - extent.start.line <
kMaxLinesDisplayTypeAliasDeclarations) { kMaxLinesDisplayTypeAliasDeclarations) {
FileContentsWithOffsets& fc = param->file_contents[db->path]; FileContentsWithOffsets& fc = param->file_contents[db->path];
@ -1312,7 +1321,6 @@ void OnIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
type->def.detailed_name = type->def.detailed_name =
ns->QualifiedName(decl->semanticContainer, type->def.short_name); ns->QualifiedName(decl->semanticContainer, type->def.short_name);
type->def.hover = type->def.detailed_name;
// } // }
if (decl->isDefinition) { if (decl->isDefinition) {
@ -1445,7 +1453,6 @@ void OnIndexReference(CXClientData client_data, const CXIdxEntityRefInfo* ref) {
std::string type_name = ToString( std::string type_name = ToString(
clang_getTypeSpelling(clang_getCursorType(referenced.cx_cursor))); clang_getTypeSpelling(clang_getCursorType(referenced.cx_cursor)));
var->def.detailed_name = type_name + " " + var->def.short_name; var->def.detailed_name = type_name + " " + var->def.short_name;
var->def.hover = type_name;
var->def.is_local = false; var->def.is_local = false;
UniqueAdd(var->uses, ResolveSpelling(referenced.cx_cursor)); UniqueAdd(var->uses, ResolveSpelling(referenced.cx_cursor));
AddDeclInitializerUsages(db, referenced.cx_cursor); AddDeclInitializerUsages(db, referenced.cx_cursor);

View File

@ -149,7 +149,7 @@ struct TypeDefDefinitionData {
// General metadata. // General metadata.
std::string short_name; std::string short_name;
std::string detailed_name; std::string detailed_name;
std::string hover; optional<std::string> hover;
// While a class/type can technically have a separate declaration/definition, // While a class/type can technically have a separate declaration/definition,
// it doesn't really happen in practice. The declaration never contains // it doesn't really happen in practice. The declaration never contains
@ -247,7 +247,7 @@ struct FuncDefDefinitionData {
// General metadata. // General metadata.
std::string short_name; std::string short_name;
std::string detailed_name; std::string detailed_name;
std::string hover; optional<std::string> hover;
optional<Range> definition_spelling; optional<Range> definition_spelling;
optional<Range> definition_extent; optional<Range> definition_extent;
@ -362,7 +362,7 @@ struct VarDefDefinitionData {
// General metadata. // General metadata.
std::string short_name; std::string short_name;
std::string detailed_name; std::string detailed_name;
std::string hover; optional<std::string> hover;
optional<Range> declaration; optional<Range> declaration;
// TODO: definitions should be a list of ranges, since there can be more // TODO: definitions should be a list of ranges, since there can be more
// than one - when?? // than one - when??

View File

@ -7,20 +7,29 @@ std::string GetHoverForSymbol(QueryDatabase* db, const SymbolIdx& symbol) {
switch (symbol.kind) { switch (symbol.kind) {
case SymbolKind::Type: { case SymbolKind::Type: {
QueryType& type = db->types[symbol.idx]; QueryType& type = db->types[symbol.idx];
if (type.def) if (type.def) {
return type.def->hover; if (type.def->hover)
return *type.def->hover;
return type.def->detailed_name;
}
break; break;
} }
case SymbolKind::Func: { case SymbolKind::Func: {
QueryFunc& func = db->funcs[symbol.idx]; QueryFunc& func = db->funcs[symbol.idx];
if (func.def) if (func.def) {
return func.def->hover; if (func.def->hover)
return *func.def->hover;
return func.def->detailed_name;
}
break; break;
} }
case SymbolKind::Var: { case SymbolKind::Var: {
QueryVar& var = db->vars[symbol.idx]; QueryVar& var = db->vars[symbol.idx];
if (var.def) if (var.def) {
return var.def->hover; if (var.def->hover)
return *var.def->hover;
return var.def->detailed_name;
}
break; break;
} }
case SymbolKind::File: case SymbolKind::File: