Skip to content

Commit ae5d491

Browse files
committed
feat: hover for component props
1 parent d5cf8f6 commit ae5d491

File tree

3 files changed

+53
-6
lines changed

3 files changed

+53
-6
lines changed

src/backend.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -522,7 +522,7 @@ impl Backend {
522522
.and_then(|loc| self.index.module_of_path(&loc.path.to_path()));
523523
let value = fomat!(
524524
"```js\n"
525-
"(component) class " (name) ";\n"
525+
"(component) class " (name) "\n"
526526
"```"
527527
if let Some(module) = module {
528528
"\n*Defined in:* `" (interner().resolve(&module)) "`"

src/component.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ pub struct PropDescriptor {
4747
}
4848

4949
bitflags::bitflags! {
50-
#[derive(Default, Copy, Clone, Debug)]
50+
#[derive(Default, Copy, Clone, Debug, PartialEq, Eq)]
5151
pub struct PropType: u8 {
5252
const Unknown = 0;
5353
const Optional = 1 << 0;

src/xml.rs

Lines changed: 51 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@ use std::path::Path;
77
use std::sync::atomic::Ordering::Relaxed;
88
use std::sync::Arc;
99

10+
use fomat_macros::fomat;
1011
use lasso::Spur;
1112
use log::{debug, warn};
1213
use miette::diagnostic;
13-
use odoo_lsp::component::ComponentTemplate;
14+
use odoo_lsp::component::{ComponentTemplate, PropType};
1415
use odoo_lsp::index::{interner, PathSymbol};
1516
use odoo_lsp::model::{Field, FieldKind};
1617
use odoo_lsp::template::gather_templates;
@@ -375,7 +376,12 @@ impl Backend {
375376
Some(RefKind::TInherit) | Some(RefKind::TName) | Some(RefKind::TCall) => {
376377
self.jump_def_template_name(needle)
377378
}
378-
Some(RefKind::PropOf(component)) => self.jump_def_component_prop(component, needle),
379+
Some(RefKind::PropOf(component)) => {
380+
if let Some((handler, _)) = needle.split_once('.') {
381+
needle = handler;
382+
}
383+
self.jump_def_component_prop(component, needle)
384+
}
379385
Some(RefKind::Id) => self.jump_def_xml_id(needle, uri),
380386
Some(RefKind::PyExpr(py_offset)) => {
381387
let mut parser = Parser::new();
@@ -448,7 +454,7 @@ impl Backend {
448454
return Ok(None);
449455
};
450456

451-
let lsp_range = offset_range_to_lsp_range(
457+
let mut lsp_range = offset_range_to_lsp_range(
452458
ref_range.clone().map_unit(|unit| ByteOffset(unit + relative_offset)),
453459
rope.clone(),
454460
);
@@ -528,7 +534,48 @@ impl Backend {
528534
offset_range_to_lsp_range(range.map_unit(|rel_unit| ByteOffset(rel_unit + anchor)), rope.clone()),
529535
)
530536
}
531-
Some(RefKind::TName) | Some(RefKind::PropOf(..)) | Some(RefKind::Component) | None => {
537+
Some(RefKind::Component) => Ok(self.hover_component(needle, lsp_range)),
538+
Some(RefKind::PropOf(component_key)) => {
539+
if let Some((handler, _)) = needle.split_once('.') {
540+
// accept handler.bind syntax as well
541+
if let Some(lsp_range) = lsp_range.as_mut() {
542+
lsp_range.end.character = lsp_range.start.character + handler.len() as u32;
543+
}
544+
needle = handler;
545+
}
546+
let prop = some!(interner().get(needle));
547+
let component = some!(interner().get(component_key));
548+
let component = some!(self.index.components.get(&component.into()));
549+
let field = some!(component.props.get(&prop.into()));
550+
let type_descriptor = field.type_ & !(PropType::Optional | PropType::Array);
551+
let needs_paren = field.type_.contains(PropType::Array) && type_descriptor.iter().count() > 1;
552+
let contents = fomat! {
553+
"(property) " (component_key) "." (needle)
554+
if field.type_.contains(PropType::Optional) { "?" } ": "
555+
if needs_paren { "(" }
556+
for type_ in type_descriptor.iter() {
557+
match type_ {
558+
PropType::String => { "string" }
559+
PropType::Number => { "number" }
560+
PropType::Boolean => { "boolean" }
561+
PropType::Object => { "object" }
562+
PropType::Function => { "Function" }
563+
_ => { "unknown" }
564+
}
565+
}
566+
separated { " | " }
567+
if needs_paren { ")" }
568+
if field.type_.contains(PropType::Array) { "[]" }
569+
};
570+
Ok(Some(Hover {
571+
range: lsp_range,
572+
contents: HoverContents::Scalar(MarkedString::LanguageString(LanguageString {
573+
language: "ts".to_string(),
574+
value: contents,
575+
})),
576+
}))
577+
}
578+
Some(RefKind::TName) | None => {
532579
#[cfg(not(debug_assertions))]
533580
return Ok(None);
534581

0 commit comments

Comments
 (0)