1//! This code was generated using Zed Agent with Claude Opus 4.
2
3// gate on rust-analyzer so rust-analyzer never needs to expand this macro, it takes up to 10 seconds to expand due to inefficiencies in rust-analyzers proc-macro srv
4#[cfg_attr(not(rust_analyzer), gpui_macros::derive_inspector_reflection)]
5trait Transform: Clone {
6 /// Doubles the value
7 fn double(self) -> Self;
8
9 /// Triples the value
10 fn triple(self) -> Self;
11
12 /// Increments the value by one
13 ///
14 /// This method has a default implementation
15 fn increment(self) -> Self {
16 // Default implementation
17 self.add_one()
18 }
19
20 /// Quadruples the value by doubling twice
21 fn quadruple(self) -> Self {
22 // Default implementation with mut self
23 self.double().double()
24 }
25
26 // These methods will be filtered out:
27 #[allow(dead_code)]
28 fn add(&self, other: &Self) -> Self;
29 #[allow(dead_code)]
30 fn set_value(&mut self, value: i32);
31 #[allow(dead_code)]
32 fn get_value(&self) -> i32;
33
34 /// Adds one to the value
35 fn add_one(self) -> Self;
36}
37
38#[derive(Debug, Clone, PartialEq)]
39struct Number(i32);
40
41impl Transform for Number {
42 fn double(self) -> Self {
43 Number(self.0 * 2)
44 }
45
46 fn triple(self) -> Self {
47 Number(self.0 * 3)
48 }
49
50 fn add(&self, other: &Self) -> Self {
51 Number(self.0 + other.0)
52 }
53
54 fn set_value(&mut self, value: i32) {
55 self.0 = value;
56 }
57
58 fn get_value(&self) -> i32 {
59 self.0
60 }
61
62 fn add_one(self) -> Self {
63 Number(self.0 + 1)
64 }
65}
66
67#[test]
68fn test_derive_inspector_reflection() {
69 use transform_reflection::*;
70
71 // Get all methods that match the pattern fn(self) -> Self or fn(mut self) -> Self
72 let methods = methods::<Number>();
73
74 assert_eq!(methods.len(), 5);
75 let method_names: Vec<_> = methods.iter().map(|m| m.name).collect();
76 assert!(method_names.contains(&"double"));
77 assert!(method_names.contains(&"triple"));
78 assert!(method_names.contains(&"increment"));
79 assert!(method_names.contains(&"quadruple"));
80 assert!(method_names.contains(&"add_one"));
81
82 // Invoke methods by name
83 let num = Number(5);
84
85 let doubled = find_method::<Number>("double").unwrap().invoke(num.clone());
86 assert_eq!(doubled, Number(10));
87
88 let tripled = find_method::<Number>("triple").unwrap().invoke(num.clone());
89 assert_eq!(tripled, Number(15));
90
91 let incremented = find_method::<Number>("increment")
92 .unwrap()
93 .invoke(num.clone());
94 assert_eq!(incremented, Number(6));
95
96 let quadrupled = find_method::<Number>("quadruple").unwrap().invoke(num);
97 assert_eq!(quadrupled, Number(20));
98
99 // Try to invoke a non-existent method
100 let result = find_method::<Number>("nonexistent");
101 assert!(result.is_none());
102
103 // Chain operations
104 let num = Number(10);
105 let result = find_method::<Number>("double")
106 .map(|m| m.invoke(num))
107 .and_then(|n| find_method::<Number>("increment").map(|m| m.invoke(n)))
108 .and_then(|n| find_method::<Number>("triple").map(|m| m.invoke(n)));
109
110 assert_eq!(result, Some(Number(63))); // (10 * 2 + 1) * 3 = 63
111
112 // Test documentationumentation capture
113 let double_method = find_method::<Number>("double").unwrap();
114 assert_eq!(double_method.documentation, Some("Doubles the value"));
115
116 let triple_method = find_method::<Number>("triple").unwrap();
117 assert_eq!(triple_method.documentation, Some("Triples the value"));
118
119 let increment_method = find_method::<Number>("increment").unwrap();
120 assert_eq!(
121 increment_method.documentation,
122 Some("Increments the value by one\n\nThis method has a default implementation")
123 );
124
125 let quadruple_method = find_method::<Number>("quadruple").unwrap();
126 assert_eq!(
127 quadruple_method.documentation,
128 Some("Quadruples the value by doubling twice")
129 );
130
131 let add_one_method = find_method::<Number>("add_one").unwrap();
132 assert_eq!(add_one_method.documentation, Some("Adds one to the value"));
133}