@@ -1702,6 +1702,7 @@ declToHierarchyItem(const NamedDecl &ND, llvm::StringRef TUPath) {
17021702
17031703 HierarchyItem HI;
17041704 HI.name = printName (Ctx, ND);
1705+ // FIXME: Populate HI.detail the way we do in symbolToHierarchyItem?
17051706 HI.kind = SK;
17061707 HI.range = Range{sourceLocToPosition (SM, DeclRange->getBegin ()),
17071708 sourceLocToPosition (SM, DeclRange->getEnd ())};
@@ -1753,6 +1754,7 @@ static std::optional<HierarchyItem> symbolToHierarchyItem(const Symbol &S,
17531754 }
17541755 HierarchyItem HI;
17551756 HI.name = std::string (S.Name );
1757+ HI.detail = (S.Scope + S.Name ).str ();
17561758 HI.kind = indexSymbolKindToSymbolKind (S.SymInfo .Kind );
17571759 HI.selectionRange = Loc->range ;
17581760 // FIXME: Populate 'range' correctly
@@ -2319,6 +2321,65 @@ incomingCalls(const CallHierarchyItem &Item, const SymbolIndex *Index) {
23192321 return Results;
23202322}
23212323
2324+ std::vector<CallHierarchyOutgoingCall>
2325+ outgoingCalls (const CallHierarchyItem &Item, const SymbolIndex *Index) {
2326+ std::vector<CallHierarchyOutgoingCall> Results;
2327+ if (!Index || Item.data .empty ())
2328+ return Results;
2329+ auto ID = SymbolID::fromStr (Item.data );
2330+ if (!ID) {
2331+ elog (" outgoingCalls failed to find symbol: {0}" , ID.takeError ());
2332+ return Results;
2333+ }
2334+ // In this function, we find outgoing calls based on the index only.
2335+ ContainedRefsRequest Request;
2336+ Request.ID = *ID;
2337+ // Initially store the ranges in a map keyed by SymbolID of the callee.
2338+ // This allows us to group different calls to the same function
2339+ // into the same CallHierarchyOutgoingCall.
2340+ llvm::DenseMap<SymbolID, std::vector<Range>> CallsOut;
2341+ // We can populate the ranges based on a refs request only. As we do so, we
2342+ // also accumulate the callee IDs into a lookup request.
2343+ LookupRequest CallsOutLookup;
2344+ Index->containedRefs (Request, [&](const auto &R) {
2345+ auto Loc = indexToLSPLocation (R.Location , Item.uri .file ());
2346+ if (!Loc) {
2347+ elog (" outgoingCalls failed to convert location: {0}" , Loc.takeError ());
2348+ return ;
2349+ }
2350+ auto It = CallsOut.try_emplace (R.Symbol , std::vector<Range>{}).first ;
2351+ It->second .push_back (Loc->range );
2352+
2353+ CallsOutLookup.IDs .insert (R.Symbol );
2354+ });
2355+ // Perform the lookup request and combine its results with CallsOut to
2356+ // get complete CallHierarchyOutgoingCall objects.
2357+ Index->lookup (CallsOutLookup, [&](const Symbol &Callee) {
2358+ // The containedRefs request should only return symbols which are
2359+ // function-like, i.e. symbols for which references to them can be "calls".
2360+ using SK = index::SymbolKind;
2361+ auto Kind = Callee.SymInfo .Kind ;
2362+ assert (Kind == SK::Function || Kind == SK::InstanceMethod ||
2363+ Kind == SK::ClassMethod || Kind == SK::StaticMethod ||
2364+ Kind == SK::Constructor || Kind == SK::Destructor ||
2365+ Kind == SK::ConversionFunction);
2366+ (void )Kind;
2367+ (void )SK::Function;
2368+
2369+ auto It = CallsOut.find (Callee.ID );
2370+ assert (It != CallsOut.end ());
2371+ if (auto CHI = symbolToCallHierarchyItem (Callee, Item.uri .file ()))
2372+ Results.push_back (
2373+ CallHierarchyOutgoingCall{std::move (*CHI), std::move (It->second )});
2374+ });
2375+ // Sort results by name of the callee.
2376+ llvm::sort (Results, [](const CallHierarchyOutgoingCall &A,
2377+ const CallHierarchyOutgoingCall &B) {
2378+ return A.to .name < B.to .name ;
2379+ });
2380+ return Results;
2381+ }
2382+
23222383llvm::DenseSet<const Decl *> getNonLocalDeclRefs (ParsedAST &AST,
23232384 const FunctionDecl *FD) {
23242385 if (!FD->hasBody ())
0 commit comments