1use std::path::Path;
2
3pub use tree_sitter;
5pub use tree_sitter_highlight;
6pub use tree_sitter_highlight::HighlightConfiguration;
7
8#[cfg(feature = "tree-sitter-bash")]
10pub use tree_sitter_bash;
11#[cfg(feature = "tree-sitter-c")]
12pub use tree_sitter_c;
13#[cfg(feature = "tree-sitter-c-sharp")]
14pub use tree_sitter_c_sharp;
15#[cfg(feature = "tree-sitter-cpp")]
16pub use tree_sitter_cpp;
17#[cfg(feature = "tree-sitter-css")]
18pub use tree_sitter_css;
19#[cfg(feature = "tree-sitter-go")]
20pub use tree_sitter_go;
21#[cfg(feature = "tree-sitter-html")]
22pub use tree_sitter_html;
23#[cfg(feature = "tree-sitter-java")]
24pub use tree_sitter_java;
25#[cfg(feature = "tree-sitter-javascript")]
26pub use tree_sitter_javascript;
27#[cfg(feature = "tree-sitter-json")]
28pub use tree_sitter_json;
29#[cfg(feature = "tree-sitter-lua")]
30pub use tree_sitter_lua;
31#[cfg(feature = "tree-sitter-odin")]
32pub use tree_sitter_odin;
33#[cfg(feature = "tree-sitter-pascal")]
34pub use tree_sitter_pascal;
35#[cfg(feature = "tree-sitter-php")]
36pub use tree_sitter_php;
37#[cfg(feature = "tree-sitter-python")]
38pub use tree_sitter_python;
39#[cfg(feature = "tree-sitter-ruby")]
40pub use tree_sitter_ruby;
41#[cfg(feature = "tree-sitter-rust")]
42pub use tree_sitter_rust;
43#[cfg(feature = "tree-sitter-typescript")]
44pub use tree_sitter_typescript;
45
46#[derive(Debug, Clone, Copy, PartialEq, Eq)]
48pub enum HighlightCategory {
49 Attribute,
50 Comment,
51 Constant,
52 Function,
53 Keyword,
54 Number,
55 Operator,
56 PunctuationBracket,
57 PunctuationDelimiter,
58 Property,
59 String,
60 Type,
61 Variable,
62}
63
64impl HighlightCategory {
65 pub fn from_default_index(index: usize) -> Option<Self> {
67 match index {
68 0 => Some(Self::Attribute),
69 1 => Some(Self::Comment),
70 2 => Some(Self::Constant),
71 3 => Some(Self::Function),
72 4 => Some(Self::Keyword),
73 5 => Some(Self::Number),
74 6 => Some(Self::Operator),
75 7 => Some(Self::PunctuationBracket),
76 8 => Some(Self::PunctuationDelimiter),
77 9 => Some(Self::Property),
78 10 => Some(Self::String),
79 11 => Some(Self::Type),
80 12 => Some(Self::Variable),
81 _ => None,
82 }
83 }
84
85 pub fn from_typescript_index(index: usize) -> Option<Self> {
87 match index {
88 0 => Some(Self::Attribute), 1 => Some(Self::Comment), 2 => Some(Self::Constant), 3 => Some(Self::Constant), 4 => Some(Self::Type), 5 => Some(Self::String), 6 => Some(Self::Function), 7 => Some(Self::Function), 8 => Some(Self::Function), 9 => Some(Self::Keyword), 10 => Some(Self::Number), 11 => Some(Self::Operator), 12 => Some(Self::Property), 13 => Some(Self::PunctuationBracket), 14 => Some(Self::PunctuationDelimiter), 15 => Some(Self::Constant), 16 => Some(Self::String), 17 => Some(Self::String), 18 => Some(Self::Type), 19 => Some(Self::Type), 20 => Some(Self::Variable), 21 => Some(Self::Constant), 22 => Some(Self::Variable), _ => None,
112 }
113 }
114
115 pub fn theme_key(&self) -> &'static str {
117 match self {
118 Self::Keyword => "syntax.keyword",
119 Self::String => "syntax.string",
120 Self::Comment => "syntax.comment",
121 Self::Function => "syntax.function",
122 Self::Type => "syntax.type",
123 Self::Variable | Self::Property => "syntax.variable",
124 Self::Constant | Self::Number | Self::Attribute => "syntax.constant",
125 Self::Operator => "syntax.operator",
126 Self::PunctuationBracket => "syntax.punctuation_bracket",
127 Self::PunctuationDelimiter => "syntax.punctuation_delimiter",
128 }
129 }
130
131 pub fn display_name(&self) -> &'static str {
133 match self {
134 Self::Attribute => "Attribute",
135 Self::Comment => "Comment",
136 Self::Constant => "Constant",
137 Self::Function => "Function",
138 Self::Keyword => "Keyword",
139 Self::Number => "Number",
140 Self::Operator => "Operator",
141 Self::PunctuationBracket => "Punctuation Bracket",
142 Self::PunctuationDelimiter => "Punctuation Delimiter",
143 Self::Property => "Property",
144 Self::String => "String",
145 Self::Type => "Type",
146 Self::Variable => "Variable",
147 }
148 }
149}
150
151#[derive(Debug, Clone, Copy, PartialEq, Eq)]
153pub enum Language {
154 Rust,
155 Python,
156 JavaScript,
157 TypeScript,
158 HTML,
159 CSS,
160 C,
161 Cpp,
162 Go,
163 Json,
164 Java,
165 CSharp,
166 Php,
167 Ruby,
168 Bash,
169 Lua,
170 Pascal,
171 Odin,
172}
173
174impl Language {
175 pub fn from_path(path: &Path) -> Option<Self> {
177 match path.extension()?.to_str()? {
178 "rs" => Some(Language::Rust),
179 "py" => Some(Language::Python),
180 "js" | "jsx" | "mjs" | "cjs" => Some(Language::JavaScript),
181 "ts" | "tsx" | "mts" | "cts" => Some(Language::TypeScript),
182 "html" => Some(Language::HTML),
183 "css" => Some(Language::CSS),
184 "c" | "h" => Some(Language::C),
185 "cpp" | "hpp" | "cc" | "hh" | "cxx" | "hxx" | "cppm" | "ixx" => Some(Language::Cpp),
186 "go" => Some(Language::Go),
187 "json" => Some(Language::Json),
188 "java" => Some(Language::Java),
189 "cs" => Some(Language::CSharp),
190 "php" => Some(Language::Php),
191 "rb" => Some(Language::Ruby),
192 "sh" | "bash" => Some(Language::Bash),
193 "lua" => Some(Language::Lua),
194 "pas" | "p" => Some(Language::Pascal),
195 "odin" => Some(Language::Odin),
196 _ => None,
197 }
198 }
199
200 pub fn highlight_config(&self) -> Result<HighlightConfiguration, String> {
202 match self {
203 Self::Rust => {
204 #[cfg(feature = "tree-sitter-rust")]
205 {
206 let mut config = HighlightConfiguration::new(
207 tree_sitter_rust::LANGUAGE.into(),
208 "rust",
209 tree_sitter_rust::HIGHLIGHTS_QUERY,
210 "",
211 "",
212 )
213 .map_err(|e| format!("Failed to create Rust highlight config: {e}"))?;
214 config.configure(DEFAULT_HIGHLIGHT_CAPTURES);
215 Ok(config)
216 }
217 #[cfg(not(feature = "tree-sitter-rust"))]
218 Err("Rust language support not enabled".to_string())
219 }
220 Self::Python => {
221 #[cfg(feature = "tree-sitter-python")]
222 {
223 let mut config = HighlightConfiguration::new(
224 tree_sitter_python::LANGUAGE.into(),
225 "python",
226 tree_sitter_python::HIGHLIGHTS_QUERY,
227 "",
228 "",
229 )
230 .map_err(|e| format!("Failed to create Python highlight config: {e}"))?;
231 config.configure(DEFAULT_HIGHLIGHT_CAPTURES);
232 Ok(config)
233 }
234 #[cfg(not(feature = "tree-sitter-python"))]
235 Err("Python language support not enabled".to_string())
236 }
237 Self::JavaScript => {
238 #[cfg(feature = "tree-sitter-javascript")]
239 {
240 let mut config = HighlightConfiguration::new(
241 tree_sitter_javascript::LANGUAGE.into(),
242 "javascript",
243 tree_sitter_javascript::HIGHLIGHT_QUERY,
244 "",
245 "",
246 )
247 .map_err(|e| format!("Failed to create JavaScript highlight config: {e}"))?;
248 config.configure(DEFAULT_HIGHLIGHT_CAPTURES);
249 Ok(config)
250 }
251 #[cfg(not(feature = "tree-sitter-javascript"))]
252 Err("JavaScript language support not enabled".to_string())
253 }
254 Self::TypeScript => {
255 #[cfg(all(feature = "tree-sitter-typescript", feature = "tree-sitter-javascript"))]
256 {
257 let combined_highlights = format!(
258 "{}\n{}",
259 tree_sitter_typescript::HIGHLIGHTS_QUERY,
260 tree_sitter_javascript::HIGHLIGHT_QUERY
261 );
262 let mut config = HighlightConfiguration::new(
263 tree_sitter_typescript::LANGUAGE_TYPESCRIPT.into(),
264 "typescript",
265 &combined_highlights,
266 "",
267 tree_sitter_typescript::LOCALS_QUERY,
268 )
269 .map_err(|e| format!("Failed to create TypeScript highlight config: {e}"))?;
270 config.configure(TYPESCRIPT_HIGHLIGHT_CAPTURES);
271 Ok(config)
272 }
273 #[cfg(not(all(
274 feature = "tree-sitter-typescript",
275 feature = "tree-sitter-javascript"
276 )))]
277 Err("TypeScript language support not enabled".to_string())
278 }
279 Self::HTML => {
280 #[cfg(feature = "tree-sitter-html")]
281 {
282 let mut config = HighlightConfiguration::new(
283 tree_sitter_html::LANGUAGE.into(),
284 "html",
285 tree_sitter_html::HIGHLIGHTS_QUERY,
286 "",
287 "",
288 )
289 .map_err(|e| format!("Failed to create HTML highlight config: {e}"))?;
290 config.configure(DEFAULT_HIGHLIGHT_CAPTURES);
291 Ok(config)
292 }
293 #[cfg(not(feature = "tree-sitter-html"))]
294 Err("HTML language support not enabled".to_string())
295 }
296 Self::CSS => {
297 #[cfg(feature = "tree-sitter-css")]
298 {
299 let mut config = HighlightConfiguration::new(
300 tree_sitter_css::LANGUAGE.into(),
301 "css",
302 tree_sitter_css::HIGHLIGHTS_QUERY,
303 "",
304 "",
305 )
306 .map_err(|e| format!("Failed to create CSS highlight config: {e}"))?;
307 config.configure(DEFAULT_HIGHLIGHT_CAPTURES);
308 Ok(config)
309 }
310 #[cfg(not(feature = "tree-sitter-css"))]
311 Err("CSS language support not enabled".to_string())
312 }
313 Self::C => {
314 #[cfg(feature = "tree-sitter-c")]
315 {
316 let mut config = HighlightConfiguration::new(
317 tree_sitter_c::LANGUAGE.into(),
318 "c",
319 tree_sitter_c::HIGHLIGHT_QUERY,
320 "",
321 "",
322 )
323 .map_err(|e| format!("Failed to create C highlight config: {e}"))?;
324 config.configure(DEFAULT_HIGHLIGHT_CAPTURES);
325 Ok(config)
326 }
327 #[cfg(not(feature = "tree-sitter-c"))]
328 Err("C language support not enabled".to_string())
329 }
330 Self::Cpp => {
331 #[cfg(feature = "tree-sitter-cpp")]
332 {
333 let mut config = HighlightConfiguration::new(
334 tree_sitter_cpp::LANGUAGE.into(),
335 "cpp",
336 tree_sitter_cpp::HIGHLIGHT_QUERY,
337 "",
338 "",
339 )
340 .map_err(|e| format!("Failed to create C++ highlight config: {e}"))?;
341 config.configure(DEFAULT_HIGHLIGHT_CAPTURES);
342 Ok(config)
343 }
344 #[cfg(not(feature = "tree-sitter-cpp"))]
345 Err("C++ language support not enabled".to_string())
346 }
347 Self::Go => {
348 #[cfg(feature = "tree-sitter-go")]
349 {
350 let mut config = HighlightConfiguration::new(
351 tree_sitter_go::LANGUAGE.into(),
352 "go",
353 tree_sitter_go::HIGHLIGHTS_QUERY,
354 "",
355 "",
356 )
357 .map_err(|e| format!("Failed to create Go highlight config: {e}"))?;
358 config.configure(DEFAULT_HIGHLIGHT_CAPTURES);
359 Ok(config)
360 }
361 #[cfg(not(feature = "tree-sitter-go"))]
362 Err("Go language support not enabled".to_string())
363 }
364 Self::Json => {
365 #[cfg(feature = "tree-sitter-json")]
366 {
367 let mut config = HighlightConfiguration::new(
368 tree_sitter_json::LANGUAGE.into(),
369 "json",
370 tree_sitter_json::HIGHLIGHTS_QUERY,
371 "",
372 "",
373 )
374 .map_err(|e| format!("Failed to create JSON highlight config: {e}"))?;
375 config.configure(DEFAULT_HIGHLIGHT_CAPTURES);
376 Ok(config)
377 }
378 #[cfg(not(feature = "tree-sitter-json"))]
379 Err("JSON language support not enabled".to_string())
380 }
381 Self::Java => {
382 #[cfg(feature = "tree-sitter-java")]
383 {
384 let mut config = HighlightConfiguration::new(
385 tree_sitter_java::LANGUAGE.into(),
386 "java",
387 tree_sitter_java::HIGHLIGHTS_QUERY,
388 "",
389 "",
390 )
391 .map_err(|e| format!("Failed to create Java highlight config: {e}"))?;
392 config.configure(DEFAULT_HIGHLIGHT_CAPTURES);
393 Ok(config)
394 }
395 #[cfg(not(feature = "tree-sitter-java"))]
396 Err("Java language support not enabled".to_string())
397 }
398 Self::CSharp => {
399 #[cfg(feature = "tree-sitter-c-sharp")]
400 {
401 let mut config = HighlightConfiguration::new(
402 tree_sitter_c_sharp::LANGUAGE.into(),
403 "c_sharp",
404 "",
405 "",
406 "",
407 )
408 .map_err(|e| format!("Failed to create C# highlight config: {e}"))?;
409 config.configure(DEFAULT_HIGHLIGHT_CAPTURES);
410 Ok(config)
411 }
412 #[cfg(not(feature = "tree-sitter-c-sharp"))]
413 Err("C# language support not enabled".to_string())
414 }
415 Self::Php => {
416 #[cfg(feature = "tree-sitter-php")]
417 {
418 let mut config = HighlightConfiguration::new(
419 tree_sitter_php::LANGUAGE_PHP.into(),
420 "php",
421 tree_sitter_php::HIGHLIGHTS_QUERY,
422 "",
423 "",
424 )
425 .map_err(|e| format!("Failed to create PHP highlight config: {e}"))?;
426 config.configure(DEFAULT_HIGHLIGHT_CAPTURES);
427 Ok(config)
428 }
429 #[cfg(not(feature = "tree-sitter-php"))]
430 Err("PHP language support not enabled".to_string())
431 }
432 Self::Ruby => {
433 #[cfg(feature = "tree-sitter-ruby")]
434 {
435 let mut config = HighlightConfiguration::new(
436 tree_sitter_ruby::LANGUAGE.into(),
437 "ruby",
438 tree_sitter_ruby::HIGHLIGHTS_QUERY,
439 "",
440 "",
441 )
442 .map_err(|e| format!("Failed to create Ruby highlight config: {e}"))?;
443 config.configure(DEFAULT_HIGHLIGHT_CAPTURES);
444 Ok(config)
445 }
446 #[cfg(not(feature = "tree-sitter-ruby"))]
447 Err("Ruby language support not enabled".to_string())
448 }
449 Self::Bash => {
450 #[cfg(feature = "tree-sitter-bash")]
451 {
452 let mut config = HighlightConfiguration::new(
453 tree_sitter_bash::LANGUAGE.into(),
454 "bash",
455 tree_sitter_bash::HIGHLIGHT_QUERY,
456 "",
457 "",
458 )
459 .map_err(|e| format!("Failed to create Bash highlight config: {e}"))?;
460 config.configure(DEFAULT_HIGHLIGHT_CAPTURES);
461 Ok(config)
462 }
463 #[cfg(not(feature = "tree-sitter-bash"))]
464 Err("Bash language support not enabled".to_string())
465 }
466 Self::Lua => {
467 #[cfg(feature = "tree-sitter-lua")]
468 {
469 let mut config = HighlightConfiguration::new(
470 tree_sitter_lua::LANGUAGE.into(),
471 "lua",
472 tree_sitter_lua::HIGHLIGHTS_QUERY,
473 "",
474 "",
475 )
476 .map_err(|e| format!("Failed to create Lua highlight config: {e}"))?;
477 config.configure(DEFAULT_HIGHLIGHT_CAPTURES);
478 Ok(config)
479 }
480 #[cfg(not(feature = "tree-sitter-lua"))]
481 Err("Lua language support not enabled".to_string())
482 }
483 Self::Pascal => {
484 #[cfg(feature = "tree-sitter-pascal")]
485 {
486 let mut config = HighlightConfiguration::new(
487 tree_sitter_pascal::LANGUAGE.into(),
488 "pascal",
489 "",
490 "",
491 "",
492 )
493 .map_err(|e| format!("Failed to create Pascal highlight config: {e}"))?;
494 config.configure(DEFAULT_HIGHLIGHT_CAPTURES);
495 Ok(config)
496 }
497 #[cfg(not(feature = "tree-sitter-pascal"))]
498 Err("Pascal language support not enabled".to_string())
499 }
500 Self::Odin => {
501 #[cfg(feature = "tree-sitter-odin")]
502 {
503 let mut config = HighlightConfiguration::new(
504 tree_sitter_odin::LANGUAGE.into(),
505 "odin",
506 "",
507 "",
508 "",
509 )
510 .map_err(|e| format!("Failed to create Odin highlight config: {e}"))?;
511 config.configure(DEFAULT_HIGHLIGHT_CAPTURES);
512 Ok(config)
513 }
514 #[cfg(not(feature = "tree-sitter-odin"))]
515 Err("Odin language support not enabled".to_string())
516 }
517 }
518 }
519
520 pub fn highlight_category(&self, index: usize) -> Option<HighlightCategory> {
522 match self {
523 Self::TypeScript => HighlightCategory::from_typescript_index(index),
524 _ => HighlightCategory::from_default_index(index),
525 }
526 }
527}
528
529impl Language {
530 pub fn all() -> &'static [Language] {
532 &[
533 Language::Rust,
534 Language::Python,
535 Language::JavaScript,
536 Language::TypeScript,
537 Language::HTML,
538 Language::CSS,
539 Language::C,
540 Language::Cpp,
541 Language::Go,
542 Language::Json,
543 Language::Java,
544 Language::CSharp,
545 Language::Php,
546 Language::Ruby,
547 Language::Bash,
548 Language::Lua,
549 Language::Pascal,
550 Language::Odin,
551 ]
552 }
553
554 pub fn id(&self) -> &'static str {
556 match self {
557 Self::Rust => "rust",
558 Self::Python => "python",
559 Self::JavaScript => "javascript",
560 Self::TypeScript => "typescript",
561 Self::HTML => "html",
562 Self::CSS => "css",
563 Self::C => "c",
564 Self::Cpp => "cpp",
565 Self::Go => "go",
566 Self::Json => "json",
567 Self::Java => "java",
568 Self::CSharp => "csharp",
569 Self::Php => "php",
570 Self::Ruby => "ruby",
571 Self::Bash => "bash",
572 Self::Lua => "lua",
573 Self::Pascal => "pascal",
574 Self::Odin => "odin",
575 }
576 }
577
578 pub fn lsp_language_id(&self, path: &Path) -> &'static str {
586 let ext = path.extension().and_then(|e| e.to_str()).unwrap_or("");
587 match (self, ext) {
588 (Self::TypeScript, "tsx") => "typescriptreact",
589 (Self::JavaScript, "jsx") => "javascriptreact",
590 _ => self.id(),
591 }
592 }
593
594 pub fn display_name(&self) -> &'static str {
596 match self {
597 Self::Rust => "Rust",
598 Self::Python => "Python",
599 Self::JavaScript => "JavaScript",
600 Self::TypeScript => "TypeScript",
601 Self::HTML => "HTML",
602 Self::CSS => "CSS",
603 Self::C => "C",
604 Self::Cpp => "C++",
605 Self::Go => "Go",
606 Self::Json => "JSON",
607 Self::Java => "Java",
608 Self::CSharp => "C#",
609 Self::Php => "PHP",
610 Self::Ruby => "Ruby",
611 Self::Bash => "Bash",
612 Self::Lua => "Lua",
613 Self::Pascal => "Pascal",
614 Self::Odin => "Odin",
615 }
616 }
617
618 pub fn from_id(id: &str) -> Option<Self> {
620 let id_lower = id.to_lowercase();
621 match id_lower.as_str() {
622 "rust" => Some(Self::Rust),
623 "python" => Some(Self::Python),
624 "javascript" => Some(Self::JavaScript),
625 "typescript" => Some(Self::TypeScript),
626 "html" => Some(Self::HTML),
627 "css" => Some(Self::CSS),
628 "c" => Some(Self::C),
629 "cpp" | "c++" => Some(Self::Cpp),
630 "go" => Some(Self::Go),
631 "json" => Some(Self::Json),
632 "java" => Some(Self::Java),
633 "c_sharp" | "c#" | "csharp" => Some(Self::CSharp),
634 "php" => Some(Self::Php),
635 "ruby" => Some(Self::Ruby),
636 "bash" => Some(Self::Bash),
637 "lua" => Some(Self::Lua),
638 "pascal" => Some(Self::Pascal),
639 "odin" => Some(Self::Odin),
640 _ => None,
641 }
642 }
643
644 pub fn from_name(name: &str) -> Option<Self> {
653 for lang in Self::all() {
655 if lang.display_name() == name {
656 return Some(*lang);
657 }
658 }
659
660 let name_lower = name.to_lowercase();
662 match name_lower.as_str() {
663 "rust" => Some(Self::Rust),
664 "python" => Some(Self::Python),
665 "javascript" | "javascript (babel)" => Some(Self::JavaScript),
666 "typescript" | "typescriptreact" => Some(Self::TypeScript),
667 "html" => Some(Self::HTML),
668 "css" => Some(Self::CSS),
669 "c" => Some(Self::C),
670 "c++" => Some(Self::Cpp),
671 "go" | "golang" => Some(Self::Go),
672 "json" => Some(Self::Json),
673 "java" => Some(Self::Java),
674 "c#" => Some(Self::CSharp),
675 "php" => Some(Self::Php),
676 "ruby" => Some(Self::Ruby),
677 "lua" => Some(Self::Lua),
678 "pascal" => Some(Self::Pascal),
679 "odin" => Some(Self::Odin),
680 _ => {
681 if name_lower.contains("bash") || name_lower.contains("shell") {
683 return Some(Self::Bash);
684 }
685 None
686 }
687 }
688 }
689}
690
691impl std::fmt::Display for Language {
692 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
693 write!(f, "{}", self.id())
694 }
695}
696
697const DEFAULT_HIGHLIGHT_CAPTURES: &[&str] = &[
698 "attribute",
699 "comment",
700 "constant",
701 "function",
702 "keyword",
703 "number",
704 "operator",
705 "punctuation.bracket",
706 "punctuation.delimiter",
707 "property",
708 "string",
709 "type",
710 "variable",
711];
712
713const TYPESCRIPT_HIGHLIGHT_CAPTURES: &[&str] = &[
714 "attribute",
715 "comment",
716 "constant",
717 "constant.builtin",
718 "constructor",
719 "embedded",
720 "function",
721 "function.builtin",
722 "function.method",
723 "keyword",
724 "number",
725 "operator",
726 "property",
727 "punctuation.bracket",
728 "punctuation.delimiter",
729 "punctuation.special",
730 "string",
731 "string.special",
732 "type",
733 "type.builtin",
734 "variable",
735 "variable.builtin",
736 "variable.parameter",
737];
738
739#[cfg(test)]
740mod tests {
741 use super::*;
742 use std::path::Path;
743
744 #[test]
745 fn test_lsp_language_id_tsx() {
746 let lang = Language::TypeScript;
747 assert_eq!(
748 lang.lsp_language_id(Path::new("app.tsx")),
749 "typescriptreact"
750 );
751 }
752
753 #[test]
754 fn test_lsp_language_id_ts() {
755 let lang = Language::TypeScript;
756 assert_eq!(lang.lsp_language_id(Path::new("app.ts")), "typescript");
757 }
758
759 #[test]
760 fn test_lsp_language_id_jsx() {
761 let lang = Language::JavaScript;
762 assert_eq!(
763 lang.lsp_language_id(Path::new("component.jsx")),
764 "javascriptreact"
765 );
766 }
767
768 #[test]
769 fn test_lsp_language_id_js() {
770 let lang = Language::JavaScript;
771 assert_eq!(lang.lsp_language_id(Path::new("app.js")), "javascript");
772 }
773
774 #[test]
775 fn test_lsp_language_id_csharp() {
776 let lang = Language::CSharp;
777 assert_eq!(lang.lsp_language_id(Path::new("main.cs")), "csharp");
778 }
779
780 #[test]
781 fn test_lsp_language_id_other_languages() {
782 assert_eq!(Language::Rust.lsp_language_id(Path::new("main.rs")), "rust");
783 assert_eq!(
784 Language::Python.lsp_language_id(Path::new("script.py")),
785 "python"
786 );
787 assert_eq!(Language::Go.lsp_language_id(Path::new("main.go")), "go");
788 }
789
790 #[test]
791 fn test_csharp_id_matches_config_key() {
792 assert_eq!(Language::CSharp.id(), "csharp");
795 }
796}