diff --git a/src/clang_symbol_kind.h b/src/clang_symbol_kind.h index 5c433add..c9dcc95e 100644 --- a/src/clang_symbol_kind.h +++ b/src/clang_symbol_kind.h @@ -44,3 +44,20 @@ enum class ClangSymbolKind : uint8_t { MAKE_REFLECT_TYPE_PROXY(ClangSymbolKind, std::underlying_type::type); +// clang/Basic/Specifiers.h clang::StorageClass +enum class ClangStorageClass : uint8_t { + // In |CX_StorageClass| but not in |clang::StorageClass| + SC_Invalid, + + // These are legal on both functions and variables. + SC_None, + SC_Extern, + SC_Static, + SC_PrivateExtern, + + // These are only legal on variables. + SC_Auto, + SC_Register +}; +MAKE_REFLECT_TYPE_PROXY(ClangStorageClass, + std::underlying_type::type); diff --git a/src/indexer.cc b/src/indexer.cc index b666dd79..3d52d0c8 100644 --- a/src/indexer.cc +++ b/src/indexer.cc @@ -109,6 +109,26 @@ ClangSymbolKind GetSymbolKind(CXIdxEntityKind kind) { } } +ClangStorageClass GetStorageClass(CX_StorageClass storage) { + switch (storage) { + case CX_SC_Invalid: + case CX_SC_OpenCLWorkGroupLocal: + return ClangStorageClass::SC_Invalid; + case CX_SC_None: + return ClangStorageClass::SC_None; + case CX_SC_Extern: + return ClangStorageClass::SC_Extern; + case CX_SC_Static: + return ClangStorageClass::SC_Static; + case CX_SC_PrivateExtern: + return ClangStorageClass::SC_PrivateExtern; + case CX_SC_Auto: + return ClangStorageClass::SC_Auto; + case CX_SC_Register: + return ClangStorageClass::SC_Register; + } +} + // Caches all instances of constructors, regardless if they are indexed or not. // The constructor may have a make_unique call associated with it that we need // to export. If we do not capture the parameter type description for the @@ -460,6 +480,7 @@ void SetVarDetail(IndexVar* var, if (type_name.find("(lambda at") != std::string::npos) type_name = "lambda"; def.comments = cursor.get_comments(); + def.storage = GetStorageClass(clang_Cursor_getStorageClass(cursor.cx_cursor)); std::string qualified_name = param->ns.QualifiedName(semanticContainer, def.short_name); @@ -1461,6 +1482,8 @@ void OnIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) { IndexFunc* func = db->Resolve(func_id); func->def.comments = decl_cursor.get_comments(); func->def.kind = GetSymbolKind(decl->entityInfo->kind); + func->def.storage = + GetStorageClass(clang_Cursor_getStorageClass(decl->cursor)); // We don't actually need to know the return type, but we need to mark it // as an interesting usage. diff --git a/src/indexer.h b/src/indexer.h index 73952815..59e87d4a 100644 --- a/src/indexer.h +++ b/src/indexer.h @@ -253,6 +253,7 @@ struct FuncDefDefinitionData { std::string short_name; std::string detailed_name; ClangSymbolKind kind = ClangSymbolKind::Unknown; + ClangStorageClass storage = ClangStorageClass::SC_Invalid; optional hover; optional comments; optional definition_spelling; @@ -304,6 +305,7 @@ void Reflect( REFLECT_MEMBER(short_name); REFLECT_MEMBER(detailed_name); REFLECT_MEMBER(kind); + REFLECT_MEMBER(storage); REFLECT_MEMBER(hover); REFLECT_MEMBER(comments); REFLECT_MEMBER(definition_spelling); @@ -372,6 +374,7 @@ struct VarDefDefinitionData { std::string short_name; std::string detailed_name; ClangSymbolKind kind = ClangSymbolKind::Unknown; + ClangStorageClass storage = ClangStorageClass::SC_Invalid; optional hover; optional comments; optional declaration; @@ -422,6 +425,7 @@ void Reflect(TVisitor& visitor, REFLECT_MEMBER(short_name); REFLECT_MEMBER(detailed_name); REFLECT_MEMBER(kind); + REFLECT_MEMBER(storage); REFLECT_MEMBER(hover); REFLECT_MEMBER(comments); REFLECT_MEMBER(definition_spelling); diff --git a/src/language_server_api.h b/src/language_server_api.h index 1770982f..062dcdcf 100644 --- a/src/language_server_api.h +++ b/src/language_server_api.h @@ -1088,6 +1088,8 @@ struct Out_CqueryPublishSemanticHighlighting // TODO Deprecate |type| in favor of fine-grained |kind|. SymbolType type = SymbolType::Type; ClangSymbolKind kind; + ClangStorageClass storage; + // TODO Deprecate |isTypeMember| in favor of semantic container. bool isTypeMember = false; std::vector ranges; }; @@ -1102,6 +1104,7 @@ MAKE_REFLECT_TYPE_PROXY(Out_CqueryPublishSemanticHighlighting::SymbolType, int); MAKE_REFLECT_STRUCT(Out_CqueryPublishSemanticHighlighting::Symbol, type, kind, + storage, isTypeMember, stableId, ranges); diff --git a/src/message_handler.cc b/src/message_handler.cc index eb69fb67..a32fb9a8 100644 --- a/src/message_handler.cc +++ b/src/message_handler.cc @@ -127,6 +127,7 @@ void EmitSemanticHighlighting(QueryDatabase* db, std::string detailed_name; bool is_type_member = false; ClangSymbolKind kind = ClangSymbolKind::Unknown; + ClangStorageClass storage = ClangStorageClass::SC_Invalid; // This switch statement also filters out symbols that are not highlighted. switch (sym.idx.kind) { case SymbolKind::Func: { @@ -162,6 +163,7 @@ void EmitSemanticHighlighting(QueryDatabase* db, if (!var->def) continue; // applies to for loop kind = var->def->kind; + storage = var->def->storage; is_type_member = var->def->declaring_type.has_value(); detailed_name = var->def->short_name; break; @@ -188,6 +190,7 @@ void EmitSemanticHighlighting(QueryDatabase* db, symbol.stableId = semantic_cache_for_file->GetStableId(sym.idx.kind, detailed_name); symbol.kind = kind; + symbol.storage = storage; symbol.type = map_symbol_kind_to_symbol_type(sym.idx.kind); symbol.isTypeMember = is_type_member; symbol.ranges.push_back(*loc); diff --git a/src/query.cc b/src/query.cc index f35662b7..bdade8b7 100644 --- a/src/query.cc +++ b/src/query.cc @@ -60,6 +60,7 @@ optional ToQuery(const IdMap& id_map, result.short_name = func.short_name; result.detailed_name = func.detailed_name; result.kind = func.kind; + result.storage = func.storage; result.hover = func.hover; result.comments = func.comments; result.definition_spelling = id_map.ToQuery(func.definition_spelling); @@ -80,6 +81,7 @@ optional ToQuery(const IdMap& id_map, const IndexVar::Def& var) { result.short_name = var.short_name; result.detailed_name = var.detailed_name; result.kind = var.kind; + result.storage = var.storage; result.hover = var.hover; result.comments = var.comments; result.declaration = id_map.ToQuery(var.declaration); diff --git a/src/serializer.cc b/src/serializer.cc index 99ec54b6..b68b2f96 100644 --- a/src/serializer.cc +++ b/src/serializer.cc @@ -164,6 +164,7 @@ void Reflect(TVisitor& visitor, IndexFunc& value) { REFLECT_MEMBER2("short_name", value.def.short_name); REFLECT_MEMBER2("detailed_name", value.def.detailed_name); REFLECT_MEMBER2("kind", value.def.kind); + REFLECT_MEMBER2("storage", value.def.storage); REFLECT_MEMBER2("hover", value.def.hover); REFLECT_MEMBER2("comments", value.def.comments); REFLECT_MEMBER2("declarations", value.declarations); @@ -185,6 +186,8 @@ void Reflect(TVisitor& visitor, IndexVar& value) { REFLECT_MEMBER2("usr", value.usr); REFLECT_MEMBER2("short_name", value.def.short_name); REFLECT_MEMBER2("detailed_name", value.def.detailed_name); + REFLECT_MEMBER2("kind", value.def.kind); + REFLECT_MEMBER2("storage", value.def.storage); REFLECT_MEMBER2("hover", value.def.hover); REFLECT_MEMBER2("comments", value.def.comments); REFLECT_MEMBER2("declaration", value.def.declaration); @@ -192,7 +195,6 @@ void Reflect(TVisitor& visitor, IndexVar& value) { REFLECT_MEMBER2("definition_extent", value.def.definition_extent); REFLECT_MEMBER2("variable_type", value.def.variable_type); REFLECT_MEMBER2("declaring_type", value.def.declaring_type); - REFLECT_MEMBER2("kind", value.def.kind); REFLECT_MEMBER2("uses", value.uses); REFLECT_MEMBER_END(); } @@ -325,9 +327,9 @@ std::unique_ptr Deserialize(SerializeFormat format, Reflect(reader, *file); if (file->version != expected_version) return nullptr; - } catch (msgpack::unpack_error& ex) { - LOG_S(ERROR) << "msgpack::unpack_err for '" << path << "' " - << ex.what(); + } catch (std::invalid_argument& e) { + LOG_S(ERROR) << "'" << path << "': failed to deserialize msgpack " + << e.what(); return nullptr; } break;