1 | //==- SemanticHighlightingTests.cpp - SemanticHighlighting tests-*- 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 "Config.h" |
11 | #include "Protocol.h" |
12 | #include "SemanticHighlighting.h" |
13 | #include "SourceCode.h" |
14 | #include "TestTU.h" |
15 | #include "llvm/ADT/ArrayRef.h" |
16 | #include "llvm/ADT/STLExtras.h" |
17 | #include "llvm/ADT/StringRef.h" |
18 | #include "llvm/Support/Error.h" |
19 | #include "llvm/Support/ScopedPrinter.h" |
20 | #include "llvm/Support/raw_ostream.h" |
21 | #include "gmock/gmock.h" |
22 | #include <algorithm> |
23 | |
24 | namespace clang { |
25 | namespace clangd { |
26 | namespace { |
27 | |
28 | using testing::IsEmpty; |
29 | using testing::SizeIs; |
30 | |
31 | /// Annotates the input code with provided semantic highlightings. Results look |
32 | /// something like: |
33 | /// class $Class[[X]] { |
34 | /// $Primitive[[int]] $Field[[a]] = 0; |
35 | /// }; |
36 | std::string annotate(llvm::StringRef Input, |
37 | llvm::ArrayRef<HighlightingToken> Tokens) { |
38 | assert(llvm::is_sorted( |
39 | Tokens, [](const HighlightingToken &L, const HighlightingToken &R) { |
40 | return L.R.start < R.R.start; |
41 | })); |
42 | |
43 | std::string Buf; |
44 | llvm::raw_string_ostream OS(Buf); |
45 | unsigned NextChar = 0; |
46 | for (auto &T : Tokens) { |
47 | unsigned StartOffset = llvm::cantFail(ValOrErr: positionToOffset(Code: Input, P: T.R.start)); |
48 | unsigned EndOffset = llvm::cantFail(ValOrErr: positionToOffset(Code: Input, P: T.R.end)); |
49 | assert(StartOffset <= EndOffset); |
50 | assert(NextChar <= StartOffset); |
51 | |
52 | bool hasDef = |
53 | T.Modifiers & (1 << uint32_t(HighlightingModifier::Definition)); |
54 | bool hasDecl = |
55 | T.Modifiers & (1 << uint32_t(HighlightingModifier::Declaration)); |
56 | EXPECT_TRUE(!hasDef || hasDecl); |
57 | |
58 | OS << Input.substr(Start: NextChar, N: StartOffset - NextChar); |
59 | OS << '$' << T.Kind; |
60 | for (unsigned I = 0; |
61 | I <= static_cast<uint32_t>(HighlightingModifier::LastModifier); ++I) { |
62 | if (T.Modifiers & (1 << I)) { |
63 | // _decl_def is common and redundant, just print _def instead. |
64 | if (I != uint32_t(HighlightingModifier::Declaration) || !hasDef) |
65 | OS << '_' << static_cast<HighlightingModifier>(I); |
66 | } |
67 | } |
68 | OS << "[[" << Input.substr(Start: StartOffset, N: EndOffset - StartOffset) << "]]" ; |
69 | NextChar = EndOffset; |
70 | } |
71 | OS << Input.substr(Start: NextChar); |
72 | return std::move(OS.str()); |
73 | } |
74 | |
75 | void checkHighlightings(llvm::StringRef Code, |
76 | std::vector<std::pair</*FileName*/ llvm::StringRef, |
77 | /*FileContent*/ llvm::StringRef>> |
78 | AdditionalFiles = {}, |
79 | uint32_t ModifierMask = -1, |
80 | std::vector<std::string> AdditionalArgs = {}) { |
81 | Annotations Test(Code); |
82 | TestTU TU; |
83 | TU.Code = std::string(Test.code()); |
84 | |
85 | TU.ExtraArgs.push_back(x: "-std=c++20" ); |
86 | TU.ExtraArgs.push_back(x: "-xobjective-c++" ); |
87 | TU.ExtraArgs.insert(position: std::end(cont&: TU.ExtraArgs), first: std::begin(cont&: AdditionalArgs), |
88 | last: std::end(cont&: AdditionalArgs)); |
89 | |
90 | for (auto File : AdditionalFiles) |
91 | TU.AdditionalFiles.insert(KV: {File.first, std::string(File.second)}); |
92 | auto AST = TU.build(); |
93 | auto Actual = |
94 | getSemanticHighlightings(AST, /*IncludeInactiveRegionTokens=*/true); |
95 | for (auto &Token : Actual) |
96 | Token.Modifiers &= ModifierMask; |
97 | |
98 | EXPECT_EQ(Code, annotate(Test.code(), Actual)); |
99 | } |
100 | |
101 | constexpr static uint32_t ScopeModifierMask = |
102 | 1 << unsigned(HighlightingModifier::FunctionScope) | |
103 | 1 << unsigned(HighlightingModifier::ClassScope) | |
104 | 1 << unsigned(HighlightingModifier::FileScope) | |
105 | 1 << unsigned(HighlightingModifier::GlobalScope); |
106 | |
107 | TEST(SemanticHighlighting, GetsCorrectTokens) { |
108 | const char *TestCases[] = { |
109 | R"cpp( |
110 | struct $Class_def[[AS]] { |
111 | double $Field_decl[[SomeMember]]; |
112 | }; |
113 | struct { |
114 | } $Variable_def[[S]]; |
115 | void $Function_def[[foo]](int $Parameter_def[[A]], $Class[[AS]] $Parameter_def[[As]]) { |
116 | $Primitive_deduced_defaultLibrary[[auto]] $LocalVariable_def[[VeryLongVariableName]] = 12312; |
117 | $Class[[AS]] $LocalVariable_def[[AA]]; |
118 | $Primitive_deduced_defaultLibrary[[auto]] $LocalVariable_def[[L]] = $LocalVariable[[AA]].$Field[[SomeMember]] $Operator[[+]] $Parameter[[A]]; |
119 | auto $LocalVariable_def[[FN]] = [ $LocalVariable[[AA]]](int $Parameter_def[[A]]) -> void {}; |
120 | $LocalVariable[[FN]]$Operator_userDefined[[(]]12312$Operator_userDefined[[)]]; |
121 | } |
122 | )cpp" , |
123 | R"cpp( |
124 | void $Function_decl[[foo]](int); |
125 | void $Function_decl[[Gah]](); |
126 | void $Function_def[[foo]]() { |
127 | auto $LocalVariable_def[[Bou]] = $Function[[Gah]]; |
128 | } |
129 | struct $Class_def[[A]] { |
130 | void $Method_decl[[abc]](); |
131 | }; |
132 | )cpp" , |
133 | R"cpp( |
134 | namespace $Namespace_decl[[abc]] { |
135 | template$Bracket[[<]]typename $TemplateParameter_def[[T]]$Bracket[[>]] |
136 | struct $Class_def[[A]] { |
137 | $TemplateParameter[[T]] $Field_decl[[t]]; |
138 | }; |
139 | } |
140 | template$Bracket[[<]]typename $TemplateParameter_def[[T]]$Bracket[[>]] |
141 | struct $Class_def[[C]] : $Namespace[[abc]]::$Class[[A]]$Bracket[[<]]$TemplateParameter[[T]]$Bracket[[>]] { |
142 | typename $TemplateParameter[[T]]::$Type_dependentName[[A]]* $Field_decl[[D]]; |
143 | }; |
144 | $Namespace[[abc]]::$Class[[A]]$Bracket[[<]]int$Bracket[[>]] $Variable_def[[AA]]; |
145 | typedef $Namespace[[abc]]::$Class[[A]]$Bracket[[<]]int$Bracket[[>]] $Class_decl[[AAA]]; |
146 | struct $Class_def[[B]] { |
147 | $Class_decl_constrDestr[[B]](); |
148 | ~$Class_decl_constrDestr[[B]](); |
149 | void operator$Operator_decl[[<<]]($Class[[B]]); |
150 | $Class[[AAA]] $Field_decl[[AA]]; |
151 | }; |
152 | $Class[[B]]::$Class_def_constrDestr[[B]]() {} |
153 | $Class[[B]]::~$Class_def_constrDestr[[B]]() {} |
154 | void $Function_def[[f]] () { |
155 | $Class[[B]] $LocalVariable_def[[BB]] = $Class[[B]](); |
156 | $LocalVariable[[BB]].~$Class_constrDestr[[B]](); |
157 | $Class[[B]](); |
158 | } |
159 | )cpp" , |
160 | R"cpp( |
161 | enum class $Enum_decl[[E]] { |
162 | $EnumConstant_decl_readonly[[A]], |
163 | $EnumConstant_decl_readonly[[B]], |
164 | }; |
165 | enum $Enum_decl[[EE]] { |
166 | $EnumConstant_decl_readonly[[Hi]], |
167 | }; |
168 | struct $Class_def[[A]] { |
169 | $Enum[[E]] $Field_decl[[EEE]]; |
170 | $Enum[[EE]] $Field_decl[[EEEE]]; |
171 | }; |
172 | int $Variable_def[[I]] = $EnumConstant_readonly[[Hi]]; |
173 | $Enum[[E]] $Variable_def[[L]] = $Enum[[E]]::$EnumConstant_readonly[[B]]; |
174 | )cpp" , |
175 | R"cpp( |
176 | namespace $Namespace_decl[[abc]] { |
177 | namespace {} |
178 | namespace $Namespace_decl[[bcd]] { |
179 | struct $Class_def[[A]] {}; |
180 | namespace $Namespace_decl[[cde]] { |
181 | struct $Class_def[[A]] { |
182 | enum class $Enum_decl[[B]] { |
183 | $EnumConstant_decl_readonly[[Hi]], |
184 | }; |
185 | }; |
186 | } |
187 | } |
188 | } |
189 | using namespace $Namespace[[abc]]::$Namespace[[bcd]]; |
190 | namespace $Namespace_decl[[vwz]] = |
191 | $Namespace[[abc]]::$Namespace[[bcd]]::$Namespace[[cde]]; |
192 | $Namespace[[abc]]::$Namespace[[bcd]]::$Class[[A]] $Variable_def[[AA]]; |
193 | $Namespace[[vwz]]::$Class[[A]]::$Enum[[B]] $Variable_def[[AAA]] = |
194 | $Namespace[[vwz]]::$Class[[A]]::$Enum[[B]]::$EnumConstant_readonly[[Hi]]; |
195 | ::$Namespace[[vwz]]::$Class[[A]] $Variable_def[[B]]; |
196 | ::$Namespace[[abc]]::$Namespace[[bcd]]::$Class[[A]] $Variable_def[[BB]]; |
197 | )cpp" , |
198 | R"cpp( |
199 | struct $Class_def[[D]] { |
200 | double $Field_decl[[C]]; |
201 | }; |
202 | struct $Class_def[[A]] { |
203 | double $Field_decl[[B]]; |
204 | $Class[[D]] $Field_decl[[E]]; |
205 | static double $StaticField_decl_static[[S]]; |
206 | static void $StaticMethod_def_static[[bar]]() {} |
207 | void $Method_def[[foo]]() { |
208 | $Field[[B]] $Operator[[=]] 123; |
209 | this->$Field[[B]] $Operator[[=]] 156; |
210 | this->$Method[[foo]](); |
211 | $Method[[foo]](); |
212 | $StaticMethod_static[[bar]](); |
213 | $StaticField_static[[S]] $Operator[[=]] 90.1; |
214 | } |
215 | }; |
216 | void $Function_def[[foo]]() { |
217 | $Class[[A]] $LocalVariable_def[[AA]]; |
218 | $LocalVariable[[AA]].$Field[[B]] $Operator[[+=]] 2; |
219 | $LocalVariable[[AA]].$Method[[foo]](); |
220 | $LocalVariable[[AA]].$Field[[E]].$Field[[C]]; |
221 | $Class[[A]]::$StaticField_static[[S]] $Operator[[=]] 90; |
222 | } |
223 | )cpp" , |
224 | R"cpp( |
225 | struct $Class_def[[AA]] { |
226 | int $Field_decl[[A]]; |
227 | }; |
228 | int $Variable_def[[B]]; |
229 | $Class[[AA]] $Variable_def[[A]]{$Variable[[B]]}; |
230 | )cpp" , |
231 | R"cpp( |
232 | namespace $Namespace_decl[[a]] { |
233 | struct $Class_def[[A]] {}; |
234 | typedef char $Primitive_decl[[C]]; |
235 | } |
236 | typedef $Namespace[[a]]::$Class[[A]] $Class_decl[[B]]; |
237 | using $Class_decl[[BB]] = $Namespace[[a]]::$Class[[A]]; |
238 | enum class $Enum_decl[[E]] {}; |
239 | typedef $Enum[[E]] $Enum_decl[[C]]; |
240 | typedef $Enum[[C]] $Enum_decl[[CC]]; |
241 | using $Enum_decl[[CD]] = $Enum[[CC]]; |
242 | $Enum[[CC]] $Function_decl[[f]]($Class[[B]]); |
243 | $Enum[[CD]] $Function_decl[[f]]($Class[[BB]]); |
244 | typedef $Namespace[[a]]::$Primitive[[C]] $Primitive_decl[[PC]]; |
245 | typedef float $Primitive_decl[[F]]; |
246 | )cpp" , |
247 | R"cpp( |
248 | template$Bracket[[<]]typename $TemplateParameter_def[[T]], typename = void$Bracket[[>]] |
249 | class $Class_def[[A]] { |
250 | $TemplateParameter[[T]] $Field_decl[[AA]]; |
251 | $TemplateParameter[[T]] $Method_decl[[foo]](); |
252 | }; |
253 | template$Bracket[[<]]class $TemplateParameter_def[[TT]]$Bracket[[>]] |
254 | class $Class_def[[B]] { |
255 | $Class[[A]]$Bracket[[<]]$TemplateParameter[[TT]]$Bracket[[>]] $Field_decl[[AA]]; |
256 | }; |
257 | template$Bracket[[<]]class $TemplateParameter_def[[TT]], class $TemplateParameter_def[[GG]]$Bracket[[>]] |
258 | class $Class_def[[BB]] {}; |
259 | template$Bracket[[<]]class $TemplateParameter_def[[T]]$Bracket[[>]] |
260 | class $Class_def[[BB]]$Bracket[[<]]$TemplateParameter[[T]], int$Bracket[[>]] {}; |
261 | template$Bracket[[<]]class $TemplateParameter_def[[T]]$Bracket[[>]] |
262 | class $Class_def[[BB]]$Bracket[[<]]$TemplateParameter[[T]], $TemplateParameter[[T]]*$Bracket[[>]] {}; |
263 | |
264 | template$Bracket[[<]]template$Bracket[[<]]class$Bracket[[>]] class $TemplateParameter_def[[T]], class $TemplateParameter_def[[C]]$Bracket[[>]] |
265 | $TemplateParameter[[T]]$Bracket[[<]]$TemplateParameter[[C]]$Bracket[[>]] $Function_decl[[f]](); |
266 | |
267 | template$Bracket[[<]]typename$Bracket[[>]] |
268 | class $Class_def[[Foo]] {}; |
269 | |
270 | template$Bracket[[<]]typename $TemplateParameter_def[[T]]$Bracket[[>]] |
271 | void $Function_decl[[foo]]($TemplateParameter[[T]] ...); |
272 | )cpp" , |
273 | R"cpp( |
274 | template $Bracket[[<]]class $TemplateParameter_def[[T]]$Bracket[[>]] |
275 | struct $Class_def[[Tmpl]] {$TemplateParameter[[T]] $Field_decl[[x]] = 0;}; |
276 | extern template struct $Class_def[[Tmpl]]$Bracket[[<]]float$Bracket[[>]]; |
277 | template struct $Class_def[[Tmpl]]$Bracket[[<]]double$Bracket[[>]]; |
278 | )cpp" , |
279 | // This test is to guard against highlightings disappearing when using |
280 | // conversion operators as their behaviour in the clang AST differ from |
281 | // other CXXMethodDecls. |
282 | R"cpp( |
283 | class $Class_def[[Foo]] {}; |
284 | struct $Class_def[[Bar]] { |
285 | explicit operator $Class[[Foo]]*() const; |
286 | explicit operator int() const; |
287 | operator $Class[[Foo]](); |
288 | }; |
289 | void $Function_def[[f]]() { |
290 | $Class[[Bar]] $LocalVariable_def[[B]]; |
291 | $Class[[Foo]] $LocalVariable_def[[F]] = $LocalVariable[[B]]; |
292 | $Class[[Foo]] *$LocalVariable_def[[FP]] = ($Class[[Foo]]*)$LocalVariable[[B]]; |
293 | int $LocalVariable_def[[I]] = (int)$LocalVariable[[B]]; |
294 | } |
295 | )cpp" , |
296 | R"cpp( |
297 | struct $Class_def[[B]] {}; |
298 | struct $Class_def[[A]] { |
299 | $Class[[B]] $Field_decl[[BB]]; |
300 | $Class[[A]] &operator$Operator_decl[[=]]($Class[[A]] &&$Parameter_def[[O]]); |
301 | }; |
302 | |
303 | $Class[[A]] &$Class[[A]]::operator$Operator_def[[=]]($Class[[A]] &&$Parameter_def[[O]]) = default; |
304 | )cpp" , |
305 | R"cpp( |
306 | enum $Enum_decl[[En]] { |
307 | $EnumConstant_decl_readonly[[EC]], |
308 | }; |
309 | class $Class_def[[Foo]] {}; |
310 | class $Class_def[[Bar]] { |
311 | public: |
312 | $Class[[Foo]] $Field_decl[[Fo]]; |
313 | $Enum[[En]] $Field_decl[[E]]; |
314 | int $Field_decl[[I]]; |
315 | $Class_def_constrDestr[[Bar]] ($Class[[Foo]] $Parameter_def[[F]], |
316 | $Enum[[En]] $Parameter_def[[E]]) |
317 | : $Field[[Fo]] ($Parameter[[F]]), $Field[[E]] ($Parameter[[E]]), |
318 | $Field[[I]] (123) {} |
319 | }; |
320 | class $Class_def[[Bar2]] : public $Class[[Bar]] { |
321 | $Class_def_constrDestr[[Bar2]]() : $Class[[Bar]]($Class[[Foo]](), $EnumConstant_readonly[[EC]]) {} |
322 | }; |
323 | )cpp" , |
324 | R"cpp( |
325 | enum $Enum_decl[[E]] { |
326 | $EnumConstant_decl_readonly[[E]], |
327 | }; |
328 | class $Class_def[[Foo]] {}; |
329 | $Enum_deduced[[auto]] $Variable_def[[AE]] = $Enum[[E]]::$EnumConstant_readonly[[E]]; |
330 | $Class_deduced[[auto]] $Variable_def[[AF]] = $Class[[Foo]](); |
331 | $Class_deduced[[decltype]](auto) $Variable_def[[AF2]] = $Class[[Foo]](); |
332 | $Class_deduced[[auto]] *$Variable_def[[AFP]] = $Operator[[&]]$Variable[[AF]]; |
333 | $Enum_deduced[[auto]] &$Variable_def[[AER]] = $Variable[[AE]]; |
334 | $Primitive_deduced_defaultLibrary[[auto]] $Variable_def[[Form]] = 10.2 $Operator[[+]] 2 $Operator[[*]] 4; |
335 | $Primitive_deduced_defaultLibrary[[decltype]]($Variable[[Form]]) $Variable_def[[F]] = 10; |
336 | auto $Variable_def[[Fun]] = []()->void{}; |
337 | )cpp" , |
338 | R"cpp( |
339 | class $Class_def[[G]] {}; |
340 | template$Bracket[[<]]$Class[[G]] *$TemplateParameter_def_readonly[[U]]$Bracket[[>]] |
341 | class $Class_def[[GP]] {}; |
342 | template$Bracket[[<]]$Class[[G]] &$TemplateParameter_def_readonly[[U]]$Bracket[[>]] |
343 | class $Class_def[[GR]] {}; |
344 | template$Bracket[[<]]int *$TemplateParameter_def_readonly[[U]]$Bracket[[>]] |
345 | class $Class_def[[IP]] { |
346 | void $Method_def[[f]]() { |
347 | $Operator[[*]]$TemplateParameter_readonly[[U]] $Operator[[+=]] 5; |
348 | } |
349 | }; |
350 | template$Bracket[[<]]unsigned $TemplateParameter_def_readonly[[U]] = 2$Bracket[[>]] |
351 | class $Class_def[[Foo]] { |
352 | void $Method_def[[f]]() { |
353 | for(int $LocalVariable_def[[I]] = 0; |
354 | $LocalVariable[[I]] $Operator[[<]] $TemplateParameter_readonly[[U]];) {} |
355 | } |
356 | }; |
357 | |
358 | $Class[[G]] $Variable_def[[L]]; |
359 | void $Function_def[[f]]() { |
360 | $Class[[Foo]]$Bracket[[<]]123$Bracket[[>]] $LocalVariable_def[[F]]; |
361 | $Class[[GP]]$Bracket[[<]]$Operator[[&]]$Variable[[L]]$Bracket[[>]] $LocalVariable_def[[LL]]; |
362 | $Class[[GR]]$Bracket[[<]]$Variable[[L]]$Bracket[[>]] $LocalVariable_def[[LLL]]; |
363 | } |
364 | )cpp" , |
365 | R"cpp( |
366 | template$Bracket[[<]]typename $TemplateParameter_def[[T]], |
367 | void ($TemplateParameter[[T]]::*$TemplateParameter_def_readonly[[method]])(int)$Bracket[[>]] |
368 | struct $Class_def[[G]] { |
369 | void $Method_def[[foo]]( |
370 | $TemplateParameter[[T]] *$Parameter_def[[O]]) { |
371 | ($Parameter[[O]]$Operator_userDefined[[->*]]$TemplateParameter_readonly[[method]])(10); |
372 | |
373 | } |
374 | }; |
375 | struct $Class_def[[F]] { |
376 | void $Method_decl[[f]](int); |
377 | }; |
378 | template$Bracket[[<]]void (*$TemplateParameter_def_readonly[[Func]])()$Bracket[[>]] |
379 | struct $Class_def[[A]] { |
380 | void $Method_def[[f]]() { |
381 | ($Operator[[*]]$TemplateParameter_readonly[[Func]])(); |
382 | } |
383 | }; |
384 | |
385 | void $Function_def[[foo]]() { |
386 | $Class[[F]] $LocalVariable_def[[FF]]; |
387 | $Class[[G]]$Bracket[[<]]$Class[[F]], $Operator[[&]]$Class[[F]]::$Method[[f]]$Bracket[[>]] $LocalVariable_def[[GG]]; |
388 | $LocalVariable[[GG]].$Method[[foo]]($Operator[[&]]$LocalVariable_usedAsMutablePointer[[FF]]); |
389 | $Class[[A]]$Bracket[[<]]$Function[[foo]]$Bracket[[>]] $LocalVariable_def[[AA]]; |
390 | } |
391 | )cpp" , |
392 | // Tokens that share a source range but have conflicting Kinds are not |
393 | // highlighted. |
394 | R"cpp( |
395 | #define $Macro_decl[[DEF_MULTIPLE]](X) namespace X { class X { int X; }; } |
396 | #define $Macro_decl[[DEF_CLASS]](T) class T {}; |
397 | // Preamble ends. |
398 | $Macro[[DEF_MULTIPLE]](XYZ); |
399 | $Macro[[DEF_MULTIPLE]](XYZW); |
400 | $Macro[[DEF_CLASS]]($Class_def[[A]]) |
401 | #define $Macro_decl[[MACRO_CONCAT]](X, V, T) T foo##X = V |
402 | #define $Macro_decl[[DEF_VAR]](X, V) int X = V |
403 | #define $Macro_decl[[DEF_VAR_T]](T, X, V) T X = V |
404 | #define $Macro_decl[[DEF_VAR_REV]](V, X) $Macro[[DEF_VAR]](X, V) |
405 | #define $Macro_decl[[CPY]](X) X |
406 | #define $Macro_decl[[DEF_VAR_TYPE]](X, Y) X Y |
407 | #define $Macro_decl[[SOME_NAME]] variable |
408 | #define $Macro_decl[[SOME_NAME_SET]] variable2 = 123 |
409 | #define $Macro_decl[[INC_VAR]](X) X += 2 |
410 | void $Function_def[[foo]]() { |
411 | $Macro[[DEF_VAR]]($LocalVariable_def[[X]], 123); |
412 | $Macro[[DEF_VAR_REV]](908, $LocalVariable_def[[XY]]); |
413 | int $Macro[[CPY]]( $LocalVariable_def[[XX]] ); |
414 | $Macro[[DEF_VAR_TYPE]]($Class[[A]], $LocalVariable_def[[AA]]); |
415 | double $Macro[[SOME_NAME]]; |
416 | int $Macro[[SOME_NAME_SET]]; |
417 | $LocalVariable[[variable]] $Operator[[=]] 20.1; |
418 | $Macro[[MACRO_CONCAT]](var, 2, float); |
419 | $Macro[[DEF_VAR_T]]($Class[[A]], $Macro[[CPY]]( |
420 | $Macro[[CPY]]($LocalVariable_def[[Nested]])), |
421 | $Macro[[CPY]]($Class[[A]]())); |
422 | $Macro[[INC_VAR]]($LocalVariable[[variable]]); |
423 | } |
424 | void $Macro[[SOME_NAME]](); |
425 | $Macro[[DEF_VAR]]($Variable_def[[MMMMM]], 567); |
426 | $Macro[[DEF_VAR_REV]](756, $Variable_def[[AB]]); |
427 | |
428 | #define $Macro_decl[[CALL_FN]](F) F(); |
429 | #define $Macro_decl[[DEF_FN]](F) void F () |
430 | $Macro[[DEF_FN]]($Function_def[[g]]) { |
431 | $Macro[[CALL_FN]]($Function[[foo]]); |
432 | } |
433 | )cpp" , |
434 | R"cpp( |
435 | #define $Macro_decl[[fail]](expr) expr |
436 | #define $Macro_decl[[assert]](COND) if (!(COND)) { $Macro[[fail]]("assertion failed" #COND); } |
437 | // Preamble ends. |
438 | int $Variable_def[[x]]; |
439 | int $Variable_def[[y]]; |
440 | int $Function_decl[[f]](); |
441 | void $Function_def[[foo]]() { |
442 | $Macro[[assert]]($Variable[[x]] $Operator[[!=]] $Variable[[y]]); |
443 | $Macro[[assert]]($Variable[[x]] $Operator[[!=]] $Function[[f]]()); |
444 | } |
445 | )cpp" , |
446 | // highlighting all macro references |
447 | R"cpp( |
448 | #ifndef $Macro[[name]] |
449 | #define $Macro_decl[[name]] |
450 | #endif |
451 | |
452 | #define $Macro_decl[[test]] |
453 | #undef $Macro[[test]] |
454 | #ifdef $Macro[[test]] |
455 | #endif |
456 | |
457 | #if defined($Macro[[test]]) |
458 | #endif |
459 | )cpp" , |
460 | R"cpp( |
461 | struct $Class_def[[S]] { |
462 | float $Field_decl[[Value]]; |
463 | $Class[[S]] *$Field_decl[[Next]]; |
464 | }; |
465 | $Class[[S]] $Variable_def[[Global]][2] = {$Class[[S]](), $Class[[S]]()}; |
466 | auto [$Variable_decl[[G1]], $Variable_decl[[G2]]] = $Variable[[Global]]; |
467 | void $Function_def[[f]]($Class[[S]] $Parameter_def[[P]]) { |
468 | int $LocalVariable_def[[A]][2] = {1,2}; |
469 | auto [$LocalVariable_decl[[B1]], $LocalVariable_decl[[B2]]] = $LocalVariable[[A]]; |
470 | auto [$LocalVariable_decl[[G1]], $LocalVariable_decl[[G2]]] = $Variable[[Global]]; |
471 | $Class_deduced[[auto]] [$LocalVariable_decl[[P1]], $LocalVariable_decl[[P2]]] = $Parameter[[P]]; |
472 | // Highlights references to BindingDecls. |
473 | $LocalVariable[[B1]]$Operator[[++]]; |
474 | } |
475 | )cpp" , |
476 | R"cpp( |
477 | template$Bracket[[<]]class $TemplateParameter_def[[T]]$Bracket[[>]] |
478 | class $Class_def[[A]] { |
479 | using $TemplateParameter_decl[[TemplateParam1]] = $TemplateParameter[[T]]; |
480 | typedef $TemplateParameter[[T]] $TemplateParameter_decl[[TemplateParam2]]; |
481 | using $Primitive_decl[[IntType]] = int; |
482 | |
483 | using $Typedef_decl[[Pointer]] = $TemplateParameter[[T]] *; |
484 | using $Typedef_decl[[LVReference]] = $TemplateParameter[[T]] &; |
485 | using $Typedef_decl[[RVReference]] = $TemplateParameter[[T]]&&; |
486 | using $Typedef_decl[[Array]] = $TemplateParameter[[T]]*[3]; |
487 | using $Typedef_decl[[MemberPointer]] = int ($Class[[A]]::*)(int); |
488 | |
489 | // Use various previously defined typedefs in a function type. |
490 | void $Method_decl[[func]]( |
491 | $Typedef[[Pointer]], $Typedef[[LVReference]], $Typedef[[RVReference]], |
492 | $Typedef[[Array]], $Typedef[[MemberPointer]]); |
493 | }; |
494 | )cpp" , |
495 | R"cpp( |
496 | template $Bracket[[<]]class $TemplateParameter_def[[T]]$Bracket[[>]] |
497 | void $Function_decl[[phase1]]($TemplateParameter[[T]]); |
498 | template $Bracket[[<]]class $TemplateParameter_def[[T]]$Bracket[[>]] |
499 | void $Function_def[[foo]]($TemplateParameter[[T]] $Parameter_def[[P]]) { |
500 | $Function[[phase1]]($Parameter[[P]]); |
501 | $Unknown_dependentName[[phase2]]($Parameter[[P]]); |
502 | } |
503 | )cpp" , |
504 | R"cpp( |
505 | class $Class_def[[A]] { |
506 | template $Bracket[[<]]class $TemplateParameter_def[[T]]$Bracket[[>]] |
507 | void $Method_decl[[bar]]($TemplateParameter[[T]]); |
508 | }; |
509 | |
510 | template $Bracket[[<]]class $TemplateParameter_def[[U]]$Bracket[[>]] |
511 | void $Function_def[[foo]]($TemplateParameter[[U]] $Parameter_def[[P]]) { |
512 | $Class[[A]]().$Method[[bar]]($Parameter[[P]]); |
513 | } |
514 | )cpp" , |
515 | R"cpp( |
516 | struct $Class_def[[A]] { |
517 | template $Bracket[[<]]class $TemplateParameter_def[[T]]$Bracket[[>]] |
518 | static void $StaticMethod_decl_static[[foo]]($TemplateParameter[[T]]); |
519 | }; |
520 | |
521 | template $Bracket[[<]]class $TemplateParameter_def[[T]]$Bracket[[>]] |
522 | struct $Class_def[[B]] { |
523 | void $Method_def[[bar]]() { |
524 | $Class[[A]]::$StaticMethod_static[[foo]]($TemplateParameter[[T]]()); |
525 | } |
526 | }; |
527 | )cpp" , |
528 | R"cpp( |
529 | template $Bracket[[<]]class $TemplateParameter_def[[T]]$Bracket[[>]] |
530 | void $Function_decl[[foo]](typename $TemplateParameter[[T]]::$Type_dependentName[[Type]] |
531 | = $TemplateParameter[[T]]::$Unknown_dependentName[[val]]); |
532 | )cpp" , |
533 | R"cpp( |
534 | template $Bracket[[<]]class $TemplateParameter_def[[T]]$Bracket[[>]] |
535 | void $Function_def[[foo]]($TemplateParameter[[T]] $Parameter_def[[P]]) { |
536 | $Parameter[[P]].$Unknown_dependentName[[Field]]; |
537 | } |
538 | )cpp" , |
539 | R"cpp( |
540 | template $Bracket[[<]]class $TemplateParameter_def[[T]]$Bracket[[>]] |
541 | class $Class_def[[A]] { |
542 | int $Method_def[[foo]]() { |
543 | return $TemplateParameter[[T]]::$Unknown_dependentName[[Field]]; |
544 | } |
545 | }; |
546 | )cpp" , |
547 | // Highlighting the using decl as the underlying using shadow decl. |
548 | R"cpp( |
549 | void $Function_decl[[foo]](); |
550 | using ::$Function[[foo]]; |
551 | )cpp" , |
552 | // Highlighting of template template arguments. |
553 | R"cpp( |
554 | template $Bracket[[<]]template $Bracket[[<]]class$Bracket[[>]] class $TemplateParameter_def[[TT]], |
555 | template $Bracket[[<]]class$Bracket[[>]] class ...$TemplateParameter_def[[TTs]]$Bracket[[>]] |
556 | struct $Class_def[[Foo]] { |
557 | $Class[[Foo]]$Bracket[[<]]$TemplateParameter[[TT]], $TemplateParameter[[TTs]]...$Bracket[[>]] |
558 | *$Field_decl[[t]]; |
559 | }; |
560 | )cpp" , |
561 | // Inactive code highlighting |
562 | R"cpp( |
563 | // Code in the preamble. |
564 | // Inactive lines get an empty InactiveCode token at the beginning. |
565 | #ifdef $Macro[[test]] |
566 | $InactiveCode[[int Inactive1;]] |
567 | #endif |
568 | |
569 | // A declaration to cause the preamble to end. |
570 | int $Variable_def[[EndPreamble]]; |
571 | |
572 | // Code after the preamble. |
573 | // Code inside inactive blocks does not get regular highlightings |
574 | // because it's not part of the AST. |
575 | #define $Macro_decl[[test2]] |
576 | #if defined($Macro[[test]]) |
577 | $InactiveCode[[int Inactive2;]] |
578 | #elif defined($Macro[[test2]]) |
579 | int $Variable_def[[Active1]]; |
580 | #else |
581 | $InactiveCode[[int Inactive3;]] |
582 | #endif |
583 | |
584 | #ifndef $Macro[[test]] |
585 | int $Variable_def[[Active2]]; |
586 | #endif |
587 | |
588 | #ifdef $Macro[[test]] |
589 | $InactiveCode[[int Inactive4;]] |
590 | #else |
591 | int $Variable_def[[Active3]]; |
592 | #endif |
593 | )cpp" , |
594 | // Argument to 'sizeof...' |
595 | R"cpp( |
596 | template $Bracket[[<]]typename... $TemplateParameter_def[[Elements]]$Bracket[[>]] |
597 | struct $Class_def[[TupleSize]] { |
598 | static const int $StaticField_decl_readonly_static[[size]] = |
599 | sizeof...($TemplateParameter[[Elements]]); |
600 | }; |
601 | )cpp" , |
602 | // More dependent types |
603 | R"cpp( |
604 | template $Bracket[[<]]typename $TemplateParameter_def[[T]]$Bracket[[>]] |
605 | struct $Class_def[[Waldo]] { |
606 | using $Typedef_decl[[Location1]] = typename $TemplateParameter[[T]] |
607 | ::$Type_dependentName[[Resolver]]::$Type_dependentName[[Location]]; |
608 | using $Typedef_decl[[Location2]] = typename $TemplateParameter[[T]] |
609 | ::template $Type_dependentName[[Resolver]]$Bracket[[<]]$TemplateParameter[[T]]$Bracket[[>]] |
610 | ::$Type_dependentName[[Location]]; |
611 | using $Typedef_decl[[Location3]] = typename $TemplateParameter[[T]] |
612 | ::$Type_dependentName[[Resolver]] |
613 | ::template $Type_dependentName[[Location]]$Bracket[[<]]$TemplateParameter[[T]]$Bracket[[>]]; |
614 | static const int $StaticField_decl_readonly_static[[Value]] = $TemplateParameter[[T]] |
615 | ::$Type_dependentName[[Resolver]]::$Unknown_dependentName[[Value]]; |
616 | }; |
617 | )cpp" , |
618 | // Dependent name with heuristic target |
619 | R"cpp( |
620 | template $Bracket[[<]]typename$Bracket[[>]] |
621 | struct $Class_def[[Foo]] { |
622 | int $Field_decl[[Waldo]]; |
623 | void $Method_def[[bar]]() { |
624 | $Class[[Foo]]().$Field_dependentName[[Waldo]]; |
625 | } |
626 | template $Bracket[[<]]typename $TemplateParameter_def[[U]]$Bracket[[>]] |
627 | void $Method_def[[bar1]]() { |
628 | $Class[[Foo]]$Bracket[[<]]$TemplateParameter[[U]]$Bracket[[>]]().$Field_dependentName[[Waldo]]; |
629 | } |
630 | |
631 | void $Method_decl[[Overload]](); |
632 | void $Method_decl_readonly[[Overload]]() const; |
633 | }; |
634 | template $Bracket[[<]]typename $TemplateParameter_def[[T]]$Bracket[[>]] |
635 | void $Function_def[[baz]]($Class[[Foo]]$Bracket[[<]]$TemplateParameter[[T]]$Bracket[[>]] $Parameter_def[[o]]) { |
636 | $Parameter[[o]].$Method_readonly_dependentName[[Overload]](); |
637 | } |
638 | )cpp" , |
639 | // Concepts |
640 | R"cpp( |
641 | template $Bracket[[<]]typename $TemplateParameter_def[[T]]$Bracket[[>]] |
642 | concept $Concept_decl[[Fooable]] = |
643 | requires($TemplateParameter[[T]] $Parameter_def[[F]]) { |
644 | $Parameter[[F]].$Unknown_dependentName[[foo]](); |
645 | }; |
646 | template $Bracket[[<]]typename $TemplateParameter_def[[T]]$Bracket[[>]] |
647 | requires $Concept[[Fooable]]$Bracket[[<]]$TemplateParameter[[T]]$Bracket[[>]] |
648 | void $Function_def[[bar]]($TemplateParameter[[T]] $Parameter_def[[F]]) { |
649 | $Parameter[[F]].$Unknown_dependentName[[foo]](); |
650 | } |
651 | |
652 | struct $Class_def[[F]] { |
653 | void $Method_def[[foo]]() {}; |
654 | }; |
655 | $Concept[[Fooable]] $Class_deduced[[auto]] $Variable_def[[f]] = $Class[[F]](); |
656 | |
657 | void $Function_def[[Bar]]($Concept[[Fooable]] $TemplateParameter[[auto]] $Parameter_def[[x]]) {} |
658 | |
659 | template$Bracket[[<]]$Concept[[Fooable]] auto $TemplateParameter_def_readonly[[x]]$Bracket[[>]] void $Function_def[[Boo]]() {} |
660 | bool $Variable_def[[b]] = $Concept[[Fooable]]$Bracket[[<]]int$Bracket[[>]]; |
661 | )cpp" , |
662 | // Dependent template name |
663 | R"cpp( |
664 | template $Bracket[[<]]template $Bracket[[<]]typename$Bracket[[>]] class$Bracket[[>]] struct $Class_def[[A]] {}; |
665 | template $Bracket[[<]]typename $TemplateParameter_def[[T]]$Bracket[[>]] |
666 | using $Typedef_decl[[W]] = $Class[[A]]$Bracket[[<]] |
667 | $TemplateParameter[[T]]::template $Class_dependentName[[Waldo]] |
668 | $Bracket[[>]]; |
669 | )cpp" , |
670 | R"cpp( |
671 | class $Class_def_abstract[[Abstract]] { |
672 | public: |
673 | virtual void $Method_decl_abstract_virtual[[pure]]() = 0; |
674 | virtual void $Method_decl_virtual[[impl]](); |
675 | }; |
676 | void $Function_def[[foo]]($Class_abstract[[Abstract]]* $Parameter_def[[A]]) { |
677 | $Parameter[[A]]->$Method_abstract_virtual[[pure]](); |
678 | $Parameter[[A]]->$Method_virtual[[impl]](); |
679 | } |
680 | )cpp" , |
681 | R"cpp( |
682 | <:[deprecated]:> int $Variable_def_deprecated[[x]]; |
683 | )cpp" , |
684 | R"cpp( |
685 | // ObjC: Classes and methods |
686 | @class $Class_decl[[Forward]]; |
687 | |
688 | @interface $Class_def[[Foo]] |
689 | @end |
690 | @interface $Class_def[[Bar]] : $Class[[Foo]] |
691 | -(id) $Method_decl[[x]]:(int)$Parameter_def[[a]] $Method_decl[[y]]:(int)$Parameter_def[[b]]; |
692 | +(instancetype)$StaticMethod_decl_static[[sharedInstance]]; |
693 | +(void) $StaticMethod_decl_static[[explode]]; |
694 | @end |
695 | @implementation $Class_def[[Bar]] |
696 | -(id) $Method_def[[x]]:(int)$Parameter_def[[a]] $Method_def[[y]]:(int)$Parameter_def[[b]] { |
697 | return self; |
698 | } |
699 | +(instancetype)$StaticMethod_def_static[[sharedInstance]] { return 0; } |
700 | +(void) $StaticMethod_def_static[[explode]] {} |
701 | @end |
702 | |
703 | void $Function_def[[m]]($Class[[Bar]] *$Parameter_def[[b]]) { |
704 | [$Parameter[[b]] $Method[[x]]:1 $Method[[y]]:2]; |
705 | [$Class[[Bar]] $StaticMethod_static[[explode]]]; |
706 | } |
707 | )cpp" , |
708 | R"cpp( |
709 | // ObjC: Protocols |
710 | @protocol $Interface_def[[Protocol]] |
711 | @end |
712 | @protocol $Interface_def[[Protocol2]] <$Interface[[Protocol]]> |
713 | @end |
714 | @interface $Class_def[[Klass]] <$Interface[[Protocol]]> |
715 | @end |
716 | id<$Interface[[Protocol]]> $Variable_def[[x]]; |
717 | )cpp" , |
718 | R"cpp( |
719 | // ObjC: Categories |
720 | @interface $Class_def[[Foo]] |
721 | @end |
722 | @interface $Class[[Foo]]($Namespace_def[[Bar]]) |
723 | @end |
724 | @implementation $Class[[Foo]]($Namespace_def[[Bar]]) |
725 | @end |
726 | )cpp" , |
727 | R"cpp( |
728 | // ObjC: Properties and Ivars. |
729 | @interface $Class_def[[Foo]] { |
730 | int $Field_decl[[_someProperty]]; |
731 | } |
732 | @property(nonatomic, assign) int $Field_decl[[someProperty]]; |
733 | @property(readonly, class) $Class[[Foo]] *$Field_decl_readonly_static[[sharedInstance]]; |
734 | @end |
735 | @implementation $Class_def[[Foo]] |
736 | @synthesize someProperty = _someProperty; |
737 | - (int)$Method_def[[otherMethod]] { |
738 | return 0; |
739 | } |
740 | - (int)$Method_def[[doSomething]] { |
741 | $Class[[Foo]].$Field_static[[sharedInstance]].$Field[[someProperty]] $Operator[[=]] 1; |
742 | self.$Field[[someProperty]] $Operator[[=]] self.$Field[[someProperty]] $Operator[[+]] self.$Field[[otherMethod]] $Operator[[+]] 1; |
743 | self->$Field[[_someProperty]] $Operator[[=]] $Field[[_someProperty]] $Operator[[+]] 1; |
744 | } |
745 | @end |
746 | )cpp" , |
747 | // Member imported from dependent base |
748 | R"cpp( |
749 | template $Bracket[[<]]typename$Bracket[[>]] struct $Class_def[[Base]] { |
750 | int $Field_decl[[member]]; |
751 | }; |
752 | template $Bracket[[<]]typename $TemplateParameter_def[[T]]$Bracket[[>]] |
753 | struct $Class_def[[Derived]] : $Class[[Base]]$Bracket[[<]]$TemplateParameter[[T]]$Bracket[[>]] { |
754 | using $Class[[Base]]$Bracket[[<]]$TemplateParameter[[T]]$Bracket[[>]]::$Field_dependentName[[member]]; |
755 | |
756 | void $Method_def[[method]]() { |
757 | (void)$Field_dependentName[[member]]; |
758 | } |
759 | }; |
760 | )cpp" , |
761 | // Modifier for variables passed as non-const references |
762 | R"cpp( |
763 | struct $Class_def[[ClassWithOp]] { |
764 | void operator$Operator_decl[[(]]$Operator_decl[[)]](int); |
765 | void operator$Operator_decl[[(]]$Operator_decl[[)]](int, int &); |
766 | void operator$Operator_decl[[(]]$Operator_decl[[)]](int, int, const int &); |
767 | int &operator$Operator_decl[[[]]$Operator_decl[[]]](int &); |
768 | int operator$Operator_decl[[[]]$Operator_decl[[]]](int) const; |
769 | }; |
770 | struct $Class_def[[ClassWithStaticMember]] { |
771 | static inline int $StaticField_def_static[[j]] = 0; |
772 | }; |
773 | struct $Class_def[[ClassWithRefMembers]] { |
774 | $Class_def_constrDestr[[ClassWithRefMembers]](int $Parameter_def[[i]]) |
775 | : $Field[[i1]]($Parameter[[i]]), |
776 | $Field_readonly[[i2]]($Parameter[[i]]), |
777 | $Field[[i3]]($Parameter_usedAsMutableReference[[i]]), |
778 | $Field_readonly[[i4]]($Class[[ClassWithStaticMember]]::$StaticField_static[[j]]), |
779 | $Field[[i5]]($Class[[ClassWithStaticMember]]::$StaticField_static_usedAsMutableReference[[j]]) |
780 | {} |
781 | int $Field_decl[[i1]]; |
782 | const int &$Field_decl_readonly[[i2]]; |
783 | int &$Field_decl[[i3]]; |
784 | const int &$Field_decl_readonly[[i4]]; |
785 | int &$Field_decl[[i5]]; |
786 | }; |
787 | void $Function_def[[fun]](int, const int, |
788 | int*, const int*, |
789 | int&, const int&, |
790 | int*&, const int*&, const int* const &, |
791 | int**, int**&, int** const &, |
792 | int = 123) { |
793 | int $LocalVariable_def[[val]]; |
794 | int* $LocalVariable_def[[ptr]]; |
795 | const int* $LocalVariable_def_readonly[[constPtr]]; |
796 | int** $LocalVariable_def[[array]]; |
797 | $Function[[fun]]($LocalVariable[[val]], $LocalVariable[[val]], |
798 | $LocalVariable_usedAsMutablePointer[[ptr]], $LocalVariable_readonly[[constPtr]], |
799 | $LocalVariable_usedAsMutableReference[[val]], $LocalVariable[[val]], |
800 | |
801 | $LocalVariable_usedAsMutableReference[[ptr]], |
802 | $LocalVariable_readonly_usedAsMutableReference[[constPtr]], |
803 | $LocalVariable_readonly[[constPtr]], |
804 | |
805 | $LocalVariable_usedAsMutablePointer[[array]], $LocalVariable_usedAsMutableReference[[array]], |
806 | $LocalVariable[[array]] |
807 | ); |
808 | [](int){}$Operator_userDefined[[(]]$LocalVariable[[val]]$Operator_userDefined[[)]]; |
809 | [](int&){}$Operator_userDefined[[(]]$LocalVariable_usedAsMutableReference[[val]]$Operator_userDefined[[)]]; |
810 | [](const int&){}$Operator_userDefined[[(]]$LocalVariable[[val]]$Operator_userDefined[[)]]; |
811 | $Class[[ClassWithOp]] $LocalVariable_def[[c]]; |
812 | const $Class[[ClassWithOp]] $LocalVariable_def_readonly[[c2]]; |
813 | $LocalVariable[[c]]$Operator_userDefined[[(]]$LocalVariable[[val]]$Operator_userDefined[[)]]; |
814 | $LocalVariable[[c]]$Operator_userDefined[[(]]0, $LocalVariable_usedAsMutableReference[[val]]$Operator_userDefined[[)]]; |
815 | $LocalVariable[[c]]$Operator_userDefined[[(]]0, 0, $LocalVariable[[val]]$Operator_userDefined[[)]]; |
816 | $LocalVariable[[c]]$Operator_userDefined[[[]]$LocalVariable_usedAsMutableReference[[val]]$Operator_userDefined[[]]]; |
817 | $LocalVariable_readonly[[c2]]$Operator_userDefined[[[]]$LocalVariable[[val]]$Operator_userDefined[[]]]; |
818 | } |
819 | struct $Class_def[[S]] { |
820 | $Class_def_constrDestr[[S]](int&) { |
821 | $Class[[S]] $LocalVariable_def[[s1]]($Field_usedAsMutableReference[[field]]); |
822 | $Class[[S]] $LocalVariable_def[[s2]]($LocalVariable[[s1]].$Field_usedAsMutableReference[[field]]); |
823 | |
824 | $Class[[S]] $LocalVariable_def[[s3]]($StaticField_static_usedAsMutableReference[[staticField]]); |
825 | $Class[[S]] $LocalVariable_def[[s4]]($Class[[S]]::$StaticField_static_usedAsMutableReference[[staticField]]); |
826 | } |
827 | int $Field_decl[[field]]; |
828 | static int $StaticField_decl_static[[staticField]]; |
829 | }; |
830 | template $Bracket[[<]]typename $TemplateParameter_def[[X]]$Bracket[[>]] |
831 | void $Function_def[[foo]]($TemplateParameter[[X]]& $Parameter_def[[x]]) { |
832 | // We do not support dependent types, so this one should *not* get the modifier. |
833 | $Function[[foo]]($Parameter[[x]]); |
834 | } |
835 | )cpp" , |
836 | // init-captures |
837 | R"cpp( |
838 | void $Function_def[[foo]]() { |
839 | int $LocalVariable_def[[a]], $LocalVariable_def[[b]]; |
840 | [ $LocalVariable_def[[c]] = $LocalVariable[[a]], |
841 | $LocalVariable_def[[d]]($LocalVariable[[b]]) ]() {}$Operator_userDefined[[(]]$Operator_userDefined[[)]]; |
842 | } |
843 | )cpp" , |
844 | // Enum base specifier |
845 | R"cpp( |
846 | using $Primitive_decl[[MyTypedef]] = int; |
847 | enum $Enum_decl[[MyEnum]] : $Primitive[[MyTypedef]] {}; |
848 | )cpp" , |
849 | // Enum base specifier |
850 | R"cpp( |
851 | typedef int $Primitive_decl[[MyTypedef]]; |
852 | enum $Enum_decl[[MyEnum]] : $Primitive[[MyTypedef]] {}; |
853 | )cpp" , |
854 | // Using enum |
855 | R"cpp( |
856 | enum class $Enum_decl[[Color]] { $EnumConstant_decl_readonly[[Black]] }; |
857 | namespace $Namespace_decl[[ns]] { |
858 | using enum $Enum[[Color]]; |
859 | $Enum[[Color]] $Variable_def[[ModelT]] = $EnumConstant[[Black]]; |
860 | } |
861 | )cpp" , |
862 | // Issue 1096 |
863 | R"cpp( |
864 | void $Function_decl[[Foo]](); |
865 | // Use <: :> digraphs for deprecated attribute to avoid conflict with annotation syntax |
866 | <:<:deprecated:>:> void $Function_decl_deprecated[[Foo]](int* $Parameter_def[[x]]); |
867 | void $Function_decl[[Foo]](int $Parameter_def[[x]]); |
868 | template $Bracket[[<]]typename $TemplateParameter_def[[T]]$Bracket[[>]] |
869 | void $Function_def[[Bar]]($TemplateParameter[[T]] $Parameter_def[[x]]) { |
870 | $Function_deprecated[[Foo]]($Parameter[[x]]); |
871 | $Function_deprecated[[Foo]]($Parameter[[x]]); |
872 | $Function_deprecated[[Foo]]($Parameter[[x]]); |
873 | } |
874 | )cpp" , |
875 | // Predefined identifiers |
876 | R"cpp( |
877 | void $Function_def[[Foo]]() { |
878 | const char *$LocalVariable_def_readonly[[s]] = $LocalVariable_readonly_static[[__func__]]; |
879 | } |
880 | )cpp" , |
881 | // override and final |
882 | R"cpp( |
883 | class $Class_def_abstract[[Base]] { virtual void $Method_decl_abstract_virtual[[m]]() = 0; }; |
884 | class $Class_def[[override]] : public $Class_abstract[[Base]] { void $Method_decl_virtual[[m]]() $Modifier[[override]]; }; |
885 | class $Class_def[[final]] : public $Class[[override]] { void $Method_decl_virtual[[m]]() $Modifier[[override]] $Modifier[[final]]; }; |
886 | )cpp" , |
887 | // Issue 1222: readonly modifier for generic parameter |
888 | R"cpp( |
889 | template $Bracket[[<]]typename $TemplateParameter_def[[T]]$Bracket[[>]] |
890 | auto $Function_def[[foo]](const $TemplateParameter[[T]] $Parameter_def_readonly[[template_type]], |
891 | const $TemplateParameter[[auto]] $Parameter_def_readonly[[auto_type]], |
892 | const int $Parameter_def_readonly[[explicit_type]]) { |
893 | return $Parameter_readonly[[template_type]] |
894 | $Operator_userDefined[[+]] $Parameter_readonly[[auto_type]] |
895 | $Operator_userDefined[[+]] $Parameter_readonly[[explicit_type]]; |
896 | } |
897 | )cpp" , |
898 | // Explicit template specialization |
899 | R"cpp( |
900 | struct $Class_def[[Base]]{}; |
901 | template $Bracket[[<]]typename $TemplateParameter_def[[T]]$Bracket[[>]] |
902 | struct $Class_def[[S]] : public $Class[[Base]] {}; |
903 | template $Bracket[[<]]$Bracket[[>]] |
904 | struct $Class_def[[S]]$Bracket[[<]]void$Bracket[[>]] : public $Class[[Base]] {}; |
905 | |
906 | template $Bracket[[<]]typename $TemplateParameter_def[[T]]$Bracket[[>]] |
907 | $TemplateParameter[[T]] $Variable_def[[x]] = {}; |
908 | template $Bracket[[<]]$Bracket[[>]] |
909 | int $Variable_def[[x]]$Bracket[[<]]int$Bracket[[>]] = (int)sizeof($Class[[Base]]); |
910 | )cpp" , |
911 | // operator calls in template |
912 | R"cpp( |
913 | template$Bracket[[<]]typename $TemplateParameter_def[[T]]$Bracket[[>]] class $Class_def[[C]] { |
914 | bool $Method_def[[compare]]($TemplateParameter[[T]] $Parameter_def[[t1]], $TemplateParameter[[T]] $Parameter_def[[t2]]) { return $Parameter[[t1]] $Operator_userDefined[[==]] $Parameter[[t2]]; } |
915 | $TemplateParameter[[T]] $Method_def[[deref]]($TemplateParameter[[T]] *$Parameter_def[[t]]) { return $Operator_userDefined[[*]]$Parameter[[t]]; } |
916 | }; |
917 | )cpp" , |
918 | // new and delete |
919 | R"cpp( |
920 | struct $Class_def[[S]] { int *$Field_decl[[a]]; }; |
921 | void $Function_def[[f]]() { |
922 | $Class[[S]] *$LocalVariable_def[[s]] = $Operator[[new]] $Class[[S]]; |
923 | $LocalVariable[[s]]->$Field[[a]] $Operator[[=]] $Operator[[new]] int[10]; |
924 | $Operator[[delete]][] $LocalVariable[[s]]->$Field[[a]]; |
925 | $Operator[[delete]] $LocalVariable[[s]]; |
926 | } |
927 | )cpp" , |
928 | // explicit operator invocation |
929 | R"cpp( |
930 | struct $Class_def[[S]] { |
931 | $Class[[S]] operator$Operator_decl[[+]](const $Class[[S]] &$Parameter_def_readonly[[other]]); |
932 | }; |
933 | void $Function_def[[f]]() { |
934 | $Class[[S]] $LocalVariable_def[[s]]; |
935 | $Class[[S]] $LocalVariable_def[[s2]] = $LocalVariable[[s]].operator$Operator_userDefined[[+]]($LocalVariable[[s]]); |
936 | } |
937 | )cpp" , |
938 | R"cpp( |
939 | // Brackets support: C++ casts |
940 | void $Function_def[[f]]() { |
941 | struct $Class_def[[B]] { virtual ~$Class_decl_constrDestr[[B]](); }; |
942 | struct $Class_def[[D]] : public $Class[[B]] {}; |
943 | $Class[[B]] $LocalVariable_def[[b]]; |
944 | int $LocalVariable_def[[i]] = static_cast$Bracket[[<]]int$Bracket[[>]](3.5); |
945 | void *$LocalVariable_def[[p]] = reinterpret_cast$Bracket[[<]]void *$Bracket[[>]](0); |
946 | $Class[[D]] &$LocalVariable_def[[d]] = dynamic_cast$Bracket[[<]]$Class[[D]] &$Bracket[[>]]($LocalVariable[[b]]); |
947 | } |
948 | )cpp" , |
949 | // Brackets support: Nested template instantiations. |
950 | R"cpp( |
951 | template$Bracket[[<]]typename $TemplateParameter_def[[T]]$Bracket[[>]] struct $Class_def[[S]] {}; |
952 | void $Function_def[[f]]() { |
953 | $Class[[S]]$Bracket[[<]]$Class[[S]]$Bracket[[<]]int$Bracket[[>]]$Bracket[[>]] $LocalVariable_def[[s1]]; |
954 | $Class[[S]]$Bracket[[<]]$Class[[S]]$Bracket[[<]]int$Bracket[[>]]\ |
955 | $Bracket[[>]] $LocalVariable_def[[s2]]; |
956 | $Class[[S]]$Bracket[[<]]$Class[[S]]$Bracket[[<]]$Class[[S]]$Bracket[[<]]int$Bracket[[>]]$Bracket[[>]]$Bracket[[>]] $LocalVariable_def[[s3]]; |
957 | $Class[[S]]$Bracket[[<]]$Class[[S]]$Bracket[[<]]$Class[[S]]$Bracket[[<]]int$Bracket[[>]]\ |
958 | $Bracket[[>]]$Bracket[[>]] $LocalVariable_def[[s4]]; |
959 | $Class[[S]]$Bracket[[<]]$Class[[S]]$Bracket[[<]]$Class[[S]]$Bracket[[<]]int$Bracket[[>]]\ |
960 | $Bracket[[>]]$Bracket[[>]] $LocalVariable_def[[s5]]; |
961 | $Class[[S]]$Bracket[[<]]$Class[[S]]$Bracket[[<]]$Class[[S]]$Bracket[[<]]int$Bracket[[>]]\ |
962 | $Bracket[[>]]$Bracket[[>]] $LocalVariable_def[[s6]]; |
963 | $Class[[S]]$Bracket[[<]]$Class[[S]]$Bracket[[<]]$Class[[S]]$Bracket[[<]]int$Bracket[[>]]$Bracket[[>]]\ |
964 | $Bracket[[>]] $LocalVariable_def[[s7]]; |
965 | } |
966 | )cpp" , |
967 | // Brackets support: One of the brackets is a macro. |
968 | R"cpp( |
969 | #define $Macro_decl[[LESS]] < |
970 | template $Macro[[LESS]] typename $TemplateParameter_def[[T]] > class $Class_def[[A]] {}; |
971 | )cpp" , |
972 | // Brackets support: Specializations |
973 | R"cpp( |
974 | template $Bracket[[<]]typename $TemplateParameter_def[[T]]$Bracket[[>]] class $Class_def[[S]] { |
975 | public: |
976 | template $Bracket[[<]]typename $TemplateParameter_def[[U]]$Bracket[[>]] class $Class_decl[[Nested]]; |
977 | }; |
978 | template $Bracket[[<]]$Bracket[[>]] class $Class_def[[S]]$Bracket[[<]]int$Bracket[[>]] {}; |
979 | template $Bracket[[<]]typename $TemplateParameter_def[[T]]$Bracket[[>]] |
980 | class $Class_def[[S]]$Bracket[[<]]$TemplateParameter[[T]]*$Bracket[[>]] {}; |
981 | template $Bracket[[<]]typename $TemplateParameter_def[[T]]$Bracket[[>]] |
982 | template $Bracket[[<]]typename $TemplateParameter_def[[U]]$Bracket[[>]] |
983 | class $Class[[S]]$Bracket[[<]]$TemplateParameter[[T]]$Bracket[[>]]::$Class_def[[Nested]] {}; |
984 | template $Bracket[[<]]$Bracket[[>]] |
985 | template $Bracket[[<]]$Bracket[[>]] |
986 | class $Class[[S]]$Bracket[[<]]float$Bracket[[>]]::$Class_def[[Nested]]$Bracket[[<]]float$Bracket[[>]] {}; |
987 | template $Bracket[[<]]typename $TemplateParameter_def[[T]]$Bracket[[>]] void $Function_decl[[foo]](); |
988 | void $Function_def[[bar]]() { |
989 | $Function[[foo]]$Bracket[[<]]int$Bracket[[>]](); |
990 | } |
991 | template $Bracket[[<]]typename $TemplateParameter_def[[T]]$Bracket[[>]] constexpr int $Variable_def_readonly[[V]] = 42; |
992 | constexpr int $Variable_def_readonly[[Y]] = $Variable_readonly[[V]]$Bracket[[<]]char$Bracket[[>]]; |
993 | template $Bracket[[<]]$Bracket[[>]] |
994 | constexpr int $Variable_def_readonly[[V]]$Bracket[[<]]int$Bracket[[>]] = 5; |
995 | template $Bracket[[<]]typename $TemplateParameter_def[[T]]$Bracket[[>]] |
996 | constexpr int $Variable_def_readonly[[V]]$Bracket[[<]]$TemplateParameter[[T]]*$Bracket[[>]] = 6; |
997 | template $Bracket[[<]]typename$Bracket[[>]] |
998 | class $Class_def[[A]] { |
999 | enum class $Enum_decl[[E]]; |
1000 | }; |
1001 | template $Bracket[[<]]typename $TemplateParameter_def[[T]]$Bracket[[>]] |
1002 | enum class $Class[[A]]$Bracket[[<]]$TemplateParameter[[T]]$Bracket[[>]]::$Enum_decl[[E]] {$EnumConstant_decl_readonly[[X]], $EnumConstant_decl_readonly[[Y]], $EnumConstant_decl_readonly[[Z]]}; |
1003 | template $Bracket[[<]]class $TemplateParameter_def[[T]]$Bracket[[>]] |
1004 | class $Class_def[[B]] { |
1005 | template $Bracket[[<]]class $TemplateParameter_def[[U]]$Bracket[[>]] void $Method_def[[foo]]($TemplateParameter[[U]]) { } |
1006 | template$Bracket[[<]]$Bracket[[>]] void $Method_def[[foo]]$Bracket[[<]]int$Bracket[[>]](int) { } |
1007 | friend void $Function_decl[[foo]]$Bracket[[<]]$Bracket[[>]]($TemplateParameter[[T]]); |
1008 | }; |
1009 | )cpp" , |
1010 | // Brackets support: Function calls |
1011 | R"cpp( |
1012 | template $Bracket[[<]]typename$Bracket[[>]] void $Function_decl[[free]](); |
1013 | template $Bracket[[<]]typename $TemplateParameter_def[[T]]$Bracket[[>]] |
1014 | struct $Class_def[[A]] { |
1015 | template $Bracket[[<]]typename$Bracket[[>]] void $Method_decl[[mem]](); |
1016 | }; |
1017 | void $Function_def[[foo]]() { |
1018 | $Class[[A]]$Bracket[[<]]int$Bracket[[>]] $LocalVariable_def[[a]]; |
1019 | $LocalVariable[[a]].$Method[[mem]]$Bracket[[<]]int$Bracket[[>]](); |
1020 | } |
1021 | template$Bracket[[<]]typename $TemplateParameter_def[[T]]$Bracket[[>]] |
1022 | void $Function_def[[bar]]() { |
1023 | $Function[[free]]$Bracket[[<]]$TemplateParameter[[T]]$Bracket[[>]](); |
1024 | $Class[[A]]$Bracket[[<]]int$Bracket[[>]] $LocalVariable_def[[a]]; |
1025 | $LocalVariable[[a]].$Method[[mem]]$Bracket[[<]]$TemplateParameter[[T]]$Bracket[[>]](); |
1026 | $Class[[A]]$Bracket[[<]]$TemplateParameter[[T]]$Bracket[[>]] $LocalVariable_def[[b]]; |
1027 | $LocalVariable[[b]].template $Method_dependentName[[mem]]$Bracket[[<]]$TemplateParameter[[T]]$Bracket[[>]](); |
1028 | } |
1029 | )cpp" , |
1030 | // Brackets support: Concepts |
1031 | R"cpp( |
1032 | template $Bracket[[<]]typename $TemplateParameter_def[[T]]$Bracket[[>]] |
1033 | concept $Concept_decl[[C]] = true; |
1034 | template $Bracket[[<]]typename $TemplateParameter_def[[T]]$Bracket[[>]] requires $Concept[[C]]$Bracket[[<]]$TemplateParameter[[T]]$Bracket[[>]] |
1035 | class $Class_def[[Z]] {}; |
1036 | template $Bracket[[<]]typename, typename$Bracket[[>]] |
1037 | concept $Concept_decl[[C2]] = true; |
1038 | template $Bracket[[<]]$Concept[[C2]]$Bracket[[<]]int$Bracket[[>]] $TemplateParameter_def[[A]]$Bracket[[>]] |
1039 | class $Class_def[[B]] {}; |
1040 | )cpp" , |
1041 | // Labels |
1042 | R"cpp( |
1043 | bool $Function_def[[funcWithGoto]](bool $Parameter_def[[b]]) { |
1044 | if ($Parameter[[b]]) |
1045 | goto $Label[[return_true]]; |
1046 | return false; |
1047 | $Label_decl[[return_true]]: |
1048 | return true; |
1049 | } |
1050 | )cpp" , |
1051 | // no crash |
1052 | R"cpp( |
1053 | struct $Class_def[[Foo]] { |
1054 | void $Method_decl[[foo]](); |
1055 | }; |
1056 | |
1057 | void $Function_def[[s]]($Class[[Foo]] $Parameter_def[[f]]) { |
1058 | auto $LocalVariable_def[[k]] = $Operator[[&]]$Class[[Foo]]::$Method[[foo]]; |
1059 | ($Parameter[[f]]$Operator[[.*]]$LocalVariable[[k]])(); // no crash on VisitCXXMemberCallExpr |
1060 | } |
1061 | )cpp" , |
1062 | R"cpp( |
1063 | template$Bracket[[<]]typename$Bracket[[>]] |
1064 | class $Class_def[[Foo]] {}; |
1065 | |
1066 | template$Bracket[[<]]typename $TemplateParameter_def[[T]]$Bracket[[>]] |
1067 | void $Function_def[[k]]() { |
1068 | auto $LocalVariable_def[[s]] = $Operator[[new]] $Class[[Foo]]$Bracket[[<]]$TemplateParameter[[T]]$Bracket[[>]](); |
1069 | $Operator[[delete]] $LocalVariable[[s]]; |
1070 | } |
1071 | )cpp" , |
1072 | // Recursive UsingValueDecl |
1073 | R"cpp( |
1074 | template $Bracket[[<]]int$Bracket[[>]] class $Class_def[[X]] { |
1075 | template $Bracket[[<]]int$Bracket[[>]] class $Class_def[[Y]] { |
1076 | using $Class[[Y]]$Bracket[[<]]0$Bracket[[>]]::$Unknown_dependentName[[xxx]]; |
1077 | }; |
1078 | }; |
1079 | )cpp" , |
1080 | // Heuristically resolved IndirectFieldDecl |
1081 | R"cpp( |
1082 | template $Bracket[[<]]typename $TemplateParameter_def[[T]]$Bracket[[>]] |
1083 | struct $Class_def[[Base]] { |
1084 | struct { |
1085 | int $Field_decl[[waldo]]; |
1086 | }; |
1087 | }; |
1088 | template $Bracket[[<]]typename $TemplateParameter_def[[T]]$Bracket[[>]] |
1089 | struct $Class_def[[Derived]] : $Class[[Base]]$Bracket[[<]]$TemplateParameter[[T]]$Bracket[[>]] { |
1090 | using $Class[[Base]]$Bracket[[<]]$TemplateParameter[[T]]$Bracket[[>]]::$Field_dependentName[[waldo]]; |
1091 | void $Method_def[[foo]]() { |
1092 | $Field_dependentName[[waldo]]; |
1093 | } |
1094 | }; |
1095 | )cpp" }; |
1096 | for (const auto &TestCase : TestCases) |
1097 | // Mask off scope modifiers to keep the tests manageable. |
1098 | // They're tested separately. |
1099 | checkHighlightings(Code: TestCase, AdditionalFiles: {}, ModifierMask: ~ScopeModifierMask); |
1100 | |
1101 | checkHighlightings(Code: R"cpp( |
1102 | class $Class_def[[A]] { |
1103 | #include "imp.h" |
1104 | }; |
1105 | )cpp" , |
1106 | AdditionalFiles: {{"imp.h" , R"cpp( |
1107 | int someMethod(); |
1108 | void otherMethod(); |
1109 | )cpp" }}, |
1110 | ModifierMask: ~ScopeModifierMask); |
1111 | |
1112 | // A separate test for macros in headers. |
1113 | checkHighlightings(Code: R"cpp( |
1114 | #include "imp.h" |
1115 | $Macro[[DEFINE_Y]] |
1116 | $Macro[[DXYZ_Y]](A); |
1117 | )cpp" , |
1118 | AdditionalFiles: {{"imp.h" , R"cpp( |
1119 | #define DXYZ(X) class X {}; |
1120 | #define DXYZ_Y(Y) DXYZ(x##Y) |
1121 | #define DEFINE(X) int X; |
1122 | #define DEFINE_Y DEFINE(Y) |
1123 | )cpp" }}, |
1124 | ModifierMask: ~ScopeModifierMask); |
1125 | |
1126 | checkHighlightings(Code: R"cpp( |
1127 | #include "SYSObject.h" |
1128 | @interface $Class_defaultLibrary[[SYSObject]] ($Namespace_def[[UserCategory]]) |
1129 | @property(nonatomic, readonly) int $Field_decl_readonly[[user_property]]; |
1130 | @end |
1131 | int $Function_def[[somethingUsingSystemSymbols]]() { |
1132 | $Class_defaultLibrary[[SYSObject]] *$LocalVariable_def[[obj]] = [$Class_defaultLibrary[[SYSObject]] $StaticMethod_static_defaultLibrary[[new]]]; |
1133 | return $LocalVariable[[obj]].$Field_defaultLibrary[[value]] $Operator[[+]] $LocalVariable[[obj]].$Field_readonly[[user_property]]; |
1134 | } |
1135 | )cpp" , |
1136 | AdditionalFiles: {{"SystemSDK/SYSObject.h" , R"cpp( |
1137 | @interface SYSObject |
1138 | @property(nonatomic, assign) int value; |
1139 | + (instancetype)new; |
1140 | @end |
1141 | )cpp" }}, |
1142 | ModifierMask: ~ScopeModifierMask, AdditionalArgs: {"-isystemSystemSDK/" }); |
1143 | } |
1144 | |
1145 | TEST(SemanticHighlighting, ScopeModifiers) { |
1146 | const char *TestCases[] = { |
1147 | R"cpp( |
1148 | static int $Variable_fileScope[[x]]; |
1149 | namespace $Namespace_globalScope[[ns]] { |
1150 | class $Class_globalScope[[x]]; |
1151 | } |
1152 | namespace { |
1153 | void $Function_fileScope[[foo]](); |
1154 | } |
1155 | )cpp" , |
1156 | R"cpp( |
1157 | void $Function_globalScope[[foo]](int $Parameter_functionScope[[y]]) { |
1158 | int $LocalVariable_functionScope[[z]]; |
1159 | } |
1160 | )cpp" , |
1161 | R"cpp( |
1162 | // Lambdas are considered functions, not classes. |
1163 | auto $Variable_fileScope[[x]] = [$LocalVariable_functionScope[[m]](42)] { |
1164 | return $LocalVariable_functionScope[[m]]; |
1165 | }; |
1166 | )cpp" , |
1167 | R"cpp( |
1168 | // Classes in functions are classes. |
1169 | void $Function_globalScope[[foo]]() { |
1170 | class $Class_functionScope[[X]] { |
1171 | int $Field_classScope[[x]]; |
1172 | }; |
1173 | }; |
1174 | )cpp" , |
1175 | R"cpp( |
1176 | template $Bracket[[<]]int $TemplateParameter_classScope[[T]]$Bracket[[>]] |
1177 | class $Class_globalScope[[X]] { |
1178 | }; |
1179 | )cpp" , |
1180 | R"cpp( |
1181 | // No useful scope for template parameters of variable templates. |
1182 | template $Bracket[[<]]typename $TemplateParameter[[A]]$Bracket[[>]] |
1183 | unsigned $Variable_globalScope[[X]] = |
1184 | $TemplateParameter[[A]]::$Unknown_classScope[[x]]; |
1185 | )cpp" , |
1186 | R"cpp( |
1187 | #define $Macro_globalScope[[X]] 1 |
1188 | int $Variable_globalScope[[Y]] = $Macro_globalScope[[X]]; |
1189 | )cpp" , |
1190 | }; |
1191 | |
1192 | for (const char *Test : TestCases) |
1193 | checkHighlightings(Code: Test, AdditionalFiles: {}, ModifierMask: ScopeModifierMask); |
1194 | } |
1195 | |
1196 | // Ranges are highlighted as variables, unless highlighted as $Function etc. |
1197 | std::vector<HighlightingToken> tokens(llvm::StringRef MarkedText) { |
1198 | Annotations A(MarkedText); |
1199 | std::vector<HighlightingToken> Results; |
1200 | for (const Range& R : A.ranges()) |
1201 | Results.push_back(x: {.Kind: HighlightingKind::Variable, .Modifiers: 0, .R: R}); |
1202 | for (unsigned I = 0; I < static_cast<unsigned>(HighlightingKind::LastKind); ++I) { |
1203 | HighlightingKind Kind = static_cast<HighlightingKind>(I); |
1204 | for (const Range& R : A.ranges(Name: llvm::to_string(Value: Kind))) |
1205 | Results.push_back(x: {.Kind: Kind, .Modifiers: 0, .R: R}); |
1206 | } |
1207 | llvm::sort(C&: Results); |
1208 | return Results; |
1209 | } |
1210 | |
1211 | TEST(SemanticHighlighting, toSemanticTokens) { |
1212 | auto Tokens = tokens(MarkedText: R"( |
1213 | [[blah]] |
1214 | |
1215 | $Function[[big]] [[bang]] |
1216 | )" ); |
1217 | Tokens.front().Modifiers |= unsigned(HighlightingModifier::Declaration); |
1218 | Tokens.front().Modifiers |= unsigned(HighlightingModifier::Readonly); |
1219 | auto Results = toSemanticTokens(Tokens, /*Code=*/"" ); |
1220 | |
1221 | ASSERT_THAT(Results, SizeIs(3)); |
1222 | EXPECT_EQ(Results[0].tokenType, unsigned(HighlightingKind::Variable)); |
1223 | EXPECT_EQ(Results[0].tokenModifiers, |
1224 | unsigned(HighlightingModifier::Declaration) | |
1225 | unsigned(HighlightingModifier::Readonly)); |
1226 | EXPECT_EQ(Results[0].deltaLine, 1u); |
1227 | EXPECT_EQ(Results[0].deltaStart, 1u); |
1228 | EXPECT_EQ(Results[0].length, 4u); |
1229 | |
1230 | EXPECT_EQ(Results[1].tokenType, unsigned(HighlightingKind::Function)); |
1231 | EXPECT_EQ(Results[1].tokenModifiers, 0u); |
1232 | EXPECT_EQ(Results[1].deltaLine, 2u); |
1233 | EXPECT_EQ(Results[1].deltaStart, 4u); |
1234 | EXPECT_EQ(Results[1].length, 3u); |
1235 | |
1236 | EXPECT_EQ(Results[2].tokenType, unsigned(HighlightingKind::Variable)); |
1237 | EXPECT_EQ(Results[1].tokenModifiers, 0u); |
1238 | EXPECT_EQ(Results[2].deltaLine, 0u); |
1239 | EXPECT_EQ(Results[2].deltaStart, 4u); |
1240 | EXPECT_EQ(Results[2].length, 4u); |
1241 | } |
1242 | |
1243 | TEST(SemanticHighlighting, diffSemanticTokens) { |
1244 | auto Before = toSemanticTokens(tokens(MarkedText: R"( |
1245 | [[foo]] [[bar]] [[baz]] |
1246 | [[one]] [[two]] [[three]] |
1247 | )" ), |
1248 | /*Code=*/"" ); |
1249 | EXPECT_THAT(diffTokens(Before, Before), IsEmpty()); |
1250 | |
1251 | auto After = toSemanticTokens(tokens(MarkedText: R"( |
1252 | [[foo]] [[hello]] [[world]] [[baz]] |
1253 | [[one]] [[two]] [[three]] |
1254 | )" ), |
1255 | /*Code=*/"" ); |
1256 | |
1257 | // Replace [bar, baz] with [hello, world, baz] |
1258 | auto Diff = diffTokens(Before, After); |
1259 | ASSERT_THAT(Diff, SizeIs(1)); |
1260 | EXPECT_EQ(1u, Diff.front().startToken); |
1261 | EXPECT_EQ(2u, Diff.front().deleteTokens); |
1262 | ASSERT_THAT(Diff.front().tokens, SizeIs(3)); |
1263 | // hello |
1264 | EXPECT_EQ(0u, Diff.front().tokens[0].deltaLine); |
1265 | EXPECT_EQ(4u, Diff.front().tokens[0].deltaStart); |
1266 | EXPECT_EQ(5u, Diff.front().tokens[0].length); |
1267 | // world |
1268 | EXPECT_EQ(0u, Diff.front().tokens[1].deltaLine); |
1269 | EXPECT_EQ(6u, Diff.front().tokens[1].deltaStart); |
1270 | EXPECT_EQ(5u, Diff.front().tokens[1].length); |
1271 | // baz |
1272 | EXPECT_EQ(0u, Diff.front().tokens[2].deltaLine); |
1273 | EXPECT_EQ(6u, Diff.front().tokens[2].deltaStart); |
1274 | EXPECT_EQ(3u, Diff.front().tokens[2].length); |
1275 | } |
1276 | |
1277 | TEST(SemanticHighlighting, MultilineTokens) { |
1278 | llvm::StringRef AnnotatedCode = R"cpp( |
1279 | [[fo |
1280 | o |
1281 | o]] [[bar]])cpp" ; |
1282 | auto Toks = toSemanticTokens(tokens(MarkedText: AnnotatedCode), |
1283 | Code: Annotations(AnnotatedCode).code()); |
1284 | ASSERT_THAT(Toks, SizeIs(4)); |
1285 | // foo |
1286 | EXPECT_EQ(Toks[0].deltaLine, 1u); |
1287 | EXPECT_EQ(Toks[0].deltaStart, 2u); |
1288 | EXPECT_EQ(Toks[0].length, 2u); |
1289 | EXPECT_EQ(Toks[1].deltaLine, 1u); |
1290 | EXPECT_EQ(Toks[1].deltaStart, 0u); |
1291 | EXPECT_EQ(Toks[1].length, 1u); |
1292 | EXPECT_EQ(Toks[2].deltaLine, 1u); |
1293 | EXPECT_EQ(Toks[2].deltaStart, 0u); |
1294 | EXPECT_EQ(Toks[2].length, 1u); |
1295 | |
1296 | // bar |
1297 | EXPECT_EQ(Toks[3].deltaLine, 0u); |
1298 | EXPECT_EQ(Toks[3].deltaStart, 2u); |
1299 | EXPECT_EQ(Toks[3].length, 3u); |
1300 | } |
1301 | |
1302 | TEST(SemanticHighlighting, WithHighlightingFilter) { |
1303 | llvm::StringRef AnnotatedCode = R"cpp( |
1304 | int *$Variable[[x]] = new int; |
1305 | )cpp" ; |
1306 | Config Cfg; |
1307 | Cfg.SemanticTokens.DisabledKinds = {"Operator" }; |
1308 | Cfg.SemanticTokens.DisabledModifiers = {"Declaration" , "Definition" }; |
1309 | WithContextValue WithCfg(Config::Key, std::move(Cfg)); |
1310 | checkHighlightings(Code: AnnotatedCode, AdditionalFiles: {}, ModifierMask: ~ScopeModifierMask); |
1311 | } |
1312 | } // namespace |
1313 | } // namespace clangd |
1314 | } // namespace clang |
1315 | |