Skip to content

Commit 89a518e

Browse files
committed
[IMP] server: references for xml that return all results without dependency check (only xml)
1 parent 086419c commit 89a518e

File tree

9 files changed

+174
-27
lines changed

9 files changed

+174
-27
lines changed

server/src/core/odoo.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use crate::core::symbols::file_symbol;
44
use crate::core::xml_data::XmlData;
55
use crate::core::xml_validation::XmlValidator;
66
use crate::features::document_symbols::DocumentSymbolFeature;
7+
use crate::features::references::ReferenceFeature;
78
use crate::threads::SessionInfo;
89
use crate::features::completion::CompletionFeature;
910
use crate::features::definition::DefinitionFeature;
@@ -1206,6 +1207,43 @@ impl Odoo {
12061207
Ok(None)
12071208
}
12081209

1210+
pub fn handle_references(session: &mut SessionInfo, params: ReferenceParams) -> Result<Option<Vec<Location>>, ResponseError> {
1211+
if session.sync_odoo.state_init == InitState::NOT_READY {
1212+
return Ok(None);
1213+
}
1214+
session.log_message(MessageType::INFO, format!("References requested on {} at {} - {}",
1215+
params.text_document_position.text_document.uri.to_string(),
1216+
params.text_document_position.position.line,
1217+
params.text_document_position.position.character));
1218+
let uri = params.text_document_position.text_document.uri.to_string();
1219+
let path = FileMgr::uri2pathname(uri.as_str());
1220+
if uri.ends_with(".py") || uri.ends_with(".pyi") || uri.ends_with(".xml") || uri.ends_with(".csv") {
1221+
if let Some(file_symbol) = SyncOdoo::get_symbol_of_opened_file(session, &PathBuf::from(path.clone())) {
1222+
let file_info = session.sync_odoo.get_file_mgr().borrow_mut().get_file_info(&path);
1223+
if let Some(file_info) = file_info {
1224+
if file_info.borrow().file_info_ast.borrow().ast.is_none() {
1225+
file_info.borrow_mut().prepare_ast(session);
1226+
}
1227+
let ast_type = file_info.borrow().file_info_ast.borrow().ast_type.clone();
1228+
match ast_type {
1229+
AstType::Python => {
1230+
if file_info.borrow_mut().file_info_ast.borrow().ast.is_some() {
1231+
return Ok(ReferenceFeature::get_references(session, &file_symbol, &file_info, params.text_document_position.position.line, params.text_document_position.position.character));
1232+
}
1233+
},
1234+
AstType::Xml => {
1235+
return Ok(ReferenceFeature::get_references_xml(session, &file_symbol, &file_info, params.text_document_position.position.line, params.text_document_position.position.character));
1236+
},
1237+
AstType::Csv => {
1238+
return Ok(ReferenceFeature::get_references_csv(session, &file_symbol, &file_info, params.text_document_position.position.line, params.text_document_position.position.character));
1239+
},
1240+
}
1241+
}
1242+
}
1243+
}
1244+
Ok(None)
1245+
}
1246+
12091247
pub fn handle_autocomplete(session: &mut SessionInfo ,params: CompletionParams) -> Result<Option<CompletionResponse>, ResponseError> {
12101248
if session.sync_odoo.state_init == InitState::NOT_READY {
12111249
return Ok(None);

server/src/features/definition.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ impl DefinitionFeature {
161161
let document = roxmltree::Document::parse(&data);
162162
if let Ok(document) = document {
163163
let root = document.root_element();
164-
let (symbols, _range) = XmlAstUtils::get_symbols(session, file_symbol, root, offset);
164+
let (symbols, _range) = XmlAstUtils::get_symbols(session, file_symbol, root, offset, true);
165165
if symbols.is_empty() {
166166
return None;
167167
}

server/src/features/hover.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ impl HoverFeature {
3737
let document = roxmltree::Document::parse(&data);
3838
if let Ok(document) = document {
3939
let root = document.root_element();
40-
let (symbols, range) = XmlAstUtils::get_symbols(session, file_symbol, root, offset);
40+
let (symbols, range) = XmlAstUtils::get_symbols(session, file_symbol, root, offset, true);
4141
let range = range.map(|r| (file_info.borrow().std_range_to_range(&r)));
4242
let evals = symbols.iter().filter(|s| matches!(s, XmlAstResult::SYMBOL(_)))
4343
.map(|s| Evaluation::eval_from_symbol(&Rc::downgrade(&s.as_symbol()), Some(false))).collect::<Vec<Evaluation>>();

server/src/features/mod.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1+
pub mod ast_utils;
12
pub mod completion;
23
pub mod definition;
34
pub mod document_symbols;
4-
pub mod hover;
5-
pub mod ast_utils;
65
pub mod features_utils;
6+
pub mod hover;
7+
pub mod references;
78
pub mod xml_ast_utils;

server/src/features/references.rs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
use std::{cell::RefCell, path::PathBuf, rc::Rc};
2+
3+
use lsp_server::ResponseError;
4+
use lsp_types::{Location, Range};
5+
6+
use crate::{constants::SymType, core::{file_mgr::{FileInfo, FileMgr}, symbols::{file_symbol::FileSymbol, symbol::Symbol}}, features::xml_ast_utils::{XmlAstResult, XmlAstUtils}, threads::SessionInfo, utils::PathSanitizer};
7+
8+
9+
10+
pub struct ReferenceFeature {
11+
12+
}
13+
14+
impl ReferenceFeature {
15+
pub fn get_references(session: &mut SessionInfo, file_symbol: &Rc<RefCell<Symbol>>, file_info: &Rc<RefCell<FileInfo>>, line: u32, character: u32) -> Option<Vec<Location>> {
16+
// Implementation for getting references
17+
None
18+
}
19+
20+
pub fn get_references_xml(session: &mut SessionInfo, file_symbol: &Rc<RefCell<Symbol>>, file_info: &Rc<RefCell<FileInfo>>, line: u32, character: u32) -> Option<Vec<Location>> {
21+
let offset = file_info.borrow().position_to_offset(line, character);
22+
let data = file_info.borrow().file_info_ast.borrow().text_rope.as_ref().unwrap().to_string();
23+
let document = roxmltree::Document::parse(&data);
24+
if let Ok(document) = document {
25+
let root = document.root_element();
26+
let (symbols, _range) = XmlAstUtils::get_symbols(session, file_symbol, root, offset, false);
27+
if symbols.is_empty() {
28+
return None;
29+
}
30+
let mut links = vec![];
31+
for xml_result in symbols.iter() {
32+
match xml_result {
33+
crate::features::xml_ast_utils::XmlAstResult::SYMBOL(s) => {
34+
if let Some(file) = s.borrow().get_file() {
35+
for path in file.upgrade().unwrap().borrow().paths().iter() {
36+
let full_path = match file.upgrade().unwrap().borrow().typ() {
37+
SymType::PACKAGE(_) => PathBuf::from(path).join(format!("__init__.py{}", file.upgrade().unwrap().borrow().as_package().i_ext())).sanitize(),
38+
_ => path.clone()
39+
};
40+
let range = match s.borrow().typ() {
41+
SymType::PACKAGE(_) | SymType::FILE | SymType::NAMESPACE | SymType::DISK_DIR => Range::default(),
42+
_ => session.sync_odoo.get_file_mgr().borrow().text_range_to_range(session, &full_path, &s.borrow().range()),
43+
};
44+
links.push(Location{uri: FileMgr::pathname2uri(&full_path), range});
45+
}
46+
}
47+
},
48+
XmlAstResult::XML_DATA(xml_file_symbol, range) => {
49+
for path in xml_file_symbol.borrow().paths().iter() {
50+
let full_path = match xml_file_symbol.borrow().typ() {
51+
SymType::PACKAGE(_) => PathBuf::from(path).join(format!("__init__.py{}", xml_file_symbol.borrow().as_package().i_ext())).sanitize(),
52+
_ => path.clone()
53+
};
54+
let range = match xml_file_symbol.borrow().typ() {
55+
SymType::PACKAGE(_) | SymType::FILE | SymType::NAMESPACE | SymType::DISK_DIR => Range::default(),
56+
_ => session.sync_odoo.get_file_mgr().borrow().std_range_to_range(session, &full_path, &range),
57+
};
58+
links.push(Location{uri: FileMgr::pathname2uri(&full_path), range: range});
59+
}
60+
}
61+
}
62+
}
63+
return Some(links);
64+
}
65+
None
66+
}
67+
68+
pub fn get_references_csv(session: &mut SessionInfo, file_symbol: &Rc<RefCell<Symbol>>, file_info: &Rc<RefCell<FileInfo>>, line: u32, character: u32) -> Option<Vec<Location>> {
69+
None
70+
}
71+
}

server/src/features/xml_ast_utils.rs

Lines changed: 46 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::{cell::RefCell, collections::HashMap, ops::Range, rc::Rc};
22

33
use roxmltree::Node;
44

5-
use crate::{constants::OYarn, core::{evaluation::ContextValue, symbols::symbol::Symbol, xml_data::XmlData}, threads::SessionInfo, Sy, S};
5+
use crate::{constants::OYarn, core::{evaluation::ContextValue, symbols::{module_symbol::ModuleSymbol, symbol::Symbol}, xml_data::XmlData}, threads::SessionInfo, Sy, S};
66

77
pub enum XmlAstResult {
88
SYMBOL(Rc<RefCell<Symbol>>),
@@ -29,61 +29,65 @@ pub struct XmlAstUtils {}
2929

3030
impl XmlAstUtils {
3131

32-
pub fn get_symbols(session: &mut SessionInfo, file_symbol: &Rc<RefCell<Symbol>>, root: roxmltree::Node, offset: usize) -> (Vec<XmlAstResult>, Option<Range<usize>>) {
32+
pub fn get_symbols(session: &mut SessionInfo, file_symbol: &Rc<RefCell<Symbol>>, root: roxmltree::Node, offset: usize, on_dep_only: bool) -> (Vec<XmlAstResult>, Option<Range<usize>>) {
3333
let mut results = (vec![], None);
3434
let from_module = file_symbol.borrow().find_module();
3535
let mut context_xml = HashMap::new();
3636
for node in root.children() {
37-
XmlAstUtils::visit_node(session, &node, offset, from_module.clone(), &mut context_xml, &mut results);
37+
XmlAstUtils::visit_node(session, &node, offset, from_module.clone(), &mut context_xml, &mut results, on_dep_only);
3838
}
3939
results
4040
}
4141

42-
fn visit_node(session: &mut SessionInfo<'_>, node: &Node, offset: usize, from_module: Option<Rc<RefCell<Symbol>>>, ctxt: &mut HashMap<String, ContextValue>, results: &mut (Vec<XmlAstResult>, Option<Range<usize>>)) {
42+
fn visit_node(session: &mut SessionInfo<'_>, node: &Node, offset: usize, from_module: Option<Rc<RefCell<Symbol>>>, ctxt: &mut HashMap<String, ContextValue>, results: &mut (Vec<XmlAstResult>, Option<Range<usize>>), on_dep_only: bool) {
4343
if node.is_element() {
4444
match node.tag_name().name() {
4545
"record" => {
46-
XmlAstUtils::visit_record(session, &node, offset, from_module.clone(), ctxt, results);
46+
XmlAstUtils::visit_record(session, &node, offset, from_module.clone(), ctxt, results, on_dep_only);
4747
}
4848
"field" => {
49-
XmlAstUtils::visit_field(session, &node, offset, from_module.clone(), ctxt, results);
49+
XmlAstUtils::visit_field(session, &node, offset, from_module.clone(), ctxt, results, on_dep_only);
5050
}
5151
_ => {
5252
for child in node.children() {
53-
XmlAstUtils::visit_node(session, &child, offset, from_module.clone(), ctxt, results);
53+
XmlAstUtils::visit_node(session, &child, offset, from_module.clone(), ctxt, results, on_dep_only);
5454
}
5555
}
5656
}
5757
} else if node.is_text() {
58-
XmlAstUtils::visit_text(session, &node, offset, from_module, ctxt, results);
58+
XmlAstUtils::visit_text(session, &node, offset, from_module, ctxt, results, on_dep_only);
5959
}
6060
}
6161

62-
fn visit_record(session: &mut SessionInfo<'_>, node: &Node, offset: usize, from_module: Option<Rc<RefCell<Symbol>>>, ctxt: &mut HashMap<String, ContextValue>, results: &mut (Vec<XmlAstResult>, Option<Range<usize>>)) {
62+
fn visit_record(session: &mut SessionInfo<'_>, node: &Node, offset: usize, from_module: Option<Rc<RefCell<Symbol>>>, ctxt: &mut HashMap<String, ContextValue>, results: &mut (Vec<XmlAstResult>, Option<Range<usize>>), on_dep_only: bool) {
6363
for attr in node.attributes() {
6464
if attr.name() == "model" {
6565
let model_name = attr.value().to_string();
6666
ctxt.insert(S!("record_model"), ContextValue::STRING(model_name.clone()));
6767
if attr.range_value().start <= offset && attr.range_value().end >= offset {
6868
if let Some(model) = session.sync_odoo.models.get(&Sy!(model_name)).cloned() {
69-
results.0.extend(model.borrow().all_symbols(session, from_module.clone(), false).iter().filter(|s| s.1.is_none()).map(|s| XmlAstResult::SYMBOL(s.0.clone())));
69+
let from_module = match on_dep_only {
70+
true => from_module.clone(),
71+
false => None,
72+
};
73+
results.0.extend(model.borrow().all_symbols(session, from_module, false).iter().filter(|s| s.1.is_none()).map(|s| XmlAstResult::SYMBOL(s.0.clone())));
7074
results.1 = Some(attr.range_value());
7175
}
7276
}
7377
} else if attr.name() == "id" {
7478
if attr.range_value().start <= offset && attr.range_value().end >= offset {
75-
XmlAstUtils::add_xml_id_result(session, attr.value(), &from_module.as_ref().unwrap(), attr.range_value(), results);
79+
XmlAstUtils::add_xml_id_result(session, attr.value(), &from_module.as_ref().unwrap(), attr.range_value(), results, on_dep_only);
7680
results.1 = Some(attr.range_value());
7781
}
7882
}
7983
}
8084
for child in node.children() {
81-
XmlAstUtils::visit_node(session, &child, offset, from_module.clone(), ctxt, results);
85+
XmlAstUtils::visit_node(session, &child, offset, from_module.clone(), ctxt, results, on_dep_only);
8286
}
8387
ctxt.remove(&S!("record_model"));
8488
}
8589

86-
fn visit_field(session: &mut SessionInfo<'_>, node: &Node, offset: usize, from_module: Option<Rc<RefCell<Symbol>>>, ctxt: &mut HashMap<String, ContextValue>, results: &mut (Vec<XmlAstResult>, Option<Range<usize>>)) {
90+
fn visit_field(session: &mut SessionInfo<'_>, node: &Node, offset: usize, from_module: Option<Rc<RefCell<Symbol>>>, ctxt: &mut HashMap<String, ContextValue>, results: &mut (Vec<XmlAstResult>, Option<Range<usize>>), on_dep_only: bool) {
8791
for attr in node.attributes() {
8892
if attr.name() == "name" {
8993
ctxt.insert(S!("field_name"), ContextValue::STRING(attr.value().to_string()));
@@ -93,7 +97,11 @@ impl XmlAstUtils {
9397
continue;
9498
}
9599
if let Some(model) = session.sync_odoo.models.get(&Sy!(model_name)).cloned() {
96-
for symbol in model.borrow().all_symbols(session, from_module.clone(), true) {
100+
let from_module = match on_dep_only {
101+
true => from_module.clone(),
102+
false => None,
103+
};
104+
for symbol in model.borrow().all_symbols(session, from_module, true) {
97105
if symbol.1.is_none() {
98106
let content = symbol.0.borrow().get_content_symbol(attr.value(), u32::MAX);
99107
for symbol in content.symbols.iter() {
@@ -113,19 +121,19 @@ impl XmlAstUtils {
113121
}
114122
}
115123
if field_name == "inherit_id" {
116-
XmlAstUtils::add_xml_id_result(session, attr.value(), &from_module.as_ref().unwrap(), attr.range_value(), results);
124+
XmlAstUtils::add_xml_id_result(session, attr.value(), &from_module.as_ref().unwrap(), attr.range_value(), results, on_dep_only);
117125
results.1 = Some(attr.range_value());
118126
}
119127
}
120128
}
121129
}
122130
for child in node.children() {
123-
XmlAstUtils::visit_node(session, &child, offset, from_module.clone(), ctxt, results);
131+
XmlAstUtils::visit_node(session, &child, offset, from_module.clone(), ctxt, results, on_dep_only);
124132
}
125133
ctxt.remove(&S!("field_name"));
126134
}
127135

128-
fn visit_text(session: &mut SessionInfo, node: &Node, offset: usize, from_module: Option<Rc<RefCell<Symbol>>>, ctxt: &mut HashMap<String, ContextValue>, results: &mut (Vec<XmlAstResult>, Option<Range<usize>>)) {
136+
fn visit_text(session: &mut SessionInfo, node: &Node, offset: usize, from_module: Option<Rc<RefCell<Symbol>>>, ctxt: &mut HashMap<String, ContextValue>, results: &mut (Vec<XmlAstResult>, Option<Range<usize>>), on_dep_only: bool) {
129137
if node.range().start <= offset && node.range().end >= offset {
130138
let model = ctxt.get(&S!("record_model")).cloned().unwrap_or(ContextValue::STRING(S!(""))).as_string();
131139
let field = ctxt.get(&S!("field_name")).cloned().unwrap_or(ContextValue::STRING(S!(""))).as_string();
@@ -135,16 +143,34 @@ impl XmlAstUtils {
135143
if model == "ir.ui.view" {
136144
if field == "model" {
137145
if let Some(model) = session.sync_odoo.models.get(node.text().unwrap()).cloned() {
138-
results.0.extend(model.borrow().all_symbols(session, from_module.clone(), false).iter().filter(|s| s.1.is_none()).map(|s| XmlAstResult::SYMBOL(s.0.clone())));
146+
let from_module = match on_dep_only {
147+
true => from_module.clone(),
148+
false => None,
149+
};
150+
results.0.extend(model.borrow().all_symbols(session, from_module, false).iter().filter(|s| s.1.is_none()).map(|s| XmlAstResult::SYMBOL(s.0.clone())));
139151
results.1 = Some(node.range());
140152
}
141153
}
142154
}
143155
}
144156
}
145157

146-
fn add_xml_id_result(session: &mut SessionInfo, xml_id: &str, file_symbol: &Rc<RefCell<Symbol>>, range: Range<usize>, results: &mut (Vec<XmlAstResult>, Option<Range<usize>>)) {
147-
let xml_ids = session.sync_odoo.get_xml_ids(file_symbol, xml_id, &range, &mut vec![]);
158+
fn add_xml_id_result(session: &mut SessionInfo, xml_id: &str, file_symbol: &Rc<RefCell<Symbol>>, range: Range<usize>, results: &mut (Vec<XmlAstResult>, Option<Range<usize>>), on_dep_only: bool) {
159+
let mut xml_ids = session.sync_odoo.get_xml_ids(file_symbol, xml_id, &range, &mut vec![]);
160+
if on_dep_only {
161+
xml_ids = xml_ids.into_iter().filter(|x|
162+
{
163+
let file = x.get_xml_file_symbol();
164+
if let Some(file) = file {
165+
let module = file.borrow().find_module();
166+
if let Some(module) = module {
167+
return ModuleSymbol::is_in_deps(session, &file_symbol.borrow().find_module().unwrap(), module.borrow().name());
168+
}
169+
}
170+
return false;
171+
}
172+
).collect::<Vec<_>>();
173+
}
148174
for xml_data in xml_ids.iter() {
149175
match xml_data {
150176
XmlData::RECORD(r) => {

0 commit comments

Comments
 (0)