Added draft of proto compiler. Currently only barebones of Kotlin-class generated - builders are not suported yet
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
CXX = g++
|
||||
CXXFLAGS = -O2 -std=c++11
|
||||
LDFLAGS = -lprotoc -lprotobuf
|
||||
|
||||
EXE = protoc
|
||||
SRCDIR = src
|
||||
BINDIR = bin
|
||||
|
||||
OBJECTS = $(patsubst $(SRCDIR)/%.cc,$(BINDIR)/%.o,$(wildcard $(SRCDIR)/*.cc))
|
||||
|
||||
all: $(EXE)
|
||||
|
||||
$(EXE): $(BINDIR) $(OBJECTS)
|
||||
$(CXX) $(OBJECTS) -o $(EXE) $(LDFLAGS)
|
||||
|
||||
$(BINDIR)/%.o: $(SRCDIR)/%.cc
|
||||
$(CXX) $(CXXFLAGS) -c -MMD -o $@ $< -lprotoc
|
||||
|
||||
include $(wildcard $(BINDIR)/*.d)
|
||||
|
||||
$(BINDIR):
|
||||
mkdir -p $(BINDIR)
|
||||
|
||||
clean:
|
||||
rm -rf $(BINDIR) $(EXE)
|
||||
|
||||
generate:
|
||||
./protoc --kotlin_out=./ ./test/addressbook.proto
|
||||
.PHONY: clean all generate
|
||||
@@ -0,0 +1,22 @@
|
||||
//
|
||||
// Created by user on 7/12/16.
|
||||
//
|
||||
|
||||
#include "kotlin_builder_generator.h"
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace kotlin {
|
||||
|
||||
BuilderGenerator::BuilderGenerator(const google::protobuf::Descriptor * descriptor) {
|
||||
|
||||
}
|
||||
|
||||
} // namespace kotlin
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
//
|
||||
// Created by user on 7/12/16.
|
||||
//
|
||||
|
||||
#ifndef PROTOBUF_KOTLIN_BUILDER_GENERATOR_H
|
||||
#define PROTOBUF_KOTLIN_BUILDER_GENERATOR_H
|
||||
|
||||
#include <google/protobuf/io/printer.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace kotlin {
|
||||
|
||||
}
|
||||
class BuilderGenerator {
|
||||
public:
|
||||
string simpleName;
|
||||
vector <
|
||||
|
||||
BuilderGenerator(Descriptor const * descriptor);
|
||||
~BuilderGenerator();
|
||||
void generateCode(io::Printer * printer);
|
||||
};
|
||||
|
||||
} // namespace kotlin
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
|
||||
#endif //PROTOBUF_KOTLIN_BUILDER_GENERATOR_H
|
||||
@@ -0,0 +1,175 @@
|
||||
//
|
||||
// Created by user on 7/11/16.
|
||||
//
|
||||
|
||||
#include "kotlin_class_generator.h"
|
||||
#include <iostream>
|
||||
#include "kotlin_enum_generator.h"
|
||||
#include "kotlin_field_generator.h"
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace kotlin {
|
||||
|
||||
void ClassGenerator::generateCode(io::Printer *printer, bool isBuilder) const {
|
||||
// print class header
|
||||
map<string, string> vars;
|
||||
vars["modifier"] = modifier.getName();
|
||||
vars["name"] = (isBuilder? "Builder" : "") + simpleName;
|
||||
printer->Print(vars,
|
||||
"$modifier$ $name$ private constructor () {"
|
||||
"\n"
|
||||
);
|
||||
printer->Indent();
|
||||
|
||||
// generate code for nested classes declarations
|
||||
for (ClassGenerator *gen: classesDeclarations) {
|
||||
gen->generateCode(printer, isBuilder);
|
||||
printer->Print("\n\n"); // separate each definition from next code block with empty line
|
||||
}
|
||||
|
||||
// generate code for nested enums declarations
|
||||
for (EnumGenerator *gen: enumsDeclaraions) {
|
||||
gen->generateCode(printer);
|
||||
printer->Print("\n\n"); // separate each definitions from next code block with empty line
|
||||
}
|
||||
|
||||
// generate code for fields
|
||||
for (FieldGenerator *gen: properties) {
|
||||
gen->generateCode(printer);
|
||||
printer->Print("\n");
|
||||
}
|
||||
|
||||
// generate constructor for builders
|
||||
if (isBuilder) {
|
||||
printer->Print("\n");
|
||||
generateConstructor(printer);
|
||||
}
|
||||
|
||||
// generate builder for fair classes
|
||||
if (!isBuilder) {
|
||||
printer->Print("\n");
|
||||
generateBuilder(printer);
|
||||
}
|
||||
|
||||
printer->Outdent();
|
||||
printer->Print("}");
|
||||
}
|
||||
|
||||
ClassGenerator::ClassGenerator(Descriptor const *descriptor) {
|
||||
simpleName = descriptor->name(); // TODO: think about more careful class naming
|
||||
modifier = ClassModifier(ClassModifier::CLASS);
|
||||
|
||||
int field_count = descriptor->field_count();
|
||||
for (int i = 0; i < field_count; ++i) {
|
||||
FieldDescriptor const * fieldDescriptor = descriptor->field(i);
|
||||
properties.push_back(new FieldGenerator(fieldDescriptor));
|
||||
}
|
||||
|
||||
int nested_types_count = descriptor->nested_type_count();
|
||||
for (int i = 0; i < nested_types_count; ++i) {
|
||||
Descriptor const * nestedClassDescriptor = descriptor->nested_type(i);
|
||||
classesDeclarations.push_back(new ClassGenerator(nestedClassDescriptor));
|
||||
}
|
||||
|
||||
int enums_declarations_count = descriptor->enum_type_count();
|
||||
for (int i = 0; i < enums_declarations_count; ++i) {
|
||||
EnumDescriptor const * nestedEnumDescriptor = descriptor->enum_type(i);
|
||||
enumsDeclaraions.push_back(new EnumGenerator(nestedEnumDescriptor));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
ClassGenerator::~ClassGenerator() {
|
||||
for (int i = 0; i < properties.size(); ++i) {
|
||||
delete properties[i];
|
||||
}
|
||||
|
||||
for (int i = 0; i < classesDeclarations.size(); ++i) {
|
||||
delete classesDeclarations[i];
|
||||
}
|
||||
|
||||
for (int i = 0; i < enumsDeclaraions.size(); ++i) {
|
||||
delete enumsDeclaraions[i];
|
||||
}
|
||||
}
|
||||
|
||||
void ClassGenerator::generateBuilder(io::Printer *) const {
|
||||
|
||||
}
|
||||
|
||||
void ClassGenerator::generateConstructor(io::Printer *printer, bool isBuilder) const {
|
||||
// generate header
|
||||
printer->Print("private constructor(\n");
|
||||
|
||||
// place each argument of constructor in separate line for a prettier code
|
||||
// we indent twice to make arguments indentation larger than indentation of inner block
|
||||
printer->Indent();
|
||||
printer->Indent();
|
||||
for (int i = 0; i < properties.size(); ++i) {
|
||||
// generate argument definition
|
||||
map<string, string> vars;
|
||||
vars["name"] = properties[i] ->simpleName;
|
||||
vars["field"] = properties[i]->fieldName;
|
||||
printer->Print(vars,
|
||||
"$name$: $field$");
|
||||
|
||||
// if it's last property, then print closing bracket for argument list, otherwise put comma
|
||||
if (i + 1 == properties.size()) {
|
||||
printer->Print(") : this()\n");
|
||||
printer->Outdent();
|
||||
printer->Outdent();
|
||||
printer->Print("{");
|
||||
printer->Indent();
|
||||
}
|
||||
else {
|
||||
printer->Print(",");
|
||||
}
|
||||
|
||||
printer->Print("\n");
|
||||
}
|
||||
|
||||
// print body of constructor - just assign arguments to corresponding fields
|
||||
for (int i = 0; i < properties.size(); ++i) {
|
||||
map <string, string> vars;
|
||||
vars["name"] = properties[i]->simpleName;
|
||||
printer->Print(vars,
|
||||
"this.$name$ = $name$"
|
||||
"\n"
|
||||
);
|
||||
}
|
||||
printer->Outdent();
|
||||
printer->Print("}");
|
||||
}
|
||||
|
||||
|
||||
const string ClassModifier::getName() const {
|
||||
string result = "";
|
||||
switch (type) {
|
||||
case CLASS:
|
||||
result = "class";
|
||||
break;
|
||||
case INTERFACE:
|
||||
result = "interface";
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ClassModifier::ClassModifier(ClassModifier::Type type)
|
||||
: type(type)
|
||||
{ }
|
||||
|
||||
ClassModifier::ClassModifier() {
|
||||
type = CLASS;
|
||||
}
|
||||
|
||||
|
||||
} // namespace kotlin
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
//
|
||||
// Created by user on 7/11/16.
|
||||
//
|
||||
|
||||
#ifndef SRC_KOTLIN_CLASS_GENERATOR_H
|
||||
#define SRC_KOTLIN_CLASS_GENERATOR_H
|
||||
|
||||
#include <vector>
|
||||
#include <google/protobuf/io/printer.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include "kotlin_field_generator.h"
|
||||
#include "kotlin_enum_generator.h"
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace kotlin {
|
||||
|
||||
// wrapper for enum CLASS/INTERFACE with convenience method of getting name
|
||||
class ClassModifier {
|
||||
public:
|
||||
enum Type {
|
||||
CLASS,
|
||||
INTERFACE
|
||||
};
|
||||
ClassModifier();
|
||||
ClassModifier(Type type);
|
||||
Type type;
|
||||
|
||||
string const getName() const;
|
||||
};
|
||||
|
||||
class ClassGenerator {
|
||||
public:
|
||||
ClassModifier modifier;
|
||||
string simpleName;
|
||||
vector <FieldGenerator *> properties;
|
||||
vector <ClassGenerator *> classesDeclarations;
|
||||
vector <EnumGenerator *> enumsDeclaraions;
|
||||
|
||||
ClassGenerator (Descriptor const * descriptor);
|
||||
~ClassGenerator ();
|
||||
|
||||
/**
|
||||
* Flag isBuilder used for reducing code repeating, as code for class itself
|
||||
* and for its inner builder are structurally very alike and can be generated
|
||||
* with very little differences (like changing 'val's to 'var's and etc.)
|
||||
*/
|
||||
void generateCode (io::Printer * printer, bool isBuilder = false) const;
|
||||
private:
|
||||
void generateBuilder (io::Printer * printer) const;
|
||||
void generateConstructor(io::Printer * printer, bool isBuilder = false) const;
|
||||
};
|
||||
|
||||
} // namespace kotlin
|
||||
} // namspace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
#endif //SRC_KOTLIN_CLASS_GENERATOR_H
|
||||
@@ -0,0 +1,73 @@
|
||||
//
|
||||
// Created by user on 7/12/16.
|
||||
//
|
||||
|
||||
#include "kotlin_enum_generator.h"
|
||||
#include <iostream>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace kotlin {
|
||||
|
||||
|
||||
EnumValueGenerator::EnumValueGenerator(EnumValueDescriptor const *descriptor) {
|
||||
simpleName = descriptor->name();
|
||||
ordinal = descriptor->number();
|
||||
}
|
||||
|
||||
void EnumValueGenerator::generateCode(io::Printer * printer) const {
|
||||
map <string, string> vars;
|
||||
vars["name"] = simpleName;
|
||||
vars["ordinal"] = std::to_string(ordinal);
|
||||
printer->Print(vars,
|
||||
"$name$ ($ordinal$)"
|
||||
);
|
||||
}
|
||||
|
||||
void EnumGenerator::generateCode(io::Printer * printer) const {
|
||||
/**
|
||||
* Generate enum class header.
|
||||
* Note that according to protobuf encoding, wire stores enum fields as ints,
|
||||
* and client is responsible for proper casting those ints to actual enum values.
|
||||
* Therefore, we have to add int-constructor in generated Kotlin-enum, and assign
|
||||
* ordinals for each enum-value properly.
|
||||
*/
|
||||
map <string, string> vars;
|
||||
vars["name"] = simpleName;
|
||||
printer->Print(vars,
|
||||
"enum class $name$(val ord: Int) {"
|
||||
"\n"
|
||||
);
|
||||
printer->Indent();
|
||||
|
||||
// Generate enum values.
|
||||
for (int i = 0; i < enumValues.size(); ++i) {
|
||||
enumValues[i]->generateCode(printer);
|
||||
if (i + 1 != enumValues.size()) {
|
||||
printer->Print(",");
|
||||
}
|
||||
printer->Print("\n");
|
||||
}
|
||||
printer->Outdent();
|
||||
printer->Print("}");
|
||||
}
|
||||
|
||||
EnumGenerator::~EnumGenerator() {
|
||||
for (int i = 0; i < enumValues.size(); ++i) {
|
||||
delete enumValues[i];
|
||||
}
|
||||
}
|
||||
|
||||
EnumGenerator::EnumGenerator(EnumDescriptor const *descriptor) {
|
||||
simpleName = descriptor->name();
|
||||
int values_count = descriptor->value_count();
|
||||
for (int i = 0; i < values_count; ++i) {
|
||||
enumValues.push_back(new EnumValueGenerator(descriptor->value(i)));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace kotlin
|
||||
} // namspace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
@@ -0,0 +1,42 @@
|
||||
//
|
||||
// Created by user on 7/12/16.
|
||||
//
|
||||
|
||||
#ifndef PROTOBUF_KOTLIN_ENUM_GENERATOR_H
|
||||
#define PROTOBUF_KOTLIN_ENUM_GENERATOR_H
|
||||
|
||||
#include <google/protobuf/io/printer.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace kotlin {
|
||||
|
||||
class EnumValueGenerator {
|
||||
public:
|
||||
EnumValueGenerator(EnumValueDescriptor const * descriptor);
|
||||
string simpleName;
|
||||
int ordinal;
|
||||
|
||||
void generateCode(io::Printer *) const;
|
||||
};
|
||||
|
||||
class EnumGenerator {
|
||||
public:
|
||||
EnumGenerator(EnumDescriptor const * descriptor);
|
||||
~EnumGenerator();
|
||||
string simpleName;
|
||||
vector <EnumValueGenerator *> enumValues;
|
||||
|
||||
void generateCode(io::Printer *) const;
|
||||
};
|
||||
|
||||
} // namespace kotlin
|
||||
} // namspace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
|
||||
#endif //PROTOBUF_KOTLIN_ENUM_GENERATOR_H
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
//
|
||||
// Created by user on 7/12/16.
|
||||
//
|
||||
|
||||
#include "kotlin_field_generator.h"
|
||||
#include <vector>
|
||||
#include <google/protobuf/io/printer.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <iostream>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace kotlin {
|
||||
|
||||
/**
|
||||
* Gets equivalent Kotlin-type for a given field descriptor.
|
||||
* This method takes protobuf field type into account, adding 'List<>'
|
||||
* for repeated fields, and '?' for optional.
|
||||
*/
|
||||
string FieldGenerator::protobufToKotlinField() const {
|
||||
string preamble = "",
|
||||
postamble = "";
|
||||
switch (modifier) {
|
||||
case FieldDescriptor::LABEL_REQUIRED:
|
||||
break;
|
||||
case FieldDescriptor::LABEL_OPTIONAL:
|
||||
postamble = "?";
|
||||
break;
|
||||
case FieldDescriptor::LABEL_REPEATED:
|
||||
preamble = "List <";
|
||||
postamble = "> ";
|
||||
break;
|
||||
}
|
||||
return preamble + protobufToKotlinType() + postamble;
|
||||
}
|
||||
/**
|
||||
* Simply maps protobuf field type to corresponding Kotlin.
|
||||
*/
|
||||
string FieldGenerator::protobufToKotlinType() const {
|
||||
FieldDescriptor::Type type = descriptor->type();
|
||||
switch(type) {
|
||||
case FieldDescriptor::TYPE_BOOL:
|
||||
return "Boolean";
|
||||
case FieldDescriptor::TYPE_BYTES:
|
||||
return ""; // TODO: support bytes type
|
||||
case FieldDescriptor::TYPE_DOUBLE:
|
||||
return "Double";
|
||||
case FieldDescriptor::TYPE_ENUM:
|
||||
return string(descriptor->enum_type()->name());
|
||||
case FieldDescriptor::TYPE_FIXED32:
|
||||
// we map uint32 into Int, storing top bit in sign bit
|
||||
return "Int";
|
||||
case FieldDescriptor::TYPE_FIXED64:
|
||||
// we map uint64 into Long, storing top bit in sign bit
|
||||
return "Long";
|
||||
case FieldDescriptor::TYPE_FLOAT:
|
||||
return "Float";
|
||||
case FieldDescriptor::TYPE_GROUP:
|
||||
return ""; // @deprecated //TODO: make proper error handling there
|
||||
case FieldDescriptor::TYPE_INT32:
|
||||
return "Int";
|
||||
case FieldDescriptor::TYPE_INT64:
|
||||
return "Long";
|
||||
case FieldDescriptor::TYPE_MESSAGE:
|
||||
return string(descriptor->message_type()->name());
|
||||
case FieldDescriptor::TYPE_SFIXED32:
|
||||
return "Int";
|
||||
case FieldDescriptor::TYPE_SFIXED64:
|
||||
return "Long";
|
||||
case FieldDescriptor::TYPE_SINT32:
|
||||
return "Int";
|
||||
case FieldDescriptor::TYPE_SINT64:
|
||||
return "Long";
|
||||
case FieldDescriptor::TYPE_STRING:
|
||||
return "kotlin.String";
|
||||
case FieldDescriptor::TYPE_UINT32:
|
||||
return "Int"; // see notes for TYPE_FIXED32
|
||||
case FieldDescriptor::TYPE_UINT64:
|
||||
return "Long"; // see notes for TYPE_FIXED64
|
||||
}
|
||||
}
|
||||
|
||||
string FieldGenerator::getInitValue() const {
|
||||
if (descriptor->is_optional()) {
|
||||
return "null";
|
||||
}
|
||||
if (descriptor->is_repeated())
|
||||
return "listOf()";
|
||||
return fieldName + "()";
|
||||
}
|
||||
|
||||
void FieldGenerator::generateCode(io::Printer *printer) const {
|
||||
/** Generate Kotlin-code for field.
|
||||
* Note that we use 'val' everywhere, as we want messages to be immutable.
|
||||
* For constructing Messages corresponding Builders should be used.
|
||||
*/
|
||||
map<string, string> vars;
|
||||
vars["name"] = simpleName;
|
||||
vars["field"] = protobufToKotlinField();
|
||||
vars["initValue"] = initValue;
|
||||
printer->Print(vars, "val $name$ : $field$ = $initValue$");
|
||||
}
|
||||
|
||||
FieldGenerator::FieldGenerator(FieldDescriptor const * descriptor)
|
||||
: descriptor(descriptor)
|
||||
, modifier(descriptor->label())
|
||||
, simpleName(descriptor->name())
|
||||
, fieldName(protobufToKotlinField())
|
||||
, initValue(getInitValue())
|
||||
{ }
|
||||
|
||||
} // namespace kotlin
|
||||
} // namspace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
@@ -0,0 +1,40 @@
|
||||
//
|
||||
// Created by user on 7/12/16.
|
||||
//
|
||||
|
||||
#ifndef PROTOBUF_KOTLIN_FIELD_GENERATOR_H
|
||||
#define PROTOBUF_KOTLIN_FIELD_GENERATOR_H
|
||||
|
||||
#include <vector>
|
||||
#include <google/protobuf/io/printer.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace kotlin {
|
||||
|
||||
class FieldGenerator {
|
||||
private:
|
||||
FieldDescriptor const * descriptor;
|
||||
string protobufToKotlinField() const;
|
||||
string protobufToKotlinType () const;
|
||||
string getInitValue() const;
|
||||
|
||||
public:
|
||||
FieldDescriptor::Label modifier;
|
||||
string simpleName;
|
||||
string fieldName;
|
||||
string initValue;
|
||||
|
||||
void generateCode(io::Printer *) const;
|
||||
FieldGenerator(FieldDescriptor const * descriptor);
|
||||
|
||||
};
|
||||
|
||||
} // namespace kotlin
|
||||
} // namspace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif //PROTOBUF_KOTLIN_FIELD_GENERATOR_H
|
||||
@@ -0,0 +1,65 @@
|
||||
//
|
||||
// Created by user on 7/11/16.
|
||||
//
|
||||
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/stubs/shared_ptr.h>
|
||||
#include <google/protobuf/io/zero_copy_stream.h>
|
||||
#ifndef _SHARED_PTR_H
|
||||
#include <google/protobuf/stubs/shared_ptr.h>
|
||||
#endif
|
||||
#include "kotlin_file_generator.h"
|
||||
#include <iostream>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace kotlin {
|
||||
|
||||
void FileGenerator::generateCode(io::Printer *printer, std::vector<ClassGenerator *> & classes) const {
|
||||
for (int i = 0; i < classes.size(); ++i) {
|
||||
classes[i]->generateCode(printer);
|
||||
printer->Print("\n\n");
|
||||
}
|
||||
}
|
||||
|
||||
bool FileGenerator::Generate(const FileDescriptor *file, const string ¶meter, GeneratorContext *context,
|
||||
string *error) const {
|
||||
std::vector<ClassGenerator *> classes;
|
||||
|
||||
//TODO: maybe wrap work with class names and stuff in separate class (like in Java implementation)
|
||||
// Get output file name
|
||||
string const proto_file_name = file->name();
|
||||
size_t file_extension_index = proto_file_name.find(".proto");
|
||||
string const file_name = proto_file_name.substr(0, file_extension_index) + ".kt";
|
||||
|
||||
|
||||
google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(context->Open(file_name));
|
||||
io::Printer printer(output.get(), '$', /* annotation_collector = */ NULL);
|
||||
|
||||
// Create Generators for all top-level messages
|
||||
int topLevelMessagesCount = file->message_type_count();
|
||||
for (int i = 0; i < topLevelMessagesCount; ++i) {
|
||||
Descriptor const * descriptor = file->message_type(i);
|
||||
ClassGenerator * cgen = new ClassGenerator(descriptor);
|
||||
classes.push_back(cgen);
|
||||
}
|
||||
|
||||
// Generate code and clean up
|
||||
generateCode(&printer, classes);
|
||||
for (int i = 0; i < classes.size(); ++i) {
|
||||
delete classes[i];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
FileGenerator::FileGenerator() { }
|
||||
|
||||
FileGenerator::~FileGenerator() {
|
||||
}
|
||||
|
||||
|
||||
} // namespace kotlin
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
@@ -0,0 +1,37 @@
|
||||
//
|
||||
// Created by user on 7/11/16.
|
||||
//
|
||||
|
||||
#ifndef SRC_KOTLIN_FILE_GENERATOR_H
|
||||
#define SRC_KOTLIN_FILE_GENERATOR_H
|
||||
|
||||
#include "kotlin_class_generator.h"
|
||||
#include <vector>
|
||||
#include <google/protobuf/io/printer.h>
|
||||
#include <google/protobuf/compiler/code_generator.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace kotlin {
|
||||
|
||||
|
||||
class FileGenerator : public CodeGenerator {
|
||||
public:
|
||||
FileGenerator();
|
||||
~FileGenerator();
|
||||
|
||||
void generateCode(io::Printer *, std::vector<ClassGenerator *> &) const;
|
||||
|
||||
// implements CodeGenerator ----------------------------------------
|
||||
bool Generate(const FileDescriptor* file,
|
||||
const string& parameter,
|
||||
GeneratorContext* context,
|
||||
string* error) const;
|
||||
};
|
||||
|
||||
} // namespace kotlin
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
#endif //SRC_KOTLIN_FILE_GENERATOR_H
|
||||
@@ -0,0 +1,28 @@
|
||||
#include <google/protobuf/compiler/command_line_interface.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_generator.h>
|
||||
#include <google/protobuf/compiler/python/python_generator.h>
|
||||
#include <google/protobuf/compiler/java/java_generator.h>
|
||||
#include <google/protobuf/compiler/javanano/javanano_generator.h>
|
||||
// TODO(teboring): Add it back when php implementation is ready
|
||||
// #include <google/protobuf/compiler/php/php_generator.h>
|
||||
#include <google/protobuf/compiler/ruby/ruby_generator.h>
|
||||
#include <google/protobuf/compiler/csharp/csharp_generator.h>
|
||||
#include <google/protobuf/compiler/objectivec/objectivec_generator.h>
|
||||
#include <google/protobuf/compiler/js/js_generator.h>
|
||||
#include "kotlin_file_generator.h"
|
||||
#include <iostream>
|
||||
|
||||
int main(int argc, const char* const * argv) {
|
||||
google::protobuf::compiler::CommandLineInterface cli;
|
||||
|
||||
// Support generation of C++ source and headers.
|
||||
google::protobuf::compiler::cpp::CppGenerator cpp_generator;
|
||||
cli.RegisterGenerator("--cpp_out", &cpp_generator,
|
||||
"Generate C++ source and header.");
|
||||
|
||||
google::protobuf::compiler::kotlin::FileGenerator kotlinGenerator;
|
||||
cli.RegisterGenerator("--kotlin_out", &kotlinGenerator,
|
||||
"Generate Foo file.");
|
||||
|
||||
return cli.Run(argc, argv);
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
class Person private constructor () {
|
||||
class PhoneNumber private constructor () {
|
||||
val number : kotlin.String? = null
|
||||
val type : PhoneType? = null
|
||||
|
||||
}
|
||||
|
||||
enum class PhoneType(val ord: Int) {
|
||||
MOBILE (0),
|
||||
HOME (1),
|
||||
WORK (2)
|
||||
}
|
||||
|
||||
val name : kotlin.String? = null
|
||||
val id : Int? = null
|
||||
val email : kotlin.String? = null
|
||||
val phones : List <PhoneNumber> = listOf()
|
||||
|
||||
}
|
||||
|
||||
class AddressBook private constructor () {
|
||||
val people : List <Person> = listOf()
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
// See README.txt for information and build instructions.
|
||||
//
|
||||
// Note: START and END tags are used in comments to define sections used in
|
||||
// tutorials. They are not part of the syntax for Protocol Buffers.
|
||||
//
|
||||
// To get an in-depth walkthrough of this file and the related examples, see:
|
||||
// https://developers.google.com/protocol-buffers/docs/tutorials
|
||||
|
||||
// [START declaration]
|
||||
syntax = "proto3";
|
||||
package tutorial;
|
||||
// [END declaration]
|
||||
|
||||
// [START java_declaration]
|
||||
option java_package = "com.example.tutorial";
|
||||
option java_outer_classname = "AddressBookProtos";
|
||||
// [END java_declaration]
|
||||
|
||||
// [START csharp_declaration]
|
||||
option csharp_namespace = "Google.Protobuf.Examples.AddressBook";
|
||||
// [END csharp_declaration]
|
||||
|
||||
// [START messages]
|
||||
message Person {
|
||||
string name = 1;
|
||||
int32 id = 2; // Unique ID number for this person.
|
||||
string email = 3;
|
||||
|
||||
enum PhoneType {
|
||||
MOBILE = 0;
|
||||
HOME = 1;
|
||||
WORK = 2;
|
||||
}
|
||||
|
||||
message PhoneNumber {
|
||||
string number = 1;
|
||||
PhoneType type = 2;
|
||||
}
|
||||
|
||||
repeated PhoneNumber phones = 4;
|
||||
}
|
||||
|
||||
// Our address book file is just one of these.
|
||||
message AddressBook {
|
||||
repeated Person people = 1;
|
||||
}
|
||||
// [END messages]
|
||||
Reference in New Issue
Block a user