swiftide_integrations/treesitter/
metadata_refs_defs_code.rs1use std::sync::Arc;
38
39use swiftide_core::{Transformer, indexing::TextNode};
40
41use crate::treesitter::{CodeParser, SupportedLanguages};
42use anyhow::{Context as _, Result};
43use async_trait::async_trait;
44
45pub const NAME_REFERENCES: &str = "References (code)";
46pub const NAME_DEFINITIONS: &str = "Definitions (code)";
47
48#[swiftide_macros::indexing_transformer(derive(skip_default))]
50pub struct MetadataRefsDefsCode {
51 code_parser: Arc<CodeParser>,
52}
53
54impl MetadataRefsDefsCode {
55 pub fn try_from_language(language: impl TryInto<SupportedLanguages>) -> Result<Self> {
61 let language: SupportedLanguages = language
62 .try_into()
63 .ok()
64 .context("Treesitter language not supported")?;
65
66 MetadataRefsDefsCode::builder()
67 .code_parser(CodeParser::from_language(language))
68 .build()
69 }
70}
71
72#[async_trait]
73impl Transformer for MetadataRefsDefsCode {
74 type Input = String;
75 type Output = String;
76 async fn transform_node(&self, mut node: TextNode) -> Result<TextNode> {
79 let refs_defs = self
80 .code_parser
81 .parse(&node.chunk)?
82 .references_and_definitions()?;
83
84 if !refs_defs.references.is_empty() {
85 node.metadata
86 .insert(NAME_REFERENCES.to_string(), refs_defs.references.join(","));
87 }
88
89 if !refs_defs.definitions.is_empty() {
90 node.metadata.insert(
91 NAME_DEFINITIONS.to_string(),
92 refs_defs.definitions.join(","),
93 );
94 }
95 Ok(node)
96 }
97}
98
99#[cfg(test)]
100mod test {
101
102 use super::*;
103 use test_case::test_case;
104
105 #[test_case("rust", "fn main() { println!(\"Hello, World!\"); }", "println", "main"; "rust")]
106 #[test_case("ruby", "def main; puts 'Hello, World!'; end", "puts", "main"; "ruby")]
107 #[test_case("python", "def main(): print('Hello, World!')", "print", "main"; "python")]
108 #[test_case("javascript", "function main() { console.log('Hello, World!'); }", "log", "main"; "javascript")]
109 #[test_case("typescript", "function main() { console.log('Hello, World!'); }", "log", "main"; "typescript")]
110 #[test_case("java", "public class Main { public static void main(String[] args) { System.out.println(\"Hello, World!\"); } }", "println", "Main,main"; "java")]
111 #[tokio::test]
112 async fn assert_refs_defs_from_code(
113 lang: &str,
114 code: &str,
115 expected_references: &str,
116 expected_definitions: &str,
117 ) {
118 let transformer = MetadataRefsDefsCode::try_from_language(lang).unwrap();
119 let node = TextNode::new(code);
120
121 let node = transformer.transform_node(node).await.unwrap();
122
123 let references = node
124 .metadata
125 .get(NAME_REFERENCES)
126 .unwrap()
127 .as_str()
128 .unwrap()
129 .to_string();
130 let definitions = node
131 .metadata
132 .get(NAME_DEFINITIONS)
133 .unwrap()
134 .as_str()
135 .unwrap()
136 .to_string();
137
138 assert_eq!(references, expected_references);
139 assert_eq!(definitions, expected_definitions);
140 }
141}