• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7 
8 #include "google/protobuf/compiler/kotlin/generator.h"
9 
10 #include <cstdint>
11 #include <memory>
12 #include <string>
13 #include <utility>
14 #include <vector>
15 
16 #include "absl/strings/str_cat.h"
17 #include "google/protobuf/compiler/code_generator.h"
18 #include "google/protobuf/compiler/java/helpers.h"
19 #include "google/protobuf/compiler/java/options.h"
20 #include "google/protobuf/compiler/kotlin/file.h"
21 #include "google/protobuf/io/printer.h"
22 
23 namespace google {
24 namespace protobuf {
25 namespace compiler {
26 namespace kotlin {
27 
28 using google::protobuf::compiler::java::Options;
29 
KotlinGenerator()30 KotlinGenerator::KotlinGenerator() {}
~KotlinGenerator()31 KotlinGenerator::~KotlinGenerator() {}
32 
GetSupportedFeatures() const33 uint64_t KotlinGenerator::GetSupportedFeatures() const {
34   return CodeGenerator::Feature::FEATURE_PROTO3_OPTIONAL |
35          CodeGenerator::Feature::FEATURE_SUPPORTS_EDITIONS;
36 }
37 
Generate(const FileDescriptor * file,const std::string & parameter,GeneratorContext * context,std::string * error) const38 bool KotlinGenerator::Generate(const FileDescriptor* file,
39                                const std::string& parameter,
40                                GeneratorContext* context,
41                                std::string* error) const {
42   // -----------------------------------------------------------------
43   // parse generator options
44 
45   std::vector<std::pair<std::string, std::string> > options;
46   ParseGeneratorParameter(parameter, &options);
47   Options file_options;
48 
49   for (auto& option : options) {
50     if (option.first == "output_list_file") {
51       file_options.output_list_file = option.second;
52     } else if (option.first == "immutable") {
53       // Note: the option is considered always set regardless of the input.
54       file_options.generate_immutable_code = true;
55     } else if (option.first == "mutable") {
56       *error = "Mutable not supported by Kotlin generator";
57       return false;
58     } else if (option.first == "shared") {
59       // Note: the option is considered always set regardless of the input.
60       file_options.generate_shared_code = true;
61     } else if (option.first == "lite") {
62       file_options.enforce_lite = true;
63     } else if (option.first == "annotate_code") {
64       file_options.annotate_code = true;
65     } else if (option.first == "annotation_list_file") {
66       file_options.annotation_list_file = option.second;
67     } else if (option.first == "experimental_strip_nonfunctional_codegen") {
68       file_options.strip_nonfunctional_codegen = true;
69     } else if (option.first == "no_jvm_dsl") {
70       file_options.jvm_dsl = false;
71     } else {
72       *error = absl::StrCat("Unknown generator option: ", option.first);
73       return false;
74     }
75   }
76 
77   // We only support generation of immutable code so we do it.
78   file_options.generate_immutable_code = true;
79   file_options.generate_shared_code = true;
80 
81   std::vector<std::string> all_files;
82   std::vector<std::string> all_annotations;
83 
84   std::unique_ptr<FileGenerator> file_generator(
85       new FileGenerator(file, file_options));
86 
87   if (!file_generator) return false;
88 
89   auto open_file = [context](const std::string& filename) {
90     return std::unique_ptr<io::ZeroCopyOutputStream>(context->Open(filename));
91   };
92   std::string package_dir =
93       java::JavaPackageToDir(file_generator->java_package());
94   std::string kotlin_filename = absl::StrCat(
95       package_dir, file_generator->GetKotlinClassname(), ".proto.kt");
96   all_files.push_back(kotlin_filename);
97   std::string info_full_path = absl::StrCat(kotlin_filename, ".pb.meta");
98   if (file_options.annotate_code) {
99     all_annotations.push_back(info_full_path);
100   }
101 
102   // Generate main kotlin file.
103   auto output = open_file(kotlin_filename);
104   GeneratedCodeInfo annotations;
105   io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector(
106       &annotations);
107   io::Printer printer(
108       output.get(), '$',
109       file_options.annotate_code ? &annotation_collector : nullptr);
110 
111   file_generator->Generate(&printer);
112   file_generator->GenerateSiblings(package_dir, context, &all_files,
113                                    &all_annotations);
114 
115   if (file_options.annotate_code) {
116     auto info_output = open_file(info_full_path);
117     annotations.SerializeToZeroCopyStream(info_output.get());
118   }
119 
120   // Generate output list if requested.
121   if (!file_options.output_list_file.empty()) {
122     // Generate output list.  This is just a simple text file placed in a
123     // deterministic location which lists the .kt files being generated.
124     auto srclist_raw_output = open_file(file_options.output_list_file);
125     io::Printer srclist_printer(srclist_raw_output.get(), '$');
126     for (auto& all_file : all_files) {
127       srclist_printer.Print("$filename$\n", "filename", all_file);
128     }
129   }
130 
131   if (!file_options.annotation_list_file.empty()) {
132     // Generate output list.  This is just a simple text file placed in a
133     // deterministic location which lists the .kt files being generated.
134     auto annotation_list_raw_output =
135         open_file(file_options.annotation_list_file);
136     io::Printer annotation_list_printer(annotation_list_raw_output.get(), '$');
137     for (auto& all_annotation : all_annotations) {
138       annotation_list_printer.Print("$filename$\n", "filename", all_annotation);
139     }
140   }
141 
142   return true;
143 }
144 
145 }  // namespace kotlin
146 }  // namespace compiler
147 }  // namespace protobuf
148 }  // namespace google
149