settings.rs

 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}