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_basic(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([(0..0, "int main() {}")], None, cx);
36
37 let ix = buffer.len() - 1;
38 buffer.edit([(ix..ix, "\n\n")], Some(AutoindentMode::EachLine), cx);
39 assert_eq!(
40 buffer.text(),
41 "int main() {\n \n}",
42 "content inside braces should be indented"
43 );
44
45 buffer
46 });
47 }
48
49 #[gpui::test]
50 async fn test_cpp_autoindent_if_else(cx: &mut TestAppContext) {
51 cx.update(|cx| {
52 let test_settings = SettingsStore::test(cx);
53 cx.set_global(test_settings);
54 cx.update_global::<SettingsStore, _>(|store, cx| {
55 store.update_user_settings(cx, |s| {
56 s.project.all_languages.defaults.tab_size = NonZeroU32::new(2);
57 });
58 });
59 });
60 let language = crate::language("cpp", tree_sitter_cpp::LANGUAGE.into());
61
62 cx.new(|cx| {
63 let mut buffer = Buffer::local("", cx).with_language(language, cx);
64
65 buffer.edit(
66 [(
67 0..0,
68 r#"
69 int main() {
70 if (a)
71 b;
72 }
73 "#
74 .unindent(),
75 )],
76 Some(AutoindentMode::EachLine),
77 cx,
78 );
79 assert_eq!(
80 buffer.text(),
81 r#"
82 int main() {
83 if (a)
84 b;
85 }
86 "#
87 .unindent(),
88 "body of if-statement without braces should be indented"
89 );
90
91 let ix = buffer.len() - 4;
92 buffer.edit([(ix..ix, "\n.c")], Some(AutoindentMode::EachLine), cx);
93 assert_eq!(
94 buffer.text(),
95 r#"
96 int main() {
97 if (a)
98 b
99 .c;
100 }
101 "#
102 .unindent(),
103 "field expression (.c) should be indented further than the statement body"
104 );
105
106 buffer.edit([(0..buffer.len(), "")], Some(AutoindentMode::EachLine), cx);
107 buffer.edit(
108 [(
109 0..0,
110 r#"
111 int main() {
112 if (a) a++;
113 else b++;
114 }
115 "#
116 .unindent(),
117 )],
118 Some(AutoindentMode::EachLine),
119 cx,
120 );
121 assert_eq!(
122 buffer.text(),
123 r#"
124 int main() {
125 if (a) a++;
126 else b++;
127 }
128 "#
129 .unindent(),
130 "single-line if/else without braces should align at the same level"
131 );
132
133 buffer.edit([(0..buffer.len(), "")], Some(AutoindentMode::EachLine), cx);
134 buffer.edit(
135 [(
136 0..0,
137 r#"
138 int main() {
139 if (a)
140 b++;
141 else
142 c++;
143 }
144 "#
145 .unindent(),
146 )],
147 Some(AutoindentMode::EachLine),
148 cx,
149 );
150 assert_eq!(
151 buffer.text(),
152 r#"
153 int main() {
154 if (a)
155 b++;
156 else
157 c++;
158 }
159 "#
160 .unindent(),
161 "multi-line if/else without braces should indent statement bodies"
162 );
163
164 buffer.edit([(0..buffer.len(), "")], Some(AutoindentMode::EachLine), cx);
165 buffer.edit(
166 [(
167 0..0,
168 r#"
169 int main() {
170 if (a)
171 if (b)
172 c++;
173 }
174 "#
175 .unindent(),
176 )],
177 Some(AutoindentMode::EachLine),
178 cx,
179 );
180 assert_eq!(
181 buffer.text(),
182 r#"
183 int main() {
184 if (a)
185 if (b)
186 c++;
187 }
188 "#
189 .unindent(),
190 "nested if statements without braces should indent properly"
191 );
192
193 buffer.edit([(0..buffer.len(), "")], Some(AutoindentMode::EachLine), cx);
194 buffer.edit(
195 [(
196 0..0,
197 r#"
198 int main() {
199 if (a)
200 b++;
201 else if (c)
202 d++;
203 else
204 f++;
205 }
206 "#
207 .unindent(),
208 )],
209 Some(AutoindentMode::EachLine),
210 cx,
211 );
212 assert_eq!(
213 buffer.text(),
214 r#"
215 int main() {
216 if (a)
217 b++;
218 else if (c)
219 d++;
220 else
221 f++;
222 }
223 "#
224 .unindent(),
225 "else-if chains should align all conditions at same level with indented bodies"
226 );
227
228 buffer.edit([(0..buffer.len(), "")], Some(AutoindentMode::EachLine), cx);
229 buffer.edit(
230 [(
231 0..0,
232 r#"
233 int main() {
234 if (a) {
235 b++;
236 } else
237 c++;
238 }
239 "#
240 .unindent(),
241 )],
242 Some(AutoindentMode::EachLine),
243 cx,
244 );
245 assert_eq!(
246 buffer.text(),
247 r#"
248 int main() {
249 if (a) {
250 b++;
251 } else
252 c++;
253 }
254 "#
255 .unindent(),
256 "mixed braces should indent properly"
257 );
258
259 buffer
260 });
261 }
262}