mirror of
https://github.com/MaskRay/ccls.git
synced 2025-01-31 09:50:26 +00:00
Format
This commit is contained in:
parent
233a108814
commit
a392301be3
@ -310,8 +310,8 @@ void TryEnsureDocumentParsed(ClangCompleteManager* manager,
|
|||||||
args.push_back("-fspell-checking");
|
args.push_back("-fspell-checking");
|
||||||
}
|
}
|
||||||
|
|
||||||
WorkingFiles::Snapshot snapshot =
|
WorkingFiles::Snapshot snapshot = session->working_files->AsSnapshot(
|
||||||
session->working_files->AsSnapshot({StripFileType(session->file.filename)});
|
{StripFileType(session->file.filename)});
|
||||||
std::vector<CXUnsavedFile> unsaved = snapshot.AsUnsavedFiles();
|
std::vector<CXUnsavedFile> unsaved = snapshot.AsUnsavedFiles();
|
||||||
|
|
||||||
LOG_S(INFO) << "Creating completion session with arguments "
|
LOG_S(INFO) << "Creating completion session with arguments "
|
||||||
@ -408,7 +408,6 @@ void CompletionQueryMain(ClangCompleteManager* completion_manager) {
|
|||||||
std::vector<CXUnsavedFile> unsaved = snapshot.AsUnsavedFiles();
|
std::vector<CXUnsavedFile> unsaved = snapshot.AsUnsavedFiles();
|
||||||
timer.ResetAndPrint("[complete] Creating WorkingFile snapshot");
|
timer.ResetAndPrint("[complete] Creating WorkingFile snapshot");
|
||||||
|
|
||||||
|
|
||||||
// Emit code completion data.
|
// Emit code completion data.
|
||||||
if (request->position) {
|
if (request->position) {
|
||||||
// Language server is 0-based, clang is 1-based.
|
// Language server is 0-based, clang is 1-based.
|
||||||
|
@ -61,22 +61,22 @@ ClangType ClangType::strip_qualifiers() const {
|
|||||||
CXType cx = cx_type;
|
CXType cx = cx_type;
|
||||||
while (1) {
|
while (1) {
|
||||||
switch (cx.kind) {
|
switch (cx.kind) {
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
case CXType_ConstantArray:
|
case CXType_ConstantArray:
|
||||||
case CXType_DependentSizedArray:
|
case CXType_DependentSizedArray:
|
||||||
case CXType_IncompleteArray:
|
case CXType_IncompleteArray:
|
||||||
case CXType_VariableArray:
|
case CXType_VariableArray:
|
||||||
cx = clang_getElementType(cx);
|
cx = clang_getElementType(cx);
|
||||||
continue;
|
continue;
|
||||||
case CXType_BlockPointer:
|
case CXType_BlockPointer:
|
||||||
case CXType_LValueReference:
|
case CXType_LValueReference:
|
||||||
case CXType_MemberPointer:
|
case CXType_MemberPointer:
|
||||||
case CXType_ObjCObjectPointer:
|
case CXType_ObjCObjectPointer:
|
||||||
case CXType_Pointer:
|
case CXType_Pointer:
|
||||||
case CXType_RValueReference:
|
case CXType_RValueReference:
|
||||||
cx = clang_getPointeeType(cx);
|
cx = clang_getPointeeType(cx);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -63,8 +63,7 @@ enum class StorageClass : uint8_t {
|
|||||||
Auto,
|
Auto,
|
||||||
Register
|
Register
|
||||||
};
|
};
|
||||||
MAKE_REFLECT_TYPE_PROXY(StorageClass,
|
MAKE_REFLECT_TYPE_PROXY(StorageClass, std::underlying_type<StorageClass>::type);
|
||||||
std::underlying_type<StorageClass>::type);
|
|
||||||
|
|
||||||
enum class SymbolRole : uint8_t {
|
enum class SymbolRole : uint8_t {
|
||||||
Declaration = 1 << 0,
|
Declaration = 1 << 0,
|
||||||
|
@ -492,15 +492,15 @@ int main(int argc, char** argv) {
|
|||||||
|
|
||||||
if (language_server) {
|
if (language_server) {
|
||||||
if (HasOption(options, "--init")) {
|
if (HasOption(options, "--init")) {
|
||||||
// We check syntax error here but override client-side initializationOptions
|
// We check syntax error here but override client-side
|
||||||
// in messages/initialize.cc
|
// initializationOptions in messages/initialize.cc
|
||||||
g_init_options = options["--init"];
|
g_init_options = options["--init"];
|
||||||
rapidjson::Document reader;
|
rapidjson::Document reader;
|
||||||
rapidjson::ParseResult ok = reader.Parse(g_init_options.c_str());
|
rapidjson::ParseResult ok = reader.Parse(g_init_options.c_str());
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
std::cerr << "Failed to parse --init as JSON: "
|
std::cerr << "Failed to parse --init as JSON: "
|
||||||
<< rapidjson::GetParseError_En(ok.Code()) << " (" << ok.Offset()
|
<< rapidjson::GetParseError_En(ok.Code()) << " ("
|
||||||
<< ")\n";
|
<< ok.Offset() << ")\n";
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
JsonReader json_reader{&reader};
|
JsonReader json_reader{&reader};
|
||||||
|
@ -530,8 +530,8 @@ void IndexWithTuFromCodeCompletion(
|
|||||||
|
|
||||||
PerformanceImportFile perf;
|
PerformanceImportFile perf;
|
||||||
ClangIndex index;
|
ClangIndex index;
|
||||||
auto indexes = ParseWithTu(
|
auto indexes = ParseWithTu(file_consumer_shared, &perf, tu, &index, path,
|
||||||
file_consumer_shared, &perf, tu, &index, path, args, file_contents);
|
args, file_contents);
|
||||||
if (!indexes)
|
if (!indexes)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
103
src/indexer.cc
103
src/indexer.cc
@ -523,7 +523,7 @@ void SetVarDetail(IndexVar* var,
|
|||||||
optional<int> extent_end = fc.ToOffset(cursor.get_extent().end);
|
optional<int> extent_end = fc.ToOffset(cursor.get_extent().end);
|
||||||
if (extent_end && *spell_end < *extent_end)
|
if (extent_end && *spell_end < *extent_end)
|
||||||
def.hover = def.detailed_name +
|
def.hover = def.detailed_name +
|
||||||
fc.content.substr(*spell_end, *extent_end - *spell_end);
|
fc.content.substr(*spell_end, *extent_end - *spell_end);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -838,10 +838,10 @@ void VisitDeclForTypeUsageVisitorHandler(ClangCursor cursor,
|
|||||||
// For |A<int> a| where there is a specialization for |A<int>|,
|
// For |A<int> a| where there is a specialization for |A<int>|,
|
||||||
// the |referenced_usr| below resolves to the primary template and
|
// the |referenced_usr| below resolves to the primary template and
|
||||||
// attributes the use to the primary template instead of the specialization.
|
// attributes the use to the primary template instead of the specialization.
|
||||||
// |toplevel_type| is retrieved |clang_getCursorType| which can be a specialization.
|
// |toplevel_type| is retrieved |clang_getCursorType| which can be a
|
||||||
// If its name is the same as the primary template's, we assume the use
|
// specialization. If its name is the same as the primary template's, we
|
||||||
// should be attributed to the specialization.
|
// assume the use should be attributed to the specialization. This heuristic
|
||||||
// This heuristic fails when a member class bears the same name with its container.
|
// fails when a member class bears the same name with its container.
|
||||||
//
|
//
|
||||||
// template<class T>
|
// template<class T>
|
||||||
// struct C { struct C {}; };
|
// struct C { struct C {}; };
|
||||||
@ -859,7 +859,9 @@ void VisitDeclForTypeUsageVisitorHandler(ClangCursor cursor,
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string referenced_usr =
|
std::string referenced_usr =
|
||||||
cursor.get_referenced().template_specialization_to_template_definition().get_usr();
|
cursor.get_referenced()
|
||||||
|
.template_specialization_to_template_definition()
|
||||||
|
.get_usr();
|
||||||
// TODO: things in STL cause this to be empty. Figure out why and document it.
|
// TODO: things in STL cause this to be empty. Figure out why and document it.
|
||||||
if (referenced_usr == "")
|
if (referenced_usr == "")
|
||||||
return;
|
return;
|
||||||
@ -1188,7 +1190,8 @@ ClangCursor::VisitResult TemplateVisitor(ClangCursor cursor,
|
|||||||
case CXCursor_DeclRefExpr: {
|
case CXCursor_DeclRefExpr: {
|
||||||
ClangCursor ref_cursor = clang_getCursorReferenced(cursor.cx_cursor);
|
ClangCursor ref_cursor = clang_getCursorReferenced(cursor.cx_cursor);
|
||||||
if (ref_cursor.get_kind() == CXCursor_NonTypeTemplateParameter) {
|
if (ref_cursor.get_kind() == CXCursor_NonTypeTemplateParameter) {
|
||||||
IndexVar* ref_index = db->Resolve(db->ToVarId(ref_cursor.get_usr_hash()));
|
IndexVar* ref_index =
|
||||||
|
db->Resolve(db->ToVarId(ref_cursor.get_usr_hash()));
|
||||||
if (ref_index->def.short_name.empty()) {
|
if (ref_index->def.short_name.empty()) {
|
||||||
ref_index->def.definition_spelling = ref_cursor.get_spelling_range();
|
ref_index->def.definition_spelling = ref_cursor.get_spelling_range();
|
||||||
ref_index->def.definition_extent = ref_cursor.get_extent();
|
ref_index->def.definition_extent = ref_cursor.get_extent();
|
||||||
@ -1234,7 +1237,8 @@ ClangCursor::VisitResult TemplateVisitor(ClangCursor cursor,
|
|||||||
case CXCursor_TemplateRef: {
|
case CXCursor_TemplateRef: {
|
||||||
ClangCursor ref_cursor = clang_getCursorReferenced(cursor.cx_cursor);
|
ClangCursor ref_cursor = clang_getCursorReferenced(cursor.cx_cursor);
|
||||||
if (ref_cursor.get_kind() == CXCursor_TemplateTemplateParameter) {
|
if (ref_cursor.get_kind() == CXCursor_TemplateTemplateParameter) {
|
||||||
IndexType* ref_index = db->Resolve(db->ToTypeId(ref_cursor.get_usr_hash()));
|
IndexType* ref_index =
|
||||||
|
db->Resolve(db->ToTypeId(ref_cursor.get_usr_hash()));
|
||||||
// TODO It seems difficult to get references to template template
|
// TODO It seems difficult to get references to template template
|
||||||
// parameters.
|
// parameters.
|
||||||
// CXCursor_TemplateTemplateParameter can be visited by visiting
|
// CXCursor_TemplateTemplateParameter can be visited by visiting
|
||||||
@ -1253,7 +1257,8 @@ ClangCursor::VisitResult TemplateVisitor(ClangCursor cursor,
|
|||||||
case CXCursor_TypeRef: {
|
case CXCursor_TypeRef: {
|
||||||
ClangCursor ref_cursor = clang_getCursorReferenced(cursor.cx_cursor);
|
ClangCursor ref_cursor = clang_getCursorReferenced(cursor.cx_cursor);
|
||||||
if (ref_cursor.get_kind() == CXCursor_TemplateTypeParameter) {
|
if (ref_cursor.get_kind() == CXCursor_TemplateTypeParameter) {
|
||||||
IndexType* ref_index = db->Resolve(db->ToTypeId(ref_cursor.get_usr_hash()));
|
IndexType* ref_index =
|
||||||
|
db->Resolve(db->ToTypeId(ref_cursor.get_usr_hash()));
|
||||||
// TODO It seems difficult to get a FunctionTemplate's template
|
// TODO It seems difficult to get a FunctionTemplate's template
|
||||||
// parameters.
|
// parameters.
|
||||||
// CXCursor_TemplateTypeParameter can be visited by visiting
|
// CXCursor_TemplateTypeParameter can be visited by visiting
|
||||||
@ -1451,7 +1456,7 @@ void OnIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
|
|||||||
if (decl->isDefinition && decl->semanticContainer) {
|
if (decl->isDefinition && decl->semanticContainer) {
|
||||||
if (IsFunctionCallContext(decl->semanticContainer->cursor.kind)) {
|
if (IsFunctionCallContext(decl->semanticContainer->cursor.kind)) {
|
||||||
IndexFuncId parent_func_id =
|
IndexFuncId parent_func_id =
|
||||||
db->ToFuncId(decl->semanticContainer->cursor);
|
db->ToFuncId(decl->semanticContainer->cursor);
|
||||||
var->def.parent_kind = SymbolKind::Func;
|
var->def.parent_kind = SymbolKind::Func;
|
||||||
var->def.parent_id = size_t(parent_func_id);
|
var->def.parent_id = size_t(parent_func_id);
|
||||||
} else if (IsTypeDefinition(decl->semanticContainer)) {
|
} else if (IsTypeDefinition(decl->semanticContainer)) {
|
||||||
@ -1689,7 +1694,7 @@ void OnIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
|
|||||||
ClangType enum_type = clang_getEnumDeclIntegerType(decl->cursor);
|
ClangType enum_type = clang_getEnumDeclIntegerType(decl->cursor);
|
||||||
if (!enum_type.is_fundamental()) {
|
if (!enum_type.is_fundamental()) {
|
||||||
IndexType* int_type =
|
IndexType* int_type =
|
||||||
db->Resolve(db->ToTypeId(enum_type.get_usr_hash()));
|
db->Resolve(db->ToTypeId(enum_type.get_usr_hash()));
|
||||||
int_type->uses.push_back(decl_spell);
|
int_type->uses.push_back(decl_spell);
|
||||||
// type is invalidated.
|
// type is invalidated.
|
||||||
type = db->Resolve(type_id);
|
type = db->Resolve(type_id);
|
||||||
@ -1699,42 +1704,44 @@ void OnIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
|
|||||||
UniqueAdd(type->uses, decl_spell);
|
UniqueAdd(type->uses, decl_spell);
|
||||||
|
|
||||||
switch (decl->entityInfo->templateKind) {
|
switch (decl->entityInfo->templateKind) {
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
case CXIdxEntity_TemplateSpecialization:
|
case CXIdxEntity_TemplateSpecialization:
|
||||||
case CXIdxEntity_TemplatePartialSpecialization: {
|
case CXIdxEntity_TemplatePartialSpecialization: {
|
||||||
// TODO Use a different dimension
|
// TODO Use a different dimension
|
||||||
ClangCursor origin_cursor =
|
ClangCursor origin_cursor =
|
||||||
decl_cursor.template_specialization_to_template_definition();
|
decl_cursor.template_specialization_to_template_definition();
|
||||||
IndexTypeId origin_id = db->ToTypeId(origin_cursor.get_usr_hash());
|
IndexTypeId origin_id = db->ToTypeId(origin_cursor.get_usr_hash());
|
||||||
IndexType* origin = db->Resolve(origin_id);
|
IndexType* origin = db->Resolve(origin_id);
|
||||||
// |type| may be invalidated.
|
// |type| may be invalidated.
|
||||||
type = db->Resolve(type_id);
|
type = db->Resolve(type_id);
|
||||||
// template<class T> class function; // not visited by OnIndexDeclaration
|
// template<class T> class function; // not visited by
|
||||||
// template<> class function<int> {}; // current cursor
|
// OnIndexDeclaration template<> class function<int> {}; // current
|
||||||
if (origin->def.short_name.empty()) {
|
// cursor
|
||||||
SetTypeName(origin, origin_cursor, nullptr,
|
if (origin->def.short_name.empty()) {
|
||||||
type->def.short_name.c_str(), ns);
|
SetTypeName(origin, origin_cursor, nullptr,
|
||||||
origin->def.kind = type->def.kind;
|
type->def.short_name.c_str(), ns);
|
||||||
|
origin->def.kind = type->def.kind;
|
||||||
|
}
|
||||||
|
// TODO The name may be assigned in |ResolveToDeclarationType| but
|
||||||
|
// |definition_spelling| is nullopt.
|
||||||
|
if (!origin->def.definition_spelling) {
|
||||||
|
origin->def.definition_spelling =
|
||||||
|
origin_cursor.get_spelling_range();
|
||||||
|
origin->def.definition_extent = origin_cursor.get_extent();
|
||||||
|
}
|
||||||
|
origin->derived.push_back(type_id);
|
||||||
|
type->def.parents.push_back(origin_id);
|
||||||
}
|
}
|
||||||
// TODO The name may be assigned in |ResolveToDeclarationType| but
|
// fallthrough
|
||||||
// |definition_spelling| is nullopt.
|
case CXIdxEntity_Template: {
|
||||||
if (!origin->def.definition_spelling) {
|
TemplateVisitorData data;
|
||||||
origin->def.definition_spelling = origin_cursor.get_spelling_range();
|
data.db = db;
|
||||||
origin->def.definition_extent = origin_cursor.get_extent();
|
data.container = decl_cursor;
|
||||||
|
data.param = param;
|
||||||
|
decl_cursor.VisitChildren(&TemplateVisitor, &data);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
origin->derived.push_back(type_id);
|
|
||||||
type->def.parents.push_back(origin_id);
|
|
||||||
}
|
|
||||||
// fallthrough
|
|
||||||
case CXIdxEntity_Template: {
|
|
||||||
TemplateVisitorData data;
|
|
||||||
data.db = db;
|
|
||||||
data.container = decl_cursor;
|
|
||||||
data.param = param;
|
|
||||||
decl_cursor.VisitChildren(&TemplateVisitor, &data);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// type_def->alias_of
|
// type_def->alias_of
|
||||||
@ -1978,7 +1985,8 @@ void OnIndexReference(CXClientData client_data, const CXIdxEntityRefInfo* ref) {
|
|||||||
case CXIdxEntity_CXXClass: {
|
case CXIdxEntity_CXXClass: {
|
||||||
ClangCursor ref_cursor = ref->referencedEntity->cursor;
|
ClangCursor ref_cursor = ref->referencedEntity->cursor;
|
||||||
ref_cursor = ref_cursor.template_specialization_to_template_definition();
|
ref_cursor = ref_cursor.template_specialization_to_template_definition();
|
||||||
IndexType* ref_type = db->Resolve(db->ToTypeId(ref_cursor.get_usr_hash()));
|
IndexType* ref_type =
|
||||||
|
db->Resolve(db->ToTypeId(ref_cursor.get_usr_hash()));
|
||||||
|
|
||||||
// The following will generate two TypeRefs to Foo, both located at the
|
// The following will generate two TypeRefs to Foo, both located at the
|
||||||
// same spot (line 3, column 3). One of the parents will be set to
|
// same spot (line 3, column 3). One of the parents will be set to
|
||||||
@ -1994,8 +2002,7 @@ void OnIndexReference(CXClientData client_data, const CXIdxEntityRefInfo* ref) {
|
|||||||
// Foo f;
|
// Foo f;
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
UniqueAdd(ref_type->uses,
|
UniqueAdd(ref_type->uses, ClangCursor(ref->cursor).get_spelling_range());
|
||||||
ClangCursor(ref->cursor).get_spelling_range());
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,9 +90,7 @@ struct RequestMessage : public BaseIpcMessage {
|
|||||||
lsRequestId id;
|
lsRequestId id;
|
||||||
RequestMessage() : BaseIpcMessage(T::kIpcId) {}
|
RequestMessage() : BaseIpcMessage(T::kIpcId) {}
|
||||||
|
|
||||||
lsRequestId GetRequestId() override {
|
lsRequestId GetRequestId() override { return id; }
|
||||||
return id;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// NotificationMessage does not have |id|.
|
// NotificationMessage does not have |id|.
|
||||||
|
@ -109,9 +109,9 @@ TEST_SUITE("FindIncludeLine") {
|
|||||||
|
|
||||||
optional<char> ReadCharFromStdinBlocking() {
|
optional<char> ReadCharFromStdinBlocking() {
|
||||||
// We do not use std::cin because it does not read bytes once stuck in
|
// We do not use std::cin because it does not read bytes once stuck in
|
||||||
// cin.bad(). We can call cin.clear() but C++ iostream has other annoyance like
|
// cin.bad(). We can call cin.clear() but C++ iostream has other annoyance
|
||||||
// std::{cin,cout} is tied by default, which causes undesired cout flush for
|
// like std::{cin,cout} is tied by default, which causes undesired cout flush
|
||||||
// cin operations.
|
// for cin operations.
|
||||||
int c = getchar();
|
int c = getchar();
|
||||||
if (c >= 0)
|
if (c >= 0)
|
||||||
return c;
|
return c;
|
||||||
@ -168,7 +168,8 @@ optional<std::string> MessageRegistry::Parse(
|
|||||||
// *message is partially deserialized but some field (e.g. |id|) are likely
|
// *message is partially deserialized but some field (e.g. |id|) are likely
|
||||||
// available.
|
// available.
|
||||||
return std::string("Fail to parse '") + method + "' " +
|
return std::string("Fail to parse '") + method + "' " +
|
||||||
static_cast<JsonReader&>(visitor).GetPath() + ", expected " + e.what();
|
static_cast<JsonReader&>(visitor).GetPath() + ", expected " +
|
||||||
|
e.what();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,7 +16,8 @@ int GetOffsetForPosition(lsPosition position, const std::string& content) {
|
|||||||
for (; position.character > 0 && i < content.size(); position.character--)
|
for (; position.character > 0 && i < content.size(); position.character--)
|
||||||
if (uint8_t(content[i++]) >= 128) {
|
if (uint8_t(content[i++]) >= 128) {
|
||||||
// Skip 0b10xxxxxx
|
// Skip 0b10xxxxxx
|
||||||
while (i < content.size() && uint8_t(content[i]) >= 128 && uint8_t(content[i]) < 192)
|
while (i < content.size() && uint8_t(content[i]) >= 128 &&
|
||||||
|
uint8_t(content[i]) < 192)
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
return int(i);
|
return int(i);
|
||||||
|
@ -25,7 +25,7 @@ struct WorkingFile;
|
|||||||
struct WorkingFiles;
|
struct WorkingFiles;
|
||||||
|
|
||||||
struct Out_CqueryPublishSemanticHighlighting
|
struct Out_CqueryPublishSemanticHighlighting
|
||||||
: public lsOutMessage<Out_CqueryPublishSemanticHighlighting> {
|
: public lsOutMessage<Out_CqueryPublishSemanticHighlighting> {
|
||||||
struct Symbol {
|
struct Symbol {
|
||||||
int stableId = 0;
|
int stableId = 0;
|
||||||
SymbolKind parentKind;
|
SymbolKind parentKind;
|
||||||
|
@ -14,7 +14,8 @@ struct Ipc_CqueryCallTreeInitial
|
|||||||
MAKE_REFLECT_STRUCT(Ipc_CqueryCallTreeInitial, id, params);
|
MAKE_REFLECT_STRUCT(Ipc_CqueryCallTreeInitial, id, params);
|
||||||
REGISTER_IPC_MESSAGE(Ipc_CqueryCallTreeInitial);
|
REGISTER_IPC_MESSAGE(Ipc_CqueryCallTreeInitial);
|
||||||
|
|
||||||
struct Ipc_CqueryCallTreeExpand : public RequestMessage<Ipc_CqueryCallTreeExpand> {
|
struct Ipc_CqueryCallTreeExpand
|
||||||
|
: public RequestMessage<Ipc_CqueryCallTreeExpand> {
|
||||||
const static IpcId kIpcId = IpcId::CqueryCallTreeExpand;
|
const static IpcId kIpcId = IpcId::CqueryCallTreeExpand;
|
||||||
struct Params {
|
struct Params {
|
||||||
std::string usr;
|
std::string usr;
|
||||||
|
@ -24,7 +24,7 @@ struct CqueryDerivedHandler : BaseMessageHandler<Ipc_CqueryDerived> {
|
|||||||
Out_LocationList out;
|
Out_LocationList out;
|
||||||
out.id = request->id;
|
out.id = request->id;
|
||||||
std::vector<SymbolRef> refs =
|
std::vector<SymbolRef> refs =
|
||||||
FindSymbolsAtLocation(working_file, file, request->params.position);
|
FindSymbolsAtLocation(working_file, file, request->params.position);
|
||||||
// A template definition may be a use of its primary template.
|
// A template definition may be a use of its primary template.
|
||||||
// We want to get the definition instead of the use.
|
// We want to get the definition instead of the use.
|
||||||
// Order by |Definition| DESC, range size ASC.
|
// Order by |Definition| DESC, range size ASC.
|
||||||
|
@ -12,7 +12,8 @@
|
|||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
struct Ipc_CqueryFreshenIndex : public NotificationMessage<Ipc_CqueryFreshenIndex> {
|
struct Ipc_CqueryFreshenIndex
|
||||||
|
: public NotificationMessage<Ipc_CqueryFreshenIndex> {
|
||||||
const static IpcId kIpcId = IpcId::CqueryFreshenIndex;
|
const static IpcId kIpcId = IpcId::CqueryFreshenIndex;
|
||||||
struct Params {
|
struct Params {
|
||||||
bool dependencies = true;
|
bool dependencies = true;
|
||||||
@ -21,7 +22,10 @@ struct Ipc_CqueryFreshenIndex : public NotificationMessage<Ipc_CqueryFreshenInde
|
|||||||
};
|
};
|
||||||
Params params;
|
Params params;
|
||||||
};
|
};
|
||||||
MAKE_REFLECT_STRUCT(Ipc_CqueryFreshenIndex::Params, dependencies, whitelist, blacklist);
|
MAKE_REFLECT_STRUCT(Ipc_CqueryFreshenIndex::Params,
|
||||||
|
dependencies,
|
||||||
|
whitelist,
|
||||||
|
blacklist);
|
||||||
MAKE_REFLECT_STRUCT(Ipc_CqueryFreshenIndex, params);
|
MAKE_REFLECT_STRUCT(Ipc_CqueryFreshenIndex, params);
|
||||||
REGISTER_IPC_MESSAGE(Ipc_CqueryFreshenIndex);
|
REGISTER_IPC_MESSAGE(Ipc_CqueryFreshenIndex);
|
||||||
|
|
||||||
|
@ -33,16 +33,11 @@ struct Out_CqueryMemberHierarchy
|
|||||||
lsRequestId id;
|
lsRequestId id;
|
||||||
std::vector<Entry> result;
|
std::vector<Entry> result;
|
||||||
};
|
};
|
||||||
MAKE_REFLECT_STRUCT(Out_CqueryMemberHierarchy::Entry,
|
MAKE_REFLECT_STRUCT(Out_CqueryMemberHierarchy::Entry, name, type_id, location);
|
||||||
name,
|
|
||||||
type_id,
|
|
||||||
location);
|
|
||||||
MAKE_REFLECT_STRUCT(Out_CqueryMemberHierarchy, jsonrpc, id, result);
|
MAKE_REFLECT_STRUCT(Out_CqueryMemberHierarchy, jsonrpc, id, result);
|
||||||
|
|
||||||
std::vector<Out_CqueryMemberHierarchy::Entry> BuildInitial(
|
std::vector<Out_CqueryMemberHierarchy::Entry>
|
||||||
QueryDatabase* db,
|
BuildInitial(QueryDatabase* db, WorkingFiles* working_files, QueryTypeId root) {
|
||||||
WorkingFiles* working_files,
|
|
||||||
QueryTypeId root) {
|
|
||||||
QueryType& root_type = db->types[root.id];
|
QueryType& root_type = db->types[root.id];
|
||||||
if (!root_type.def || !root_type.def->definition_spelling)
|
if (!root_type.def || !root_type.def->definition_spelling)
|
||||||
return {};
|
return {};
|
||||||
@ -59,9 +54,7 @@ std::vector<Out_CqueryMemberHierarchy::Entry> BuildInitial(
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Out_CqueryMemberHierarchy::Entry>
|
std::vector<Out_CqueryMemberHierarchy::Entry>
|
||||||
ExpandNode(QueryDatabase* db,
|
ExpandNode(QueryDatabase* db, WorkingFiles* working_files, QueryTypeId root) {
|
||||||
WorkingFiles* working_files,
|
|
||||||
QueryTypeId root) {
|
|
||||||
QueryType& root_type = db->types[root.id];
|
QueryType& root_type = db->types[root.id];
|
||||||
if (!root_type.def)
|
if (!root_type.def)
|
||||||
return {};
|
return {};
|
||||||
@ -99,7 +92,7 @@ struct CqueryMemberHierarchyInitialHandler
|
|||||||
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) {
|
if (ref.idx.kind == SymbolKind::Type) {
|
||||||
out.result = BuildInitial(db, working_files, QueryTypeId(ref.idx.idx));
|
out.result = BuildInitial(db, working_files, QueryTypeId(ref.idx.idx));
|
||||||
break;
|
break;
|
||||||
|
@ -421,7 +421,7 @@ void Reflect(Reader& reader, lsInitializeParams::lsTrace& value) {
|
|||||||
value = lsInitializeParams::lsTrace::Verbose;
|
value = lsInitializeParams::lsTrace::Verbose;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0 // unused
|
#if 0 // unused
|
||||||
void Reflect(Writer& writer, lsInitializeParams::lsTrace& value) {
|
void Reflect(Writer& writer, lsInitializeParams::lsTrace& value) {
|
||||||
switch (value) {
|
switch (value) {
|
||||||
case lsInitializeParams::lsTrace::Off:
|
case lsInitializeParams::lsTrace::Off:
|
||||||
@ -610,20 +610,19 @@ struct InitializeHandler : BaseMessageHandler<Ipc_InitializeRequest> {
|
|||||||
|
|
||||||
auto* queue = QueueManager::instance();
|
auto* queue = QueueManager::instance();
|
||||||
time.Reset();
|
time.Reset();
|
||||||
project->ForAllFilteredFiles(
|
project->ForAllFilteredFiles(config, [&](int i,
|
||||||
config, [&](int i, const Project::Entry& entry) {
|
const Project::Entry& entry) {
|
||||||
optional<std::string> content = ReadContent(entry.filename);
|
optional<std::string> content = ReadContent(entry.filename);
|
||||||
if (!content) {
|
if (!content) {
|
||||||
LOG_S(ERROR) << "When loading project, canont read file "
|
LOG_S(ERROR) << "When loading project, canont read file "
|
||||||
<< entry.filename;
|
<< entry.filename;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
bool is_interactive =
|
bool is_interactive =
|
||||||
working_files->GetFileByFilename(entry.filename) != nullptr;
|
working_files->GetFileByFilename(entry.filename) != nullptr;
|
||||||
queue->index_request.Enqueue(
|
queue->index_request.Enqueue(Index_Request(
|
||||||
Index_Request(entry.filename, entry.args, is_interactive,
|
entry.filename, entry.args, is_interactive, *content, request->id));
|
||||||
*content, request->id));
|
});
|
||||||
});
|
|
||||||
|
|
||||||
// We need to support multiple concurrent index processes.
|
// We need to support multiple concurrent index processes.
|
||||||
time.ResetAndPrint("[perf] Dispatched initial index requests");
|
time.ResetAndPrint("[perf] Dispatched initial index requests");
|
||||||
|
@ -173,11 +173,13 @@ struct TextDocumentCodeLensHandler
|
|||||||
|
|
||||||
int16_t offset = 0;
|
int16_t offset = 0;
|
||||||
|
|
||||||
// For functions, the outline will report a location that is using the extent since that is better for outline. This tries to convert the extent location to the spelling location.
|
// For functions, the outline will report a location that is using the
|
||||||
|
// extent since that is better for outline. This tries to convert the
|
||||||
|
// extent location to the spelling location.
|
||||||
auto try_ensure_spelling = [&](SymbolRef sym) {
|
auto try_ensure_spelling = [&](SymbolRef sym) {
|
||||||
optional<QueryLocation> def = GetDefinitionSpellingOfSymbol(db, sym.idx);
|
optional<QueryLocation> def =
|
||||||
if (!def ||
|
GetDefinitionSpellingOfSymbol(db, sym.idx);
|
||||||
def->path != sym.loc.path ||
|
if (!def || def->path != sym.loc.path ||
|
||||||
def->range.start.line != sym.loc.range.start.line) {
|
def->range.start.line != sym.loc.range.start.line) {
|
||||||
return sym.loc;
|
return sym.loc;
|
||||||
}
|
}
|
||||||
|
@ -316,9 +316,8 @@ struct TextDocumentCompletionHandler : MessageHandler {
|
|||||||
// results Only do this when trigger is not manual or context doesn't
|
// results Only do this when trigger is not manual or context doesn't
|
||||||
// exist (for Atom support).
|
// exist (for Atom support).
|
||||||
if (existing_completion.empty() && is_global_completion &&
|
if (existing_completion.empty() && is_global_completion &&
|
||||||
(request->params.context &&
|
(request->params.context && request->params.context->triggerKind !=
|
||||||
request->params.context->triggerKind !=
|
lsCompletionTriggerKind::Invoked)) {
|
||||||
lsCompletionTriggerKind::Invoked)) {
|
|
||||||
LOG_S(INFO) << "Existing completion is empty, no completion results "
|
LOG_S(INFO) << "Existing completion is empty, no completion results "
|
||||||
"will be returned";
|
"will be returned";
|
||||||
Out_TextDocumentComplete out;
|
Out_TextDocumentComplete out;
|
||||||
@ -336,9 +335,8 @@ struct TextDocumentCompletionHandler : MessageHandler {
|
|||||||
out.result.items = results;
|
out.result.items = results;
|
||||||
|
|
||||||
// Emit completion results.
|
// Emit completion results.
|
||||||
FilterAndSortCompletionResponse(
|
FilterAndSortCompletionResponse(&out, existing_completion,
|
||||||
&out, existing_completion,
|
config->completion.filterAndSort);
|
||||||
config->completion.filterAndSort);
|
|
||||||
QueueManager::WriteStdout(IpcId::TextDocumentCompletion, out);
|
QueueManager::WriteStdout(IpcId::TextDocumentCompletion, out);
|
||||||
|
|
||||||
// Cache completion results.
|
// Cache completion results.
|
||||||
|
@ -15,8 +15,7 @@ struct Ipc_TextDocumentDocumentLink
|
|||||||
};
|
};
|
||||||
Params params;
|
Params params;
|
||||||
};
|
};
|
||||||
MAKE_REFLECT_STRUCT(Ipc_TextDocumentDocumentLink::Params,
|
MAKE_REFLECT_STRUCT(Ipc_TextDocumentDocumentLink::Params, textDocument);
|
||||||
textDocument);
|
|
||||||
MAKE_REFLECT_STRUCT(Ipc_TextDocumentDocumentLink, id, params);
|
MAKE_REFLECT_STRUCT(Ipc_TextDocumentDocumentLink, id, params);
|
||||||
REGISTER_IPC_MESSAGE(Ipc_TextDocumentDocumentLink);
|
REGISTER_IPC_MESSAGE(Ipc_TextDocumentDocumentLink);
|
||||||
|
|
||||||
@ -58,8 +57,8 @@ struct TextDocumentDocumentLinkHandler
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (const IndexInclude& include : file->def->includes) {
|
for (const IndexInclude& include : file->def->includes) {
|
||||||
optional<int> buffer_line =
|
optional<int> buffer_line = working_file->GetBufferPosFromIndexPos(
|
||||||
working_file->GetBufferPosFromIndexPos(include.line, nullptr, false);
|
include.line, nullptr, false);
|
||||||
if (!buffer_line)
|
if (!buffer_line)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -571,8 +571,8 @@ TEST_SUITE("Project") {
|
|||||||
/* raw */ {"clang.exe"},
|
/* raw */ {"clang.exe"},
|
||||||
/* expected */
|
/* expected */
|
||||||
{"clang.exe", "-working-directory", "/dir/", "-xc++", "-std=c++14",
|
{"clang.exe", "-working-directory", "/dir/", "-xc++", "-std=c++14",
|
||||||
"-resource-dir=/w/resource_dir/", "-Wno-unknown-warning-option",
|
"-resource-dir=/w/resource_dir/", "-Wno-unknown-warning-option",
|
||||||
"-fparse-all-comments"});
|
"-fparse-all-comments"});
|
||||||
|
|
||||||
CheckFlags(
|
CheckFlags(
|
||||||
/* raw */ {"goma", "clang"},
|
/* raw */ {"goma", "clang"},
|
||||||
@ -974,8 +974,7 @@ TEST_SUITE("Project") {
|
|||||||
"lock_screen_sanity_unittest.cc",
|
"lock_screen_sanity_unittest.cc",
|
||||||
"-resource-dir=/w/resource_dir/",
|
"-resource-dir=/w/resource_dir/",
|
||||||
"-Wno-unknown-warning-option",
|
"-Wno-unknown-warning-option",
|
||||||
"-fparse-all-comments"
|
"-fparse-all-comments"});
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checks flag parsing for an example chromium file.
|
// Checks flag parsing for an example chromium file.
|
||||||
@ -1300,8 +1299,7 @@ TEST_SUITE("Project") {
|
|||||||
"&/w/c/s/out/Release/../../apps/app_lifetime_monitor.cc",
|
"&/w/c/s/out/Release/../../apps/app_lifetime_monitor.cc",
|
||||||
"-resource-dir=/w/resource_dir/",
|
"-resource-dir=/w/resource_dir/",
|
||||||
"-Wno-unknown-warning-option",
|
"-Wno-unknown-warning-option",
|
||||||
"-fparse-all-comments"
|
"-fparse-all-comments"});
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Directory extraction") {
|
TEST_CASE("Directory extraction") {
|
||||||
|
13
src/query.cc
13
src/query.cc
@ -243,7 +243,8 @@ QueryFile::Def BuildFileDef(const IdMap& id_map, const IndexFile& indexed) {
|
|||||||
if (func.def.definition_extent.has_value())
|
if (func.def.definition_extent.has_value())
|
||||||
add_outline(id_map.ToSymbol(func.id), func.def.definition_extent.value());
|
add_outline(id_map.ToSymbol(func.id), func.def.definition_extent.value());
|
||||||
for (const IndexFunc::Declaration& decl : func.declarations) {
|
for (const IndexFunc::Declaration& decl : func.declarations) {
|
||||||
add_all_symbols(id_map.ToSymbol(func.id), SymbolRole::Declaration, decl.spelling);
|
add_all_symbols(id_map.ToSymbol(func.id), SymbolRole::Declaration,
|
||||||
|
decl.spelling);
|
||||||
add_outline(id_map.ToSymbol(func.id), decl.spelling);
|
add_outline(id_map.ToSymbol(func.id), decl.spelling);
|
||||||
}
|
}
|
||||||
for (const IndexFuncRef& caller : func.callers) {
|
for (const IndexFuncRef& caller : func.callers) {
|
||||||
@ -321,8 +322,8 @@ inline optional<QueryTypeId> GetQueryTypeIdFromUsr(QueryDatabase* query_db,
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline optional<QueryFuncId> GetQueryFuncIdFromUsr(QueryDatabase* query_db,
|
inline optional<QueryFuncId> GetQueryFuncIdFromUsr(QueryDatabase* query_db,
|
||||||
Usr usr,
|
Usr usr,
|
||||||
bool create_if_missing) {
|
bool create_if_missing) {
|
||||||
auto it = query_db->usr_to_func.find(usr);
|
auto it = query_db->usr_to_func.find(usr);
|
||||||
if (it != query_db->usr_to_func.end())
|
if (it != query_db->usr_to_func.end())
|
||||||
return QueryFuncId(it->second.id);
|
return QueryFuncId(it->second.id);
|
||||||
@ -336,8 +337,8 @@ inline optional<QueryFuncId> GetQueryFuncIdFromUsr(QueryDatabase* query_db,
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline optional<QueryVarId> GetQueryVarIdFromUsr(QueryDatabase* query_db,
|
inline optional<QueryVarId> GetQueryVarIdFromUsr(QueryDatabase* query_db,
|
||||||
Usr usr,
|
Usr usr,
|
||||||
bool create_if_missing) {
|
bool create_if_missing) {
|
||||||
auto it = query_db->usr_to_var.find(usr);
|
auto it = query_db->usr_to_var.find(usr);
|
||||||
if (it != query_db->usr_to_var.end())
|
if (it != query_db->usr_to_var.end())
|
||||||
return QueryVarId(it->second.id);
|
return QueryVarId(it->second.id);
|
||||||
@ -809,7 +810,7 @@ void QueryDatabase::ApplyIndexUpdate(IndexUpdate* update) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (const std::string& filename : update->files_removed)
|
for (const std::string& filename : update->files_removed)
|
||||||
files[usr_to_file[filename].id].def = nullopt;
|
files[usr_to_file[filename].id].def = nullopt;
|
||||||
ImportOrUpdate(update->files_def_update);
|
ImportOrUpdate(update->files_def_update);
|
||||||
|
|
||||||
RemoveUsrs(SymbolKind::Type, update->types_removed);
|
RemoveUsrs(SymbolKind::Type, update->types_removed);
|
||||||
|
@ -119,7 +119,7 @@ struct QueryFuncRef {
|
|||||||
bool operator!=(const QueryFuncRef& that) const { return !(*this == that); }
|
bool operator!=(const QueryFuncRef& that) const { return !(*this == that); }
|
||||||
bool operator<(const QueryFuncRef& that) const {
|
bool operator<(const QueryFuncRef& that) const {
|
||||||
if (id_ != that.id_)
|
if (id_ != that.id_)
|
||||||
return id_ < that.id_;
|
return id_ < that.id_;
|
||||||
if (loc != that.loc)
|
if (loc != that.loc)
|
||||||
return loc < that.loc;
|
return loc < that.loc;
|
||||||
return is_implicit < that.is_implicit;
|
return is_implicit < that.is_implicit;
|
||||||
|
@ -209,8 +209,7 @@ std::vector<QueryLocation> GetUsesOfSymbol(QueryDatabase* db,
|
|||||||
if (include_decl) {
|
if (include_decl) {
|
||||||
if (var.def && var.def->definition_spelling)
|
if (var.def && var.def->definition_spelling)
|
||||||
ret.push_back(*var.def->definition_spelling);
|
ret.push_back(*var.def->definition_spelling);
|
||||||
ret.insert(ret.end(), var.declarations.begin(),
|
ret.insert(ret.end(), var.declarations.begin(), var.declarations.end());
|
||||||
var.declarations.end());
|
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -326,7 +325,8 @@ optional<lsPosition> GetLsPosition(WorkingFile* working_file,
|
|||||||
return lsPosition(position.line, position.column);
|
return lsPosition(position.line, position.column);
|
||||||
|
|
||||||
int column = position.column;
|
int column = position.column;
|
||||||
optional<int> start = working_file->GetBufferPosFromIndexPos(position.line, &column, false);
|
optional<int> start =
|
||||||
|
working_file->GetBufferPosFromIndexPos(position.line, &column, false);
|
||||||
if (!start)
|
if (!start)
|
||||||
return nullopt;
|
return nullopt;
|
||||||
|
|
||||||
@ -335,16 +335,15 @@ optional<lsPosition> GetLsPosition(WorkingFile* working_file,
|
|||||||
|
|
||||||
optional<lsRange> GetLsRange(WorkingFile* working_file, const Range& location) {
|
optional<lsRange> GetLsRange(WorkingFile* working_file, const Range& location) {
|
||||||
if (!working_file) {
|
if (!working_file) {
|
||||||
return lsRange(
|
return lsRange(lsPosition(location.start.line, location.start.column),
|
||||||
lsPosition(location.start.line, location.start.column),
|
lsPosition(location.end.line, location.end.column));
|
||||||
lsPosition(location.end.line, location.end.column));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int start_column = location.start.column, end_column = location.end.column;
|
int start_column = location.start.column, end_column = location.end.column;
|
||||||
optional<int> start =
|
optional<int> start = working_file->GetBufferPosFromIndexPos(
|
||||||
working_file->GetBufferPosFromIndexPos(location.start.line, &start_column, false);
|
location.start.line, &start_column, false);
|
||||||
optional<int> end =
|
optional<int> end = working_file->GetBufferPosFromIndexPos(location.end.line,
|
||||||
working_file->GetBufferPosFromIndexPos(location.end.line, &end_column, true);
|
&end_column, true);
|
||||||
if (!start || !end)
|
if (!start || !end)
|
||||||
return nullopt;
|
return nullopt;
|
||||||
|
|
||||||
@ -444,12 +443,12 @@ optional<lsSymbolInformation> GetSymbolInfo(QueryDatabase* db,
|
|||||||
info.containerName = type.def->detailed_name;
|
info.containerName = type.def->detailed_name;
|
||||||
// TODO ClangSymbolKind -> lsSymbolKind
|
// TODO ClangSymbolKind -> lsSymbolKind
|
||||||
switch (type.def->kind) {
|
switch (type.def->kind) {
|
||||||
default:
|
default:
|
||||||
info.kind = lsSymbolKind::Class;
|
info.kind = lsSymbolKind::Class;
|
||||||
break;
|
break;
|
||||||
case ClangSymbolKind::Namespace:
|
case ClangSymbolKind::Namespace:
|
||||||
info.kind = lsSymbolKind::Namespace;
|
info.kind = lsSymbolKind::Namespace;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
@ -523,19 +522,20 @@ std::vector<SymbolRef> FindSymbolsAtLocation(WorkingFile* working_file,
|
|||||||
//
|
//
|
||||||
// Then order functions before other types, which makes goto definition work
|
// Then order functions before other types, which makes goto definition work
|
||||||
// better on constructors.
|
// better on constructors.
|
||||||
std::sort(symbols.begin(), symbols.end(), [](const SymbolRef& a,
|
std::sort(symbols.begin(), symbols.end(),
|
||||||
const SymbolRef& b) {
|
[](const SymbolRef& a, const SymbolRef& b) {
|
||||||
int a_size = ComputeRangeSize(a.loc.range);
|
int a_size = ComputeRangeSize(a.loc.range);
|
||||||
int b_size = ComputeRangeSize(b.loc.range);
|
int b_size = ComputeRangeSize(b.loc.range);
|
||||||
|
|
||||||
if (a_size != b_size)
|
if (a_size != b_size)
|
||||||
return a_size < b_size;
|
return a_size < b_size;
|
||||||
// operator> orders Var/Func before Type.
|
// operator> orders Var/Func before Type.
|
||||||
int t = static_cast<int>(a.idx.kind) - static_cast<int>(b.idx.kind);
|
int t =
|
||||||
if (t)
|
static_cast<int>(a.idx.kind) - static_cast<int>(b.idx.kind);
|
||||||
return t > 0;
|
if (t)
|
||||||
return a.idx.idx < b.idx.idx;
|
return t > 0;
|
||||||
});
|
return a.idx.idx < b.idx.idx;
|
||||||
|
});
|
||||||
|
|
||||||
return symbols;
|
return symbols;
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ struct Index_Request {
|
|||||||
const std::vector<std::string>& args,
|
const std::vector<std::string>& args,
|
||||||
bool is_interactive,
|
bool is_interactive,
|
||||||
const std::string& contents,
|
const std::string& contents,
|
||||||
lsRequestId id={});
|
lsRequestId id = {});
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Index_DoIdMap {
|
struct Index_DoIdMap {
|
||||||
|
@ -17,7 +17,8 @@ bool gTestOutputMode = false;
|
|||||||
//// Elementary types
|
//// Elementary types
|
||||||
|
|
||||||
void Reflect(Reader& visitor, uint8_t& value) {
|
void Reflect(Reader& visitor, uint8_t& value) {
|
||||||
if (!visitor.IsInt()) throw std::invalid_argument("uint8_t");
|
if (!visitor.IsInt())
|
||||||
|
throw std::invalid_argument("uint8_t");
|
||||||
value = (uint8_t)visitor.GetInt();
|
value = (uint8_t)visitor.GetInt();
|
||||||
}
|
}
|
||||||
void Reflect(Writer& visitor, uint8_t& value) {
|
void Reflect(Writer& visitor, uint8_t& value) {
|
||||||
@ -25,7 +26,8 @@ void Reflect(Writer& visitor, uint8_t& value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Reflect(Reader& visitor, int16_t& value) {
|
void Reflect(Reader& visitor, int16_t& value) {
|
||||||
if (!visitor.IsInt()) throw std::invalid_argument("int16_t");
|
if (!visitor.IsInt())
|
||||||
|
throw std::invalid_argument("int16_t");
|
||||||
value = (int16_t)visitor.GetInt();
|
value = (int16_t)visitor.GetInt();
|
||||||
}
|
}
|
||||||
void Reflect(Writer& visitor, int16_t& value) {
|
void Reflect(Writer& visitor, int16_t& value) {
|
||||||
@ -33,7 +35,8 @@ void Reflect(Writer& visitor, int16_t& value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Reflect(Reader& visitor, int& value) {
|
void Reflect(Reader& visitor, int& value) {
|
||||||
if (!visitor.IsInt()) throw std::invalid_argument("int");
|
if (!visitor.IsInt())
|
||||||
|
throw std::invalid_argument("int");
|
||||||
value = visitor.GetInt();
|
value = visitor.GetInt();
|
||||||
}
|
}
|
||||||
void Reflect(Writer& visitor, int& value) {
|
void Reflect(Writer& visitor, int& value) {
|
||||||
@ -41,7 +44,8 @@ void Reflect(Writer& visitor, int& value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Reflect(Reader& visitor, unsigned& value) {
|
void Reflect(Reader& visitor, unsigned& value) {
|
||||||
if (!visitor.IsInt()) throw std::invalid_argument("unsigned");
|
if (!visitor.IsInt())
|
||||||
|
throw std::invalid_argument("unsigned");
|
||||||
value = visitor.GetUint32();
|
value = visitor.GetUint32();
|
||||||
}
|
}
|
||||||
void Reflect(Writer& visitor, unsigned& value) {
|
void Reflect(Writer& visitor, unsigned& value) {
|
||||||
@ -49,7 +53,8 @@ void Reflect(Writer& visitor, unsigned& value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Reflect(Reader& visitor, long& value) {
|
void Reflect(Reader& visitor, long& value) {
|
||||||
if (!visitor.IsInt64()) throw std::invalid_argument("long");
|
if (!visitor.IsInt64())
|
||||||
|
throw std::invalid_argument("long");
|
||||||
value = long(visitor.GetInt64());
|
value = long(visitor.GetInt64());
|
||||||
}
|
}
|
||||||
void Reflect(Writer& visitor, long& value) {
|
void Reflect(Writer& visitor, long& value) {
|
||||||
@ -57,7 +62,8 @@ void Reflect(Writer& visitor, long& value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Reflect(Reader& visitor, unsigned long& value) {
|
void Reflect(Reader& visitor, unsigned long& value) {
|
||||||
if (!visitor.IsUint64()) throw std::invalid_argument("unsigned long");
|
if (!visitor.IsUint64())
|
||||||
|
throw std::invalid_argument("unsigned long");
|
||||||
value = (unsigned long)visitor.GetUint64();
|
value = (unsigned long)visitor.GetUint64();
|
||||||
}
|
}
|
||||||
void Reflect(Writer& visitor, unsigned long& value) {
|
void Reflect(Writer& visitor, unsigned long& value) {
|
||||||
@ -65,7 +71,8 @@ void Reflect(Writer& visitor, unsigned long& value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Reflect(Reader& visitor, long long& value) {
|
void Reflect(Reader& visitor, long long& value) {
|
||||||
if (!visitor.IsInt64()) throw std::invalid_argument("long long");
|
if (!visitor.IsInt64())
|
||||||
|
throw std::invalid_argument("long long");
|
||||||
value = visitor.GetInt64();
|
value = visitor.GetInt64();
|
||||||
}
|
}
|
||||||
void Reflect(Writer& visitor, long long& value) {
|
void Reflect(Writer& visitor, long long& value) {
|
||||||
@ -73,7 +80,8 @@ void Reflect(Writer& visitor, long long& value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Reflect(Reader& visitor, unsigned long long& value) {
|
void Reflect(Reader& visitor, unsigned long long& value) {
|
||||||
if (!visitor.IsUint64()) throw std::invalid_argument("unsigned long long");
|
if (!visitor.IsUint64())
|
||||||
|
throw std::invalid_argument("unsigned long long");
|
||||||
value = visitor.GetUint64();
|
value = visitor.GetUint64();
|
||||||
}
|
}
|
||||||
void Reflect(Writer& visitor, unsigned long long& value) {
|
void Reflect(Writer& visitor, unsigned long long& value) {
|
||||||
@ -81,7 +89,8 @@ void Reflect(Writer& visitor, unsigned long long& value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Reflect(Reader& visitor, double& value) {
|
void Reflect(Reader& visitor, double& value) {
|
||||||
if (!visitor.IsDouble()) throw std::invalid_argument("double");
|
if (!visitor.IsDouble())
|
||||||
|
throw std::invalid_argument("double");
|
||||||
value = visitor.GetDouble();
|
value = visitor.GetDouble();
|
||||||
}
|
}
|
||||||
void Reflect(Writer& visitor, double& value) {
|
void Reflect(Writer& visitor, double& value) {
|
||||||
@ -89,7 +98,8 @@ void Reflect(Writer& visitor, double& value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Reflect(Reader& visitor, bool& value) {
|
void Reflect(Reader& visitor, bool& value) {
|
||||||
if (!visitor.IsBool()) throw std::invalid_argument("bool");
|
if (!visitor.IsBool())
|
||||||
|
throw std::invalid_argument("bool");
|
||||||
value = visitor.GetBool();
|
value = visitor.GetBool();
|
||||||
}
|
}
|
||||||
void Reflect(Writer& visitor, bool& value) {
|
void Reflect(Writer& visitor, bool& value) {
|
||||||
@ -98,7 +108,8 @@ void Reflect(Writer& visitor, bool& value) {
|
|||||||
|
|
||||||
// std::string
|
// std::string
|
||||||
void Reflect(Reader& visitor, std::string& value) {
|
void Reflect(Reader& visitor, std::string& value) {
|
||||||
if (!visitor.IsString()) throw std::invalid_argument("std::string");
|
if (!visitor.IsString())
|
||||||
|
throw std::invalid_argument("std::string");
|
||||||
value = visitor.GetString();
|
value = visitor.GetString();
|
||||||
}
|
}
|
||||||
void Reflect(Writer& visitor, std::string& value) {
|
void Reflect(Writer& visitor, std::string& value) {
|
||||||
@ -314,8 +325,7 @@ std::unique_ptr<IndexFile> Deserialize(SerializeFormat format,
|
|||||||
Reflect(json_reader, *file);
|
Reflect(json_reader, *file);
|
||||||
} catch (std::invalid_argument& e) {
|
} catch (std::invalid_argument& e) {
|
||||||
LOG_S(INFO) << "'" << path << "': failed to deserialize "
|
LOG_S(INFO) << "'" << path << "': failed to deserialize "
|
||||||
<< json_reader.GetPath() << "."
|
<< json_reader.GetPath() << "." << e.what();
|
||||||
<< e.what();
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -79,15 +79,15 @@ struct IndexFile;
|
|||||||
#define REFLECT_MEMBER2(name, value) ReflectMember(visitor, name, value)
|
#define REFLECT_MEMBER2(name, value) ReflectMember(visitor, name, value)
|
||||||
|
|
||||||
// TODO Make it inline because this macro can be used in header files.
|
// TODO Make it inline because this macro can be used in header files.
|
||||||
#define MAKE_REFLECT_TYPE_PROXY(type, as_type) \
|
#define MAKE_REFLECT_TYPE_PROXY(type, as_type) \
|
||||||
ATTRIBUTE_UNUSED inline void Reflect(Reader& visitor, type& value) { \
|
ATTRIBUTE_UNUSED inline void Reflect(Reader& visitor, type& value) { \
|
||||||
as_type value0; \
|
as_type value0; \
|
||||||
::Reflect(visitor, value0); \
|
::Reflect(visitor, value0); \
|
||||||
value = static_cast<type>(value0); \
|
value = static_cast<type>(value0); \
|
||||||
} \
|
} \
|
||||||
ATTRIBUTE_UNUSED inline void Reflect(Writer& visitor, type& value) { \
|
ATTRIBUTE_UNUSED inline void Reflect(Writer& visitor, type& value) { \
|
||||||
auto value0 = static_cast<as_type>(value); \
|
auto value0 = static_cast<as_type>(value); \
|
||||||
::Reflect(visitor, value0); \
|
::Reflect(visitor, value0); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define _MAPPABLE_REFLECT_MEMBER(name) REFLECT_MEMBER(name);
|
#define _MAPPABLE_REFLECT_MEMBER(name) REFLECT_MEMBER(name);
|
||||||
@ -229,7 +229,7 @@ struct disjunction
|
|||||||
: std::conditional<bool(B0::value), B0, disjunction<Bs...>>::type {};
|
: std::conditional<bool(B0::value), B0, disjunction<Bs...>>::type {};
|
||||||
template <typename B0>
|
template <typename B0>
|
||||||
struct disjunction<B0> : B0 {};
|
struct disjunction<B0> : B0 {};
|
||||||
}
|
} // namespace
|
||||||
|
|
||||||
// Helper struct to reflect std::variant
|
// Helper struct to reflect std::variant
|
||||||
template <size_t N, typename... Ts>
|
template <size_t N, typename... Ts>
|
||||||
@ -255,8 +255,8 @@ struct ReflectVariant {
|
|||||||
// Based on tag dispatch, call different ReflectTag helper.
|
// Based on tag dispatch, call different ReflectTag helper.
|
||||||
if (visitor.IsNull())
|
if (visitor.IsNull())
|
||||||
ReflectTag<std::monostate>(visitor, value);
|
ReflectTag<std::monostate>(visitor, value);
|
||||||
// It is possible that IsInt64() && IsInt(). We don't call ReflectTag<int> if
|
// It is possible that IsInt64() && IsInt(). We don't call ReflectTag<int>
|
||||||
// int is not in Ts...
|
// if int is not in Ts...
|
||||||
else if (disjunction<std::is_same<int, Ts>...>::value && visitor.IsInt())
|
else if (disjunction<std::is_same<int, Ts>...>::value && visitor.IsInt())
|
||||||
ReflectTag<int>(visitor, value);
|
ReflectTag<int>(visitor, value);
|
||||||
else if (visitor.IsInt64())
|
else if (visitor.IsInt64())
|
||||||
|
@ -56,9 +56,9 @@ void Timer::Resume() {
|
|||||||
start_ = Clock::now();
|
start_ = Clock::now();
|
||||||
}
|
}
|
||||||
|
|
||||||
ScopedPerfTimer::ScopedPerfTimer(const std::string& message) : message_(message) {}
|
ScopedPerfTimer::ScopedPerfTimer(const std::string& message)
|
||||||
|
: message_(message) {}
|
||||||
|
|
||||||
ScopedPerfTimer::~ScopedPerfTimer() {
|
ScopedPerfTimer::~ScopedPerfTimer() {
|
||||||
timer_.ResetAndPrint(message_);
|
timer_.ResetAndPrint(message_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,9 +3,9 @@
|
|||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
|
|
||||||
#include <doctest/doctest.h>
|
#include <doctest/doctest.h>
|
||||||
|
#include <siphash.h>
|
||||||
#include <tinydir.h>
|
#include <tinydir.h>
|
||||||
#include <loguru/loguru.hpp>
|
#include <loguru/loguru.hpp>
|
||||||
#include <siphash.h>
|
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
@ -110,9 +110,10 @@ bool EndsWithAny(const std::string& value,
|
|||||||
|
|
||||||
bool FindAnyPartial(const std::string& value,
|
bool FindAnyPartial(const std::string& value,
|
||||||
const std::vector<std::string>& values) {
|
const std::vector<std::string>& values) {
|
||||||
return std::any_of(
|
return std::any_of(std::begin(values), std::end(values),
|
||||||
std::begin(values), std::end(values),
|
[&value](const std::string& v) {
|
||||||
[&value](const std::string& v) { return value.find(v) != std::string::npos; });
|
return value.find(v) != std::string::npos;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GetBaseName(const std::string& path) {
|
std::string GetBaseName(const std::string& path) {
|
||||||
|
@ -45,28 +45,32 @@ lsPosition GetPositionForOffset(const std::string& content, int offset) {
|
|||||||
int MyersDiff(const char* a, int la, const char* b, int lb, int threshold) {
|
int MyersDiff(const char* a, int la, const char* b, int lb, int threshold) {
|
||||||
assert(threshold <= kMaxDiff);
|
assert(threshold <= kMaxDiff);
|
||||||
static int v_static[kMaxDiff + 2];
|
static int v_static[kMaxDiff + 2];
|
||||||
const char *ea = a + la, *eb = b + lb;
|
const char *ea = a + la, *eb = b + lb;
|
||||||
// Strip prefix
|
// Strip prefix
|
||||||
for (; a < ea && b < eb && *a == *b; a++, b++) {}
|
for (; a < ea && b < eb && *a == *b; a++, b++) {
|
||||||
// Strip suffix
|
}
|
||||||
for (; a < ea && b < eb && ea[-1] == eb[-1]; ea--, eb--) {}
|
// Strip suffix
|
||||||
la = int(ea - a);
|
for (; a < ea && b < eb && ea[-1] == eb[-1]; ea--, eb--) {
|
||||||
lb = int(eb - b);
|
}
|
||||||
|
la = int(ea - a);
|
||||||
|
lb = int(eb - b);
|
||||||
|
|
||||||
int* v = v_static + lb;
|
int* v = v_static + lb;
|
||||||
v[1] = 0;
|
v[1] = 0;
|
||||||
for (int di = 0; di <= threshold; di++) {
|
for (int di = 0; di <= threshold; di++) {
|
||||||
int low = -di + 2 * std::max(0, di - lb), high = di - 2 * std::max(0, di - la);
|
int low = -di + 2 * std::max(0, di - lb),
|
||||||
for (int i = low; i <= high; i += 2) {
|
high = di - 2 * std::max(0, di - la);
|
||||||
int x = i == -di || (i != di && v[i-1] < v[i+1]) ? v[i+1] : v[i-1] + 1,
|
for (int i = low; i <= high; i += 2) {
|
||||||
|
int x = i == -di || (i != di && v[i - 1] < v[i + 1]) ? v[i + 1]
|
||||||
|
: v[i - 1] + 1,
|
||||||
y = x - i;
|
y = x - i;
|
||||||
while (x < la && y < lb && a[x] == b[y])
|
while (x < la && y < lb && a[x] == b[y])
|
||||||
x++, y++;
|
x++, y++;
|
||||||
v[i] = x;
|
v[i] = x;
|
||||||
if (x == la && y == lb)
|
if (x == la && y == lb)
|
||||||
return di;
|
return di;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return threshold + 1;
|
return threshold + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,8 +160,10 @@ optional<int> FindMatchingLine(const std::vector<std::string>& index_lines,
|
|||||||
|
|
||||||
// Find the nearest two confident lines above and below.
|
// Find the nearest two confident lines above and below.
|
||||||
int up = line, down = line;
|
int up = line, down = line;
|
||||||
while (--up >= 0 && index_to_buffer[up] < 0) {}
|
while (--up >= 0 && index_to_buffer[up] < 0) {
|
||||||
while (++down < int(index_to_buffer.size()) && index_to_buffer[down] < 0) {}
|
}
|
||||||
|
while (++down < int(index_to_buffer.size()) && index_to_buffer[down] < 0) {
|
||||||
|
}
|
||||||
up = up < 0 ? 0 : index_to_buffer[up];
|
up = up < 0 ? 0 : index_to_buffer[up];
|
||||||
down = down >= int(index_to_buffer.size()) ? int(buffer_lines.size()) - 1
|
down = down >= int(index_to_buffer.size()) ? int(buffer_lines.size()) - 1
|
||||||
: index_to_buffer[down];
|
: index_to_buffer[down];
|
||||||
@ -231,7 +237,8 @@ void WorkingFile::ComputeLineMapping() {
|
|||||||
std::vector<uint64_t> buffer_hashes(buffer_lines.size());
|
std::vector<uint64_t> buffer_hashes(buffer_lines.size());
|
||||||
index_to_buffer.resize(index_lines.size());
|
index_to_buffer.resize(index_lines.size());
|
||||||
buffer_to_index.resize(buffer_lines.size());
|
buffer_to_index.resize(buffer_lines.size());
|
||||||
hash_to_unique.reserve(std::max(index_to_buffer.size(), buffer_to_index.size()));
|
hash_to_unique.reserve(
|
||||||
|
std::max(index_to_buffer.size(), buffer_to_index.size()));
|
||||||
|
|
||||||
// For index line i, set index_to_buffer[i] to -1 if line i is duplicated.
|
// For index line i, set index_to_buffer[i] to -1 if line i is duplicated.
|
||||||
int i = 0;
|
int i = 0;
|
||||||
@ -268,8 +275,8 @@ void WorkingFile::ComputeLineMapping() {
|
|||||||
buffer_hashes[i++] = h;
|
buffer_hashes[i++] = h;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If index line i is the identical to buffer line j, and they are both unique,
|
// If index line i is the identical to buffer line j, and they are both
|
||||||
// align them by pointing from_index[i] to j.
|
// unique, align them by pointing from_index[i] to j.
|
||||||
i = 0;
|
i = 0;
|
||||||
for (auto h : index_hashes) {
|
for (auto h : index_hashes) {
|
||||||
if (index_to_buffer[i] >= 0) {
|
if (index_to_buffer[i] >= 0) {
|
||||||
@ -290,7 +297,7 @@ void WorkingFile::ComputeLineMapping() {
|
|||||||
index_hashes[i + 1] == buffer_hashes[j + 1])
|
index_hashes[i + 1] == buffer_hashes[j + 1])
|
||||||
index_to_buffer[i + 1] = j + 1;
|
index_to_buffer[i + 1] = j + 1;
|
||||||
}
|
}
|
||||||
for (i = (int)index_hashes.size(); --i > 0; ) {
|
for (i = (int)index_hashes.size(); --i > 0;) {
|
||||||
int j = index_to_buffer[i];
|
int j = index_to_buffer[i];
|
||||||
if (0 < j && index_hashes[i - 1] == buffer_hashes[j - 1])
|
if (0 < j && index_hashes[i - 1] == buffer_hashes[j - 1])
|
||||||
index_to_buffer[i - 1] = j - 1;
|
index_to_buffer[i - 1] = j - 1;
|
||||||
@ -303,7 +310,9 @@ void WorkingFile::ComputeLineMapping() {
|
|||||||
buffer_to_index[index_to_buffer[i]] = i;
|
buffer_to_index[index_to_buffer[i]] = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
optional<int> WorkingFile::GetBufferPosFromIndexPos(int line, int* column, bool is_end) {
|
optional<int> WorkingFile::GetBufferPosFromIndexPos(int line,
|
||||||
|
int* column,
|
||||||
|
bool is_end) {
|
||||||
// The implementation is simple but works pretty well for most cases. We
|
// The implementation is simple but works pretty well for most cases. We
|
||||||
// lookup the line contents in the indexed file contents, and try to find the
|
// lookup the line contents in the indexed file contents, and try to find the
|
||||||
// most similar line in the current buffer file.
|
// most similar line in the current buffer file.
|
||||||
@ -330,7 +339,9 @@ optional<int> WorkingFile::GetBufferPosFromIndexPos(int line, int* column, bool
|
|||||||
buffer_lines, is_end);
|
buffer_lines, is_end);
|
||||||
}
|
}
|
||||||
|
|
||||||
optional<int> WorkingFile::GetIndexPosFromBufferPos(int line, int* column, bool is_end) {
|
optional<int> WorkingFile::GetIndexPosFromBufferPos(int line,
|
||||||
|
int* column,
|
||||||
|
bool is_end) {
|
||||||
// See GetBufferLineFromIndexLine for additional comments.
|
// See GetBufferLineFromIndexLine for additional comments.
|
||||||
if (line < 0 || line >= (int)buffer_lines.size())
|
if (line < 0 || line >= (int)buffer_lines.size())
|
||||||
return nullopt;
|
return nullopt;
|
||||||
@ -494,7 +505,8 @@ void WorkingFiles::OnChange(const lsTextDocumentDidChangeParams& change) {
|
|||||||
GetOffsetForPosition(diff.range->start, file->buffer_content);
|
GetOffsetForPosition(diff.range->start, file->buffer_content);
|
||||||
// Ignore TextDocumentContentChangeEvent.rangeLength which causes trouble
|
// Ignore TextDocumentContentChangeEvent.rangeLength which causes trouble
|
||||||
// when UTF-16 surrogate pairs are used.
|
// when UTF-16 surrogate pairs are used.
|
||||||
int end_offset = GetOffsetForPosition(diff.range->end, file->buffer_content);
|
int end_offset =
|
||||||
|
GetOffsetForPosition(diff.range->end, file->buffer_content);
|
||||||
file->buffer_content.replace(file->buffer_content.begin() + start_offset,
|
file->buffer_content.replace(file->buffer_content.begin() + start_offset,
|
||||||
file->buffer_content.begin() + end_offset,
|
file->buffer_content.begin() + end_offset,
|
||||||
diff.text);
|
diff.text);
|
||||||
|
@ -87,7 +87,6 @@ struct WorkingFiles {
|
|||||||
std::vector<File> files;
|
std::vector<File> files;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// :: IMPORTANT :: All methods in this class are guarded by a single lock.
|
// :: IMPORTANT :: All methods in this class are guarded by a single lock.
|
||||||
//
|
//
|
||||||
|
Loading…
Reference in New Issue
Block a user