Skip to content

Commit b563060

Browse files
committed
feat(lsp): improve documentation and completion
1 parent bcb284b commit b563060

File tree

3 files changed

+97
-16
lines changed

3 files changed

+97
-16
lines changed

Cargo.lock

Lines changed: 38 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lsp/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ serde_json = { version = "1", features = ["std"] }
1010
tokio = { version = "1.37", default-features = false, features = ["rt-multi-thread", "io-std", "macros"] }
1111
serde = { version = "1.0.210", features = ["derive"] }
1212
regex = "1.10.6"
13+
walkdir = "2.5.0"

lsp/src/main.rs

Lines changed: 58 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::path::Path;
1+
use std::path::{Path, PathBuf};
22

33
use dashmap::DashMap;
44
use serde::Deserialize;
@@ -67,9 +67,10 @@ impl Backend {
6767
config.clone()
6868
}
6969

70-
async fn load_env_vars(&self, modified_file: Option<&Path>) {
70+
async fn load_env_vars(&self, workdir: Option<PathBuf>, modified_file: Option<&Path>) {
7171
let configs = self.get_configs().await;
7272
let mut envs = DashMap::new();
73+
let regex = regex::Regex::new(&configs.dotenv_environment).unwrap();
7374

7475
if configs.load_shell {
7576
envs.extend(std::env::vars().map(|(k, v)| (k, (v, None))));
@@ -81,10 +82,38 @@ impl Backend {
8182
}));
8283
}
8384

84-
// load envfiles
85+
// load all envfiles
86+
if let Some(workdir) = workdir.and_then(|v| {
87+
regex
88+
.is_match(v.file_name().unwrap().to_str().unwrap())
89+
.then_some(v)
90+
}) {
91+
let files = walkdir::WalkDir::new(workdir)
92+
.into_iter()
93+
.filter_map(|e| {
94+
if e.as_ref().is_ok_and(|f| {
95+
f.path().is_file() && regex.is_match(f.path().to_str().unwrap_or(""))
96+
}) {
97+
e.ok()
98+
} else {
99+
None
100+
}
101+
})
102+
.collect::<Vec<_>>();
103+
for entry in files {
104+
let path = entry.path();
105+
self.client
106+
.log_message(MessageType::INFO, &format!("File match: {path:?}"))
107+
.await;
108+
109+
let content = std::fs::read_to_string(path).unwrap();
110+
envs.extend(parse_dotenv(&content));
111+
}
112+
}
113+
// Load changed env files
85114
if let Some(modified_file) = modified_file.and_then(|v| {
86-
let r = regex::Regex::new(&configs.dotenv_environment).unwrap();
87-
r.is_match(v.file_name().unwrap().to_str().unwrap())
115+
regex
116+
.is_match(v.file_name().unwrap().to_str().unwrap())
88117
.then_some(v)
89118
}) {
90119
let content = std::fs::read_to_string(modified_file).unwrap();
@@ -112,6 +141,9 @@ impl LanguageServer for Backend {
112141
*config = serde_json::from_value(options).unwrap();
113142
}
114143

144+
self.load_env_vars(params.root_uri.map(|root| PathBuf::from(root.path())), None)
145+
.await;
146+
115147
Ok(InitializeResult {
116148
server_info: Some(ServerInfo {
117149
name: env!("CARGO_PKG_NAME").to_owned(),
@@ -136,12 +168,12 @@ impl LanguageServer for Backend {
136168
}
137169

138170
async fn did_open(&self, params: DidOpenTextDocumentParams) {
139-
self.load_env_vars(Some(Path::new(params.text_document.uri.path())))
171+
self.load_env_vars(None, Some(Path::new(params.text_document.uri.path())))
140172
.await
141173
}
142174

143175
async fn did_change(&self, params: DidChangeTextDocumentParams) {
144-
self.load_env_vars(Some(Path::new(params.text_document.uri.path())))
176+
self.load_env_vars(None, Some(Path::new(params.text_document.uri.path())))
145177
.await
146178
}
147179

@@ -158,7 +190,26 @@ impl LanguageServer for Backend {
158190
.map(|env| {
159191
let key = env.key().to_owned();
160192
let (value, docs) = env.value();
193+
let documentation = if configs.show_documentation {
194+
docs.as_ref().map(|d| {
195+
let value = if configs.show_content_on_docs && !value.is_empty() {
196+
format!("{d}\n\ncontent: {value}")
197+
} else {
198+
d.clone()
199+
};
200+
Documentation::MarkupContent(MarkupContent {
201+
value,
202+
kind: configs
203+
.documentation_kind
204+
.clone()
205+
.unwrap_or(MarkupKind::Markdown),
206+
})
207+
})
208+
} else {
209+
None
210+
};
161211
CompletionItem {
212+
documentation,
162213
label: key.clone(),
163214
kind: Some(configs.item_kind),
164215
text_edit: Some(CompletionTextEdit::Edit(TextEdit::new(
@@ -169,15 +220,6 @@ impl LanguageServer for Backend {
169220
key
170221
},
171222
))),
172-
documentation: docs.as_ref().map(|d| {
173-
Documentation::MarkupContent(MarkupContent {
174-
kind: configs
175-
.documentation_kind
176-
.clone()
177-
.unwrap_or(MarkupKind::Markdown),
178-
value: d.clone(),
179-
})
180-
}),
181223
..Default::default()
182224
}
183225
})

0 commit comments

Comments
 (0)