16 #include "llvm/ADT/ArrayRef.h"
17 #include "llvm/ADT/STLExtras.h"
18 #include "llvm/ADT/StringRef.h"
19 #include "llvm/Support/Error.h"
20 #include "llvm/Support/ScopedPrinter.h"
21 #include "gmock/gmock.h"
28 using testing::IsEmpty;
29 using testing::SizeIs;
31 MATCHER_P(LineNumber, L,
"") {
return arg.Line == L; }
32 MATCHER(EmptyHighlightings,
"") {
return arg.Tokens.empty(); }
34 std::vector<HighlightingToken>
36 std::vector<HighlightingToken> Tokens(Ranges.size());
37 for (
int I = 0, End = Ranges.size(); I < End; ++I) {
38 Tokens[I].R = Ranges[I];
39 Tokens[I].Kind =
Kind;
45 std::vector<HighlightingToken> getExpectedTokens(Annotations &Test) {
46 static const std::map<HighlightingKind, std::string> KindToString{
66 std::vector<HighlightingToken> ExpectedTokens;
67 for (
const auto &KindString : KindToString) {
68 std::vector<HighlightingToken> Toks = makeHighlightingTokens(
69 Test.ranges(KindString.second), KindString.first);
70 ExpectedTokens.insert(ExpectedTokens.end(), Toks.begin(), Toks.end());
72 llvm::sort(ExpectedTokens);
73 return ExpectedTokens;
81 std::string annotate(llvm::StringRef Input,
82 llvm::ArrayRef<HighlightingToken> Tokens) {
83 assert(std::is_sorted(
84 Tokens.begin(), Tokens.end(),
85 [](
const HighlightingToken &L,
const HighlightingToken &R) {
86 return L.R.start < R.R.start;
90 unsigned NextChar = 0;
91 for (
auto &T : Tokens) {
94 assert(StartOffset <= EndOffset);
95 assert(NextChar <= StartOffset);
97 Result += Input.substr(NextChar, StartOffset - NextChar);
98 Result += std::string(
99 llvm::formatv(
"${0}[[{1}]]", T.Kind,
100 Input.substr(StartOffset, EndOffset - StartOffset)));
101 NextChar = EndOffset;
103 Result += Input.substr(NextChar);
107 void checkHighlightings(llvm::StringRef
Code,
108 std::vector<std::pair< llvm::StringRef,
110 AdditionalFiles = {}) {
111 Annotations Test(
Code);
113 TU.Code = std::string(Test.code());
117 TU.ExtraArgs.push_back(
"-fno-delayed-template-parsing");
118 TU.ExtraArgs.push_back(
"-std=c++20");
120 for (
auto File : AdditionalFiles)
121 TU.AdditionalFiles.insert({File.first, std::string(File.second)});
122 auto AST = TU.
build();
132 void checkDiffedHighlights(llvm::StringRef OldCode, llvm::StringRef NewCode) {
133 Annotations OldTest(OldCode);
134 Annotations NewTest(NewCode);
135 std::vector<HighlightingToken> OldTokens = getExpectedTokens(OldTest);
136 std::vector<HighlightingToken> NewTokens = getExpectedTokens(NewTest);
138 llvm::DenseMap<int, std::vector<HighlightingToken>> ExpectedLines;
139 for (
const Position &Point : NewTest.points()) {
140 ExpectedLines[Point.line];
143 std::vector<LineHighlightings> ExpectedLinePairHighlighting;
144 for (
const HighlightingToken &Token : NewTokens) {
145 auto It = ExpectedLines.find(Token.R.start.line);
146 if (It != ExpectedLines.end())
147 It->second.push_back(Token);
149 for (
auto &LineTokens : ExpectedLines)
150 ExpectedLinePairHighlighting.push_back(
151 {LineTokens.first, LineTokens.second,
false});
153 std::vector<LineHighlightings> ActualDiffed =
155 EXPECT_THAT(ActualDiffed,
156 testing::UnorderedElementsAreArray(ExpectedLinePairHighlighting))
160 TEST(SemanticHighlighting, GetsCorrectTokens) {
161 const char *TestCases[] = {
163 struct $Class[[AS]] {
164 double $Field[[SomeMember]];
168 void $Function[[foo]](int $Parameter[[A]], $Class[[AS]] $Parameter[[As]]) {
169 $Primitive[[auto]] $LocalVariable[[VeryLongVariableName]] = 12312;
170 $Class[[AS]] $LocalVariable[[AA]];
171 $Primitive[[auto]] $LocalVariable[[L]] = $LocalVariable[[AA]].$Field[[SomeMember]] + $Parameter[[A]];
172 auto $LocalVariable[[FN]] = [ $LocalVariable[[AA]]](int $Parameter[[A]]) -> void {};
173 $LocalVariable[[FN]](12312);
177 void $Function[[foo]](int);
178 void $Function[[Gah]]();
179 void $Function[[foo]]() {
180 auto $LocalVariable[[Bou]] = $Function[[Gah]];
183 void $Method[[abc]]();
187 namespace $Namespace[[abc]] {
188 template<typename $TemplateParameter[[T]]>
190 $TemplateParameter[[T]] $Field[[t]];
193 template<typename $TemplateParameter[[T]]>
194 struct $Class[[C]] : $Namespace[[abc]]::$Class[[A]]<$TemplateParameter[[T]]> {
195 typename $TemplateParameter[[T]]::$DependentType[[A]]* $Field[[D]];
197 $Namespace[[abc]]::$Class[[A]]<int> $Variable[[AA]];
198 typedef $Namespace[[abc]]::$Class[[A]]<int> $Class[[AAA]];
202 void operator<<($Class[[B]]);
203 $Class[[AAA]] $Field[[AA]];
205 $Class[[B]]::$Class[[B]]() {}
206 $Class[[B]]::~$Class[[B]]() {}
207 void $Function[[f]] () {
208 $Class[[B]] $LocalVariable[[BB]] = $Class[[B]]();
209 $LocalVariable[[BB]].~$Class[[B]]();
214 enum class $Enum[[E]] {
222 $Enum[[E]] $Field[[EEE]];
223 $Enum[[EE]] $Field[[EEEE]];
225 int $Variable[[I]] = $EnumConstant[[Hi]];
226 $Enum[[E]] $Variable[[L]] = $Enum[[E]]::$EnumConstant[[B]];
229 namespace $Namespace[[abc]] {
231 namespace $Namespace[[bcd]] {
232 struct $Class[[A]] {};
233 namespace $Namespace[[cde]] {
235 enum class $Enum[[B]] {
242 using namespace $Namespace[[abc]]::$Namespace[[bcd]];
243 namespace $Namespace[[vwz]] =
244 $Namespace[[abc]]::$Namespace[[bcd]]::$Namespace[[cde]];
245 $Namespace[[abc]]::$Namespace[[bcd]]::$Class[[A]] $Variable[[AA]];
246 $Namespace[[vwz]]::$Class[[A]]::$Enum[[B]] $Variable[[AAA]] =
247 $Namespace[[vwz]]::$Class[[A]]::$Enum[[B]]::$EnumConstant[[Hi]];
248 ::$Namespace[[vwz]]::$Class[[A]] $Variable[[B]];
249 ::$Namespace[[abc]]::$Namespace[[bcd]]::$Class[[A]] $Variable[[BB]];
257 $Class[[D]] $Field[[E]];
258 static double $StaticField[[S]];
259 static void $StaticMethod[[bar]]() {}
260 void $Method[[foo]]() {
262 this->$Field[[B]] = 156;
263 this->$Method[[foo]]();
265 $StaticMethod[[bar]]();
266 $StaticField[[S]] = 90.1;
269 void $Function[[foo]]() {
270 $Class[[A]] $LocalVariable[[AA]];
271 $LocalVariable[[AA]].$Field[[B]] += 2;
272 $LocalVariable[[AA]].$Method[[foo]]();
273 $LocalVariable[[AA]].$Field[[E]].$Field[[C]];
274 $Class[[A]]::$StaticField[[S]] = 90;
278 struct $Class[[AA]] {
282 $Class[[AA]] $Variable[[A]]{$Variable[[B]]};
285 namespace $Namespace[[a]] {
286 struct $Class[[A]] {};
287 typedef char $Primitive[[C]];
289 typedef $Namespace[[a]]::$Class[[A]] $Class[[B]];
290 using $Class[[BB]] = $Namespace[[a]]::$Class[[A]];
291 enum class $Enum[[E]] {};
292 typedef $Enum[[E]] $Enum[[C]];
293 typedef $Enum[[C]] $Enum[[CC]];
294 using $Enum[[CD]] = $Enum[[CC]];
295 $Enum[[CC]] $Function[[f]]($Class[[B]]);
296 $Enum[[CD]] $Function[[f]]($Class[[BB]]);
297 typedef $Namespace[[a]]::$Primitive[[C]] $Primitive[[PC]];
298 typedef float $Primitive[[F]];
301 template<typename $TemplateParameter[[T]], typename = void>
303 $TemplateParameter[[T]] $Field[[AA]];
304 $TemplateParameter[[T]] $Method[[foo]]();
306 template<class $TemplateParameter[[TT]]>
308 $Class[[A]]<$TemplateParameter[[TT]]> $Field[[AA]];
310 template<class $TemplateParameter[[TT]], class $TemplateParameter[[GG]]>
311 class $Class[[BB]] {};
312 template<class $TemplateParameter[[T]]>
313 class $Class[[BB]]<$TemplateParameter[[T]], int> {};
314 template<class $TemplateParameter[[T]]>
315 class $Class[[BB]]<$TemplateParameter[[T]], $TemplateParameter[[T]]*> {};
317 template<template<class> class $TemplateParameter[[T]], class $TemplateParameter[[C]]>
318 $TemplateParameter[[T]]<$TemplateParameter[[C]]> $Function[[f]]();
321 class $Class[[Foo]] {};
323 template<typename $TemplateParameter[[T]]>
324 void $Function[[foo]]($TemplateParameter[[T]] ...);
327 template <class $TemplateParameter[[T]]>
328 struct $Class[[Tmpl]] {$TemplateParameter[[T]] $Field[[x]] = 0;};
329 extern template struct $Class[[Tmpl]]<float>;
330 template struct $Class[[Tmpl]]<double>;
336 class $Class[[Foo]] {};
337 struct $Class[[Bar]] {
338 explicit operator $Class[[Foo]]*() const;
339 explicit operator int() const;
340 operator $Class[[Foo]]();
342 void $Function[[f]]() {
343 $Class[[Bar]] $LocalVariable[[B]];
344 $Class[[Foo]] $LocalVariable[[F]] = $LocalVariable[[B]];
345 $Class[[Foo]] *$LocalVariable[[FP]] = ($Class[[Foo]]*)$LocalVariable[[B]];
346 int $LocalVariable[[I]] = (int)$LocalVariable[[B]];
350 struct $Class[[B]] {};
352 $Class[[B]] $Field[[BB]];
353 $Class[[A]] &operator=($Class[[A]] &&$Parameter[[O]]);
356 $Class[[A]] &$Class[[A]]::operator=($Class[[A]] &&$Parameter[[O]]) = default;
362 class $Class[[Foo]] {};
363 class $Class[[Bar]] {
365 $Class[[Foo]] $Field[[Fo]];
366 $Enum[[En]] $Field[[E]];
368 $Class[[Bar]] ($Class[[Foo]] $Parameter[[F]],
369 $Enum[[En]] $Parameter[[E]])
370 : $Field[[Fo]] ($Parameter[[F]]), $Field[[E]] ($Parameter[[E]]),
373 class $Class[[Bar2]] : public $Class[[Bar]] {
374 $Class[[Bar2]]() : $Class[[Bar]]($Class[[Foo]](), $EnumConstant[[EC]]) {}
381 class $Class[[Foo]] {};
382 $Enum[[auto]] $Variable[[AE]] = $Enum[[E]]::$EnumConstant[[E]];
383 $Class[[auto]] $Variable[[AF]] = $Class[[Foo]]();
384 $Class[[decltype]](auto) $Variable[[AF2]] = $Class[[Foo]]();
385 $Class[[auto]] *$Variable[[AFP]] = &$Variable[[AF]];
386 $Enum[[auto]] &$Variable[[AER]] = $Variable[[AE]];
387 $Primitive[[auto]] $Variable[[Form]] = 10.2 + 2 * 4;
388 $Primitive[[decltype]]($Variable[[Form]]) $Variable[[F]] = 10;
389 auto $Variable[[Fun]] = []()->void{};
392 class $Class[[G]] {};
393 template<$Class[[G]] *$TemplateParameter[[U]]>
394 class $Class[[GP]] {};
395 template<$Class[[G]] &$TemplateParameter[[U]]>
396 class $Class[[GR]] {};
397 template<int *$TemplateParameter[[U]]>
399 void $Method[[f]]() {
400 *$TemplateParameter[[U]] += 5;
403 template<unsigned $TemplateParameter[[U]] = 2>
404 class $Class[[Foo]] {
405 void $Method[[f]]() {
406 for(int $LocalVariable[[I]] = 0;
407 $LocalVariable[[I]] < $TemplateParameter[[U]];) {}
411 $Class[[G]] $Variable[[L]];
412 void $Function[[f]]() {
413 $Class[[Foo]]<123> $LocalVariable[[F]];
414 $Class[[GP]]<&$Variable[[L]]> $LocalVariable[[LL]];
415 $Class[[GR]]<$Variable[[L]]> $LocalVariable[[LLL]];
419 template<typename $TemplateParameter[[T]],
420 void ($TemplateParameter[[T]]::*$TemplateParameter[[method]])(int)>
423 $TemplateParameter[[T]] *$Parameter[[O]]) {
424 ($Parameter[[O]]->*$TemplateParameter[[method]])(10);
428 void $Method[[f]](int);
430 template<void (*$TemplateParameter[[Func]])()>
432 void $Method[[f]]() {
433 (*$TemplateParameter[[Func]])();
437 void $Function[[foo]]() {
438 $Class[[F]] $LocalVariable[[FF]];
439 $Class[[G]]<$Class[[F]], &$Class[[F]]::$Method[[f]]> $LocalVariable[[GG]];
440 $LocalVariable[[GG]].$Method[[foo]](&$LocalVariable[[FF]]);
441 $Class[[A]]<$Function[[foo]]> $LocalVariable[[AA]];
447 #define $Macro[[DEF_MULTIPLE]](X) namespace X { class X { int X; }; }
448 #define $Macro[[DEF_CLASS]](T) class T {};
450 $Macro[[DEF_MULTIPLE]](XYZ);
451 $Macro[[DEF_MULTIPLE]](XYZW);
452 $Macro[[DEF_CLASS]]($Class[[A]])
453 #define $Macro[[MACRO_CONCAT]](X, V, T) T foo##X = V
454 #define $Macro[[DEF_VAR]](X, V) int X = V
455 #define $Macro[[DEF_VAR_T]](T, X, V) T X = V
456 #define $Macro[[DEF_VAR_REV]](V, X) DEF_VAR(X, V)
457 #define $Macro[[CPY]](X) X
458 #define $Macro[[DEF_VAR_TYPE]](X, Y) X Y
459 #define $Macro[[SOME_NAME]] variable
460 #define $Macro[[SOME_NAME_SET]] variable2 = 123
461 #define $Macro[[INC_VAR]](X) X += 2
462 void $Function[[foo]]() {
463 $Macro[[DEF_VAR]]($LocalVariable[[X]], 123);
464 $Macro[[DEF_VAR_REV]](908, $LocalVariable[[XY]]);
465 int $Macro[[CPY]]( $LocalVariable[[XX]] );
466 $Macro[[DEF_VAR_TYPE]]($Class[[A]], $LocalVariable[[AA]]);
467 double $Macro[[SOME_NAME]];
468 int $Macro[[SOME_NAME_SET]];
469 $LocalVariable[[variable]] = 20.1;
470 $Macro[[MACRO_CONCAT]](var, 2, float);
471 $Macro[[DEF_VAR_T]]($Class[[A]], $Macro[[CPY]](
472 $Macro[[CPY]]($LocalVariable[[Nested]])),
473 $Macro[[CPY]]($Class[[A]]()));
474 $Macro[[INC_VAR]]($LocalVariable[[variable]]);
476 void $Macro[[SOME_NAME]]();
477 $Macro[[DEF_VAR]]($Variable[[MMMMM]], 567);
478 $Macro[[DEF_VAR_REV]](756, $Variable[[AB]]);
480 #define $Macro[[CALL_FN]](F) F();
481 #define $Macro[[DEF_FN]](F) void F ()
482 $Macro[[DEF_FN]]($Function[[g]]) {
483 $Macro[[CALL_FN]]($Function[[foo]]);
487 #define $Macro[[fail]](expr) expr
488 #define $Macro[[assert]](COND) if (!(COND)) { fail("assertion failed" #COND); }
492 int $Function[[f]]();
493 void $Function[[foo]]() {
494 $Macro[[assert]]($Variable[[x]] != $Variable[[y]]);
495 $Macro[[assert]]($Variable[[x]] != $Function[[f]]());
500 #ifndef $Macro[[name]]
501 #define $Macro[[name]]
504 #define $Macro[[test]]
505 #undef $Macro[[test]]
506 $InactiveCode[[]] #ifdef $Macro[[test]]
507 $InactiveCode[[]] #endif
509 $InactiveCode[[]] #if defined($Macro[[test]])
510 $InactiveCode[[]] #endif
514 float $Field[[Value]];
515 $Class[[S]] *$Field[[Next]];
517 $Class[[S]] $Variable[[Global]][2] = {$Class[[S]](), $Class[[S]]()};
518 void $Function[[f]]($Class[[S]] $Parameter[[P]]) {
519 int $LocalVariable[[A]][2] = {1,2};
520 auto [$Variable[[B1]], $Variable[[B2]]] = $LocalVariable[[A]];
521 auto [$Variable[[G1]], $Variable[[G2]]] = $Variable[[Global]];
522 $Class[[auto]] [$Variable[[P1]], $Variable[[P2]]] = $Parameter[[P]];
523 // Highlights references to BindingDecls.
528 template<class $TemplateParameter[[T]]>
530 using $TemplateParameter[[TemplateParam1]] = $TemplateParameter[[T]];
531 typedef $TemplateParameter[[T]] $TemplateParameter[[TemplateParam2]];
532 using $Primitive[[IntType]] = int;
534 using $Typedef[[Pointer]] = $TemplateParameter[[T]] *;
535 using $Typedef[[LVReference]] = $TemplateParameter[[T]] &;
536 using $Typedef[[RVReference]] = $TemplateParameter[[T]]&&;
537 using $Typedef[[Array]] = $TemplateParameter[[T]]*[3];
538 using $Typedef[[MemberPointer]] = int ($Class[[A]]::*)(int);
540 // Use various previously defined typedefs in a function type.
541 void $Method[[func]](
542 $Typedef[[Pointer]], $Typedef[[LVReference]], $Typedef[[RVReference]],
543 $Typedef[[Array]], $Typedef[[MemberPointer]]);
547 template <class $TemplateParameter[[T]]>
548 void $Function[[phase1]]($TemplateParameter[[T]]);
549 template <class $TemplateParameter[[T]]>
550 void $Function[[foo]]($TemplateParameter[[T]] $Parameter[[P]]) {
551 $Function[[phase1]]($Parameter[[P]]);
552 $DependentName[[phase2]]($Parameter[[P]]);
557 template <class $TemplateParameter[[T]]>
558 void $Method[[bar]]($TemplateParameter[[T]]);
561 template <class $TemplateParameter[[U]]>
562 void $Function[[foo]]($TemplateParameter[[U]] $Parameter[[P]]) {
563 $Class[[A]]().$Method[[bar]]($Parameter[[P]]);
568 template <class $TemplateParameter[[T]]>
569 static void $StaticMethod[[foo]]($TemplateParameter[[T]]);
572 template <class $TemplateParameter[[T]]>
574 void $Method[[bar]]() {
575 $Class[[A]]::$StaticMethod[[foo]]($TemplateParameter[[T]]());
580 template <class $TemplateParameter[[T]]>
581 void $Function[[foo]](typename $TemplateParameter[[T]]::$DependentType[[Type]]
582 = $TemplateParameter[[T]]::$DependentName[[val]]);
585 template <class $TemplateParameter[[T]]>
586 void $Function[[foo]]($TemplateParameter[[T]] $Parameter[[P]]) {
587 $Parameter[[P]].$DependentName[[Field]];
591 template <class $TemplateParameter[[T]]>
593 int $Method[[foo]]() {
594 return $TemplateParameter[[T]]::$DependentName[[Field]];
600 void $Function[[foo]]();
601 using ::$Function[[foo]];
605 template <template <class> class $TemplateParameter[[TT]],
606 template <class> class ...$TemplateParameter[[TTs]]>
607 struct $Class[[Foo]] {
608 $Class[[Foo]]<$TemplateParameter[[TT]], $TemplateParameter[[TTs]]...>
614 // Code in the preamble.
615 // Inactive lines get an empty InactiveCode token at the beginning.
616 $InactiveCode[[]] #ifdef $Macro[[test]]
617 $InactiveCode[[]] #endif
619 // A declaration to cause the preamble to end.
620 int $Variable[[EndPreamble]];
622 // Code after the preamble.
623 // Code inside inactive blocks does not get regular highlightings
624 // because it's not part of the AST.
625 $InactiveCode[[]] #ifdef $Macro[[test]]
626 $InactiveCode[[]] int Inactive2;
627 $InactiveCode[[]] #endif
629 #ifndef $Macro[[test]]
630 int $Variable[[Active1]];
633 $InactiveCode[[]] #ifdef $Macro[[test]]
634 $InactiveCode[[]] int Inactive3;
635 $InactiveCode[[]] #else
636 int $Variable[[Active2]];
641 template <typename... $TemplateParameter[[Elements]]>
642 struct $Class[[TupleSize]] {
643 static const int $StaticField[[size]] =
644 sizeof...($TemplateParameter[[Elements]]);
649 template <typename $TemplateParameter[[T]]>
650 struct $Class[[Waldo]] {
651 using $Typedef[[Location1]] = typename $TemplateParameter[[T]]
652 ::$DependentType[[Resolver]]::$DependentType[[Location]];
653 using $Typedef[[Location2]] = typename $TemplateParameter[[T]]
654 ::template $DependentType[[Resolver]]<$TemplateParameter[[T]]>
655 ::$DependentType[[Location]];
656 using $Typedef[[Location3]] = typename $TemplateParameter[[T]]
657 ::$DependentType[[Resolver]]
658 ::template $DependentType[[Location]]<$TemplateParameter[[T]]>;
659 static const int $StaticField[[Value]] = $TemplateParameter[[T]]
660 ::$DependentType[[Resolver]]::$DependentName[[Value]];
666 struct $Class[[Foo]] {
668 void $Method[[bar]]() {
669 $Class[[Foo]]().$Field[[Waldo]];
671 template <typename $TemplateParameter[[U]]>
672 void $Method[[bar1]]() {
673 $Class[[Foo]]<$TemplateParameter[[U]]>().$Field[[Waldo]];
679 template <typename $TemplateParameter[[T]]>
680 concept $Concept[[Fooable]] =
681 requires($TemplateParameter[[T]] $Parameter[[F]]) {
682 $Parameter[[F]].$DependentName[[foo]]();
684 template <typename $TemplateParameter[[T]]>
685 requires $Concept[[Fooable]]<$TemplateParameter[[T]]>
686 void $Function[[bar]]($TemplateParameter[[T]] $Parameter[[F]]) {
687 $Parameter[[F]].$DependentName[[foo]]();
690 for (
const auto &TestCase : TestCases) {
691 checkHighlightings(TestCase);
694 checkHighlightings(R
"cpp(
705 checkHighlightings(R
"cpp(
711 #define DXYZ(X) class X {};
712 #define DXYZ_Y(Y) DXYZ(x##Y)
713 #define DEFINE(X) int X;
714 #define DEFINE_Y DEFINE(Y)
718 TEST(SemanticHighlighting, GeneratesHighlightsWhenFileChange) {
719 class HighlightingsCounter :
public ClangdServer::Callbacks {
721 std::atomic<int> Count = {0};
723 void onHighlightingsReady(
725 std::vector<HighlightingToken> Highlightings)
override {
734 MockCompilationDatabase MCD;
737 Server.addDocument(FooCpp,
"int a;");
738 ASSERT_TRUE(Server.blockUntilIdleForTest()) <<
"Waiting for server";
743 std::vector<HighlightingToken> tokens(llvm::StringRef MarkedText) {
744 Annotations A(MarkedText);
745 std::vector<HighlightingToken>
Results;
746 for (
const Range& R : A.ranges())
747 Results.push_back({HighlightingKind::Variable, R});
750 for (
const Range& R : A.ranges(llvm::to_string(
Kind)))
761 $Function[[big]] [[bang]]
764 ASSERT_THAT(Results, SizeIs(3));
766 EXPECT_EQ(
Results[0].deltaLine, 1u);
767 EXPECT_EQ(
Results[0].deltaStart, 1u);
768 EXPECT_EQ(
Results[0].length, 4u);
771 EXPECT_EQ(
Results[1].deltaLine, 2u);
772 EXPECT_EQ(
Results[1].deltaStart, 4u);
773 EXPECT_EQ(
Results[1].length, 3u);
776 EXPECT_EQ(
Results[2].deltaLine, 0u);
777 EXPECT_EQ(
Results[2].deltaStart, 4u);
778 EXPECT_EQ(
Results[2].length, 4u);
781 TEST(SemanticHighlighting, diffSemanticTokens) {
783 [[foo]] [[bar]] [[baz]]
784 [[one]] [[two]] [[three]]
786 EXPECT_THAT(diffTokens(Before, Before), IsEmpty());
789 [[foo]] [[hello]] [[world]] [[baz]]
790 [[one]] [[two]] [[three]]
795 ASSERT_THAT(Diff, SizeIs(1));
796 EXPECT_EQ(1u, Diff.front().startToken);
797 EXPECT_EQ(2u, Diff.front().deleteTokens);
798 ASSERT_THAT(Diff.front().tokens, SizeIs(3));
800 EXPECT_EQ(0u, Diff.front().tokens[0].deltaLine);
801 EXPECT_EQ(4u, Diff.front().tokens[0].deltaStart);
802 EXPECT_EQ(5u, Diff.front().tokens[0].length);
804 EXPECT_EQ(0u, Diff.front().tokens[1].deltaLine);
805 EXPECT_EQ(6u, Diff.front().tokens[1].deltaStart);
806 EXPECT_EQ(5u, Diff.front().tokens[1].length);
808 EXPECT_EQ(0u, Diff.front().tokens[2].deltaLine);
809 EXPECT_EQ(6u, Diff.front().tokens[2].deltaStart);
810 EXPECT_EQ(3u, Diff.front().tokens[2].length);
814 auto CreatePosition = [](
int Line,
int Character) -> Position {
821 std::vector<LineHighlightings> Tokens{
824 Range{CreatePosition(3, 8), CreatePosition(3, 12)}},
826 Range{CreatePosition(3, 4), CreatePosition(3, 7)}}},
830 Range{CreatePosition(1, 1), CreatePosition(1, 5)}}},
832 std::vector<TheiaSemanticHighlightingInformation> ActualResults =
834 std::vector<TheiaSemanticHighlightingInformation> ExpectedResults = {
835 {3,
"AAAACAAEAAAAAAAEAAMAAw=="}, {1,
"AAAAAQAEAAA="}};
836 EXPECT_EQ(ActualResults, ExpectedResults);
839 TEST(SemanticHighlighting, HighlightingDiffer) {
841 llvm::StringRef OldCode;
842 llvm::StringRef NewCode;
859 $Class[[C]] $Variable[[V]] $Field[[F]]
865 $Class[[C]] $Variable[[V]] $Field[[F]]
884 $Class[[C]] $Variable[[V]] $Field[[F]]
890 $Class[[C]] $Variable[[V]] $Field[[F]]
926 for (
const auto &Test : TestCases)
927 checkDiffedHighlights(Test.OldCode, Test.NewCode);
930 TEST(SemanticHighlighting, DiffBeyondTheEndOfFile) {
931 llvm::StringRef OldCode =
938 llvm::StringRef NewCode =
940 $Class[[A]] // line 1
941 $Variable[[A]] // line 2
944 Annotations OldTest(OldCode);
945 Annotations NewTest(NewCode);
946 std::vector<HighlightingToken> OldTokens = getExpectedTokens(OldTest);
947 std::vector<HighlightingToken> NewTokens = getExpectedTokens(NewTest);
950 EXPECT_THAT(ActualDiff,
951 testing::UnorderedElementsAre(
952 testing::AllOf(LineNumber(3), EmptyHighlightings()),
953 testing::AllOf(LineNumber(4), EmptyHighlightings())));