mono-docs: Allow derived classes to have external examples

Summary:
You can now have external example files for derived classes (Efl.Ui.Button.SetText)
as well as for base classes (Efl.IText.SetText).
If both files are present, both examples are embedded in the docs. The more
examples the better!

Examples for classes in-between the hierarchy (Efl.Ui.Widget.SetText) are not
picked up. Might be worth examining in the future.

Test Plan:
Create example files for both `Efl.Ui.Button.AutorepeatEnabled.cs` and `Efl.Ui.IAutorepeat.AutorepeatEnabled.cs`.
You should see both examples appearing in the docs.

Reviewers: lauromoura, vitor.sousa

Reviewed By: vitor.sousa

Subscribers: cedric, #reviewers, #committers

Tags: #efl

Differential Revision: https://phab.enlightenment.org/D8597
This commit is contained in:
Xavi Artigas 2019-04-11 12:40:21 +02:00 committed by Mike Blumenkrantz
parent 5f7be6a3e5
commit 800b931269
3 changed files with 45 additions and 11 deletions

View File

@ -313,12 +313,12 @@ struct documentation_generator
}
template<typename OutputIterator, typename Context>
bool generate_tag_example(OutputIterator sink, std::string const& object_name, Context const& context) const
bool generate_tag_example(OutputIterator sink, std::string const& full_object_name, Context const& context) const
{
auto options = efl::eolian::grammar::context_find_tag<options_context>(context);
// Example embedding not requested
if (options.examples_dir.empty()) return true;
std::string file_name = options.examples_dir + object_name + ".cs";
std::string file_name = options.examples_dir + full_object_name + ".cs";
std::ifstream exfile(file_name);
// There is no example file for this class or method, just return
if (!exfile.good()) return true;
@ -335,6 +335,24 @@ struct documentation_generator
return as_generator("\n").generate(sink, attributes::unused, context);
}
template<typename OutputIterator, typename Context>
bool generate_all_tag_examples(OutputIterator sink, std::string const & full_class_name, std::string const& object_name, Context const& context) const
{
// Take example from derived class
auto derived_klass = efl::eolian::grammar::context_find_tag<class_context>(context);
std::string derived_full_name =
derived_klass.name.empty() ? object_name : derived_klass.name + "." + object_name;
std::string base_full_name =
full_class_name.empty() ? object_name : full_class_name + "." + object_name;
if (!derived_klass.name.empty())
{
if (!generate_tag_example(sink, derived_full_name, context)) return false;
}
if (derived_full_name.compare(base_full_name) == 0) return true;
// Take example from base class
return generate_tag_example(sink, base_full_name, context);
}
// Actual exported generators
template<typename OutputIterator, typename Attribute, typename Context>
bool generate(OutputIterator sink, Attribute const& attr, Context const& context) const
@ -366,9 +384,10 @@ struct documentation_generator
if (!text.empty())
if (!generate_tag_value(sink, text, context)) return false;
std::string managed_name = name_helpers::klass_full_concrete_or_interface_name(prop.klass);
managed_name += "." + name_helpers::property_managed_name(prop);
return generate_tag_example(sink, managed_name, context);
return generate_all_tag_examples(sink,
name_helpers::klass_full_concrete_or_interface_name(prop.klass),
name_helpers::property_managed_name(prop),
context);
}
template<typename OutputIterator, typename Context>
@ -404,7 +423,10 @@ struct documentation_generator
if (!generate_tag_return(sink, func.return_documentation.full_text, context))
return false;
return generate_tag_example(sink, function_conversion(func), context);
return generate_all_tag_examples(sink,
name_helpers::klass_full_concrete_or_interface_name(func.klass),
name_helpers::managed_method_name(func.klass.eolian_name, func.name),
context);
}
template<typename OutputIterator, typename Context>
@ -420,7 +442,10 @@ struct documentation_generator
if (!generate_tag_return(sink, func.return_documentation.full_text, context))
return false;
return generate_tag_example(sink, function_conversion(func), context);
return generate_all_tag_examples(sink,
name_helpers::klass_full_concrete_or_interface_name(func.klass),
name_helpers::managed_method_name(func.klass.eolian_name, func.name),
context);
}
template<typename OutputIterator, typename Context>

View File

@ -20,6 +20,7 @@ struct class_context
variables,
};
wrapper_kind current_wrapper_kind;
std::string name;
};
struct indentation_context

View File

@ -117,7 +117,9 @@ struct klass
// Interface class
if(class_type == "interface")
{
auto iface_cxt = context_add_tag(class_context{class_context::interface}, context);
auto iface_cxt = context_add_tag(class_context{class_context::interface,
name_helpers::klass_full_concrete_or_interface_name(cls)},
context);
if(!as_generator(documentation).generate(sink, cls, iface_cxt))
return false;
@ -195,7 +197,9 @@ struct klass
// Concrete class for interfaces, mixins, etc.
if(class_type != "class" && class_type != "abstract class")
{
auto concrete_cxt = context_add_tag(class_context{class_context::concrete}, context);
auto concrete_cxt = context_add_tag(class_context{class_context::concrete,
name_helpers::klass_full_concrete_or_interface_name(cls)},
context);
auto concrete_name = name_helpers::klass_concrete_name(cls);
auto interface_name = name_helpers::klass_interface_name(cls);
@ -277,7 +281,9 @@ struct klass
// Inheritable class
if(class_type == "class" || class_type == "abstract class")
{
auto inherit_cxt = context_add_tag(class_context{class_context::inherit}, context);
auto inherit_cxt = context_add_tag(class_context{class_context::inherit,
name_helpers::klass_full_concrete_or_interface_name(cls)},
context);
// Class header
if(!as_generator
@ -351,7 +357,9 @@ struct klass
// Native Inherit class
//if(class_type == "class")
{
auto inative_cxt = context_add_tag(class_context{class_context::inherit_native}, context);
auto inative_cxt = context_add_tag(class_context{class_context::inherit_native,
name_helpers::klass_full_concrete_or_interface_name(cls)},
context);
auto native_inherit_name = name_helpers::klass_native_inherit_name(cls);
auto inherit_name = name_helpers::klass_inherit_name(cls);
std::string base_name;