@@ -1688,6 +1688,7 @@ declToHierarchyItem(const NamedDecl &ND, llvm::StringRef TUPath) {
16881688
16891689 HierarchyItem HI;
16901690 HI.name = printName (Ctx, ND);
1691+ // FIXME: Populate HI.detail the way we do in symbolToHierarchyItem?
16911692 HI.kind = SK;
16921693 HI.range = Range{sourceLocToPosition (SM, DeclRange->getBegin ()),
16931694 sourceLocToPosition (SM, DeclRange->getEnd ())};
@@ -1739,6 +1740,7 @@ static std::optional<HierarchyItem> symbolToHierarchyItem(const Symbol &S,
17391740 }
17401741 HierarchyItem HI;
17411742 HI.name = std::string (S.Name );
1743+ HI.detail = (S.Scope + S.Name ).str ();
17421744 HI.kind = indexSymbolKindToSymbolKind (S.SymInfo .Kind );
17431745 HI.selectionRange = Loc->range ;
17441746 // FIXME: Populate 'range' correctly
@@ -2305,6 +2307,65 @@ incomingCalls(const CallHierarchyItem &Item, const SymbolIndex *Index) {
23052307 return Results;
23062308}
23072309
2310+ std::vector<CallHierarchyOutgoingCall>
2311+ outgoingCalls (const CallHierarchyItem &Item, const SymbolIndex *Index) {
2312+ std::vector<CallHierarchyOutgoingCall> Results;
2313+ if (!Index || Item.data .empty ())
2314+ return Results;
2315+ auto ID = SymbolID::fromStr (Item.data );
2316+ if (!ID) {
2317+ elog (" outgoingCalls failed to find symbol: {0}" , ID.takeError ());
2318+ return Results;
2319+ }
2320+ // In this function, we find outgoing calls based on the index only.
2321+ ContainedRefsRequest Request;
2322+ Request.ID = *ID;
2323+ // Initially store the ranges in a map keyed by SymbolID of the callee.
2324+ // This allows us to group different calls to the same function
2325+ // into the same CallHierarchyOutgoingCall.
2326+ llvm::DenseMap<SymbolID, std::vector<Range>> CallsOut;
2327+ // We can populate the ranges based on a refs request only. As we do so, we
2328+ // also accumulate the callee IDs into a lookup request.
2329+ LookupRequest CallsOutLookup;
2330+ Index->containedRefs (Request, [&](const auto &R) {
2331+ auto Loc = indexToLSPLocation (R.Location , Item.uri .file ());
2332+ if (!Loc) {
2333+ elog (" outgoingCalls failed to convert location: {0}" , Loc.takeError ());
2334+ return ;
2335+ }
2336+ auto It = CallsOut.try_emplace (R.Symbol , std::vector<Range>{}).first ;
2337+ It->second .push_back (Loc->range );
2338+
2339+ CallsOutLookup.IDs .insert (R.Symbol );
2340+ });
2341+ // Perform the lookup request and combine its results with CallsOut to
2342+ // get complete CallHierarchyOutgoingCall objects.
2343+ Index->lookup (CallsOutLookup, [&](const Symbol &Callee) {
2344+ // The containedRefs request should only return symbols which are
2345+ // function-like, i.e. symbols for which references to them can be "calls".
2346+ using SK = index::SymbolKind;
2347+ auto Kind = Callee.SymInfo .Kind ;
2348+ assert (Kind == SK::Function || Kind == SK::InstanceMethod ||
2349+ Kind == SK::ClassMethod || Kind == SK::StaticMethod ||
2350+ Kind == SK::Constructor || Kind == SK::Destructor ||
2351+ Kind == SK::ConversionFunction);
2352+ (void )Kind;
2353+ (void )SK::Function;
2354+
2355+ auto It = CallsOut.find (Callee.ID );
2356+ assert (It != CallsOut.end ());
2357+ if (auto CHI = symbolToCallHierarchyItem (Callee, Item.uri .file ()))
2358+ Results.push_back (
2359+ CallHierarchyOutgoingCall{std::move (*CHI), std::move (It->second )});
2360+ });
2361+ // Sort results by name of the callee.
2362+ llvm::sort (Results, [](const CallHierarchyOutgoingCall &A,
2363+ const CallHierarchyOutgoingCall &B) {
2364+ return A.to .name < B.to .name ;
2365+ });
2366+ return Results;
2367+ }
2368+
23082369llvm::DenseSet<const Decl *> getNonLocalDeclRefs (ParsedAST &AST,
23092370 const FunctionDecl *FD) {
23102371 if (!FD->hasBody ())
0 commit comments