Add Config->largeFileSize; pure virtual or defaulted methods are definitions; fix $ccls/callHierarchy

This commit is contained in:
Fangrui Song 2018-06-01 14:22:55 -07:00
parent f0559bba54
commit 806a05b234
13 changed files with 60 additions and 62 deletions

View File

@ -69,11 +69,15 @@ set(_Clang_REQUIRED_VARS Clang_LIBRARY Clang_INCLUDE_DIR Clang_EXECUTABLE
LLVM_INCLUDE_DIR LLVM_BUILD_INCLUDE_DIR) LLVM_INCLUDE_DIR LLVM_BUILD_INCLUDE_DIR)
_Clang_find_library(Clang_LIBRARY clang) _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(clangDriver)
_Clang_find_add_library(clangBasic) _Clang_find_add_library(clangBasic)
if(USE_SHARED_LLVM) if(USE_SHARED_LLVM)
_Clang_find_add_library(LLVM) _Clang_find_add_library(LLVM)
else() else()
_Clang_find_add_library(LLVMCore)
_Clang_find_add_library(LLVMBinaryFormat)
_Clang_find_add_library(LLVMOption) _Clang_find_add_library(LLVMOption)
_Clang_find_add_library(LLVMSupport) _Clang_find_add_library(LLVMSupport)
_Clang_find_add_library(LLVMDemangle) _Clang_find_add_library(LLVMDemangle)

View File

@ -1,4 +1,4 @@
#include "config.h" #include "config.h"
std::unique_ptr<Config> g_config; Config* g_config;
thread_local int g_thread_id; thread_local int g_thread_id;

View File

