Skip to content

Commit c4ae1a5

Browse files
committed
add function module
it combines function and docs into one HashMap with clear interface for getting functions or docs for them
1 parent 170cee2 commit c4ae1a5

5 files changed

Lines changed: 81 additions & 32 deletions

File tree

src/backend.rs

Lines changed: 12 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,14 @@ use simplicityhl::{
2828
};
2929

3030
use crate::completion::{self, CompletionProvider};
31+
use crate::function::Functions;
3132
use crate::utils::{
3233
find_related_call, get_call_span, get_comments_from_lines, position_to_span, span_to_positions,
3334
};
3435

3536
#[derive(Debug)]
3637
struct Document {
37-
functions: Vec<parse::Function>,
38-
functions_docs: HashMap<String, String>,
38+
functions: Functions,
3939
text: Rope,
4040
}
4141

@@ -243,18 +243,8 @@ impl Backend {
243243
return None;
244244
}
245245

246-
let mut completions = CompletionProvider::get_function_completions(
247-
&doc.functions
248-
.iter()
249-
.map(|func| {
250-
let function_doc = doc
251-
.functions_docs
252-
.get(&func.name().to_string())
253-
.map_or(String::new(), String::clone);
254-
(func.to_owned(), function_doc)
255-
})
256-
.collect::<Vec<_>>(),
257-
);
246+
let mut completions =
247+
CompletionProvider::get_function_completions(&doc.functions.functions_and_docs());
258248
completions.extend_from_slice(self.completion_provider.builtins());
259249
completions.extend_from_slice(self.completion_provider.modules());
260250

