diff --git a/crates/lang_srv/src/analysis.rs b/crates/lang_srv/src/analysis.rs index 30f2387471..b17963b158 100644 --- a/crates/lang_srv/src/analysis.rs +++ b/crates/lang_srv/src/analysis.rs @@ -59,93 +59,78 @@ fn is_roc_identifier_char(char: &char) -> bool { } ///Returns a closure that will run the global analysis and the docinfo for the provided source ///This means that you can get positions within the source code before the analysis completes -pub(crate) fn global_analysis( - source_url: Url, - source: String, - version: i32, -) -> (impl FnOnce() -> Vec, DocInfo) { - let fi = source_url.to_file_path().unwrap(); +pub(crate) fn global_analysis(doc_info: DocInfo) -> Vec { + let fi = doc_info.url.to_file_path().unwrap(); let src_dir = find_src_dir(&fi).to_path_buf(); - let line_info = LineInfo::new(&source); - let doc_info = DocInfo { - url: source_url.clone(), - line_info: line_info.clone(), - source: source.clone(), - version, - }; //We will return this before the analysis has completed to enable completion - let doc_info_return = doc_info.clone(); - let perform_analysis = move || { - let arena = Bump::new(); - let loaded = roc_load::load_and_typecheck_str( - &arena, - fi, - &source, - src_dir, - roc_target::TargetInfo::default_x86_64(), - roc_load::FunctionKind::LambdaSet, - roc_reporting::report::RenderTarget::Generic, - RocCacheDir::Persistent(cache::roc_cache_dir().as_path()), - roc_reporting::report::DEFAULT_PALETTE, - ); + let arena = Bump::new(); + let loaded = roc_load::load_and_typecheck_str( + &arena, + fi, + &doc_info.source, + src_dir, + roc_target::TargetInfo::default_x86_64(), + roc_load::FunctionKind::LambdaSet, + roc_reporting::report::RenderTarget::Generic, + RocCacheDir::Persistent(cache::roc_cache_dir().as_path()), + roc_reporting::report::DEFAULT_PALETTE, + ); - let module = match loaded { - Ok(module) => module, - Err(problem) => { - let all_problems = problem - .into_lsp_diagnostic(&()) - .into_iter() - .collect::>(); + let module = match loaded { + Ok(module) => module, + Err(problem) => { + let all_problems = problem + .into_lsp_diagnostic(&()) + .into_iter() + .collect::>(); - let analyzed_document = AnalyzedDocument { - doc_info, - analysis_result: AnalysisResult { - module: None, - diagnostics: all_problems, - }, - }; + let analyzed_document = AnalyzedDocument { + doc_info, + analysis_result: AnalysisResult { + module: None, + diagnostics: all_problems, + }, + }; - return vec![analyzed_document]; - } - }; - - let mut documents = vec![]; - - let LoadedModule { - interns, - mut can_problems, - mut type_problems, - mut declarations_by_id, - sources, - mut typechecked, - solved, - abilities_store, - .. - } = module; - - let mut root_module = Some(RootModule { - subs: solved.into_inner(), - abilities_store, - }); - - let mut builder = AnalyzedDocumentBuilder { - interns: &interns, - module_id_to_url: module_id_to_url_from_sources(&sources), - can_problems: &mut can_problems, - type_problems: &mut type_problems, - declarations_by_id: &mut declarations_by_id, - typechecked: &mut typechecked, - root_module: &mut root_module, - }; - - for (module_id, (path, source)) in sources { - documents.push(builder.build_document(path, source, module_id, version)); + return vec![analyzed_document]; } - - documents }; - (perform_analysis, doc_info_return) + + let mut documents = vec![]; + + let LoadedModule { + interns, + mut can_problems, + mut type_problems, + mut declarations_by_id, + sources, + mut typechecked, + solved, + abilities_store, + .. + } = module; + + let mut root_module = Some(RootModule { + subs: solved.into_inner(), + abilities_store, + }); + + let mut builder = AnalyzedDocumentBuilder { + interns: &interns, + module_id_to_url: module_id_to_url_from_sources(&sources), + can_problems: &mut can_problems, + type_problems: &mut type_problems, + declarations_by_id: &mut declarations_by_id, + typechecked: &mut typechecked, + root_module: &mut root_module, + }; + + for (module_id, (path, source)) in sources { + documents.push(builder.build_document(path, source, module_id, doc_info.version)); + } + + documents } fn find_src_dir(path: &Path) -> &Path { @@ -313,17 +298,26 @@ pub struct DocInfo { pub version: i32, } impl DocInfo { + pub fn new(url: Url, source: String, version: i32) -> Self { + Self { + url, + line_info: LineInfo::new(&source), + source, + version, + } + } + #[cfg(debug_assertions)] #[allow(unused)] fn debug_log_prefix(&self, offset: usize) { - debug!("prefix source{:?}", self.source); + debug!("prefix source: {:?}", self.source); let last_few = self.source.get(offset - 5..offset + 5).unwrap(); let (before, after) = last_few.split_at(5); debug!( - "starting to get completion items at offset:{:?} content:: '{:?}|{:?}'", + "starting to get completion items at offset: {:?} content: '{:?}|{:?}'", offset, before, after ); } diff --git a/crates/lang_srv/src/analysis/completion.rs b/crates/lang_srv/src/analysis/completion.rs index d8d7fb3972..f645fc47d5 100644 --- a/crates/lang_srv/src/analysis/completion.rs +++ b/crates/lang_srv/src/analysis/completion.rs @@ -342,7 +342,7 @@ fn find_record_fields(var: Variable, subs: &mut Subs) -> Vec<(String, Variable)> } _ => { - warn!("Trying to get field completion for a type that is not a record ",); + warn!("Trying to get field completion for a type that is not a record : {:?}", subs.dbg(typ)); vec![] } }, diff --git a/crates/lang_srv/src/server.rs b/crates/lang_srv/src/server.rs index fc57213e32..0d1466dc6e 100644 --- a/crates/lang_srv/src/server.rs +++ b/crates/lang_srv/src/server.rs @@ -8,7 +8,7 @@ use tower_lsp::jsonrpc::Result; use tower_lsp::lsp_types::*; use tower_lsp::{Client, LanguageServer, LspService, Server}; -use crate::analysis::global_analysis; +use crate::analysis::{global_analysis, DocInfo}; mod analysis; mod convert; @@ -132,10 +132,10 @@ impl Inner { //was write lock debug!("V{:?}:change acquired registry lock", version); - let (results, partial) = global_analysis(fi.clone(), text, version); + let doc_info = DocInfo::new(fi.clone(), text, version); self.registry - .apply_doc_info_changes(fi.clone(), partial.clone()) + .apply_doc_info_changes(fi.clone(), doc_info.clone()) .await; //Now that we've got our new partial document written and we hold the exclusive write_handle to its analysis we can allow other tasks to access the registry and the doc_info inside this partial document @@ -158,7 +158,7 @@ impl Inner { return Err("Not latest version skipping analysis".to_string()); } - let results = match tokio::task::spawn_blocking(results).await { + let results = match tokio::task::spawn_blocking(|| global_analysis(doc_info)).await { Err(e) => return Err(format!("Document analysis failed. reason:{:?}", e)), Ok(a) => a, };