@@ -298,6 +298,55 @@ std::string PluginName(absl::string_view plugin_prefix,
298
298
directive.substr (2 , directive.size () - 6 ));
299
299
}
300
300
301
+
302
+ // Get all transitive dependencies of the given file (including the file
303
+ // itself), adding them to the given list of FileDescriptorProtos. The
304
+ // protos will be ordered such that every file is listed before any file that
305
+ // depends on it, so that you can call DescriptorPool::BuildFile() on them
306
+ // in order. Any files in *already_seen will not be added, and each file
307
+ // added will be inserted into *already_seen. If include_source_code_info is
308
+ // true then include the source code information in the FileDescriptorProtos.
309
+ // If include_json_name is true, populate the json_name field of
310
+ // FieldDescriptorProto for all fields.
311
+ struct TransitiveDependencyOptions {
312
+ bool include_json_name = false ;
313
+ bool include_source_code_info = false ;
314
+ bool retain_options = false ;
315
+ };
316
+
317
+ void GetTransitiveDependencies (
318
+ const FileDescriptor* file,
319
+ absl::flat_hash_set<const FileDescriptor*>* already_seen,
320
+ RepeatedPtrField<FileDescriptorProto>* output,
321
+ const TransitiveDependencyOptions& options =
322
+ TransitiveDependencyOptions ()) {
323
+ if (!already_seen->insert (file).second ) {
324
+ // Already saw this file. Skip.
325
+ return ;
326
+ }
327
+
328
+ // Add all dependencies.
329
+ for (int i = 0 ; i < file->dependency_count (); i++) {
330
+ GetTransitiveDependencies (file->dependency (i), already_seen, output,
331
+ options);
332
+ }
333
+
334
+ // Add this file.
335
+ FileDescriptorProto* new_descriptor = output->Add ();
336
+ if (options.retain_options ) {
337
+ file->CopyTo (new_descriptor);
338
+ if (options.include_source_code_info ) {
339
+ file->CopySourceCodeInfoTo (new_descriptor);
340
+ }
341
+ } else {
342
+ *new_descriptor =
343
+ StripSourceRetentionOptions (*file, options.include_source_code_info );
344
+ }
345
+ if (options.include_json_name ) {
346
+ file->CopyJsonNameTo (new_descriptor);
347
+ }
348
+ }
349
+
301
350
} // namespace
302
351
303
352
// A MultiFileErrorCollector that prints errors to stderr.
@@ -1454,6 +1503,7 @@ void CommandLineInterface::Clear() {
1454
1503
print_mode_ = PRINT_NONE;
1455
1504
imports_in_descriptor_set_ = false ;
1456
1505
source_info_in_descriptor_set_ = false ;
1506
+ retain_options_in_descriptor_set_ = false ;
1457
1507
disallow_services_ = false ;
1458
1508
direct_dependencies_explicitly_set_ = false ;
1459
1509
deterministic_output_ = false ;
@@ -1709,6 +1759,11 @@ CommandLineInterface::ParseArgumentStatus CommandLineInterface::ParseArguments(
1709
1759
" --descriptor_set_out."
1710
1760
<< std::endl;
1711
1761
}
1762
+ if (retain_options_in_descriptor_set_ && descriptor_set_out_name_.empty ()) {
1763
+ std::cerr << " --retain_options only makes sense when combined with "
1764
+ " --descriptor_set_out."
1765
+ << std::endl;
1766
+ }
1712
1767
1713
1768
return PARSE_ARGUMENT_DONE_AND_CONTINUE;
1714
1769
}
@@ -1759,7 +1814,8 @@ bool CommandLineInterface::ParseArgument(const char* arg, std::string* name,
1759
1814
1760
1815
if (*name == " -h" || *name == " --help" || *name == " --disallow_services" ||
1761
1816
*name == " --include_imports" || *name == " --include_source_info" ||
1762
- *name == " --version" || *name == " --decode_raw" ||
1817
+ *name == " --retain_options" || *name == " --version" ||
1818
+ *name == " --decode_raw" ||
1763
1819
*name == " --print_free_field_numbers" ||
1764
1820
*name == " --experimental_allow_proto3_optional" ||
1765
1821
*name == " --deterministic_output" || *name == " --fatal_warnings" ) {
@@ -1954,6 +2010,13 @@ CommandLineInterface::InterpretArgument(const std::string& name,
1954
2010
}
1955
2011
source_info_in_descriptor_set_ = true ;
1956
2012
2013
+ } else if (name == " --retain_options" ) {
2014
+ if (retain_options_in_descriptor_set_) {
2015
+ std::cerr << name << " may only be passed once." << std::endl;
2016
+ return PARSE_ARGUMENT_FAIL;
2017
+ }
2018
+ retain_options_in_descriptor_set_ = true ;
2019
+
1957
2020
} else if (name == " -h" || name == " --help" ) {
1958
2021
PrintHelpText ();
1959
2022
return PARSE_ARGUMENT_DONE_AND_EXIT; // Exit without running compiler.
@@ -2190,6 +2253,11 @@ Parse PROTO_FILES and generate output based on the options given:
2190
2253
include information about the original
2191
2254
location of each decl in the source file as
2192
2255
well as surrounding comments.
2256
+ --retain_options When using --descriptor_set_out, do not strip
2257
+ any options from the FileDescriptorProto.
2258
+ This results in potentially larger descriptors
2259
+ that include information about options that were
2260
+ only meant to be useful during compilation.
2193
2261
--dependency_out=FILE Write a dependency output file in the format
2194
2262
expected by make. This writes the transitive
2195
2263
set of input file paths to FILE
@@ -2328,7 +2396,7 @@ bool CommandLineInterface::GenerateDependencyManifestFile(
2328
2396
2329
2397
absl::flat_hash_set<const FileDescriptor*> already_seen;
2330
2398
for (int i = 0 ; i < parsed_files.size (); i++) {
2331
- GetTransitiveDependencies (parsed_files[i], false , false , &already_seen,
2399
+ GetTransitiveDependencies (parsed_files[i], &already_seen,
2332
2400
file_set.mutable_file ());
2333
2401
}
2334
2402
@@ -2410,10 +2478,11 @@ bool CommandLineInterface::GeneratePluginOutput(
2410
2478
absl::flat_hash_set<const FileDescriptor*> already_seen;
2411
2479
for (int i = 0 ; i < parsed_files.size (); i++) {
2412
2480
request.add_file_to_generate (parsed_files[i]->name ());
2413
- GetTransitiveDependencies (parsed_files[i],
2414
- true , // Include json_name for plugins.
2415
- true , // Include source code info.
2416
- &already_seen, request.mutable_proto_file ());
2481
+ GetTransitiveDependencies (parsed_files[i], &already_seen,
2482
+ request.mutable_proto_file (),
2483
+ {/* .include_json_name =*/ true ,
2484
+ /* .include_source_code_info =*/ true ,
2485
+ /* .retain_options =*/ true });
2417
2486
}
2418
2487
2419
2488
google::protobuf::compiler::Version* version =
@@ -2575,11 +2644,13 @@ bool CommandLineInterface::WriteDescriptorSet(
2575
2644
}
2576
2645
}
2577
2646
}
2647
+ TransitiveDependencyOptions options;
2648
+ options.include_json_name = true ;
2649
+ options.include_source_code_info = source_info_in_descriptor_set_;
2650
+ options.retain_options = retain_options_in_descriptor_set_;
2578
2651
for (int i = 0 ; i < parsed_files.size (); i++) {
2579
- GetTransitiveDependencies (parsed_files[i],
2580
- true , // Include json_name
2581
- source_info_in_descriptor_set_, &already_seen,
2582
- file_set.mutable_file ());
2652
+ GetTransitiveDependencies (parsed_files[i], &already_seen,
2653
+ file_set.mutable_file (), options);
2583
2654
}
2584
2655
2585
2656
int fd;
@@ -2617,31 +2688,6 @@ bool CommandLineInterface::WriteDescriptorSet(
2617
2688
return true ;
2618
2689
}
2619
2690
2620
- void CommandLineInterface::GetTransitiveDependencies (
2621
- const FileDescriptor* file, bool include_json_name,
2622
- bool include_source_code_info,
2623
- absl::flat_hash_set<const FileDescriptor*>* already_seen,
2624
- RepeatedPtrField<FileDescriptorProto>* output) {
2625
- if (!already_seen->insert (file).second ) {
2626
- // Already saw this file. Skip.
2627
- return ;
2628
- }
2629
-
2630
- // Add all dependencies.
2631
- for (int i = 0 ; i < file->dependency_count (); i++) {
2632
- GetTransitiveDependencies (file->dependency (i), include_json_name,
2633
- include_source_code_info, already_seen, output);
2634
- }
2635
-
2636
- // Add this file.
2637
- FileDescriptorProto* new_descriptor = output->Add ();
2638
- *new_descriptor =
2639
- StripSourceRetentionOptions (*file, include_source_code_info);
2640
- if (include_json_name) {
2641
- file->CopyJsonNameTo (new_descriptor);
2642
- }
2643
- }
2644
-
2645
2691
const CommandLineInterface::GeneratorInfo*
2646
2692
CommandLineInterface::FindGeneratorByFlag (const std::string& name) const {
2647
2693
auto it = generators_by_flag_name_.find (name);
0 commit comments