diff --git a/src/clang_tu.cc b/src/clang_tu.cc index 46015bdf..e53d1ea4 100644 --- a/src/clang_tu.cc +++ b/src/clang_tu.cc @@ -28,47 +28,57 @@ std::string PathFromFileEntry(const FileEntry &file) { return ret; } +static Position Decomposed2LineAndCol(const SourceManager &SM, + std::pair I) { + int l = (int)SM.getLineNumber(I.first, I.second) - 1, + c = (int)SM.getColumnNumber(I.first, I.second) - 1; + return {(int16_t)std::min(l, INT16_MAX), + (int16_t)std::min(c, INT16_MAX)}; +} + Range FromCharSourceRange(const SourceManager &SM, const LangOptions &LangOpts, CharSourceRange R, llvm::sys::fs::UniqueID *UniqueID) { SourceLocation BLoc = R.getBegin(), ELoc = R.getEnd(); - std::pair BInfo = SM.getDecomposedLoc(BLoc); - std::pair EInfo = SM.getDecomposedLoc(ELoc); + std::pair BInfo = SM.getDecomposedLoc(BLoc), + EInfo = SM.getDecomposedLoc(ELoc); if (R.isTokenRange()) EInfo.second += Lexer::MeasureTokenLength(ELoc, SM, LangOpts); - unsigned l0 = SM.getLineNumber(BInfo.first, BInfo.second) - 1, - c0 = SM.getColumnNumber(BInfo.first, BInfo.second) - 1, - l1 = SM.getLineNumber(EInfo.first, EInfo.second) - 1, - c1 = SM.getColumnNumber(EInfo.first, EInfo.second) - 1; - if (l0 > INT16_MAX) - l0 = 0; - if (c0 > INT16_MAX) - c0 = 0; - if (l1 > INT16_MAX) - l1 = 0; - if (c1 > INT16_MAX) - c1 = 0; if (UniqueID) { if (const FileEntry *F = SM.getFileEntryForID(BInfo.first)) *UniqueID = F->getUniqueID(); else *UniqueID = llvm::sys::fs::UniqueID(0, 0); } - return {{int16_t(l0), int16_t(c0)}, {int16_t(l1), int16_t(c1)}}; + return {Decomposed2LineAndCol(SM, BInfo), Decomposed2LineAndCol(SM, EInfo)}; } -Range FromCharRange(const SourceManager &SM, const LangOptions &LangOpts, +Range FromCharRange(const SourceManager &SM, const LangOptions &Lang, SourceRange R, llvm::sys::fs::UniqueID *UniqueID) { - return FromCharSourceRange(SM, LangOpts, CharSourceRange::getCharRange(R), + return FromCharSourceRange(SM, Lang, CharSourceRange::getCharRange(R), UniqueID); } -Range FromTokenRange(const SourceManager &SM, const LangOptions &LangOpts, +Range FromTokenRange(const SourceManager &SM, const LangOptions &Lang, SourceRange R, llvm::sys::fs::UniqueID *UniqueID) { - return FromCharSourceRange(SM, LangOpts, CharSourceRange::getTokenRange(R), + return FromCharSourceRange(SM, Lang, CharSourceRange::getTokenRange(R), UniqueID); } +Range FromTokenRangeDefaulted(const SourceManager &SM, const LangOptions &Lang, + SourceRange R, const FileEntry *FE, Range range) { + auto I = SM.getDecomposedLoc(SM.getExpansionLoc(R.getBegin())); + if (SM.getFileEntryForID(I.first) == FE) + range.start = Decomposed2LineAndCol(SM, I); + SourceLocation L = SM.getExpansionLoc(R.getEnd()); + I = SM.getDecomposedLoc(L); + if (SM.getFileEntryForID(I.first) == FE) { + I.second += Lexer::MeasureTokenLength(L, SM, Lang); + range.end = Decomposed2LineAndCol(SM, I); + } + return range; +} + std::unique_ptr BuildCompilerInvocation(std::vector args, IntrusiveRefCntPtr VFS) { diff --git a/src/clang_tu.hh b/src/clang_tu.hh index 5db41d17..3b405a09 100644 --- a/src/clang_tu.hh +++ b/src/clang_tu.hh @@ -32,6 +32,11 @@ Range FromTokenRange(const clang::SourceManager &SM, const clang::LangOptions &LangOpts, clang::SourceRange R, llvm::sys::fs::UniqueID *UniqueID = nullptr); +Range FromTokenRangeDefaulted(const clang::SourceManager &SM, + const clang::LangOptions &Lang, + clang::SourceRange R, const clang::FileEntry *FE, + Range range); + std::unique_ptr BuildCompilerInvocation(std::vector args, llvm::IntrusiveRefCntPtr VFS); diff --git a/src/indexer.cc b/src/indexer.cc index 30f14eaf..e2c5321f 100644 --- a/src/indexer.cc +++ b/src/indexer.cc @@ -770,20 +770,19 @@ public: Usr usr = GetUsr(D, &info); auto do_def_decl = [&](auto *entity) { + Use use{{loc, role}, lid}; if (is_def) { SourceRange R = OrigD->getSourceRange(); - entity->def.spell = { - Use{{loc, role}, lid}, - R.getBegin().isFileID() ? FromTokenRange(SM, Lang, R) : loc}; + entity->def.spell = {use, + FromTokenRangeDefaulted(SM, Lang, R, FE, loc)}; entity->def.parent_kind = lsSymbolKind::File; GetSymbolKind(cast(SemDC), entity->def.parent_kind); } else if (is_decl) { - DeclRef &dr = entity->declarations.emplace_back(); - static_cast(dr) = {{loc, role}, lid}; SourceRange R = OrigD->getSourceRange(); - dr.extent = R.getBegin().isFileID() ? FromTokenRange(SM, Lang, R) : loc; + entity->declarations.push_back( + {use, FromTokenRangeDefaulted(SM, Lang, R, FE, loc)}); } else { - entity->uses.push_back({{loc, role}, lid}); + entity->uses.push_back(use); return; } if (entity->def.comments[0] == '\0' && g_config->index.comments) diff --git a/src/messages/ccls_navigate.cc b/src/messages/ccls_navigate.cc index e2528be8..af3f4238 100644 --- a/src/messages/ccls_navigate.cc +++ b/src/messages/ccls_navigate.cc @@ -21,6 +21,18 @@ MAKE_REFLECT_STRUCT(In_CclsNavigate::Params, textDocument, position, direction); MAKE_REFLECT_STRUCT(In_CclsNavigate, id, params); REGISTER_IN_MESSAGE(In_CclsNavigate); +Maybe FindParent(QueryFile *file, Position pos) { + Maybe parent; + for (auto [sym, refcnt] : file->symbol2refcnt) + if (refcnt > 0 && sym.extent.Valid() && sym.extent.start <= pos && + pos < sym.extent.end && + (!parent || (parent->start == sym.extent.start + ? parent->end < sym.extent.end + : parent->start < sym.extent.start))) + parent = sym.extent; + return parent; +} + struct Handler_CclsNavigate : BaseMessageHandler { MethodType GetMethodType() const override { return kMethodType; } void Run(In_CclsNavigate *request) override { @@ -42,11 +54,7 @@ struct Handler_CclsNavigate : BaseMessageHandler { Maybe res; switch (params.direction[0]) { case 'D': { - Maybe parent; - for (auto [sym, refcnt] : file->symbol2refcnt) - if (refcnt > 0 && sym.extent.Valid() && sym.extent.start <= pos && - pos < sym.extent.end && (!parent || parent->start < sym.extent.start)) - parent = sym.extent; + Maybe parent = FindParent(file, pos); for (auto [sym, refcnt] : file->symbol2refcnt) if (refcnt > 0 && pos < sym.extent.start && (!parent || sym.extent.end <= parent->end) && @@ -62,11 +70,7 @@ struct Handler_CclsNavigate : BaseMessageHandler { res = sym.extent; break; case 'R': { - Maybe parent; - for (auto [sym, refcnt] : file->symbol2refcnt) - if (refcnt > 0 && sym.extent.Valid() && sym.extent.start <= pos && - pos < sym.extent.end && (!parent || parent->start < sym.extent.start)) - parent = sym.extent; + Maybe parent = FindParent(file, pos); if (parent && parent->start.line == pos.line && pos < parent->end) { pos = parent->end; if (pos.column) diff --git a/src/messages/textDocument_typeDefinition.cc b/src/messages/textDocument_typeDefinition.cc index 209e3802..74cd6995 100644 --- a/src/messages/textDocument_typeDefinition.cc +++ b/src/messages/textDocument_typeDefinition.cc @@ -62,6 +62,8 @@ struct Handler_TextDocumentTypeDefinition } } + std::sort(result.begin(), result.end()); + result.erase(std::unique(result.begin(), result.end()), result.end()); pipeline::Reply(request->id, result); } };