@@ -588,6 +588,28 @@ fn has_children(value: SEXP) -> bool {
588
588
}
589
589
}
590
590
591
+ fn has_viewer ( value : SEXP ) -> bool {
592
+ if !( r_is_data_frame ( value) || r_is_matrix ( value) ) {
593
+ return false ;
594
+ }
595
+
596
+ // We have a data.frame or matrix. Dispatch to the has_viewer method
597
+ match ArkGenerics :: VariableHasViewer . try_dispatch :: < bool > ( value, vec ! [ ] ) {
598
+ Err ( err) => {
599
+ log:: error!(
600
+ "Error from '{}' method: {err}" ,
601
+ ArkGenerics :: VariableHasViewer . to_string( )
602
+ ) ;
603
+ // The viewer method exists, but failed
604
+ false
605
+ } ,
606
+ // A matching viewer method was not found
607
+ Ok ( None ) => true ,
608
+ // The viewer method was found, use its result
609
+ Ok ( Some ( val) ) => val,
610
+ }
611
+ }
612
+
591
613
enum EnvironmentVariableNode {
592
614
Concrete { object : RObject } ,
593
615
R6Node { object : RObject , name : String } ,
@@ -653,7 +675,7 @@ impl PositronVariable {
653
675
size : 0 , // It's up to the caller to set the size.
654
676
has_children : has_children ( x) ,
655
677
is_truncated,
656
- has_viewer : r_is_data_frame ( x ) || r_is_matrix ( x) ,
678
+ has_viewer : has_viewer ( x) ,
657
679
updated_time : Self :: update_timestamp ( ) ,
658
680
} ,
659
681
}
@@ -1681,6 +1703,10 @@ mod tests {
1681
1703
"other"
1682
1704
})
1683
1705
1706
+ .ark.register_method("ark_positron_variable_has_viewer", "foo", function(x) {
1707
+ TRUE
1708
+ })
1709
+
1684
1710
.ark.register_method("ark_positron_variable_get_children", "foo", function(x) {
1685
1711
children <- list(
1686
1712
"hello" = list(a = 1, b = 2),
@@ -1741,6 +1767,10 @@ mod tests {
1741
1767
1742
1768
assert_eq ! ( variable. kind, VariableKind :: Other ) ;
1743
1769
1770
+ // Even though the viewer method returns TRUE, the object is not a data.frame
1771
+ // or matrix, so it doesn't have a viewer.
1772
+ assert_eq ! ( variable. has_viewer, false ) ;
1773
+
1744
1774
// Now inspect `x`
1745
1775
let path = vec ! [ String :: from( "x" ) ] ;
1746
1776
let variables = PositronVariable :: inspect ( env. clone ( ) , & path) . unwrap ( ) ;
@@ -1766,6 +1796,7 @@ mod tests {
1766
1796
.ark.unregister_method("ark_positron_variable_display_value", "foo")
1767
1797
.ark.unregister_method("ark_positron_variable_display_type", "foo")
1768
1798
.ark.unregister_method("ark_positron_variable_has_children", "foo")
1799
+ .ark.unregister_method("ark_positron_variable_has_viewer", "foo")
1769
1800
.ark.unregister_method("ark_positron_variable_kind", "foo")
1770
1801
.ark.unregister_method("ark_positron_variable_get_children", "foo")
1771
1802
.ark.unregister_method("ark_positron_variable_get_child_at", "foo")
@@ -1775,6 +1806,52 @@ mod tests {
1775
1806
} )
1776
1807
}
1777
1808
1809
+ #[ test]
1810
+ fn test_has_viewer_data_frame_subclass ( ) {
1811
+ r_task ( || {
1812
+ // Create an object with that class in an env.
1813
+ let env = harp:: parse_eval_base (
1814
+ r#"
1815
+ local({
1816
+ env <- new.env(parent = emptyenv())
1817
+ env$x <- structure(data.frame(x = 1, y = 2), class = c("foo", "data.frame"))
1818
+ env
1819
+ })
1820
+ "# ,
1821
+ )
1822
+ . unwrap ( ) ;
1823
+
1824
+ let has_viewer = || {
1825
+ let path = vec ! [ ] ;
1826
+ let variables = PositronVariable :: inspect ( env. clone ( ) , & path) . unwrap ( ) ;
1827
+
1828
+ assert_eq ! ( variables. len( ) , 1 ) ;
1829
+ let variable = variables[ 0 ] . clone ( ) ;
1830
+ variable. has_viewer
1831
+ } ;
1832
+
1833
+ assert ! ( has_viewer( ) ) ;
1834
+
1835
+ harp:: parse_eval_global (
1836
+ r#"
1837
+ .ark.register_method("ark_positron_variable_has_viewer", "foo", function(x) {
1838
+ FALSE
1839
+ })
1840
+ "# ,
1841
+ )
1842
+ . unwrap ( ) ;
1843
+
1844
+ assert ! ( !has_viewer( ) ) ;
1845
+
1846
+ harp:: parse_eval_global (
1847
+ r#"
1848
+ .ark.unregister_method("ark_positron_variable_has_viewer", "foo")
1849
+ "# ,
1850
+ )
1851
+ . unwrap ( ) ;
1852
+ } )
1853
+ }
1854
+
1778
1855
#[ test]
1779
1856
fn test_inspect_r6 ( ) {
1780
1857
r_task ( || {
0 commit comments