[refactor] Add the AST source selection component

Authored by arphaman on Jul 5 2017, 6:56 AM.



This patch adds the base AST source selection component to the refactoring library. AST selection is represented using a tree of SelectedASTNode values. Each selected node gets its own selection kind, which can actually be None even in the middle of tree (e.g. statement in a macro whose child is in a macro argument). The initial version constructs a "raw" selection tree, without applying filters and canonicalisation operations to the nodes.

Diff Detail

arphaman created this revision.Jul 5 2017, 6:56 AM
arphaman updated this revision to Diff 105269.EditedJul 5 2017, 7:25 AM

Add a test-case for implicit declarations.

klimek added inline comments.Jul 17 2017, 4:44 AM
30 ↗(On Diff #105269)

It's unclear what a selection point is. I'd have expected this to mean "overlaps" when first reading it.

68–74 ↗(On Diff #105269)

Any reason not to do multiple ranges?

Also, it's not clear from reading the description here why we need the Location.

100 ↗(On Diff #105269)

Why do we always stop traversal?

103 ↗(On Diff #105269)

A short comment explaining when this happens would help understand this.

164 ↗(On Diff #105269)

Why don't we do this as part of TraverseDecl() in the visitor?

1 ↗(On Diff #105269)

I'm somewhat opposed to files having "utils" in the name, as they tend to accumulate too much stuff.
Can we implement those in SourceLocation and SourceManager respectively?

Some nits.

23 ↗(On Diff #105269)

In LLVM, we use the following class layout:

class X {
  void f();

  void g();

  int member;
76 ↗(On Diff #105269)

I think getSelectedASTNode would be clearer.

90 ↗(On Diff #105269)

Use FIXME(<user-id>) instead of TODO in LLVM. Here and elsewhere.

126–129 ↗(On Diff #105269)

This seems to be a recurring pattern. Maybe pull into a function?

arphaman added inline comments.Jul 17 2017, 9:19 AM
68–74 ↗(On Diff #105269)

I guess multiple ranges can be supported in follow-up patches to keep this one simpler.

I'll add it to the comment, but the idea is that the location corresponds to the cursor/right click position in the editor. That means that location doesn't have to be identical to the selection, since you can select something and then right click anywhere in the editor.

100 ↗(On Diff #105269)

False stops traversal, true is the default return value.

klimek added inline comments.Jul 18 2017, 1:39 AM
100 ↗(On Diff #105269)

Ah, right. Generally, I'd have expected us to stop traversal once we're past the range?

arphaman updated this revision to Diff 107067.Jul 18 2017, 5:44 AM
arphaman marked 7 inline comments as done.
  • Address review comments.
  • Remove the Location parameter and ContainsSelectionPoint enum value.
  • Stop traversing early when a declaration that ends after the selection range was reached.
68–74 ↗(On Diff #105269)

I've decided to get rid of Location and ContainsSelectionPoint at this level. I will instead handle this editor specific thing at a higher-level and make selection search range only to simplify things at this level.

100 ↗(On Diff #105269)

We already do stop traversal early in findSelectedASTNodes once we match everything that's possible (although if the selection doesn't overlap with anything we will traverse all top level nodes). I see the point though, we might as stop after the range as well. I added the check to do that in the updated patch.

164 ↗(On Diff #105269)

I think it's easier to handle the Objective-C @implementation logic here, unless there's some better way that I can't see ATM.

klimek added inline comments.Jul 18 2017, 6:35 AM
164 ↗(On Diff #105269)

Ok, in that case, can you write a comment at the start of the loop explaining that we basically only do that for the Objective-C @implementation? (I'd also like to understand that better in general, as I have no clue about Obj-C :)

arphaman added inline comments.Jul 18 2017, 7:03 AM
164 ↗(On Diff #105269)

Hmm, maybe it would be better to move this logic to another layer. Like a wrapper around RecursiveASTVisitor that ensures that iteration occurs in a lexical order. It can then be used by other things that might need this, this code will get simpler and I will be able to test it better.

klimek added inline comments.Jul 18 2017, 7:08 AM
164 ↗(On Diff #105269)

Great idea! That would be useful in a bunch of use cases.

arphaman updated this revision to Diff 107121.Jul 18 2017, 9:46 AM

Factor out the lexical ordering code into a new visitor and simplify the implementation of the ast selection visitor

Oops, I just realised that now there's a small bug with early exits. Since we don't actually have true lexical order for declarations in the @implementation we might exit early after visiting a method in the @implementation before a function that's actually written before that method. I will probably constraint early exits to avoid this case.

arphaman updated this revision to Diff 107138.Jul 18 2017, 10:44 AM

rm early exit bug

arphaman updated this revision to Diff 108078.Jul 25 2017, 7:32 AM

Simplified the implementation of LexicallyOrderedRecursiveASTVisitor and removed redundant DenseMap checks.

klimek added a comment.Aug 1 2017, 3:15 AM

Apart from nits, looks OK to me - Eric, are all your concerns addressed?

51–53 ↗(On Diff #108078)

As this is a public interface, perhaps we should make them const?

ioeric accepted this revision.Aug 1 2017, 3:20 AM

Yep. Lgtm!

This revision is now accepted and ready to land.Aug 1 2017, 3:20 AM
This revision was automatically updated to reflect the committed changes.

The test CursorAtStartOfFunction is segfaulting.