This is an archive of the discontinued LLVM Phabricator instance.

[clangd] Include macro expansions in documentSymbol hierarchy
ClosedPublic

Authored by sammccall on Feb 27 2021, 5:16 AM.

Details

Summary

Browsing macro-generated symbols is confusing.
On the one hand, it seems very *useful* to be able to see the summary of
symbols that were generated.
On the other hand, some macros spew a lot of confusing symbols into the
namespace and when used repeatedly (ABSL_FLAG) can create a lot of spam
that's hard to navigate.

Design constraints:

  • the macro expansion tree need not align with the AST, though it often does in practice. We address this by defining the nesting based on the *primary* location of decls, rather than their ranges.
  • DocumentSymbol.children[*].range should nest within DocumentSymbol.range (This constraint is not in LSP "breadcrumbs" breaks without it) We adjust macro ranges so they cover their "children", rather than just the macro expansion
  • LSP does not have a "macro expansion" symbolkind, nor does it allow a symbol to have no kind. I've arbitrarily picked "null" as this is unlikely to conflict with anything useful.

This patch makes all macros and children visible for simplicity+consistency,
though in some cases it may be better to elide the macro node.
We may consider adding heuristics for this in future (e.g. when it expands
to one decl only?) but it doesn't seem clear-cut to me.

Diff Detail

Event Timeline

sammccall created this revision.Feb 27 2021, 5:16 AM
sammccall requested review of this revision.Feb 27 2021, 5:16 AM

Before:


After:

thanks, LGTM. with a couple nits and asking for some extra clarifications :)

clang-tools-extra/clangd/FindSymbols.cpp
303

nit: drop this one?

310

this comment feels a little out-of-place, maybe move it next to possibleMacroContainer call?

347

nit:

Sym.range = Sym.selectionRange = halfOpenToRange(SM, Tok.range(SM).toCharRange(SM));
if (Exp) {
  Sym.range = .... // cover Exp;
  // Populate Sym.detail.
}
420

also mention that there's at most one node for each macro invocation in the document symbol hierarchy, even if it yields multiple decls

442

nit:

SourceLocation ExpansionLoc = Loc;
// If ExpansionLoc is inside a macro argument, use the outer macro invocation instead. e.g:
//    #define ID(X) X
//    ID(int y); // chose location of ID, not X
if(SM.isMacroArgExpansion(ExpansionLoc))
  ExpansionLoc = SM.getImmediateExpansionRange(Loc).getBegin();
FileID MacroBody = SM.getFileID(ExpansionLoc);
This revision was not accepted when it landed; it landed in state Needs Review.Mar 2 2021, 8:52 AM
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
sammccall marked 3 inline comments as done.