• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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   };
1028 
1029   for (const auto& Case : Cases) {
1030     SCOPED_TRACE(Case.Code);
1031     Annotations T(Case.Code);
1032     TestTU TU = TestTU::withCode(T.code());
1033     TU.HeaderCode = CommonHeader;
1034     TU.ExtraArgs.push_back("-fno-delayed-template-parsing");
1035     if (Case.IsHeaderFile) {
1036       // We open the .h file as the main file.
1037       TU.Filename = "test.h";
1038       // Parsing the .h file as C++ include.
1039       TU.ExtraArgs.push_back("-xobjective-c++-header");
1040     }
1041     auto AST = TU.build();
1042     llvm::StringRef NewName = Case.NewName;
1043     auto Results =
1044         rename({T.point(), NewName, AST, testPath(TU.Filename), Case.Index});
1045     bool WantRename = true;
1046     if (T.ranges().empty())
1047       WantRename = false;
1048     if (!WantRename) {
1049       assert(Case.ErrorMessage && "Error message must be set!");
1050       EXPECT_FALSE(Results)
1051           << "expected rename returned an error: " << T.code();
1052       auto ActualMessage = llvm::toString(Results.takeError());
1053       EXPECT_THAT(ActualMessage, testing::HasSubstr(Case.ErrorMessage));
1054     } else {
1055       EXPECT_TRUE(bool(Results)) << "rename returned an error: "
1056                                  << llvm::toString(Results.takeError());
1057       ASSERT_EQ(1u, Results->GlobalChanges.size());
1058       EXPECT_EQ(applyEdits(std::move(Results->GlobalChanges)).front().second,
1059                 expectedResult(T, NewName));
1060     }
1061   }
1062 }
1063 
TEST(RenameTest,MainFileReferencesOnly)1064 TEST(RenameTest, MainFileReferencesOnly) {
1065   // filter out references not from main file.
1066   llvm::StringRef Test =
1067       R"cpp(
1068         void test() {
1069           int [[fo^o]] = 1;
1070           // rename references not from main file are not included.
1071           #include "foo.inc"
1072         })cpp";
1073 
1074   Annotations Code(Test);
1075   auto TU = TestTU::withCode(Code.code());
1076   TU.AdditionalFiles["foo.inc"] = R"cpp(
1077       #define Macro(X) X
1078       &Macro(foo);
1079       &foo;
1080     )cpp";
1081   auto AST = TU.build();
1082   llvm::StringRef NewName = "abcde";
1083 
1084   auto RenameResult =
1085       rename({Code.point(), NewName, AST, testPath(TU.Filename)});
1086   ASSERT_TRUE(bool(RenameResult)) << RenameResult.takeError() << Code.point();
1087   ASSERT_EQ(1u, RenameResult->GlobalChanges.size());
1088   EXPECT_EQ(applyEdits(std::move(RenameResult->GlobalChanges)).front().second,
1089             expectedResult(Code, NewName));
1090 }
1091 
TEST(RenameTest,ProtobufSymbolIsExcluded)1092 TEST(RenameTest, ProtobufSymbolIsExcluded) {
1093   Annotations Code("Prot^obuf buf;");
1094   auto TU = TestTU::withCode(Code.code());
1095   TU.HeaderCode =
1096       R"cpp(// Generated by the protocol buffer compiler.  DO NOT EDIT!
1097       class Protobuf {};
1098       )cpp";
1099   TU.HeaderFilename = "protobuf.pb.h";
1100   auto AST = TU.build();
1101   auto Results = rename({Code.point(), "newName", AST, testPath(TU.Filename)});
1102   EXPECT_FALSE(Results);
1103   EXPECT_THAT(llvm::toString(Results.takeError()),
1104               testing::HasSubstr("not a supported kind"));
1105 }
1106 
TEST(RenameTest,PrepareRename)1107 TEST(RenameTest, PrepareRename) {
1108   Annotations FooH("void func();");
1109   Annotations FooCC(R"cpp(
1110     #include "foo.h"
1111     void [[fu^nc]]() {}
1112   )cpp");
1113   std::string FooHPath = testPath("foo.h");
1114   std::string FooCCPath = testPath("foo.cc");
1115   MockFS FS;
1116   FS.Files[FooHPath] = std::string(FooH.code());
1117   FS.Files[FooCCPath] = std::string(FooCC.code());
1118 
1119   auto ServerOpts = ClangdServer::optsForTest();
1120   ServerOpts.BuildDynamicSymbolIndex = true;
1121 
1122   trace::TestTracer Tracer;
1123   MockCompilationDatabase CDB;
1124   ClangdServer Server(CDB, FS, ServerOpts);
1125   runAddDocument(Server, FooHPath, FooH.code());
1126   runAddDocument(Server, FooCCPath, FooCC.code());
1127 
1128   auto Results = runPrepareRename(Server, FooCCPath, FooCC.point(),
1129                                   /*NewName=*/llvm::None, {/*CrossFile=*/true});
1130   // Verify that for multi-file rename, we only return main-file occurrences.
1131   ASSERT_TRUE(bool(Results)) << Results.takeError();
1132   // We don't know the result is complete in prepareRename (passing a nullptr
1133   // index internally), so GlobalChanges should be empty.
1134   EXPECT_TRUE(Results->GlobalChanges.empty());
1135   EXPECT_THAT(FooCC.ranges(),
1136               testing::UnorderedElementsAreArray(Results->LocalChanges));
1137 
1138   // Name validation.
1139   Results =
1140       runPrepareRename(Server, FooCCPath, FooCC.point(),
1141                        /*NewName=*/std::string("int"), {/*CrossFile=*/true});
1142   EXPECT_FALSE(Results);
1143   EXPECT_THAT(llvm::toString(Results.takeError()),
1144               testing::HasSubstr("keyword"));
1145   EXPECT_THAT(Tracer.takeMetric("rename_name_invalid", "Keywords"),
1146               ElementsAre(1));
1147 
1148   // Single-file rename on global symbols, we should report an error.
1149   Results = runPrepareRename(Server, FooCCPath, FooCC.point(),
1150                              /*NewName=*/llvm::None, {/*CrossFile=*/false});
1151   EXPECT_FALSE(Results);
1152   EXPECT_THAT(llvm::toString(Results.takeError()),
1153               testing::HasSubstr("is used outside"));
1154 }
1155 
TEST(CrossFileRenameTests,DirtyBuffer)1156 TEST(CrossFileRenameTests, DirtyBuffer) {
1157   Annotations FooCode("class [[Foo]] {};");
1158   std::string FooPath = testPath("foo.cc");
1159   Annotations FooDirtyBuffer("class [[Foo]] {};\n// this is dirty buffer");
1160   Annotations BarCode("void [[Bar]]() {}");
1161   std::string BarPath = testPath("bar.cc");
1162   // Build the index, the index has "Foo" references from foo.cc and "Bar"
1163   // references from bar.cc.
1164   FileSymbols FSymbols;
1165   FSymbols.update(FooPath, nullptr, buildRefSlab(FooCode, "Foo", FooPath),
1166                   nullptr, false);
1167   FSymbols.update(BarPath, nullptr, buildRefSlab(BarCode, "Bar", BarPath),
1168                   nullptr, false);
1169   auto Index = FSymbols.buildIndex(IndexType::Light);
1170 
1171   Annotations MainCode("class  [[Fo^o]] {};");
1172   auto MainFilePath = testPath("main.cc");
1173   // Dirty buffer for foo.cc.
1174   auto GetDirtyBuffer = [&](PathRef Path) -> llvm::Optional<std::string> {
1175     if (Path == FooPath)
1176       return FooDirtyBuffer.code().str();
1177     return llvm::None;
1178   };
1179 
1180   // Run rename on Foo, there is a dirty buffer for foo.cc, rename should
1181   // respect the dirty buffer.
1182   TestTU TU = TestTU::withCode(MainCode.code());
1183   auto AST = TU.build();
1184   llvm::StringRef NewName = "newName";
1185   auto Results = rename({MainCode.point(),
1186                          NewName,
1187                          AST,
1188                          MainFilePath,
1189                          Index.get(),
1190                          {/*CrossFile=*/true},
1191                          GetDirtyBuffer});
1192   ASSERT_TRUE(bool(Results)) << Results.takeError();
1193   EXPECT_THAT(
1194       applyEdits(std::move(Results->GlobalChanges)),
1195       UnorderedElementsAre(
1196           Pair(Eq(FooPath), Eq(expectedResult(FooDirtyBuffer, NewName))),
1197           Pair(Eq(MainFilePath), Eq(expectedResult(MainCode, NewName)))));
1198 
1199   // Run rename on Bar, there is no dirty buffer for the affected file bar.cc,
1200   // so we should read file content from VFS.
1201   MainCode = Annotations("void [[Bar]]() { [[B^ar]](); }");
1202   TU = TestTU::withCode(MainCode.code());
1203   // Set a file "bar.cc" on disk.
1204   TU.AdditionalFiles["bar.cc"] = std::string(BarCode.code());
1205   AST = TU.build();
1206   Results = rename({MainCode.point(),
1207                     NewName,
1208                     AST,
1209                     MainFilePath,
1210                     Index.get(),
1211                     {/*CrossFile=*/true},
1212                     GetDirtyBuffer});
1213   ASSERT_TRUE(bool(Results)) << Results.takeError();
1214   EXPECT_THAT(
1215       applyEdits(std::move(Results->GlobalChanges)),
1216       UnorderedElementsAre(
1217           Pair(Eq(BarPath), Eq(expectedResult(BarCode, NewName))),
1218           Pair(Eq(MainFilePath), Eq(expectedResult(MainCode, NewName)))));
1219 
1220   // Run rename on a pagination index which couldn't return all refs in one
1221   // request, we reject rename on this case.
1222   class PaginationIndex : public SymbolIndex {
1223     bool refs(const RefsRequest &Req,
1224               llvm::function_ref<void(const Ref &)> Callback) const override {
1225       return true; // has more references
1226     }
1227 
1228     bool fuzzyFind(
1229         const FuzzyFindRequest &Req,
1230         llvm::function_ref<void(const Symbol &)> Callback) const override {
1231       return false;
1232     }
1233     void
1234     lookup(const LookupRequest &Req,
1235            llvm::function_ref<void(const Symbol &)> Callback) const override {}
1236 
1237     void relations(const RelationsRequest &Req,
1238                    llvm::function_ref<void(const SymbolID &, const Symbol &)>
1239                        Callback) const override {}
1240     size_t estimateMemoryUsage() const override { return 0; }
1241   } PIndex;
1242   Results = rename({MainCode.point(),
1243                     NewName,
1244                     AST,
1245                     MainFilePath,
1246                     &PIndex,
1247                     {/*CrossFile=*/true},
1248                     GetDirtyBuffer});
1249   EXPECT_FALSE(Results);
1250   EXPECT_THAT(llvm::toString(Results.takeError()),
1251               testing::HasSubstr("too many occurrences"));
1252 }
1253 
TEST(CrossFileRenameTests,DeduplicateRefsFromIndex)1254 TEST(CrossFileRenameTests, DeduplicateRefsFromIndex) {
1255   auto MainCode = Annotations("int [[^x]] = 2;");
1256   auto MainFilePath = testPath("main.cc");
1257   auto BarCode = Annotations("int [[x]];");
1258   auto BarPath = testPath("bar.cc");
1259   auto TU = TestTU::withCode(MainCode.code());
1260   // Set a file "bar.cc" on disk.
1261   TU.AdditionalFiles["bar.cc"] = std::string(BarCode.code());
1262   auto AST = TU.build();
1263   std::string BarPathURI = URI::create(BarPath).toString();
1264   Ref XRefInBarCC = refWithRange(BarCode.range(), BarPathURI);
1265   // The index will return duplicated refs, our code should be robost to handle
1266   // it.
1267   class DuplicatedXRefIndex : public SymbolIndex {
1268   public:
1269     DuplicatedXRefIndex(const Ref &ReturnedRef) : ReturnedRef(ReturnedRef) {}
1270     bool refs(const RefsRequest &Req,
1271               llvm::function_ref<void(const Ref &)> Callback) const override {
1272       // Return two duplicated refs.
1273       Callback(ReturnedRef);
1274       Callback(ReturnedRef);
1275       return false;
1276     }
1277 
1278     bool fuzzyFind(const FuzzyFindRequest &,
1279                    llvm::function_ref<void(const Symbol &)>) const override {
1280       return false;
1281     }
1282     void lookup(const LookupRequest &,
1283                 llvm::function_ref<void(const Symbol &)>) const override {}
1284 
1285     void relations(const RelationsRequest &,
1286                    llvm::function_ref<void(const SymbolID &, const Symbol &)>)
1287         const override {}
1288     size_t estimateMemoryUsage() const override { return 0; }
1289     Ref ReturnedRef;
1290   } DIndex(XRefInBarCC);
1291   llvm::StringRef NewName = "newName";
1292   auto Results = rename({MainCode.point(),
1293                          NewName,
1294                          AST,
1295                          MainFilePath,
1296                          &DIndex,
1297                          {/*CrossFile=*/true}});
1298   ASSERT_TRUE(bool(Results)) << Results.takeError();
1299   EXPECT_THAT(
1300       applyEdits(std::move(Results->GlobalChanges)),
1301       UnorderedElementsAre(
1302           Pair(Eq(BarPath), Eq(expectedResult(BarCode, NewName))),
1303           Pair(Eq(MainFilePath), Eq(expectedResult(MainCode, NewName)))));
1304 }
1305 
TEST(CrossFileRenameTests,WithUpToDateIndex)1306 TEST(CrossFileRenameTests, WithUpToDateIndex) {
1307   MockCompilationDatabase CDB;
1308   CDB.ExtraClangFlags = {"-xc++"};
1309   // rename is runnning on all "^" points in FooH, and "[[]]" ranges are the
1310   // expected rename occurrences.
1311   struct Case {
1312     llvm::StringRef FooH;
1313     llvm::StringRef FooCC;
1314   } Cases[] = {
1315       {
1316           // classes.
1317           R"cpp(
1318         class [[Fo^o]] {
1319           [[Foo]]();
1320           ~[[Foo]]();
1321         };
1322       )cpp",
1323           R"cpp(
1324         #include "foo.h"
1325         [[Foo]]::[[Foo]]() {}
1326         [[Foo]]::~[[Foo]]() {}
1327 
1328         void func() {
1329           [[Foo]] foo;
1330         }
1331       )cpp",
1332       },
1333       {
1334           // class templates.
1335           R"cpp(
1336         template <typename T>
1337         class [[Foo]] {};
1338         // FIXME: explicit template specializations are not supported due the
1339         // clangd index limitations.
1340         template <>
1341         class Foo<double> {};
1342       )cpp",
1343           R"cpp(
1344         #include "foo.h"
1345         void func() {
1346           [[F^oo]]<int> foo;
1347         }
1348       )cpp",
1349       },
1350       {
1351           // class methods.
1352           R"cpp(
1353         class Foo {
1354           void [[f^oo]]();
1355         };
1356       )cpp",
1357           R"cpp(
1358         #include "foo.h"
1359         void Foo::[[foo]]() {}
1360 
1361         void func(Foo* p) {
1362           p->[[foo]]();
1363         }
1364       )cpp",
1365       },
1366       {
1367           // rename on constructor and destructor.
1368           R"cpp(
1369         class [[Foo]] {
1370           [[^Foo]]();
1371           ~[[Foo^]]();
1372         };
1373       )cpp",
1374           R"cpp(
1375         #include "foo.h"
1376         [[Foo]]::[[Foo]]() {}
1377         [[Foo]]::~[[Foo]]() {}
1378 
1379         void func() {
1380           [[Foo]] foo;
1381         }
1382       )cpp",
1383       },
1384       {
1385           // functions.
1386           R"cpp(
1387         void [[f^oo]]();
1388       )cpp",
1389           R"cpp(
1390         #include "foo.h"
1391         void [[foo]]() {}
1392 
1393         void func() {
1394           [[foo]]();
1395         }
1396       )cpp",
1397       },
1398       {
1399           // typedefs.
1400           R"cpp(
1401       typedef int [[IN^T]];
1402       [[INT]] foo();
1403       )cpp",
1404           R"cpp(
1405         #include "foo.h"
1406         [[INT]] foo() {}
1407       )cpp",
1408       },
1409       {
1410           // usings.
1411           R"cpp(
1412       using [[I^NT]] = int;
1413       [[INT]] foo();
1414       )cpp",
1415           R"cpp(
1416         #include "foo.h"
1417         [[INT]] foo() {}
1418       )cpp",
1419       },
1420       {
1421           // variables.
1422           R"cpp(
1423         static const int [[VA^R]] = 123;
1424       )cpp",
1425           R"cpp(
1426         #include "foo.h"
1427         int s = [[VAR]];
1428       )cpp",
1429       },
1430       {
1431           // scope enums.
1432           R"cpp(
1433       enum class [[K^ind]] { ABC };
1434       )cpp",
1435           R"cpp(
1436         #include "foo.h"
1437         [[Kind]] ff() {
1438           return [[Kind]]::ABC;
1439         }
1440       )cpp",
1441       },
1442       {
1443           // enum constants.
1444           R"cpp(
1445       enum class Kind { [[A^BC]] };
1446       )cpp",
1447           R"cpp(
1448         #include "foo.h"
1449         Kind ff() {
1450           return Kind::[[ABC]];
1451         }
1452       )cpp",
1453       },
1454       {
1455           // Implicit references in macro expansions.
1456           R"cpp(
1457         class [[Fo^o]] {};
1458         #define FooFoo Foo
1459         #define FOO Foo
1460       )cpp",
1461           R"cpp(
1462         #include "foo.h"
1463         void bar() {
1464           [[Foo]] x;
1465           FOO y;
1466           FooFoo z;
1467         }
1468       )cpp",
1469       },
1470   };
1471 
1472   trace::TestTracer Tracer;
1473   for (const auto &T : Cases) {
1474     SCOPED_TRACE(T.FooH);
1475     Annotations FooH(T.FooH);
1476     Annotations FooCC(T.FooCC);
1477     std::string FooHPath = testPath("foo.h");
1478     std::string FooCCPath = testPath("foo.cc");
1479 
1480     MockFS FS;
1481     FS.Files[FooHPath] = std::string(FooH.code());
1482     FS.Files[FooCCPath] = std::string(FooCC.code());
1483 
1484     auto ServerOpts = ClangdServer::optsForTest();
1485     ServerOpts.BuildDynamicSymbolIndex = true;
1486     ClangdServer Server(CDB, FS, ServerOpts);
1487 
1488     // Add all files to clangd server to make sure the dynamic index has been
1489     // built.
1490     runAddDocument(Server, FooHPath, FooH.code());
1491     runAddDocument(Server, FooCCPath, FooCC.code());
1492 
1493     llvm::StringRef NewName = "NewName";
1494     for (const auto &RenamePos : FooH.points()) {
1495       EXPECT_THAT(Tracer.takeMetric("rename_files"), SizeIs(0));
1496       auto FileEditsList = llvm::cantFail(runRename(
1497           Server, FooHPath, RenamePos, NewName, {/*CrossFile=*/true}));
1498       EXPECT_THAT(Tracer.takeMetric("rename_files"), ElementsAre(2));
1499       EXPECT_THAT(
1500           applyEdits(std::move(FileEditsList.GlobalChanges)),
1501           UnorderedElementsAre(
1502               Pair(Eq(FooHPath), Eq(expectedResult(T.FooH, NewName))),
1503               Pair(Eq(FooCCPath), Eq(expectedResult(T.FooCC, NewName)))));
1504     }
1505   }
1506 }
1507 
TEST(CrossFileRenameTests,CrossFileOnLocalSymbol)1508 TEST(CrossFileRenameTests, CrossFileOnLocalSymbol) {
1509   // cross-file rename should work for function-local symbols, even there is no
1510   // index provided.
1511   Annotations Code("void f(int [[abc]]) { [[a^bc]] = 3; }");
1512   auto TU = TestTU::withCode(Code.code());
1513   auto Path = testPath(TU.Filename);
1514   auto AST = TU.build();
1515   llvm::StringRef NewName = "newName";
1516   auto Results = rename({Code.point(), NewName, AST, Path});
1517   ASSERT_TRUE(bool(Results)) << Results.takeError();
1518   EXPECT_THAT(
1519       applyEdits(std::move(Results->GlobalChanges)),
1520       UnorderedElementsAre(Pair(Eq(Path), Eq(expectedResult(Code, NewName)))));
1521 }
1522 
TEST(CrossFileRenameTests,BuildRenameEdits)1523 TEST(CrossFileRenameTests, BuildRenameEdits) {
1524   Annotations Code("[[��]]");
1525   auto LSPRange = Code.range();
1526   llvm::StringRef FilePath = "/test/TestTU.cpp";
1527   llvm::StringRef NewName = "abc";
1528   auto Edit = buildRenameEdit(FilePath, Code.code(), {LSPRange}, NewName);
1529   ASSERT_TRUE(bool(Edit)) << Edit.takeError();
1530   ASSERT_EQ(1UL, Edit->Replacements.size());
1531   EXPECT_EQ(FilePath, Edit->Replacements.begin()->getFilePath());
1532   EXPECT_EQ(4UL, Edit->Replacements.begin()->getLength());
1533 
1534   // Test invalid range.
1535   LSPRange.end = {10, 0}; // out of range
1536   Edit = buildRenameEdit(FilePath, Code.code(), {LSPRange}, NewName);
1537   EXPECT_FALSE(Edit);
1538   EXPECT_THAT(llvm::toString(Edit.takeError()),
1539               testing::HasSubstr("fail to convert"));
1540 
1541   // Normal ascii characters.
1542   Annotations T(R"cpp(
1543     [[range]]
1544               [[range]]
1545       [[range]]
1546   )cpp");
1547   Edit = buildRenameEdit(FilePath, T.code(), T.ranges(), NewName);
1548   ASSERT_TRUE(bool(Edit)) << Edit.takeError();
1549   EXPECT_EQ(applyEdits(FileEdits{{T.code(), std::move(*Edit)}}).front().second,
1550             expectedResult(T, NewName));
1551 }
1552 
TEST(CrossFileRenameTests,adjustRenameRanges)1553 TEST(CrossFileRenameTests, adjustRenameRanges) {
1554   // Ranges in IndexedCode indicate the indexed occurrences;
1555   // ranges in DraftCode indicate the expected mapped result, empty indicates
1556   // we expect no matched result found.
1557   struct {
1558     llvm::StringRef IndexedCode;
1559     llvm::StringRef DraftCode;
1560   } Tests[] = {
1561     {
1562       // both line and column are changed, not a near miss.
1563       R"cpp(
1564         int [[x]] = 0;
1565       )cpp",
1566       R"cpp(
1567         // insert a line.
1568         double x = 0;
1569       )cpp",
1570     },
1571     {
1572       // subset.
1573       R"cpp(
1574         int [[x]] = 0;
1575       )cpp",
1576       R"cpp(
1577         int [[x]] = 0;
1578         {int x = 0; }
1579       )cpp",
1580     },
1581     {
1582       // shift columns.
1583       R"cpp(int [[x]] = 0; void foo(int x);)cpp",
1584       R"cpp(double [[x]] = 0; void foo(double x);)cpp",
1585     },
1586     {
1587       // shift lines.
1588       R"cpp(
1589         int [[x]] = 0;
1590         void foo(int x);
1591       )cpp",
1592       R"cpp(
1593         // insert a line.
1594         int [[x]] = 0;
1595         void foo(int x);
1596       )cpp",
1597     },
1598   };
1599   LangOptions LangOpts;
1600   LangOpts.CPlusPlus = true;
1601   for (const auto &T : Tests) {
1602     SCOPED_TRACE(T.DraftCode);
1603     Annotations Draft(T.DraftCode);
1604     auto ActualRanges = adjustRenameRanges(
1605         Draft.code(), "x", Annotations(T.IndexedCode).ranges(), LangOpts);
1606     if (!ActualRanges)
1607        EXPECT_THAT(Draft.ranges(), testing::IsEmpty());
1608     else
1609       EXPECT_THAT(Draft.ranges(),
1610                   testing::UnorderedElementsAreArray(*ActualRanges));
1611   }
1612 }
1613 
TEST(RangePatchingHeuristic,GetMappedRanges)1614 TEST(RangePatchingHeuristic, GetMappedRanges) {
1615   // ^ in LexedCode marks the ranges we expect to be mapped; no ^ indicates
1616   // there are no mapped ranges.
1617   struct {
1618     llvm::StringRef IndexedCode;
1619     llvm::StringRef LexedCode;
1620   } Tests[] = {
1621     {
1622       // no lexed ranges.
1623       "[[]]",
1624       "",
1625     },
1626     {
1627       // both line and column are changed, not a near miss.
1628       R"([[]])",
1629       R"(
1630         [[]]
1631       )",
1632     },
1633     {
1634       // subset.
1635       "[[]]",
1636       "^[[]]  [[]]"
1637     },
1638     {
1639       // shift columns.
1640       "[[]]   [[]]",
1641       "  ^[[]]   ^[[]]  [[]]"
1642     },
1643     {
1644       R"(
1645         [[]]
1646 
1647         [[]] [[]]
1648       )",
1649       R"(
1650         // insert a line
1651         ^[[]]
1652 
1653         ^[[]] ^[[]]
1654       )",
1655     },
1656     {
1657       R"(
1658         [[]]
1659 
1660         [[]] [[]]
1661       )",
1662       R"(
1663         // insert a line
1664         ^[[]]
1665           ^[[]]  ^[[]] // column is shifted.
1666       )",
1667     },
1668     {
1669       R"(
1670         [[]]
1671 
1672         [[]] [[]]
1673       )",
1674       R"(
1675         // insert a line
1676         [[]]
1677 
1678           [[]]  [[]] // not mapped (both line and column are changed).
1679       )",
1680     },
1681     {
1682       R"(
1683         [[]]
1684                 [[]]
1685 
1686                    [[]]
1687                   [[]]
1688 
1689         }
1690       )",
1691       R"(
1692         // insert a new line
1693         ^[[]]
1694                 ^[[]]
1695              [[]] // additional range
1696                    ^[[]]
1697                   ^[[]]
1698             [[]] // additional range
1699       )",
1700     },
1701     {
1702       // non-distinct result (two best results), not a near miss
1703       R"(
1704         [[]]
1705             [[]]
1706             [[]]
1707       )",
1708       R"(
1709         [[]]
1710         [[]]
1711             [[]]
1712             [[]]
1713       )",
1714     }
1715   };
1716   for (const auto &T : Tests) {
1717     SCOPED_TRACE(T.IndexedCode);
1718     auto Lexed = Annotations(T.LexedCode);
1719     auto LexedRanges = Lexed.ranges();
1720     std::vector<Range> ExpectedMatches;
1721     for (auto P : Lexed.points()) {
1722       auto Match = llvm::find_if(LexedRanges, [&P](const Range& R) {
1723         return R.start == P;
1724       });
1725       ASSERT_NE(Match, LexedRanges.end());
1726       ExpectedMatches.push_back(*Match);
1727     }
1728 
1729     auto Mapped =
1730         getMappedRanges(Annotations(T.IndexedCode).ranges(), LexedRanges);
1731     if (!Mapped)
1732       EXPECT_THAT(ExpectedMatches, IsEmpty());
1733     else
1734       EXPECT_THAT(ExpectedMatches, UnorderedElementsAreArray(*Mapped));
1735   }
1736 }
1737 
TEST(CrossFileRenameTests,adjustmentCost)1738 TEST(CrossFileRenameTests, adjustmentCost) {
1739   struct {
1740     llvm::StringRef RangeCode;
1741     size_t ExpectedCost;
1742   } Tests[] = {
1743     {
1744       R"(
1745         $idx[[]]$lex[[]] // diff: 0
1746       )",
1747       0,
1748     },
1749     {
1750       R"(
1751         $idx[[]]
1752         $lex[[]] // line diff: +1
1753                        $idx[[]]
1754                        $lex[[]] // line diff: +1
1755         $idx[[]]
1756         $lex[[]] // line diff: +1
1757 
1758           $idx[[]]
1759 
1760           $lex[[]] // line diff: +2
1761       )",
1762       1 + 1
1763     },
1764     {
1765        R"(
1766         $idx[[]]
1767         $lex[[]] // line diff: +1
1768                        $idx[[]]
1769 
1770                        $lex[[]] // line diff: +2
1771         $idx[[]]
1772 
1773 
1774         $lex[[]] // line diff: +3
1775       )",
1776       1 + 1 + 1
1777     },
1778     {
1779        R"(
1780         $idx[[]]
1781 
1782 
1783         $lex[[]] // line diff: +3
1784                        $idx[[]]
1785 
1786                        $lex[[]] // line diff: +2
1787         $idx[[]]
1788         $lex[[]] // line diff: +1
1789       )",
1790       3 + 1 + 1
1791     },
1792     {
1793       R"(
1794         $idx[[]]
1795         $lex[[]] // line diff: +1
1796                        $lex[[]] // line diff: -2
1797 
1798                        $idx[[]]
1799         $idx[[]]
1800 
1801 
1802         $lex[[]] // line diff: +3
1803       )",
1804       1 + 3 + 5
1805     },
1806     {
1807       R"(
1808                        $idx[[]] $lex[[]] // column diff: +1
1809         $idx[[]]$lex[[]] // diff: 0
1810       )",
1811       1
1812     },
1813     {
1814       R"(
1815         $idx[[]]
1816         $lex[[]] // diff: +1
1817                        $idx[[]] $lex[[]] // column diff: +1
1818         $idx[[]]$lex[[]] // diff: 0
1819       )",
1820       1 + 1 + 1
1821     },
1822     {
1823       R"(
1824         $idx[[]] $lex[[]] // column diff: +1
1825       )",
1826       1
1827     },
1828     {
1829       R"(
1830         // column diffs: +1, +2, +3
1831         $idx[[]] $lex[[]] $idx[[]]  $lex[[]] $idx[[]]   $lex[[]]
1832       )",
1833       1 + 1 + 1,
1834     },
1835   };
1836   for (const auto &T : Tests) {
1837     SCOPED_TRACE(T.RangeCode);
1838     Annotations C(T.RangeCode);
1839     std::vector<size_t> MappedIndex;
1840     for (size_t I = 0; I < C.ranges("lex").size(); ++I)
1841       MappedIndex.push_back(I);
1842     EXPECT_EQ(renameRangeAdjustmentCost(C.ranges("idx"), C.ranges("lex"),
1843                                         MappedIndex),
1844               T.ExpectedCost);
1845   }
1846 }
1847 
1848 } // namespace
1849 } // namespace clangd
1850 } // namespace clang
1851