@@ -601,6 +601,8 @@ def __lt__(self, other):
601
601
'If this argument is specified, an update Javadoc references file ' +
602
602
'will be saved to the given location. It is OK if this file does not ' +
603
603
'exist.' )
604
+ _CMDLINE_PARSER .add_argument ('--unused-classes-to-generate' , default = None , help = 'Specify types ' +
605
+ 'that we want to generate regardless of whether they are used.' )
604
606
605
607
class JavaCodeGenerator (CodeGenerator ):
606
608
cmdline_parser = _CMDLINE_PARSER
@@ -2033,6 +2035,9 @@ def update_serializer_visibility(self, data_type_fq_name, visibility):
2033
2035
self ._serializer_visibility [data_type ], visibility
2034
2036
)
2035
2037
2038
+ def mark_data_type_as_used (self , data_type ):
2039
+ self ._client_data_types .add (data_type )
2040
+
2036
2041
2037
2042
class JavaReferences (object ):
2038
2043
@@ -2372,6 +2377,9 @@ def generate_all(self):
2372
2377
2373
2378
self .generate_client ()
2374
2379
2380
+ # some classes are unused, but we still want them to be generated
2381
+ self ._mark_special_unused_classes ()
2382
+
2375
2383
for namespace in self .api .namespaces .values ():
2376
2384
self .generate_namespace (namespace )
2377
2385
@@ -2467,6 +2475,55 @@ def generate_namespace(self, namespace):
2467
2475
if namespace .routes :
2468
2476
self .generate_namespace_routes (namespace )
2469
2477
2478
+ def _mark_special_unused_classes (self ):
2479
+ j = self .j
2480
+
2481
+ if not self .g .args .unused_classes_to_generate :
2482
+ return
2483
+
2484
+ special_class_names = self .g .args .unused_classes_to_generate .split (', ' )
2485
+
2486
+ if not special_class_names :
2487
+ return
2488
+
2489
+ special_data_types = [
2490
+ unwrap_nullable (data_type )[0 ]
2491
+ for namespace in j .stone_api .namespaces .values ()
2492
+ for data_type in namespace .data_types
2493
+ if data_type .name in special_class_names
2494
+ ]
2495
+
2496
+ all_special_data_types = set ()
2497
+
2498
+ # mark all special types public and used, and likewise mark all of their
2499
+ # referenced types as public and used
2500
+
2501
+ def _propagate_changes (data_type ):
2502
+ all_special_data_types .add (data_type )
2503
+
2504
+ if is_void_type (data_type ) or not is_user_defined_type (data_type ):
2505
+ return
2506
+
2507
+ field_types = [unwrap_nullable (f .data_type )[0 ] for f in data_type .all_fields ]
2508
+ for field_type in field_types :
2509
+ if field_type not in all_special_data_types :
2510
+ _propagate_changes (field_type )
2511
+ if data_type .parent_type :
2512
+ if data_type .parent_type not in all_special_data_types :
2513
+ _propagate_changes (data_type .parent_type )
2514
+
2515
+ for data_type in special_data_types :
2516
+ _propagate_changes (data_type )
2517
+
2518
+ for data_type in all_special_data_types :
2519
+ if is_user_defined_type (data_type ) and not is_void_type (data_type ):
2520
+ data_type_fq_name = j .stone_fq_name (data_type )
2521
+
2522
+ # mark public
2523
+ j .update_data_type_visibility (data_type_fq_name , Visibility .PUBLIC )
2524
+ # mark as being referenced somewhere so that we generate
2525
+ j .mark_data_type_as_used (data_type )
2526
+
2470
2527
def generate_namespace_routes (self , namespace ):
2471
2528
assert isinstance (namespace , ApiNamespace ), repr (namespace )
2472
2529
@@ -2866,7 +2923,7 @@ def generate_data_type(self, data_type):
2866
2923
2867
2924
j = self .j
2868
2925
2869
- if not ( self .g .args .data_types_only or j .is_used_by_client (data_type ) ):
2926
+ if not self .g .args .data_types_only and not j .is_used_by_client (data_type ):
2870
2927
return
2871
2928
2872
2929
with self .class_writer (data_type ) as w :
0 commit comments