Add hover/context APIs to wasm component

This commit is contained in:
Luke Street 2025-03-02 21:51:47 -07:00
parent 2eafbb218b
commit 48305e0380
2 changed files with 194 additions and 25 deletions

View File

@ -25,10 +25,11 @@ use exports::objdiff::core::{
GuestObjectDiff, Object, ObjectBorrow, ObjectDiff, ObjectDiffBorrow,
},
display::{
ContextMenuItem, DiffText, DiffTextColor, DiffTextOpcode, DiffTextSegment, DiffTextSymbol,
DisplayConfig, Guest as GuestDisplay, HoverItem, InstructionDiffKind, InstructionDiffRow,
SectionDisplay, SectionDisplaySymbol, SymbolDisplay, SymbolFilter, SymbolFlags, SymbolKind,
SymbolRef,
ContextItem, ContextItemCopy, ContextItemNavigate, DiffText, DiffTextColor, DiffTextOpcode,
DiffTextSegment, DiffTextSymbol, DisplayConfig, Guest as GuestDisplay, HoverItem,
HoverItemColor, HoverItemText, InstructionDiffKind, InstructionDiffRow, SectionDisplay,
SectionDisplaySymbol, SymbolDisplay, SymbolFilter, SymbolFlags, SymbolKind,
SymbolNavigationKind, SymbolRef,
},
};
@ -86,10 +87,6 @@ impl GuestDiff for Component {
}
impl GuestDisplay for Component {
fn symbol_context(_obj: ObjectBorrow, _symbol: SymbolRef) -> Vec<ContextMenuItem> { todo!() }
fn symbol_hover(_obj: ObjectBorrow, _symbol: SymbolRef) -> Vec<HoverItem> { todo!() }
fn display_sections(
diff: ObjectDiffBorrow,
filter: SymbolFilter,
@ -202,6 +199,102 @@ impl GuestDisplay for Component {
.unwrap();
InstructionDiffRow { segments, diff_kind: InstructionDiffKind::from(row.kind) }
}
fn symbol_context(
diff: ObjectDiffBorrow,
symbol_display: SectionDisplaySymbol,
) -> Vec<ContextItem> {
let obj_diff = diff.get::<ResourceObjectDiff>();
let obj = obj_diff.0.as_ref();
diff::display::symbol_context(obj, symbol_display.symbol as usize)
.into_iter()
.map(|item| ContextItem::from(item))
.collect()
}
fn symbol_hover(
diff: ObjectDiffBorrow,
symbol_display: SectionDisplaySymbol,
) -> Vec<HoverItem> {
let obj_diff = diff.get::<ResourceObjectDiff>();
let obj = obj_diff.0.as_ref();
diff::display::symbol_hover(obj, symbol_display.symbol as usize, 0 /* TODO */)
.into_iter()
.map(|item| HoverItem::from(item))
.collect()
}
fn instruction_context(
diff: ObjectDiffBorrow,
symbol_display: SectionDisplaySymbol,
row_index: u32,
diff_config: DiffConfigBorrow,
) -> Result<Vec<ContextItem>, String> {
let obj_diff = diff.get::<ResourceObjectDiff>();
let obj = obj_diff.0.as_ref();
let obj_diff = &obj_diff.1;
let symbol_idx = symbol_display.symbol as usize;
let symbol_diff = if symbol_display.is_mapping_symbol {
obj_diff
.mapping_symbols
.iter()
.find(|s| s.symbol_index == symbol_idx)
.map(|s| &s.symbol_diff)
.unwrap()
} else {
&obj_diff.symbols[symbol_idx]
};
let row = &symbol_diff.instruction_rows[row_index as usize];
let Some(ins_ref) = row.ins_ref else {
return Ok(Vec::new());
};
let diff_config = diff_config.get::<ResourceDiffConfig>().0.borrow();
let Some(resolved) = obj.resolve_instruction_ref(symbol_idx, ins_ref) else {
return Err("Failed to resolve instruction".into());
};
let ins =
obj.arch.process_instruction(resolved, &diff_config).map_err(|e| e.to_string())?;
Ok(diff::display::instruction_context(obj, resolved, &ins)
.into_iter()
.map(|item| ContextItem::from(item))
.collect())
}
fn instruction_hover(
diff: ObjectDiffBorrow,
symbol_display: SectionDisplaySymbol,
row_index: u32,
diff_config: DiffConfigBorrow,
) -> Result<Vec<HoverItem>, String> {
let obj_diff = diff.get::<ResourceObjectDiff>();
let obj = obj_diff.0.as_ref();
let obj_diff = &obj_diff.1;
let symbol_idx = symbol_display.symbol as usize;
let symbol_diff = if symbol_display.is_mapping_symbol {
obj_diff
.mapping_symbols
.iter()
.find(|s| s.symbol_index == symbol_idx)
.map(|s| &s.symbol_diff)
.unwrap()
} else {
&obj_diff.symbols[symbol_idx]
};
let row = &symbol_diff.instruction_rows[row_index as usize];
let Some(ins_ref) = row.ins_ref else {
return Ok(Vec::new());
};
let diff_config = diff_config.get::<ResourceDiffConfig>().0.borrow();
let Some(resolved) = obj.resolve_instruction_ref(symbol_idx, ins_ref) else {
return Err("Failed to resolve instruction".into());
};
let ins =
obj.arch.process_instruction(resolved, &diff_config).map_err(|e| e.to_string())?;
Ok(diff::display::instruction_hover(obj, resolved, &ins)
.into_iter()
.map(|item| HoverItem::from(item))
.collect())
}
}
impl From<obj::SymbolKind> for SymbolKind {
@ -342,4 +435,52 @@ impl GuestObjectDiff for ResourceObjectDiff {
}
}
impl From<diff::display::HoverItem> for HoverItem {
fn from(item: diff::display::HoverItem) -> Self {
match item {
diff::display::HoverItem::Text { label, value, color } => {
HoverItem::Text(HoverItemText { label, value, color: HoverItemColor::from(color) })
}
diff::display::HoverItem::Separator => HoverItem::Separator,
}
}
}
impl From<diff::display::HoverItemColor> for HoverItemColor {
fn from(color: diff::display::HoverItemColor) -> Self {
match color {
diff::display::HoverItemColor::Normal => HoverItemColor::Normal,
diff::display::HoverItemColor::Emphasized => HoverItemColor::Emphasized,
diff::display::HoverItemColor::Special => HoverItemColor::Special,
}
}
}
impl From<diff::display::ContextItem> for ContextItem {
fn from(item: diff::display::ContextItem) -> Self {
match item {
diff::display::ContextItem::Copy { value, label } => {
ContextItem::Copy(ContextItemCopy { value, label })
}
diff::display::ContextItem::Navigate { label, symbol_index, kind } => {
ContextItem::Navigate(ContextItemNavigate {
label,
symbol: symbol_index as SymbolRef,
kind: SymbolNavigationKind::from(kind),
})
}
diff::display::ContextItem::Separator => ContextItem::Separator,
}
}
}
impl From<diff::display::SymbolNavigationKind> for SymbolNavigationKind {
fn from(kind: diff::display::SymbolNavigationKind) -> Self {
match kind {
diff::display::SymbolNavigationKind::Normal => SymbolNavigationKind::Normal,
diff::display::SymbolNavigationKind::Extab => SymbolNavigationKind::Extab,
}
}
}
export!(Component);

View File

@ -108,18 +108,26 @@ interface display {
row-count: u32,
}
record context-menu-item-copy {
enum symbol-navigation-kind {
normal,
extab,
}
record context-item-copy {
value: string,
label: option<string>,
}
record context-menu-item-navigate {
record context-item-navigate {
label: string,
symbol: symbol-ref,
kind: symbol-navigation-kind,
}
variant context-menu-item {
copy(context-menu-item-copy),
navigate(context-menu-item-navigate),
variant context-item {
copy(context-item-copy),
navigate(context-item-navigate),
separator,
}
enum hover-item-color {
@ -128,11 +136,17 @@ interface display {
special,
}
record hover-item {
text: string,
record hover-item-text {
label: string,
value: string,
color: hover-item-color,
}
variant hover-item {
text(hover-item-text),
separator,
}
record diff-text-opcode {
mnemonic: string,
opcode: u16,
@ -216,22 +230,36 @@ interface display {
symbol: section-display-symbol,
) -> symbol-display;
symbol-context: func(
object: borrow<object>,
symbol: symbol-ref,
) -> list<context-menu-item>;
symbol-hover: func(
object: borrow<object>,
symbol: symbol-ref,
) -> list<hover-item>;
display-instruction-row: func(
diff: borrow<object-diff>,
symbol: section-display-symbol,
row-index: u32,
config: borrow<diff-config>,
) -> instruction-diff-row;
symbol-context: func(
diff: borrow<object-diff>,
symbol: section-display-symbol,
) -> list<context-item>;
symbol-hover: func(
diff: borrow<object-diff>,
symbol: section-display-symbol,
) -> list<hover-item>;
instruction-context: func(
diff: borrow<object-diff>,
symbol: section-display-symbol,
row-index: u32,
config: borrow<diff-config>,
) -> result<list<context-item>, string>;
instruction-hover: func(
diff: borrow<object-diff>,
symbol: section-display-symbol,
row-index: u32,
config: borrow<diff-config>,
) -> result<list<hover-item>, string>;
}
world api {