@ -2,7 +2,6 @@
#include "serializer.h" #include "serializer.h"
#include <memory>
#include <string> #include <string>
/* /*
@ -192,6 +191,9 @@ struct Config {
std::vector<std::string> whitelist; std::vector<std::string> whitelist;
} index; } index;
// Disable semantic highlighting for files larger than the size.
int64_t largeFileSize = 2 * 1024 * 1024;
struct WorkspaceSymbol { struct WorkspaceSymbol {
int caseSensitivity = 1; int caseSensitivity = 1;
// Maximum workspace search results. // Maximum workspace search results.
@ -252,8 +254,9 @@ MAKE_REFLECT_STRUCT(Config,
diagnostics, diagnostics,
highlight, highlight,
index, index,
largeFileSize,
workspaceSymbol, workspaceSymbol,
xref); xref);
extern std::unique_ptr<Config> g_config; extern Config* g_config;
thread_local extern int g_thread_id; thread_local extern int g_thread_id;

View File

@ -5,7 +5,9 @@
#include "serializer.h" #include "serializer.h"
#include "type_printer.h" #include "type_printer.h"
#include <clang/AST/AST.h>
#include <llvm/Support/Timer.h> #include <llvm/Support/Timer.h>
using namespace clang;
using namespace llvm; using namespace llvm;
#include <assert.h> #include <assert.h>
@ -151,26 +153,24 @@ lsSymbolKind GetSymbolKind(CXIdxEntityKind kind) {
return lsSymbolKind::Unknown; return lsSymbolKind::Unknown;
} }
StorageClass GetStorageClass(CX_StorageClass storage) { StorageClass GetStorageC(CX_StorageClass storage) {
switch (storage) { switch (storage) {
default:
case CX_SC_Invalid: case CX_SC_Invalid:
case CX_SC_OpenCLWorkGroupLocal: case CX_SC_OpenCLWorkGroupLocal:
return StorageClass::Invalid;
case CX_SC_None: case CX_SC_None:
return StorageClass::None; return SC_None;
case CX_SC_Extern: case CX_SC_Extern:
return StorageClass::Extern; return SC_Extern;
case CX_SC_Static: case CX_SC_Static:
return StorageClass::Static; return SC_Static;
case CX_SC_PrivateExtern: case CX_SC_PrivateExtern:
return StorageClass::PrivateExtern; return SC_PrivateExtern;
case CX_SC_Auto: case CX_SC_Auto:
return StorageClass::Auto; return SC_Auto;
case CX_SC_Register: 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. // Caches all instances of constructors, regardless if they are indexed or not.
@ -583,7 +583,7 @@ void SetVarDetail(IndexVar& var,
type_name = "lambda"; type_name = "lambda";
if (g_config->index.comments) if (g_config->index.comments)
def.comments = cursor.get_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? // TODO how to make PrettyPrint'ed variable name qualified?
#if 0 && CINDEX_HAVE_PRETTY #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.comments = cursor.get_comments();
func.def.kind = GetSymbolKind(decl->entityInfo->kind); func.def.kind = GetSymbolKind(decl->entityInfo->kind);
func.def.storage = 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 // We don't actually need to know the return type, but we need to mark it
// as an interesting usage. // 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 // Add definition or declaration. This is a bit tricky because we treat
// template specializations as declarations, even though they are // template specializations as declarations, even though they are
// technically definitions. // technically definitions.
// TODO: Support multiple function definitions, which is common for bool is_def = decl->isDefinition;
// template specializations. if (!is_def) {
if (decl->isDefinition && !is_template_specialization) { auto* D = static_cast<const Decl*>(decl->cursor.data[0]);
// assert(!func->def.spell); auto* Method = dyn_cast_or_null<CXXMethodDecl>(D->getAsFunction());
// assert(!func->def.extent); 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.spell = SetUse(db, spell, sem_parent, Role::Definition);
func.def.extent = SetUse(db, extent, lex_parent, Role::None); func.def.extent = SetUse(db, extent, lex_parent, Role::None);
} else { } else {

View File

@ -12,6 +12,7 @@
#include "symbol.h" #include "symbol.h"
#include "utils.h" #include "utils.h"
#include <clang/Basic/Specifiers.h>
#include <llvm/ADT/StringMap.h> #include <llvm/ADT/StringMap.h>
#include <stdint.h> #include <stdint.h>
@ -62,6 +63,8 @@ struct Use : Reference {
void Reflect(Reader& visitor, Reference& value); void Reflect(Reader& visitor, Reference& value);
void Reflect(Writer& visitor, Reference& value); void Reflect(Writer& visitor, Reference& value);
MAKE_REFLECT_TYPE_PROXY2(clang::StorageClass, uint8_t);
template <typename D> template <typename D>
struct NameMixin { struct NameMixin {
std::string_view Name(bool qualified) const { std::string_view Name(bool qualified) const {
@ -99,7 +102,7 @@ struct FuncDef : NameMixin<FuncDef> {
int16_t short_name_offset = 0; int16_t short_name_offset = 0;
int16_t short_name_size = 0; int16_t short_name_size = 0;
lsSymbolKind kind = lsSymbolKind::Unknown; lsSymbolKind kind = lsSymbolKind::Unknown;
StorageClass storage = StorageClass::Invalid; clang::StorageClass storage = clang::SC_None;
std::vector<Usr> GetBases() const { return bases; } std::vector<Usr> GetBases() const { return bases; }
bool operator==(const FuncDef& o) const { bool operator==(const FuncDef& o) const {
@ -213,11 +216,11 @@ struct VarDef : NameMixin<VarDef> {
lsSymbolKind kind = lsSymbolKind::Unknown; lsSymbolKind kind = lsSymbolKind::Unknown;
// Note a variable may have instances of both |None| and |Extern| // Note a variable may have instances of both |None| and |Extern|
// (declaration). // (declaration).
StorageClass storage = StorageClass::Invalid; clang::StorageClass storage = clang::SC_None;
bool is_local() const { bool is_local() const {
return spell && spell->kind != SymbolKind::File && return spell && spell->kind != SymbolKind::File &&
storage == StorageClass::None; storage == clang::SC_None;
} }
std::vector<Usr> GetBases() const { return {}; } std::vector<Usr> GetBases() const { return {}; }

View File

@ -6,6 +6,8 @@
#include "pipeline.hh" #include "pipeline.hh"
using namespace ccls; using namespace ccls;
using namespace clang;
#include <algorithm> #include <algorithm>
MAKE_HASHABLE(SymbolIdx, t.usr, t.kind); MAKE_HASHABLE(SymbolIdx, t.usr, t.kind);
@ -187,10 +189,11 @@ void EmitInactiveLines(WorkingFile* working_file,
void EmitSemanticHighlighting(DB* db, void EmitSemanticHighlighting(DB* db,
SemanticHighlightSymbolCache* semantic_cache, SemanticHighlightSymbolCache* semantic_cache,
WorkingFile* working_file, WorkingFile* wfile,
QueryFile* file) { QueryFile* file) {
assert(file->def); 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; return;
auto semantic_cache_for_file = auto semantic_cache_for_file =
semantic_cache->GetCacheForFile(file->def->path); semantic_cache->GetCacheForFile(file->def->path);
@ -202,7 +205,7 @@ void EmitSemanticHighlighting(DB* db,
std::string_view detailed_name; std::string_view detailed_name;
lsSymbolKind parent_kind = lsSymbolKind::Unknown; lsSymbolKind parent_kind = lsSymbolKind::Unknown;
lsSymbolKind 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. // This switch statement also filters out symbols that are not highlighted.
switch (sym.kind) { switch (sym.kind) {
case SymbolKind::Func: { case SymbolKind::Func: {
@ -237,9 +240,9 @@ void EmitSemanticHighlighting(DB* db,
detailed_name.substr(0, detailed_name.find('<')); detailed_name.substr(0, detailed_name.find('<'));
int16_t start_line = sym.range.start.line; int16_t start_line = sym.range.start.line;
int16_t start_col = sym.range.start.column; 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; 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; sym.range.end.line = start_line;
if (!(start_col + concise_name.size() <= line.size() && if (!(start_col + concise_name.size() <= line.size() &&
line.compare(start_col, concise_name.size(), concise_name) == 0)) line.compare(start_col, concise_name.size(), concise_name) == 0))
@ -280,7 +283,7 @@ void EmitSemanticHighlighting(DB* db,
continue; // applies to for loop continue; // applies to for loop
} }
std::optional<lsRange> loc = GetLsRange(working_file, sym.range); std::optional<lsRange> loc = GetLsRange(wfile, sym.range);
if (loc) { if (loc) {
auto it = grouped_symbols.find(sym); auto it = grouped_symbols.find(sym);
if (it != grouped_symbols.end()) { if (it != grouped_symbols.end()) {
@ -339,7 +342,7 @@ void EmitSemanticHighlighting(DB* db,
// Publish. // Publish.
Out_CclsPublishSemanticHighlighting out; Out_CclsPublishSemanticHighlighting out;
out.params.uri = lsDocumentUri::FromPath(working_file->filename); out.params.uri = lsDocumentUri::FromPath(wfile->filename);
for (auto& entry : grouped_symbols) for (auto& entry : grouped_symbols)
if (entry.second.ranges.size()) if (entry.second.ranges.size())
out.params.symbols.push_back(entry.second); out.params.symbols.push_back(entry.second);

View File

@ -63,7 +63,7 @@ struct Out_CclsPublishSemanticHighlighting
int stableId = 0; int stableId = 0;
lsSymbolKind parentKind; lsSymbolKind parentKind;
lsSymbolKind kind; lsSymbolKind kind;
StorageClass storage; clang::StorageClass storage;
std::vector<lsRange> ranges; std::vector<lsRange> ranges;
}; };
struct Params { struct Params {

View File

@ -95,7 +95,7 @@ bool Expand(MessageHandler* m,
entry->numChildren = 0; entry->numChildren = 0;
if (!def) if (!def)
return false; return false;
auto handle = [&](Use use, CallType call_type) { auto handle = [&](Use use, CallType call_type1) {
entry->numChildren++; entry->numChildren++;
if (levels > 0) { if (levels > 0) {
Out_CclsCallHierarchy::Entry entry1; Out_CclsCallHierarchy::Entry entry1;
@ -103,7 +103,7 @@ bool Expand(MessageHandler* m,
entry1.usr = use.usr; entry1.usr = use.usr;
if (auto loc = GetLsLocation(m->db, m->working_files, use)) if (auto loc = GetLsLocation(m->db, m->working_files, use))
entry1.location = *loc; entry1.location = *loc;
entry1.callType = call_type; entry1.callType = call_type1;
if (Expand(m, &entry1, callee, call_type, qualified, levels - 1)) if (Expand(m, &entry1, callee, call_type, qualified, levels - 1))
entry->children.push_back(std::move(entry1)); entry->children.push_back(std::move(entry1));
} }

View File

@ -438,9 +438,9 @@ struct Handler_Initialize : BaseMessageHandler<In_InitializeRequest> {
{ {
if (params.initializationOptions) if (params.initializationOptions)
g_config = std::make_unique<Config>(*params.initializationOptions); g_config = new Config(*params.initializationOptions);
else else
g_config = std::make_unique<Config>(); g_config = new Config;
rapidjson::Document reader; rapidjson::Document reader;
reader.Parse(g_init_options.c_str()); reader.Parse(g_init_options.c_str());
if (!reader.HasParseError()) { if (!reader.HasParseError()) {

View File

@ -2,6 +2,7 @@
#include "pipeline.hh" #include "pipeline.hh"
#include "query_utils.h" #include "query_utils.h"
using namespace ccls; using namespace ccls;
using namespace clang;
namespace { namespace {
MethodType kMethodType = "textDocument/documentSymbol"; MethodType kMethodType = "textDocument/documentSymbol";
@ -51,9 +52,8 @@ struct Handler_TextDocumentDocumentSymbol
if (!def || !def->spell) if (!def || !def->spell)
continue; continue;
// Ignore local variables. // Ignore local variables.
if (def->spell->kind == SymbolKind::Func && if (def->spell->kind == SymbolKind::Func && def->storage != SC_Static &&
def->storage != StorageClass::Static && def->storage != SC_Extern)
def->storage != StorageClass::Extern)
continue; continue;
} }

View File

@ -450,7 +450,9 @@ TEST_SUITE("Project") {
void CheckFlags(const std::string& directory, const std::string& file, void CheckFlags(const std::string& directory, const std::string& file,
std::vector<std::string> raw, std::vector<std::string> raw,
std::vector<std::string> expected) { std::vector<std::string> expected) {
g_config = std::make_unique<Config>(); if (g_config)
delete g_config;
g_config = new Config;
g_config->clang.resourceDir = "/w/resource_dir/"; g_config->clang.resourceDir = "/w/resource_dir/";
ProjectConfig project; ProjectConfig project;
project.project_dir = "/w/c/s/"; project.project_dir = "/w/c/s/";
@ -536,7 +538,9 @@ TEST_SUITE("Project") {
} }
TEST_CASE("Directory extraction") { TEST_CASE("Directory extraction") {
g_config = std::make_unique<Config>(); if (g_config)
delete g_config;
g_config = new Config;
ProjectConfig config; ProjectConfig config;
config.project_dir = "/w/c/s/"; config.project_dir = "/w/c/s/";

View File

@ -8,27 +8,6 @@
enum class SymbolKind : uint8_t { Invalid, File, Type, Func, Var }; enum class SymbolKind : uint8_t { Invalid, File, Type, Func, Var };
MAKE_REFLECT_TYPE_PROXY(SymbolKind); 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 { enum class Role : uint16_t {
None = 0, None = 0,
Declaration = 1 << 0, Declaration = 1 << 0,

View File

@ -288,7 +288,7 @@ bool RunIndexTests(const std::string& filter_path, bool enable_update) {
flags.push_back(path); flags.push_back(path);
// Run test. // Run test.
g_config = std::make_unique<Config>(); g_config = new Config;
VFS vfs; VFS vfs;
auto dbs = index.Index(&vfs, path, flags, {}); auto dbs = index.Index(&vfs, path, flags, {});