csharp: Add support for default param references in documentation
authorLauro Moura <lauromoura@expertisesolutions.com.br>
Fri, 20 Sep 2019 14:05:01 +0000 (16:05 +0200)
committerJongmin Lee <jm105.lee@samsung.com>
Fri, 20 Sep 2019 21:20:40 +0000 (06:20 +0900)
Summary:
This also adds the information of default values in `parameter_def`.
This will help adding actual default parameter support in the C#
bindings.

Thanks to @segfaultxavi for improved formatting and escaping.

Fixes T8224

Reviewers: segfaultxavi, felipealmeida, brunobelo

Reviewed By: segfaultxavi

Subscribers: cedric, #reviewers, segfaultxavi, #committers

Tags: #efl

Maniphest Tasks: T8224

Differential Revision: https://phab.enlightenment.org/D10050

src/bin/eolian_mono/eolian/mono/documentation.hh
src/bin/eolian_mono/eolian/mono/name_helpers.hh
src/lib/eolian_cxx/grammar/klass_def.hpp

index 201ee16..2b4ed87 100644 (file)
@@ -540,7 +540,22 @@ struct documentation_generator
    template<typename OutputIterator, typename Context>
    bool generate_parameter(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
    {
-      return generate_tag_param(sink, name_helpers::escape_keyword(param.param_name), param.documentation.full_text, context);
+      auto text = param.documentation.full_text;
+      if (param.default_value.is_engaged())
+      {
+          auto value = param.default_value->serialized;
+
+          if (param.default_value->is_name_ref)
+            {
+               value = name_helpers::full_managed_name(value);
+               text += "\\<br/\\>The default value is \\<see cref=\\\"" + value + "\\\"/\\>.";
+            }
+          else
+            {
+               text += "\\<br/\\>The default value is \\<c\\>" + value + "\\</c\\>.";
+            }
+      }
+      return generate_tag_param(sink, name_helpers::escape_keyword(param.param_name), text, context);
    }
 
    template<typename OutputIterator, typename Context>
index a1fd8cd..b206311 100644 (file)
@@ -204,6 +204,30 @@ inline std::string managed_name(std::string const& name, char separator='_')
   return utils::to_pascal_case(tokens);
 }
 
+inline std::string full_managed_name(std::string const& name)
+{
+  std::stringstream ss;
+
+  auto words = utils::split(name, '.');
+  std::transform(words.begin(), words.end(), words.begin(), [](std::string const& word) {
+     return managed_name(word);
+  });
+
+  auto b = std::begin(words), e = std::end(words);
+
+  if (b != e)
+    {
+      std::copy(b, std::prev(e), std::ostream_iterator<std::string>(ss, "."));
+      b = std::prev(e);
+    }
+
+  // Avoid trailing separator
+  if (b != e)
+    ss << *b;
+
+  return ss.str();
+}
+
 inline std::string alias_full_eolian_name(attributes::alias_def const& alias)
 {
 
index a3f3f3d..b1f6c38 100644 (file)
@@ -412,6 +412,9 @@ struct type_def
                << rhs.c_type << " has_own " << rhs.has_own << " is_ptr "
                << rhs.is_ptr << "]";
    }
+
+private:
+   void set(const char* regular_name, const char* c_type);
 };
 
 struct get_qualifier_visitor
@@ -516,17 +519,39 @@ inline void type_def::set(Eolian_Expression_Type eolian_exp_type)
     switch(eolian_exp_type)
       {
       case EOLIAN_EXPR_INT:
-        original_type = attributes::regular_type_def{"int", {{}, {}}, {}};
-        c_type = "int";
+        set("int", "int");
+        break;
+      case EOLIAN_EXPR_UINT:
+        set("uint", "unsigned int");
+        break;
+      case EOLIAN_EXPR_FLOAT:
+        set("float", "float");
+        break;
+      case EOLIAN_EXPR_DOUBLE:
+        set("double", "double");
+        break;
+      case EOLIAN_EXPR_STRING:
+        set("string", "const char *");
+      case EOLIAN_EXPR_BOOL:
+        set("bool", "Eina_Bool");
+        break;
+      case EOLIAN_EXPR_NULL:
+        set("null", "void *");
         break;
       default:
         // FIXME implement the remaining types
-        EINA_LOG_ERR("Unsupported expression type");
+        EINA_LOG_ERR("Unsupported expression type : %d", eolian_exp_type);
         std::abort();
         break;
       }
 }
 
