mirror of
				https://github.com/MaskRay/ccls.git
				synced 2025-11-04 06:15:20 +00:00 
			
		
		
		
	Add Config->largeFileSize; pure virtual or defaulted methods are definitions; fix $ccls/callHierarchy
This commit is contained in:
		
							parent
							
								
									a36e548e03
								
							
						
					
					
						commit
						66580104ba
					
				@ -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)
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
#include "config.h"
 | 
			
		||||
 | 
			
		||||
std::unique_ptr<Config> g_config;
 | 
			
		||||
Config* g_config;
 | 
			
		||||
thread_local int g_thread_id;
 | 
			
		||||
 | 
			
		||||
@ -2,7 +2,6 @@
 | 
			
		||||
 | 
			
		||||
#include "serializer.h"
 | 
			
		||||
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
@ -192,6 +191,9 @@ struct Config {
 | 
			
		||||
    std::vector<std::string> 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<Config> g_config;
 | 
			
		||||
extern Config* g_config;
 | 
			
		||||
thread_local extern int g_thread_id;
 | 
			
		||||
 | 
			
		||||
@ -5,7 +5,9 @@
 | 
			
		||||
#include "serializer.h"
 | 
			
		||||
#include "type_printer.h"
 | 
			
		||||
 | 
			
		||||
#include <clang/AST/AST.h>
 | 
			
		||||
#include <llvm/Support/Timer.h>
 | 
			
		||||
using namespace clang;
 | 
			
		||||
using namespace llvm;
 | 
			
		||||
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
@ -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<const Decl*>(decl->cursor.data[0]);
 | 
			
		||||
        auto* Method = dyn_cast_or_null<CXXMethodDecl>(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 {
 | 
			
		||||
 | 
			
		||||
@ -12,6 +12,7 @@
 | 
			
		||||
#include "symbol.h"
 | 
			
		||||
#include "utils.h"
 | 
			
		||||
 | 
			
		||||
#include <clang/Basic/Specifiers.h>
 | 
			
		||||
#include <llvm/ADT/StringMap.h>
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
@ -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 <typename D>
 | 
			
		||||
struct NameMixin {
 | 
			
		||||
  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_size = 0;
 | 
			
		||||
  lsSymbolKind kind = lsSymbolKind::Unknown;
 | 
			
		||||
  StorageClass storage = StorageClass::Invalid;
 | 
			
		||||
  clang::StorageClass storage = clang::SC_None;
 | 
			
		||||
 | 
			
		||||
  std::vector<Usr> GetBases() const { return bases; }
 | 
			
		||||
  bool operator==(const FuncDef& o) const {
 | 
			
		||||
@ -213,11 +216,11 @@ struct VarDef : NameMixin<VarDef> {
 | 
			
		||||
  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<Usr> GetBases() const { return {}; }
 | 
			
		||||
 | 
			
		||||
@ -6,6 +6,8 @@
 | 
			
		||||
#include "pipeline.hh"
 | 
			
		||||
using namespace ccls;
 | 
			
		||||
 | 
			
		||||
using namespace clang;
 | 
			
		||||
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
 | 
			
		||||
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<lsRange> loc = GetLsRange(working_file, sym.range);
 | 
			
		||||
    std::optional<lsRange> 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);
 | 
			
		||||
 | 
			
		||||
@ -63,7 +63,7 @@ struct Out_CclsPublishSemanticHighlighting
 | 
			
		||||
    int stableId = 0;
 | 
			
		||||
    lsSymbolKind parentKind;
 | 
			
		||||
    lsSymbolKind kind;
 | 
			
		||||
    StorageClass storage;
 | 
			
		||||
    clang::StorageClass storage;
 | 
			
		||||
    std::vector<lsRange> ranges;
 | 
			
		||||
  };
 | 
			
		||||
  struct Params {
 | 
			
		||||
 | 
			
		||||
@ -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));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -438,9 +438,9 @@ struct Handler_Initialize : BaseMessageHandler<In_InitializeRequest> {
 | 
			
		||||
 | 
			
		||||
    {
 | 
			
		||||
      if (params.initializationOptions)
 | 
			
		||||
        g_config = std::make_unique<Config>(*params.initializationOptions);
 | 
			
		||||
        g_config = new Config(*params.initializationOptions);
 | 
			
		||||
      else
 | 
			
		||||
        g_config = std::make_unique<Config>();
 | 
			
		||||
        g_config = new Config;
 | 
			
		||||
      rapidjson::Document reader;
 | 
			
		||||
      reader.Parse(g_init_options.c_str());
 | 
			
		||||
      if (!reader.HasParseError()) {
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -450,7 +450,9 @@ TEST_SUITE("Project") {
 | 
			
		||||
  void CheckFlags(const std::string& directory, const std::string& file,
 | 
			
		||||
                  std::vector<std::string> raw,
 | 
			
		||||
                  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/";
 | 
			
		||||
    ProjectConfig project;
 | 
			
		||||
    project.project_dir = "/w/c/s/";
 | 
			
		||||
@ -536,7 +538,9 @@ TEST_SUITE("Project") {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  TEST_CASE("Directory extraction") {
 | 
			
		||||
    g_config = std::make_unique<Config>();
 | 
			
		||||
    if (g_config)
 | 
			
		||||
      delete g_config;
 | 
			
		||||
    g_config = new Config;
 | 
			
		||||
    ProjectConfig config;
 | 
			
		||||
    config.project_dir = "/w/c/s/";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										21
									
								
								src/symbol.h
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								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,
 | 
			
		||||
 | 
			
		||||
@ -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<Config>();
 | 
			
		||||
        g_config = new Config;
 | 
			
		||||
        VFS vfs;
 | 
			
		||||
        auto dbs = index.Index(&vfs, path, flags, {});
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user