1use std::path::PathBuf;
2use thiserror::Error;
3
4#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
6pub enum Language {
7 Rust,
8 TypeScript,
9 JavaScript,
10 Python,
11 Go,
12 Cpp,
13 C,
14}
15
16impl std::fmt::Display for Language {
17 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
18 match self {
19 Language::Rust => write!(f, "rust"),
20 Language::TypeScript => write!(f, "typescript"),
21 Language::JavaScript => write!(f, "javascript"),
22 Language::Python => write!(f, "python"),
23 Language::Go => write!(f, "go"),
24 Language::Cpp => write!(f, "cpp"),
25 Language::C => write!(f, "c"),
26 }
27 }
28}
29
30impl Language {
31 pub fn language_id(&self) -> &'static str {
33 match self {
34 Language::Rust => "rust",
35 Language::TypeScript => "typescript",
36 Language::JavaScript => "javascript",
37 Language::Python => "python",
38 Language::Go => "go",
39 Language::Cpp => "cpp",
40 Language::C => "c",
41 }
42 }
43
44 pub fn from_extension(ext: &str) -> Option<Self> {
46 match ext.to_lowercase().as_str() {
47 "rs" => Some(Language::Rust),
48 "ts" | "tsx" => Some(Language::TypeScript),
49 "js" | "jsx" | "mjs" | "cjs" => Some(Language::JavaScript),
50 "py" | "pyi" => Some(Language::Python),
51 "go" => Some(Language::Go),
52 "cpp" | "cc" | "cxx" | "hpp" | "hxx" => Some(Language::Cpp),
53 "c" | "h" => Some(Language::C),
54 _ => None,
55 }
56 }
57
58 pub fn from_str(s: &str) -> Option<Self> {
60 match s.to_lowercase().as_str() {
61 "rust" | "rs" => Some(Language::Rust),
62 "typescript" | "ts" => Some(Language::TypeScript),
63 "javascript" | "js" => Some(Language::JavaScript),
64 "python" | "py" => Some(Language::Python),
65 "go" | "golang" => Some(Language::Go),
66 "cpp" | "c++" => Some(Language::Cpp),
67 "c" => Some(Language::C),
68 _ => None,
69 }
70 }
71}
72
73#[derive(Error, Debug)]
75pub enum LspMcpError {
76 #[error("No active workspace. Call lsp_activate_workspace first.")]
77 NoActiveWorkspace,
78
79 #[error("Workspace not found: {0}")]
80 WorkspaceNotFound(PathBuf),
81
82 #[error("Language server not running for {language} in {workspace}")]
83 ServerNotRunning {
84 language: Language,
85 workspace: PathBuf,
86 },
87
88 #[error("Language server failed to start: {0}")]
89 ServerStartFailed(String),
90
91 #[error("Language server initialization failed: {0}")]
92 InitializationFailed(String),
93
94 #[error("LSP request timed out after {0} seconds")]
95 RequestTimeout(u64),
96
97 #[error("LSP protocol error: {0}")]
98 ProtocolError(String),
99
100 #[error("File not found: {0}")]
101 FileNotFound(PathBuf),
102
103 #[error("Unsupported language: {0}")]
104 UnsupportedLanguage(String),
105
106 #[error("Invalid position: line {line}, character {character}")]
107 InvalidPosition { line: u32, character: u32 },
108
109 #[error("Language server not available: {0}")]
110 ServerNotAvailable(String),
111
112 #[error("IO error: {0}")]
113 Io(#[from] std::io::Error),
114
115 #[error("JSON error: {0}")]
116 Json(#[from] serde_json::Error),
117
118 #[error("Channel send error")]
119 ChannelSend,
120
121 #[error("Channel receive error")]
122 ChannelRecv,
123}
124
125pub type Result<T> = std::result::Result<T, LspMcpError>;