+inline void type_def::set(const char* regular_name, const char* c_type)
+{
+    original_type = attributes::regular_type_def{regular_name, {{}, {}}, {}};
+    this->c_type = c_type;
+}
+
 struct alias_def
 {
   std::string eolian_name;
@@ -585,12 +610,57 @@ struct add_optional_qualifier_visitor
 };
 }
 
+struct value_def
+{
+  typedef eina::variant<int> variant_type; // FIXME support other types
+  variant_type value;
+  std::string literal;
+  type_def type;
+
+  value_def() = default;
+  value_def(Eolian_Value value_obj)
+  {
+    type.set(value_obj.type);
+    value = value_obj.value.i;
+    literal = eolian_expression_value_to_literal(&value_obj);
+  }
+};
+
+
+struct expression_def
+{
+  value_def value;
+  std::string serialized;
+  // We store this explicitly as evaluating the value reduces a name reference
+  // to a plain string value.
+  bool is_name_ref;
+
+  friend inline bool operator==(expression_def const& lhs, expression_def const& rhs)
+  {
+    return lhs.serialized == rhs.serialized;
+  }
+  friend inline bool operator!=(expression_def const& lhs, expression_def const& rhs)
+  {
+    return lhs != rhs;
+  }
+
+  expression_def(Eolian_Expression const* expression) : value(::eolian_expression_eval(expression, EOLIAN_MASK_ALL))
+                                                , serialized()
+                                                , is_name_ref(::eolian_expression_type_get(expression) == EOLIAN_EXPR_NAME)
+  {
+    auto serialized_s = ::eolian_expression_serialize(expression);
+    serialized = serialized_s;
+    ::eina_stringshare_del(serialized_s);
+  }
+};
+
 struct parameter_def
 {
   parameter_direction direction;
   type_def type;
   std::string param_name;
   documentation_def documentation;
+  eina::optional<expression_def> default_value;
   Eolian_Unit const* unit;
 
   friend inline bool operator==(parameter_def const& lhs, parameter_def const& rhs)
@@ -598,7 +668,8 @@ struct parameter_def
     return lhs.direction == rhs.direction
       && lhs.type == rhs.type
       && lhs.param_name == rhs.param_name
-      && lhs.documentation == rhs.documentation;
+      && lhs.documentation == rhs.documentation
+      && lhs.default_value == rhs.default_value;
   }
   friend inline bool operator!=(parameter_def const& lhs, parameter_def const& rhs)
   {
@@ -608,13 +679,17 @@ struct parameter_def
   parameter_def(parameter_direction direction, type_def type, std::string param_name,
                 documentation_def documentation, Eolian_Unit const* unit)
     : direction(std::move(direction)), type(std::move(type)), param_name(std::move(param_name)), documentation(documentation), unit(unit) {}
-  parameter_def(Eolian_Function_Parameter const* param, Eolian_Unit const* unit)
+  parameter_def(Eolian_Function_Parameter const* param, Eolian_Unit const* _unit)
     : type( ::eolian_parameter_type_get(param)
-            , unit
+            , _unit
             , eolian_parameter_c_type_get(param, EINA_FALSE)
             , eolian_parameter_is_move(param)
             , eolian_parameter_is_by_ref(param))
-    , param_name( ::eolian_parameter_name_get(param)), unit(unit)
+    , param_name( ::eolian_parameter_name_get(param))
+    , default_value(::eolian_parameter_default_value_get(param) ?
+                        ::eolian_parameter_default_value_get(param) :
+                        eina::optional<expression_def>{})
+    , unit(_unit)
   {
      Eolian_Parameter_Dir direction = ::eolian_parameter_direction_get(param);
      switch(direction)
@@ -1530,22 +1605,6 @@ struct klass_def
   }
 };
 
-struct value_def
-{
-  typedef eina::variant<int> variant_type; // FIXME support other types
-  variant_type value;
-  std::string literal;
-  type_def type;
-
-  value_def() = default;
-  value_def(Eolian_Value value_obj)
-  {
-    type.set(value_obj.type);
-    value = value_obj.value.i;
-    literal = eolian_expression_value_to_literal(&value_obj);
-  }
-};
-
 struct enum_value_def
 {
   value_def value;