1use std::ops::Range;
2
3use tree_sitter::{Query, QueryMatch};
4
5use crate::MigrationPatterns;
6
7pub const SETTINGS_PATTERNS: MigrationPatterns = &[(
8 SETTINGS_CONTEXT_SERVER_PATTERN,
9 migrate_context_server_settings,
10)];
11
12const SETTINGS_CONTEXT_SERVER_PATTERN: &str = r#"(document
13 (object
14 (pair
15 key: (string (string_content) @context-servers)
16 value: (object
17 (pair
18 key: (string (string_content) @server-name)
19 value: (object) @server-settings
20 )
21 )
22 )
23 )
24 (#eq? @context-servers "context_servers")
25)"#;
26
27fn migrate_context_server_settings(
28 contents: &str,
29 mat: &QueryMatch,
30 query: &Query,
31) -> Option<(Range<usize>, String)> {
32 let server_settings_index = query.capture_index_for_name("server-settings")?;
33 let server_settings = mat.nodes_for_capture_index(server_settings_index).next()?;
34
35 let mut has_command = false;
36 let mut has_settings = false;
37 let mut other_keys = 0;
38 let mut column = None;
39
40 // Parse the server settings to check what keys it contains
41 let mut cursor = server_settings.walk();
42 for child in server_settings.children(&mut cursor) {
43 if child.kind() == "pair"
44 && let Some(key_node) = child.child_by_field_name("key")
45 {
46 if let (None, Some(quote_content)) = (column, key_node.child(0)) {
47 column = Some(quote_content.start_position().column);
48 }
49 if let Some(string_content) = key_node.child(1) {
50 let key = &contents[string_content.byte_range()];
51 match key {
52 // If it already has a source key, don't modify it
53 "source" => return None,
54 "command" => has_command = true,
55 "settings" => has_settings = true,
56 _ => other_keys += 1,
57 }
58 }
59 }
60 }
61
62 let source_type = if has_command { "custom" } else { "extension" };
63
64 // Insert the source key at the beginning of the object
65 let start = server_settings.start_byte() + 1;
66 let indent = " ".repeat(column.unwrap_or(12));
67
68 if !has_command && !has_settings {
69 return Some((
70 start..start,
71 format!(
72 r#"
73{indent}"source": "{}",
74{indent}"settings": {{}}{}
75 "#,
76 source_type,
77 if other_keys > 0 { "," } else { "" }
78 ),
79 ));
80 }
81
82 Some((
83 start..start,
84 format!(
85 r#"
86{indent}"source": "{}","#,
87 source_type
88 ),
89 ))
90}