this repo has no description
1mod code_action;
2mod compiler;
3mod completer;
4mod edits;
5mod engine;
6mod feedback;
7mod files;
8mod messages;
9mod progress;
10mod reference;
11mod rename;
12mod router;
13mod server;
14mod signature_help;
15
16#[cfg(test)]
17mod tests;
18
19pub use server::LanguageServer;
20
21use crate::{
22 Result, ast::SrcSpan, build::Target, line_numbers::LineNumbers, manifest::Manifest,
23 paths::ProjectPaths,
24};
25use camino::Utf8PathBuf;
26use lsp_types::{Position, Range, TextEdit, Url};
27use std::any::Any;
28
29#[derive(Debug)]
30pub struct LockGuard(pub Box<dyn Any>);
31
32pub trait Locker {
33 fn lock_for_build(&self) -> Result<LockGuard>;
34}
35
36pub trait MakeLocker {
37 fn make_locker(&self, paths: &ProjectPaths, target: Target) -> Result<Box<dyn Locker>>;
38}
39
40pub trait DownloadDependencies {
41 fn download_dependencies(&self, paths: &ProjectPaths) -> Result<Manifest>;
42}
43
44pub fn src_span_to_lsp_range(location: SrcSpan, line_numbers: &LineNumbers) -> Range {
45 let start = line_numbers.line_and_column_number(location.start);
46 let end = line_numbers.line_and_column_number(location.end);
47
48 Range::new(
49 Position::new(start.line - 1, start.column - 1),
50 Position::new(end.line - 1, end.column - 1),
51 )
52}
53
54pub fn lsp_range_to_src_span(range: Range, line_numbers: &LineNumbers) -> SrcSpan {
55 let start = line_numbers.byte_index(range.start);
56 let end = line_numbers.byte_index(range.end);
57 SrcSpan { start, end }
58}
59
60/// A little wrapper around LineNumbers to make it easier to build text edits.
61///
62#[derive(Debug)]
63pub struct TextEdits<'a> {
64 line_numbers: &'a LineNumbers,
65 edits: Vec<TextEdit>,
66}
67
68impl<'a> TextEdits<'a> {
69 pub fn new(line_numbers: &'a LineNumbers) -> Self {
70 TextEdits {
71 line_numbers,
72 edits: vec![],
73 }
74 }
75
76 pub fn src_span_to_lsp_range(&self, location: SrcSpan) -> Range {
77 src_span_to_lsp_range(location, self.line_numbers)
78 }
79
80 pub fn lsp_range_to_src_span(&self, range: Range) -> SrcSpan {
81 lsp_range_to_src_span(range, self.line_numbers)
82 }
83
84 pub fn replace(&mut self, location: SrcSpan, new_text: String) {
85 self.edits.push(TextEdit {
86 range: src_span_to_lsp_range(location, self.line_numbers),
87 new_text,
88 })
89 }
90
91 pub fn insert(&mut self, at: u32, new_text: String) {
92 self.replace(SrcSpan { start: at, end: at }, new_text)
93 }
94
95 pub fn delete(&mut self, location: SrcSpan) {
96 self.replace(location, "".to_string())
97 }
98
99 fn delete_range(&mut self, range: Range) {
100 self.edits.push(TextEdit {
101 range,
102 new_text: "".into(),
103 })
104 }
105}
106
107fn path(uri: &Url) -> Utf8PathBuf {
108 // The to_file_path method is available on these platforms
109 #[cfg(any(unix, windows, target_os = "redox", target_os = "wasi"))]
110 return Utf8PathBuf::from_path_buf(uri.to_file_path().expect("URL file"))
111 .expect("Non Utf8 Path");
112
113 #[cfg(not(any(unix, windows, target_os = "redox", target_os = "wasi")))]
114 return Utf8PathBuf::from_path_buf(uri.path().into()).expect("Non Utf8 Path");
115}
116
117fn url_from_path(path: &str) -> Option<Url> {
118 // The targets for which `from_file_path` is defined
119 #[cfg(any(
120 unix,
121 windows,
122 target_os = "redox",
123 target_os = "wasi",
124 target_os = "hermit"
125 ))]
126 let uri = Url::from_file_path(path).ok();
127
128 #[cfg(not(any(
129 unix,
130 windows,
131 target_os = "redox",
132 target_os = "wasi",
133 target_os = "hermit"
134 )))]
135 let uri = Url::parse(&format!("file://{path}")).ok();
136
137 uri
138}