cpp.rs

  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}