This is an archive of the discontinued LLVM Phabricator instance.

[clangd] Add correctness checks for index-based rename
AbandonedPublic

Authored by kbobyrev on Jan 2 2020, 2:32 AM.

Details

Summary

In some cases the candidate ranges for rename final stage (textual
replacements) are invalid and do not contain references to identifier being
renamed. Examples of such behavior include implicit references that are
currently not filtered out (though in the future they should be dealt with
during the references collection stage).

This patch addresses this issue by explicitly checking whether the text in each
candidate range is equivalent to the renamed identifier's name. It does not make
index-based rename absolutely correct, but it is a cheap way to filter out some
replacements that are clearly incorrect.

Diff Detail

Event Timeline

kbobyrev created this revision.Jan 2 2020, 2:32 AM
Herald added a project: Restricted Project. · View Herald TranscriptJan 2 2020, 2:32 AM

@sammccall Indexed.size() > Lexed.size() is one of the assumptions that I think might not hold in real-world scenarios. I was reading patch heuristics code a lot and trying to understand whether anything breaks when this check is not in place, but I couldn't come up with some cases, so I thought it'd be OK to remove it.

I have written down some thoughts on the topic in the issue I opened on GitHub:

https://github.com/clangd/clangd/issues/238

We have briefly discussed range patching heuristics in D71598, @kadircet has more context if you are interested.

I'd be happy to discuss more details once I'm back, let me know if you have any thoughts/comments on the issue.

kbobyrev updated this revision to Diff 235841.Jan 2 2020, 2:42 AM

Improve wording in the comment

Unit tests: pass. 61168 tests passed, 0 failed and 728 were skipped.

clang-tidy: pass.

clang-format: pass.

Build artifacts: diff.json, clang-tidy.txt, clang-format.patch, CMakeCache.txt, console-log.txt, test-results.xml

Unit tests: pass. 61168 tests passed, 0 failed and 728 were skipped.

clang-tidy: pass.

clang-format: pass.

Build artifacts: diff.json, clang-tidy.txt, clang-format.patch, CMakeCache.txt, console-log.txt, test-results.xml

kadircet added inline comments.Jan 2 2020, 3:39 AM
clang-tools-extra/clangd/refactor/Rename.cpp
378

nit: move both this and invocation above(line 363) out of the loop into a std::string OldName

565

maybe I am missing it but, it is unclear whether start to end is half-open/closed intervals.
could you add a test case with a single character identifier(you might want to accept equality, if this is a closed interval) and add some comments to the OccurrencesOffsets?

sammccall requested changes to this revision.Jan 2 2020, 5:53 AM

Postfiltering non-textual references won't work for the index-based rename, as the whole adjust-the-ranges algorithm relies on the index references being a subset of textual matches. More details in https://github.com/clangd/clangd/issues/238

It looks like this code change only affects index-based rename, but the attached test is only for AST-based rename.

I thought the plan of record was to make sure the index knew whether the reference was textual or not, and filter them out before calling adjustRenameRanges?

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

this isn't valid c++

882

If you want to be sure of fixing this bug, I'd like to see a test case:

  • where the index is out of date
  • where the macro name is unrelated to the symbol name
  • where the macro usages are interleaved with the non-macro usages
  • where the macro usages are in the file which is renamed based on the index, not the one where renamed based on ast
This revision now requires changes to proceed.Jan 2 2020, 5:53 AM
kbobyrev abandoned this revision.Apr 20 2020, 6:45 AM