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/file.h"
9
10 #include <memory>
11 #include <string>
12 #include <vector>
13
14 #include "absl/strings/str_cat.h"
15 #include "google/protobuf/compiler/code_generator.h"
16 #include "google/protobuf/compiler/java/context.h"
17 #include "google/protobuf/compiler/java/helpers.h"
18 #include "google/protobuf/compiler/java/name_resolver.h"
19 #include "google/protobuf/compiler/java/names.h"
20 #include "google/protobuf/compiler/java/options.h"
21 #include "google/protobuf/compiler/kotlin/message.h"
22 #include "google/protobuf/descriptor.pb.h"
23 #include "google/protobuf/io/printer.h"
24
25 namespace google {
26 namespace protobuf {
27 namespace compiler {
28 namespace kotlin {
29
30 using google::protobuf::compiler::java::Context;
31 using google::protobuf::compiler::java::Options;
32
FileGenerator(const FileDescriptor * file,const Options & options)33 FileGenerator::FileGenerator(const FileDescriptor* file, const Options& options)
34 : file_(file),
35 java_package_(java::FileJavaPackage(file, options)),
36 message_generators_(file->message_type_count()),
37 context_(new Context(file, options)),
38 name_resolver_(context_->GetNameResolver()),
39 options_(options) {
40 for (int i = 0; i < file_->message_type_count(); ++i) {
41 message_generators_[i] = std::make_unique<MessageGenerator>(
42 file_->message_type(i), context_.get());
43 }
44 }
45
GetKotlinClassname()46 std::string FileGenerator::GetKotlinClassname() {
47 return absl::StrCat(name_resolver_->GetFileImmutableClassName(file_), "Kt");
48 }
49
Generate(io::Printer * printer)50 void FileGenerator::Generate(io::Printer* printer) {
51 printer->Print(
52 "// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
53 "// NO CHECKED-IN PROTOBUF "
54 // Intentional line breaker
55 "GENCODE\n"
56 "// source: $filename$\n"
57 "\n",
58 "filename", file_->name());
59 printer->Print(
60 "// Generated files should ignore deprecation warnings\n"
61 "@file:Suppress(\"DEPRECATION\")\n");
62 if (!java_package_.empty()) {
63 printer->Print(
64 "package $package$;\n"
65 "\n",
66 "package", java::EscapeKotlinKeywords(java_package_));
67 }
68 }
69
GenerateSiblings(const std::string & package_dir,GeneratorContext * context,std::vector<std::string> * file_list,std::vector<std::string> * annotation_list)70 void FileGenerator::GenerateSiblings(
71 const std::string& package_dir, GeneratorContext* context,
72 std::vector<std::string>* file_list,
73 std::vector<std::string>* annotation_list) {
74 for (int i = 0; i < file_->message_type_count(); i++) {
75 const Descriptor* descriptor = file_->message_type(i);
76 MessageGenerator* generator = message_generators_[i].get();
77 auto open_file = [context](const std::string& filename) {
78 return std::unique_ptr<io::ZeroCopyOutputStream>(context->Open(filename));
79 };
80 std::string filename =
81 absl::StrCat(package_dir, descriptor->name(), "Kt.kt");
82 file_list->push_back(filename);
83 std::string info_full_path = absl::StrCat(filename, ".pb.meta");
84 GeneratedCodeInfo annotations;
85 io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector(
86 &annotations);
87 auto output = open_file(filename);
88 io::Printer printer(
89 output.get(), '$',
90 options_.annotate_code ? &annotation_collector : nullptr);
91
92 printer.Print(
93 "// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
94 "// NO CHECKED-IN PROTOBUF "
95 // Intentional line breaker
96 "GENCODE\n"
97 "// source: $filename$\n"
98 "\n",
99 "filename", descriptor->file()->name());
100 printer.Print(
101 "// Generated files should ignore deprecation warnings\n"
102 "@file:Suppress(\"DEPRECATION\")\n");
103 if (!java_package_.empty()) {
104 printer.Print(
105 "package $package$;\n"
106 "\n",
107 "package", java::EscapeKotlinKeywords(java_package_));
108 }
109
110 generator->GenerateMembers(&printer);
111 generator->GenerateTopLevelMembers(&printer);
112
113 if (options_.annotate_code) {
114 auto info_output = open_file(info_full_path);
115 annotations.SerializeToZeroCopyStream(info_output.get());
116 annotation_list->push_back(info_full_path);
117 }
118 }
119 }
120
121 } // namespace kotlin
122 } // namespace compiler
123 } // namespace protobuf
124 } // namespace google
125