diff --git a/crates/lsp/src/database.rs b/crates/lsp/src/database.rs index 45155ed..21be5a5 100644 --- a/crates/lsp/src/database.rs +++ b/crates/lsp/src/database.rs @@ -127,9 +127,12 @@ impl SemanticLocations { if let Some(locations) = self.0.get_mut(&token_id) { locations.push(range); } else { - self.0.insert(token_id, Vec::new()); + self.0.insert(token_id, vec![range]); } } + pub fn new() -> Self { + Self(HashMap::new()) + } } #[derive(Debug, Clone)] @@ -138,6 +141,17 @@ pub struct TemplateDataSemantic { pub variable: SemanticLocations, pub component: SemanticLocations, } + +impl TemplateDataSemantic { + fn new() -> Self { + Self { + signal: SemanticLocations::new(), + variable: SemanticLocations::new(), + component: SemanticLocations::new(), + } + } +} + #[derive(Debug, Clone)] pub struct SemanticData { pub template: SemanticLocations, @@ -173,24 +187,31 @@ impl SemanticDB { } pub fn insert(&mut self, file_id: FileId, semantic_info: SemanticInfo) { - if let Some(semantic) = self.semantic.get_mut(&file_id) { - match semantic_info { - SemanticInfo::Template((id, range)) => semantic.template.insert(id, range), - SemanticInfo::TemplateData((template_id, template_data_info)) => { - if let Some(template_semantic) = - semantic.template_data_semantic.get_mut(&template_id) - { - match template_data_info { - TemplateDataInfo::Component((id, r)) => { - template_semantic.component.insert(id, r) - } - TemplateDataInfo::Variable((id, r)) => { - template_semantic.variable.insert(id, r) - } - TemplateDataInfo::Signal((id, r)) => { - template_semantic.signal.insert(id, r) - } + let semantic = self.semantic.entry(file_id).or_insert(SemanticData { + template: SemanticLocations::new(), + template_data_semantic: HashMap::new(), + }); + + match semantic_info { + SemanticInfo::Template((id, range)) => { + semantic.template.insert(id, range); + } + SemanticInfo::TemplateData((template_id, template_data_info)) => { + let template_semantic = semantic + .template_data_semantic + .entry(template_id) + .or_insert(TemplateDataSemantic::new()); + if let Some(template_semantic) = + semantic.template_data_semantic.get_mut(&template_id) + { + match template_data_info { + TemplateDataInfo::Component((id, r)) => { + template_semantic.component.insert(id, r) } + TemplateDataInfo::Variable((id, r)) => { + template_semantic.variable.insert(id, r) + } + TemplateDataInfo::Signal((id, r)) => template_semantic.signal.insert(id, r), } } } @@ -268,7 +289,7 @@ impl SemanticDB { file_db.file_id, SemanticInfo::TemplateData(( template_id, - TemplateDataInfo::Signal(( + TemplateDataInfo::Variable(( name.syntax().token_id(), file_db.range(var.syntax()), )), @@ -279,7 +300,6 @@ impl SemanticDB { } } } - #[cfg(test)] mod tests { diff --git a/crates/lsp/src/global_state.rs b/crates/lsp/src/global_state.rs index d0a07d4..5f04f38 100644 --- a/crates/lsp/src/global_state.rs +++ b/crates/lsp/src/global_state.rs @@ -66,36 +66,27 @@ impl GlobalState { &self, root: &FileDB, ast: &AstCircomProgram, - semantic_data: &SemanticData, token: &SyntaxToken, ) -> Vec { - let mut result = lookup_definition(root, ast, semantic_data, token); + let semantic_data = self.db.semantic.get(&root.file_id).unwrap(); + let mut result = lookup_definition(root, ast, semantic_data, token); let p = root.get_path(); for lib in ast.libs() { let lib_abs_path = PathBuf::from(lib.lib().unwrap().value()); let lib_path = p.parent().unwrap().join(lib_abs_path).clone(); - let url = Url::from_file_path(lib_path.clone()).unwrap(); - if let Ok(src) = fs::read_to_string(lib_path) { - let text_doc = TextDocument { - text: src, - uri: url.clone(), - }; - - let file = &FileDB::create(&text_doc.text, url.clone()); - - let syntax = SyntaxTreeBuilder::syntax_tree(&text_doc.text); - - if let Some(lib_ast) = AstCircomProgram::cast(syntax) { - let lib_id = file.file_id; - let lib_semantic = self.db.semantic.get(&lib_id).unwrap(); - let ans = lookup_definition(file, &lib_ast, &lib_semantic, token); - result.extend(ans); - } - } - } + let lib_url = Url::from_file_path(lib_path.clone()).unwrap(); + let file_lib = self.file_map.get(&lib_url.to_string()).unwrap(); + let ast_lib = self.ast_map.get(&lib_url.to_string()).unwrap(); + + let semantic_data_lib = self.db.semantic.get(&file_lib.file_id).unwrap(); + + let lib_result = lookup_definition(&file_lib, &ast_lib, semantic_data_lib, token); + + result.extend(lib_result); + } result } pub fn goto_definition_handler(&self, id: RequestId, params: GotoDefinitionParams) -> Response { @@ -103,14 +94,12 @@ impl GlobalState { let ast = self.ast_map.get(&uri.to_string()).unwrap(); let file = self.file_map.get(&uri.to_string()).unwrap(); - eprintln!("goto {:?}", file.file_id); - eprintln!("{:?}", self.db.semantic); - let semantic_data = self.db.semantic.get(&file.file_id).unwrap(); + let mut locations = Vec::new(); if let Some(token) = lookup_token_at_postion(&file, &ast, params.text_document_position_params.position) { - locations = self.lookup_definition(&file, &ast, &semantic_data, &token); + locations = self.lookup_definition(&file, &ast, &token); }; let result: Option = Some(GotoDefinitionResponse::Array(locations)); @@ -132,12 +121,34 @@ impl GlobalState { let file_db = FileDB::create(text, text_document.uri.clone()); let file_id = file_db.file_id; - eprintln!("{}", AstCircomProgram::can_cast(TokenKind::CircomProgram)); + let p = file_db.get_path(); + if let Some(ast) = AstCircomProgram::cast(syntax) { - eprintln!("{}", url.to_string()); - eprintln!("{:?}", file_id); self.db.semantic.remove(&file_id); self.db.circom_program_semantic(&file_db, &ast); + + for lib in ast.libs() { + let lib_abs_path = PathBuf::from(lib.lib().unwrap().value()); + let lib_path = p.parent().unwrap().join(lib_abs_path).clone(); + let lib_url = Url::from_file_path(lib_path.clone()).unwrap(); + if let Ok(src) = fs::read_to_string(lib_path) { + let text_doc = TextDocument { + text: src, + uri: lib_url.clone(), + }; + + let lib_file = FileDB::create(&text_doc.text, lib_url.clone()); + let syntax = SyntaxTreeBuilder::syntax_tree(&text_doc.text); + + if let Some(lib_ast) = AstCircomProgram::cast(syntax) { + self.db.semantic.remove(&lib_file.file_id); + self.db.circom_program_semantic(&lib_file, &lib_ast); + self.ast_map.insert(lib_url.to_string(), lib_ast); + } + + self.file_map.insert(lib_url.to_string(), lib_file); + } + } self.ast_map.insert(url.to_string(), ast); } diff --git a/crates/lsp/src/handler/goto_definition.rs b/crates/lsp/src/handler/goto_definition.rs index 5f35a53..f44d976 100644 --- a/crates/lsp/src/handler/goto_definition.rs +++ b/crates/lsp/src/handler/goto_definition.rs @@ -61,8 +61,6 @@ pub fn lookup_definition( ) -> Vec { let template_list = ast.template_list(); - let file_id = file.file_id; - let mut res = Vec::new(); let mut signal_outside = false; if let Some(component_call) = lookup_node_wrap_token(TokenKind::ComponentCall, token) { @@ -82,15 +80,16 @@ pub fn lookup_definition( if let Some(other_template) = ast.get_template_by_name(&ast_template_name) { - eprintln!("{:?}", other_template); - eprintln!("{:?}", signal); let template_id = other_template.syntax().token_id(); if let Some(semantic) = semantic_data.template_data_semantic.get(&template_id) { - res.extend( - semantic.signal.0.get(&signal.syntax().token_id()).unwrap(), - ) + eprintln!("{} {:?}", signal.syntax().text(), signal.syntax().token_id()); + if let Some(tmp) = + semantic.signal.0.get(&signal.syntax().token_id()) + { + res.extend(tmp) + } } } }