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