xref: /llvm-project/clang-tools-extra/clangd/unittests/RenameTests.cpp (revision 61fe67a4017375fd675f75652e857e837f77fa51)
1 //===-- RenameTests.cpp -----------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "Annotations.h"
10 #include "ClangdServer.h"
11 #include "SyncAPI.h"
12 #include "TestFS.h"
13 #include "TestTU.h"
14 #include "index/Ref.h"
15 #include "refactor/Rename.h"
16 #include "support/TestTracer.h"
17 #include "clang/Tooling/Core/Replacement.h"
18 #include "llvm/ADT/STLExtras.h"
19 #include "llvm/Support/MemoryBuffer.h"
20 #include <algorithm>
21 #include "gmock/gmock.h"
22 #include "gtest/gtest.h"
23 
24 namespace clang {
25 namespace clangd {
26 namespace {
27 
28 using testing::ElementsAre;
29 using testing::Eq;
30 using testing::IsEmpty;
31 using testing::Pair;
32 using testing::SizeIs;
33 using testing::UnorderedElementsAre;
34 using testing::UnorderedElementsAreArray;
35 
36 llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem>
37 createOverlay(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> Base,
38               llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> Overlay) {
39   auto OFS =
40       llvm::makeIntrusiveRefCnt<llvm::vfs::OverlayFileSystem>(std::move(Base));
41   OFS->pushOverlay(std::move(Overlay));
42   return OFS;
43 }
44 
45 llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> getVFSFromAST(ParsedAST &AST) {
46   return &AST.getSourceManager().getFileManager().getVirtualFileSystem();
47 }
48 
49 // Convert a Range to a Ref.
50 Ref refWithRange(const clangd::Range &Range, const std::string &URI) {
51   Ref Result;
52   Result.Kind = RefKind::Reference | RefKind::Spelled;
53   Result.Location.Start.setLine(Range.start.line);
54   Result.Location.Start.setColumn(Range.start.character);
55   Result.Location.End.setLine(Range.end.line);
56   Result.Location.End.setColumn(Range.end.character);
57   Result.Location.FileURI = URI.c_str();
58   return Result;
59 }
60 
61 // Build a RefSlab from all marked ranges in the annotation. The ranges are
62 // assumed to associate with the given SymbolName.
63 std::unique_ptr<RefSlab> buildRefSlab(const Annotations &Code,
64                                       llvm::StringRef SymbolName,
65                                       llvm::StringRef Path) {
66   RefSlab::Builder Builder;
67   TestTU TU;
68   TU.HeaderCode = std::string(Code.code());
69   auto Symbols = TU.headerSymbols();
70   const auto &SymbolID = findSymbol(Symbols, SymbolName).ID;
71   std::string PathURI = URI::create(Path).toString();
72   for (const auto &Range : Code.ranges())
73     Builder.insert(SymbolID, refWithRange(Range, PathURI));
74 
75   return std::make_unique<RefSlab>(std::move(Builder).build());
76 }
77 
78 std::vector<
79     std::pair</*FilePath*/ std::string, /*CodeAfterRename*/ std::string>>
80 applyEdits(FileEdits FE) {
81   std::vector<std::pair<std::string, std::string>> Results;
82   for (auto &It : FE)
83     Results.emplace_back(
84         It.first().str(),
85         llvm::cantFail(tooling::applyAllReplacements(
86             It.getValue().InitialCode, It.getValue().Replacements)));
87   return Results;
88 }
89 
90 // Generates an expected rename result by replacing all ranges in the given
91 // annotation with the NewName.
92 std::string expectedResult(Annotations Test, llvm::StringRef NewName) {
93   std::string Result;
94   unsigned NextChar = 0;
95   llvm::StringRef Code = Test.code();
96   for (const auto &R : Test.llvm::Annotations::ranges()) {
97     assert(R.Begin <= R.End && NextChar <= R.Begin);
98     Result += Code.substr(NextChar, R.Begin - NextChar);
99     Result += NewName;
100     NextChar = R.End;
101   }
102   Result += Code.substr(NextChar);
103   return Result;
104 }
105 
106 std::vector<SymbolRange> symbolRanges(llvm::ArrayRef<Range> Ranges) {
107   std::vector<SymbolRange> Result;
108   for (const auto &R : Ranges)
109     Result.emplace_back(R);
110   return Result;
111 }
112 
113 TEST(RenameTest, WithinFileRename) {
114   // For each "^" this test moves cursor to its location and applies renaming
115   // while checking that all identifiers in [[]] ranges are also renamed.
116   llvm::StringRef Tests[] = {
117       // Function.
118       R"cpp(
119         void [[foo^]]() {
120           [[fo^o]]();
121         }
122       )cpp",
123 
124       // Type.
125       R"cpp(
126         struct [[foo^]] {};
127         [[foo]] test() {
128            [[f^oo]] x;
129            return x;
130         }
131       )cpp",
132 
133       // Local variable.
134       R"cpp(
135         void bar() {
136           if (auto [[^foo]] = 5) {
137             [[foo]] = 3;
138           }
139         }
140       )cpp",
141 
142       // Class, its constructor and destructor.
143       R"cpp(
144         class [[F^oo]] {
145           [[F^oo]]();
146           ~[[F^oo]]();
147           [[F^oo]] *foo(int x);
148 
149           [[F^oo]] *Ptr;
150         };
151         [[F^oo]]::[[Fo^o]]() {}
152         [[F^oo]]::~[[Fo^o]]() {}
153         [[F^oo]] *[[F^oo]]::foo(int x) { return Ptr; }
154       )cpp",
155 
156       // Template class, its constructor and destructor.
157       R"cpp(
158         template <typename T>
159         class [[F^oo]] {
160           [[F^oo]]();
161           ~[[F^oo]]();
162           void f([[F^oo]] x);
163         };
164 
165         template<typename T>
166         [[F^oo]]<T>::[[Fo^o]]() {}
167 
168         template<typename T>
169         [[F^oo]]<T>::~[[Fo^o]]() {}
170       )cpp",
171 
172       // Template class constructor.
173       R"cpp(
174         class [[F^oo]] {
175           template<typename T>
176           [[Fo^o]]();
177 
178           template<typename T>
179           [[F^oo]](T t);
180         };
181 
182         template<typename T>
183         [[F^oo]]::[[Fo^o]]() {}
184       )cpp",
185 
186       // Class in template argument.
187       R"cpp(
188         class [[F^oo]] {};
189         template <typename T> void func();
190         template <typename T> class Baz {};
191         int main() {
192           func<[[F^oo]]>();
193           Baz<[[F^oo]]> obj;
194           return 0;
195         }
196       )cpp",
197 
198       // Forward class declaration without definition.
199       R"cpp(
200         class [[F^oo]];
201         [[F^oo]] *f();
202       )cpp",
203 
204       // Member function.
205       R"cpp(
206         struct X {
207           void [[F^oo]]() {}
208           void Baz() { [[F^oo]](); }
209         };
210       )cpp",
211 
212       // Templated method instantiation.
213       R"cpp(
214         template<typename T>
215         class Foo {
216         public:
217           static T [[f^oo]]() {}
218         };
219 
220         void bar() {
221           Foo<int>::[[f^oo]]();
222         }
223       )cpp",
224       R"cpp(
225         template<typename T>
226         class Foo {
227         public:
228           T [[f^oo]]() {}
229         };
230 
231         void bar() {
232           Foo<int>().[[f^oo]]();
233         }
234       )cpp",
235 
236       // Template class (partial) specializations.
237       R"cpp(
238         template <typename T>
239         class [[F^oo]] {};
240 
241         template<>
242         class [[F^oo]]<bool> {};
243         template <typename T>
244         class [[F^oo]]<T*> {};
245 
246         void test() {
247           [[F^oo]]<int> x;
248           [[F^oo]]<bool> y;
249           [[F^oo]]<int*> z;
250         }
251       )cpp",
252 
253       // Incomplete class specializations
254       R"cpp(
255         template <typename T>
256         class [[Fo^o]] {};
257         void func([[F^oo]]<int>);
258       )cpp",
259 
260       // Template class instantiations.
261       R"cpp(
262         template <typename T>
263         class [[F^oo]] {
264         public:
265           T foo(T arg, T& ref, T* ptr) {
266             T value;
267             int number = 42;
268             value = (T)number;
269             value = static_cast<T>(number);
270             return value;
271           }
272           static void foo(T value) {}
273           T member;
274         };
275 
276         template <typename T>
277         void func() {
278           [[F^oo]]<T> obj;
279           obj.member = T();
280           [[Foo]]<T>::foo();
281         }
282 
283         void test() {
284           [[F^oo]]<int> i;
285           i.member = 0;
286           [[F^oo]]<int>::foo(0);
287 
288           [[F^oo]]<bool> b;
289           b.member = false;
290           [[F^oo]]<bool>::foo(false);
291         }
292       )cpp",
293 
294       // Template class methods.
295       R"cpp(
296         template <typename T>
297         class A {
298         public:
299           void [[f^oo]]() {}
300         };
301 
302         void func() {
303           A<int>().[[f^oo]]();
304           A<double>().[[f^oo]]();
305           A<float>().[[f^oo]]();
306         }
307       )cpp",
308 
309       // Templated class specialization.
310       R"cpp(
311         template<typename T, typename U=bool>
312         class [[Foo^]];
313 
314         template<typename T, typename U>
315         class [[Foo^]] {};
316 
317         template<typename T=int, typename U>
318         class [[Foo^]];
319       )cpp",
320       R"cpp(
321         template<typename T=float, typename U=int>
322         class [[Foo^]];
323 
324         template<typename T, typename U>
325         class [[Foo^]] {};
326       )cpp",
327 
328       // Function template specialization.
329       R"cpp(
330         template<typename T=int, typename U=bool>
331         U [[foo^]]();
332 
333         template<typename T, typename U>
334         U [[foo^]]() {};
335       )cpp",
336       R"cpp(
337         template<typename T, typename U>
338         U [[foo^]]() {};
339 
340         template<typename T=int, typename U=bool>
341         U [[foo^]]();
342       )cpp",
343       R"cpp(
344         template<typename T=int, typename U=bool>
345         U [[foo^]]();
346 
347         template<typename T, typename U>
348         U [[foo^]]();
349       )cpp",
350       R"cpp(
351         template <typename T>
352         void [[f^oo]](T t);
353 
354         template <>
355         void [[f^oo]](int a);
356 
357         void test() {
358           [[f^oo]]<double>(1);
359         }
360       )cpp",
361 
362       // Variable template.
363       R"cpp(
364         template <typename T, int U>
365         bool [[F^oo]] = true;
366 
367         // Explicit template specialization
368         template <>
369         bool [[F^oo]]<int, 0> = false;
370 
371         // Partial template specialization
372         template <typename T>
373         bool [[F^oo]]<T, 1> = false;
374 
375         void foo() {
376           // Ref to the explicit template specialization
377           [[F^oo]]<int, 0>;
378           // Ref to the primary template.
379           [[F^oo]]<double, 2>;
380         }
381       )cpp",
382 
383       // Complicated class type.
384       R"cpp(
385          // Forward declaration.
386         class [[Fo^o]];
387         class Baz {
388           virtual int getValue() const = 0;
389         };
390 
391         class [[F^oo]] : public Baz  {
392         public:
393           [[F^oo]](int value = 0) : x(value) {}
394 
395           [[F^oo]] &operator++(int);
396 
397           bool operator<([[Foo]] const &rhs);
398           int getValue() const;
399         private:
400           int x;
401         };
402 
403         void func() {
404           [[F^oo]] *Pointer = 0;
405           [[F^oo]] Variable = [[Foo]](10);
406           for ([[F^oo]] it; it < Variable; it++);
407           const [[F^oo]] *C = new [[Foo]]();
408           const_cast<[[F^oo]] *>(C)->getValue();
409           [[F^oo]] foo;
410           const Baz &BazReference = foo;
411           const Baz *BazPointer = &foo;
412           reinterpret_cast<const [[^Foo]] *>(BazPointer)->getValue();
413           static_cast<const [[^Foo]] &>(BazReference).getValue();
414           static_cast<const [[^Foo]] *>(BazPointer)->getValue();
415         }
416       )cpp",
417 
418       // Static class member.
419       R"cpp(
420         struct Foo {
421           static Foo *[[Static^Member]];
422         };
423 
424         Foo* Foo::[[Static^Member]] = nullptr;
425 
426         void foo() {
427           Foo* Pointer = Foo::[[Static^Member]];
428         }
429       )cpp",
430 
431       // Reference in lambda parameters.
432       R"cpp(
433         template <class T>
434         class function;
435         template <class R, class... ArgTypes>
436         class function<R(ArgTypes...)> {
437         public:
438           template <typename Functor>
439           function(Functor f) {}
440 
441           function() {}
442 
443           R operator()(ArgTypes...) const {}
444         };
445 
446         namespace ns {
447         class [[Old]] {};
448         void f() {
449           function<void([[Old]])> func;
450         }
451         }  // namespace ns
452       )cpp",
453 
454       // Destructor explicit call.
455       R"cpp(
456         class [[F^oo]] {
457         public:
458           ~[[^Foo]]();
459         };
460 
461         [[Foo^]]::~[[^Foo]]() {}
462 
463         int main() {
464           [[Fo^o]] f;
465           f.~/*something*/[[^Foo]]();
466           f.~[[^Foo]]();
467         }
468       )cpp",
469 
470       // Derived destructor explicit call.
471       R"cpp(
472         class [[Bas^e]] {};
473         class Derived : public [[Bas^e]] {};
474 
475         int main() {
476           [[Bas^e]] *foo = new Derived();
477           foo->[[^Base]]::~[[^Base]]();
478         }
479       )cpp",
480 
481       // CXXConstructor initializer list.
482       R"cpp(
483         class Baz {};
484         class Qux {
485           Baz [[F^oo]];
486         public:
487           Qux();
488         };
489         Qux::Qux() : [[F^oo]]() {}
490       )cpp",
491 
492       // DeclRefExpr.
493       R"cpp(
494         class C {
495         public:
496           static int [[F^oo]];
497         };
498 
499         int foo(int x);
500         #define MACRO(a) foo(a)
501 
502         void func() {
503           C::[[F^oo]] = 1;
504           MACRO(C::[[Foo]]);
505           int y = C::[[F^oo]];
506         }
507       )cpp",
508 
509       // Macros.
510       R"cpp(
511         // no rename inside macro body.
512         #define M1 foo
513         #define M2(x) x
514         int [[fo^o]]();
515         void boo(int);
516 
517         void qoo() {
518           [[f^oo]]();
519           boo([[f^oo]]());
520           M1();
521           boo(M1());
522           M2([[f^oo]]());
523           M2(M1()); // foo is inside the nested macro body.
524         }
525       )cpp",
526 
527       // MemberExpr in macros
528       R"cpp(
529         class Baz {
530         public:
531           int [[F^oo]];
532         };
533         int qux(int x);
534         #define MACRO(a) qux(a)
535 
536         int main() {
537           Baz baz;
538           baz.[[F^oo]] = 1;
539           MACRO(baz.[[F^oo]]);
540           int y = baz.[[F^oo]];
541         }
542       )cpp",
543 
544       // Fields in classes & partial and full specialiations.
545       R"cpp(
546         template<typename T>
547         struct Foo {
548           T [[Vari^able]] = 42;
549         };
550 
551         void foo() {
552           Foo<int> f;
553           f.[[Varia^ble]] = 9000;
554         }
555       )cpp",
556       R"cpp(
557         template<typename T, typename U>
558         struct Foo {
559           T Variable[42];
560           U Another;
561 
562           void bar() {}
563         };
564 
565         template<typename T>
566         struct Foo<T, bool> {
567           T [[Var^iable]];
568           void bar() { ++[[Var^iable]]; }
569         };
570 
571         void foo() {
572           Foo<unsigned, bool> f;
573           f.[[Var^iable]] = 9000;
574         }
575       )cpp",
576       R"cpp(
577         template<typename T, typename U>
578         struct Foo {
579           T Variable[42];
580           U Another;
581 
582           void bar() {}
583         };
584 
585         template<typename T>
586         struct Foo<T, bool> {
587           T Variable;
588           void bar() { ++Variable; }
589         };
590 
591         template<>
592         struct Foo<unsigned, bool> {
593           unsigned [[Var^iable]];
594           void bar() { ++[[Var^iable]]; }
595         };
596 
597         void foo() {
598           Foo<unsigned, bool> f;
599           f.[[Var^iable]] = 9000;
600         }
601       )cpp",
602       // Static fields.
603       R"cpp(
604         struct Foo {
605           static int [[Var^iable]];
606         };
607 
608         int Foo::[[Var^iable]] = 42;
609 
610         void foo() {
611           int LocalInt = Foo::[[Var^iable]];
612         }
613       )cpp",
614       R"cpp(
615         template<typename T>
616         struct Foo {
617           static T [[Var^iable]];
618         };
619 
620         template <>
621         int Foo<int>::[[Var^iable]] = 42;
622 
623         template <>
624         bool Foo<bool>::[[Var^iable]] = true;
625 
626         void foo() {
627           int LocalInt = Foo<int>::[[Var^iable]];
628           bool LocalBool = Foo<bool>::[[Var^iable]];
629         }
630       )cpp",
631 
632       // Template parameters.
633       R"cpp(
634         template <typename [[^T]]>
635         class Foo {
636           [[T^]] foo([[T^]] arg, [[T^]]& ref, [[^T]]* ptr) {
637             [[T]] value;
638             int number = 42;
639             value = ([[T^]])number;
640             value = static_cast<[[^T]]>(number);
641             return value;
642           }
643           static void foo([[T^]] value) {}
644           [[T^]] member;
645         };
646       )cpp",
647 
648       // Typedef.
649       R"cpp(
650         namespace ns {
651         class basic_string {};
652         typedef basic_string [[s^tring]];
653         } // namespace ns
654 
655         ns::[[s^tring]] foo();
656       )cpp",
657 
658       // Variable.
659       R"cpp(
660         namespace A {
661         int [[F^oo]];
662         }
663         int Foo;
664         int Qux = Foo;
665         int Baz = A::[[^Foo]];
666         void fun() {
667           struct {
668             int Foo;
669           } b = {100};
670           int Foo = 100;
671           Baz = Foo;
672           {
673             extern int Foo;
674             Baz = Foo;
675             Foo = A::[[F^oo]] + Baz;
676             A::[[Fo^o]] = b.Foo;
677           }
678           Foo = b.Foo;
679         }
680       )cpp",
681 
682       // Namespace alias.
683       R"cpp(
684         namespace a { namespace b { void foo(); } }
685         namespace [[^x]] = a::b;
686         void bar() {
687           [[x^]]::foo();
688         }
689       )cpp",
690 
691       // Enum.
692       R"cpp(
693         enum [[C^olor]] { Red, Green, Blue };
694         void foo() {
695           [[C^olor]] c;
696           c = [[C^olor]]::Blue;
697         }
698       )cpp",
699 
700       // Scoped enum.
701       R"cpp(
702         enum class [[K^ind]] { ABC };
703         void ff() {
704           [[K^ind]] s;
705           s = [[K^ind]]::ABC;
706         }
707       )cpp",
708 
709       // Template class in template argument list.
710       R"cpp(
711         template<typename T>
712         class [[Fo^o]] {};
713         template <template<typename> class Z> struct Bar { };
714         template <> struct Bar<[[F^oo]]> {};
715       )cpp",
716 
717       // Designated initializer.
718       R"cpp(
719         struct Bar {
720           int [[Fo^o]];
721         };
722         Bar bar { .[[^Foo]] = 42 };
723       )cpp",
724 
725       // Nested designated initializer.
726       R"cpp(
727         struct Baz {
728           int Field;
729         };
730         struct Bar {
731           Baz [[Fo^o]];
732         };
733         // FIXME:    v selecting here results in renaming Field.
734         Bar bar { .[[Foo]].Field = 42 };
735       )cpp",
736       R"cpp(
737         struct Baz {
738           int [[Fiel^d]];
739         };
740         struct Bar {
741           Baz Foo;
742         };
743         Bar bar { .Foo.[[^Field]] = 42 };
744       )cpp",
745 
746       // Templated alias.
747       R"cpp(
748         template <typename T>
749         class X { T t; };
750 
751         template <typename T>
752         using [[Fo^o]] = X<T>;
753 
754         void bar() {
755           [[Fo^o]]<int> Bar;
756         }
757       )cpp",
758 
759       // Alias.
760       R"cpp(
761         class X {};
762         using [[F^oo]] = X;
763 
764         void bar() {
765           [[Fo^o]] Bar;
766         }
767       )cpp",
768 
769       // Alias within a namespace.
770       R"cpp(
771         namespace x { class X {}; }
772         namespace ns {
773         using [[Fo^o]] = x::X;
774         }
775 
776         void bar() {
777           ns::[[Fo^o]] Bar;
778         }
779       )cpp",
780 
781       // Alias within macros.
782       R"cpp(
783         namespace x { class Old {}; }
784         namespace ns {
785         #define REF(alias) alias alias_var;
786 
787         #define ALIAS(old) \
788           using old##Alias = x::old; \
789           REF(old##Alias);
790 
791         ALIAS(Old);
792 
793         [[Old^Alias]] old_alias;
794         }
795 
796         void bar() {
797           ns::[[Old^Alias]] Bar;
798         }
799       )cpp",
800 
801       // User defined conversion.
802       R"cpp(
803         class [[F^oo]] {
804         public:
805           [[F^oo]]() {}
806         };
807 
808         class Baz {
809         public:
810           operator [[F^oo]]() {
811             return [[F^oo]]();
812           }
813         };
814 
815         int main() {
816           Baz boo;
817           [[F^oo]] foo = static_cast<[[F^oo]]>(boo);
818         }
819       )cpp",
820 
821       // ObjC, should not crash.
822       R"cpp(
823         @interface ObjC {
824           char [[da^ta]];
825         } @end
826       )cpp",
827 
828       // Issue 170: Rename symbol introduced by UsingDecl
829       R"cpp(
830         namespace ns { void [[f^oo]](); }
831 
832         using ns::[[f^oo]];
833 
834         void f() {
835             [[f^oo]]();
836             auto p = &[[f^oo]];
837         }
838       )cpp",
839 
840       // Issue 170: using decl that imports multiple overloads
841       // -> Only the overload under the cursor is renamed
842       R"cpp(
843         namespace ns { int [[^foo]](int); char foo(char); }
844         using ns::[[foo]];
845         void f() {
846           [[^foo]](42);
847           foo('x');
848         }
849       )cpp",
850 
851       // ObjC class with a category.
852       R"cpp(
853         @interface [[Fo^o]]
854         @end
855         @implementation [[F^oo]]
856         @end
857         @interface [[Fo^o]] (Category)
858         @end
859         @implementation [[F^oo]] (Category)
860         @end
861 
862         void func([[Fo^o]] *f) {}
863       )cpp",
864   };
865   llvm::StringRef NewName = "NewName";
866   for (llvm::StringRef T : Tests) {
867     SCOPED_TRACE(T);
868     Annotations Code(T);
869     auto TU = TestTU::withCode(Code.code());
870     TU.ExtraArgs.push_back("-xobjective-c++");
871     auto AST = TU.build();
872     auto Index = TU.index();
873     for (const auto &RenamePos : Code.points()) {
874       auto RenameResult =
875           rename({RenamePos, NewName, AST, testPath(TU.Filename),
876                   getVFSFromAST(AST), Index.get()});
877       ASSERT_TRUE(bool(RenameResult)) << RenameResult.takeError();
878       ASSERT_EQ(1u, RenameResult->GlobalChanges.size());
879       EXPECT_EQ(
880           applyEdits(std::move(RenameResult->GlobalChanges)).front().second,
881           expectedResult(Code, NewName));
882     }
883   }
884 }
885 
886 TEST(RenameTest, ObjCWithinFileRename) {
887   struct TestCase {
888     /// Annotated source code that should be renamed. Every point (indicated by
889     /// `^`) will be used as a rename location.
890     llvm::StringRef Input;
891     /// The new name that should be given to the rename locaitons.
892     llvm::StringRef NewName;
893     /// The expected rename source code or `nullopt` if we expect rename to
894     /// fail.
895     std::optional<llvm::StringRef> Expected;
896   };
897   TestCase Tests[] = {// Simple rename
898                       {
899                           // Input
900                           R"cpp(
901         @interface Foo
902         - (int)performA^ction:(int)action w^ith:(int)value;
903         @end
904         @implementation Foo
905         - (int)performAc^tion:(int)action w^ith:(int)value {
906           return [self performAction:action with:value];
907         }
908         @end
909       )cpp",
910                           // New name
911                           "performNewAction:by:",
912                           // Expected
913                           R"cpp(
914         @interface Foo
915         - (int)performNewAction:(int)action by:(int)value;
916         @end
917         @implementation Foo
918         - (int)performNewAction:(int)action by:(int)value {
919           return [self performNewAction:action by:value];
920         }
921         @end
922       )cpp",
923                       },
924                       // Rename selector with macro
925                       {
926                           // Input
927                           R"cpp(
928         #define mySelector - (int)performAction:(int)action with:(int)value
929         @interface Foo
930         ^mySelector;
931         @end
932         @implementation Foo
933         mySelector {
934           return [self performAction:action with:value];
935         }
936         @end
937       )cpp",
938                           // New name
939                           "performNewAction:by:",
940                           // Expected error
941                           std::nullopt,
942                       },
943                       // Rename selector in macro definition
944                       {
945                           // Input
946                           R"cpp(
947         #define mySelector - (int)perform^Action:(int)action with:(int)value
948         @interface Foo
949         mySelector;
950         @end
951         @implementation Foo
952         mySelector {
953           return [self performAction:action with:value];
954         }
955         @end
956       )cpp",
957                           // New name
958                           "performNewAction:by:",
959                           // Expected error
960                           std::nullopt,
961                       },
962                       // Don't rename `@selector`
963                       // `@selector` is not tied to a single selector. Eg. there
964                       // might be multiple
965                       // classes in the codebase that implement that selector.
966                       // It's thus more like
967                       // a string literal and we shouldn't rename it.
968                       {
969                           // Input
970                           R"cpp(
971         @interface Foo
972         - (void)performA^ction:(int)action with:(int)value;
973         @end
974         @implementation Foo
975         - (void)performAction:(int)action with:(int)value {
976           SEL mySelector = @selector(performAction:with:);
977         }
978         @end
979       )cpp",
980                           // New name
981                           "performNewAction:by:",
982                           // Expected
983                           R"cpp(
984         @interface Foo
985         - (void)performNewAction:(int)action by:(int)value;
986         @end
987         @implementation Foo
988         - (void)performNewAction:(int)action by:(int)value {
989           SEL mySelector = @selector(performAction:with:);
990         }
991         @end
992       )cpp",
993                       },
994                       // Fail if rename initiated inside @selector
995                       {
996                           // Input
997                           R"cpp(
998         @interface Foo
999         - (void)performAction:(int)action with:(int)value;
1000         @end
1001         @implementation Foo
1002         - (void)performAction:(int)action with:(int)value {
1003           SEL mySelector = @selector(perfo^rmAction:with:);
1004         }
1005         @end
1006       )cpp",
1007                           // New name
1008                           "performNewAction:by:",
1009                           // Expected
1010                           std::nullopt,
1011                       }};
1012   for (TestCase T : Tests) {
1013     SCOPED_TRACE(T.Input);
1014     Annotations Code(T.Input);
1015     auto TU = TestTU::withCode(Code.code());
1016     TU.ExtraArgs.push_back("-xobjective-c");
1017     auto AST = TU.build();
1018     auto Index = TU.index();
1019     for (const auto &RenamePos : Code.points()) {
1020       auto RenameResult =
1021           rename({RenamePos, T.NewName, AST, testPath(TU.Filename),
1022                   getVFSFromAST(AST), Index.get()});
1023       if (std::optional<StringRef> Expected = T.Expected) {
1024         ASSERT_TRUE(bool(RenameResult)) << RenameResult.takeError();
1025         ASSERT_EQ(1u, RenameResult->GlobalChanges.size());
1026         EXPECT_EQ(
1027             applyEdits(std::move(RenameResult->GlobalChanges)).front().second,
1028             *Expected);
1029       } else {
1030         ASSERT_FALSE(bool(RenameResult));
1031         consumeError(RenameResult.takeError());
1032       }
1033     }
1034   }
1035 }
1036 
1037 TEST(RenameTest, Renameable) {
1038   struct Case {
1039     const char *Code;
1040     const char* ErrorMessage; // null if no error
1041     bool IsHeaderFile;
1042     llvm::StringRef NewName = "MockName";
1043   };
1044   const bool HeaderFile = true;
1045   Case Cases[] = {
1046       {R"cpp(// allow -- function-local
1047         void f(int [[Lo^cal]]) {
1048           [[Local]] = 2;
1049         }
1050       )cpp",
1051        nullptr, HeaderFile},
1052 
1053       {R"cpp(// disallow -- symbol in anonymous namespace in header is not indexable.
1054         namespace {
1055         class Unin^dexable {};
1056         }
1057       )cpp",
1058        "not eligible for indexing", HeaderFile},
1059 
1060       {R"cpp(// disallow -- namespace symbol isn't supported
1061         namespace n^s {}
1062       )cpp",
1063        "not a supported kind", HeaderFile},
1064 
1065       {R"cpp(// disallow - category rename.
1066         @interface Foo
1067         @end
1068         @interface Foo (Cate^gory)
1069         @end
1070       )cpp",
1071        "Cannot rename symbol: there is no symbol at the given location",
1072        HeaderFile},
1073 
1074       {
1075           R"cpp(
1076          #define MACRO 1
1077          int s = MAC^RO;
1078        )cpp",
1079           "not a supported kind", HeaderFile},
1080 
1081       {
1082           R"cpp(
1083         struct X { X operator++(int); };
1084         void f(X x) {x+^+;})cpp",
1085           "no symbol", HeaderFile},
1086 
1087       {R"cpp(
1088          @interface Foo {}
1089          - (int)[[fo^o]]:(int)x;
1090          @end
1091        )cpp",
1092        nullptr, HeaderFile, "newName:"},
1093       {R"cpp(//disallow as : count must match
1094          @interface Foo {}
1095          - (int)fo^o:(int)x;
1096          @end
1097        )cpp",
1098        "invalid name: the chosen name \"MockName\" is not a valid identifier",
1099        HeaderFile},
1100       {R"cpp(
1101          @interface Foo {}
1102          - (int)[[o^ne]]:(int)one two:(int)two;
1103          @end
1104        )cpp",
1105        nullptr, HeaderFile, "a:two:"},
1106       {R"cpp(
1107          @interface Foo {}
1108          - (int)[[o^ne]]:(int)one [[two]]:(int)two;
1109          @end
1110        )cpp",
1111        nullptr, HeaderFile, "a:b:"},
1112       {R"cpp(
1113          @interface Foo {}
1114          - (int)o^ne:(int)one [[two]]:(int)two;
1115          @end
1116        )cpp",
1117        nullptr, HeaderFile, "one:three:"},
1118 
1119       {R"cpp(
1120          void foo(int);
1121          void foo(char);
1122          template <typename T> void f(T t) {
1123            fo^o(t);
1124          })cpp",
1125        "multiple symbols", !HeaderFile},
1126 
1127       {R"cpp(// disallow rename on unrelated token.
1128          cl^ass Foo {};
1129        )cpp",
1130        "no symbol", !HeaderFile},
1131 
1132       {R"cpp(// disallow rename on unrelated token.
1133          temp^late<typename T>
1134          class Foo {};
1135        )cpp",
1136        "no symbol", !HeaderFile},
1137 
1138       {R"cpp(
1139         namespace {
1140         int Conflict;
1141         int Va^r;
1142         }
1143       )cpp",
1144        "conflict", !HeaderFile, "Conflict"},
1145 
1146       {R"cpp(
1147         int Conflict;
1148         int Va^r;
1149       )cpp",
1150        "conflict", !HeaderFile, "Conflict"},
1151 
1152       {R"cpp(
1153         class Foo {
1154           int Conflict;
1155           int Va^r;
1156         };
1157       )cpp",
1158        "conflict", !HeaderFile, "Conflict"},
1159 
1160       {R"cpp(
1161         enum E {
1162           Conflict,
1163           Fo^o,
1164         };
1165       )cpp",
1166        "conflict", !HeaderFile, "Conflict"},
1167 
1168       {R"cpp(
1169         int Conflict;
1170         enum E { // transparent context.
1171           F^oo,
1172         };
1173       )cpp",
1174        "conflict", !HeaderFile, "Conflict"},
1175 
1176       {R"cpp(
1177         void func() {
1178           bool Whatever;
1179           int V^ar;
1180           char Conflict;
1181         }
1182       )cpp",
1183        "conflict", !HeaderFile, "Conflict"},
1184 
1185       {R"cpp(
1186         void func() {
1187           if (int Conflict = 42) {
1188             int V^ar;
1189           }
1190         }
1191       )cpp",
1192        "conflict", !HeaderFile, "Conflict"},
1193 
1194       {R"cpp(
1195         void func() {
1196           if (int Conflict = 42) {
1197           } else {
1198             bool V^ar;
1199           }
1200         }
1201       )cpp",
1202        "conflict", !HeaderFile, "Conflict"},
1203 
1204       {R"cpp(
1205         void func() {
1206           if (int V^ar = 42) {
1207           } else {
1208             bool Conflict;
1209           }
1210         }
1211       )cpp",
1212        "conflict", !HeaderFile, "Conflict"},
1213 
1214       {R"cpp(
1215         void func() {
1216           while (int V^ar = 10) {
1217             bool Conflict = true;
1218           }
1219         }
1220       )cpp",
1221        "conflict", !HeaderFile, "Conflict"},
1222 
1223       {R"cpp(
1224         void func() {
1225           for (int Something = 9000, Anything = 14, Conflict = 42; Anything > 9;
1226                ++Something) {
1227             int V^ar;
1228           }
1229         }
1230       )cpp",
1231        "conflict", !HeaderFile, "Conflict"},
1232 
1233       {R"cpp(
1234         void func() {
1235           for (int V^ar = 14, Conflict = 42;;) {
1236           }
1237         }
1238       )cpp",
1239        "conflict", !HeaderFile, "Conflict"},
1240 
1241       {R"cpp(
1242         void func(int Conflict) {
1243           bool V^ar;
1244         }
1245       )cpp",
1246        "conflict", !HeaderFile, "Conflict"},
1247 
1248       {R"cpp(
1249         void func(int Var);
1250 
1251         void func(int V^ar) {
1252           bool Conflict;
1253         }
1254       )cpp",
1255        "conflict", !HeaderFile, "Conflict"},
1256 
1257       {R"cpp(// No conflict: only forward declaration's argument is renamed.
1258         void func(int [[V^ar]]);
1259 
1260         void func(int Var) {
1261           bool Conflict;
1262         }
1263       )cpp",
1264        nullptr, !HeaderFile, "Conflict"},
1265 
1266       {R"cpp(
1267         void func(int V^ar, int Conflict) {
1268         }
1269       )cpp",
1270        "conflict", !HeaderFile, "Conflict"},
1271 
1272       {R"cpp(
1273         void func(int);
1274         void [[o^therFunc]](double);
1275       )cpp",
1276        nullptr, !HeaderFile, "func"},
1277       {R"cpp(
1278         struct S {
1279           void func(int);
1280           void [[o^therFunc]](double);
1281         };
1282       )cpp",
1283        nullptr, !HeaderFile, "func"},
1284 
1285       {R"cpp(
1286         int V^ar;
1287       )cpp",
1288        "\"const\" is a keyword", !HeaderFile, "const"},
1289 
1290       {R"cpp(// Trying to rename into the same name, SameName == SameName.
1291         void func() {
1292           int S^ameName;
1293         }
1294       )cpp",
1295        "new name is the same", !HeaderFile, "SameName"},
1296       {R"cpp(// Ensure it doesn't associate base specifier with base name.
1297         struct A {};
1298         struct B : priv^ate A {};
1299       )cpp",
1300        "Cannot rename symbol: there is no symbol at the given location", false},
1301       {R"cpp(// Ensure it doesn't associate base specifier with base name.
1302         /*error-ok*/
1303         struct A {
1304           A() : inva^lid(0) {}
1305         };
1306       )cpp",
1307        "no symbol", false},
1308 
1309       {R"cpp(// FIXME we probably want to rename both overloads here,
1310              // but renaming currently assumes there's only a
1311              // single canonical declaration.
1312         namespace ns { int foo(int); char foo(char); }
1313         using ns::^foo;
1314       )cpp",
1315        "there are multiple symbols at the given location", !HeaderFile},
1316 
1317       {R"cpp(
1318         void test() {
1319           // no crash
1320           using namespace std;
1321           int [[V^ar]];
1322         }
1323       )cpp",
1324        nullptr, !HeaderFile},
1325   };
1326 
1327   for (const auto& Case : Cases) {
1328     SCOPED_TRACE(Case.Code);
1329     Annotations T(Case.Code);
1330     TestTU TU = TestTU::withCode(T.code());
1331     TU.ExtraArgs.push_back("-fno-delayed-template-parsing");
1332     if (Case.IsHeaderFile) {
1333       // We open the .h file as the main file.
1334       TU.Filename = "test.h";
1335       // Parsing the .h file as C++ include.
1336       TU.ExtraArgs.push_back("-xobjective-c++-header");
1337     }
1338     auto AST = TU.build();
1339     llvm::StringRef NewName = Case.NewName;
1340     auto Results = rename({T.point(), NewName, AST, testPath(TU.Filename)});
1341     bool WantRename = true;
1342     if (T.ranges().empty())
1343       WantRename = false;
1344     if (!WantRename) {
1345       assert(Case.ErrorMessage && "Error message must be set!");
1346       EXPECT_FALSE(Results)
1347           << "expected rename returned an error: " << T.code();
1348       auto ActualMessage = llvm::toString(Results.takeError());
1349       EXPECT_THAT(ActualMessage, testing::HasSubstr(Case.ErrorMessage));
1350     } else {
1351       EXPECT_TRUE(bool(Results)) << "rename returned an error: "
1352                                  << llvm::toString(Results.takeError());
1353       EXPECT_EQ(Results->LocalChanges, T.ranges());
1354     }
1355   }
1356 }
1357 
1358 MATCHER_P(newText, T, "") { return arg.newText == T; }
1359 
1360 TEST(RenameTest, IndexMergeMainFile) {
1361   Annotations Code("int ^x();");
1362   TestTU TU = TestTU::withCode(Code.code());
1363   TU.Filename = "main.cc";
1364   auto AST = TU.build();
1365 
1366   auto Main = testPath("main.cc");
1367   auto InMemFS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
1368   InMemFS->addFile(testPath("main.cc"), 0,
1369                    llvm::MemoryBuffer::getMemBuffer(Code.code()));
1370   InMemFS->addFile(testPath("other.cc"), 0,
1371                    llvm::MemoryBuffer::getMemBuffer(Code.code()));
1372 
1373   auto Rename = [&](const SymbolIndex *Idx) {
1374     RenameInputs Inputs{Code.point(),
1375                         "xPrime",
1376                         AST,
1377                         Main,
1378                         Idx ? createOverlay(getVFSFromAST(AST), InMemFS)
1379                             : nullptr,
1380                         Idx,
1381                         RenameOptions()};
1382     auto Results = rename(Inputs);
1383     EXPECT_TRUE(bool(Results)) << llvm::toString(Results.takeError());
1384     return std::move(*Results);
1385   };
1386 
1387   // We do not expect to see duplicated edits from AST vs index.
1388   auto Results = Rename(TU.index().get());
1389   EXPECT_THAT(Results.GlobalChanges.keys(), ElementsAre(Main));
1390   EXPECT_THAT(Results.GlobalChanges[Main].asTextEdits(),
1391               ElementsAre(newText("xPrime")));
1392 
1393   // Sanity check: we do expect to see index results!
1394   TU.Filename = "other.cc";
1395   Results = Rename(TU.index().get());
1396   EXPECT_THAT(Results.GlobalChanges.keys(),
1397               UnorderedElementsAre(Main, testPath("other.cc")));
1398 
1399 #ifdef CLANGD_PATH_CASE_INSENSITIVE
1400   // On case-insensitive systems, no duplicates if AST vs index case differs.
1401   // https://github.com/clangd/clangd/issues/665
1402   TU.Filename = "MAIN.CC";
1403   Results = Rename(TU.index().get());
1404   EXPECT_THAT(Results.GlobalChanges.keys(), ElementsAre(Main));
1405   EXPECT_THAT(Results.GlobalChanges[Main].asTextEdits(),
1406               ElementsAre(newText("xPrime")));
1407 #endif
1408 }
1409 
1410 TEST(RenameTest, MainFileReferencesOnly) {
1411   // filter out references not from main file.
1412   llvm::StringRef Test =
1413       R"cpp(
1414         void test() {
1415           int [[fo^o]] = 1;
1416           // rename references not from main file are not included.
1417           #include "foo.inc"
1418         })cpp";
1419 
1420   Annotations Code(Test);
1421   auto TU = TestTU::withCode(Code.code());
1422   TU.AdditionalFiles["foo.inc"] = R"cpp(
1423       #define Macro(X) X
1424       &Macro(foo);
1425       &foo;
1426     )cpp";
1427   auto AST = TU.build();
1428   llvm::StringRef NewName = "abcde";
1429 
1430   auto RenameResult =
1431       rename({Code.point(), NewName, AST, testPath(TU.Filename)});
1432   ASSERT_TRUE(bool(RenameResult)) << RenameResult.takeError() << Code.point();
1433   ASSERT_EQ(1u, RenameResult->GlobalChanges.size());
1434   EXPECT_EQ(applyEdits(std::move(RenameResult->GlobalChanges)).front().second,
1435             expectedResult(Code, NewName));
1436 }
1437 
1438 TEST(RenameTest, NoRenameOnSymbolsFromSystemHeaders) {
1439   llvm::StringRef Test =
1440       R"cpp(
1441         #include <cstdlib>
1442         #include <system>
1443 
1444         SystemSym^bol abc;
1445 
1446         void foo() { at^oi("9000"); }
1447         )cpp";
1448 
1449   Annotations Code(Test);
1450   auto TU = TestTU::withCode(Code.code());
1451   TU.AdditionalFiles["system"] = R"cpp(
1452     class SystemSymbol {};
1453     )cpp";
1454   TU.AdditionalFiles["cstdlib"] = R"cpp(
1455     int atoi(const char *str);
1456     )cpp";
1457   TU.ExtraArgs = {"-isystem", testRoot()};
1458   auto AST = TU.build();
1459   llvm::StringRef NewName = "abcde";
1460 
1461   // Clangd will not allow renaming symbols from the system headers for
1462   // correctness.
1463   for (auto &Point : Code.points()) {
1464     auto Results = rename({Point, NewName, AST, testPath(TU.Filename)});
1465     EXPECT_FALSE(Results) << "expected rename returned an error: "
1466                           << Code.code();
1467     auto ActualMessage = llvm::toString(Results.takeError());
1468     EXPECT_THAT(ActualMessage, testing::HasSubstr("not a supported kind"));
1469   }
1470 }
1471 
1472 TEST(RenameTest, ProtobufSymbolIsExcluded) {
1473   Annotations Code("Prot^obuf buf;");
1474   auto TU = TestTU::withCode(Code.code());
1475   TU.HeaderCode =
1476       R"cpp(// Generated by the protocol buffer compiler.  DO NOT EDIT!
1477       class Protobuf {};
1478       )cpp";
1479   TU.HeaderFilename = "protobuf.pb.h";
1480   auto AST = TU.build();
1481   auto Results = rename({Code.point(), "newName", AST, testPath(TU.Filename)});
1482   EXPECT_FALSE(Results);
1483   EXPECT_THAT(llvm::toString(Results.takeError()),
1484               testing::HasSubstr("not a supported kind"));
1485 }
1486 
1487 TEST(RenameTest, PrepareRename) {
1488   Annotations FooH("void func();");
1489   Annotations FooCC(R"cpp(
1490     #include "foo.h"
1491     void [[fu^nc]]() {}
1492   )cpp");
1493   std::string FooHPath = testPath("foo.h");
1494   std::string FooCCPath = testPath("foo.cc");
1495   MockFS FS;
1496   FS.Files[FooHPath] = std::string(FooH.code());
1497   FS.Files[FooCCPath] = std::string(FooCC.code());
1498 
1499   auto ServerOpts = ClangdServer::optsForTest();
1500   ServerOpts.BuildDynamicSymbolIndex = true;
1501 
1502   trace::TestTracer Tracer;
1503   MockCompilationDatabase CDB;
1504   ClangdServer Server(CDB, FS, ServerOpts);
1505   runAddDocument(Server, FooHPath, FooH.code());
1506   runAddDocument(Server, FooCCPath, FooCC.code());
1507 
1508   auto Results = runPrepareRename(Server, FooCCPath, FooCC.point(),
1509                                   /*NewName=*/std::nullopt, {});
1510   // Verify that for multi-file rename, we only return main-file occurrences.
1511   ASSERT_TRUE(bool(Results)) << Results.takeError();
1512   // We don't know the result is complete in prepareRename (passing a nullptr
1513   // index internally), so GlobalChanges should be empty.
1514   EXPECT_TRUE(Results->GlobalChanges.empty());
1515   EXPECT_THAT(FooCC.ranges(),
1516               testing::UnorderedElementsAreArray(Results->LocalChanges));
1517 
1518   // Name validation.
1519   Results = runPrepareRename(Server, FooCCPath, FooCC.point(),
1520                              /*NewName=*/std::string("int"), {});
1521   EXPECT_FALSE(Results);
1522   EXPECT_THAT(llvm::toString(Results.takeError()),
1523               testing::HasSubstr("keyword"));
1524   EXPECT_THAT(Tracer.takeMetric("rename_name_invalid", "Keywords"),
1525               ElementsAre(1));
1526 
1527   for (std::string BadIdent : {"foo!bar", "123foo", "��@"}) {
1528     Results = runPrepareRename(Server, FooCCPath, FooCC.point(),
1529                                /*NewName=*/BadIdent, {});
1530     EXPECT_FALSE(Results);
1531     EXPECT_THAT(llvm::toString(Results.takeError()),
1532                 testing::HasSubstr("identifier"));
1533     EXPECT_THAT(Tracer.takeMetric("rename_name_invalid", "BadIdentifier"),
1534                 ElementsAre(1));
1535   }
1536   for (std::string GoodIdent : {"fooBar", "__foo$", "��"}) {
1537     Results = runPrepareRename(Server, FooCCPath, FooCC.point(),
1538                                /*NewName=*/GoodIdent, {});
1539     EXPECT_TRUE(bool(Results));
1540   }
1541 }
1542 
1543 TEST(CrossFileRenameTests, DirtyBuffer) {
1544   Annotations FooCode("class [[Foo]] {};");
1545   std::string FooPath = testPath("foo.cc");
1546   Annotations FooDirtyBuffer("class [[Foo]] {};\n// this is dirty buffer");
1547   Annotations BarCode("void [[Bar]]() {}");
1548   std::string BarPath = testPath("bar.cc");
1549   // Build the index, the index has "Foo" references from foo.cc and "Bar"
1550   // references from bar.cc.
1551   FileSymbols FSymbols(IndexContents::All, true);
1552   FSymbols.update(FooPath, nullptr, buildRefSlab(FooCode, "Foo", FooPath),
1553                   nullptr, false);
1554   FSymbols.update(BarPath, nullptr, buildRefSlab(BarCode, "Bar", BarPath),
1555                   nullptr, false);
1556   auto Index = FSymbols.buildIndex(IndexType::Light);
1557 
1558   Annotations MainCode("class  [[Fo^o]] {};");
1559   auto MainFilePath = testPath("main.cc");
1560   llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemFS =
1561       new llvm::vfs::InMemoryFileSystem;
1562   InMemFS->addFile(FooPath, 0,
1563                    llvm::MemoryBuffer::getMemBuffer(FooDirtyBuffer.code()));
1564 
1565   // Run rename on Foo, there is a dirty buffer for foo.cc, rename should
1566   // respect the dirty buffer.
1567   TestTU TU = TestTU::withCode(MainCode.code());
1568   auto AST = TU.build();
1569   llvm::StringRef NewName = "newName";
1570   auto Results =
1571       rename({MainCode.point(), NewName, AST, MainFilePath,
1572               createOverlay(getVFSFromAST(AST), InMemFS), Index.get()});
1573   ASSERT_TRUE(bool(Results)) << Results.takeError();
1574   EXPECT_THAT(
1575       applyEdits(std::move(Results->GlobalChanges)),
1576       UnorderedElementsAre(
1577           Pair(Eq(FooPath), Eq(expectedResult(FooDirtyBuffer, NewName))),
1578           Pair(Eq(MainFilePath), Eq(expectedResult(MainCode, NewName)))));
1579 
1580   // Run rename on Bar, there is no dirty buffer for the affected file bar.cc,
1581   // so we should read file content from VFS.
1582   MainCode = Annotations("void [[Bar]]() { [[B^ar]](); }");
1583   TU = TestTU::withCode(MainCode.code());
1584   // Set a file "bar.cc" on disk.
1585   TU.AdditionalFiles["bar.cc"] = std::string(BarCode.code());
1586   AST = TU.build();
1587   Results = rename({MainCode.point(), NewName, AST, MainFilePath,
1588                     createOverlay(getVFSFromAST(AST), InMemFS), Index.get()});
1589   ASSERT_TRUE(bool(Results)) << Results.takeError();
1590   EXPECT_THAT(
1591       applyEdits(std::move(Results->GlobalChanges)),
1592       UnorderedElementsAre(
1593           Pair(Eq(BarPath), Eq(expectedResult(BarCode, NewName))),
1594           Pair(Eq(MainFilePath), Eq(expectedResult(MainCode, NewName)))));
1595 
1596   // Run rename on a pagination index which couldn't return all refs in one
1597   // request, we reject rename on this case.
1598   class PaginationIndex : public SymbolIndex {
1599     bool refs(const RefsRequest &Req,
1600               llvm::function_ref<void(const Ref &)> Callback) const override {
1601       return true; // has more references
1602     }
1603 
1604     bool containedRefs(const ContainedRefsRequest &Req,
1605                        llvm::function_ref<void(const ContainedRefsResult &)>
1606                            Callback) const override {
1607       return false;
1608     }
1609 
1610     bool fuzzyFind(
1611         const FuzzyFindRequest &Req,
1612         llvm::function_ref<void(const Symbol &)> Callback) const override {
1613       return false;
1614     }
1615     void
1616     lookup(const LookupRequest &Req,
1617            llvm::function_ref<void(const Symbol &)> Callback) const override {}
1618 
1619     void relations(const RelationsRequest &Req,
1620                    llvm::function_ref<void(const SymbolID &, const Symbol &)>
1621                        Callback) const override {}
1622 
1623     llvm::unique_function<IndexContents(llvm::StringRef) const>
1624     indexedFiles() const override {
1625       return [](llvm::StringRef) { return IndexContents::None; };
1626     }
1627 
1628     size_t estimateMemoryUsage() const override { return 0; }
1629   } PIndex;
1630   Results = rename({MainCode.point(), NewName, AST, MainFilePath,
1631                     createOverlay(getVFSFromAST(AST), InMemFS), &PIndex});
1632   EXPECT_FALSE(Results);
1633   EXPECT_THAT(llvm::toString(Results.takeError()),
1634               testing::HasSubstr("too many occurrences"));
1635 }
1636 
1637 TEST(CrossFileRenameTests, DeduplicateRefsFromIndex) {
1638   auto MainCode = Annotations("int [[^x]] = 2;");
1639   auto MainFilePath = testPath("main.cc");
1640   auto BarCode = Annotations("int [[x]];");
1641   auto BarPath = testPath("bar.cc");
1642   auto TU = TestTU::withCode(MainCode.code());
1643   // Set a file "bar.cc" on disk.
1644   TU.AdditionalFiles["bar.cc"] = std::string(BarCode.code());
1645   auto AST = TU.build();
1646   std::string BarPathURI = URI::create(BarPath).toString();
1647   Ref XRefInBarCC = refWithRange(BarCode.range(), BarPathURI);
1648   // The index will return duplicated refs, our code should be robost to handle
1649   // it.
1650   class DuplicatedXRefIndex : public SymbolIndex {
1651   public:
1652     DuplicatedXRefIndex(const Ref &ReturnedRef) : ReturnedRef(ReturnedRef) {}
1653     bool refs(const RefsRequest &Req,
1654               llvm::function_ref<void(const Ref &)> Callback) const override {
1655       // Return two duplicated refs.
1656       Callback(ReturnedRef);
1657       Callback(ReturnedRef);
1658       return false;
1659     }
1660 
1661     bool containedRefs(const ContainedRefsRequest &Req,
1662                        llvm::function_ref<void(const ContainedRefsResult &)>
1663                            Callback) const override {
1664       return false;
1665     }
1666 
1667     bool fuzzyFind(const FuzzyFindRequest &,
1668                    llvm::function_ref<void(const Symbol &)>) const override {
1669       return false;
1670     }
1671     void lookup(const LookupRequest &,
1672                 llvm::function_ref<void(const Symbol &)>) const override {}
1673 
1674     void relations(const RelationsRequest &,
1675                    llvm::function_ref<void(const SymbolID &, const Symbol &)>)
1676         const override {}
1677 
1678     llvm::unique_function<IndexContents(llvm::StringRef) const>
1679     indexedFiles() const override {
1680       return [](llvm::StringRef) { return IndexContents::None; };
1681     }
1682 
1683     size_t estimateMemoryUsage() const override { return 0; }
1684     Ref ReturnedRef;
1685   } DIndex(XRefInBarCC);
1686   llvm::StringRef NewName = "newName";
1687   auto Results = rename({MainCode.point(), NewName, AST, MainFilePath,
1688                          getVFSFromAST(AST), &DIndex});
1689   ASSERT_TRUE(bool(Results)) << Results.takeError();
1690   EXPECT_THAT(
1691       applyEdits(std::move(Results->GlobalChanges)),
1692       UnorderedElementsAre(
1693           Pair(Eq(BarPath), Eq(expectedResult(BarCode, NewName))),
1694           Pair(Eq(MainFilePath), Eq(expectedResult(MainCode, NewName)))));
1695 }
1696 
1697 TEST(CrossFileRenameTests, WithUpToDateIndex) {
1698   MockCompilationDatabase CDB;
1699   CDB.ExtraClangFlags = {"-xobjective-c++"};
1700   // rename is runnning on all "^" points in FooH, and "[[]]" ranges are the
1701   // expected rename occurrences.
1702   struct Case {
1703     llvm::StringRef FooH;
1704     llvm::StringRef FooCC;
1705   } Cases[] = {
1706       {
1707           // classes.
1708           R"cpp(
1709         class [[Fo^o]] {
1710           [[Foo]]();
1711           ~[[Foo]]();
1712         };
1713       )cpp",
1714           R"cpp(
1715         #include "foo.h"
1716         [[Foo]]::[[Foo]]() {}
1717         [[Foo]]::~[[Foo]]() {}
1718 
1719         void func() {
1720           [[Foo]] foo;
1721         }
1722       )cpp",
1723       },
1724       {
1725           // class templates.
1726           R"cpp(
1727         template <typename T>
1728         class [[Foo]] {};
1729         // FIXME: explicit template specializations are not supported due the
1730         // clangd index limitations.
1731         template <>
1732         class Foo<double> {};
1733       )cpp",
1734           R"cpp(
1735         #include "foo.h"
1736         void func() {
1737           [[F^oo]]<int> foo;
1738         }
1739       )cpp",
1740       },
1741       {
1742           // class methods.
1743           R"cpp(
1744         class Foo {
1745           void [[f^oo]]();
1746         };
1747       )cpp",
1748           R"cpp(
1749         #include "foo.h"
1750         void Foo::[[foo]]() {}
1751 
1752         void func(Foo* p) {
1753           p->[[foo]]();
1754         }
1755       )cpp",
1756       },
1757       {
1758           // virtual methods.
1759           R"cpp(
1760         class Base {
1761           virtual void [[foo]]();
1762         };
1763         class Derived1 : public Base {
1764           void [[f^oo]]() override;
1765         };
1766         class NotDerived {
1767           void foo() {};
1768         }
1769       )cpp",
1770           R"cpp(
1771         #include "foo.h"
1772         void Base::[[foo]]() {}
1773         void Derived1::[[foo]]() {}
1774 
1775         class Derived2 : public Derived1 {
1776           void [[foo]]() override {};
1777         };
1778 
1779         void func(Base* b, Derived1* d1,
1780                   Derived2* d2, NotDerived* nd) {
1781           b->[[foo]]();
1782           d1->[[foo]]();
1783           d2->[[foo]]();
1784           nd->foo();
1785         }
1786       )cpp",
1787       },
1788       {// virtual templated method
1789        R"cpp(
1790         template <typename> class Foo { virtual void [[m]](); };
1791         class Bar : Foo<int> { void [[^m]]() override; };
1792       )cpp",
1793        R"cpp(
1794           #include "foo.h"
1795 
1796           template<typename T> void Foo<T>::[[m]]() {}
1797           // FIXME: not renamed as the index doesn't see this as an override of
1798           // the canonical Foo<T>::m().
1799           // https://github.com/clangd/clangd/issues/1325
1800           class Baz : Foo<float> { void m() override; };
1801         )cpp"},
1802       {
1803           // rename on constructor and destructor.
1804           R"cpp(
1805         class [[Foo]] {
1806           [[^Foo]]();
1807           ~[[Foo^]]();
1808         };
1809       )cpp",
1810           R"cpp(
1811         #include "foo.h"
1812         [[Foo]]::[[Foo]]() {}
1813         [[Foo]]::~[[Foo]]() {}
1814 
1815         void func() {
1816           [[Foo]] foo;
1817         }
1818       )cpp",
1819       },
1820       {
1821           // functions.
1822           R"cpp(
1823         void [[f^oo]]();
1824       )cpp",
1825           R"cpp(
1826         #include "foo.h"
1827         void [[foo]]() {}
1828 
1829         void func() {
1830           [[foo]]();
1831         }
1832       )cpp",
1833       },
1834       {
1835           // typedefs.
1836           R"cpp(
1837       typedef int [[IN^T]];
1838       [[INT]] foo();
1839       )cpp",
1840           R"cpp(
1841         #include "foo.h"
1842         [[INT]] foo() {}
1843       )cpp",
1844       },
1845       {
1846           // usings.
1847           R"cpp(
1848       using [[I^NT]] = int;
1849       [[INT]] foo();
1850       )cpp",
1851           R"cpp(
1852         #include "foo.h"
1853         [[INT]] foo() {}
1854       )cpp",
1855       },
1856       {
1857           // variables.
1858           R"cpp(
1859         static const int [[VA^R]] = 123;
1860       )cpp",
1861           R"cpp(
1862         #include "foo.h"
1863         int s = [[VAR]];
1864       )cpp",
1865       },
1866       {
1867           // scope enums.
1868           R"cpp(
1869       enum class [[K^ind]] { ABC };
1870       )cpp",
1871           R"cpp(
1872         #include "foo.h"
1873         [[Kind]] ff() {
1874           return [[Kind]]::ABC;
1875         }
1876       )cpp",
1877       },
1878       {
1879           // enum constants.
1880           R"cpp(
1881       enum class Kind { [[A^BC]] };
1882       )cpp",
1883           R"cpp(
1884         #include "foo.h"
1885         Kind ff() {
1886           return Kind::[[ABC]];
1887         }
1888       )cpp",
1889       },
1890       {
1891           // Implicit references in macro expansions.
1892           R"cpp(
1893         class [[Fo^o]] {};
1894         #define FooFoo Foo
1895         #define FOO Foo
1896       )cpp",
1897           R"cpp(
1898         #include "foo.h"
1899         void bar() {
1900           [[Foo]] x;
1901           FOO y;
1902           FooFoo z;
1903         }
1904       )cpp",
1905       },
1906       {
1907           // Objective-C classes.
1908           R"cpp(
1909         @interface [[Fo^o]]
1910         @end
1911       )cpp",
1912           R"cpp(
1913         #include "foo.h"
1914         @implementation [[Foo]]
1915         @end
1916 
1917         void func([[Foo]] *f) {}
1918       )cpp",
1919       },
1920   };
1921 
1922   trace::TestTracer Tracer;
1923   for (const auto &T : Cases) {
1924     SCOPED_TRACE(T.FooH);
1925     Annotations FooH(T.FooH);
1926     Annotations FooCC(T.FooCC);
1927     std::string FooHPath = testPath("foo.h");
1928     std::string FooCCPath = testPath("foo.cc");
1929 
1930     MockFS FS;
1931     FS.Files[FooHPath] = std::string(FooH.code());
1932     FS.Files[FooCCPath] = std::string(FooCC.code());
1933 
1934     auto ServerOpts = ClangdServer::optsForTest();
1935     ServerOpts.BuildDynamicSymbolIndex = true;
1936     ClangdServer Server(CDB, FS, ServerOpts);
1937 
1938     // Add all files to clangd server to make sure the dynamic index has been
1939     // built.
1940     runAddDocument(Server, FooHPath, FooH.code());
1941     runAddDocument(Server, FooCCPath, FooCC.code());
1942 
1943     llvm::StringRef NewName = "NewName";
1944     for (const auto &RenamePos : FooH.points()) {
1945       EXPECT_THAT(Tracer.takeMetric("rename_files"), SizeIs(0));
1946       auto FileEditsList =
1947           llvm::cantFail(runRename(Server, FooHPath, RenamePos, NewName, {}));
1948       EXPECT_THAT(Tracer.takeMetric("rename_files"), ElementsAre(2));
1949       EXPECT_THAT(
1950           applyEdits(std::move(FileEditsList.GlobalChanges)),
1951           UnorderedElementsAre(
1952               Pair(Eq(FooHPath), Eq(expectedResult(T.FooH, NewName))),
1953               Pair(Eq(FooCCPath), Eq(expectedResult(T.FooCC, NewName)))));
1954     }
1955   }
1956 }
1957 
1958 TEST(CrossFileRenameTests, ObjC) {
1959   MockCompilationDatabase CDB;
1960   CDB.ExtraClangFlags = {"-xobjective-c"};
1961   // rename is runnning on all "^" points in FooH.
1962   struct Case {
1963     llvm::StringRef FooH;
1964     llvm::StringRef FooM;
1965     llvm::StringRef NewName;
1966     llvm::StringRef ExpectedFooH;
1967     llvm::StringRef ExpectedFooM;
1968   };
1969   Case Cases[] = {// --- Zero arg selector
1970                   {
1971                       // Input
1972                       R"cpp(
1973         @interface Foo
1974         - (int)performA^ction;
1975         @end
1976       )cpp",
1977                       R"cpp(
1978         @implementation Foo
1979         - (int)performAction {
1980           [self performAction];
1981         }
1982         @end
1983       )cpp",
1984                       // New name
1985                       "performNewAction",
1986                       // Expected
1987                       R"cpp(
1988         @interface Foo
1989         - (int)performNewAction;
1990         @end
1991       )cpp",
1992                       R"cpp(
1993         @implementation Foo
1994         - (int)performNewAction {
1995           [self performNewAction];
1996         }
1997         @end
1998       )cpp",
1999                   },
2000                   // --- Single arg selector
2001                   {
2002                       // Input
2003                       R"cpp(
2004         @interface Foo
2005         - (int)performA^ction:(int)action;
2006         @end
2007       )cpp",
2008                       R"cpp(
2009         @implementation Foo
2010         - (int)performAction:(int)action {
2011           [self performAction:action];
2012         }
2013         @end
2014       )cpp",
2015                       // New name
2016                       "performNewAction:",
2017                       // Expected
2018                       R"cpp(
2019         @interface Foo
2020         - (int)performNewAction:(int)action;
2021         @end
2022       )cpp",
2023                       R"cpp(
2024         @implementation Foo
2025         - (int)performNewAction:(int)action {
2026           [self performNewAction:action];
2027         }
2028         @end
2029       )cpp",
2030                   },
2031                   // --- Multi arg selector
2032                   {
2033                       // Input
2034                       R"cpp(
2035         @interface Foo
2036         - (int)performA^ction:(int)action with:(int)value;
2037         @end
2038       )cpp",
2039                       R"cpp(
2040         @implementation Foo
2041         - (int)performAction:(int)action with:(int)value {
2042           [self performAction:action with:value];
2043         }
2044         @end
2045       )cpp",
2046                       // New name
2047                       "performNewAction:by:",
2048                       // Expected
2049                       R"cpp(
2050         @interface Foo
2051         - (int)performNewAction:(int)action by:(int)value;
2052         @end
2053       )cpp",
2054                       R"cpp(
2055         @implementation Foo
2056         - (int)performNewAction:(int)action by:(int)value {
2057           [self performNewAction:action by:value];
2058         }
2059         @end
2060       )cpp",
2061                   }};
2062 
2063   trace::TestTracer Tracer;
2064   for (const auto &T : Cases) {
2065     SCOPED_TRACE(T.FooH);
2066     Annotations FooH(T.FooH);
2067     Annotations FooM(T.FooM);
2068     std::string FooHPath = testPath("foo.h");
2069     std::string FooMPath = testPath("foo.m");
2070 
2071     MockFS FS;
2072     FS.Files[FooHPath] = std::string(FooH.code());
2073     FS.Files[FooMPath] = std::string(FooM.code());
2074 
2075     auto ServerOpts = ClangdServer::optsForTest();
2076     ServerOpts.BuildDynamicSymbolIndex = true;
2077     ClangdServer Server(CDB, FS, ServerOpts);
2078 
2079     // Add all files to clangd server to make sure the dynamic index has been
2080     // built.
2081     runAddDocument(Server, FooHPath, FooH.code());
2082     runAddDocument(Server, FooMPath, FooM.code());
2083 
2084     for (const auto &RenamePos : FooH.points()) {
2085       EXPECT_THAT(Tracer.takeMetric("rename_files"), SizeIs(0));
2086       auto FileEditsList =
2087           llvm::cantFail(runRename(Server, FooHPath, RenamePos, T.NewName, {}));
2088       EXPECT_THAT(Tracer.takeMetric("rename_files"), ElementsAre(2));
2089       EXPECT_THAT(applyEdits(std::move(FileEditsList.GlobalChanges)),
2090                   UnorderedElementsAre(Pair(Eq(FooHPath), Eq(T.ExpectedFooH)),
2091                                        Pair(Eq(FooMPath), Eq(T.ExpectedFooM))));
2092     }
2093   }
2094 }
2095 
2096 TEST(CrossFileRenameTests, CrossFileOnLocalSymbol) {
2097   // cross-file rename should work for function-local symbols, even there is no
2098   // index provided.
2099   Annotations Code("void f(int [[abc]]) { [[a^bc]] = 3; }");
2100   auto TU = TestTU::withCode(Code.code());
2101   auto Path = testPath(TU.Filename);
2102   auto AST = TU.build();
2103   llvm::StringRef NewName = "newName";
2104   auto Results = rename({Code.point(), NewName, AST, Path});
2105   ASSERT_TRUE(bool(Results)) << Results.takeError();
2106   EXPECT_THAT(
2107       applyEdits(std::move(Results->GlobalChanges)),
2108       UnorderedElementsAre(Pair(Eq(Path), Eq(expectedResult(Code, NewName)))));
2109 }
2110 
2111 TEST(CrossFileRenameTests, BuildRenameEdits) {
2112   Annotations Code("[[��]]");
2113   auto LSPRange = Code.range();
2114   llvm::StringRef FilePath = "/test/TestTU.cpp";
2115   llvm::SmallVector<llvm::StringRef, 2> NewNames = {"abc"};
2116   auto Edit = buildRenameEdit(FilePath, Code.code(), {LSPRange}, NewNames);
2117   ASSERT_TRUE(bool(Edit)) << Edit.takeError();
2118   ASSERT_EQ(1UL, Edit->Replacements.size());
2119   EXPECT_EQ(FilePath, Edit->Replacements.begin()->getFilePath());
2120   EXPECT_EQ(4UL, Edit->Replacements.begin()->getLength());
2121 
2122   // Test invalid range.
2123   LSPRange.end = {10, 0}; // out of range
2124   Edit = buildRenameEdit(FilePath, Code.code(), {LSPRange}, NewNames);
2125   EXPECT_FALSE(Edit);
2126   EXPECT_THAT(llvm::toString(Edit.takeError()),
2127               testing::HasSubstr("fail to convert"));
2128 
2129   // Normal ascii characters.
2130   Annotations T(R"cpp(
2131     [[range]]
2132               [[range]]
2133       [[range]]
2134   )cpp");
2135   Edit =
2136       buildRenameEdit(FilePath, T.code(), symbolRanges(T.ranges()), NewNames);
2137   ASSERT_TRUE(bool(Edit)) << Edit.takeError();
2138   EXPECT_EQ(applyEdits(FileEdits{{T.code(), std::move(*Edit)}}).front().second,
2139             expectedResult(T, NewNames[0]));
2140 }
2141 
2142 TEST(CrossFileRenameTests, adjustRenameRanges) {
2143   // Ranges in IndexedCode indicate the indexed occurrences;
2144   // ranges in DraftCode indicate the expected mapped result, empty indicates
2145   // we expect no matched result found.
2146   struct {
2147     llvm::StringRef IndexedCode;
2148     llvm::StringRef DraftCode;
2149   } Tests[] = {
2150     {
2151       // both line and column are changed, not a near miss.
2152       R"cpp(
2153         int [[x]] = 0;
2154       )cpp",
2155       R"cpp(
2156         // insert a line.
2157         double x = 0;
2158       )cpp",
2159     },
2160     {
2161       // subset.
2162       R"cpp(
2163         int [[x]] = 0;
2164       )cpp",
2165       R"cpp(
2166         int [[x]] = 0;
2167         {int x = 0; }
2168       )cpp",
2169     },
2170     {
2171       // shift columns.
2172       R"cpp(int [[x]] = 0; void foo(int x);)cpp",
2173       R"cpp(double [[x]] = 0; void foo(double x);)cpp",
2174     },
2175     {
2176       // shift lines.
2177       R"cpp(
2178         int [[x]] = 0;
2179         void foo(int x);
2180       )cpp",
2181       R"cpp(
2182         // insert a line.
2183         int [[x]] = 0;
2184         void foo(int x);
2185       )cpp",
2186     },
2187   };
2188   LangOptions LangOpts;
2189   LangOpts.CPlusPlus = true;
2190   for (const auto &T : Tests) {
2191     SCOPED_TRACE(T.DraftCode);
2192     Annotations Draft(T.DraftCode);
2193     auto ActualRanges = adjustRenameRanges(Draft.code(), "x",
2194                                            Annotations(T.IndexedCode).ranges(),
2195                                            LangOpts, std::nullopt);
2196     if (!ActualRanges)
2197        EXPECT_THAT(Draft.ranges(), testing::IsEmpty());
2198     else
2199       EXPECT_THAT(Draft.ranges(),
2200                   testing::UnorderedElementsAreArray(*ActualRanges));
2201   }
2202 }
2203 
2204 TEST(RangePatchingHeuristic, GetMappedRanges) {
2205   // ^ in LexedCode marks the ranges we expect to be mapped; no ^ indicates
2206   // there are no mapped ranges.
2207   struct {
2208     llvm::StringRef IndexedCode;
2209     llvm::StringRef LexedCode;
2210   } Tests[] = {
2211     {
2212       // no lexed ranges.
2213       "[[]]",
2214       "",
2215     },
2216     {
2217       // both line and column are changed, not a near miss.
2218       R"([[]])",
2219       R"(
2220         [[]]
2221       )",
2222     },
2223     {
2224       // subset.
2225       "[[]]",
2226       "^[[]]  [[]]"
2227     },
2228     {
2229       // shift columns.
2230       "[[]]   [[]]",
2231       "  ^[[]]   ^[[]]  [[]]"
2232     },
2233     {
2234       R"(
2235         [[]]
2236 
2237         [[]] [[]]
2238       )",
2239       R"(
2240         // insert a line
2241         ^[[]]
2242 
2243         ^[[]] ^[[]]
2244       )",
2245     },
2246     {
2247       R"(
2248         [[]]
2249 
2250         [[]] [[]]
2251       )",
2252       R"(
2253         // insert a line
2254         ^[[]]
2255           ^[[]]  ^[[]] // column is shifted.
2256       )",
2257     },
2258     {
2259       R"(
2260         [[]]
2261 
2262         [[]] [[]]
2263       )",
2264       R"(
2265         // insert a line
2266         [[]]
2267 
2268           [[]]  [[]] // not mapped (both line and column are changed).
2269       )",
2270     },
2271     {
2272       R"(
2273         [[]]
2274                 [[]]
2275 
2276                    [[]]
2277                   [[]]
2278 
2279         }
2280       )",
2281       R"(
2282         // insert a new line
2283         ^[[]]
2284                 ^[[]]
2285              [[]] // additional range
2286                    ^[[]]
2287                   ^[[]]
2288             [[]] // additional range
2289       )",
2290     },
2291     {
2292       // non-distinct result (two best results), not a near miss
2293       R"(
2294         [[]]
2295             [[]]
2296             [[]]
2297       )",
2298       R"(
2299         [[]]
2300         [[]]
2301             [[]]
2302             [[]]
2303       )",
2304     }
2305   };
2306   for (const auto &T : Tests) {
2307     SCOPED_TRACE(T.IndexedCode);
2308     auto Lexed = Annotations(T.LexedCode);
2309     auto LexedRanges = symbolRanges(Lexed.ranges());
2310     std::vector<SymbolRange> ExpectedMatches;
2311     for (auto P : Lexed.points()) {
2312       auto Match = llvm::find_if(LexedRanges, [&P](const SymbolRange &R) {
2313         return R.range().start == P;
2314       });
2315       ASSERT_NE(Match, LexedRanges.end());
2316       ExpectedMatches.push_back(*Match);
2317     }
2318 
2319     auto Mapped =
2320         getMappedRanges(Annotations(T.IndexedCode).ranges(), LexedRanges);
2321     if (!Mapped)
2322       EXPECT_THAT(ExpectedMatches, IsEmpty());
2323     else
2324       EXPECT_THAT(ExpectedMatches, UnorderedElementsAreArray(*Mapped));
2325   }
2326 }
2327 
2328 TEST(CrossFileRenameTests, adjustmentCost) {
2329   struct {
2330     llvm::StringRef RangeCode;
2331     size_t ExpectedCost;
2332   } Tests[] = {
2333     {
2334       R"(
2335         $idx[[]]$lex[[]] // diff: 0
2336       )",
2337       0,
2338     },
2339     {
2340       R"(
2341         $idx[[]]
2342         $lex[[]] // line diff: +1
2343                        $idx[[]]
2344                        $lex[[]] // line diff: +1
2345         $idx[[]]
2346         $lex[[]] // line diff: +1
2347 
2348           $idx[[]]
2349 
2350           $lex[[]] // line diff: +2
2351       )",
2352       1 + 1
2353     },
2354     {
2355        R"(
2356         $idx[[]]
2357         $lex[[]] // line diff: +1
2358                        $idx[[]]
2359 
2360                        $lex[[]] // line diff: +2
2361         $idx[[]]
2362 
2363 
2364         $lex[[]] // line diff: +3
2365       )",
2366       1 + 1 + 1
2367     },
2368     {
2369        R"(
2370         $idx[[]]
2371 
2372 
2373         $lex[[]] // line diff: +3
2374                        $idx[[]]
2375 
2376                        $lex[[]] // line diff: +2
2377         $idx[[]]
2378         $lex[[]] // line diff: +1
2379       )",
2380       3 + 1 + 1
2381     },
2382     {
2383       R"(
2384         $idx[[]]
2385         $lex[[]] // line diff: +1
2386                        $lex[[]] // line diff: -2
2387 
2388                        $idx[[]]
2389         $idx[[]]
2390 
2391 
2392         $lex[[]] // line diff: +3
2393       )",
2394       1 + 3 + 5
2395     },
2396     {
2397       R"(
2398                        $idx[[]] $lex[[]] // column diff: +1
2399         $idx[[]]$lex[[]] // diff: 0
2400       )",
2401       1
2402     },
2403     {
2404       R"(
2405         $idx[[]]
2406         $lex[[]] // diff: +1
2407                        $idx[[]] $lex[[]] // column diff: +1
2408         $idx[[]]$lex[[]] // diff: 0
2409       )",
2410       1 + 1 + 1
2411     },
2412     {
2413       R"(
2414         $idx[[]] $lex[[]] // column diff: +1
2415       )",
2416       1
2417     },
2418     {
2419       R"(
2420         // column diffs: +1, +2, +3
2421         $idx[[]] $lex[[]] $idx[[]]  $lex[[]] $idx[[]]   $lex[[]]
2422       )",
2423       1 + 1 + 1,
2424     },
2425   };
2426   for (const auto &T : Tests) {
2427     SCOPED_TRACE(T.RangeCode);
2428     Annotations C(T.RangeCode);
2429     std::vector<size_t> MappedIndex;
2430     for (size_t I = 0; I < C.ranges("lex").size(); ++I)
2431       MappedIndex.push_back(I);
2432     EXPECT_EQ(renameRangeAdjustmentCost(
2433                   C.ranges("idx"), symbolRanges(C.ranges("lex")), MappedIndex),
2434               T.ExpectedCost);
2435   }
2436 }
2437 
2438 } // namespace
2439 } // namespace clangd
2440 } // namespace clang
2441