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