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