Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

*: Add the support for structured annotations #13

Merged
merged 10 commits into from
Oct 10, 2024
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
compiler/cpp/src/parse: Add virtual class to carry name and annotations
  • Loading branch information
AlexisMontagne committed Oct 8, 2024
commit b51801e6bcd4c44e897f99d7ba27eace80a3f492
1 change: 1 addition & 0 deletions compiler/cpp/Makefile.am
Original file line number Diff line number Diff line change
@@ -41,6 +41,7 @@ thrift_SOURCES = src/main.cc \
src/logging.h \
src/md5.h \
src/parse/t_doc.h \
src/parse/t_annotated.h \
src/parse/t_type.h \
src/parse/t_base_type.h \
src/parse/t_enum.h \
2 changes: 1 addition & 1 deletion compiler/cpp/src/generate/t_as3_generator.cc
Original file line number Diff line number Diff line change
@@ -679,7 +679,7 @@ void t_as3_generator::generate_as3_struct_definition(ofstream& out,
bool is_result) {
generate_as3_doc(out, tstruct);

bool is_final = (tstruct->annotations_.find("final") != tstruct->annotations_.end());
bool is_final = tstruct->has_legacy_annotation("final");
bool bindable = !is_exception && !in_class && bindable_;

indent(out) << (in_class ? "" : "public ") << (is_final ? "final " : "") << "class "
9 changes: 4 additions & 5 deletions compiler/cpp/src/generate/t_cpp_generator.cc
Original file line number Diff line number Diff line change
@@ -1014,7 +1014,7 @@ void t_cpp_generator::generate_struct_declaration(ofstream& out,
scope_down(out);
}

if (tstruct->annotations_.find("final") == tstruct->annotations_.end()) {
if (!tstruct->has_legacy_annotation("final")) {
out << endl << indent() << "virtual ~" << tstruct->get_name() << "() throw();" << endl;
}

@@ -1134,7 +1134,7 @@ void t_cpp_generator::generate_struct_definition(ofstream& out,
const vector<t_field*>& members = tstruct->get_members();

// Destructor
if (tstruct->annotations_.find("final") == tstruct->annotations_.end()) {
if (!tstruct->has_legacy_annotation("final")) {
force_cpp_out << endl << indent() << tstruct->get_name() << "::~" << tstruct->get_name()
<< "() throw() {" << endl;
indent_up();
@@ -4017,9 +4017,8 @@ string t_cpp_generator::namespace_close(string ns) {
string t_cpp_generator::type_name(t_type* ttype, bool in_typedef, bool arg) {
if (ttype->is_base_type()) {
string bname = base_type_name(((t_base_type*)ttype)->get_base());
std::map<string, string>::iterator it = ttype->annotations_.find("cpp.type");
if (it != ttype->annotations_.end()) {
bname = it->second;
if (ttype->has_legacy_annotation("cpp.type")) {
bname = ttype->legacy_annotation_value("cpp.type");
}

if (!arg) {
10 changes: 5 additions & 5 deletions compiler/cpp/src/generate/t_csharp_generator.cc
Original file line number Diff line number Diff line change
@@ -695,7 +695,7 @@ void t_csharp_generator::generate_csharp_struct_definition(ofstream& out,
<< endl; // do not make exception classes directly WCF serializable, we provide a
// separate "fault" for that
}
bool is_final = (tstruct->annotations_.find("final") != tstruct->annotations_.end());
bool is_final = tstruct->has_legacy_annotation("final");

indent(out) << "public " << (is_final ? "sealed " : "") << "partial class "
<< normalize_name(tstruct->get_name()) << " : ";
@@ -881,7 +881,7 @@ void t_csharp_generator::generate_csharp_wcffault(ofstream& out, t_struct* tstru
indent(out) << "[Serializable]" << endl;
indent(out) << "#endif" << endl;
indent(out) << "[DataContract]" << endl;
bool is_final = (tstruct->annotations_.find("final") != tstruct->annotations_.end());
bool is_final = tstruct->has_legacy_annotation("final");

indent(out) << "public " << (is_final ? "sealed " : "") << "partial class " << tstruct->get_name()
<< "Fault" << endl;
@@ -2512,11 +2512,11 @@ void t_csharp_generator::prepare_member_name_mapping(void* scope,
// current C# generator policy:
// - prop names are always rendered with an Uppercase first letter
// - struct names are used as given


// prevent name conflicts with struct (CS0542 error)
used_member_names.insert(structname);

// prevent name conflicts with known methods (THRIFT-2942)
used_member_names.insert("Read");
used_member_names.insert("Write");
2 changes: 1 addition & 1 deletion compiler/cpp/src/generate/t_delphi_generator.cc
Original file line number Diff line number Diff line change
@@ -1623,7 +1623,7 @@ void t_delphi_generator::generate_delphi_struct_definition(ostream& out,
bool in_class,
bool is_result,
bool is_x_factory) {
bool is_final = (tstruct->annotations_.find("final") != tstruct->annotations_.end());
bool is_final = tstruct->has_legacy_annotation("final");
string struct_intf_name;
string struct_name;
string isset_name;
7 changes: 3 additions & 4 deletions compiler/cpp/src/generate/t_go_generator.cc
Original file line number Diff line number Diff line change
@@ -360,7 +360,7 @@ static bool type_need_reference(t_type* type) {
// returns false if field could not use comparison to default value as !IsSet*
bool t_go_generator::is_pointer_field(t_field* tfield, bool in_container_value) {
(void)in_container_value;
if (tfield->annotations_.count("cpp.ref") != 0) {
if (tfield->has_legacy_annotation("cpp.ref")) {
return true;
}
t_type* type = tfield->get_type()->get_true_type();
@@ -1201,9 +1201,8 @@ void t_go_generator::generate_go_struct_definition(ofstream& out,
} else {
gotag = "json:\"" + escape_string((*m_iter)->get_name()) + "\"";
}
std::map<string, string>::iterator it = (*m_iter)->annotations_.find("go.tag");
if (it != (*m_iter)->annotations_.end()) {
gotag = it->second;
if ((*m_iter)->has_legacy_annotation("go.tag")) {
gotag = (*m_iter)->legacy_annotation_value("go.tag");
}
indent(out) << publicize((*m_iter)->get_name()) << " " << goType
<< " `thrift:\"" << escape_string((*m_iter)->get_name()) << ","
4 changes: 2 additions & 2 deletions compiler/cpp/src/generate/t_java_generator.cc
Original file line number Diff line number Diff line change
@@ -768,7 +768,7 @@ void t_java_generator::generate_java_union(t_struct* tstruct) {

generate_java_doc(f_struct, tstruct);

bool is_final = (tstruct->annotations_.find("final") != tstruct->annotations_.end());
bool is_final = tstruct->has_legacy_annotation("final");

indent(f_struct) << "public " << (is_final ? "final " : "") << "class " << tstruct->get_name()
<< " extends org.apache.thrift.TUnion<" << tstruct->get_name() << ", "
@@ -1325,7 +1325,7 @@ void t_java_generator::generate_java_struct_definition(ofstream& out,
bool is_result) {
generate_java_doc(out, tstruct);

bool is_final = (tstruct->annotations_.find("final") != tstruct->annotations_.end());
bool is_final = tstruct->has_legacy_annotation("final");

if (!in_class) {
generate_javax_generated_annotation(out);
4 changes: 2 additions & 2 deletions compiler/cpp/src/generate/t_javame_generator.cc
Original file line number Diff line number Diff line change
@@ -656,7 +656,7 @@ void t_javame_generator::generate_java_union(t_struct* tstruct) {

generate_java_doc(f_struct, tstruct);

bool is_final = (tstruct->annotations_.find("final") != tstruct->annotations_.end());
bool is_final = tstruct->has_legacy_annotation("final");

indent(f_struct) << "public " << (is_final ? "final " : "") << "class " << tstruct->get_name()
<< " extends TUnion ";
@@ -996,7 +996,7 @@ void t_javame_generator::generate_java_struct_definition(ofstream& out,
bool is_result) {
generate_java_doc(out, tstruct);

bool is_final = (tstruct->annotations_.find("final") != tstruct->annotations_.end());
bool is_final = tstruct->has_legacy_annotation("final");

indent(out) << "public " << (is_final ? "final " : "") << (in_class ? "static " : "") << "class "
<< tstruct->get_name() << " ";
80 changes: 80 additions & 0 deletions compiler/cpp/src/parse/t_annotated.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

#ifndef T_ANNOTATED_H
#define T_ANNOTATED_H

#include <string>
#include <map>
#include "t_doc.h"

class t_type;
class t_const_value;

class t_structured_annotation {
public:
t_structured_annotation() : type_(NULL), value_(NULL) {};
t_type* type_;
t_const_value* value_;

};

/**
* Placeholder struct for returning the key and value of an annotation
* during parsing.
*/
struct t_legacy_annotation {
std::string key;
std::string val;
};


class t_annotated : public t_doc {
public:
void append_legacy_annotation(t_legacy_annotation* v) { legacy_annotations_[v->key] = v->val; }
void append_structured_annotation(t_structured_annotation* v) { structured_annotations_.push_back(v); }

void merge(t_annotated* other) {
legacy_annotations_.insert(std::make_move_iterator(other->legacy_annotations_.begin()), std::make_move_iterator(other->legacy_annotations_.end()));
structured_annotations_.insert(structured_annotations_.end(), std::make_move_iterator(other->structured_annotations_.begin()), std::make_move_iterator(other->structured_annotations_.end()));
}

const std::map<std::string, std::string>& legacy_annotations() { return legacy_annotations_; }

const std::string& get_name() const { return name_; }

bool has_legacy_annotation(std::string key) {
return legacy_annotations_.find(key) != legacy_annotations_.end();
}

const std::string legacy_annotation_value(std::string key) {
return legacy_annotations_.find(key)->second;
}

t_annotated() : name_("") {}
protected:
t_annotated(std::string name) : name_(name) {}
std::string name_;

private:
std::map<std::string, std::string> legacy_annotations_;
std::vector<t_structured_annotation*> structured_annotations_;
};

#endif
7 changes: 2 additions & 5 deletions compiler/cpp/src/parse/t_const.h
Original file line number Diff line number Diff line change
@@ -30,20 +30,17 @@
* whole thing out.
*
*/
class t_const : public t_doc {
class t_const : public t_annotated {
public:
t_const(t_type* type, std::string name, t_const_value* value)
: type_(type), name_(name), value_(value) {}
: t_annotated(name), type_(type), value_(value) {}

t_type* get_type() const { return type_; }

std::string get_name() const { return name_; }

t_const_value* get_value() const { return value_; }

private:
t_type* type_;
std::string name_;
t_const_value* value_;
};

12 changes: 3 additions & 9 deletions compiler/cpp/src/parse/t_enum_value.h
Original file line number Diff line number Diff line change
@@ -21,28 +21,22 @@
#define T_ENUM_VALUE_H

#include <string>
#include "t_doc.h"
#include "t_annotated.h"

/**
* A constant. These are used inside of enum definitions. Constants are just
* symbol identifiers that may or may not have an explicit value associated
* with them.
*
*/
class t_enum_value : public t_doc {
class t_enum_value : public t_annotated {
public:
t_enum_value(std::string name, int value) : name_(name), value_(value) {}
t_enum_value(std::string name, int value) : t_annotated(name), value_(value) {}

~t_enum_value() {}

const std::string& get_name() const { return name_; }

int get_value() const { return value_; }

std::map<std::string, std::string> annotations_;

private:
std::string name_;
int value_;
};

15 changes: 6 additions & 9 deletions compiler/cpp/src/parse/t_field.h
Original file line number Diff line number Diff line change
@@ -23,7 +23,7 @@
#include <string>
#include <sstream>

#include "t_doc.h"
#include "t_annotated.h"

// Forward declare for xsd_attrs
class t_struct;
@@ -33,11 +33,11 @@ class t_struct;
* a symbolic name, and a numeric identifier.
*
*/
class t_field : public t_doc {
class t_field : public t_annotated {
public:
t_field(t_type* type, std::string name)
: type_(type),
name_(name),
: t_annotated(name),
type_(type),
key_(0),
value_(NULL),
xsd_optional_(false),
@@ -46,8 +46,8 @@ class t_field : public t_doc {
reference_(false) {}

t_field(t_type* type, std::string name, int32_t key)
: type_(type),
name_(name),
: t_annotated(name),
type_(type),
key_(key),
req_(T_OPT_IN_REQ_OUT),
value_(NULL),
@@ -106,15 +106,12 @@ class t_field : public t_doc {
}
};

std::map<std::string, std::string> annotations_;

bool get_reference() { return reference_; }

void set_reference(bool reference) { reference_ = reference; }

private:
t_type* type_;
std::string name_;
int32_t key_;
e_req req_;
t_const_value* value_;
16 changes: 5 additions & 11 deletions compiler/cpp/src/parse/t_function.h
Original file line number Diff line number Diff line change
@@ -23,18 +23,18 @@
#include <string>
#include "t_type.h"
#include "t_struct.h"
#include "t_doc.h"
#include "t_annotated.h"

/**
* Representation of a function. Key parts are return type, function name,
* optional modifiers, and an argument list, which is implemented as a thrift
* struct.
*
*/
class t_function : public t_doc {
class t_function : public t_annotated {
public:
t_function(t_type* returntype, std::string name, t_struct* arglist, bool oneway = false)
: returntype_(returntype), name_(name), arglist_(arglist), oneway_(oneway) {
: t_annotated(name), returntype_(returntype), arglist_(arglist), oneway_(oneway) {
xceptions_ = new t_struct(NULL);
if (oneway_ && (!returntype_->is_void())) {
pwarning(1, "Oneway methods should return void.\n");
@@ -46,8 +46,8 @@ class t_function : public t_doc {
t_struct* arglist,
t_struct* xceptions,
bool oneway = false)
: returntype_(returntype),
name_(name),
: t_annotated(name),
returntype_(returntype),
arglist_(arglist),
xceptions_(xceptions),
oneway_(oneway) {
@@ -63,19 +63,13 @@ class t_function : public t_doc {

t_type* get_returntype() const { return returntype_; }

const std::string& get_name() const { return name_; }

t_struct* get_arglist() const { return arglist_; }

t_struct* get_xceptions() const { return xceptions_; }

bool is_oneway() const { return oneway_; }

std::map<std::string, std::string> annotations_;

private:
t_type* returntype_;
std::string name_;
t_struct* arglist_;
t_struct* xceptions_;
bool oneway_;
Loading