Skip to content

Commit

Permalink
feat: hover for component props
Browse files Browse the repository at this point in the history
  • Loading branch information
Desdaemon committed May 18, 2024
1 parent d5cf8f6 commit ae5d491
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 6 deletions.
2 changes: 1 addition & 1 deletion src/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -522,7 +522,7 @@ impl Backend {
.and_then(|loc| self.index.module_of_path(&loc.path.to_path()));
let value = fomat!(
"```js\n"
"(component) class " (name) ";\n"
"(component) class " (name) "\n"
"```"
if let Some(module) = module {
"\n*Defined in:* `" (interner().resolve(&module)) "`"
Expand Down
2 changes: 1 addition & 1 deletion src/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ pub struct PropDescriptor {
}

bitflags::bitflags! {
#[derive(Default, Copy, Clone, Debug)]
#[derive(Default, Copy, Clone, Debug, PartialEq, Eq)]
pub struct PropType: u8 {
const Unknown = 0;
const Optional = 1 << 0;
Expand Down
55 changes: 51 additions & 4 deletions src/xml.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ use std::path::Path;
use std::sync::atomic::Ordering::Relaxed;
use std::sync::Arc;

use fomat_macros::fomat;
use lasso::Spur;
use log::{debug, warn};
use miette::diagnostic;
use odoo_lsp::component::ComponentTemplate;
use odoo_lsp::component::{ComponentTemplate, PropType};
use odoo_lsp::index::{interner, PathSymbol};
use odoo_lsp::model::{Field, FieldKind};
use odoo_lsp::template::gather_templates;
Expand Down Expand Up @@ -375,7 +376,12 @@ impl Backend {
Some(RefKind::TInherit) | Some(RefKind::TName) | Some(RefKind::TCall) => {
self.jump_def_template_name(needle)
}
Some(RefKind::PropOf(component)) => self.jump_def_component_prop(component, needle),
Some(RefKind::PropOf(component)) => {
if let Some((handler, _)) = needle.split_once('.') {
needle = handler;
}
self.jump_def_component_prop(component, needle)
}
Some(RefKind::Id) => self.jump_def_xml_id(needle, uri),
Some(RefKind::PyExpr(py_offset)) => {
let mut parser = Parser::new();
Expand Down Expand Up @@ -448,7 +454,7 @@ impl Backend {
return Ok(None);
};

let lsp_range = offset_range_to_lsp_range(
let mut lsp_range = offset_range_to_lsp_range(
ref_range.clone().map_unit(|unit| ByteOffset(unit + relative_offset)),
rope.clone(),
);
Expand Down Expand Up @@ -528,7 +534,48 @@ impl Backend {
offset_range_to_lsp_range(range.map_unit(|rel_unit| ByteOffset(rel_unit + anchor)), rope.clone()),
)
}
Some(RefKind::TName) | Some(RefKind::PropOf(..)) | Some(RefKind::Component) | None => {
Some(RefKind::Component) => Ok(self.hover_component(needle, lsp_range)),
Some(RefKind::PropOf(component_key)) => {
if let Some((handler, _)) = needle.split_once('.') {
// accept handler.bind syntax as well
if let Some(lsp_range) = lsp_range.as_mut() {
lsp_range.end.character = lsp_range.start.character + handler.len() as u32;
}
needle = handler;
}
let prop = some!(interner().get(needle));
let component = some!(interner().get(component_key));
let component = some!(self.index.components.get(&component.into()));
let field = some!(component.props.get(&prop.into()));
let type_descriptor = field.type_ & !(PropType::Optional | PropType::Array);
let needs_paren = field.type_.contains(PropType::Array) && type_descriptor.iter().count() > 1;
let contents = fomat! {
"(property) " (component_key) "." (needle)
if field.type_.contains(PropType::Optional) { "?" } ": "
if needs_paren { "(" }
for type_ in type_descriptor.iter() {
match type_ {
PropType::String => { "string" }
PropType::Number => { "number" }
PropType::Boolean => { "boolean" }
PropType::Object => { "object" }
PropType::Function => { "Function" }
_ => { "unknown" }
}
}
separated { " | " }
if needs_paren { ")" }
if field.type_.contains(PropType::Array) { "[]" }
};
Ok(Some(Hover {
range: lsp_range,
contents: HoverContents::Scalar(MarkedString::LanguageString(LanguageString {
language: "ts".to_string(),
value: contents,
})),
}))
}
Some(RefKind::TName) | None => {
#[cfg(not(debug_assertions))]
return Ok(None);

Expand Down

0 comments on commit ae5d491

Please sign in to comment.