mirror of
https://github.com/MaskRay/ccls.git
synced 2024-11-29 11:01:57 +00:00
std::string {hover,comments} -> NTString (null-terminated string)
Typically, sizeof(std::string) = 32, sizeof(NTString) = 8 hover and comments are usually empty and thus wasteful to spend 24*2 bytes for them
This commit is contained in:
parent
e019968f51
commit
8ab45cb43d
@ -434,6 +434,25 @@ std::string GetDocumentContentInRange(CXTranslationUnit cx_tu,
|
||||
return result;
|
||||
}
|
||||
|
||||
void SetUsePreflight(IndexFile* db, ClangCursor lex_parent) {
|
||||
switch (GetSymbolKind(lex_parent.get_kind())) {
|
||||
default:
|
||||
break;
|
||||
case SymbolKind::Func: {
|
||||
(void)db->ToFuncId(lex_parent.cx_cursor);
|
||||
break;
|
||||
}
|
||||
case SymbolKind::Type: {
|
||||
(void)db->ToTypeId(lex_parent.cx_cursor);
|
||||
break;
|
||||
}
|
||||
case SymbolKind::Var: {
|
||||
(void)db->ToVarId(lex_parent.cx_cursor);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SetUse(IndexFile* db, Maybe<Use>* def, Range range, ClangCursor lex_parent, Role role) {
|
||||
switch (GetSymbolKind(lex_parent.get_kind())) {
|
||||
default:
|
||||
@ -561,8 +580,8 @@ void SetVarDetail(IndexVar* var,
|
||||
def.detailed_name = param->PrettyPrintCursor(cursor.cx_cursor, false);
|
||||
def.hover = std::move(qualified_name);
|
||||
#else
|
||||
def.detailed_name = std::move(type_name);
|
||||
ConcatTypeAndName(def.detailed_name, qualified_name);
|
||||
ConcatTypeAndName(type_name, qualified_name);
|
||||
def.detailed_name = type_name;
|
||||
// Append the textual initializer, bit field, constructor to |hover|.
|
||||
// Omit |hover| for these types:
|
||||
// int (*a)(); int (&a)(); int (&&a)(); int a[1]; auto x = ...
|
||||
@ -580,7 +599,7 @@ void SetVarDetail(IndexVar* var,
|
||||
optional<int> spell_end = fc.ToOffset(cursor.get_spelling_range().end);
|
||||
optional<int> extent_end = fc.ToOffset(cursor.get_extent().end);
|
||||
if (extent_end && *spell_end < *extent_end)
|
||||
def.hover = def.detailed_name +
|
||||
def.hover = std::string(def.detailed_name.c_str()) +
|
||||
fc.content.substr(*spell_end, *extent_end - *spell_end);
|
||||
}
|
||||
#endif
|
||||
@ -1210,21 +1229,22 @@ ClangCursor::VisitResult VisitMacroDefinitionAndExpansions(ClangCursor cursor,
|
||||
else
|
||||
decl_usr = cursor.get_referenced().get_usr_hash();
|
||||
|
||||
SetUsePreflight(db, parent);
|
||||
IndexVar* var_def = db->Resolve(db->ToVarId(decl_usr));
|
||||
if (cursor.get_kind() == CXCursor_MacroDefinition) {
|
||||
CXSourceRange cx_extent = clang_getCursorExtent(cursor.cx_cursor);
|
||||
var_def->def.detailed_name = cursor.get_display_name();
|
||||
var_def->def.short_name_offset = 0;
|
||||
var_def->def.short_name_size = int(var_def->def.detailed_name.size());
|
||||
var_def->def.short_name_size =
|
||||
int16_t(strlen(var_def->def.detailed_name.c_str()));
|
||||
var_def->def.hover =
|
||||
"#define " + GetDocumentContentInRange(param->tu->cx_tu, cx_extent);
|
||||
var_def->def.kind = ClangSymbolKind::Macro;
|
||||
var_def->def.comments = cursor.get_comments();
|
||||
ClangCursor lex_parent;
|
||||
SetUse(db, &var_def->def.spell, decl_loc_spelling, lex_parent,
|
||||
SetUse(db, &var_def->def.spell, decl_loc_spelling, parent,
|
||||
Role::Definition);
|
||||
SetUse(db, &var_def->def.extent,
|
||||
ResolveCXSourceRange(cx_extent, nullptr), lex_parent, Role::None);
|
||||
ResolveCXSourceRange(cx_extent, nullptr), parent, Role::None);
|
||||
} else
|
||||
UniqueAddUse(db, var_def->uses, decl_loc_spelling, parent);
|
||||
|
||||
@ -1257,6 +1277,7 @@ ClangCursor::VisitResult TemplateVisitor(ClangCursor cursor,
|
||||
case CXCursor_DeclRefExpr: {
|
||||
ClangCursor ref_cursor = clang_getCursorReferenced(cursor.cx_cursor);
|
||||
if (ref_cursor.get_kind() == CXCursor_NonTypeTemplateParameter) {
|
||||
SetUsePreflight(db, parent);
|
||||
IndexVar* ref_var =
|
||||
db->Resolve(db->ToVarId(ref_cursor.get_usr_hash()));
|
||||
if (ref_var->def.detailed_name.empty()) {
|
||||
@ -1305,6 +1326,7 @@ ClangCursor::VisitResult TemplateVisitor(ClangCursor cursor,
|
||||
case CXCursor_TemplateRef: {
|
||||
ClangCursor ref_cursor = clang_getCursorReferenced(cursor.cx_cursor);
|
||||
if (ref_cursor.get_kind() == CXCursor_TemplateTemplateParameter) {
|
||||
SetUsePreflight(db, parent);
|
||||
IndexType* ref_index =
|
||||
db->Resolve(db->ToTypeId(ref_cursor.get_usr_hash()));
|
||||
// TODO It seems difficult to get references to template template
|
||||
@ -1321,7 +1343,8 @@ ClangCursor::VisitResult TemplateVisitor(ClangCursor cursor,
|
||||
ref_index->def.detailed_name = ref_cursor.get_spelling();
|
||||
#endif
|
||||
ref_index->def.short_name_offset = 0;
|
||||
ref_index->def.short_name_size = ref_index->def.detailed_name.size();
|
||||
ref_index->def.short_name_size =
|
||||
int16_t(strlen(ref_index->def.detailed_name.c_str()));
|
||||
ref_index->def.kind = ClangSymbolKind::Parameter;
|
||||
}
|
||||
UniqueAddUseSpell(db, ref_index->uses, cursor);
|
||||
@ -1331,6 +1354,7 @@ ClangCursor::VisitResult TemplateVisitor(ClangCursor cursor,
|
||||
case CXCursor_TypeRef: {
|
||||
ClangCursor ref_cursor = clang_getCursorReferenced(cursor.cx_cursor);
|
||||
if (ref_cursor.get_kind() == CXCursor_TemplateTypeParameter) {
|
||||
SetUsePreflight(db, parent);
|
||||
IndexType* ref_index =
|
||||
db->Resolve(db->ToTypeId(ref_cursor.get_usr_hash()));
|
||||
// TODO It seems difficult to get a FunctionTemplate's template
|
||||
@ -1347,7 +1371,8 @@ ClangCursor::VisitResult TemplateVisitor(ClangCursor cursor,
|
||||
ref_index->def.detailed_name = ref_cursor.get_spelling();
|
||||
#endif
|
||||
ref_index->def.short_name_offset = 0;
|
||||
ref_index->def.short_name_size = ref_index->def.detailed_name.size();
|
||||
ref_index->def.short_name_size =
|
||||
int16_t(strlen(ref_index->def.detailed_name.c_str()));
|
||||
ref_index->def.kind = ClangSymbolKind::Parameter;
|
||||
}
|
||||
UniqueAddUseSpell(db, ref_index->uses, cursor);
|
||||
@ -1455,6 +1480,7 @@ void OnIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
|
||||
|
||||
NamespaceHelper* ns = ¶m->ns;
|
||||
ClangCursor lex_parent(fromContainer(decl->lexicalContainer));
|
||||
SetUsePreflight(db, lex_parent);
|
||||
|
||||
switch (decl->entityInfo->kind) {
|
||||
case CXIdxEntity_CXXNamespace: {
|
||||
@ -1745,7 +1771,7 @@ void OnIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
|
||||
if (extent_start && spell_start && spell_end && extent_end) {
|
||||
type->def.hover =
|
||||
fc.content.substr(*extent_start, *spell_start - *extent_start) +
|
||||
type->def.detailed_name +
|
||||
type->def.detailed_name.c_str() +
|
||||
fc.content.substr(*spell_end, *extent_end - *spell_end);
|
||||
}
|
||||
}
|
||||
@ -1935,6 +1961,7 @@ void OnIndexReference(CXClientData client_data, const CXIdxEntityRefInfo* ref) {
|
||||
|
||||
ClangCursor cursor(ref->cursor);
|
||||
ClangCursor lex_parent(fromContainer(ref->container));
|
||||
SetUsePreflight(db, lex_parent);
|
||||
|
||||
switch (ref->referencedEntity->kind) {
|
||||
case CXIdxEntity_CXXNamespaceAlias:
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "file_contents.h"
|
||||
#include "language_server_api.h"
|
||||
#include "maybe.h"
|
||||
#include "ntstring.h"
|
||||
#include "performance.h"
|
||||
#include "position.h"
|
||||
#include "serializer.h"
|
||||
@ -160,8 +161,8 @@ template <typename F>
|
||||
struct TypeDefDefinitionData {
|
||||
// General metadata.
|
||||
std::string detailed_name;
|
||||
std::string hover;
|
||||
std::string comments;
|
||||
NTString hover;
|
||||
NTString comments;
|
||||
|
||||
// While a class/type can technically have a separate declaration/definition,
|
||||
// it doesn't really happen in practice. The declaration never contains
|
||||
@ -258,8 +259,8 @@ template <typename F>
|
||||
struct FuncDefDefinitionData {
|
||||
// General metadata.
|
||||
std::string detailed_name;
|
||||
std::string hover;
|
||||
std::string comments;
|
||||
NTString hover;
|
||||
NTString comments;
|
||||
Maybe<Use> spell;
|
||||
Maybe<Use> extent;
|
||||
|
||||
@ -368,8 +369,8 @@ template <typename F>
|
||||
struct VarDefDefinitionData {
|
||||
// General metadata.
|
||||
std::string detailed_name;
|
||||
std::string hover;
|
||||
std::string comments;
|
||||
NTString hover;
|
||||
NTString comments;
|
||||
// TODO: definitions should be a list of ranges, since there can be more
|
||||
// than one - when??
|
||||
Maybe<Use> spell;
|
||||
|
@ -180,7 +180,7 @@ MAKE_REFLECT_STRUCT(lsLocation, uri, range);
|
||||
|
||||
// cquery extension
|
||||
struct lsLocationEx : lsLocation {
|
||||
optional<std::string> containerName;
|
||||
optional<std::string_view> containerName;
|
||||
};
|
||||
MAKE_REFLECT_STRUCT(lsLocationEx, uri, range, containerName);
|
||||
|
||||
|
@ -14,7 +14,7 @@ REGISTER_IPC_MESSAGE(Ipc_CqueryTypeHierarchyTree);
|
||||
struct Out_CqueryTypeHierarchyTree
|
||||
: public lsOutMessage<Out_CqueryTypeHierarchyTree> {
|
||||
struct TypeEntry {
|
||||
std::string name;
|
||||
std::string_view name;
|
||||
optional<lsLocation> location;
|
||||
std::vector<TypeEntry> children;
|
||||
};
|
||||
@ -36,7 +36,7 @@ BuildParentInheritanceHierarchyForType(QueryDatabase* db,
|
||||
|
||||
EachWithGen(db->types, root_type.def->parents, [&](QueryType& parent_type) {
|
||||
Out_CqueryTypeHierarchyTree::TypeEntry parent_entry;
|
||||
parent_entry.name = parent_type.def->detailed_name;
|
||||
parent_entry.name = parent_type.def->detailed_name.c_str();
|
||||
if (parent_type.def->spell)
|
||||
parent_entry.location = GetLsLocation(
|
||||
db, working_files, *parent_type.def->spell);
|
||||
|
@ -11,25 +11,28 @@ std::pair<std::string_view, std::string_view> GetCommentsAndHover(
|
||||
case SymbolKind::Type: {
|
||||
QueryType& type = db->types[sym.Idx()];
|
||||
if (type.def)
|
||||
return {type.def->comments, type.def->hover.size()
|
||||
? type.def->hover
|
||||
: type.def->detailed_name};
|
||||
return {type.def->comments,
|
||||
!type.def->hover.empty()
|
||||
? std::string_view(type.def->hover)
|
||||
: std::string_view(type.def->detailed_name)};
|
||||
break;
|
||||
}
|
||||
case SymbolKind::Func: {
|
||||
QueryFunc& func = db->funcs[sym.Idx()];
|
||||
if (func.def)
|
||||
return {func.def->comments, func.def->hover.size()
|
||||
? func.def->hover
|
||||
: func.def->detailed_name};
|
||||
return {func.def->comments,
|
||||
!func.def->hover.empty()
|
||||
? std::string_view(func.def->hover)
|
||||
: std::string_view(func.def->detailed_name)};
|
||||
break;
|
||||
}
|
||||
case SymbolKind::Var: {
|
||||
QueryVar& var = db->vars[sym.Idx()];
|
||||
if (var.def)
|
||||
return {var.def->comments, var.def->hover.size()
|
||||
? var.def->hover
|
||||
: var.def->detailed_name};
|
||||
return {var.def->comments,
|
||||
!var.def->hover.empty()
|
||||
? std::string_view(var.def->hover)
|
||||
: std::string_view(var.def->detailed_name)};
|
||||
break;
|
||||
}
|
||||
case SymbolKind::File:
|
||||
|
57
src/ntstring.h
Normal file
57
src/ntstring.h
Normal file
@ -0,0 +1,57 @@
|
||||
#pragma once
|
||||
|
||||
#include <string_view.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
class Reader;
|
||||
class Writer;
|
||||
|
||||
// Null-terminated string
|
||||
// This is used in Query{Func,Type,Var}::def to reduce memory footprint.
|
||||
class NTString {
|
||||
using size_type = std::string::size_type;
|
||||
std::unique_ptr<char[]> str;
|
||||
|
||||
public:
|
||||
NTString() : str(new char[1]()) {}
|
||||
NTString(const NTString& o) : str(new char[strlen(o.c_str()) + 1]) {
|
||||
strcpy(str.get(), o.c_str());
|
||||
}
|
||||
NTString(NTString&& o) = default;
|
||||
NTString(std::string_view sv) {
|
||||
*this = sv;
|
||||
}
|
||||
|
||||
operator std::string_view() const { return str.get(); }
|
||||
const char* c_str() const { return str.get(); }
|
||||
std::string_view substr(size_type pos, size_type cnt) const {
|
||||
return std::string_view(c_str() + pos, cnt);
|
||||
}
|
||||
bool empty() const { return !str || str.get()[0] == '\0'; }
|
||||
size_type find(const char* s) {
|
||||
const char *p = strstr(c_str(), s);
|
||||
return p ? std::string::size_type(p - c_str()) : std::string::npos;
|
||||
}
|
||||
size_type find(const char* s, size_type pos, size_type cnt) {
|
||||
auto* p = (const char*)memmem(c_str() + pos, strlen(c_str()) - pos, s, cnt);
|
||||
return p ? std::string::size_type(p - c_str()) : std::string::npos;
|
||||
}
|
||||
size_type find(std::string_view sv) {
|
||||
return find(sv.data(), 0, sv.size());
|
||||
}
|
||||
|
||||
void operator=(std::string_view sv) {
|
||||
str = std::unique_ptr<char[]>(new char[sv.size() + 1]);
|
||||
memcpy(str.get(), sv.data(), sv.size());
|
||||
str.get()[sv.size()] = '\0';
|
||||
}
|
||||
void operator=(const NTString& o) {
|
||||
*this = static_cast<std::string_view>(o);
|
||||
}
|
||||
bool operator==(const NTString& o) const {
|
||||
return strcmp(c_str(), o.c_str()) == 0;
|
||||
}
|
||||
};
|
@ -406,19 +406,19 @@ optional<lsLocationEx> GetLsLocationEx(QueryDatabase* db,
|
||||
case SymbolKind::Func: {
|
||||
QueryFunc& func = db->GetFunc(use);
|
||||
if (func.def)
|
||||
ret.containerName = func.def->detailed_name;
|
||||
ret.containerName = std::string_view(func.def->detailed_name);
|
||||
break;
|
||||
}
|
||||
case SymbolKind::Type: {
|
||||
QueryType& type = db->GetType(use);
|
||||
if (type.def)
|
||||
ret.containerName = type.def->detailed_name;
|
||||
ret.containerName = std::string_view(type.def->detailed_name);
|
||||
break;
|
||||
}
|
||||
case SymbolKind::Var: {
|
||||
QueryVar& var = db->GetVar(use);
|
||||
if (var.def)
|
||||
ret.containerName = var.def->detailed_name;
|
||||
ret.containerName = std::string_view(var.def->detailed_name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -470,7 +470,7 @@ optional<lsSymbolInformation> GetSymbolInfo(QueryDatabase* db,
|
||||
info.name = type.def->ShortName();
|
||||
else
|
||||
info.name = type.def->detailed_name;
|
||||
if (type.def->detailed_name != type.def->ShortName())
|
||||
if (type.def->detailed_name.c_str() != type.def->ShortName())
|
||||
info.containerName = type.def->detailed_name;
|
||||
// TODO ClangSymbolKind -> lsSymbolKind
|
||||
switch (type.def->kind) {
|
||||
|
@ -125,18 +125,14 @@ void Reflect(Writer& visitor, std::string_view& data) {
|
||||
visitor.String(&data[0], (rapidjson::SizeType)data.size());
|
||||
}
|
||||
|
||||
void Reflect(Reader& visitor, std::unique_ptr<char[]>& value) {
|
||||
void Reflect(Reader& visitor, NTString& value) {
|
||||
if (!visitor.IsString())
|
||||
throw std::invalid_argument("std::string");
|
||||
std::string t = visitor.GetString();
|
||||
value = std::unique_ptr<char[]>(new char[t.size() + 1]);
|
||||
strcpy(value.get(), t.c_str());
|
||||
value = visitor.GetString();
|
||||
}
|
||||
void Reflect(Writer& visitor, std::unique_ptr<char[]>& value) {
|
||||
if (!value)
|
||||
visitor.String("");
|
||||
else
|
||||
visitor.String(value.get());
|
||||
void Reflect(Writer& visitor, NTString& value) {
|
||||
const char* s = value.c_str();
|
||||
visitor.String(s ? s : "");
|
||||
}
|
||||
|
||||
// TODO: Move this to indexer.cc
|
||||
@ -169,9 +165,9 @@ void ReflectHoverAndComments(Reader& visitor, Def& def) {
|
||||
template <typename Def>
|
||||
void ReflectHoverAndComments(Writer& visitor, Def& def) {
|
||||
// Don't emit empty hover and comments in JSON test mode.
|
||||
if (!gTestOutputMode || def.hover.size())
|
||||
if (!gTestOutputMode || !def.hover.empty())
|
||||
ReflectMember(visitor, "hover", def.hover);
|
||||
if (!gTestOutputMode || def.comments.size())
|
||||
if (!gTestOutputMode || !def.comments.empty())
|
||||
ReflectMember(visitor, "comments", def.comments);
|
||||
}
|
||||
|
||||
@ -192,8 +188,8 @@ void ReflectShortName(Reader& visitor, Def& def) {
|
||||
template <typename Def>
|
||||
void ReflectShortName(Writer& visitor, Def& def) {
|
||||
if (gTestOutputMode) {
|
||||
std::string short_name =
|
||||
def.detailed_name.substr(def.short_name_offset, def.short_name_size);
|
||||
std::string short_name(
|
||||
def.detailed_name.substr(def.short_name_offset, def.short_name_size));
|
||||
ReflectMember(visitor, "short_name", short_name);
|
||||
} else {
|
||||
ReflectMember(visitor, "short_name_offset", def.short_name_offset);
|
||||
|
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "maybe.h"
|
||||
#include "ntstring.h"
|
||||
#include "port.h"
|
||||
|
||||
#include <macro_map.h>
|
||||
@ -160,8 +161,8 @@ void Reflect(Writer& visitor, std::string& value);
|
||||
void Reflect(Reader& visitor, std::string_view& view);
|
||||
void Reflect(Writer& visitor, std::string_view& view);
|
||||
|
||||
void Reflect(Reader& visitor, std::unique_ptr<char[]>& value);
|
||||
void Reflect(Writer& visitor, std::unique_ptr<char[]>& value);
|
||||
void Reflect(Reader& visitor, NTString& value);
|
||||
void Reflect(Writer& visitor, NTString& value);
|
||||
|
||||
// std::monostate is used to represent JSON null
|
||||
void Reflect(Reader& visitor, std::monostate&);
|
||||
|
Loading…
Reference in New Issue
Block a user