This is an archive of the discontinued LLVM Phabricator instance.

[clangd] Reduce availability of extract function
ClosedPublic

Authored by kadircet on Aug 5 2020, 1:22 PM.

Details

Summary

This patch introduces hoisting detection logic into prepare state with
a partial AST traversal of the enclosing function.

We had some complaints from the users about this code action being almost always
available but failing most of the time. Hopefully this should reduce that noise.

The latency/correctness tradeoff is a bunch of hand-waving, but at least today
we don't have any other actions that are available on selection of statements,
so when we get to do the traversal it is quite likely that all the other checks
will bail out early. But this is still up for discussion, I am happy to abandon
the patch if you believe this is not practical.

Diff Detail

Event Timeline

kadircet created this revision.Aug 5 2020, 1:22 PM
kadircet requested review of this revision.Aug 5 2020, 1:22 PM
sammccall accepted this revision.Aug 21 2020, 1:47 AM
sammccall added inline comments.
clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp
321

Maybe obvious but "if any are, we can't perform extraction, as we don't support hoisting".

331

I think this would be clearer as two for loops:

  • one filling RootStmts. i.e. the old generateRootStmts, though I do like inlining it here as it's initiaziling the ExtractionZone which really is this function's job
  • the other looping over it as part of the big block of analysis that the comment applies to

As far as I can tell, the analysis doesn't have any side-effects, so I'd move it to a separate function (either a free function that you'd call here, or a member so the tweak can if (MaybeExtZone && MaybeExtZone->canApply()) or so. Again this is because mixing initialization and complex validation can make the data flow non-obvious.

Alternatively, maybe we can unify/reuse this logic? Surely it has a lot in common with captureZoneInfo() - is it really cheaper to run?

This revision is now accepted and ready to land.Aug 21 2020, 1:47 AM
kadircet updated this revision to Diff 296110.Oct 5 2020, 1:53 AM
kadircet marked 2 inline comments as done.
  • Address comments
kadircet added inline comments.Oct 7 2020, 2:38 AM
clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp
331

I think this would be clearer as two for loops:

done.

As far as I can tell, the analysis doesn't have any side-effects, so I'd move it to a separate function (either a free function that you'd call here, or a member so the tweak can if (MaybeExtZone && MaybeExtZone->canApply()) or so. Again this is because mixing initialization and complex validation can make the data flow non-obvious.

moved into a member named requiresHoisting.

Alternatively, maybe we can unify/reuse this logic? Surely it has a lot in common with captureZoneInfo() - is it really cheaper to run?

In theory this should be always cheaper than captureZoneInfo as it traverses the whole enclosing function, whereas this one only traverses ast nodes that intersect with selection or come after it.
So if selection is near the beginning of the function body, or the function itself is small, the delta is likely negligible.

sammccall accepted this revision.Oct 7 2020, 9:58 AM
This revision was landed with ongoing or failed builds.Oct 9 2020, 1:16 AM
This revision was automatically updated to reflect the committed changes.