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