diff --git a/src/clang_cursor.cc b/src/clang_cursor.cc index 7a1eb14f..612b7475 100644 --- a/src/clang_cursor.cc +++ b/src/clang_cursor.cc @@ -119,18 +119,6 @@ CXCursorKind ClangCursor::get_kind() const { return cx_cursor.kind; } -ClangCursor ClangCursor::get_declaration() const { - ClangType type = get_type(); - - // auto x = new Foo() will not be deduced to |Foo| if we do not use the - // canonical type. However, a canonical type will look past typedefs so we - // will not accurately report variables on typedefs if we always do this. - if (type.cx_type.kind == CXType_Auto) - type = type.get_canonical(); - - return type.strip_qualifiers().get_declaration(); -} - ClangType ClangCursor::get_type() const { return ClangType(clang_getCursorType(cx_cursor)); } diff --git a/src/clang_cursor.h b/src/clang_cursor.h index 3f0a33dc..b39289dd 100644 --- a/src/clang_cursor.h +++ b/src/clang_cursor.h @@ -51,7 +51,6 @@ class ClangCursor { bool operator!=(const ClangCursor& rhs) const; CXCursorKind get_kind() const; - ClangCursor get_declaration() const; ClangType get_type() const; std::string get_spelling() const; Range get_spelling_range(CXFile* cx_file = nullptr) const; diff --git a/src/config.h b/src/config.h index 3d3088d9..5f65f49b 100644 --- a/src/config.h +++ b/src/config.h @@ -91,18 +91,27 @@ struct Config { // a function or method bool enableSnippetInsertion = true; - // 0: no; 1: Doxygen comment markers; 2: -fparse-all-comments, which includes - // plain // /* + // TODO Deprecated in favor of index.comments int enableComments = 0; // If true, filter and sort completion response. bool filterAndSortCompletionResponse = true; + struct Index { + bool builtin_types = false; + + // 0: no; 1: Doxygen comment markers; 2: -fparse-all-comments, which includes + // plain // /* + int comments = 0; + }; + Index index; + //// For debugging // Dump AST after parsing if some pattern matches the source filename. std::vector dumpAST; }; +MAKE_REFLECT_STRUCT(Config::Index, builtin_types, comments); MAKE_REFLECT_STRUCT(Config, compilationDatabaseDirectory, cacheDirectory, @@ -141,6 +150,8 @@ MAKE_REFLECT_STRUCT(Config, enableComments, + index, + filterAndSortCompletionResponse, dumpAST); diff --git a/src/indexer.cc b/src/indexer.cc index e2457444..7fe0fb9b 100644 --- a/src/indexer.cc +++ b/src/indexer.cc @@ -17,6 +17,9 @@ // TODO: See if we can use clang_indexLoc_getFileLocation to get a type ref on // |Foobar| in DISALLOW_COPY(Foobar) +// TODO Global variable +bool g_index_builtin_types; + namespace { constexpr bool kIndexStdDeclarations = true; @@ -393,13 +396,35 @@ bool IsFunctionCallContext(CXCursorKind kind) { // (ie, Foo => Foo<*,*>). optional ResolveToDeclarationType(IndexFile* db, ClangCursor cursor) { - ClangCursor declaration = cursor.get_declaration(); - declaration = declaration.template_specialization_to_template_definition(); - // TODO optimize - std::string usr = declaration.get_usr(); - if (usr.size()) - return db->ToTypeId(declaration.get_usr_hash()); - return nullopt; + ClangType type = cursor.get_type(); + + // auto x = new Foo() will not be deduced to |Foo| if we do not use the + // canonical type. However, a canonical type will look past typedefs so we + // will not accurately report variables on typedefs if we always do this. + if (type.cx_type.kind == CXType_Auto) + type = type.get_canonical(); + + type = type.strip_qualifiers(); + + if (CXType_FirstBuiltin <= type.cx_type.kind && + type.cx_type.kind <= CXType_LastBuiltin) { + if (!g_index_builtin_types) + return nullopt; + return db->ToTypeId(type.cx_type.kind); + } + + ClangCursor declaration = + ClangCursor(type.get_declaration()) + .template_specialization_to_template_definition(); + CXString cx_usr = clang_getCursorUSR(declaration.cx_cursor); + const char* str_usr = clang_getCString(cx_usr); + if (!str_usr || str_usr[0] == '\0') { + clang_disposeString(cx_usr); + return nullopt; + } + Usr usr = HashUsr(str_usr); + clang_disposeString(cx_usr); + return db->ToTypeId(usr); } void SetVarDetail(IndexVar* var, diff --git a/src/messages/cquery_vars.cc b/src/messages/cquery_vars.cc index 255a138f..c6521b85 100644 --- a/src/messages/cquery_vars.cc +++ b/src/messages/cquery_vars.cc @@ -25,11 +25,24 @@ struct CqueryVarsHandler : BaseMessageHandler { out.id = request->id; for (const SymbolRef& ref : FindSymbolsAtLocation(working_file, file, request->params.position)) { - if (ref.idx.kind == SymbolKind::Type) { - QueryType& type = db->types[ref.idx.idx]; - std::vector locations = - ToQueryLocation(db, type.instances); - out.result = GetLsLocations(db, working_files, locations); + size_t id = ref.idx.idx; + switch (ref.idx.kind) { + default: + break; + case SymbolKind::Var: { + QueryVar& var = db->vars[id]; + if (!var.def || !var.def->variable_type) + continue; + id = var.def->variable_type->id; + } + // fallthrough + case SymbolKind::Type: { + QueryType& type = db->types[id]; + std::vector locations = + ToQueryLocation(db, type.instances); + out.result = GetLsLocations(db, working_files, locations); + break; + } } } QueueManager::WriteStdout(IpcId::CqueryVars, out); diff --git a/src/messages/initialize.cc b/src/messages/initialize.cc index d4904fd6..6a63bcb7 100644 --- a/src/messages/initialize.cc +++ b/src/messages/initialize.cc @@ -14,6 +14,7 @@ // TODO Cleanup global variables extern std::string g_init_options; +extern bool g_index_builtin_types; extern int g_enable_comments; namespace { @@ -74,7 +75,9 @@ struct InitializeHandler : BaseMessageHandler { } } } - g_enable_comments = config->enableComments; + g_index_builtin_types = config->index.builtin_types; + // TODO Remove enableComments + g_enable_comments = std::max(config->enableComments, config->index.comments); // Check client version. if (config->clientVersion.has_value() &&