@@ -269,8 +259,8 @@ impl Backend {
269259
let token_pos = params.text_document_position_params.position;
270260
let token_span = position_to_span(token_pos).ok()?;
271261

272-
let call = find_related_call(&document.functions, token_span).ok()?;
273-
let call_span = get_call_span(call).ok()?;
262+
let call = find_related_call(&document.functions.functions(), token_span).ok()?;
263+
let call_span = get_call_span(&call).ok()?;
274264
let (start, end) = span_to_positions(&call_span).ok()?;
275265

276266
let description = match call.name() {
@@ -289,8 +279,7 @@ impl Backend {
289279
)
290280
}
291281
parse::CallName::Custom(func) => {
292-
let function = document.functions.iter().find(|f| f.name() == func)?;
293-
let function_doc = document.functions_docs.get(&func.to_string())?;
282+
let (function, function_doc) = document.functions.get(func.as_inner())?;
294283

295284
let template = completion::function_to_template(function, function_doc);
296285
format!(
@@ -335,14 +324,11 @@ impl Backend {
335324
let token_position = params.text_document_position_params.position;
336325
let token_span = position_to_span(token_position).ok()?;
337326

338-
let call = find_related_call(&document.functions, token_span).ok()?;
327+
let call = find_related_call(&document.functions.functions(), token_span).ok()?;
339328

340329
match call.name() {
341330
simplicityhl::parse::CallName::Custom(func) => {
342-
let function = document
343-
.functions
344-
.iter()
345-
.find(|function| function.name() == func)?;
331+
let function = document.functions.get_func(func.as_inner())?;
346332

347333
let (start, end) = span_to_positions(function.as_ref()).ok()?;
348334
Some(GotoDefinitionResponse::from(Location::new(
@@ -358,8 +344,7 @@ impl Backend {
358344
/// Create [`Document`] using parsed program and code.
359345
fn create_document(program: &simplicityhl::parse::Program, text: &str) -> Document {
360346
let mut document = Document {
361-
functions: vec![],
362-
functions_docs: HashMap::new(),
347+
functions: Functions::new(),
363348
text: Rope::from_str(text),
364349
};
365350

@@ -376,9 +361,9 @@ fn create_document(program: &simplicityhl::parse::Program, text: &str) -> Docume
376361
.for_each(|func| {
377362
let start_line = u32::try_from(func.as_ref().start.line.get()).unwrap_or_default() - 1;
378363

379-
document.functions.push(func.to_owned());
380-
document.functions_docs.insert(
364+
document.functions.insert(
381365
func.name().to_string(),
366+
func.to_owned(),
382367
get_comments_from_lines(start_line, &document.text),
383368
);
384369
});
@@ -423,7 +408,6 @@ mod tests {
423408
assert!(err.is_none(), "Expected no parsing error");
424409
let doc = doc.expect("Expected Some(Document)");
425410
assert_eq!(doc.functions.len(), 2);
426-
assert!(doc.functions_docs.contains_key("add"));
427411
}
428412

429413
#[test]

src/completion/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ impl CompletionProvider {
6464
}
6565

6666
/// Get generic functions completions.
67-
pub fn get_function_completions(functions: &[(Function, String)]) -> Vec<CompletionItem> {
67+
pub fn get_function_completions(functions: &Vec<(&Function, &String)>) -> Vec<CompletionItem> {
6868
functions
6969
.iter()
7070
.map(|(func, doc)| {

src/function.rs

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
use simplicityhl::parse::Function;
2+
use std::collections::HashMap;
3+
4+
/// Container for parsed functions and their corresponding source text.
5+
#[derive(Debug, Clone)]
6+
pub struct Functions {
7+
/// The map from function name to its parsed representation and source text.
8+
pub map: HashMap<String, (Function, String)>,
9+
}
10+
11+
#[allow(dead_code)]
12+
impl Functions {
13+
/// Creates a new, empty `Functions` structure.
14+
pub fn new() -> Self {
15+
Self {
16+
map: HashMap::new(),
17+
}
18+
}
19+
20+
/// Inserts or updates a function and its document text.
21+
pub fn insert(&mut self, name: String, func: Function, doc: String) {
22+
self.map.insert(name, (func, doc));
23+
}
24+
25+
/// Get pair of function and documentation.
26+
pub fn get(&self, name: &str) -> Option<(&Function, &String)> {
27+
self.map.get(name).map(|(func, doc)| (func, doc))
28+
}
29+
30+
/// Retrieves a reference to a parsed function by name.
31+
pub fn get_func(&self, name: &str) -> Option<&Function> {
32+
self.map.get(name).map(|(func, _)| func)
33+
}
34+
35+
/// Retrieves a reference to the function's documentation.
36+
pub fn get_doc(&self, name: &str) -> Option<&String> {
37+
self.map.get(name).map(|(_, doc)| doc)
38+
}
39+
40+
/// Returns lenght of inner map.
41+
pub fn len(&self) -> usize {
42+
self.map.len()
43+
}
44+
45+
/// Returns all function names.
46+
pub fn keys(&self) -> impl Iterator<Item = &String> {
47+
self.map.keys()
48+
}
49+
50+
/// Returns a vector of all parsed functions.
51+
pub fn functions(&self) -> Vec<&Function> {
52+
self.map.values().map(|(func, _)| func).collect()
53+
}
54+
55+
/// Returns a vector of all function document strings.
56+
pub fn documentations(&self) -> Vec<&String> {
57+
self.map.values().map(|(_, doc)| doc).collect()
58+
}
59+
60+
/// Returns a vector of (function name, function) pairs.
61+
pub fn functions_and_docs(&self) -> Vec<(&Function, &String)> {
62+
self.map.values().map(|(func, doc)| (func, doc)).collect()
63+
}
64+
}

src/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
mod backend;
22
mod completion;
3+
mod function;
34
mod utils;
45

56
use backend::Backend;

src/utils.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -159,9 +159,9 @@ pub fn get_comments_from_lines(line: u32, rope: &Rope) -> String {
159159

160160
/// Find [`simplicityhl::parse::Call`] which contains given [`simplicityhl::error::Span`], which also have minimal Span.
161161
pub fn find_related_call(
162-
functions: &[parse::Function],
162+
functions: &[&parse::Function],
163163
token_span: simplicityhl::error::Span,
164-
) -> std::result::Result<&simplicityhl::parse::Call, &'static str> {
164+
) -> std::result::Result<simplicityhl::parse::Call, &'static str> {
165165
let func = functions
166166
.iter()
167167
.find(|func| span_contains(func.span(), &token_span))
@@ -182,7 +182,7 @@ pub fn find_related_call(
182182
.last()
183183
.ok_or("no related call found")?;
184184

185-
Ok(call)
185+
Ok(call.to_owned())
186186
}
187187

188188
pub fn get_call_span(

0 commit comments

Comments
 (0)