integration_go.rs
1 mod common; 2 use common::TestFixture; 3 use ecolog_lsp::server::handlers::{compute_diagnostics, handle_completion, handle_hover}; 4 use tower_lsp::lsp_types::{ 5 HoverParams, Position, TextDocumentIdentifier, TextDocumentPositionParams, 6 }; 7 8 #[tokio::test] 9 async fn test_go_hover_getenv() { 10 let fixture = TestFixture::new().await; 11 12 let content = "package main\nimport \"os\"\nfunc main() {\n val := os.Getenv(\"DB_URL\")\n}"; 13 let uri = fixture.create_file("test.go", content); 14 15 fixture 16 .state 17 .document_manager 18 .open(uri.clone(), "go".to_string(), content.to_string(), 0) 19 .await; 20 21 let hover = handle_hover( 22 HoverParams { 23 text_document_position_params: TextDocumentPositionParams { 24 text_document: TextDocumentIdentifier { uri }, 25 position: Position::new(3, 22), 26 }, 27 work_done_progress_params: Default::default(), 28 }, 29 &fixture.state, 30 ) 31 .await; 32 33 assert!(hover.is_some(), "Hover failed for os.Getenv"); 34 assert!(format!("{:?}", hover.unwrap()).contains("postgres://")); 35 } 36 37 #[tokio::test] 38 async fn test_go_hover_lookupenv() { 39 let fixture = TestFixture::new().await; 40 let uri = fixture.create_file( 41 "test.go", 42 "package main\nimport \"os\"\nfunc main() {\n val, _ := os.LookupEnv(\"API_KEY\")\n}", 43 ); 44 45 fixture 46 .state 47 .document_manager 48 .open( 49 uri.clone(), 50 "go".to_string(), 51 "package main\nimport \"os\"\nfunc main() {\n val, _ := os.LookupEnv(\"API_KEY\")\n}" 52 .to_string(), 53 0, 54 ) 55 .await; 56 57 let hover = handle_hover( 58 HoverParams { 59 text_document_position_params: TextDocumentPositionParams { 60 text_document: TextDocumentIdentifier { uri }, 61 position: Position::new(3, 27), 62 }, 63 work_done_progress_params: Default::default(), 64 }, 65 &fixture.state, 66 ) 67 .await; 68 69 assert!(hover.is_some(), "Hover failed for os.LookupEnv"); 70 assert!(format!("{:?}", hover.unwrap()).contains("secret_key")); 71 } 72 73 #[tokio::test] 74 async fn test_go_completion() { 75 let fixture = TestFixture::new().await; 76 77 tokio::time::sleep(std::time::Duration::from_millis(100)).await; 78 let content = "package main\nimport \"os\"\nfunc main() {\n os.LookupEnv(\"\")\n}"; 79 let uri = fixture.create_file("test.go", content); 80 81 fixture 82 .state 83 .document_manager 84 .open(uri.clone(), "go".to_string(), content.to_string(), 0) 85 .await; 86 87 let completion = handle_completion( 88 tower_lsp::lsp_types::CompletionParams { 89 text_document_position: TextDocumentPositionParams { 90 text_document: TextDocumentIdentifier { uri }, 91 position: Position::new(3, 16), 92 }, 93 work_done_progress_params: Default::default(), 94 partial_result_params: Default::default(), 95 context: None, 96 }, 97 &fixture.state, 98 ) 99 .await; 100 101 assert!(completion.is_some(), "Completion failed for os.Getenv"); 102 assert!(completion.unwrap().iter().any(|i| i.label == "PORT")); 103 } 104 105 // ═══════════════════════════════════════════════════════════════════════════ 106 // New Pattern Tests: struct init, multiple assignment, conditional binding, viper 107 // ═══════════════════════════════════════════════════════════════════════════ 108 109 #[tokio::test] 110 async fn test_go_hover_struct_init() { 111 let fixture = TestFixture::new().await; 112 let content = r#"package main 113 import "os" 114 type Config struct { DB string } 115 func main() { 116 cfg := Config{DB: os.Getenv("DB_URL")} 117 }"#; 118 let uri = fixture.create_file("test.go", content); 119 120 fixture 121 .state 122 .document_manager 123 .open(uri.clone(), "go".to_string(), content.to_string(), 0) 124 .await; 125 126 let hover = handle_hover( 127 HoverParams { 128 text_document_position_params: TextDocumentPositionParams { 129 text_document: TextDocumentIdentifier { uri }, 130 position: Position::new(4, 33), 131 }, 132 work_done_progress_params: Default::default(), 133 }, 134 &fixture.state, 135 ) 136 .await; 137 138 assert!(hover.is_some(), "Expected hover for struct field init"); 139 assert!(format!("{:?}", hover.unwrap()).contains("postgres://")); 140 } 141 142 #[tokio::test] 143 async fn test_go_hover_lookupenv_with_ok() { 144 let fixture = TestFixture::new().await; 145 let content = r#"package main 146 import "os" 147 func main() { 148 val, ok := os.LookupEnv("DB_URL") 149 if ok { println(val) } 150 }"#; 151 let uri = fixture.create_file("test.go", content); 152 153 fixture 154 .state 155 .document_manager 156 .open(uri.clone(), "go".to_string(), content.to_string(), 0) 157 .await; 158 159 let hover = handle_hover( 160 HoverParams { 161 text_document_position_params: TextDocumentPositionParams { 162 text_document: TextDocumentIdentifier { uri }, 163 position: Position::new(3, 28), 164 }, 165 work_done_progress_params: Default::default(), 166 }, 167 &fixture.state, 168 ) 169 .await; 170 171 assert!(hover.is_some(), "Expected hover for LookupEnv with ok"); 172 assert!(format!("{:?}", hover.unwrap()).contains("postgres://")); 173 } 174 175 #[tokio::test] 176 async fn test_go_hover_if_init() { 177 let fixture = TestFixture::new().await; 178 let content = r#"package main 179 import "os" 180 func main() { 181 if val, ok := os.LookupEnv("DB_URL"); ok { 182 println(val) 183 } 184 }"#; 185 let uri = fixture.create_file("test.go", content); 186 187 fixture 188 .state 189 .document_manager 190 .open(uri.clone(), "go".to_string(), content.to_string(), 0) 191 .await; 192 193 let hover = handle_hover( 194 HoverParams { 195 text_document_position_params: TextDocumentPositionParams { 196 text_document: TextDocumentIdentifier { uri }, 197 position: Position::new(3, 31), 198 }, 199 work_done_progress_params: Default::default(), 200 }, 201 &fixture.state, 202 ) 203 .await; 204 205 assert!(hover.is_some(), "Expected hover for if statement init"); 206 assert!(format!("{:?}", hover.unwrap()).contains("postgres://")); 207 } 208 209 #[tokio::test] 210 async fn test_go_hover_viper_getstring() { 211 let fixture = TestFixture::new().await; 212 let content = r#"package main 213 import "github.com/spf13/viper" 214 func main() { 215 db := viper.GetString("DB_URL") 216 }"#; 217 let uri = fixture.create_file("test.go", content); 218 219 fixture 220 .state 221 .document_manager 222 .open(uri.clone(), "go".to_string(), content.to_string(), 0) 223 .await; 224 225 let hover = handle_hover( 226 HoverParams { 227 text_document_position_params: TextDocumentPositionParams { 228 text_document: TextDocumentIdentifier { uri }, 229 position: Position::new(3, 26), 230 }, 231 work_done_progress_params: Default::default(), 232 }, 233 &fixture.state, 234 ) 235 .await; 236 237 assert!(hover.is_some(), "Expected hover for viper.GetString"); 238 assert!(format!("{:?}", hover.unwrap()).contains("postgres://")); 239 } 240 241 #[tokio::test] 242 async fn test_go_diagnostics_undefined() { 243 let fixture = TestFixture::new().await; 244 let content = r#"package main 245 import "os" 246 func main() { 247 val := os.Getenv("MISSING_VAR") 248 println(val) 249 }"#; 250 let uri = fixture.create_file("test.go", content); 251 252 fixture 253 .state 254 .document_manager 255 .open(uri.clone(), "go".to_string(), content.to_string(), 0) 256 .await; 257 258 let diags = compute_diagnostics(&uri, &fixture.state).await; 259 260 assert!(!diags.is_empty()); 261 assert!(diags.iter().any(|d| d.message.contains("not defined"))); 262 }