@@ -10,6 +10,7 @@ use crate::generator::{docs, functions_common};
10
10
use crate :: models:: domain:: {
11
11
ApiView , Class , ClassLike , ClassMethod , FnQualifier , Function , TyName ,
12
12
} ;
13
+ use crate :: special_cases;
13
14
use crate :: util:: ident;
14
15
use proc_macro2:: { Ident , TokenStream } ;
15
16
use quote:: quote;
@@ -150,7 +151,10 @@ fn make_special_virtual_methods(notification_enum_name: &Ident) -> TokenStream {
150
151
}
151
152
}
152
153
153
- fn make_virtual_method ( method : & ClassMethod ) -> Option < TokenStream > {
154
+ fn make_virtual_method (
155
+ method : & ClassMethod ,
156
+ override_is_required : Option < bool > ,
157
+ ) -> Option < TokenStream > {
154
158
if !method. is_virtual ( ) {
155
159
return None ;
156
160
}
@@ -166,7 +170,8 @@ fn make_virtual_method(method: &ClassMethod) -> Option<TokenStream> {
166
170
// make_return() requests following args, but they are not used for virtual methods. We can provide empty streams.
167
171
varcall_invocation : TokenStream :: new ( ) ,
168
172
ptrcall_invocation : TokenStream :: new ( ) ,
169
- is_virtual_required : method. is_virtual_required ( ) ,
173
+ is_virtual_required : override_is_required
174
+ . unwrap_or_else ( || method. is_virtual_required ( ) ) ,
170
175
is_varcall_fallible : true ,
171
176
} ,
172
177
None ,
@@ -186,15 +191,20 @@ fn make_all_virtual_methods(
186
191
187
192
for method in class. methods . iter ( ) {
188
193
// Assumes that inner function filters on is_virtual.
189
- if let Some ( tokens) = make_virtual_method ( method) {
194
+ if let Some ( tokens) = make_virtual_method ( method, None ) {
190
195
all_tokens. push ( tokens) ;
191
196
}
192
197
}
193
198
194
199
for base_name in all_base_names {
195
200
let base_class = view. get_engine_class ( base_name) ;
196
201
for method in base_class. methods . iter ( ) {
197
- if let Some ( tokens) = make_virtual_method ( method) {
202
+ // Certain derived classes in Godot implement a virtual method declared in a base class, thus no longer
203
+ // making it required. This isn't advertised in the extension_api, but instead manually tracked via special cases.
204
+ let is_required =
205
+ special_cases:: is_derived_virtual_method_required ( class. name ( ) , method. name ( ) ) ;
206
+
207
+ if let Some ( tokens) = make_virtual_method ( method, is_required) {
198
208
all_tokens. push ( tokens) ;
199
209
}
200
210
}
0 commit comments