Skip to repository content653 lines · 19.7 KB · rust
tenant.openagents/omega
No repository description is available.
OpenAgents Git authority 2026-07-28T03:27:58.561Z Public web read
NIP-34 coordinate
30617:7649603503856e5148d571eac2766b288a8ff1e9e35d380337a1d2b0015b4f92:omegaMaintainersHidden in public view
References2 branches · 1 tag
Read-only clone
git clone https://openagents.com/git/tenant.openagents/omega.gitBrowse files
cpp.rs
1use settings::SemanticTokenRules;
2
3pub(crate) fn semantic_token_rules() -> SemanticTokenRules {
4 let content = grammars::get_file("cpp/semantic_token_rules.json")
5 .expect("missing cpp/semantic_token_rules.json");
6 let json = std::str::from_utf8(&content.data).expect("invalid utf-8 in semantic_token_rules");
7 settings::parse_json_with_comments::<SemanticTokenRules>(json)
8 .expect("failed to parse cpp semantic_token_rules.json")
9}
10
11#[cfg(test)]
12mod tests {
13 use gpui::{AppContext as _, BorrowAppContext, TestAppContext};
14 use language::{AutoindentMode, Buffer};
15 use settings::SettingsStore;
16 use std::num::NonZeroU32;
17 use unindent::Unindent;
18
19 #[gpui::test]
20 async fn test_cpp_autoindent_switch_case(cx: &mut TestAppContext) {
21 cx.update(|cx| {
22 let test_settings = SettingsStore::test(cx);
23 cx.set_global(test_settings);
24 cx.update_global::<SettingsStore, _>(|store, cx| {
25 store.update_user_settings(cx, |s| {
26 s.project.all_languages.defaults.tab_size = NonZeroU32::new(2);
27 });
28 });
29 });
30 let language = crate::language("cpp", tree_sitter_cpp::LANGUAGE.into());
31
32 cx.new(|cx| {
33 let mut buffer = Buffer::local("", cx).with_language(language, cx);
34
35 buffer.edit(
36 [(
37 0..0,
38 r#"
39 int main() {
40 switch (a) {
41 case 1:
42 b++;
43 break;
44 case 2:
45 case 3:
46 c++;
47 break;
48 default:
49 d++;
50 }
51 }
52 "#
53 .unindent(),
54 )],
55 Some(AutoindentMode::EachLine),
56 cx,
57 );
58 assert_eq!(
59 buffer.text(),
60 r#"
61 int main() {
62 switch (a) {
63 case 1:
64 b++;
65 break;
66 case 2:
67 case 3:
68 c++;
69 break;
70 default:
71 d++;
72 }
73 }
74 "#
75 .unindent(),
76 "statements under a case label should be indented, and the next label outdented"
77 );
78
79 buffer
80 });
81 }
82
83 #[gpui::test]
84 async fn test_cpp_autoindent_access_specifier(cx: &mut TestAppContext) {
85 cx.update(|cx| {
86 let test_settings = SettingsStore::test(cx);
87 cx.set_global(test_settings);
88 cx.update_global::<SettingsStore, _>(|store, cx| {
89 store.update_user_settings(cx, |s| {
90 s.project.all_languages.defaults.tab_size = NonZeroU32::new(2);
91 });
92 });
93 });
94 let language = crate::language("cpp", tree_sitter_cpp::LANGUAGE.into());
95
96 cx.new(|cx| {
97 let mut buffer = Buffer::local("", cx).with_language(language, cx);
98
99 buffer.edit(
100 [(
101 0..0,
102 r#"
103 class Foo {
104 public:
105 void bar();
106 private:
107 int x;
108 };
109 "#
110 .unindent(),
111 )],
112 Some(AutoindentMode::EachLine),
113 cx,
114 );
115 assert_eq!(
116 buffer.text(),
117 r#"
118 class Foo {
119 public:
120 void bar();
121 private:
122 int x;
123 };
124 "#
125 .unindent(),
126 "members after access specifiers should be indented one level deeper than the specifier"
127 );
128
129 buffer
130 });
131 }
132
133 #[gpui::test]
134 async fn test_cpp_autoindent_access_specifier_next_line(cx: &mut TestAppContext) {
135 cx.update(|cx| {
136 let test_settings = SettingsStore::test(cx);
137 cx.set_global(test_settings);
138 cx.update_global::<SettingsStore, _>(|store, cx| {
139 store.update_user_settings(cx, |s| {
140 s.project.all_languages.defaults.tab_size = NonZeroU32::new(2);
141 });
142 });
143 });
144 let language = crate::language("cpp", tree_sitter_cpp::LANGUAGE.into());
145
146 cx.new(|cx| {
147 let mut buffer = Buffer::local("", cx).with_language(language, cx);
148
149 buffer.edit(
150 [(
151 0..0,
152 r#"
153 class Foo {
154 public:
155 void bar();
156 void baz();
157 private:
158 int x;
159 };
160 "#
161 .unindent(),
162 )],
163 Some(AutoindentMode::EachLine),
164 cx,
165 );
166 assert_eq!(
167 buffer.text(),
168 r#"
169 class Foo {
170 public:
171 void bar();
172 void baz();
173 private:
174 int x;
175 };
176 "#
177 .unindent(),
178 "members after access specifiers should be indented one level deeper than the specifier"
179 );
180
181 buffer
182 });
183 }
184
185 #[gpui::test]
186 async fn test_cpp_autoindent_nested_class_access_specifiers(cx: &mut TestAppContext) {
187 cx.update(|cx| {
188 let test_settings = SettingsStore::test(cx);
189 cx.set_global(test_settings);
190 cx.update_global::<SettingsStore, _>(|store, cx| {
191 store.update_user_settings(cx, |s| {
192 s.project.all_languages.defaults.tab_size = NonZeroU32::new(2);
193 });
194 });
195 });
196 let language = crate::language("cpp", tree_sitter_cpp::LANGUAGE.into());
197
198 cx.new(|cx| {
199 let mut buffer = Buffer::local("", cx).with_language(language, cx);
200
201 buffer.edit(
202 [(
203 0..0,
204 r#"
205 class Outer {
206 public:
207 class Inner {
208 public:
209 void inner_pub();
210 private:
211 int inner_priv;
212 };
213 private:
214 int outer_priv;
215 };
216 "#
217 .unindent(),
218 )],
219 Some(AutoindentMode::EachLine),
220 cx,
221 );
222 assert_eq!(
223 buffer.text(),
224 r#"
225 class Outer {
226 public:
227 class Inner {
228 public:
229 void inner_pub();
230 private:
231 int inner_priv;
232 };
233 private:
234 int outer_priv;
235 };
236 "#
237 .unindent(),
238 "nested class access specifiers should indent independently at each nesting level"
239 );
240
241 buffer
242 });
243 }
244
245 #[gpui::test]
246 async fn test_cpp_autoindent_consecutive_access_specifiers(cx: &mut TestAppContext) {
247 cx.update(|cx| {
248 let test_settings = SettingsStore::test(cx);
249 cx.set_global(test_settings);
250 cx.update_global::<SettingsStore, _>(|store, cx| {
251 store.update_user_settings(cx, |s| {
252 s.project.all_languages.defaults.tab_size = NonZeroU32::new(2);
253 });
254 });
255 });
256 let language = crate::language("cpp", tree_sitter_cpp::LANGUAGE.into());
257
258 cx.new(|cx| {
259 let mut buffer = Buffer::local("", cx).with_language(language, cx);
260
261 buffer.edit(
262 [(
263 0..0,
264 r#"
265 class Foo {
266 public:
267 protected:
268 private:
269 int x;
270 };
271 "#
272 .unindent(),
273 )],
274 Some(AutoindentMode::EachLine),
275 cx,
276 );
277 assert_eq!(
278 buffer.text(),
279 r#"
280 class Foo {
281 public:
282 protected:
283 private:
284 int x;
285 };
286 "#
287 .unindent(),
288 "consecutive access specifiers with no members between them should all align at class level"
289 );
290
291 buffer
292 });
293 }
294
295 #[gpui::test]
296 async fn test_cpp_autoindent_indented_access_specifiers(cx: &mut TestAppContext) {
297 cx.update(|cx| {
298 let test_settings = SettingsStore::test(cx);
299 cx.set_global(test_settings);
300 cx.update_global::<SettingsStore, _>(|store, cx| {
301 store.update_user_settings(cx, |s| {
302 s.project.all_languages.defaults.tab_size = NonZeroU32::new(2);
303 });
304 });
305 });
306 let language = crate::language("cpp", tree_sitter_cpp::LANGUAGE.into());
307
308 cx.new(|cx| {
309 let mut buffer = Buffer::local("", cx).with_language(language, cx);
310
311 buffer.edit(
312 [(
313 0..0,
314 r#"
315 class Foo {
316 int default_member;
317 public:
318 void pub_method();
319 private:
320 int priv_member;
321 };
322 "#
323 .unindent(),
324 )],
325 Some(AutoindentMode::EachLine),
326 cx,
327 );
328 assert_eq!(
329 buffer.text(),
330 r#"
331 class Foo {
332 int default_member;
333 public:
334 void pub_method();
335 private:
336 int priv_member;
337 };
338 "#
339 .unindent(),
340 "access specifiers should be indented one level inside class braces"
341 );
342
343 buffer
344 });
345 }
346
347 #[gpui::test]
348 async fn test_cpp_autoindent_access_specifier_with_method_bodies(cx: &mut TestAppContext) {
349 cx.update(|cx| {
350 let test_settings = SettingsStore::test(cx);
351 cx.set_global(test_settings);
352 cx.update_global::<SettingsStore, _>(|store, cx| {
353 store.update_user_settings(cx, |s| {
354 s.project.all_languages.defaults.tab_size = NonZeroU32::new(2);
355 });
356 });
357 });
358 let language = crate::language("cpp", tree_sitter_cpp::LANGUAGE.into());
359
360 cx.new(|cx| {
361 let mut buffer = Buffer::local("", cx).with_language(language, cx);
362
363 buffer.edit(
364 [(
365 0..0,
366 r#"
367 class Foo {
368 public:
369 void bar() {
370 if (x)
371 y++;
372 }
373 private:
374 int get_x() {
375 return x;
376 }
377 int x;
378 };
379 "#
380 .unindent(),
381 )],
382 Some(AutoindentMode::EachLine),
383 cx,
384 );
385 assert_eq!(
386 buffer.text(),
387 r#"
388 class Foo {
389 public:
390 void bar() {
391 if (x)
392 y++;
393 }
394 private:
395 int get_x() {
396 return x;
397 }
398 int x;
399 };
400 "#
401 .unindent(),
402 "method bodies inside access specifier sections should compose brace and specifier indent"
403 );
404
405 buffer
406 });
407 }
408
409 #[gpui::test]
410 async fn test_cpp_autoindent_basic(cx: &mut TestAppContext) {
411 cx.update(|cx| {
412 let test_settings = SettingsStore::test(cx);
413 cx.set_global(test_settings);
414 cx.update_global::<SettingsStore, _>(|store, cx| {
415 store.update_user_settings(cx, |s| {
416 s.project.all_languages.defaults.tab_size = NonZeroU32::new(2);
417 });
418 });
419 });
420 let language = crate::language("cpp", tree_sitter_cpp::LANGUAGE.into());
421
422 cx.new(|cx| {
423 let mut buffer = Buffer::local("", cx).with_language(language, cx);
424
425 buffer.edit([(0..0, "int main() {}")], None, cx);
426
427 let ix = buffer.len() - 1;
428 buffer.edit([(ix..ix, "\n\n")], Some(AutoindentMode::EachLine), cx);
429 assert_eq!(
430 buffer.text(),
431 "int main() {\n \n}",
432 "content inside braces should be indented"
433 );
434
435 buffer
436 });
437 }
438
439 #[gpui::test]
440 async fn test_cpp_autoindent_if_else(cx: &mut TestAppContext) {
441 cx.update(|cx| {
442 let test_settings = SettingsStore::test(cx);
443 cx.set_global(test_settings);
444 cx.update_global::<SettingsStore, _>(|store, cx| {
445 store.update_user_settings(cx, |s| {
446 s.project.all_languages.defaults.tab_size = NonZeroU32::new(2);
447 });
448 });
449 });
450 let language = crate::language("cpp", tree_sitter_cpp::LANGUAGE.into());
451
452 cx.new(|cx| {
453 let mut buffer = Buffer::local("", cx).with_language(language, cx);
454
455 buffer.edit(
456 [(
457 0..0,
458 r#"
459 int main() {
460 if (a)
461 b;
462 }
463 "#
464 .unindent(),
465 )],
466 Some(AutoindentMode::EachLine),
467 cx,
468 );
469 assert_eq!(
470 buffer.text(),
471 r#"
472 int main() {
473 if (a)
474 b;
475 }
476 "#
477 .unindent(),
478 "body of if-statement without braces should be indented"
479 );
480
481 let ix = buffer.len() - 4;
482 buffer.edit([(ix..ix, "\n.c")], Some(AutoindentMode::EachLine), cx);
483 assert_eq!(
484 buffer.text(),
485 r#"
486 int main() {
487 if (a)
488 b
489 .c;
490 }
491 "#
492 .unindent(),
493 "field expression (.c) should be indented further than the statement body"
494 );
495
496 buffer.edit([(0..buffer.len(), "")], Some(AutoindentMode::EachLine), cx);
497 buffer.edit(
498 [(
499 0..0,
500 r#"
501 int main() {
502 if (a) a++;
503 else b++;
504 }
505 "#
506 .unindent(),
507 )],
508 Some(AutoindentMode::EachLine),
509 cx,
510 );
511 assert_eq!(
512 buffer.text(),
513 r#"
514 int main() {
515 if (a) a++;
516 else b++;
517 }
518 "#
519 .unindent(),
520 "single-line if/else without braces should align at the same level"
521 );
522
523 buffer.edit([(0..buffer.len(), "")], Some(AutoindentMode::EachLine), cx);
524 buffer.edit(
525 [(
526 0..0,
527 r#"
528 int main() {
529 if (a)
530 b++;
531 else
532 c++;
533 }
534 "#
535 .unindent(),
536 )],
537 Some(AutoindentMode::EachLine),
538 cx,
539 );
540 assert_eq!(
541 buffer.text(),
542 r#"
543 int main() {
544 if (a)
545 b++;
546 else
547 c++;
548 }
549 "#
550 .unindent(),
551 "multi-line if/else without braces should indent statement bodies"
552 );
553
554 buffer.edit([(0..buffer.len(), "")], Some(AutoindentMode::EachLine), cx);
555 buffer.edit(
556 [(
557 0..0,
558 r#"
559 int main() {
560 if (a)
561 if (b)
562 c++;
563 }
564 "#
565 .unindent(),
566 )],
567 Some(AutoindentMode::EachLine),
568 cx,
569 );
570 assert_eq!(
571 buffer.text(),
572 r#"
573 int main() {
574 if (a)
575 if (b)
576 c++;
577 }
578 "#
579 .unindent(),
580 "nested if statements without braces should indent properly"
581 );
582
583 buffer.edit([(0..buffer.len(), "")], Some(AutoindentMode::EachLine), cx);
584 buffer.edit(
585 [(
586 0..0,
587 r#"
588 int main() {
589 if (a)
590 b++;
591 else if (c)
592 d++;
593 else
594 f++;
595 }
596 "#
597 .unindent(),
598 )],
599 Some(AutoindentMode::EachLine),
600 cx,
601 );
602 assert_eq!(
603 buffer.text(),
604 r#"
605 int main() {
606 if (a)
607 b++;
608 else if (c)
609 d++;
610 else
611 f++;
612 }
613 "#
614 .unindent(),
615 "else-if chains should align all conditions at same level with indented bodies"
616 );
617
618 buffer.edit([(0..buffer.len(), "")], Some(AutoindentMode::EachLine), cx);
619 buffer.edit(
620 [(
621 0..0,
622 r#"
623 int main() {
624 if (a) {
625 b++;
626 } else
627 c++;
628 }
629 "#
630 .unindent(),
631 )],
632 Some(AutoindentMode::EachLine),
633 cx,
634 );
635 assert_eq!(
636 buffer.text(),
637 r#"
638 int main() {
639 if (a) {
640 b++;
641 } else
642 c++;
643 }
644 "#
645 .unindent(),
646 "mixed braces should indent properly"
647 );
648
649 buffer
650 });
651 }
652}
653