1// use crate::language_settings::{
2// AllLanguageSettings, AllLanguageSettingsContent, LanguageSettingsContent,
3// };
4
5// use super::*;
6// use clock::ReplicaId;
7// use collections::BTreeMap;
8// use gpui2::{AppContext, Handle};
9// use indoc::indoc;
10// use proto::deserialize_operation;
11// use rand::prelude::*;
12// use regex::RegexBuilder;
13// use settings::SettingsStore;
14// use std::{
15// cell::RefCell,
16// env,
17// ops::Range,
18// rc::Rc,
19// time::{Duration, Instant},
20// };
21// use text::network::Network;
22// use text::LineEnding;
23// use unindent::Unindent as _;
24// use util::{assert_set_eq, post_inc, test::marked_text_ranges, RandomCharIter};
25
26// lazy_static! {
27// static ref TRAILING_WHITESPACE_REGEX: Regex = RegexBuilder::new("[ \t]+$")
28// .multi_line(true)
29// .build()
30// .unwrap();
31// }
32
33// #[cfg(test)]
34// #[ctor::ctor]
35// fn init_logger() {
36// if std::env::var("RUST_LOG").is_ok() {
37// env_logger::init();
38// }
39// }
40
41// #[gpui::test]
42// fn test_line_endings(cx: &mut gpui::AppContext) {
43// init_settings(cx, |_| {});
44
45// cx.add_model(|cx| {
46// let mut buffer = Buffer::new(0, cx.model_id() as u64, "one\r\ntwo\rthree")
47// .with_language(Arc::new(rust_lang()), cx);
48// assert_eq!(buffer.text(), "one\ntwo\nthree");
49// assert_eq!(buffer.line_ending(), LineEnding::Windows);
50
51// buffer.check_invariants();
52// buffer.edit(
53// [(buffer.len()..buffer.len(), "\r\nfour")],
54// Some(AutoindentMode::EachLine),
55// cx,
56// );
57// buffer.edit([(0..0, "zero\r\n")], None, cx);
58// assert_eq!(buffer.text(), "zero\none\ntwo\nthree\nfour");
59// assert_eq!(buffer.line_ending(), LineEnding::Windows);
60// buffer.check_invariants();
61
62// buffer
63// });
64// }
65
66// #[gpui::test]
67// fn test_select_language() {
68// let registry = Arc::new(LanguageRegistry::test());
69// registry.add(Arc::new(Language::new(
70// LanguageConfig {
71// name: "Rust".into(),
72// path_suffixes: vec!["rs".to_string()],
73// ..Default::default()
74// },
75// Some(tree_sitter_rust::language()),
76// )));
77// registry.add(Arc::new(Language::new(
78// LanguageConfig {
79// name: "Make".into(),
80// path_suffixes: vec!["Makefile".to_string(), "mk".to_string()],
81// ..Default::default()
82// },
83// Some(tree_sitter_rust::language()),
84// )));
85
86// // matching file extension
87// assert_eq!(
88// registry
89// .language_for_file("zed/lib.rs", None)
90// .now_or_never()
91// .and_then(|l| Some(l.ok()?.name())),
92// Some("Rust".into())
93// );
94// assert_eq!(
95// registry
96// .language_for_file("zed/lib.mk", None)
97// .now_or_never()
98// .and_then(|l| Some(l.ok()?.name())),
99// Some("Make".into())
100// );
101
102// // matching filename
103// assert_eq!(
104// registry
105// .language_for_file("zed/Makefile", None)
106// .now_or_never()
107// .and_then(|l| Some(l.ok()?.name())),
108// Some("Make".into())
109// );
110
111// // matching suffix that is not the full file extension or filename
112// assert_eq!(
113// registry
114// .language_for_file("zed/cars", None)
115// .now_or_never()
116// .and_then(|l| Some(l.ok()?.name())),
117// None
118// );
119// assert_eq!(
120// registry
121// .language_for_file("zed/a.cars", None)
122// .now_or_never()
123// .and_then(|l| Some(l.ok()?.name())),
124// None
125// );
126// assert_eq!(
127// registry
128// .language_for_file("zed/sumk", None)
129// .now_or_never()
130// .and_then(|l| Some(l.ok()?.name())),
131// None
132// );
133// }
134
135// #[gpui::test]
136// fn test_edit_events(cx: &mut gpui::AppContext) {
137// let mut now = Instant::now();
138// let buffer_1_events = Rc::new(RefCell::new(Vec::new()));
139// let buffer_2_events = Rc::new(RefCell::new(Vec::new()));
140
141// let buffer1 = cx.add_model(|cx| Buffer::new(0, cx.model_id() as u64, "abcdef"));
142// let buffer2 = cx.add_model(|cx| Buffer::new(1, cx.model_id() as u64, "abcdef"));
143// let buffer1_ops = Rc::new(RefCell::new(Vec::new()));
144// buffer1.update(cx, {
145// let buffer1_ops = buffer1_ops.clone();
146// |buffer, cx| {
147// let buffer_1_events = buffer_1_events.clone();
148// cx.subscribe(&buffer1, move |_, _, event, _| match event.clone() {
149// Event::Operation(op) => buffer1_ops.borrow_mut().push(op),
150// event => buffer_1_events.borrow_mut().push(event),
151// })
152// .detach();
153// let buffer_2_events = buffer_2_events.clone();
154// cx.subscribe(&buffer2, move |_, _, event, _| {
155// buffer_2_events.borrow_mut().push(event.clone())
156// })
157// .detach();
158
159// // An edit emits an edited event, followed by a dirty changed event,
160// // since the buffer was previously in a clean state.
161// buffer.edit([(2..4, "XYZ")], None, cx);
162
163// // An empty transaction does not emit any events.
164// buffer.start_transaction();
165// buffer.end_transaction(cx);
166
167// // A transaction containing two edits emits one edited event.
168// now += Duration::from_secs(1);
169// buffer.start_transaction_at(now);
170// buffer.edit([(5..5, "u")], None, cx);
171// buffer.edit([(6..6, "w")], None, cx);
172// buffer.end_transaction_at(now, cx);
173
174// // Undoing a transaction emits one edited event.
175// buffer.undo(cx);
176// }
177// });
178
179// // Incorporating a set of remote ops emits a single edited event,
180// // followed by a dirty changed event.
181// buffer2.update(cx, |buffer, cx| {
182// buffer
183// .apply_ops(buffer1_ops.borrow_mut().drain(..), cx)
184// .unwrap();
185// });
186// assert_eq!(
187// mem::take(&mut *buffer_1_events.borrow_mut()),
188// vec![
189// Event::Edited,
190// Event::DirtyChanged,
191// Event::Edited,
192// Event::Edited,
193// ]
194// );
195// assert_eq!(
196// mem::take(&mut *buffer_2_events.borrow_mut()),
197// vec![Event::Edited, Event::DirtyChanged]
198// );
199
200// buffer1.update(cx, |buffer, cx| {
201// // Undoing the first transaction emits edited event, followed by a
202// // dirty changed event, since the buffer is again in a clean state.
203// buffer.undo(cx);
204// });
205// // Incorporating the remote ops again emits a single edited event,
206// // followed by a dirty changed event.
207// buffer2.update(cx, |buffer, cx| {
208// buffer
209// .apply_ops(buffer1_ops.borrow_mut().drain(..), cx)
210// .unwrap();
211// });
212// assert_eq!(
213// mem::take(&mut *buffer_1_events.borrow_mut()),
214// vec![Event::Edited, Event::DirtyChanged,]
215// );
216// assert_eq!(
217// mem::take(&mut *buffer_2_events.borrow_mut()),
218// vec![Event::Edited, Event::DirtyChanged]
219// );
220// }
221
222// #[gpui::test]
223// async fn test_apply_diff(cx: &mut gpui::TestAppContext) {
224// let text = "a\nbb\nccc\ndddd\neeeee\nffffff\n";
225// let buffer = cx.add_model(|cx| Buffer::new(0, cx.model_id() as u64, text));
226// let anchor = buffer.read_with(cx, |buffer, _| buffer.anchor_before(Point::new(3, 3)));
227
228// let text = "a\nccc\ndddd\nffffff\n";
229// let diff = buffer.read_with(cx, |b, cx| b.diff(text.into(), cx)).await;
230// buffer.update(cx, |buffer, cx| {
231// buffer.apply_diff(diff, cx).unwrap();
232// assert_eq!(buffer.text(), text);
233// assert_eq!(anchor.to_point(buffer), Point::new(2, 3));
234// });
235
236// let text = "a\n1\n\nccc\ndd2dd\nffffff\n";
237// let diff = buffer.read_with(cx, |b, cx| b.diff(text.into(), cx)).await;
238// buffer.update(cx, |buffer, cx| {
239// buffer.apply_diff(diff, cx).unwrap();
240// assert_eq!(buffer.text(), text);
241// assert_eq!(anchor.to_point(buffer), Point::new(4, 4));
242// });
243// }
244
245// #[gpui::test(iterations = 10)]
246// async fn test_normalize_whitespace(cx: &mut gpui::TestAppContext) {
247// let text = [
248// "zero", //
249// "one ", // 2 trailing spaces
250// "two", //
251// "three ", // 3 trailing spaces
252// "four", //
253// "five ", // 4 trailing spaces
254// ]
255// .join("\n");
256
257// let buffer = cx.add_model(|cx| Buffer::new(0, cx.model_id() as u64, text));
258
259// // Spawn a task to format the buffer's whitespace.
260// // Pause so that the foratting task starts running.
261// let format = buffer.read_with(cx, |buffer, cx| buffer.remove_trailing_whitespace(cx));
262// smol::future::yield_now().await;
263
264// // Edit the buffer while the normalization task is running.
265// let version_before_edit = buffer.read_with(cx, |buffer, _| buffer.version());
266// buffer.update(cx, |buffer, cx| {
267// buffer.edit(
268// [
269// (Point::new(0, 1)..Point::new(0, 1), "EE"),
270// (Point::new(3, 5)..Point::new(3, 5), "EEE"),
271// ],
272// None,
273// cx,
274// );
275// });
276
277// let format_diff = format.await;
278// buffer.update(cx, |buffer, cx| {
279// let version_before_format = format_diff.base_version.clone();
280// buffer.apply_diff(format_diff, cx);
281
282// // The outcome depends on the order of concurrent taks.
283// //
284// // If the edit occurred while searching for trailing whitespace ranges,
285// // then the trailing whitespace region touched by the edit is left intact.
286// if version_before_format == version_before_edit {
287// assert_eq!(
288// buffer.text(),
289// [
290// "zEEero", //
291// "one", //
292// "two", //
293// "threeEEE ", //
294// "four", //
295// "five", //
296// ]
297// .join("\n")
298// );
299// }
300// // Otherwise, all trailing whitespace is removed.
301// else {
302// assert_eq!(
303// buffer.text(),
304// [
305// "zEEero", //
306// "one", //
307// "two", //
308// "threeEEE", //
309// "four", //
310// "five", //
311// ]
312// .join("\n")
313// );
314// }
315// });
316// }
317
318// #[gpui::test]
319// async fn test_reparse(cx: &mut gpui::TestAppContext) {
320// let text = "fn a() {}";
321// let buffer = cx.add_model(|cx| {
322// Buffer::new(0, cx.model_id() as u64, text).with_language(Arc::new(rust_lang()), cx)
323// });
324
325// // Wait for the initial text to parse
326// buffer.condition(cx, |buffer, _| !buffer.is_parsing()).await;
327// assert_eq!(
328// get_tree_sexp(&buffer, cx),
329// concat!(
330// "(source_file (function_item name: (identifier) ",
331// "parameters: (parameters) ",
332// "body: (block)))"
333// )
334// );
335
336// buffer.update(cx, |buffer, _| {
337// buffer.set_sync_parse_timeout(Duration::ZERO)
338// });
339
340// // Perform some edits (add parameter and variable reference)
341// // Parsing doesn't begin until the transaction is complete
342// buffer.update(cx, |buf, cx| {
343// buf.start_transaction();
344
345// let offset = buf.text().find(')').unwrap();
346// buf.edit([(offset..offset, "b: C")], None, cx);
347// assert!(!buf.is_parsing());
348
349// let offset = buf.text().find('}').unwrap();
350// buf.edit([(offset..offset, " d; ")], None, cx);
351// assert!(!buf.is_parsing());
352
353// buf.end_transaction(cx);
354// assert_eq!(buf.text(), "fn a(b: C) { d; }");
355// assert!(buf.is_parsing());
356// });
357// buffer.condition(cx, |buffer, _| !buffer.is_parsing()).await;
358// assert_eq!(
359// get_tree_sexp(&buffer, cx),
360// concat!(
361// "(source_file (function_item name: (identifier) ",
362// "parameters: (parameters (parameter pattern: (identifier) type: (type_identifier))) ",
363// "body: (block (expression_statement (identifier)))))"
364// )
365// );
366
367// // Perform a series of edits without waiting for the current parse to complete:
368// // * turn identifier into a field expression
369// // * turn field expression into a method call
370// // * add a turbofish to the method call
371// buffer.update(cx, |buf, cx| {
372// let offset = buf.text().find(';').unwrap();
373// buf.edit([(offset..offset, ".e")], None, cx);
374// assert_eq!(buf.text(), "fn a(b: C) { d.e; }");
375// assert!(buf.is_parsing());
376// });
377// buffer.update(cx, |buf, cx| {
378// let offset = buf.text().find(';').unwrap();
379// buf.edit([(offset..offset, "(f)")], None, cx);
380// assert_eq!(buf.text(), "fn a(b: C) { d.e(f); }");
381// assert!(buf.is_parsing());
382// });
383// buffer.update(cx, |buf, cx| {
384// let offset = buf.text().find("(f)").unwrap();
385// buf.edit([(offset..offset, "::<G>")], None, cx);
386// assert_eq!(buf.text(), "fn a(b: C) { d.e::<G>(f); }");
387// assert!(buf.is_parsing());
388// });
389// buffer.condition(cx, |buffer, _| !buffer.is_parsing()).await;
390// assert_eq!(
391// get_tree_sexp(&buffer, cx),
392// concat!(
393// "(source_file (function_item name: (identifier) ",
394// "parameters: (parameters (parameter pattern: (identifier) type: (type_identifier))) ",
395// "body: (block (expression_statement (call_expression ",
396// "function: (generic_function ",
397// "function: (field_expression value: (identifier) field: (field_identifier)) ",
398// "type_arguments: (type_arguments (type_identifier))) ",
399// "arguments: (arguments (identifier)))))))",
400// )
401// );
402
403// buffer.update(cx, |buf, cx| {
404// buf.undo(cx);
405// buf.undo(cx);
406// buf.undo(cx);
407// buf.undo(cx);
408// assert_eq!(buf.text(), "fn a() {}");
409// assert!(buf.is_parsing());
410// });
411// buffer.condition(cx, |buffer, _| !buffer.is_parsing()).await;
412// assert_eq!(
413// get_tree_sexp(&buffer, cx),
414// concat!(
415// "(source_file (function_item name: (identifier) ",
416// "parameters: (parameters) ",
417// "body: (block)))"
418// )
419// );
420
421// buffer.update(cx, |buf, cx| {
422// buf.redo(cx);
423// buf.redo(cx);
424// buf.redo(cx);
425// buf.redo(cx);
426// assert_eq!(buf.text(), "fn a(b: C) { d.e::<G>(f); }");
427// assert!(buf.is_parsing());
428// });
429// buffer.condition(cx, |buffer, _| !buffer.is_parsing()).await;
430// assert_eq!(
431// get_tree_sexp(&buffer, cx),
432// concat!(
433// "(source_file (function_item name: (identifier) ",
434// "parameters: (parameters (parameter pattern: (identifier) type: (type_identifier))) ",
435// "body: (block (expression_statement (call_expression ",
436// "function: (generic_function ",
437// "function: (field_expression value: (identifier) field: (field_identifier)) ",
438// "type_arguments: (type_arguments (type_identifier))) ",
439// "arguments: (arguments (identifier)))))))",
440// )
441// );
442// }
443
444// #[gpui::test]
445// async fn test_resetting_language(cx: &mut gpui::TestAppContext) {
446// let buffer = cx.add_model(|cx| {
447// let mut buffer =
448// Buffer::new(0, cx.model_id() as u64, "{}").with_language(Arc::new(rust_lang()), cx);
449// buffer.set_sync_parse_timeout(Duration::ZERO);
450// buffer
451// });
452
453// // Wait for the initial text to parse
454// buffer.condition(cx, |buffer, _| !buffer.is_parsing()).await;
455// assert_eq!(
456// get_tree_sexp(&buffer, cx),
457// "(source_file (expression_statement (block)))"
458// );
459
460// buffer.update(cx, |buffer, cx| {
461// buffer.set_language(Some(Arc::new(json_lang())), cx)
462// });
463// buffer.condition(cx, |buffer, _| !buffer.is_parsing()).await;
464// assert_eq!(get_tree_sexp(&buffer, cx), "(document (object))");
465// }
466
467// #[gpui::test]
468// async fn test_outline(cx: &mut gpui::TestAppContext) {
469// let text = r#"
470// struct Person {
471// name: String,
472// age: usize,
473// }
474
475// mod module {
476// enum LoginState {
477// LoggedOut,
478// LoggingOn,
479// LoggedIn {
480// person: Person,
481// time: Instant,
482// }
483// }
484// }
485
486// impl Eq for Person {}
487
488// impl Drop for Person {
489// fn drop(&mut self) {
490// println!("bye");
491// }
492// }
493// "#
494// .unindent();
495
496// let buffer = cx.add_model(|cx| {
497// Buffer::new(0, cx.model_id() as u64, text).with_language(Arc::new(rust_lang()), cx)
498// });
499// let outline = buffer
500// .read_with(cx, |buffer, _| buffer.snapshot().outline(None))
501// .unwrap();
502
503// assert_eq!(
504// outline
505// .items
506// .iter()
507// .map(|item| (item.text.as_str(), item.depth))
508// .collect::<Vec<_>>(),
509// &[
510// ("struct Person", 0),
511// ("name", 1),
512// ("age", 1),
513// ("mod module", 0),
514// ("enum LoginState", 1),
515// ("LoggedOut", 2),
516// ("LoggingOn", 2),
517// ("LoggedIn", 2),
518// ("person", 3),
519// ("time", 3),
520// ("impl Eq for Person", 0),
521// ("impl Drop for Person", 0),
522// ("fn drop", 1),
523// ]
524// );
525
526// // Without space, we only match on names
527// assert_eq!(
528// search(&outline, "oon", cx).await,
529// &[
530// ("mod module", vec![]), // included as the parent of a match
531// ("enum LoginState", vec![]), // included as the parent of a match
532// ("LoggingOn", vec![1, 7, 8]), // matches
533// ("impl Drop for Person", vec![7, 18, 19]), // matches in two disjoint names
534// ]
535// );
536
537// assert_eq!(
538// search(&outline, "dp p", cx).await,
539// &[
540// ("impl Drop for Person", vec![5, 8, 9, 14]),
541// ("fn drop", vec![]),
542// ]
543// );
544// assert_eq!(
545// search(&outline, "dpn", cx).await,
546// &[("impl Drop for Person", vec![5, 14, 19])]
547// );
548// assert_eq!(
549// search(&outline, "impl ", cx).await,
550// &[
551// ("impl Eq for Person", vec![0, 1, 2, 3, 4]),
552// ("impl Drop for Person", vec![0, 1, 2, 3, 4]),
553// ("fn drop", vec![]),
554// ]
555// );
556
557// async fn search<'a>(
558// outline: &'a Outline<Anchor>,
559// query: &'a str,
560// cx: &'a gpui::TestAppContext,
561// ) -> Vec<(&'a str, Vec<usize>)> {
562// let matches = cx
563// .read(|cx| outline.search(query, cx.background().clone()))
564// .await;
565// matches
566// .into_iter()
567// .map(|mat| (outline.items[mat.candidate_id].text.as_str(), mat.positions))
568// .collect::<Vec<_>>()
569// }
570// }
571
572// #[gpui::test]
573// async fn test_outline_nodes_with_newlines(cx: &mut gpui::TestAppContext) {
574// let text = r#"
575// impl A for B<
576// C
577// > {
578// };
579// "#
580// .unindent();
581
582// let buffer = cx.add_model(|cx| {
583// Buffer::new(0, cx.model_id() as u64, text).with_language(Arc::new(rust_lang()), cx)
584// });
585// let outline = buffer
586// .read_with(cx, |buffer, _| buffer.snapshot().outline(None))
587// .unwrap();
588
589// assert_eq!(
590// outline
591// .items
592// .iter()
593// .map(|item| (item.text.as_str(), item.depth))
594// .collect::<Vec<_>>(),
595// &[("impl A for B<", 0)]
596// );
597// }
598
599// #[gpui::test]
600// async fn test_outline_with_extra_context(cx: &mut gpui::TestAppContext) {
601// let language = javascript_lang()
602// .with_outline_query(
603// r#"
604// (function_declaration
605// "function" @context
606// name: (_) @name
607// parameters: (formal_parameters
608// "(" @context.extra
609// ")" @context.extra)) @item
610// "#,
611// )
612// .unwrap();
613
614// let text = r#"
615// function a() {}
616// function b(c) {}
617// "#
618// .unindent();
619
620// let buffer = cx.add_model(|cx| {
621// Buffer::new(0, cx.model_id() as u64, text).with_language(Arc::new(language), cx)
622// });
623// let snapshot = buffer.read_with(cx, |buffer, _| buffer.snapshot());
624
625// // extra context nodes are included in the outline.
626// let outline = snapshot.outline(None).unwrap();
627// assert_eq!(
628// outline
629// .items
630// .iter()
631// .map(|item| (item.text.as_str(), item.depth))
632// .collect::<Vec<_>>(),
633// &[("function a()", 0), ("function b( )", 0),]
634// );
635
636// // extra context nodes do not appear in breadcrumbs.
637// let symbols = snapshot.symbols_containing(3, None).unwrap();
638// assert_eq!(
639// symbols
640// .iter()
641// .map(|item| (item.text.as_str(), item.depth))
642// .collect::<Vec<_>>(),
643// &[("function a", 0)]
644// );
645// }
646
647// #[gpui::test]
648// async fn test_symbols_containing(cx: &mut gpui::TestAppContext) {
649// let text = r#"
650// impl Person {
651// fn one() {
652// 1
653// }
654
655// fn two() {
656// 2
657// }fn three() {
658// 3
659// }
660// }
661// "#
662// .unindent();
663
664// let buffer = cx.add_model(|cx| {
665// Buffer::new(0, cx.model_id() as u64, text).with_language(Arc::new(rust_lang()), cx)
666// });
667// let snapshot = buffer.read_with(cx, |buffer, _| buffer.snapshot());
668
669// // point is at the start of an item
670// assert_eq!(
671// symbols_containing(Point::new(1, 4), &snapshot),
672// vec![
673// (
674// "impl Person".to_string(),
675// Point::new(0, 0)..Point::new(10, 1)
676// ),
677// ("fn one".to_string(), Point::new(1, 4)..Point::new(3, 5))
678// ]
679// );
680
681// // point is in the middle of an item
682// assert_eq!(
683// symbols_containing(Point::new(2, 8), &snapshot),
684// vec![
685// (
686// "impl Person".to_string(),
687// Point::new(0, 0)..Point::new(10, 1)
688// ),
689// ("fn one".to_string(), Point::new(1, 4)..Point::new(3, 5))
690// ]
691// );
692
693// // point is at the end of an item
694// assert_eq!(
695// symbols_containing(Point::new(3, 5), &snapshot),
696// vec![
697// (
698// "impl Person".to_string(),
699// Point::new(0, 0)..Point::new(10, 1)
700// ),
701// ("fn one".to_string(), Point::new(1, 4)..Point::new(3, 5))
702// ]
703// );
704
705// // point is in between two adjacent items
706// assert_eq!(
707// symbols_containing(Point::new(7, 5), &snapshot),
708// vec![
709// (
710// "impl Person".to_string(),
711// Point::new(0, 0)..Point::new(10, 1)
712// ),
713// ("fn two".to_string(), Point::new(5, 4)..Point::new(7, 5))
714// ]
715// );
716
717// fn symbols_containing(
718// position: Point,
719// snapshot: &BufferSnapshot,
720// ) -> Vec<(String, Range<Point>)> {
721// snapshot
722// .symbols_containing(position, None)
723// .unwrap()
724// .into_iter()
725// .map(|item| {
726// (
727// item.text,
728// item.range.start.to_point(snapshot)..item.range.end.to_point(snapshot),
729// )
730// })
731// .collect()
732// }
733// }
734
735// #[gpui::test]
736// fn test_enclosing_bracket_ranges(cx: &mut AppContext) {
737// let mut assert = |selection_text, range_markers| {
738// assert_bracket_pairs(selection_text, range_markers, rust_lang(), cx)
739// };
740
741// assert(
742// indoc! {"
743// mod x {
744// moˇd y {
745
746// }
747// }
748// let foo = 1;"},
749// vec![indoc! {"
750// mod x «{»
751// mod y {
752
753// }
754// «}»
755// let foo = 1;"}],
756// );
757
758// assert(
759// indoc! {"
760// mod x {
761// mod y ˇ{
762
763// }
764// }
765// let foo = 1;"},
766// vec![
767// indoc! {"
768// mod x «{»
769// mod y {
770
771// }
772// «}»
773// let foo = 1;"},
774// indoc! {"
775// mod x {
776// mod y «{»
777
778// «}»
779// }
780// let foo = 1;"},
781// ],
782// );
783
784// assert(
785// indoc! {"
786// mod x {
787// mod y {
788
789// }ˇ
790// }
791// let foo = 1;"},
792// vec![
793// indoc! {"
794// mod x «{»
795// mod y {
796
797// }
798// «}»
799// let foo = 1;"},
800// indoc! {"
801// mod x {
802// mod y «{»
803
804// «}»
805// }
806// let foo = 1;"},
807// ],
808// );
809
810// assert(
811// indoc! {"
812// mod x {
813// mod y {
814
815// }
816// ˇ}
817// let foo = 1;"},
818// vec![indoc! {"
819// mod x «{»
820// mod y {
821
822// }
823// «}»
824// let foo = 1;"}],
825// );
826
827// assert(
828// indoc! {"
829// mod x {
830// mod y {
831
832// }
833// }
834// let fˇoo = 1;"},
835// vec![],
836// );
837
838// // Regression test: avoid crash when querying at the end of the buffer.
839// assert(
840// indoc! {"
841// mod x {
842// mod y {
843
844// }
845// }
846// let foo = 1;ˇ"},
847// vec![],
848// );
849// }
850
851// #[gpui::test]
852// fn test_enclosing_bracket_ranges_where_brackets_are_not_outermost_children(cx: &mut AppContext) {
853// let mut assert = |selection_text, bracket_pair_texts| {
854// assert_bracket_pairs(selection_text, bracket_pair_texts, javascript_lang(), cx)
855// };
856
857// assert(
858// indoc! {"
859// for (const a in b)ˇ {
860// // a comment that's longer than the for-loop header
861// }"},
862// vec![indoc! {"
863// for «(»const a in b«)» {
864// // a comment that's longer than the for-loop header
865// }"}],
866// );
867
868// // Regression test: even though the parent node of the parentheses (the for loop) does
869// // intersect the given range, the parentheses themselves do not contain the range, so
870// // they should not be returned. Only the curly braces contain the range.
871// assert(
872// indoc! {"
873// for (const a in b) {ˇ
874// // a comment that's longer than the for-loop header
875// }"},
876// vec![indoc! {"
877// for (const a in b) «{»
878// // a comment that's longer than the for-loop header
879// «}»"}],
880// );
881// }
882
883// #[gpui::test]
884// fn test_range_for_syntax_ancestor(cx: &mut AppContext) {
885// cx.add_model(|cx| {
886// let text = "fn a() { b(|c| {}) }";
887// let buffer =
888// Buffer::new(0, cx.model_id() as u64, text).with_language(Arc::new(rust_lang()), cx);
889// let snapshot = buffer.snapshot();
890
891// assert_eq!(
892// snapshot.range_for_syntax_ancestor(empty_range_at(text, "|")),
893// Some(range_of(text, "|"))
894// );
895// assert_eq!(
896// snapshot.range_for_syntax_ancestor(range_of(text, "|")),
897// Some(range_of(text, "|c|"))
898// );
899// assert_eq!(
900// snapshot.range_for_syntax_ancestor(range_of(text, "|c|")),
901// Some(range_of(text, "|c| {}"))
902// );
903// assert_eq!(
904// snapshot.range_for_syntax_ancestor(range_of(text, "|c| {}")),
905// Some(range_of(text, "(|c| {})"))
906// );
907
908// buffer
909// });
910
911// fn empty_range_at(text: &str, part: &str) -> Range<usize> {
912// let start = text.find(part).unwrap();
913// start..start
914// }
915
916// fn range_of(text: &str, part: &str) -> Range<usize> {
917// let start = text.find(part).unwrap();
918// start..start + part.len()
919// }
920// }
921
922// #[gpui::test]
923// fn test_autoindent_with_soft_tabs(cx: &mut AppContext) {
924// init_settings(cx, |_| {});
925
926// cx.add_model(|cx| {
927// let text = "fn a() {}";
928// let mut buffer =
929// Buffer::new(0, cx.model_id() as u64, text).with_language(Arc::new(rust_lang()), cx);
930
931// buffer.edit([(8..8, "\n\n")], Some(AutoindentMode::EachLine), cx);
932// assert_eq!(buffer.text(), "fn a() {\n \n}");
933
934// buffer.edit(
935// [(Point::new(1, 4)..Point::new(1, 4), "b()\n")],
936// Some(AutoindentMode::EachLine),
937// cx,
938// );
939// assert_eq!(buffer.text(), "fn a() {\n b()\n \n}");
940
941// // Create a field expression on a new line, causing that line
942// // to be indented.
943// buffer.edit(
944// [(Point::new(2, 4)..Point::new(2, 4), ".c")],
945// Some(AutoindentMode::EachLine),
946// cx,
947// );
948// assert_eq!(buffer.text(), "fn a() {\n b()\n .c\n}");
949
950// // Remove the dot so that the line is no longer a field expression,
951// // causing the line to be outdented.
952// buffer.edit(
953// [(Point::new(2, 8)..Point::new(2, 9), "")],
954// Some(AutoindentMode::EachLine),
955// cx,
956// );
957// assert_eq!(buffer.text(), "fn a() {\n b()\n c\n}");
958
959// buffer
960// });
961// }
962
963// #[gpui::test]
964// fn test_autoindent_with_hard_tabs(cx: &mut AppContext) {
965// init_settings(cx, |settings| {
966// settings.defaults.hard_tabs = Some(true);
967// });
968
969// cx.add_model(|cx| {
970// let text = "fn a() {}";
971// let mut buffer =
972// Buffer::new(0, cx.model_id() as u64, text).with_language(Arc::new(rust_lang()), cx);
973
974// buffer.edit([(8..8, "\n\n")], Some(AutoindentMode::EachLine), cx);
975// assert_eq!(buffer.text(), "fn a() {\n\t\n}");
976
977// buffer.edit(
978// [(Point::new(1, 1)..Point::new(1, 1), "b()\n")],
979// Some(AutoindentMode::EachLine),
980// cx,
981// );
982// assert_eq!(buffer.text(), "fn a() {\n\tb()\n\t\n}");
983
984// // Create a field expression on a new line, causing that line
985// // to be indented.
986// buffer.edit(
987// [(Point::new(2, 1)..Point::new(2, 1), ".c")],
988// Some(AutoindentMode::EachLine),
989// cx,
990// );
991// assert_eq!(buffer.text(), "fn a() {\n\tb()\n\t\t.c\n}");
992
993// // Remove the dot so that the line is no longer a field expression,
994// // causing the line to be outdented.
995// buffer.edit(
996// [(Point::new(2, 2)..Point::new(2, 3), "")],
997// Some(AutoindentMode::EachLine),
998// cx,
999// );
1000// assert_eq!(buffer.text(), "fn a() {\n\tb()\n\tc\n}");
1001
1002// buffer
1003// });
1004// }
1005
1006// #[gpui::test]
1007// fn test_autoindent_does_not_adjust_lines_with_unchanged_suggestion(cx: &mut AppContext) {
1008// init_settings(cx, |_| {});
1009
1010// cx.add_model(|cx| {
1011// let mut buffer = Buffer::new(
1012// 0,
1013// cx.model_id() as u64,
1014// "
1015// fn a() {
1016// c;
1017// d;
1018// }
1019// "
1020// .unindent(),
1021// )
1022// .with_language(Arc::new(rust_lang()), cx);
1023
1024// // Lines 2 and 3 don't match the indentation suggestion. When editing these lines,
1025// // their indentation is not adjusted.
1026// buffer.edit_via_marked_text(
1027// &"
1028// fn a() {
1029// c«()»;
1030// d«()»;
1031// }
1032// "
1033// .unindent(),
1034// Some(AutoindentMode::EachLine),
1035// cx,
1036// );
1037// assert_eq!(
1038// buffer.text(),
1039// "
1040// fn a() {
1041// c();
1042// d();
1043// }
1044// "
1045// .unindent()
1046// );
1047
1048// // When appending new content after these lines, the indentation is based on the
1049// // preceding lines' actual indentation.
1050// buffer.edit_via_marked_text(
1051// &"
1052// fn a() {
1053// c«
1054// .f
1055// .g()»;
1056// d«
1057// .f
1058// .g()»;
1059// }
1060// "
1061// .unindent(),
1062// Some(AutoindentMode::EachLine),
1063// cx,
1064// );
1065
1066// assert_eq!(
1067// buffer.text(),
1068// "
1069// fn a() {
1070// c
1071// .f
1072// .g();
1073// d
1074// .f
1075// .g();
1076// }
1077// "
1078// .unindent()
1079// );
1080// buffer
1081// });
1082
1083// cx.add_model(|cx| {
1084// let mut buffer = Buffer::new(
1085// 0,
1086// cx.model_id() as u64,
1087// "
1088// fn a() {
1089// b();
1090// |
1091// "
1092// .replace("|", "") // marker to preserve trailing whitespace
1093// .unindent(),
1094// )
1095// .with_language(Arc::new(rust_lang()), cx);
1096
1097// // Insert a closing brace. It is outdented.
1098// buffer.edit_via_marked_text(
1099// &"
1100// fn a() {
1101// b();
1102// «}»
1103// "
1104// .unindent(),
1105// Some(AutoindentMode::EachLine),
1106// cx,
1107// );
1108// assert_eq!(
1109// buffer.text(),
1110// "
1111// fn a() {
1112// b();
1113// }
1114// "
1115// .unindent()
1116// );
1117
1118// // Manually edit the leading whitespace. The edit is preserved.
1119// buffer.edit_via_marked_text(
1120// &"
1121// fn a() {
1122// b();
1123// « »}
1124// "
1125// .unindent(),
1126// Some(AutoindentMode::EachLine),
1127// cx,
1128// );
1129// assert_eq!(
1130// buffer.text(),
1131// "
1132// fn a() {
1133// b();
1134// }
1135// "
1136// .unindent()
1137// );
1138// buffer
1139// });
1140// }
1141
1142// #[gpui::test]
1143// fn test_autoindent_does_not_adjust_lines_within_newly_created_errors(cx: &mut AppContext) {
1144// init_settings(cx, |_| {});
1145
1146// cx.add_model(|cx| {
1147// let mut buffer = Buffer::new(
1148// 0,
1149// cx.model_id() as u64,
1150// "
1151// fn a() {
1152// i
1153// }
1154// "
1155// .unindent(),
1156// )
1157// .with_language(Arc::new(rust_lang()), cx);
1158
1159// // Regression test: line does not get outdented due to syntax error
1160// buffer.edit_via_marked_text(
1161// &"
1162// fn a() {
1163// i«f let Some(x) = y»
1164// }
1165// "
1166// .unindent(),
1167// Some(AutoindentMode::EachLine),
1168// cx,
1169// );
1170// assert_eq!(
1171// buffer.text(),
1172// "
1173// fn a() {
1174// if let Some(x) = y
1175// }
1176// "
1177// .unindent()
1178// );
1179
1180// buffer.edit_via_marked_text(
1181// &"
1182// fn a() {
1183// if let Some(x) = y« {»
1184// }
1185// "
1186// .unindent(),
1187// Some(AutoindentMode::EachLine),
1188// cx,
1189// );
1190// assert_eq!(
1191// buffer.text(),
1192// "
1193// fn a() {
1194// if let Some(x) = y {
1195// }
1196// "
1197// .unindent()
1198// );
1199
1200// buffer
1201// });
1202// }
1203
1204// #[gpui::test]
1205// fn test_autoindent_adjusts_lines_when_only_text_changes(cx: &mut AppContext) {
1206// init_settings(cx, |_| {});
1207
1208// cx.add_model(|cx| {
1209// let mut buffer = Buffer::new(
1210// 0,
1211// cx.model_id() as u64,
1212// "
1213// fn a() {}
1214// "
1215// .unindent(),
1216// )
1217// .with_language(Arc::new(rust_lang()), cx);
1218
1219// buffer.edit_via_marked_text(
1220// &"
1221// fn a(«
1222// b») {}
1223// "
1224// .unindent(),
1225// Some(AutoindentMode::EachLine),
1226// cx,
1227// );
1228// assert_eq!(
1229// buffer.text(),
1230// "
1231// fn a(
1232// b) {}
1233// "
1234// .unindent()
1235// );
1236
1237// // The indentation suggestion changed because `@end` node (a close paren)
1238// // is now at the beginning of the line.
1239// buffer.edit_via_marked_text(
1240// &"
1241// fn a(
1242// ˇ) {}
1243// "
1244// .unindent(),
1245// Some(AutoindentMode::EachLine),
1246// cx,
1247// );
1248// assert_eq!(
1249// buffer.text(),
1250// "
1251// fn a(
1252// ) {}
1253// "
1254// .unindent()
1255// );
1256
1257// buffer
1258// });
1259// }
1260
1261// #[gpui::test]
1262// fn test_autoindent_with_edit_at_end_of_buffer(cx: &mut AppContext) {
1263// init_settings(cx, |_| {});
1264
1265// cx.add_model(|cx| {
1266// let text = "a\nb";
1267// let mut buffer =
1268// Buffer::new(0, cx.model_id() as u64, text).with_language(Arc::new(rust_lang()), cx);
1269// buffer.edit(
1270// [(0..1, "\n"), (2..3, "\n")],
1271// Some(AutoindentMode::EachLine),
1272// cx,
1273// );
1274// assert_eq!(buffer.text(), "\n\n\n");
1275// buffer
1276// });
1277// }
1278
1279// #[gpui::test]
1280// fn test_autoindent_multi_line_insertion(cx: &mut AppContext) {
1281// init_settings(cx, |_| {});
1282
1283// cx.add_model(|cx| {
1284// let text = "
1285// const a: usize = 1;
1286// fn b() {
1287// if c {
1288// let d = 2;
1289// }
1290// }
1291// "
1292// .unindent();
1293
1294// let mut buffer =
1295// Buffer::new(0, cx.model_id() as u64, text).with_language(Arc::new(rust_lang()), cx);
1296// buffer.edit(
1297// [(Point::new(3, 0)..Point::new(3, 0), "e(\n f()\n);\n")],
1298// Some(AutoindentMode::EachLine),
1299// cx,
1300// );
1301// assert_eq!(
1302// buffer.text(),
1303// "
1304// const a: usize = 1;
1305// fn b() {
1306// if c {
1307// e(
1308// f()
1309// );
1310// let d = 2;
1311// }
1312// }
1313// "
1314// .unindent()
1315// );
1316
1317// buffer
1318// });
1319// }
1320
1321// #[gpui::test]
1322// fn test_autoindent_block_mode(cx: &mut AppContext) {
1323// init_settings(cx, |_| {});
1324
1325// cx.add_model(|cx| {
1326// let text = r#"
1327// fn a() {
1328// b();
1329// }
1330// "#
1331// .unindent();
1332// let mut buffer =
1333// Buffer::new(0, cx.model_id() as u64, text).with_language(Arc::new(rust_lang()), cx);
1334
1335// // When this text was copied, both of the quotation marks were at the same
1336// // indent level, but the indentation of the first line was not included in
1337// // the copied text. This information is retained in the
1338// // 'original_indent_columns' vector.
1339// let original_indent_columns = vec![4];
1340// let inserted_text = r#"
1341// "
1342// c
1343// d
1344// e
1345// "
1346// "#
1347// .unindent();
1348
1349// // Insert the block at column zero. The entire block is indented
1350// // so that the first line matches the previous line's indentation.
1351// buffer.edit(
1352// [(Point::new(2, 0)..Point::new(2, 0), inserted_text.clone())],
1353// Some(AutoindentMode::Block {
1354// original_indent_columns: original_indent_columns.clone(),
1355// }),
1356// cx,
1357// );
1358// assert_eq!(
1359// buffer.text(),
1360// r#"
1361// fn a() {
1362// b();
1363// "
1364// c
1365// d
1366// e
1367// "
1368// }
1369// "#
1370// .unindent()
1371// );
1372
1373// // Grouping is disabled in tests, so we need 2 undos
1374// buffer.undo(cx); // Undo the auto-indent
1375// buffer.undo(cx); // Undo the original edit
1376
1377// // Insert the block at a deeper indent level. The entire block is outdented.
1378// buffer.edit([(Point::new(2, 0)..Point::new(2, 0), " ")], None, cx);
1379// buffer.edit(
1380// [(Point::new(2, 8)..Point::new(2, 8), inserted_text)],
1381// Some(AutoindentMode::Block {
1382// original_indent_columns: original_indent_columns.clone(),
1383// }),
1384// cx,
1385// );
1386// assert_eq!(
1387// buffer.text(),
1388// r#"
1389// fn a() {
1390// b();
1391// "
1392// c
1393// d
1394// e
1395// "
1396// }
1397// "#
1398// .unindent()
1399// );
1400
1401// buffer
1402// });
1403// }
1404
1405// #[gpui::test]
1406// fn test_autoindent_block_mode_without_original_indent_columns(cx: &mut AppContext) {
1407// init_settings(cx, |_| {});
1408
1409// cx.add_model(|cx| {
1410// let text = r#"
1411// fn a() {
1412// if b() {
1413
1414// }
1415// }
1416// "#
1417// .unindent();
1418// let mut buffer =
1419// Buffer::new(0, cx.model_id() as u64, text).with_language(Arc::new(rust_lang()), cx);
1420
1421// // The original indent columns are not known, so this text is
1422// // auto-indented in a block as if the first line was copied in
1423// // its entirety.
1424// let original_indent_columns = Vec::new();
1425// let inserted_text = " c\n .d()\n .e();";
1426
1427// // Insert the block at column zero. The entire block is indented
1428// // so that the first line matches the previous line's indentation.
1429// buffer.edit(
1430// [(Point::new(2, 0)..Point::new(2, 0), inserted_text)],
1431// Some(AutoindentMode::Block {
1432// original_indent_columns: original_indent_columns.clone(),
1433// }),
1434// cx,
1435// );
1436// assert_eq!(
1437// buffer.text(),
1438// r#"
1439// fn a() {
1440// if b() {
1441// c
1442// .d()
1443// .e();
1444// }
1445// }
1446// "#
1447// .unindent()
1448// );
1449
1450// // Grouping is disabled in tests, so we need 2 undos
1451// buffer.undo(cx); // Undo the auto-indent
1452// buffer.undo(cx); // Undo the original edit
1453
1454// // Insert the block at a deeper indent level. The entire block is outdented.
1455// buffer.edit(
1456// [(Point::new(2, 0)..Point::new(2, 0), " ".repeat(12))],
1457// None,
1458// cx,
1459// );
1460// buffer.edit(
1461// [(Point::new(2, 12)..Point::new(2, 12), inserted_text)],
1462// Some(AutoindentMode::Block {
1463// original_indent_columns: Vec::new(),
1464// }),
1465// cx,
1466// );
1467// assert_eq!(
1468// buffer.text(),
1469// r#"
1470// fn a() {
1471// if b() {
1472// c
1473// .d()
1474// .e();
1475// }
1476// }
1477// "#
1478// .unindent()
1479// );
1480
1481// buffer
1482// });
1483// }
1484
1485// #[gpui::test]
1486// fn test_autoindent_language_without_indents_query(cx: &mut AppContext) {
1487// init_settings(cx, |_| {});
1488
1489// cx.add_model(|cx| {
1490// let text = "
1491// * one
1492// - a
1493// - b
1494// * two
1495// "
1496// .unindent();
1497
1498// let mut buffer = Buffer::new(0, cx.model_id() as u64, text).with_language(
1499// Arc::new(Language::new(
1500// LanguageConfig {
1501// name: "Markdown".into(),
1502// auto_indent_using_last_non_empty_line: false,
1503// ..Default::default()
1504// },
1505// Some(tree_sitter_json::language()),
1506// )),
1507// cx,
1508// );
1509// buffer.edit(
1510// [(Point::new(3, 0)..Point::new(3, 0), "\n")],
1511// Some(AutoindentMode::EachLine),
1512// cx,
1513// );
1514// assert_eq!(
1515// buffer.text(),
1516// "
1517// * one
1518// - a
1519// - b
1520
1521// * two
1522// "
1523// .unindent()
1524// );
1525// buffer
1526// });
1527// }
1528
1529// #[gpui::test]
1530// fn test_autoindent_with_injected_languages(cx: &mut AppContext) {
1531// init_settings(cx, |settings| {
1532// settings.languages.extend([
1533// (
1534// "HTML".into(),
1535// LanguageSettingsContent {
1536// tab_size: Some(2.try_into().unwrap()),
1537// ..Default::default()
1538// },
1539// ),
1540// (
1541// "JavaScript".into(),
1542// LanguageSettingsContent {
1543// tab_size: Some(8.try_into().unwrap()),
1544// ..Default::default()
1545// },
1546// ),
1547// ])
1548// });
1549
1550// let html_language = Arc::new(html_lang());
1551
1552// let javascript_language = Arc::new(javascript_lang());
1553
1554// let language_registry = Arc::new(LanguageRegistry::test());
1555// language_registry.add(html_language.clone());
1556// language_registry.add(javascript_language.clone());
1557
1558// cx.add_model(|cx| {
1559// let (text, ranges) = marked_text_ranges(
1560// &"
1561// <div>ˇ
1562// </div>
1563// <script>
1564// init({ˇ
1565// })
1566// </script>
1567// <span>ˇ
1568// </span>
1569// "
1570// .unindent(),
1571// false,
1572// );
1573
1574// let mut buffer = Buffer::new(0, cx.model_id() as u64, text);
1575// buffer.set_language_registry(language_registry);
1576// buffer.set_language(Some(html_language), cx);
1577// buffer.edit(
1578// ranges.into_iter().map(|range| (range, "\na")),
1579// Some(AutoindentMode::EachLine),
1580// cx,
1581// );
1582// assert_eq!(
1583// buffer.text(),
1584// "
1585// <div>
1586// a
1587// </div>
1588// <script>
1589// init({
1590// a
1591// })
1592// </script>
1593// <span>
1594// a
1595// </span>
1596// "
1597// .unindent()
1598// );
1599// buffer
1600// });
1601// }
1602
1603// #[gpui::test]
1604// fn test_autoindent_query_with_outdent_captures(cx: &mut AppContext) {
1605// init_settings(cx, |settings| {
1606// settings.defaults.tab_size = Some(2.try_into().unwrap());
1607// });
1608
1609// cx.add_model(|cx| {
1610// let mut buffer =
1611// Buffer::new(0, cx.model_id() as u64, "").with_language(Arc::new(ruby_lang()), cx);
1612
1613// let text = r#"
1614// class C
1615// def a(b, c)
1616// puts b
1617// puts c
1618// rescue
1619// puts "errored"
1620// exit 1
1621// end
1622// end
1623// "#
1624// .unindent();
1625
1626// buffer.edit([(0..0, text)], Some(AutoindentMode::EachLine), cx);
1627
1628// assert_eq!(
1629// buffer.text(),
1630// r#"
1631// class C
1632// def a(b, c)
1633// puts b
1634// puts c
1635// rescue
1636// puts "errored"
1637// exit 1
1638// end
1639// end
1640// "#
1641// .unindent()
1642// );
1643
1644// buffer
1645// });
1646// }
1647
1648// #[gpui::test]
1649// fn test_language_scope_at_with_javascript(cx: &mut AppContext) {
1650// init_settings(cx, |_| {});
1651
1652// cx.add_model(|cx| {
1653// let language = Language::new(
1654// LanguageConfig {
1655// name: "JavaScript".into(),
1656// line_comment: Some("// ".into()),
1657// brackets: BracketPairConfig {
1658// pairs: vec![
1659// BracketPair {
1660// start: "{".into(),
1661// end: "}".into(),
1662// close: true,
1663// newline: false,
1664// },
1665// BracketPair {
1666// start: "'".into(),
1667// end: "'".into(),
1668// close: true,
1669// newline: false,
1670// },
1671// ],
1672// disabled_scopes_by_bracket_ix: vec![
1673// Vec::new(), //
1674// vec!["string".into()],
1675// ],
1676// },
1677// overrides: [(
1678// "element".into(),
1679// LanguageConfigOverride {
1680// line_comment: Override::Remove { remove: true },
1681// block_comment: Override::Set(("{/*".into(), "*/}".into())),
1682// ..Default::default()
1683// },
1684// )]
1685// .into_iter()
1686// .collect(),
1687// ..Default::default()
1688// },
1689// Some(tree_sitter_typescript::language_tsx()),
1690// )
1691// .with_override_query(
1692// r#"
1693// (jsx_element) @element
1694// (string) @string
1695// "#,
1696// )
1697// .unwrap();
1698
1699// let text = r#"a["b"] = <C d="e"></C>;"#;
1700
1701// let buffer =
1702// Buffer::new(0, cx.model_id() as u64, text).with_language(Arc::new(language), cx);
1703// let snapshot = buffer.snapshot();
1704
1705// let config = snapshot.language_scope_at(0).unwrap();
1706// assert_eq!(config.line_comment_prefix().unwrap().as_ref(), "// ");
1707// // Both bracket pairs are enabled
1708// assert_eq!(
1709// config.brackets().map(|e| e.1).collect::<Vec<_>>(),
1710// &[true, true]
1711// );
1712
1713// let string_config = snapshot.language_scope_at(3).unwrap();
1714// assert_eq!(string_config.line_comment_prefix().unwrap().as_ref(), "// ");
1715// // Second bracket pair is disabled
1716// assert_eq!(
1717// string_config.brackets().map(|e| e.1).collect::<Vec<_>>(),
1718// &[true, false]
1719// );
1720
1721// let element_config = snapshot.language_scope_at(10).unwrap();
1722// assert_eq!(element_config.line_comment_prefix(), None);
1723// assert_eq!(
1724// element_config.block_comment_delimiters(),
1725// Some((&"{/*".into(), &"*/}".into()))
1726// );
1727// // Both bracket pairs are enabled
1728// assert_eq!(
1729// element_config.brackets().map(|e| e.1).collect::<Vec<_>>(),
1730// &[true, true]
1731// );
1732
1733// buffer
1734// });
1735// }
1736
1737// #[gpui::test]
1738// fn test_language_scope_at_with_rust(cx: &mut AppContext) {
1739// init_settings(cx, |_| {});
1740
1741// cx.add_model(|cx| {
1742// let language = Language::new(
1743// LanguageConfig {
1744// name: "Rust".into(),
1745// brackets: BracketPairConfig {
1746// pairs: vec![
1747// BracketPair {
1748// start: "{".into(),
1749// end: "}".into(),
1750// close: true,
1751// newline: false,
1752// },
1753// BracketPair {
1754// start: "'".into(),
1755// end: "'".into(),
1756// close: true,
1757// newline: false,
1758// },
1759// ],
1760// disabled_scopes_by_bracket_ix: vec![
1761// Vec::new(), //
1762// vec!["string".into()],
1763// ],
1764// },
1765// ..Default::default()
1766// },
1767// Some(tree_sitter_rust::language()),
1768// )
1769// .with_override_query(
1770// r#"
1771// (string_literal) @string
1772// "#,
1773// )
1774// .unwrap();
1775
1776// let text = r#"
1777// const S: &'static str = "hello";
1778// "#
1779// .unindent();
1780
1781// let buffer = Buffer::new(0, cx.model_id() as u64, text.clone())
1782// .with_language(Arc::new(language), cx);
1783// let snapshot = buffer.snapshot();
1784
1785// // By default, all brackets are enabled
1786// let config = snapshot.language_scope_at(0).unwrap();
1787// assert_eq!(
1788// config.brackets().map(|e| e.1).collect::<Vec<_>>(),
1789// &[true, true]
1790// );
1791
1792// // Within a string, the quotation brackets are disabled.
1793// let string_config = snapshot
1794// .language_scope_at(text.find("ello").unwrap())
1795// .unwrap();
1796// assert_eq!(
1797// string_config.brackets().map(|e| e.1).collect::<Vec<_>>(),
1798// &[true, false]
1799// );
1800
1801// buffer
1802// });
1803// }
1804
1805// #[gpui::test]
1806// fn test_language_scope_at_with_combined_injections(cx: &mut AppContext) {
1807// init_settings(cx, |_| {});
1808
1809// cx.add_model(|cx| {
1810// let text = r#"
1811// <ol>
1812// <% people.each do |person| %>
1813// <li>
1814// <%= person.name %>
1815// </li>
1816// <% end %>
1817// </ol>
1818// "#
1819// .unindent();
1820
1821// let language_registry = Arc::new(LanguageRegistry::test());
1822// language_registry.add(Arc::new(ruby_lang()));
1823// language_registry.add(Arc::new(html_lang()));
1824// language_registry.add(Arc::new(erb_lang()));
1825
1826// let mut buffer = Buffer::new(0, cx.model_id() as u64, text);
1827// buffer.set_language_registry(language_registry.clone());
1828// buffer.set_language(
1829// language_registry
1830// .language_for_name("ERB")
1831// .now_or_never()
1832// .unwrap()
1833// .ok(),
1834// cx,
1835// );
1836
1837// let snapshot = buffer.snapshot();
1838// let html_config = snapshot.language_scope_at(Point::new(2, 4)).unwrap();
1839// assert_eq!(html_config.line_comment_prefix(), None);
1840// assert_eq!(
1841// html_config.block_comment_delimiters(),
1842// Some((&"<!--".into(), &"-->".into()))
1843// );
1844
1845// let ruby_config = snapshot.language_scope_at(Point::new(3, 12)).unwrap();
1846// assert_eq!(ruby_config.line_comment_prefix().unwrap().as_ref(), "# ");
1847// assert_eq!(ruby_config.block_comment_delimiters(), None);
1848
1849// buffer
1850// });
1851// }
1852
1853// #[gpui::test]
1854// fn test_serialization(cx: &mut gpui::AppContext) {
1855// let mut now = Instant::now();
1856
1857// let buffer1 = cx.add_model(|cx| {
1858// let mut buffer = Buffer::new(0, cx.model_id() as u64, "abc");
1859// buffer.edit([(3..3, "D")], None, cx);
1860
1861// now += Duration::from_secs(1);
1862// buffer.start_transaction_at(now);
1863// buffer.edit([(4..4, "E")], None, cx);
1864// buffer.end_transaction_at(now, cx);
1865// assert_eq!(buffer.text(), "abcDE");
1866
1867// buffer.undo(cx);
1868// assert_eq!(buffer.text(), "abcD");
1869
1870// buffer.edit([(4..4, "F")], None, cx);
1871// assert_eq!(buffer.text(), "abcDF");
1872// buffer
1873// });
1874// assert_eq!(buffer1.read(cx).text(), "abcDF");
1875
1876// let state = buffer1.read(cx).to_proto();
1877// let ops = cx
1878// .background()
1879// .block(buffer1.read(cx).serialize_ops(None, cx));
1880// let buffer2 = cx.add_model(|cx| {
1881// let mut buffer = Buffer::from_proto(1, state, None).unwrap();
1882// buffer
1883// .apply_ops(
1884// ops.into_iter()
1885// .map(|op| proto::deserialize_operation(op).unwrap()),
1886// cx,
1887// )
1888// .unwrap();
1889// buffer
1890// });
1891// assert_eq!(buffer2.read(cx).text(), "abcDF");
1892// }
1893
1894// #[gpui::test(iterations = 100)]
1895// fn test_random_collaboration(cx: &mut AppContext, mut rng: StdRng) {
1896// let min_peers = env::var("MIN_PEERS")
1897// .map(|i| i.parse().expect("invalid `MIN_PEERS` variable"))
1898// .unwrap_or(1);
1899// let max_peers = env::var("MAX_PEERS")
1900// .map(|i| i.parse().expect("invalid `MAX_PEERS` variable"))
1901// .unwrap_or(5);
1902// let operations = env::var("OPERATIONS")
1903// .map(|i| i.parse().expect("invalid `OPERATIONS` variable"))
1904// .unwrap_or(10);
1905
1906// let base_text_len = rng.gen_range(0..10);
1907// let base_text = RandomCharIter::new(&mut rng)
1908// .take(base_text_len)
1909// .collect::<String>();
1910// let mut replica_ids = Vec::new();
1911// let mut buffers = Vec::new();
1912// let network = Rc::new(RefCell::new(Network::new(rng.clone())));
1913// let base_buffer = cx.add_model(|cx| Buffer::new(0, cx.model_id() as u64, base_text.as_str()));
1914
1915// for i in 0..rng.gen_range(min_peers..=max_peers) {
1916// let buffer = cx.add_model(|cx| {
1917// let state = base_buffer.read(cx).to_proto();
1918// let ops = cx
1919// .background()
1920// .block(base_buffer.read(cx).serialize_ops(None, cx));
1921// let mut buffer = Buffer::from_proto(i as ReplicaId, state, None).unwrap();
1922// buffer
1923// .apply_ops(
1924// ops.into_iter()
1925// .map(|op| proto::deserialize_operation(op).unwrap()),
1926// cx,
1927// )
1928// .unwrap();
1929// buffer.set_group_interval(Duration::from_millis(rng.gen_range(0..=200)));
1930// let network = network.clone();
1931// cx.subscribe(&cx.handle(), move |buffer, _, event, _| {
1932// if let Event::Operation(op) = event {
1933// network
1934// .borrow_mut()
1935// .broadcast(buffer.replica_id(), vec![proto::serialize_operation(op)]);
1936// }
1937// })
1938// .detach();
1939// buffer
1940// });
1941// buffers.push(buffer);
1942// replica_ids.push(i as ReplicaId);
1943// network.borrow_mut().add_peer(i as ReplicaId);
1944// log::info!("Adding initial peer with replica id {}", i);
1945// }
1946
1947// log::info!("initial text: {:?}", base_text);
1948
1949// let mut now = Instant::now();
1950// let mut mutation_count = operations;
1951// let mut next_diagnostic_id = 0;
1952// let mut active_selections = BTreeMap::default();
1953// loop {
1954// let replica_index = rng.gen_range(0..replica_ids.len());
1955// let replica_id = replica_ids[replica_index];
1956// let buffer = &mut buffers[replica_index];
1957// let mut new_buffer = None;
1958// match rng.gen_range(0..100) {
1959// 0..=29 if mutation_count != 0 => {
1960// buffer.update(cx, |buffer, cx| {
1961// buffer.start_transaction_at(now);
1962// buffer.randomly_edit(&mut rng, 5, cx);
1963// buffer.end_transaction_at(now, cx);
1964// log::info!("buffer {} text: {:?}", buffer.replica_id(), buffer.text());
1965// });
1966// mutation_count -= 1;
1967// }
1968// 30..=39 if mutation_count != 0 => {
1969// buffer.update(cx, |buffer, cx| {
1970// if rng.gen_bool(0.2) {
1971// log::info!("peer {} clearing active selections", replica_id);
1972// active_selections.remove(&replica_id);
1973// buffer.remove_active_selections(cx);
1974// } else {
1975// let mut selections = Vec::new();
1976// for id in 0..rng.gen_range(1..=5) {
1977// let range = buffer.random_byte_range(0, &mut rng);
1978// selections.push(Selection {
1979// id,
1980// start: buffer.anchor_before(range.start),
1981// end: buffer.anchor_before(range.end),
1982// reversed: false,
1983// goal: SelectionGoal::None,
1984// });
1985// }
1986// let selections: Arc<[Selection<Anchor>]> = selections.into();
1987// log::info!(
1988// "peer {} setting active selections: {:?}",
1989// replica_id,
1990// selections
1991// );
1992// active_selections.insert(replica_id, selections.clone());
1993// buffer.set_active_selections(selections, false, Default::default(), cx);
1994// }
1995// });
1996// mutation_count -= 1;
1997// }
1998// 40..=49 if mutation_count != 0 && replica_id == 0 => {
1999// let entry_count = rng.gen_range(1..=5);
2000// buffer.update(cx, |buffer, cx| {
2001// let diagnostics = DiagnosticSet::new(
2002// (0..entry_count).map(|_| {
2003// let range = buffer.random_byte_range(0, &mut rng);
2004// let range = range.to_point_utf16(buffer);
2005// let range = range.start..range.end;
2006// DiagnosticEntry {
2007// range,
2008// diagnostic: Diagnostic {
2009// message: post_inc(&mut next_diagnostic_id).to_string(),
2010// ..Default::default()
2011// },
2012// }
2013// }),
2014// buffer,
2015// );
2016// log::info!("peer {} setting diagnostics: {:?}", replica_id, diagnostics);
2017// buffer.update_diagnostics(LanguageServerId(0), diagnostics, cx);
2018// });
2019// mutation_count -= 1;
2020// }
2021// 50..=59 if replica_ids.len() < max_peers => {
2022// let old_buffer_state = buffer.read(cx).to_proto();
2023// let old_buffer_ops = cx
2024// .background()
2025// .block(buffer.read(cx).serialize_ops(None, cx));
2026// let new_replica_id = (0..=replica_ids.len() as ReplicaId)
2027// .filter(|replica_id| *replica_id != buffer.read(cx).replica_id())
2028// .choose(&mut rng)
2029// .unwrap();
2030// log::info!(
2031// "Adding new replica {} (replicating from {})",
2032// new_replica_id,
2033// replica_id
2034// );
2035// new_buffer = Some(cx.add_model(|cx| {
2036// let mut new_buffer =
2037// Buffer::from_proto(new_replica_id, old_buffer_state, None).unwrap();
2038// new_buffer
2039// .apply_ops(
2040// old_buffer_ops
2041// .into_iter()
2042// .map(|op| deserialize_operation(op).unwrap()),
2043// cx,
2044// )
2045// .unwrap();
2046// log::info!(
2047// "New replica {} text: {:?}",
2048// new_buffer.replica_id(),
2049// new_buffer.text()
2050// );
2051// new_buffer.set_group_interval(Duration::from_millis(rng.gen_range(0..=200)));
2052// let network = network.clone();
2053// cx.subscribe(&cx.handle(), move |buffer, _, event, _| {
2054// if let Event::Operation(op) = event {
2055// network.borrow_mut().broadcast(
2056// buffer.replica_id(),
2057// vec![proto::serialize_operation(op)],
2058// );
2059// }
2060// })
2061// .detach();
2062// new_buffer
2063// }));
2064// network.borrow_mut().replicate(replica_id, new_replica_id);
2065
2066// if new_replica_id as usize == replica_ids.len() {
2067// replica_ids.push(new_replica_id);
2068// } else {
2069// let new_buffer = new_buffer.take().unwrap();
2070// while network.borrow().has_unreceived(new_replica_id) {
2071// let ops = network
2072// .borrow_mut()
2073// .receive(new_replica_id)
2074// .into_iter()
2075// .map(|op| proto::deserialize_operation(op).unwrap());
2076// if ops.len() > 0 {
2077// log::info!(
2078// "peer {} (version: {:?}) applying {} ops from the network. {:?}",
2079// new_replica_id,
2080// buffer.read(cx).version(),
2081// ops.len(),
2082// ops
2083// );
2084// new_buffer.update(cx, |new_buffer, cx| {
2085// new_buffer.apply_ops(ops, cx).unwrap();
2086// });
2087// }
2088// }
2089// buffers[new_replica_id as usize] = new_buffer;
2090// }
2091// }
2092// 60..=69 if mutation_count != 0 => {
2093// buffer.update(cx, |buffer, cx| {
2094// buffer.randomly_undo_redo(&mut rng, cx);
2095// log::info!("buffer {} text: {:?}", buffer.replica_id(), buffer.text());
2096// });
2097// mutation_count -= 1;
2098// }
2099// _ if network.borrow().has_unreceived(replica_id) => {
2100// let ops = network
2101// .borrow_mut()
2102// .receive(replica_id)
2103// .into_iter()
2104// .map(|op| proto::deserialize_operation(op).unwrap());
2105// if ops.len() > 0 {
2106// log::info!(
2107// "peer {} (version: {:?}) applying {} ops from the network. {:?}",
2108// replica_id,
2109// buffer.read(cx).version(),
2110// ops.len(),
2111// ops
2112// );
2113// buffer.update(cx, |buffer, cx| buffer.apply_ops(ops, cx).unwrap());
2114// }
2115// }
2116// _ => {}
2117// }
2118
2119// now += Duration::from_millis(rng.gen_range(0..=200));
2120// buffers.extend(new_buffer);
2121
2122// for buffer in &buffers {
2123// buffer.read(cx).check_invariants();
2124// }
2125
2126// if mutation_count == 0 && network.borrow().is_idle() {
2127// break;
2128// }
2129// }
2130
2131// let first_buffer = buffers[0].read(cx).snapshot();
2132// for buffer in &buffers[1..] {
2133// let buffer = buffer.read(cx).snapshot();
2134// assert_eq!(
2135// buffer.version(),
2136// first_buffer.version(),
2137// "Replica {} version != Replica 0 version",
2138// buffer.replica_id()
2139// );
2140// assert_eq!(
2141// buffer.text(),
2142// first_buffer.text(),
2143// "Replica {} text != Replica 0 text",
2144// buffer.replica_id()
2145// );
2146// assert_eq!(
2147// buffer
2148// .diagnostics_in_range::<_, usize>(0..buffer.len(), false)
2149// .collect::<Vec<_>>(),
2150// first_buffer
2151// .diagnostics_in_range::<_, usize>(0..first_buffer.len(), false)
2152// .collect::<Vec<_>>(),
2153// "Replica {} diagnostics != Replica 0 diagnostics",
2154// buffer.replica_id()
2155// );
2156// }
2157
2158// for buffer in &buffers {
2159// let buffer = buffer.read(cx).snapshot();
2160// let actual_remote_selections = buffer
2161// .remote_selections_in_range(Anchor::MIN..Anchor::MAX)
2162// .map(|(replica_id, _, _, selections)| (replica_id, selections.collect::<Vec<_>>()))
2163// .collect::<Vec<_>>();
2164// let expected_remote_selections = active_selections
2165// .iter()
2166// .filter(|(replica_id, _)| **replica_id != buffer.replica_id())
2167// .map(|(replica_id, selections)| (*replica_id, selections.iter().collect::<Vec<_>>()))
2168// .collect::<Vec<_>>();
2169// assert_eq!(
2170// actual_remote_selections,
2171// expected_remote_selections,
2172// "Replica {} remote selections != expected selections",
2173// buffer.replica_id()
2174// );
2175// }
2176// }
2177
2178// #[test]
2179// fn test_contiguous_ranges() {
2180// assert_eq!(
2181// contiguous_ranges([1, 2, 3, 5, 6, 9, 10, 11, 12].into_iter(), 100).collect::<Vec<_>>(),
2182// &[1..4, 5..7, 9..13]
2183// );
2184
2185// // Respects the `max_len` parameter
2186// assert_eq!(
2187// contiguous_ranges(
2188// [2, 3, 4, 5, 6, 7, 8, 9, 23, 24, 25, 26, 30, 31].into_iter(),
2189// 3
2190// )
2191// .collect::<Vec<_>>(),
2192// &[2..5, 5..8, 8..10, 23..26, 26..27, 30..32],
2193// );
2194// }
2195
2196// #[gpui::test(iterations = 500)]
2197// fn test_trailing_whitespace_ranges(mut rng: StdRng) {
2198// // Generate a random multi-line string containing
2199// // some lines with trailing whitespace.
2200// let mut text = String::new();
2201// for _ in 0..rng.gen_range(0..16) {
2202// for _ in 0..rng.gen_range(0..36) {
2203// text.push(match rng.gen_range(0..10) {
2204// 0..=1 => ' ',
2205// 3 => '\t',
2206// _ => rng.gen_range('a'..'z'),
2207// });
2208// }
2209// text.push('\n');
2210// }
2211
2212// match rng.gen_range(0..10) {
2213// // sometimes remove the last newline
2214// 0..=1 => drop(text.pop()), //
2215
2216// // sometimes add extra newlines
2217// 2..=3 => text.push_str(&"\n".repeat(rng.gen_range(1..5))),
2218// _ => {}
2219// }
2220
2221// let rope = Rope::from(text.as_str());
2222// let actual_ranges = trailing_whitespace_ranges(&rope);
2223// let expected_ranges = TRAILING_WHITESPACE_REGEX
2224// .find_iter(&text)
2225// .map(|m| m.range())
2226// .collect::<Vec<_>>();
2227// assert_eq!(
2228// actual_ranges,
2229// expected_ranges,
2230// "wrong ranges for text lines:\n{:?}",
2231// text.split("\n").collect::<Vec<_>>()
2232// );
2233// }
2234
2235// fn ruby_lang() -> Language {
2236// Language::new(
2237// LanguageConfig {
2238// name: "Ruby".into(),
2239// path_suffixes: vec!["rb".to_string()],
2240// line_comment: Some("# ".into()),
2241// ..Default::default()
2242// },
2243// Some(tree_sitter_ruby::language()),
2244// )
2245// .with_indents_query(
2246// r#"
2247// (class "end" @end) @indent
2248// (method "end" @end) @indent
2249// (rescue) @outdent
2250// (then) @indent
2251// "#,
2252// )
2253// .unwrap()
2254// }
2255
2256// fn html_lang() -> Language {
2257// Language::new(
2258// LanguageConfig {
2259// name: "HTML".into(),
2260// block_comment: Some(("<!--".into(), "-->".into())),
2261// ..Default::default()
2262// },
2263// Some(tree_sitter_html::language()),
2264// )
2265// .with_indents_query(
2266// "
2267// (element
2268// (start_tag) @start
2269// (end_tag)? @end) @indent
2270// ",
2271// )
2272// .unwrap()
2273// .with_injection_query(
2274// r#"
2275// (script_element
2276// (raw_text) @content
2277// (#set! "language" "javascript"))
2278// "#,
2279// )
2280// .unwrap()
2281// }
2282
2283// fn erb_lang() -> Language {
2284// Language::new(
2285// LanguageConfig {
2286// name: "ERB".into(),
2287// path_suffixes: vec!["erb".to_string()],
2288// block_comment: Some(("<%#".into(), "%>".into())),
2289// ..Default::default()
2290// },
2291// Some(tree_sitter_embedded_template::language()),
2292// )
2293// .with_injection_query(
2294// r#"
2295// (
2296// (code) @content
2297// (#set! "language" "ruby")
2298// (#set! "combined")
2299// )
2300
2301// (
2302// (content) @content
2303// (#set! "language" "html")
2304// (#set! "combined")
2305// )
2306// "#,
2307// )
2308// .unwrap()
2309// }
2310
2311// fn rust_lang() -> Language {
2312// Language::new(
2313// LanguageConfig {
2314// name: "Rust".into(),
2315// path_suffixes: vec!["rs".to_string()],
2316// ..Default::default()
2317// },
2318// Some(tree_sitter_rust::language()),
2319// )
2320// .with_indents_query(
2321// r#"
2322// (call_expression) @indent
2323// (field_expression) @indent
2324// (_ "(" ")" @end) @indent
2325// (_ "{" "}" @end) @indent
2326// "#,
2327// )
2328// .unwrap()
2329// .with_brackets_query(
2330// r#"
2331// ("{" @open "}" @close)
2332// "#,
2333// )
2334// .unwrap()
2335// .with_outline_query(
2336// r#"
2337// (struct_item
2338// "struct" @context
2339// name: (_) @name) @item
2340// (enum_item
2341// "enum" @context
2342// name: (_) @name) @item
2343// (enum_variant
2344// name: (_) @name) @item
2345// (field_declaration
2346// name: (_) @name) @item
2347// (impl_item
2348// "impl" @context
2349// trait: (_)? @name
2350// "for"? @context
2351// type: (_) @name) @item
2352// (function_item
2353// "fn" @context
2354// name: (_) @name) @item
2355// (mod_item
2356// "mod" @context
2357// name: (_) @name) @item
2358// "#,
2359// )
2360// .unwrap()
2361// }
2362
2363// fn json_lang() -> Language {
2364// Language::new(
2365// LanguageConfig {
2366// name: "Json".into(),
2367// path_suffixes: vec!["js".to_string()],
2368// ..Default::default()
2369// },
2370// Some(tree_sitter_json::language()),
2371// )
2372// }
2373
2374// fn javascript_lang() -> Language {
2375// Language::new(
2376// LanguageConfig {
2377// name: "JavaScript".into(),
2378// ..Default::default()
2379// },
2380// Some(tree_sitter_typescript::language_tsx()),
2381// )
2382// .with_brackets_query(
2383// r#"
2384// ("{" @open "}" @close)
2385// ("(" @open ")" @close)
2386// "#,
2387// )
2388// .unwrap()
2389// .with_indents_query(
2390// r#"
2391// (object "}" @end) @indent
2392// "#,
2393// )
2394// .unwrap()
2395// }
2396
2397// fn get_tree_sexp(buffer: &ModelHandle<Buffer>, cx: &gpui::TestAppContext) -> String {
2398// buffer.read_with(cx, |buffer, _| {
2399// let snapshot = buffer.snapshot();
2400// let layers = snapshot.syntax.layers(buffer.as_text_snapshot());
2401// layers[0].node().to_sexp()
2402// })
2403// }
2404
2405// // Assert that the enclosing bracket ranges around the selection match the pairs indicated by the marked text in `range_markers`
2406// fn assert_bracket_pairs(
2407// selection_text: &'static str,
2408// bracket_pair_texts: Vec<&'static str>,
2409// language: Language,
2410// cx: &mut AppContext,
2411// ) {
2412// let (expected_text, selection_ranges) = marked_text_ranges(selection_text, false);
2413// let buffer = cx.add_model(|cx| {
2414// Buffer::new(0, cx.model_id() as u64, expected_text.clone())
2415// .with_language(Arc::new(language), cx)
2416// });
2417// let buffer = buffer.update(cx, |buffer, _cx| buffer.snapshot());
2418
2419// let selection_range = selection_ranges[0].clone();
2420
2421// let bracket_pairs = bracket_pair_texts
2422// .into_iter()
2423// .map(|pair_text| {
2424// let (bracket_text, ranges) = marked_text_ranges(pair_text, false);
2425// assert_eq!(bracket_text, expected_text);
2426// (ranges[0].clone(), ranges[1].clone())
2427// })
2428// .collect::<Vec<_>>();
2429
2430// assert_set_eq!(
2431// buffer.bracket_ranges(selection_range).collect::<Vec<_>>(),
2432// bracket_pairs
2433// );
2434// }
2435
2436// fn init_settings(cx: &mut AppContext, f: fn(&mut AllLanguageSettingsContent)) {
2437// cx.set_global(SettingsStore::test(cx));
2438// crate::init(cx);
2439// cx.update_global::<SettingsStore, _, _>(|settings, cx| {
2440// settings.update_user_settings::<AllLanguageSettings>(cx, f);
2441// });
2442// }