[ 
https://issues.apache.org/jira/browse/THRIFT-3773?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15519366#comment-15519366
 ] 

ASF GitHub Bot commented on THRIFT-3773:
----------------------------------------

Github user apocolipse commented on a diff in the pull request:

    https://github.com/apache/thrift/pull/1084#discussion_r80365498
  
    --- Diff: compiler/cpp/src/generate/t_swift_3_generator.cc ---
    @@ -0,0 +1,2458 @@
    +/*
    + * 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.
    + */
    +
    +#include <string>
    +#include <fstream>
    +#include <iostream>
    +#include <vector>
    +#include <set>
    +
    +#include <stdlib.h>
    +#include <sys/stat.h>
    +#include <sstream>
    +#include "t_oop_generator.h"
    +#include "platform.h"
    +
    +using std::map;
    +using std::ostream;
    +using std::ofstream;
    +using std::ostringstream;
    +using std::set;
    +using std::string;
    +using std::stringstream;
    +using std::vector;
    +
    +static const string endl = "\n"; // avoid ostream << std::endl flushes
    +
    +/**
    + * Swift 3 code generator.
    + *
    + * Designed from the Swift/Cocoa code generator(s)
    + */
    +class t_swift_3_generator : public t_oop_generator {
    +public:
    +  t_swift_3_generator(t_program* program,
    +                    const map<string, string>& parsed_options,
    +                    const string& option_string)
    +    : t_oop_generator(program) {
    +    (void)option_string;
    +    map<string, string>::const_iterator iter;
    +
    +    log_unexpected_ = false;
    +    async_clients_ = false;
    +    debug_descriptions_ = false;
    +    no_strict_ = false;
    +
    +    for( iter = parsed_options.begin(); iter != parsed_options.end(); 
++iter) {
    +      if( iter->first.compare("log_unexpected") == 0) {
    +        log_unexpected_ = true;
    +      } else if( iter->first.compare("async_clients") == 0) {
    +        async_clients_ = true;
    +      } else if( iter->first.compare("no_strict") == 0) {
    +        no_strict_ = true;
    +      } else if( iter->first.compare("debug_descriptions") == 0) {
    +        debug_descriptions_ = true;
    +      } else {
    +        throw "unknown option swift:" + iter->first;
    +      }
    +    }
    +
    +    out_dir_base_ = "gen-swift";
    +  }
    +
    +  /**
    +   * Init and close methods
    +   */
    +
    +  void init_generator();
    +  void close_generator();
    +
    +  void generate_consts(vector<t_const*> consts);
    +
    +  /**
    +   * Program-level generation functions
    +   */
    +
    +  void generate_typedef(t_typedef* ttypedef);
    +  void generate_enum(t_enum* tenum);
    +  void generate_struct(t_struct* tstruct);
    +  void generate_xception(t_struct* txception);
    +  void generate_service(t_service* tservice);
    +
    +  void print_const_value(ostream& out,
    +                         string name,
    +                         t_type* type,
    +                         t_const_value* value,
    +                         bool defval = false,
    +                         bool is_property = false);
    +  void render_const_value(ostream& out,
    +                          t_type* type,
    +                          t_const_value* value);
    +
    +  void generate_swift_struct(ofstream& out,
    +                             t_struct* tstruct,
    +                             bool is_private,
    +                             bool is_result);
    +  void generate_swift_struct_init(ofstream& out,
    +                                  t_struct* tstruct,
    +                                  bool all,
    +                                  bool is_private);
    +
    +  void generate_swift_struct_implementation(ofstream& out,
    +                                            t_struct* tstruct,
    +                                            bool is_result,
    +                                            bool is_private);
    +  void generate_swift_struct_hashable_extension(ofstream& out,
    +                                                t_struct* tstruct,
    +                                                bool is_private);
    +  void generate_swift_struct_equatable_extension(ofstream& out,
    +                                                 t_struct* tstruct,
    +                                                 bool is_private);
    +  void generate_swift_struct_thrift_extension(ofstream& out,
    +                                              t_struct* tstruct,
    +                                              bool is_result,
    +                                              bool is_private);
    +  void generate_swift_struct_reader(ofstream& out, t_struct* tstruct, bool 
is_private);
    +  void generate_swift_union_reader(ofstream& out, t_struct* tstruct);
    +
    +  void generate_swift_struct_writer(ofstream& out,t_struct* tstruct, bool 
is_private);
    +  void generate_swift_struct_result_writer(ofstream& out, t_struct* 
tstruct);
    +  void generate_swift_struct_printable_extension(ofstream& out, t_struct* 
tstruct);
    +
    +  string function_result_helper_struct_type(t_service *tservice, 
t_function* tfunction);
    +  string function_args_helper_struct_type(t_service* tservice, t_function* 
tfunction);
    +  void generate_function_helpers(t_service *tservice, t_function* 
tfunction);
    +
    +  /**
    +   * Service-level generation functions
    +   */
    +
    +  void generate_swift_service_protocol(ofstream& out, t_service* tservice);
    +  void generate_swift_service_protocol_async(ofstream& out, t_service* 
tservice);
    +
    +  void generate_swift_service_client(ofstream& out, t_service* tservice);
    +  void generate_swift_service_client_async(ofstream& out, t_service* 
tservice);
    +
    +  void 
generate_swift_service_client_send_function_implementation(ofstream& out,
    +                                                                  
t_service* tservice,
    +                                                                  
t_function* tfunction,
    +                                                                  bool 
needs_protocol);
    +  void generate_swift_service_client_send_function_invocation(ofstream& 
out, t_function* tfunction);
    +  void 
generate_swift_service_client_send_async_function_invocation(ofstream& out,
    +                                                                    
t_function* tfunction);
    +  void 
generate_swift_service_client_recv_function_implementation(ofstream& out,
    +                                                                  
t_service* tservice,
    +                                                                  
t_function* tfunction,
    +                                                                  bool 
needs_protocol);
    +  void generate_swift_service_client_implementation(ofstream& out, 
t_service* tservice);
    +  void generate_swift_service_client_async_implementation(ofstream& out, 
t_service* tservice);
    +
    +  void generate_swift_service_server(ofstream& out, t_service* tservice);
    +  void generate_swift_service_server_implementation(ofstream& out, 
t_service* tservice);
    +  void generate_swift_service_helpers(t_service* tservice);
    +  /**
    +   * Helper rendering functions
    +   */
    +
    +  string swift_imports();
    +  string swift_thrift_imports();
    +  string type_name(t_type* ttype, bool is_optional=false, bool 
is_forced=false);
    +  string base_type_name(t_base_type* tbase);
    +  string declare_property(t_field* tfield, bool is_private);
    +  string function_signature(t_function* tfunction);
    +  string async_function_signature(t_function* tfunction);
    +  string argument_list(t_struct* tstruct, string protocol_name, bool 
is_internal, bool default_val);
    +  string type_to_enum(t_type* ttype, bool qualified=false);
    +  string maybe_escape_identifier(const string& identifier);
    +  string enum_case_name(t_enum_value* tenum_case, bool declaration);
    +  string enum_const_name(string enum_identifier);
    +  void populate_reserved_words();
    +  void generate_docstring(ofstream& out, string& doc);
    +
    +private:
    +
    +  void block_open(ostream& out) {
    +    out << " {" << endl;
    +    indent_up();
    +  }
    +
    +  void block_close(ostream& out, bool end_line=true) {
    +    indent_down();
    +    indent(out) << "}";
    +    if (end_line) out << endl;
    +  }
    +
    +
    +  bool field_is_optional(t_field* tfield) {
    +    return tfield->get_req() == t_field::T_OPTIONAL;
    +  }
    +
    +  bool struct_has_required_fields(t_struct* tstruct) {
    +    const vector<t_field*>& members = tstruct->get_members();
    +    vector<t_field*>::const_iterator m_iter;
    +    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
    +      if (!field_is_optional(*m_iter)) {
    +        return true;
    +      }
    +    }
    +    return false;
    +  }
    +
    +  bool struct_has_optional_fields(t_struct* tstruct) {
    +    const vector<t_field*>& members = tstruct->get_members();
    +    vector<t_field*>::const_iterator m_iter;
    +    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
    +      if (field_is_optional(*m_iter)) {
    +        return true;
    +      }
    +    }
    +    return false;
    +  }
    +
    +  string constants_declarations_;
    +
    +  /**
    +   * File streams
    +   */
    +
    +  ofstream f_decl_;
    +  ofstream f_impl_;
    +
    +  bool log_unexpected_;
    +  bool async_clients_;
    +  bool debug_descriptions_;
    +  bool no_strict_;
    +
    +  set<string> swift_reserved_words_;
    +};
    +
    +/**
    + * Prepares for file generation by opening up the necessary file output
    + * streams.
    + */
    +void t_swift_3_generator::init_generator() {
    +  // Make output directory
    +  MKDIR(get_out_dir().c_str());
    +
    +  populate_reserved_words();
    +
    +  // we have a .swift declarations file...
    +  string f_decl_name = capitalize(program_name_) + ".swift";
    +  string f_decl_fullname = get_out_dir() + f_decl_name;
    +  f_decl_.open(f_decl_fullname.c_str());
    +
    +  f_decl_ << autogen_comment() << endl;
    +
    +  f_decl_ << swift_imports() << swift_thrift_imports() << endl;
    +
    +  // ...and a .swift implementation extensions file
    +  string f_impl_name = capitalize(program_name_) + "+Exts.swift";
    +  string f_impl_fullname = get_out_dir() + f_impl_name;
    +  f_impl_.open(f_impl_fullname.c_str());
    +
    +  f_impl_ << autogen_comment() << endl;
    +
    +  f_impl_ << swift_imports() << swift_thrift_imports() << endl;
    +
    +}
    +
    +/**
    + * Prints the value of a constant with the given type. Note that type 
checking
    + * is NOT performed in this function as it is always run beforehand using 
the
    + * validate_types method in main.cc
    + */
    +void t_swift_3_generator::print_const_value(ostream& out,
    +                                            string name,
    +                                            t_type* type,
    +                                            t_const_value* value,
    +                                            bool defval,
    +                                            bool is_property) {
    +  // type = get_true_type(type);
    +
    +  // if (type->is_base_type()) {
    +  //   string v2 = render_const_value(out, type, value);
    +  //   indent(out);
    +  //   if (defval)
    +  //     out << type_name(type) << " ";
    +  //   out << name << " = " << v2 << ";" << endl << endl;
    +  // } else if (type->is_enum()) {
    +  //   indent(out);
    +  //   if (defval)
    +  //     out << type_name(type) << " ";
    +  //   out << name << " = " << render_const_value(out, type, value) << ";" 
<< endl << endl;
    +  // } else if (type->is_struct() || type->is_xception()) {
    +  //   indent(out);
    +  //   const vector<t_field*>& fields = ((t_struct*)type)->get_members();
    +  //   vector<t_field*>::const_iterator f_iter;
    +  //   const map<t_const_value*, t_const_value*>& val = value->get_map();
    +  //   map<t_const_value*, t_const_value*>::const_iterator v_iter;
    +  //   if (defval)
    +  //     out << type_name(type) << " ";
    +  //   out << name << " = [" << type_name(type, true) << " new];"
    +  //       << endl;
    +  //   for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
    +  //     t_type* field_type = NULL;
    +  //     for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
    +  //       if ((*f_iter)->get_name() == v_iter->first->get_string()) {
    +  //         field_type = (*f_iter)->get_type();
    +  //       }
    +  //     }
    +  //     if (field_type == NULL) {
    +  //       throw "type error: " + type->get_name() + " has no field " + 
v_iter->first->get_string();
    +  //     }
    +  //     string val = render_const_value(out, field_type, v_iter->second);
    +  //     std::string cap_name = capitalize(v_iter->first->get_string());
    +  //     indent(out) << "[" << name << " set" << cap_name << ":" << val << 
"];" << endl;
    +  //   }
    +  // } else if (type->is_map()) {
    +  //   ostringstream mapout;
    +  //   indent(mapout);
    +  //   t_type* ktype = ((t_map*)type)->get_key_type();
    +  //   t_type* vtype = ((t_map*)type)->get_val_type();
    +  //   const map<t_const_value*, t_const_value*>& val = value->get_map();
    +  //   map<t_const_value*, t_const_value*>::const_iterator v_iter;
    +  //   if (defval)
    +  //     mapout << type_name(type) << " ";
    +  //   mapout << name << " = @{";
    +  //   for (v_iter = val.begin(); v_iter != val.end();) {
    +  //     mapout << render_const_value(out, ktype, v_iter->first, true) << 
": "
    +  //         << render_const_value(out, vtype, v_iter->second, true);
    +  //     if (++v_iter != val.end()) {
    +  //       mapout << ", ";
    +  //     }
    +  //   }
    +  //   mapout << "}";
    +  //   out << mapout.str();
    +  // } else if (type->is_list()) {
    +  //   ostringstream listout;
    +  //   indent(listout);
    +  //   t_type* etype = ((t_list*)type)->get_elem_type();
    +  //   const vector<t_const_value*>& val = value->get_list();
    +  //   vector<t_const_value*>::const_iterator v_iter;
    +  //   if (defval)
    +  //     listout << type_name(type) << " ";
    +  //   listout << name << " = @[";
    +  //   for (v_iter = val.begin(); v_iter != val.end();) {
    +  //     listout << render_const_value(out, etype, *v_iter, true);
    +  //     if (++v_iter != val.end()) {
    +  //       listout << ", ";
    +  //     }
    +  //   }
    +  //   listout << "]";
    +  //   out << listout.str();
    +  // } else if (type->is_set()) {
    +  //   ostringstream setout;
    +  //   indent(setout);
    +  //   t_type* etype = ((t_set*)type)->get_elem_type();
    +  //   const vector<t_const_value*>& val = value->get_list();
    +  //   vector<t_const_value*>::const_iterator v_iter;
    +  //   if (defval)
    +  //     setout << type_name(type) << " ";
    +  //   setout << name << " = [NSSet setWithArray:@[";
    +  //   for (v_iter = val.begin(); v_iter != val.end();) {
    +  //     setout << render_const_value(out, etype, *v_iter, true);
    +  //     if (++v_iter != val.end()) {
    +  //       setout << ", ";
    +  //     }
    +  //   }
    +  //   setout << "]]";
    +  //   out << setout.str();
    +  // } else {
    +  //   throw "compiler error: no const of type " + type->get_name();
    +  // }
    +}
    +
    +/**
    + * Prints standard Cocoa imports
    + *
    + * @return List of imports for Cocoa libraries
    + */
    +string t_swift_3_generator::swift_imports() {
    +
    +  vector<string> includes_list;
    +  includes_list.push_back("Foundation");
    +
    +  ostringstream includes;
    +
    +  vector<string>::const_iterator i_iter;
    +  for (i_iter=includes_list.begin(); i_iter!=includes_list.end(); 
++i_iter) {
    +    includes << "import " << *i_iter << endl;
    +  }
    +
    +  includes << endl;
    +
    +  return includes.str();
    +}
    +
    +/**
    + * Prints Thrift runtime imports
    + *
    + * @return List of imports necessary for Thrift runtime
    + */
    +string t_swift_3_generator::swift_thrift_imports() {
    +
    +  vector<string> includes_list;
    +  includes_list.push_back("Thrift");
    +
    +  ostringstream includes;
    +
    +  vector<string>::const_iterator i_iter;
    +  for (i_iter=includes_list.begin(); i_iter!=includes_list.end(); 
++i_iter) {
    +    includes << "import " << *i_iter << endl;
    +  }
    +
    +  includes << endl;
    +
    +  return includes.str();
    +}
    +
    +/**
    + * Finish up generation.
    + */
    +void t_swift_3_generator::close_generator() {
    +  // stick our constants declarations at the end of the header file
    +  // since they refer to things we are defining.
    +  f_decl_ << constants_declarations_ << endl;
    +}
    +
    +/**
    + * Generates a typedef. This is just a simple 1-liner in Swift
    + *
    + * @param ttypedef The type definition
    + */
    +void t_swift_3_generator::generate_typedef(t_typedef* ttypedef) {
    +  f_decl_ << indent() << "public typealias " << ttypedef->get_symbolic()
    +          << " = " << type_name(ttypedef->get_type()) << endl;
    +  f_decl_ << endl;
    +}
    +
    +
    +/**
    + * Generates code for an enumerated type. In Swift, this is
    + * essentially the same as the thrift definition itself, using
    + * Swift syntax.  Conforms to TEnum which
    + * implementes read/write.
    + *
    + * @param tenum The enumeration
    + */
    +void t_swift_3_generator::generate_enum(t_enum* tenum) {
    +  f_decl_ << indent() << "public enum " << tenum->get_name() << " : Int32, 
TEnum";
    +  block_open(f_decl_);
    +
    +  vector<t_enum_value*> constants = tenum->get_constants();
    +  vector<t_enum_value*>::iterator c_iter;
    +
    +  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
    +    f_decl_ << indent() << "case " << enum_case_name((*c_iter), true)
    +            << " = " << (*c_iter)->get_value() << endl;
    +  }
    +
    +  f_decl_ << endl;
    +  f_decl_ << indent() << "public init()";
    +  block_open(f_decl_);
    +
    +  f_decl_ << indent() << "self = ." << enum_case_name(constants.front(), 
false) << endl;
    +  block_close(f_decl_);
    +
    +  block_close(f_decl_);
    +  f_decl_ << endl;
    +}
    +
    +string t_swift_3_generator::enum_case_name(t_enum_value* tenum_case, bool 
declaration) {
    +  string name = tenum_case->get_name();
    +  // force to lowercase for Swift style, maybe escape if its a keyword
    +  std::transform(name.begin(), name.end(), name.begin(), ::tolower);
    +  if (declaration) {
    +    name = maybe_escape_identifier(name);
    +  }
    +  return name;
    +}
    +
    +/**
    + * Renders a constant enum value by transforming the value portion to 
lowercase
    + * for Swift style.
    + */
    +string t_swift_3_generator::enum_const_name(string enum_identifier) {
    +  string::iterator it;
    +  for (it = enum_identifier.begin(); it < enum_identifier.end(); ++it) {
    +    if ((*it) == '.') {
    +      break;
    +    }
    +  }
    +  std::transform(it, enum_identifier.end(), it, ::tolower);
    +  return enum_identifier;
    +}
    +
    +/**
    + * Generates public constants for all Thrift constants.
    + *
    + * @param consts Constants to generate
    + */
    +void t_swift_3_generator::generate_consts(vector<t_const*> consts) {
    +
    +  ostringstream const_interface;
    +
    +  // Public constants for base types & strings
    +  vector<t_const*>::iterator c_iter;
    +  for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
    +    t_type* type = (*c_iter)->get_type();
    +    const_interface << "public let " << capitalize((*c_iter)->get_name()) 
<< " : " << type_name(type) << " = ";
    +    render_const_value(const_interface, type, (*c_iter)->get_value());
    +    const_interface << endl << endl;
    +  }
    +
    +  // this gets spit into the header file in ::close_generator
    +  constants_declarations_ = const_interface.str();
    +
    +}
    +
    +/**
    + * Generates a struct definition for a thrift data type. This is a struct
    + * with public members. Optional types are used for optional properties to
    + * allow them to be tested for availability. Separate inits are included 
for
    + * required properties & all properties.
    + *
    + * Generates extensions to provide conformance to TStruct, TSerializable,
    + * Hashable & Equatable
    + *
    + * @param tstruct The struct definition
    + */
    +void t_swift_3_generator::generate_struct(t_struct* tstruct) {
    +  generate_swift_struct(f_decl_, tstruct, false, false);
    +  generate_swift_struct_implementation(f_impl_, tstruct, false, false);
    +}
    +
    +/**
    + * Exceptions are structs, but they conform to Error
    + *
    + * @param tstruct The struct definition
    + */
    +void t_swift_3_generator::generate_xception(t_struct* txception) {
    +  generate_swift_struct(f_decl_, txception, false, false);
    +  generate_swift_struct_implementation(f_impl_, txception, false, false);
    +}
    +
    +void t_swift_3_generator::generate_docstring(ofstream& out,
    +                                             string& doc) {
    +  if (doc != "") {
    +    std::vector<std::string> strings;
    +
    +    std::string::size_type pos = 0;
    +    std::string::size_type prev = 0;
    +    while ((pos = doc.find("\n", prev)) != std::string::npos)
    +    {
    +        strings.push_back(doc.substr(prev, pos - prev));
    +        prev = pos + 1;
    +    }
    +
    +    // To get the last substring (or only, if delimiter is not found)
    +    strings.push_back(doc.substr(prev));
    +
    +    vector<string>::const_iterator d_iter;
    +    for (d_iter = strings.begin(); d_iter != strings.end(); ++d_iter) {
    +      out << indent() << "/// " << (*d_iter) << endl;
    +    }
    +  }
    +}
    +
    +
    +
    +/**
    + * Generate the interface for a struct. Only properties and
    + * init methods are included.
    + *
    + * @param tstruct The struct definition
    + * @param is_private
    + *                Is the struct public or private
    + */
    +void t_swift_3_generator::generate_swift_struct(ofstream& out,
    +                                              t_struct* tstruct,
    +                                              bool is_private,
    +                                              bool is_result) {
    +
    +
    +  string doc = tstruct->get_doc();
    +  if (doc != "") {
    +    std::vector<std::string> strings;
    +
    +    std::string::size_type pos = 0;
    +    std::string::size_type prev = 0;
    +    while ((pos = doc.find("\n", prev)) != std::string::npos)
    +    {
    +        strings.push_back(doc.substr(prev, pos - prev));
    +        prev = pos + 1;
    +    }
    +
    +    // To get the last substring (or only, if delimiter is not found)
    +    strings.push_back(doc.substr(prev));
    +
    +    vector<string>::const_iterator d_iter;
    +    for (d_iter = strings.begin(); d_iter != strings.end(); ++d_iter) {
    +      out << "/// " << (*d_iter) << endl;
    +    }
    +  }
    +
    +  // properties
    +  const vector<t_field*>& members = tstruct->get_members();
    +  vector<t_field*>::const_iterator m_iter;
    +
    +
    +  if (tstruct->is_union()) {
    +    // special, unions
    +    out << indent() << "public enum " << tstruct->get_name();
    +    block_open(out);
    +    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
    +      out << endl;
    +      // TODO: Defaults
    +      // add swift docstring if available
    +      string doc = (*m_iter)->get_doc();
    +      if (doc != "") {
    +        out << indent() << "/// " << doc;
    +      }
    +      out << indent() << "case "
    +          << maybe_escape_identifier((*m_iter)->get_name()) << "(val: "
    +          << type_name((*m_iter)->get_type(), false) << ")" << endl;
    +    }
    +  } else {
    +    // Normal structs
    +
    +    string visibility = is_private ? "fileprivate" : "public";
    +
    +    out << indent() << visibility << " final class " << 
tstruct->get_name();
    --- End diff --
    
    Thrift allows for self-referring structs, Swift does not.  Making them 
final gives the same non-subclassable semantics while allowing to be 
self-referencing.  Just loses value semantics.


> Swift Library
> -------------
>
>                 Key: THRIFT-3773
>                 URL: https://issues.apache.org/jira/browse/THRIFT-3773
>             Project: Thrift
>          Issue Type: New Feature
>          Components: Swift - Library
>            Reporter: Thomas Bartelmess
>
> We already have the option to generate Swift code in the Cocoa compiler, 
> however large parts of the (Objective-C) Cocoa Library still depend on Cocoa 
> and  Objective-C.
> It would be good to have a native Swift library that doesn't depend on the 
> Cocoa libraries.
> Design goals:
> - Fully compatible with the code that is currently generated by the Cocoa 
> compiler (both Objective-C and Swift).
> - Ability to run on Linux
> - Pure Swift, no Objective-C code.
> - No dependencies on closed source apple libraries
> - Keep the same interface, so that the library is compatible with the code 
> the current cocoa compiler generates
> - Better server support that the current Objective-C library.
> - Follow the new Swift packaging format to be compatible with the Swift 
> Package manager



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

Reply via email to