Add initialization option index.builtin_types for indexing builtin types

Also deprecate enableComments in favor of index.comments

Make $cquery/vars work on variables (by obtaining their types first).
This is currently the only way to list instances of builtin types.
This commit is contained in:
Fangrui Song 2018-01-20 22:34:41 -08:00
parent 619ad11f9e
commit 6acea187c7
6 changed files with 67 additions and 28 deletions

View File

@ -119,18 +119,6 @@ CXCursorKind ClangCursor::get_kind() const {
return cx_cursor.kind; 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 { ClangType ClangCursor::get_type() const {
return ClangType(clang_getCursorType(cx_cursor)); return ClangType(clang_getCursorType(cx_cursor));
} }

View File

@ -51,7 +51,6 @@ class ClangCursor {
bool operator!=(const ClangCursor& rhs) const; bool operator!=(const ClangCursor& rhs) const;
CXCursorKind get_kind() const; CXCursorKind get_kind() const;
ClangCursor get_declaration() const;
ClangType get_type() const; ClangType get_type() const;
std::string get_spelling() const; std::string get_spelling() const;
Range get_spelling_range(CXFile* cx_file = nullptr) const; Range get_spelling_range(CXFile* cx_file = nullptr) const;

View File

@ -91,18 +91,27 @@ struct Config {
// a function or method // a function or method
bool enableSnippetInsertion = true; bool enableSnippetInsertion = true;
// 0: no; 1: Doxygen comment markers; 2: -fparse-all-comments, which includes // TODO Deprecated in favor of index.comments
// plain // /*
int enableComments = 0; int enableComments = 0;
// If true, filter and sort completion response. // If true, filter and sort completion response.
bool filterAndSortCompletionResponse = true; 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 //// For debugging
// Dump AST after parsing if some pattern matches the source filename. // Dump AST after parsing if some pattern matches the source filename.
std::vector<std::string> dumpAST; std::vector<std::string> dumpAST;
}; };
MAKE_REFLECT_STRUCT(Config::Index, builtin_types, comments);
MAKE_REFLECT_STRUCT(Config, MAKE_REFLECT_STRUCT(Config,
compilationDatabaseDirectory, compilationDatabaseDirectory,
cacheDirectory, cacheDirectory,
@ -141,6 +150,8 @@ MAKE_REFLECT_STRUCT(Config,
enableComments, enableComments,
index,
filterAndSortCompletionResponse, filterAndSortCompletionResponse,
dumpAST); dumpAST);

View File

@ -17,6 +17,9 @@
// TODO: See if we can use clang_indexLoc_getFileLocation to get a type ref on // TODO: See if we can use clang_indexLoc_getFileLocation to get a type ref on
// |Foobar| in DISALLOW_COPY(Foobar) // |Foobar| in DISALLOW_COPY(Foobar)
// TODO Global variable
bool g_index_builtin_types;
namespace { namespace {
constexpr bool kIndexStdDeclarations = true; constexpr bool kIndexStdDeclarations = true;
@ -393,13 +396,35 @@ bool IsFunctionCallContext(CXCursorKind kind) {
// (ie, Foo<A,B> => Foo<*,*>). // (ie, Foo<A,B> => Foo<*,*>).
optional<IndexTypeId> ResolveToDeclarationType(IndexFile* db, optional<IndexTypeId> ResolveToDeclarationType(IndexFile* db,
ClangCursor cursor) { ClangCursor cursor) {
ClangCursor declaration = cursor.get_declaration(); ClangType type = cursor.get_type();
declaration = declaration.template_specialization_to_template_definition();
// TODO optimize // auto x = new Foo() will not be deduced to |Foo| if we do not use the
std::string usr = declaration.get_usr(); // canonical type. However, a canonical type will look past typedefs so we
if (usr.size()) // will not accurately report variables on typedefs if we always do this.
return db->ToTypeId(declaration.get_usr_hash()); if (type.cx_type.kind == CXType_Auto)
return nullopt; 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, void SetVarDetail(IndexVar* var,

View File

@ -25,11 +25,24 @@ struct CqueryVarsHandler : BaseMessageHandler<Ipc_CqueryVars> {
out.id = request->id; out.id = request->id;
for (const SymbolRef& ref : for (const SymbolRef& ref :
FindSymbolsAtLocation(working_file, file, request->params.position)) { FindSymbolsAtLocation(working_file, file, request->params.position)) {
if (ref.idx.kind == SymbolKind::Type) { size_t id = ref.idx.idx;
QueryType& type = db->types[ref.idx.idx]; switch (ref.idx.kind) {
std::vector<QueryLocation> locations = default:
ToQueryLocation(db, type.instances); break;
out.result = GetLsLocations(db, working_files, locations); 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<QueryLocation> locations =
ToQueryLocation(db, type.instances);
out.result = GetLsLocations(db, working_files, locations);
break;
}
} }
} }
QueueManager::WriteStdout(IpcId::CqueryVars, out); QueueManager::WriteStdout(IpcId::CqueryVars, out);

View File

@ -14,6 +14,7 @@
// TODO Cleanup global variables // TODO Cleanup global variables
extern std::string g_init_options; extern std::string g_init_options;
extern bool g_index_builtin_types;
extern int g_enable_comments; extern int g_enable_comments;
namespace { namespace {
@ -74,7 +75,9 @@ struct InitializeHandler : BaseMessageHandler<Ipc_InitializeRequest> {
} }
} }
} }
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. // Check client version.
if (config->clientVersion.has_value() && if (config->clientVersion.has_value() &&