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 // Convert a Range to a Ref.
refWithRange(const clangd::Range & Range,const std::string & URI)37 Ref refWithRange(const clangd::Range &Range, const std::string &URI) {
38   Ref Result;
39   Result.Kind = RefKind::Reference | RefKind::Spelled;
40   Result.Location.Start.setLine(Range.start.line);
41   Result.Location.Start.setColumn(Range.start.character);
42   Result.Location.End.setLine(Range.end.line);
43   Result.Location.End.setColumn(Range.end.character);
44   Result.Location.FileURI = URI.c_str();
45   return Result;
46 }
47 
48 // Build a RefSlab from all marked ranges in the annotation. The ranges are
49 // assumed to associate with the given SymbolName.
buildRefSlab(const Annotations & Code,llvm::StringRef SymbolName,llvm::StringRef Path)50 std::unique_ptr<RefSlab> buildRefSlab(const Annotations &Code,
51                                       llvm::StringRef SymbolName,
52                                       llvm::StringRef Path) {
53   RefSlab::Builder Builder;
54   TestTU TU;
55   TU.HeaderCode = std::string(Code.code());
56   auto Symbols = TU.headerSymbols();
57   const auto &SymbolID = findSymbol(Symbols, SymbolName).ID;
58   std::string PathURI = URI::create(Path).toString();
59   for (const auto &Range : Code.ranges())
60     Builder.insert(SymbolID, refWithRange(Range, PathURI));
61 
62   return std::make_unique<RefSlab>(std::move(Builder).build());
63 }
64 
65 std::vector<
66     std::pair</*FilePath*/ std::string, /*CodeAfterRename*/ std::string>>
applyEdits(FileEdits FE)67 applyEdits(FileEdits FE) {
68   std::vector<std::pair<std::string, std::string>> Results;
69   for (auto &It : FE)
70     Results.emplace_back(
71         It.first().str(),
72         llvm::cantFail(tooling::applyAllReplacements(
73             It.getValue().InitialCode, It.getValue().Replacements)));
74   return Results;
75 }
76 
77 // Generates an expected rename result by replacing all ranges in the given
78 // annotation with the NewName.
expectedResult(Annotations Test,llvm::StringRef NewName)79 std::string expectedResult(Annotations Test, llvm::StringRef NewName) {
80   std::string Result;
81   unsigned NextChar = 0;
82   llvm::StringRef Code = Test.code();
83   for (const auto &R : Test.llvm::Annotations::ranges()) {
84     assert(R.Begin <= R.End && NextChar <= R.Begin);
85     Result += Code.substr(NextChar, R.Begin - NextChar);
86     Result += NewName;
87     NextChar = R.End;
88   }
89   Result += Code.substr(NextChar);
90   return Result;
91 }
92 
TEST(RenameTest,WithinFileRename)93 TEST(RenameTest, WithinFileRename) {
94   // For each "^" this test moves cursor to its location and applies renaming
95   // while checking that all identifiers in [[]] ranges are also renamed.
96   llvm::StringRef Tests[] = {
97       // Function.
98       R"cpp(
99         void [[foo^]]() {
100           [[fo^o]]();
101         }
102       )cpp",
103 
104       // Type.
105       R"cpp(
106         struct [[foo^]] {};
107         [[foo]] test() {
108            [[f^oo]] x;
109            return x;
110         }
111       )cpp",
112 
113       // Local variable.
114       R"cpp(
115         void bar() {
116           if (auto [[^foo]] = 5) {
117             [[foo]] = 3;
118           }
119         }
120       )cpp",
121 
122       // Class, its constructor and destructor.
123       R"cpp(
124         class [[F^oo]] {
125           [[F^oo]]();
126           ~[[F^oo]]();
127           [[F^oo]] *foo(int x);
128 
129           [[F^oo]] *Ptr;
130         };
131         [[F^oo]]::[[Fo^o]]() {}
132         [[F^oo]]::~[[Fo^o]]() {}
133         [[F^oo]] *[[F^oo]]::foo(int x) { return Ptr; }
134       )cpp",
135 
136       // Template class, its constructor and destructor.
137       R"cpp(
138         template <typename T>
139         class [[F^oo]] {
140           [[F^oo]]();
141           ~[[F^oo]]();
142           void f([[F^oo]] x);
143         };
144 
145         template<typename T>
146         [[F^oo]]<T>::[[Fo^o]]() {}
147 
148         template<typename T>
149         [[F^oo]]<T>::~[[Fo^o]]() {}
150       )cpp",
151 
152       // Template class constructor.
153       R"cpp(
154         class [[F^oo]] {
155           template<typename T>
156           [[Fo^o]]();
157 
158           template<typename T>
159           [[F^oo]](T t);
160         };
161 
162         template<typename T>
163         [[F^oo]]::[[Fo^o]]() {}
164       )cpp",
165 
166       // Class in template argument.
167       R"cpp(
168         class [[F^oo]] {};
169         template <typename T> void func();
170         template <typename T> class Baz {};
171         int main() {
172           func<[[F^oo]]>();
173           Baz<[[F^oo]]> obj;
174           return 0;
175         }
176       )cpp",
177 
178       // Forward class declaration without definition.
179       R"cpp(
180         class [[F^oo]];
181         [[F^oo]] *f();
182       )cpp",
183 
184       // Member function.
185       R"cpp(
186         struct X {
187           void [[F^oo]]() {}
188           void Baz() { [[F^oo]](); }
189         };
190       )cpp",
191 
192       // Class methods overrides.
193       R"cpp(
194         struct A {
195          virtual void [[f^oo]]() {}
196         };
197         struct B : A {
198           void [[f^oo]]() override {}
199         };
200         struct C : B {
201           void [[f^oo]]() override {}
202         };
203 
204         void func() {
205           A().[[f^oo]]();
206           B().[[f^oo]]();
207           C().[[f^oo]]();
208         }
209       )cpp",
210 
211       // Templated method instantiation.
212       R"cpp(
213         template<typename T>
214         class Foo {
215         public:
216           static T [[f^oo]]() {}
217         };
218 
219         void bar() {
220           Foo<int>::[[f^oo]]();
221         }
222       )cpp",
223       R"cpp(
224         template<typename T>
225         class Foo {
226         public:
227           T [[f^oo]]() {}
228         };
229 
230         void bar() {
231           Foo<int>().[[f^oo]]();
232         }
233       )cpp",
234 
235       // Template class (partial) specializations.
236       R"cpp(
237         template <typename T>
238         class [[F^oo]] {};
239 
240         template<>
241         class [[F^oo]]<bool> {};
242         template <typename T>
243         class [[F^oo]]<T*> {};
244 
245         void test() {
246           [[F^oo]]<int> x;
247           [[F^oo]]<bool> y;
248           [[F^oo]]<int*> z;
249         }
250       )cpp",
251 
252       // Incomplete class specializations
253       R"cpp(
254         template <typename T>
255         class [[Fo^o]] {};
256         void func([[F^oo]]<int>);
257       )cpp",
258 
259       // Template class instantiations.
260       R"cpp(
261         template <typename T>
262         class [[F^oo]] {
263         public:
264           T foo(T arg, T& ref, T* ptr) {
265             T value;
266             int number = 42;
267             value = (T)number;
268             value = static_cast<T>(number);
269             return value;
270           }
271           static void foo(T value) {}
272           T member;
273         };
274 
275         template <typename T>
276         void func() {
277           [[F^oo]]<T> obj;
278           obj.member = T();
279           [[Foo]]<T>::foo();
280         }
281 
282         void test() {
283           [[F^oo]]<int> i;
284           i.member = 0;
285           [[F^oo]]<int>::foo(0);
286 
287           [[F^oo]]<bool> b;
288           b.member = false;
289           [[F^oo]]<bool>::foo(false);
290         }
291       )cpp",
292 
293       // Template class methods.
294       R"cpp(
295         template <typename T>
296         class A {
297         public:
298           void [[f^oo]]() {}
299         };
300 
301         void func() {
302           A<int>().[[f^oo]]();
303           A<double>().[[f^oo]]();
304           A<float>().[[f^oo]]();
305         }
306       )cpp",
307 
308       // Templated class specialization.
309       R"cpp(
310         template<typename T, typename U=bool>
311         class [[Foo^]];
312 
313         template<typename T, typename U>
314         class [[Foo^]] {};
315 
316         template<typename T=int, typename U>
317         class [[Foo^]];
318       )cpp",
319       R"cpp(
320         template<typename T=float, typename U=int>
321         class [[Foo^]];
322 
323         template<typename T, typename U>
324         class [[Foo^]] {};
325       )cpp",
326 
327       // Function template specialization.
328       R"cpp(
329         template<typename T=int, typename U=bool>
330         U [[foo^]]();
331 
332         template<typename T, typename U>
333         U [[foo^]]() {};
334       )cpp",
335       R"cpp(
336         template<typename T, typename U>
337         U [[foo^]]() {};
338 
339         template<typename T=int, typename U=bool>
340         U [[foo^]]();
341       )cpp",
342       R"cpp(
343         template<typename T=int, typename U=bool>
344         U [[foo^]]();
345 
346         template<typename T, typename U>
347         U [[foo^]]();
348       )cpp",
349       R"cpp(
350         template <typename T>
351         void [[f^oo]](T t);
352 
353         template <>
354         void [[f^oo]](int a);
355 
356         void test() {
357           [[f^oo]]<double>(1);
358         }
359       )cpp",
360 
361       // Variable template.
362       R"cpp(
363         template <typename T, int U>
364         bool [[F^oo]] = true;
365 
366         // Explicit template specialization
367         template <>
368         bool [[F^oo]]<int, 0> = false;
369 
370         // Partial template specialization
371         template <typename T>
372         bool [[F^oo]]<T, 1> = false;
373 
374         void foo() {
375           // Ref to the explicit template specialization
376           [[F^oo]]<int, 0>;
377           // Ref to the primary template.
378           [[F^oo]]<double, 2>;
379         }
380       )cpp",
381 
382       // Complicated class type.
383       R"cpp(
384          // Forward declaration.
385         class [[Fo^o]];
386         class Baz {
387           virtual int getValue() const = 0;
388         };
389 
390         class [[F^oo]] : public Baz  {
391         public:
392           [[F^oo]](int value = 0) : x(value) {}
393 
394           [[F^oo]] &operator++(int);
395 
396           bool operator<([[Foo]] const &rhs);
397           int getValue() const;
398         private:
399           int x;
400         };
401 
402         void func() {
403           [[F^oo]] *Pointer = 0;
404           [[F^oo]] Variable = [[Foo]](10);
405           for ([[F^oo]] it; it < Variable; it++);
406           const [[F^oo]] *C = new [[Foo]]();
407           const_cast<[[F^oo]] *>(C)->getValue();
408           [[F^oo]] foo;
409           const Baz &BazReference = foo;
410           const Baz *BazPointer = &foo;
411           reinterpret_cast<const [[^Foo]] *>(BazPointer)->getValue();
412           static_cast<const [[^Foo]] &>(BazReference).getValue();
413           static_cast<const [[^Foo]] *>(BazPointer)->getValue();
414         }
415       )cpp",
416 
417       // Static class member.
418       R"cpp(
419         struct Foo {
420           static Foo *[[Static^Member]];
421         };
422 
423         Foo* Foo::[[Static^Member]] = nullptr;
424 
425         void foo() {
426           Foo* Pointer = Foo::[[Static^Member]];
427         }
428       )cpp",
429 
430       // Reference in lambda parameters.
431       R"cpp(
432         template <class T>
433         class function;
434         template <class R, class... ArgTypes>
435         class function<R(ArgTypes...)> {
436         public:
437           template <typename Functor>
438           function(Functor f) {}
439 
440           function() {}
441 
442           R operator()(ArgTypes...) const {}
443         };
444 
445         namespace ns {
446         class [[Old]] {};
447         void f() {
448           function<void([[Old]])> func;
449         }
450         }  // namespace ns
451       )cpp",
452 
453       // Destructor explicit call.
454       R"cpp(
455         class [[F^oo]] {
456         public:
457           ~[[^Foo]]();
458         };
459 
460         [[Foo^]]::~[[^Foo]]() {}
461 
462         int main() {
463           [[Fo^o]] f;
464           f.~/*something*/[[^Foo]]();
465           f.~[[^Foo]]();
466         }
467       )cpp",
468 
469       // Derived destructor explicit call.
470       R"cpp(
471         class [[Bas^e]] {};
472         class Derived : public [[Bas^e]] {};
473 
474         int main() {
475           [[Bas^e]] *foo = new Derived();
476           foo->[[^Base]]::~[[^Base]]();
477         }
478       )cpp",
479 
480       // CXXConstructor initializer list.
481       R"cpp(
482         class Baz {};
483         class Qux {
484           Baz [[F^oo]];
485         public:
486           Qux();
487         };
488         Qux::Qux() : [[F^oo]]() {}
489       )cpp",
490 
491       // DeclRefExpr.
492       R"cpp(
493         class C {
494         public:
495           static int [[F^oo]];
496         };
497 
498         int foo(int x);
499         #define MACRO(a) foo(a)
500 
501         void func() {
502           C::[[F^oo]] = 1;
503           MACRO(C::[[Foo]]);
504           int y = C::[[F^oo]];
505         }
506       )cpp",
507 
508       // Macros.
509       R"cpp(
510         // no rename inside macro body.
511         #define M1 foo
512         #define M2(x) x
513         int [[fo^o]]();
514         void boo(int);
515 
516         void qoo() {
517           [[f^oo]]();
518           boo([[f^oo]]());
519           M1();
520           boo(M1());
521           M2([[f^oo]]());
522           M2(M1()); // foo is inside the nested macro body.
523         }
524       )cpp",
525 
526       // MemberExpr in macros
527       R"cpp(
528         class Baz {
529         public:
530           int [[F^oo]];
531         };
532         int qux(int x);
533         #define MACRO(a) qux(a)
534 
535         int main() {
536           Baz baz;
537           baz.[[F^oo]] = 1;
538           MACRO(baz.[[F^oo]]);
539           int y = baz.[[F^oo]];
540         }
541       )cpp",
542 
543       // Fields in classes & partial and full specialiations.
544       R"cpp(
545         template<typename T>
546         struct Foo {
547           T [[Vari^able]] = 42;
548         };
549 
550         void foo() {
551           Foo<int> f;
552           f.[[Varia^ble]] = 9000;
553         }
554       )cpp",
555       R"cpp(
556         template<typename T, typename U>
557         struct Foo {
558           T Variable[42];
559           U Another;
560 
561           void bar() {}
562         };
563 
564         template<typename T>
565         struct Foo<T, bool> {
566           T [[Var^iable]];
567           void bar() { ++[[Var^iable]]; }
568         };
569 
570         void foo() {
571           Foo<unsigned, bool> f;
572           f.[[Var^iable]] = 9000;
573         }
574       )cpp",
575       R"cpp(
576         template<typename T, typename U>
577         struct Foo {
578           T Variable[42];
579           U Another;
580 
581           void bar() {}
582         };
583 
584         template<typename T>
585         struct Foo<T, bool> {
586           T Variable;
587           void bar() { ++Variable; }
588         };
589 
590         template<>
591         struct Foo<unsigned, bool> {
592           unsigned [[Var^iable]];
593           void bar() { ++[[Var^iable]]; }
594         };
595 
596         void foo() {
597           Foo<unsigned, bool> f;
598           f.[[Var^iable]] = 9000;
599         }
600       )cpp",
601       // Static fields.
602       R"cpp(
603         struct Foo {
604           static int [[Var^iable]];
605         };
606 
607         int Foo::[[Var^iable]] = 42;
608 
609         void foo() {
610           int LocalInt = Foo::[[Var^iable]];
611         }
612       )cpp",
613       R"cpp(
614         template<typename T>
615         struct Foo {
616           static T [[Var^iable]];
617         };
618 
619         template <>
620         int Foo<int>::[[Var^iable]] = 42;
621 
622         template <>
623         bool Foo<bool>::[[Var^iable]] = true;
624 
625         void foo() {
626           int LocalInt = Foo<int>::[[Var^iable]];
627           bool LocalBool = Foo<bool>::[[Var^iable]];
628         }
629       )cpp",
630 
631       // Template parameters.
632       R"cpp(
633         template <typename [[^T]]>
634         class Foo {
635           [[T^]] foo([[T^]] arg, [[T^]]& ref, [[^T]]* ptr) {
636             [[T]] value;
637             int number = 42;
638             value = ([[T^]])number;
639             value = static_cast<[[^T]]>(number);
640             return value;
641           }
642           static void foo([[T^]] value) {}
643           [[T^]] member;
644         };
645       )cpp",
646 
647       // Typedef.
648       R"cpp(
649         namespace ns {
650         class basic_string {};
651         typedef basic_string [[s^tring]];
652         } // namespace ns
653 
654         ns::[[s^tring]] foo();
655       )cpp",
656 
657       // Variable.
658       R"cpp(
659         namespace A {
660         int [[F^oo]];
661         }
662         int Foo;
663         int Qux = Foo;
664         int Baz = A::[[^Foo]];
665         void fun() {
666           struct {
667             int Foo;
668           } b = {100};
669           int Foo = 100;
670           Baz = Foo;
671           {
672             extern int Foo;
673             Baz = Foo;
674             Foo = A::[[F^oo]] + Baz;
675             A::[[Fo^o]] = b.Foo;
676           }
677           Foo = b.Foo;
678         }
679       )cpp",
680 
681       // Namespace alias.
682       R"cpp(
683         namespace a { namespace b { void foo(); } }
684         namespace [[^x]] = a::b;
685         void bar() {
686           [[x^]]::foo();
687         }
688       )cpp",
689 
690       // Enum.
691       R"cpp(
692         enum [[C^olor]] { Red, Green, Blue };
693         void foo() {
694           [[C^olor]] c;
695           c = [[C^olor]]::Blue;
696         }
697       )cpp",
698 
699       // Scoped enum.
700       R"cpp(
701         enum class [[K^ind]] { ABC };
702         void ff() {
703           [[K^ind]] s;
704           s = [[K^ind]]::ABC;
705         }
706       )cpp",
707 
708       // Template class in template argument list.
709       R"cpp(
710         template<typename T>
711         class [[Fo^o]] {};
712         template <template<typename> class Z> struct Bar { };
713         template <> struct Bar<[[F^oo]]> {};
714       )cpp",
715 
716       // Designated initializer.
717       R"cpp(
718         struct Bar {
719           int [[Fo^o]];
720         };
721         Bar bar { .[[^Foo]] = 42 };
722       )cpp",
723 
724       // Nested designated initializer.
725       R"cpp(
726         struct Baz {
727           int Field;
728         };
729         struct Bar {
730           Baz [[Fo^o]];
731         };
732         // FIXME:    v selecting here results in renaming Field.
733         Bar bar { .[[Foo]].Field = 42 };
734       )cpp",
735       R"cpp(
736         struct Baz {
737           int [[Fiel^d]];
738         };
739         struct Bar {
740           Baz Foo;
741         };
742         Bar bar { .Foo.[[^Field]] = 42 };
743       )cpp",
744 
745       // Templated alias.
746       R"cpp(
747         template <typename T>
748         class X { T t; };
749 
750         template <typename T>
751         using [[Fo^o]] = X<T>;
752 
753         void bar() {
754           [[Fo^o]]<int> Bar;
755         }
756       )cpp",
757 
758       // Alias.
759       R"cpp(
760         class X {};
761         using [[F^oo]] = X;
762 
763         void bar() {
764           [[Fo^o]] Bar;
765         }
766       )cpp",
767 
768       // Alias within a namespace.
769       R"cpp(
770         namespace x { class X {}; }
771         namespace ns {
772         using [[Fo^o]] = x::X;
773         }
774 
775         void bar() {
776           ns::[[Fo^o]] Bar;
777         }
778       )cpp",
779 
780       // Alias within macros.
781       R"cpp(
782         namespace x { class Old {}; }
783         namespace ns {
784         #define REF(alias) alias alias_var;
785 
786         #define ALIAS(old) \
787           using old##Alias = x::old; \
788           REF(old##Alias);
789 
790         ALIAS(Old);
791 
792         [[Old^Alias]] old_alias;
793         }
794 
795         void bar() {
796           ns::[[Old^Alias]] Bar;
797         }
798       )cpp",
799 
800       // User defined conversion.
801       R"cpp(
802         class [[F^oo]] {
803         public:
804           [[F^oo]]() {}
805         };
806 
807         class Baz {
808         public:
809           operator [[F^oo]]() {
810             return [[F^oo]]();
811           }
812         };
813 
814         int main() {
815           Baz boo;
816           [[F^oo]] foo = static_cast<[[F^oo]]>(boo);
817         }
818       )cpp",
819 
820       // ObjC, should not crash.
821       R"cpp(
822         @interface ObjC {
823           char [[da^ta]];
824         } @end
825       )cpp",
826   };
827   llvm::StringRef NewName = "NewName";
828   for (llvm::StringRef T : Tests) {
829     SCOPED_TRACE(T);
830     Annotations Code(T);
831     auto TU = TestTU::withCode(Code.code());
832     TU.ExtraArgs.push_back("-fno-delayed-template-parsing");
833     TU.ExtraArgs.push_back("-xobjective-c++");
834     auto AST = TU.build();
835     for (const auto &RenamePos : Code.points()) {
836       auto RenameResult =
837           rename({RenamePos, NewName, AST, testPath(TU.Filename)});
838       ASSERT_TRUE(bool(RenameResult)) << RenameResult.takeError();
839       ASSERT_EQ(1u, RenameResult->GlobalChanges.size());
840       EXPECT_EQ(
841           applyEdits(std::move(RenameResult->GlobalChanges)).front().second,
842           expectedResult(Code, NewName));
843     }
844   }
845 }
846 
TEST(RenameTest,Renameable)847 TEST(RenameTest, Renameable) {
848   struct Case {
849     const char *Code;
850     const char* ErrorMessage; // null if no error
851     bool IsHeaderFile;
852     const SymbolIndex *Index;
853     llvm::StringRef NewName = "DummyName";
854   };
855   TestTU OtherFile = TestTU::withCode("Outside s; auto ss = &foo;");
856   const char *CommonHeader = R"cpp(
857     class Outside {};
858     void foo();
859   )cpp";
860   OtherFile.HeaderCode = CommonHeader;
861   OtherFile.Filename = "other.cc";
862   // The index has a "Outside" reference and a "foo" reference.
863   auto OtherFileIndex = OtherFile.index();
864   const SymbolIndex *Index = OtherFileIndex.get();
865 
866   const bool HeaderFile = true;
867   Case Cases[] = {
868       {R"cpp(// allow -- function-local
869         void f(int [[Lo^cal]]) {
870           [[Local]] = 2;
871         }
872       )cpp",
873        nullptr, HeaderFile, Index},
874 
875       {R"cpp(// allow -- symbol is indexable and has no refs in index.
876         void [[On^lyInThisFile]]();
877       )cpp",
878        nullptr, HeaderFile, Index},
879 
880       {R"cpp(
881         void ^f();
882       )cpp",
883        "keyword", HeaderFile, Index, "return"},
884 
885       {R"cpp(// disallow -- symbol is indexable and has other refs in index.
886         void f() {
887           Out^side s;
888         }
889       )cpp",
890        "used outside main file", HeaderFile, Index},
891 
892       {R"cpp(// disallow -- symbol in anonymous namespace in header is not indexable.
893         namespace {
894         class Unin^dexable {};
895         }
896       )cpp",
897        "not eligible for indexing", HeaderFile, Index},
898 
899       {R"cpp(// allow -- symbol in anonymous namespace in non-header file is indexable.
900         namespace {
901         class [[F^oo]] {};
902         }
903       )cpp",
904        nullptr, !HeaderFile, Index},
905 
906       {R"cpp(// disallow -- namespace symbol isn't supported
907         namespace n^s {}
908       )cpp",
909        "not a supported kind", HeaderFile, Index},
910 
911       {
912           R"cpp(
913          #define MACRO 1
914          int s = MAC^RO;
915        )cpp",
916           "not a supported kind", HeaderFile, Index},
917 
918       {
919           R"cpp(
920         struct X { X operator++(int); };
921         void f(X x) {x+^+;})cpp",
922           "no symbol", HeaderFile, Index},
923 
924       {R"cpp(// foo is declared outside the file.
925         void fo^o() {}
926       )cpp",
927        "used outside main file", !HeaderFile /*cc file*/, Index},
928 
929       {R"cpp(
930          // We should detect the symbol is used outside the file from the AST.
931          void fo^o() {})cpp",
932        "used outside main file", !HeaderFile, nullptr /*no index*/},
933 
934       {R"cpp(// disallow rename on excluded symbols (e.g. std symbols)
935          namespace std {
936          class str^ing {};
937          }
938        )cpp",
939        "not a supported kind", !HeaderFile, Index},
940       {R"cpp(// disallow rename on excluded symbols (e.g. std symbols)
941          namespace std {
942          inline namespace __u {
943          class str^ing {};
944          }
945          }
946        )cpp",
947        "not a supported kind", !HeaderFile, Index},
948 
949       {R"cpp(// disallow rename on non-normal identifiers.
950          @interface Foo {}
951          -(int) fo^o:(int)x; // Token is an identifier, but declaration name isn't a simple identifier.
952          @end
953        )cpp",
954        "not a supported kind", HeaderFile, Index},
955 
956       {R"cpp(
957          void foo(int);
958          void foo(char);
959          template <typename T> void f(T t) {
960            fo^o(t);
961          })cpp",
962        "multiple symbols", !HeaderFile, nullptr /*no index*/},
963 
964       {R"cpp(// disallow rename on unrelated token.
965          cl^ass Foo {};
966        )cpp",
967        "no symbol", !HeaderFile, nullptr},
968 
969       {R"cpp(// disallow rename on unrelated token.
970          temp^late<typename T>
971          class Foo {};
972        )cpp",
973        "no symbol", !HeaderFile, nullptr},
974 
975       {R"cpp(
976         namespace {
977         int Conflict;
978         int Va^r;
979         }
980       )cpp",
981        "conflict", !HeaderFile, nullptr, "Conflict"},
982 
983       {R"cpp(
984         int Conflict;
985         int Va^r;
986       )cpp",
987        "conflict", !HeaderFile, nullptr, "Conflict"},
988 
989       {R"cpp(
990         class Foo {
991           int Conflict;
992           int Va^r;
993         };
994       )cpp",
995        "conflict", !HeaderFile, nullptr, "Conflict"},
996 
997       {R"cpp(
998         enum E {
999           Conflict,
1000           Fo^o,
1001         };
1002       )cpp",
1003        "conflict", !HeaderFile, nullptr, "Conflict"},
1004 
1005       {R"cpp(
1006         int Conflict;
1007         enum E { // transparent context.
1008           F^oo,
1009         };
1010       )cpp",
1011        "conflict", !HeaderFile, nullptr, "Conflict"},
1012 
1013       {R"cpp(// FIXME: detecting local variables is not supported yet.
1014         void func() {
1015           int Conflict;
1016           int [[V^ar]];
1017         }
1018       )cpp",
1019        nullptr, !HeaderFile, nullptr, "Conflict"},
1020 
1021       {R"cpp(// Trying to rename into the same name, SameName == SameName.
1022         void func() {
1023           int S^ameName;
1024         }
1025       )cpp",
1026        "new name is the same", !HeaderFile, nullptr, "SameName"},
1027       {R"cpp(// Ensure it doesn't associate base specifier with base name.
1028         struct A {};
1029         struct B : priv^ate A {};
1030       )cpp",
1031        "Cannot rename symbol: there is no symbol at the given location", false,
1032        nullptr},
1033   };
1034 
1035   for (const auto& Case : Cases) {
1036     SCOPED_TRACE(Case.Code);
1037     Annotations T(Case.Code);
1038     TestTU TU = TestTU::withCode(T.code());
1039     TU.HeaderCode = CommonHeader;
1040     TU.ExtraArgs.push_back("-fno-delayed-template-parsing");
1041     if (Case.IsHeaderFile) {
1042       // We open the .h file as the main file.
1043       TU.Filename = "test.h";
1044       // Parsing the .h file as C++ include.
1045       TU.ExtraArgs.push_back("-xobjective-c++-header");
1046     }
1047     auto AST = TU.build();
1048     llvm::StringRef NewName = Case.NewName;
1049     auto Results =
1050         rename({T.point(), NewName, AST, testPath(TU.Filename), Case.Index});
1051     bool WantRename = true;
1052     if (T.ranges().empty())
1053       WantRename = false;
1054     if (!WantRename) {
1055       assert(Case.ErrorMessage && "Error message must be set!");
1056       EXPECT_FALSE(Results)
1057           << "expected rename returned an error: " << T.code();
1058       auto ActualMessage = llvm::toString(Results.takeError());
1059       EXPECT_THAT(ActualMessage, testing::HasSubstr(Case.ErrorMessage));
1060     } else {
1061       EXPECT_TRUE(bool(Results)) << "rename returned an error: "
1062                                  << llvm::toString(Results.takeError());
1063       ASSERT_EQ(1u, Results->GlobalChanges.size());
1064       EXPECT_EQ(applyEdits(std::move(Results->GlobalChanges)).front().second,
1065                 expectedResult(T, NewName));
1066     }
1067   }
1068 }
1069 
1070 MATCHER_P(newText, T, "") { return arg.newText == T; }
1071 
TEST(RenameTest,IndexMergeMainFile)1072 TEST(RenameTest, IndexMergeMainFile) {
1073   Annotations Code("int ^x();");
1074   TestTU TU = TestTU::withCode(Code.code());
1075   TU.Filename = "main.cc";
1076   auto AST = TU.build();
1077 
1078   auto Main = testPath("main.cc");
1079 
1080   auto Rename = [&](const SymbolIndex *Idx) {
1081     auto GetDirtyBuffer = [&](PathRef Path) -> llvm::Optional<std::string> {
1082       return Code.code().str(); // Every file has the same content.
1083     };
1084     RenameOptions Opts;
1085     Opts.AllowCrossFile = true;
1086     RenameInputs Inputs{Code.point(), "xPrime", AST,           Main,
1087                         Idx,          Opts,     GetDirtyBuffer};
1088     auto Results = rename(Inputs);
1089     EXPECT_TRUE(bool(Results)) << llvm::toString(Results.takeError());
1090     return std::move(*Results);
1091   };
1092 
1093   // We do not expect to see duplicated edits from AST vs index.
1094   auto Results = Rename(TU.index().get());
1095   EXPECT_THAT(Results.GlobalChanges.keys(), ElementsAre(Main));
1096   EXPECT_THAT(Results.GlobalChanges[Main].asTextEdits(),
1097               ElementsAre(newText("xPrime")));
1098 
1099   // Sanity check: we do expect to see index results!
1100   TU.Filename = "other.cc";
1101   Results = Rename(TU.index().get());
1102   EXPECT_THAT(Results.GlobalChanges.keys(),
1103               UnorderedElementsAre(Main, testPath("other.cc")));
1104 
1105 #ifdef CLANGD_PATH_CASE_INSENSITIVE
1106   // On case-insensitive systems, no duplicates if AST vs index case differs.
1107   // https://github.com/clangd/clangd/issues/665
1108   TU.Filename = "MAIN.CC";
1109   Results = Rename(TU.index().get());
1110   EXPECT_THAT(Results.GlobalChanges.keys(), ElementsAre(Main));
1111   EXPECT_THAT(Results.GlobalChanges[Main].asTextEdits(),
1112               ElementsAre(newText("xPrime")));
1113 #endif
1114 }
1115 
TEST(RenameTest,MainFileReferencesOnly)1116 TEST(RenameTest, MainFileReferencesOnly) {
1117   // filter out references not from main file.
1118   llvm::StringRef Test =
1119       R"cpp(
1120         void test() {
1121           int [[fo^o]] = 1;
1122           // rename references not from main file are not included.
1123           #include "foo.inc"
1124         })cpp";
1125 
1126   Annotations Code(Test);
1127   auto TU = TestTU::withCode(Code.code());
1128   TU.AdditionalFiles["foo.inc"] = R"cpp(
1129       #define Macro(X) X
1130       &Macro(foo);
1131       &foo;
1132     )cpp";
1133   auto AST = TU.build();
1134   llvm::StringRef NewName = "abcde";
1135 
1136   auto RenameResult =
1137       rename({Code.point(), NewName, AST, testPath(TU.Filename)});
1138   ASSERT_TRUE(bool(RenameResult)) << RenameResult.takeError() << Code.point();
1139   ASSERT_EQ(1u, RenameResult->GlobalChanges.size());
1140   EXPECT_EQ(applyEdits(std::move(RenameResult->GlobalChanges)).front().second,
1141             expectedResult(Code, NewName));
1142 }
1143 
TEST(RenameTest,ProtobufSymbolIsExcluded)1144 TEST(RenameTest, ProtobufSymbolIsExcluded) {
1145   Annotations Code("Prot^obuf buf;");
1146   auto TU = TestTU::withCode(Code.code());
1147   TU.HeaderCode =
1148       R"cpp(// Generated by the protocol buffer compiler.  DO NOT EDIT!
1149       class Protobuf {};
1150       )cpp";
1151   TU.HeaderFilename = "protobuf.pb.h";
1152   auto AST = TU.build();
1153   auto Results = rename({Code.point(), "newName", AST, testPath(TU.Filename)});
1154   EXPECT_FALSE(Results);
1155   EXPECT_THAT(llvm::toString(Results.takeError()),
1156               testing::HasSubstr("not a supported kind"));
1157 }
1158 
TEST(RenameTest,PrepareRename)1159 TEST(RenameTest, PrepareRename) {
1160   Annotations FooH("void func();");
1161   Annotations FooCC(R"cpp(
1162     #include "foo.h"
1163     void [[fu^nc]]() {}
1164   )cpp");
1165   std::string FooHPath = testPath("foo.h");
1166   std::string FooCCPath = testPath("foo.cc");
1167   MockFS FS;
1168   FS.Files[FooHPath] = std::string(FooH.code());
1169   FS.Files[FooCCPath] = std::string(FooCC.code());
1170 
1171   auto ServerOpts = ClangdServer::optsForTest();
1172   ServerOpts.BuildDynamicSymbolIndex = true;
1173 
1174   trace::TestTracer Tracer;
1175   MockCompilationDatabase CDB;
1176   ClangdServer Server(CDB, FS, ServerOpts);
1177   runAddDocument(Server, FooHPath, FooH.code());
1178   runAddDocument(Server, FooCCPath, FooCC.code());
1179 
1180   auto Results = runPrepareRename(Server, FooCCPath, FooCC.point(),
1181                                   /*NewName=*/llvm::None, {/*CrossFile=*/true});
1182   // Verify that for multi-file rename, we only return main-file occurrences.
1183   ASSERT_TRUE(bool(Results)) << Results.takeError();
1184   // We don't know the result is complete in prepareRename (passing a nullptr
1185   // index internally), so GlobalChanges should be empty.
1186   EXPECT_TRUE(Results->GlobalChanges.empty());
1187   EXPECT_THAT(FooCC.ranges(),
1188               testing::UnorderedElementsAreArray(Results->LocalChanges));
1189 
1190   // Name validation.
1191   Results =
1192       runPrepareRename(Server, FooCCPath, FooCC.point(),
1193                        /*NewName=*/std::string("int"), {/*CrossFile=*/true});
1194   EXPECT_FALSE(Results);
1195   EXPECT_THAT(llvm::toString(Results.takeError()),
1196               testing::HasSubstr("keyword"));
1197   EXPECT_THAT(Tracer.takeMetric("rename_name_invalid", "Keywords"),
1198               ElementsAre(1));
1199 
1200   // Single-file rename on global symbols, we should report an error.
1201   Results = runPrepareRename(Server, FooCCPath, FooCC.point(),
1202                              /*NewName=*/llvm::None, {/*CrossFile=*/false});
1203   EXPECT_FALSE(Results);
1204   EXPECT_THAT(llvm::toString(Results.takeError()),
1205               testing::HasSubstr("is used outside"));
1206 }
1207 
TEST(CrossFileRenameTests,DirtyBuffer)1208 TEST(CrossFileRenameTests, DirtyBuffer) {
1209   Annotations FooCode("class [[Foo]] {};");
1210   std::string FooPath = testPath("foo.cc");
1211   Annotations FooDirtyBuffer("class [[Foo]] {};\n// this is dirty buffer");
1212   Annotations BarCode("void [[Bar]]() {}");
1213   std::string BarPath = testPath("bar.cc");
1214   // Build the index, the index has "Foo" references from foo.cc and "Bar"
1215   // references from bar.cc.
1216   FileSymbols FSymbols;
1217   FSymbols.update(FooPath, nullptr, buildRefSlab(FooCode, "Foo", FooPath),
1218                   nullptr, false);
1219   FSymbols.update(BarPath, nullptr, buildRefSlab(BarCode, "Bar", BarPath),
1220                   nullptr, false);
1221   auto Index = FSymbols.buildIndex(IndexType::Light);
1222 
1223   Annotations MainCode("class  [[Fo^o]] {};");
1224   auto MainFilePath = testPath("main.cc");
1225   // Dirty buffer for foo.cc.
1226   auto GetDirtyBuffer = [&](PathRef Path) -> llvm::Optional<std::string> {
1227     if (Path == FooPath)
1228       return FooDirtyBuffer.code().str();
1229     return llvm::None;
1230   };
1231 
1232   // Run rename on Foo, there is a dirty buffer for foo.cc, rename should
1233   // respect the dirty buffer.
1234   TestTU TU = TestTU::withCode(MainCode.code());
1235   auto AST = TU.build();
1236   llvm::StringRef NewName = "newName";
1237   auto Results = rename({MainCode.point(),
1238                          NewName,
1239                          AST,
1240                          MainFilePath,
1241                          Index.get(),
1242                          {/*CrossFile=*/true},
1243                          GetDirtyBuffer});
1244   ASSERT_TRUE(bool(Results)) << Results.takeError();
1245   EXPECT_THAT(
1246       applyEdits(std::move(Results->GlobalChanges)),
1247       UnorderedElementsAre(
1248           Pair(Eq(FooPath), Eq(expectedResult(FooDirtyBuffer, NewName))),
1249           Pair(Eq(MainFilePath), Eq(expectedResult(MainCode, NewName)))));
1250 
1251   // Run rename on Bar, there is no dirty buffer for the affected file bar.cc,
1252   // so we should read file content from VFS.
1253   MainCode = Annotations("void [[Bar]]() { [[B^ar]](); }");
1254   TU = TestTU::withCode(MainCode.code());
1255   // Set a file "bar.cc" on disk.
1256   TU.AdditionalFiles["bar.cc"] = std::string(BarCode.code());
1257   AST = TU.build();
1258   Results = rename({MainCode.point(),
1259                     NewName,
1260                     AST,
1261                     MainFilePath,
1262                     Index.get(),
1263                     {/*CrossFile=*/true},
1264                     GetDirtyBuffer});
1265   ASSERT_TRUE(bool(Results)) << Results.takeError();
1266   EXPECT_THAT(
1267       applyEdits(std::move(Results->GlobalChanges)),
1268       UnorderedElementsAre(
1269           Pair(Eq(BarPath), Eq(expectedResult(BarCode, NewName))),
1270           Pair(Eq(MainFilePath), Eq(expectedResult(MainCode, NewName)))));
1271 
1272   // Run rename on a pagination index which couldn't return all refs in one
1273   // request, we reject rename on this case.
1274   class PaginationIndex : public SymbolIndex {
1275     bool refs(const RefsRequest &Req,
1276               llvm::function_ref<void(const Ref &)> Callback) const override {
1277       return true; // has more references
1278     }
1279 
1280     bool fuzzyFind(
1281         const FuzzyFindRequest &Req,
1282         llvm::function_ref<void(const Symbol &)> Callback) const override {
1283       return false;
1284     }
1285     void
1286     lookup(const LookupRequest &Req,
1287            llvm::function_ref<void(const Symbol &)> Callback) const override {}
1288 
1289     void relations(const RelationsRequest &Req,
1290                    llvm::function_ref<void(const SymbolID &, const Symbol &)>
1291                        Callback) const override {}
1292 
1293     llvm::unique_function<bool(llvm::StringRef) const>
1294     indexedFiles() const override {
1295       return [](llvm::StringRef) { return false; };
1296     }
1297 
1298     size_t estimateMemoryUsage() const override { return 0; }
1299   } PIndex;
1300   Results = rename({MainCode.point(),
1301                     NewName,
1302                     AST,
1303                     MainFilePath,
1304                     &PIndex,
1305                     {/*CrossFile=*/true},
1306                     GetDirtyBuffer});
1307   EXPECT_FALSE(Results);
1308   EXPECT_THAT(llvm::toString(Results.takeError()),
1309               testing::HasSubstr("too many occurrences"));
1310 }
1311 
TEST(CrossFileRenameTests,DeduplicateRefsFromIndex)1312 TEST(CrossFileRenameTests, DeduplicateRefsFromIndex) {
1313   auto MainCode = Annotations("int [[^x]] = 2;");
1314   auto MainFilePath = testPath("main.cc");
1315   auto BarCode = Annotations("int [[x]];");
1316   auto BarPath = testPath("bar.cc");
1317   auto TU = TestTU::withCode(MainCode.code());
1318   // Set a file "bar.cc" on disk.
1319   TU.AdditionalFiles["bar.cc"] = std::string(BarCode.code());
1320   auto AST = TU.build();
1321   std::string BarPathURI = URI::create(BarPath).toString();
1322   Ref XRefInBarCC = refWithRange(BarCode.range(), BarPathURI);
1323   // The index will return duplicated refs, our code should be robost to handle
1324   // it.
1325   class DuplicatedXRefIndex : public SymbolIndex {
1326   public:
1327     DuplicatedXRefIndex(const Ref &ReturnedRef) : ReturnedRef(ReturnedRef) {}
1328     bool refs(const RefsRequest &Req,
1329               llvm::function_ref<void(const Ref &)> Callback) const override {
1330       // Return two duplicated refs.
1331       Callback(ReturnedRef);
1332       Callback(ReturnedRef);
1333       return false;
1334     }
1335 
1336     bool fuzzyFind(const FuzzyFindRequest &,
1337                    llvm::function_ref<void(const Symbol &)>) const override {
1338       return false;
1339     }
1340     void lookup(const LookupRequest &,
1341                 llvm::function_ref<void(const Symbol &)>) const override {}
1342 
1343     void relations(const RelationsRequest &,
1344                    llvm::function_ref<void(const SymbolID &, const Symbol &)>)
1345         const override {}
1346 
1347     llvm::unique_function<bool(llvm::StringRef) const>
1348     indexedFiles() const override {
1349       return [](llvm::StringRef) { return false; };
1350     }
1351 
1352     size_t estimateMemoryUsage() const override { return 0; }
1353     Ref ReturnedRef;
1354   } DIndex(XRefInBarCC);
1355   llvm::StringRef NewName = "newName";
1356   auto Results = rename({MainCode.point(),
1357                          NewName,
1358                          AST,
1359                          MainFilePath,
1360                          &DIndex,
1361                          {/*CrossFile=*/true}});
1362   ASSERT_TRUE(bool(Results)) << Results.takeError();
1363   EXPECT_THAT(
1364       applyEdits(std::move(Results->GlobalChanges)),
1365       UnorderedElementsAre(
1366           Pair(Eq(BarPath), Eq(expectedResult(BarCode, NewName))),
1367           Pair(Eq(MainFilePath), Eq(expectedResult(MainCode, NewName)))));
1368 }
1369 
TEST(CrossFileRenameTests,WithUpToDateIndex)1370 TEST(CrossFileRenameTests, WithUpToDateIndex) {
1371   MockCompilationDatabase CDB;
1372   CDB.ExtraClangFlags = {"-xc++"};
1373   // rename is runnning on all "^" points in FooH, and "[[]]" ranges are the
1374   // expected rename occurrences.
1375   struct Case {
1376     llvm::StringRef FooH;
1377     llvm::StringRef FooCC;
1378   } Cases[] = {
1379       {
1380           // classes.
1381           R"cpp(
1382         class [[Fo^o]] {
1383           [[Foo]]();
1384           ~[[Foo]]();
1385         };
1386       )cpp",
1387           R"cpp(
1388         #include "foo.h"
1389         [[Foo]]::[[Foo]]() {}
1390         [[Foo]]::~[[Foo]]() {}
1391 
1392         void func() {
1393           [[Foo]] foo;
1394         }
1395       )cpp",
1396       },
1397       {
1398           // class templates.
1399           R"cpp(
1400         template <typename T>
1401         class [[Foo]] {};
1402         // FIXME: explicit template specializations are not supported due the
1403         // clangd index limitations.
1404         template <>
1405         class Foo<double> {};
1406       )cpp",
1407           R"cpp(
1408         #include "foo.h"
1409         void func() {
1410           [[F^oo]]<int> foo;
1411         }
1412       )cpp",
1413       },
1414       {
1415           // class methods.
1416           R"cpp(
1417         class Foo {
1418           void [[f^oo]]();
1419         };
1420       )cpp",
1421           R"cpp(
1422         #include "foo.h"
1423         void Foo::[[foo]]() {}
1424 
1425         void func(Foo* p) {
1426           p->[[foo]]();
1427         }
1428       )cpp",
1429       },
1430       {
1431           // rename on constructor and destructor.
1432           R"cpp(
1433         class [[Foo]] {
1434           [[^Foo]]();
1435           ~[[Foo^]]();
1436         };
1437       )cpp",
1438           R"cpp(
1439         #include "foo.h"
1440         [[Foo]]::[[Foo]]() {}
1441         [[Foo]]::~[[Foo]]() {}
1442 
1443         void func() {
1444           [[Foo]] foo;
1445         }
1446       )cpp",
1447       },
1448       {
1449           // functions.
1450           R"cpp(
1451         void [[f^oo]]();
1452       )cpp",
1453           R"cpp(
1454         #include "foo.h"
1455         void [[foo]]() {}
1456 
1457         void func() {
1458           [[foo]]();
1459         }
1460       )cpp",
1461       },
1462       {
1463           // typedefs.
1464           R"cpp(
1465       typedef int [[IN^T]];
1466       [[INT]] foo();
1467       )cpp",
1468           R"cpp(
1469         #include "foo.h"
1470         [[INT]] foo() {}
1471       )cpp",
1472       },
1473       {
1474           // usings.
1475           R"cpp(
1476       using [[I^NT]] = int;
1477       [[INT]] foo();
1478       )cpp",
1479           R"cpp(
1480         #include "foo.h"
1481         [[INT]] foo() {}
1482       )cpp",
1483       },
1484       {
1485           // variables.
1486           R"cpp(
1487         static const int [[VA^R]] = 123;
1488       )cpp",
1489           R"cpp(
1490         #include "foo.h"
1491         int s = [[VAR]];
1492       )cpp",
1493       },
1494       {
1495           // scope enums.
1496           R"cpp(
1497       enum class [[K^ind]] { ABC };
1498       )cpp",
1499           R"cpp(
1500         #include "foo.h"
1501         [[Kind]] ff() {
1502           return [[Kind]]::ABC;
1503         }
1504       )cpp",
1505       },
1506       {
1507           // enum constants.
1508           R"cpp(
1509       enum class Kind { [[A^BC]] };
1510       )cpp",
1511           R"cpp(
1512         #include "foo.h"
1513         Kind ff() {
1514           return Kind::[[ABC]];
1515         }
1516       )cpp",
1517       },
1518       {
1519           // Implicit references in macro expansions.
1520           R"cpp(
1521         class [[Fo^o]] {};
1522         #define FooFoo Foo
1523         #define FOO Foo
1524       )cpp",
1525           R"cpp(
1526         #include "foo.h"
1527         void bar() {
1528           [[Foo]] x;
1529           FOO y;
1530           FooFoo z;
1531         }
1532       )cpp",
1533       },
1534   };
1535 
1536   trace::TestTracer Tracer;
1537   for (const auto &T : Cases) {
1538     SCOPED_TRACE(T.FooH);
1539     Annotations FooH(T.FooH);
1540     Annotations FooCC(T.FooCC);
1541     std::string FooHPath = testPath("foo.h");
1542     std::string FooCCPath = testPath("foo.cc");
1543 
1544     MockFS FS;
1545     FS.Files[FooHPath] = std::string(FooH.code());
1546     FS.Files[FooCCPath] = std::string(FooCC.code());
1547 
1548     auto ServerOpts = ClangdServer::optsForTest();
1549     ServerOpts.BuildDynamicSymbolIndex = true;
1550     ClangdServer Server(CDB, FS, ServerOpts);
1551 
1552     // Add all files to clangd server to make sure the dynamic index has been
1553     // built.
1554     runAddDocument(Server, FooHPath, FooH.code());
1555     runAddDocument(Server, FooCCPath, FooCC.code());
1556 
1557     llvm::StringRef NewName = "NewName";
1558     for (const auto &RenamePos : FooH.points()) {
1559       EXPECT_THAT(Tracer.takeMetric("rename_files"), SizeIs(0));
1560       auto FileEditsList = llvm::cantFail(runRename(
1561           Server, FooHPath, RenamePos, NewName, {/*CrossFile=*/true}));
1562       EXPECT_THAT(Tracer.takeMetric("rename_files"), ElementsAre(2));
1563       EXPECT_THAT(
1564           applyEdits(std::move(FileEditsList.GlobalChanges)),
1565           UnorderedElementsAre(
1566               Pair(Eq(FooHPath), Eq(expectedResult(T.FooH, NewName))),
1567               Pair(Eq(FooCCPath), Eq(expectedResult(T.FooCC, NewName)))));
1568     }
1569   }
1570 }
1571 
TEST(CrossFileRenameTests,CrossFileOnLocalSymbol)1572 TEST(CrossFileRenameTests, CrossFileOnLocalSymbol) {
1573   // cross-file rename should work for function-local symbols, even there is no
1574   // index provided.
1575   Annotations Code("void f(int [[abc]]) { [[a^bc]] = 3; }");
1576   auto TU = TestTU::withCode(Code.code());
1577   auto Path = testPath(TU.Filename);
1578   auto AST = TU.build();
1579   llvm::StringRef NewName = "newName";
1580   auto Results = rename({Code.point(), NewName, AST, Path});
1581   ASSERT_TRUE(bool(Results)) << Results.takeError();
1582   EXPECT_THAT(
1583       applyEdits(std::move(Results->GlobalChanges)),
1584       UnorderedElementsAre(Pair(Eq(Path), Eq(expectedResult(Code, NewName)))));
1585 }
1586 
TEST(CrossFileRenameTests,BuildRenameEdits)1587 TEST(CrossFileRenameTests, BuildRenameEdits) {
1588   Annotations Code("[[��]]");
1589   auto LSPRange = Code.range();
1590   llvm::StringRef FilePath = "/test/TestTU.cpp";
1591   llvm::StringRef NewName = "abc";
1592   auto Edit = buildRenameEdit(FilePath, Code.code(), {LSPRange}, NewName);
1593   ASSERT_TRUE(bool(Edit)) << Edit.takeError();
1594   ASSERT_EQ(1UL, Edit->Replacements.size());
1595   EXPECT_EQ(FilePath, Edit->Replacements.begin()->getFilePath());
1596   EXPECT_EQ(4UL, Edit->Replacements.begin()->getLength());
1597 
1598   // Test invalid range.
1599   LSPRange.end = {10, 0}; // out of range
1600   Edit = buildRenameEdit(FilePath, Code.code(), {LSPRange}, NewName);
1601   EXPECT_FALSE(Edit);
1602   EXPECT_THAT(llvm::toString(Edit.takeError()),
1603               testing::HasSubstr("fail to convert"));
1604 
1605   // Normal ascii characters.
1606   Annotations T(R"cpp(
1607     [[range]]
1608               [[range]]
1609       [[range]]
1610   )cpp");
1611   Edit = buildRenameEdit(FilePath, T.code(), T.ranges(), NewName);
1612   ASSERT_TRUE(bool(Edit)) << Edit.takeError();
1613   EXPECT_EQ(applyEdits(FileEdits{{T.code(), std::move(*Edit)}}).front().second,
1614             expectedResult(T, NewName));
1615 }
1616 
TEST(CrossFileRenameTests,adjustRenameRanges)1617 TEST(CrossFileRenameTests, adjustRenameRanges) {
1618   // Ranges in IndexedCode indicate the indexed occurrences;
1619   // ranges in DraftCode indicate the expected mapped result, empty indicates
1620   // we expect no matched result found.
1621   struct {
1622     llvm::StringRef IndexedCode;
1623     llvm::StringRef DraftCode;
1624   } Tests[] = {
1625     {
1626       // both line and column are changed, not a near miss.
1627       R"cpp(
1628         int [[x]] = 0;
1629       )cpp",
1630       R"cpp(
1631         // insert a line.
1632         double x = 0;
1633       )cpp",
1634     },
1635     {
1636       // subset.
1637       R"cpp(
1638         int [[x]] = 0;
1639       )cpp",
1640       R"cpp(
1641         int [[x]] = 0;
1642         {int x = 0; }
1643       )cpp",
1644     },
1645     {
1646       // shift columns.
1647       R"cpp(int [[x]] = 0; void foo(int x);)cpp",
1648       R"cpp(double [[x]] = 0; void foo(double x);)cpp",
1649     },
1650     {
1651       // shift lines.
1652       R"cpp(
1653         int [[x]] = 0;
1654         void foo(int x);
1655       )cpp",
1656       R"cpp(
1657         // insert a line.
1658         int [[x]] = 0;
1659         void foo(int x);
1660       )cpp",
1661     },
1662   };
1663   LangOptions LangOpts;
1664   LangOpts.CPlusPlus = true;
1665   for (const auto &T : Tests) {
1666     SCOPED_TRACE(T.DraftCode);
1667     Annotations Draft(T.DraftCode);
1668     auto ActualRanges = adjustRenameRanges(
1669         Draft.code(), "x", Annotations(T.IndexedCode).ranges(), LangOpts);
1670     if (!ActualRanges)
1671        EXPECT_THAT(Draft.ranges(), testing::IsEmpty());
1672     else
1673       EXPECT_THAT(Draft.ranges(),
1674                   testing::UnorderedElementsAreArray(*ActualRanges));
1675   }
1676 }
1677 
TEST(RangePatchingHeuristic,GetMappedRanges)1678 TEST(RangePatchingHeuristic, GetMappedRanges) {
1679   // ^ in LexedCode marks the ranges we expect to be mapped; no ^ indicates
1680   // there are no mapped ranges.
1681   struct {
1682     llvm::StringRef IndexedCode;
1683     llvm::StringRef LexedCode;
1684   } Tests[] = {
1685     {
1686       // no lexed ranges.
1687       "[[]]",
1688       "",
1689     },
1690     {
1691       // both line and column are changed, not a near miss.
1692       R"([[]])",
1693       R"(
1694         [[]]
1695       )",
1696     },
1697     {
1698       // subset.
1699       "[[]]",
1700       "^[[]]  [[]]"
1701     },
1702     {
1703       // shift columns.
1704       "[[]]   [[]]",
1705       "  ^[[]]   ^[[]]  [[]]"
1706     },
1707     {
1708       R"(
1709         [[]]
1710 
1711         [[]] [[]]
1712       )",
1713       R"(
1714         // insert a line
1715         ^[[]]
1716 
1717         ^[[]] ^[[]]
1718       )",
1719     },
1720     {
1721       R"(
1722         [[]]
1723 
1724         [[]] [[]]
1725       )",
1726       R"(
1727         // insert a line
1728         ^[[]]
1729           ^[[]]  ^[[]] // column is shifted.
1730       )",
1731     },
1732     {
1733       R"(
1734         [[]]
1735 
1736         [[]] [[]]
1737       )",
1738       R"(
1739         // insert a line
1740         [[]]
1741 
1742           [[]]  [[]] // not mapped (both line and column are changed).
1743       )",
1744     },
1745     {
1746       R"(
1747         [[]]
1748                 [[]]
1749 
1750                    [[]]
1751                   [[]]
1752 
1753         }
1754       )",
1755       R"(
1756         // insert a new line
1757         ^[[]]
1758                 ^[[]]
1759              [[]] // additional range
1760                    ^[[]]
1761                   ^[[]]
1762             [[]] // additional range
1763       )",
1764     },
1765     {
1766       // non-distinct result (two best results), not a near miss
1767       R"(
1768         [[]]
1769             [[]]
1770             [[]]
1771       )",
1772       R"(
1773         [[]]
1774         [[]]
1775             [[]]
1776             [[]]
1777       )",
1778     }
1779   };
1780   for (const auto &T : Tests) {
1781     SCOPED_TRACE(T.IndexedCode);
1782     auto Lexed = Annotations(T.LexedCode);
1783     auto LexedRanges = Lexed.ranges();
1784     std::vector<Range> ExpectedMatches;
1785     for (auto P : Lexed.points()) {
1786       auto Match = llvm::find_if(LexedRanges, [&P](const Range& R) {
1787         return R.start == P;
1788       });
1789       ASSERT_NE(Match, LexedRanges.end());
1790       ExpectedMatches.push_back(*Match);
1791     }
1792 
1793     auto Mapped =
1794         getMappedRanges(Annotations(T.IndexedCode).ranges(), LexedRanges);
1795     if (!Mapped)
1796       EXPECT_THAT(ExpectedMatches, IsEmpty());
1797     else
1798       EXPECT_THAT(ExpectedMatches, UnorderedElementsAreArray(*Mapped));
1799   }
1800 }
1801 
TEST(CrossFileRenameTests,adjustmentCost)1802 TEST(CrossFileRenameTests, adjustmentCost) {
1803   struct {
1804     llvm::StringRef RangeCode;
1805     size_t ExpectedCost;
1806   } Tests[] = {
1807     {
1808       R"(
1809         $idx[[]]$lex[[]] // diff: 0
1810       )",
1811       0,
1812     },
1813     {
1814       R"(
1815         $idx[[]]
1816         $lex[[]] // line diff: +1
1817                        $idx[[]]
1818                        $lex[[]] // line diff: +1
1819         $idx[[]]
1820         $lex[[]] // line diff: +1
1821 
1822           $idx[[]]
1823 
1824           $lex[[]] // line diff: +2
1825       )",
1826       1 + 1
1827     },
1828     {
1829        R"(
1830         $idx[[]]
1831         $lex[[]] // line diff: +1
1832                        $idx[[]]
1833 
1834                        $lex[[]] // line diff: +2
1835         $idx[[]]
1836 
1837 
1838         $lex[[]] // line diff: +3
1839       )",
1840       1 + 1 + 1
1841     },
1842     {
1843        R"(
1844         $idx[[]]
1845 
1846 
1847         $lex[[]] // line diff: +3
1848                        $idx[[]]
1849 
1850                        $lex[[]] // line diff: +2
1851         $idx[[]]
1852         $lex[[]] // line diff: +1
1853       )",
1854       3 + 1 + 1
1855     },
1856     {
1857       R"(
1858         $idx[[]]
1859         $lex[[]] // line diff: +1
1860                        $lex[[]] // line diff: -2
1861 
1862                        $idx[[]]
1863         $idx[[]]
1864 
1865 
1866         $lex[[]] // line diff: +3
1867       )",
1868       1 + 3 + 5
1869     },
1870     {
1871       R"(
1872                        $idx[[]] $lex[[]] // column diff: +1
1873         $idx[[]]$lex[[]] // diff: 0
1874       )",
1875       1
1876     },
1877     {
1878       R"(
1879         $idx[[]]
1880         $lex[[]] // diff: +1
1881                        $idx[[]] $lex[[]] // column diff: +1
1882         $idx[[]]$lex[[]] // diff: 0
1883       )",
1884       1 + 1 + 1
1885     },
1886     {
1887       R"(
1888         $idx[[]] $lex[[]] // column diff: +1
1889       )",
1890       1
1891     },
1892     {
1893       R"(
1894         // column diffs: +1, +2, +3
1895         $idx[[]] $lex[[]] $idx[[]]  $lex[[]] $idx[[]]   $lex[[]]
1896       )",
1897       1 + 1 + 1,
1898     },
1899   };
1900   for (const auto &T : Tests) {
1901     SCOPED_TRACE(T.RangeCode);
1902     Annotations C(T.RangeCode);
1903     std::vector<size_t> MappedIndex;
1904     for (size_t I = 0; I < C.ranges("lex").size(); ++I)
1905       MappedIndex.push_back(I);
1906     EXPECT_EQ(renameRangeAdjustmentCost(C.ranges("idx"), C.ranges("lex"),
1907                                         MappedIndex),
1908               T.ExpectedCost);
1909   }
1910 }
1911 
1912 } // namespace
1913 } // namespace clangd
1914 } // namespace clang
1915