diff --git a/cmake/FindClang.cmake b/cmake/FindClang.cmake index ad085d48..6bfac108 100644 --- a/cmake/FindClang.cmake +++ b/cmake/FindClang.cmake @@ -69,11 +69,15 @@ set(_Clang_REQUIRED_VARS Clang_LIBRARY Clang_INCLUDE_DIR Clang_EXECUTABLE LLVM_INCLUDE_DIR LLVM_BUILD_INCLUDE_DIR) _Clang_find_library(Clang_LIBRARY clang) +_Clang_find_add_library(clangAST) +_Clang_find_add_library(clangLex) _Clang_find_add_library(clangDriver) _Clang_find_add_library(clangBasic) if(USE_SHARED_LLVM) _Clang_find_add_library(LLVM) else() + _Clang_find_add_library(LLVMCore) + _Clang_find_add_library(LLVMBinaryFormat) _Clang_find_add_library(LLVMOption) _Clang_find_add_library(LLVMSupport) _Clang_find_add_library(LLVMDemangle) diff --git a/src/config.cc b/src/config.cc index 102d05a6..27fac9c4 100644 --- a/src/config.cc +++ b/src/config.cc @@ -1,4 +1,4 @@ #include "config.h" -std::unique_ptr g_config; +Config* g_config; thread_local int g_thread_id; diff --git a/src/config.h b/src/config.h index 58946bac..114f0c66 100644 --- a/src/config.h +++ b/src/config.h @@ -2,7 +2,6 @@ #include "serializer.h" -#include #include /* @@ -192,6 +191,9 @@ struct Config { std::vector whitelist; } index; + // Disable semantic highlighting for files larger than the size. + int64_t largeFileSize = 2 * 1024 * 1024; + struct WorkspaceSymbol { int caseSensitivity = 1; // Maximum workspace search results. @@ -252,8 +254,9 @@ MAKE_REFLECT_STRUCT(Config, diagnostics, highlight, index, + largeFileSize, workspaceSymbol, xref); -extern std::unique_ptr g_config; +extern Config* g_config; thread_local extern int g_thread_id; diff --git a/src/indexer.cc b/src/indexer.cc index de393f9c..e714a6c2 100644 --- a/src/indexer.cc +++ b/src/indexer.cc @@ -5,7 +5,9 @@ #include "serializer.h" #include "type_printer.h" +#include #include +using namespace clang; using namespace llvm; #include @@ -151,26 +153,24 @@ lsSymbolKind GetSymbolKind(CXIdxEntityKind kind) { return lsSymbolKind::Unknown; } -StorageClass GetStorageClass(CX_StorageClass storage) { +StorageClass GetStorageC(CX_StorageClass storage) { switch (storage) { + default: case CX_SC_Invalid: case CX_SC_OpenCLWorkGroupLocal: - return StorageClass::Invalid; case CX_SC_None: - return StorageClass::None; + return SC_None; case CX_SC_Extern: - return StorageClass::Extern; + return SC_Extern; case CX_SC_Static: - return StorageClass::Static; + return SC_Static; case CX_SC_PrivateExtern: - return StorageClass::PrivateExtern; + return SC_PrivateExtern; case CX_SC_Auto: - return StorageClass::Auto; + return SC_Auto; case CX_SC_Register: - return StorageClass::Register; + return SC_Register; } - - return StorageClass::None; } // Caches all instances of constructors, regardless if they are indexed or not. @@ -583,7 +583,7 @@ void SetVarDetail(IndexVar& var, type_name = "lambda"; if (g_config->index.comments) def.comments = cursor.get_comments(); - def.storage = GetStorageClass(clang_Cursor_getStorageClass(cursor.cx_cursor)); + def.storage = GetStorageC(clang_Cursor_getStorageClass(cursor.cx_cursor)); // TODO how to make PrettyPrint'ed variable name qualified? #if 0 && CINDEX_HAVE_PRETTY @@ -1526,7 +1526,7 @@ void OnIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) { func.def.comments = cursor.get_comments(); func.def.kind = GetSymbolKind(decl->entityInfo->kind); func.def.storage = - GetStorageClass(clang_Cursor_getStorageClass(decl->cursor)); + GetStorageC(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. @@ -1536,11 +1536,13 @@ void OnIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) { // Add definition or declaration. This is a bit tricky because we treat // template specializations as declarations, even though they are // technically definitions. - // TODO: Support multiple function definitions, which is common for - // template specializations. - if (decl->isDefinition && !is_template_specialization) { - // assert(!func->def.spell); - // assert(!func->def.extent); + bool is_def = decl->isDefinition; + if (!is_def) { + auto* D = static_cast(decl->cursor.data[0]); + auto* Method = dyn_cast_or_null(D->getAsFunction()); + is_def = Method && (Method->isDefaulted() || Method->isPure()); + } + if (is_def && !is_template_specialization) { func.def.spell = SetUse(db, spell, sem_parent, Role::Definition); func.def.extent = SetUse(db, extent, lex_parent, Role::None); } else { diff --git a/src/indexer.h b/src/indexer.h index 70619e9d..156f7c66 100644 --- a/src/indexer.h +++ b/src/indexer.h @@ -12,6 +12,7 @@ #include "symbol.h" #include "utils.h" +#include #include #include @@ -62,6 +63,8 @@ struct Use : Reference { void Reflect(Reader& visitor, Reference& value); void Reflect(Writer& visitor, Reference& value); +MAKE_REFLECT_TYPE_PROXY2(clang::StorageClass, uint8_t); + template struct NameMixin { std::string_view Name(bool qualified) const { @@ -99,7 +102,7 @@ struct FuncDef : NameMixin { int16_t short_name_offset = 0; int16_t short_name_size = 0; lsSymbolKind kind = lsSymbolKind::Unknown; - StorageClass storage = StorageClass::Invalid; + clang::StorageClass storage = clang::SC_None; std::vector GetBases() const { return bases; } bool operator==(const FuncDef& o) const { @@ -213,11 +216,11 @@ struct VarDef : NameMixin { lsSymbolKind kind = lsSymbolKind::Unknown; // Note a variable may have instances of both |None| and |Extern| // (declaration). - StorageClass storage = StorageClass::Invalid; + clang::StorageClass storage = clang::SC_None; bool is_local() const { return spell && spell->kind != SymbolKind::File && - storage == StorageClass::None; + storage == clang::SC_None; } std::vector GetBases() const { return {}; } diff --git a/src/message_handler.cc b/src/message_handler.cc index 168fa605..60aea634 100644 --- a/src/message_handler.cc +++ b/src/message_handler.cc @@ -6,6 +6,8 @@ #include "pipeline.hh" using namespace ccls; +using namespace clang; + #include MAKE_HASHABLE(SymbolIdx, t.usr, t.kind); @@ -187,10 +189,11 @@ void EmitInactiveLines(WorkingFile* working_file, void EmitSemanticHighlighting(DB* db, SemanticHighlightSymbolCache* semantic_cache, - WorkingFile* working_file, + WorkingFile* wfile, QueryFile* file) { assert(file->def); - if (!semantic_cache->match_->IsMatch(file->def->path)) + if (wfile->buffer_content.size() > g_config->largeFileSize || + !semantic_cache->match_->IsMatch(file->def->path)) return; auto semantic_cache_for_file = semantic_cache->GetCacheForFile(file->def->path); @@ -202,7 +205,7 @@ void EmitSemanticHighlighting(DB* db, std::string_view detailed_name; lsSymbolKind parent_kind = lsSymbolKind::Unknown; lsSymbolKind kind = lsSymbolKind::Unknown; - StorageClass storage = StorageClass::Invalid; + StorageClass storage = SC_None; // This switch statement also filters out symbols that are not highlighted. switch (sym.kind) { case SymbolKind::Func: { @@ -237,9 +240,9 @@ void EmitSemanticHighlighting(DB* db, detailed_name.substr(0, detailed_name.find('<')); int16_t start_line = sym.range.start.line; int16_t start_col = sym.range.start.column; - if (start_line < 0 || start_line >= working_file->index_lines.size()) + if (start_line < 0 || start_line >= wfile->index_lines.size()) continue; - std::string_view line = working_file->index_lines[start_line]; + std::string_view line = wfile->index_lines[start_line]; sym.range.end.line = start_line; if (!(start_col + concise_name.size() <= line.size() && line.compare(start_col, concise_name.size(), concise_name) == 0)) @@ -280,7 +283,7 @@ void EmitSemanticHighlighting(DB* db, continue; // applies to for loop } - std::optional loc = GetLsRange(working_file, sym.range); + std::optional loc = GetLsRange(wfile, sym.range); if (loc) { auto it = grouped_symbols.find(sym); if (it != grouped_symbols.end()) { @@ -339,7 +342,7 @@ void EmitSemanticHighlighting(DB* db, // Publish. Out_CclsPublishSemanticHighlighting out; - out.params.uri = lsDocumentUri::FromPath(working_file->filename); + out.params.uri = lsDocumentUri::FromPath(wfile->filename); for (auto& entry : grouped_symbols) if (entry.second.ranges.size()) out.params.symbols.push_back(entry.second); diff --git a/src/message_handler.h b/src/message_handler.h index f73dc483..64e73e57 100644 --- a/src/message_handler.h +++ b/src/message_handler.h @@ -63,7 +63,7 @@ struct Out_CclsPublishSemanticHighlighting int stableId = 0; lsSymbolKind parentKind; lsSymbolKind kind; - StorageClass storage; + clang::StorageClass storage; std::vector ranges; }; struct Params { diff --git a/src/messages/ccls_call_hierarchy.cc b/src/messages/ccls_call_hierarchy.cc index bff5ca84..92267d83 100644 --- a/src/messages/ccls_call_hierarchy.cc +++ b/src/messages/ccls_call_hierarchy.cc @@ -95,7 +95,7 @@ bool Expand(MessageHandler* m, entry->numChildren = 0; if (!def) return false; - auto handle = [&](Use use, CallType call_type) { + auto handle = [&](Use use, CallType call_type1) { entry->numChildren++; if (levels > 0) { Out_CclsCallHierarchy::Entry entry1; @@ -103,7 +103,7 @@ bool Expand(MessageHandler* m, entry1.usr = use.usr; if (auto loc = GetLsLocation(m->db, m->working_files, use)) entry1.location = *loc; - entry1.callType = call_type; + entry1.callType = call_type1; if (Expand(m, &entry1, callee, call_type, qualified, levels - 1)) entry->children.push_back(std::move(entry1)); } diff --git a/src/messages/initialize.cc b/src/messages/initialize.cc index 4045eda8..02d6c1db 100644 --- a/src/messages/initialize.cc +++ b/src/messages/initialize.cc @@ -438,9 +438,9 @@ struct Handler_Initialize : BaseMessageHandler { { if (params.initializationOptions) - g_config = std::make_unique(*params.initializationOptions); + g_config = new Config(*params.initializationOptions); else - g_config = std::make_unique(); + g_config = new Config; rapidjson::Document reader; reader.Parse(g_init_options.c_str()); if (!reader.HasParseError()) { diff --git a/src/messages/text_document_document_symbol.cc b/src/messages/text_document_document_symbol.cc index 959328e3..212994cd 100644 --- a/src/messages/text_document_document_symbol.cc +++ b/src/messages/text_document_document_symbol.cc @@ -2,6 +2,7 @@ #include "pipeline.hh" #include "query_utils.h" using namespace ccls; +using namespace clang; namespace { MethodType kMethodType = "textDocument/documentSymbol"; @@ -51,9 +52,8 @@ struct Handler_TextDocumentDocumentSymbol if (!def || !def->spell) continue; // Ignore local variables. - if (def->spell->kind == SymbolKind::Func && - def->storage != StorageClass::Static && - def->storage != StorageClass::Extern) + if (def->spell->kind == SymbolKind::Func && def->storage != SC_Static && + def->storage != SC_Extern) continue; } diff --git a/src/project.cc b/src/project.cc index 74c82080..0ff3193a 100644 --- a/src/project.cc +++ b/src/project.cc @@ -450,7 +450,9 @@ TEST_SUITE("Project") { void CheckFlags(const std::string& directory, const std::string& file, std::vector raw, std::vector expected) { - g_config = std::make_unique(); + if (g_config) + delete g_config; + g_config = new Config; g_config->clang.resourceDir = "/w/resource_dir/"; ProjectConfig project; project.project_dir = "/w/c/s/"; @@ -536,7 +538,9 @@ TEST_SUITE("Project") { } TEST_CASE("Directory extraction") { - g_config = std::make_unique(); + if (g_config) + delete g_config; + g_config = new Config; ProjectConfig config; config.project_dir = "/w/c/s/"; diff --git a/src/symbol.h b/src/symbol.h index 13b9f39a..3a79ba07 100644 --- a/src/symbol.h +++ b/src/symbol.h @@ -8,27 +8,6 @@ enum class SymbolKind : uint8_t { Invalid, File, Type, Func, Var }; MAKE_REFLECT_TYPE_PROXY(SymbolKind); -// clang/Basic/Specifiers.h clang::StorageClass -enum class StorageClass : uint8_t { - // In |CX_StorageClass| but not in |clang::StorageClass| - // e.g. non-type template parameters - Invalid, - - // These are legal on both functions and variables. - // e.g. global functions/variables, local variables - None, - Extern, - Static, - // e.g. |__private_extern__ int a;| - PrivateExtern, - - // These are only legal on variables. - // e.g. explicit |auto int a;| - Auto, - Register -}; -MAKE_REFLECT_TYPE_PROXY(StorageClass); - enum class Role : uint16_t { None = 0, Declaration = 1 << 0, diff --git a/src/test.cc b/src/test.cc index f3001f6c..c9dff5cf 100644 --- a/src/test.cc +++ b/src/test.cc @@ -288,7 +288,7 @@ bool RunIndexTests(const std::string& filter_path, bool enable_update) { flags.push_back(path); // Run test. - g_config = std::make_unique(); + g_config = new Config; VFS vfs; auto dbs = index.Index(&vfs, path, flags, {});