This is an archive of the discontinued LLVM Phabricator instance.

[clangd] Rename constructors and destructors in cross-file case
ClosedPublic

Authored by kbobyrev on Dec 10 2019, 3:13 AM.

Details

Summary
  • Use ad-hoc Decl canonicalization from Clang-Rename to allow renaming constructors and destructors while using cross-file rename.
  • Manually handle the destructor selection
  • Add unit tests to prevent regressions and ensure the correct behaviour

Diff Detail

Event Timeline

kbobyrev created this revision.Dec 10 2019, 3:13 AM
kbobyrev updated this revision to Diff 233037.Dec 10 2019, 3:21 AM

Improve wording in the comment I moved.

kadircet added inline comments.Dec 10 2019, 3:26 AM
clang-tools-extra/clangd/unittests/RenameTests.cpp
754

could you also add a case with ~^Foo()

kbobyrev updated this revision to Diff 233048.Dec 10 2019, 4:19 AM
kbobyrev marked an inline comment as done.

Add another test for ~^Foo and rebase on top of master.

sammccall added inline comments.Dec 10 2019, 9:18 AM
clang-tools-extra/clangd/refactor/Rename.cpp
86–87

Braindump from an offline conversation...
This seems like an unfortunate place to put a complicated special case and it doesn't generalize well.

The TokenStartLoc check is a bit unfortunate to begin with - it's subject to all the heuristic-token-rewinding problems we've encountered in the past. Its one advantage over plain selectiontree is that it works at the end of the identifier.

Better approach seems to be:

  • we only allow rename targeted at an identifier token
  • there can be at most one identifier touching the location (if there's one before and after, they'd be a single identifier)
  • so find that identifier spelled token using TokenBuffer
  • then look it up as a macro (we get its start location for free)
  • if that fails, create a selectiontree for the token's range and rename what we find

I don't think there's a better TokenBuffer API than calling spelledTokens() and binary-searching, at the moment.

This touches more code, but is less special-case-y overall. I'd consider putting the getIdentifierTouching(SourceLocation, TokenBuffer, SourceManager) in SourceCode.h

kbobyrev planned changes to this revision.Dec 11 2019, 3:15 AM

Need to address the comments.

kbobyrev updated this revision to Diff 233381.Dec 11 2019, 8:49 AM
kbobyrev marked an inline comment as done.

Address the comments and simplify the code.

sammccall added inline comments.Dec 11 2019, 10:11 AM
clang-tools-extra/clangd/refactor/Rename.cpp
91

why is this code being moved?

453

so getting an invalid location from the editor isn't the same thing as the symbol being used outside the file! Here we already have an Error to return.

if (!Offset)
  return Offset.takeError();

but really there's a helper to do this:

SourceLocation Loc = sourceLocationInMainFile(SM, RInputs.Pos);
if (!Loc)
  return Loc.takeError();
const syntax::Token *IdentifierToken = spelledIdentifierTouching(Loc, AST.getTokens());
456

nit: auto* for pointers, but spelling out the type here would be clearer I think

458

this is an invariant of the function we're calling, not this one - no need to document it (next line is good though)

462

This unwrapping doesn't seem necessary, - it doesn't make a difference for macros (which we don't support anyway), nor for selectiontree. Just inline usages of IdentifierToken->location() below?

kbobyrev updated this revision to Diff 233533.Dec 12 2019, 1:28 AM
kbobyrev marked 5 inline comments as done.
kbobyrev added inline comments.
clang-tools-extra/clangd/refactor/Rename.cpp
91

So, this code was previously only in the within-file rename path and hence triggering rename from a constructor/destructor-s was only possible there. Moving the code here improves overall "symbol selection" and fixes it for global renames, too.

sammccall added inline comments.Dec 12 2019, 3:14 AM
clang-tools-extra/clangd/refactor/Rename.cpp
91

Clangd as a whole actually canonicalizes in the other direction (templatedecl -> templated decl).
So I think this change introduces a bug (the references you seek won't be in the index).

Certainly up for discussion which is better (behavior is historical) but that's a larger change.

96

dyn_cast then unconditionally inserting seems dodgy - if it can be null, it must be checked, and if it can't, it should be plain cast

kbobyrev updated this revision to Diff 233563.Dec 12 2019, 3:23 AM
kbobyrev marked 3 inline comments as done.
sammccall added inline comments.Dec 12 2019, 3:48 AM
clang-tools-extra/clangd/refactor/Rename.cpp
91

OK, this can definitely fail though - just select 'friend X' in a class body or so. Need to check for ND and bail out.

223

you removed this comment and the fixme, but it still applies?

clang-tools-extra/clangd/unittests/RenameTests.cpp
732

nit: put these after "class methods" rather than at the top?

750

4 is too many cases for constructor/destructor.

What about 2: Constructor at start, destructor at end?
Renaming in the middle of the token is covered by existing cases.

sammccall accepted this revision.Dec 12 2019, 3:49 AM

LG but the cast needs to be fixed

This revision is now accepted and ready to land.Dec 12 2019, 3:49 AM
kbobyrev updated this revision to Diff 233571.Dec 12 2019, 4:01 AM
kbobyrev marked 4 inline comments as done.
This revision was automatically updated to reflect the committed changes.
Herald added a project: Restricted Project. · View Herald TranscriptDec 12 2019, 4:15 AM