diff options
25 files changed, 544 insertions, 166 deletions
diff --git a/Makefile-giscanner.am b/Makefile-giscanner.am index e3a934ac..bccd8151 100644 --- a/Makefile-giscanner.am +++ b/Makefile-giscanner.am @@ -62,33 +62,42 @@ nobase_dist_template_DATA = \ giscanner/doctemplates/base.tmpl \ giscanner/doctemplates/class.tmpl \ giscanner/doctemplates/namespace.tmpl \ + giscanner/doctemplates/C/callback.tmpl \ giscanner/doctemplates/C/class.tmpl \ giscanner/doctemplates/C/constructor.tmpl \ giscanner/doctemplates/C/default.tmpl \ giscanner/doctemplates/C/enum.tmpl \ giscanner/doctemplates/C/function.tmpl \ + giscanner/doctemplates/C/field.tmpl \ + giscanner/doctemplates/C/interface.tmpl \ giscanner/doctemplates/C/method.tmpl \ giscanner/doctemplates/C/namespace.tmpl \ giscanner/doctemplates/C/property.tmpl \ giscanner/doctemplates/C/record.tmpl \ giscanner/doctemplates/C/signal.tmpl \ giscanner/doctemplates/C/vfunc.tmpl \ + giscanner/doctemplates/Python/callback.tmpl \ giscanner/doctemplates/Python/class.tmpl \ giscanner/doctemplates/Python/constructor.tmpl \ giscanner/doctemplates/Python/default.tmpl \ giscanner/doctemplates/Python/enum.tmpl \ giscanner/doctemplates/Python/function.tmpl \ + giscanner/doctemplates/Python/field.tmpl \ + giscanner/doctemplates/Python/interface.tmpl \ giscanner/doctemplates/Python/method.tmpl \ giscanner/doctemplates/Python/namespace.tmpl \ giscanner/doctemplates/Python/property.tmpl \ giscanner/doctemplates/Python/record.tmpl \ giscanner/doctemplates/Python/signal.tmpl \ giscanner/doctemplates/Python/vfunc.tmpl \ + giscanner/doctemplates/Gjs/callback.tmpl \ giscanner/doctemplates/Gjs/class.tmpl \ giscanner/doctemplates/Gjs/constructor.tmpl \ giscanner/doctemplates/Gjs/default.tmpl \ giscanner/doctemplates/Gjs/enum.tmpl \ giscanner/doctemplates/Gjs/function.tmpl \ + giscanner/doctemplates/Gjs/field.tmpl \ + giscanner/doctemplates/Gjs/interface.tmpl \ giscanner/doctemplates/Gjs/method.tmpl \ giscanner/doctemplates/Gjs/namespace.tmpl \ giscanner/doctemplates/Gjs/property.tmpl \ diff --git a/giscanner/doctemplates/C/callback.tmpl b/giscanner/doctemplates/C/callback.tmpl new file mode 100644 index 00000000..f285ff68 --- /dev/null +++ b/giscanner/doctemplates/C/callback.tmpl @@ -0,0 +1,4 @@ +<%inherit file="./function.tmpl"/> +<%block name="info"> + ${formatter.format_xref(node.parent, type="guide", group=page_kind)} + </%block> diff --git a/giscanner/doctemplates/C/field.tmpl b/giscanner/doctemplates/C/field.tmpl new file mode 100644 index 00000000..b66ae926 --- /dev/null +++ b/giscanner/doctemplates/C/field.tmpl @@ -0,0 +1 @@ +<%inherit file="/base.tmpl"/> diff --git a/giscanner/doctemplates/C/function.tmpl b/giscanner/doctemplates/C/function.tmpl index 8d669438..3f9e6275 100644 --- a/giscanner/doctemplates/C/function.tmpl +++ b/giscanner/doctemplates/C/function.tmpl @@ -6,7 +6,7 @@ <api:type>${formatter.format_type(node.retval.type) | x}</api:type> </api:returns> <api:name>${formatter.format_function_name(node)}</api:name> -% for arg in formatter.get_parameters(node): +% for arg in formatter.get_in_parameters(node): % if arg.type.ctype == '<varargs>': <api:varargs/> % else: @@ -19,12 +19,12 @@ </api:function> </%block> <%block name="synopsis"> -<synopsis><code mime="text/x-csrc"> + <synopsis><code mime="text/x-csrc"> ${node.retval.type.ctype} ${formatter.format_function_name(node)} (\ -% if not formatter.get_parameters(node): +% if not formatter.get_in_parameters(node): void\ % else: -% for ix, arg in enumerate(formatter.get_parameters(node)): +% for ix, arg in enumerate(formatter.get_in_parameters(node)): % if ix != 0: ${' ' * (len(formatter.format_type(node.retval.type)) + len(formatter.format_function_name(node)) + 3)}\ % endif @@ -33,18 +33,17 @@ ${' ' * (len(formatter.format_type(node.retval.type)) + len(formatter.format_fun % else: ${formatter.format_type(arg.type) | x} ${arg.argname}\ % endif -% if ix != len(formatter.get_parameters(node)) - 1: +% if ix != len(formatter.get_in_parameters(node)) - 1: , % endif % endfor % endif ); -</code></synopsis> -</%block> + </code></synopsis></%block> <%block name="details"> -% if formatter.get_parameters(node) or node.retval: +% if formatter.get_in_parameters(node) or node.retval: <terms> -% for arg in formatter.get_parameters(node): +% for arg in formatter.get_in_parameters(node): <item> <title><code>${arg.argname}</code></title> ${formatter.format(node, arg.doc)} diff --git a/giscanner/doctemplates/C/interface.tmpl b/giscanner/doctemplates/C/interface.tmpl new file mode 100644 index 00000000..3f18b021 --- /dev/null +++ b/giscanner/doctemplates/C/interface.tmpl @@ -0,0 +1,2 @@ +<%! page_type="guide" %>\ +<%inherit file="/class.tmpl"/> diff --git a/giscanner/doctemplates/Gjs/callback.tmpl b/giscanner/doctemplates/Gjs/callback.tmpl new file mode 100644 index 00000000..d7b97794 --- /dev/null +++ b/giscanner/doctemplates/Gjs/callback.tmpl @@ -0,0 +1,27 @@ +<%inherit file="/base.tmpl"/> +<%block name="synopsis"> + <synopsis><code mime="text/x-gjs"> +function on${node.name}(\ +${', '.join('%s: %s' % (arg.argname, formatter.format_type(arg.type, True)) for arg in formatter.get_in_parameters(node))}\ +): ${formatter.format_out_parameters(node)} { +} + </code></synopsis></%block> +<%block name="details"> +% if formatter.has_any_parameters(node): +<terms> +% for arg in formatter.get_in_parameters(node): +<item> +<title><code>${arg.argname}</code></title> +${formatter.format(node, arg.doc)} +</item> +% endfor +% for arg in formatter.get_out_parameters(node): +<item> +<title><code>${(arg.argname + ' (out)') if arg.direction == 'inout' else arg.argname}</code></title> +${formatter.format(node, arg.doc)} +</item> +% endfor +</terms> +% endif +</%block> + diff --git a/giscanner/doctemplates/Gjs/class.tmpl b/giscanner/doctemplates/Gjs/class.tmpl index 887c646b..d8433704 100644 --- a/giscanner/doctemplates/Gjs/class.tmpl +++ b/giscanner/doctemplates/Gjs/class.tmpl @@ -3,16 +3,19 @@ <synopsis><code> const ${namespace.name} = imports.gi.${namespace.name}; -let ${formatter.to_underscores(node.name).lower()} = new ${namespace.name}.${node.name}(\ +let ${formatter.to_lower_camel_case(node.name)} = new ${namespace.name}.${node.name}(\ +% if isinstance(node, (ast.Class, ast.Interface)): % if len(node.properties) > 0: { % for ix, property_ in enumerate(node.properties): -% if property_.construct or property_.construct_only or property_.writable: +% if (property_.construct or property_.construct_only) and property_.writable: <link xref='${namespace.name}.${node.name}-${property_.name}'>${property_.name.replace('-', '_')}</link>: value, % endif % endfor }\ % endif +% else: +${formatter.format_gboxed_constructor(node)}\ +% endif ); - </code></synopsis> -</%block> + </code></synopsis></%block> diff --git a/giscanner/doctemplates/Gjs/field.tmpl b/giscanner/doctemplates/Gjs/field.tmpl new file mode 100644 index 00000000..dda82469 --- /dev/null +++ b/giscanner/doctemplates/Gjs/field.tmpl @@ -0,0 +1,9 @@ +<%inherit file="/base.tmpl"/> +<%block name="info"> + ${formatter.format_xref(node.parent, type="guide", group=page_kind)} + <title type="link" role="topic">${node.name}</title> +</%block> +<%block name="synopsis"> + <synopsis><code mime="text/x-gjs"> +${node.parent.name}.${formatter.to_underscores(node)}: ${formatter.format_type(node.type, True)} (${formatter.format_property_flags(node)}) + </code></synopsis></%block> diff --git a/giscanner/doctemplates/Gjs/function.tmpl b/giscanner/doctemplates/Gjs/function.tmpl index e0fd9612..012978ac 100644 --- a/giscanner/doctemplates/Gjs/function.tmpl +++ b/giscanner/doctemplates/Gjs/function.tmpl @@ -6,7 +6,7 @@ <api:type>${formatter.format_type(node.retval.type) | x}</api:type> </api:returns> <api:name>${node.symbol}</api:name> -% for arg in formatter.get_parameters(node): +% for arg in formatter.get_in_parameters(node): % if arg.type.ctype == '<varargs>': <api:varargs/> % else: @@ -19,30 +19,29 @@ </api:function> </%block> <%block name="synopsis"> -<synopsis><code mime="text/x-gjs"> + <synopsis><code mime="text/x-gjs"> function \ ${node.name}(\ -${', '.join('%s:%s' % (arg.argname, formatter.format_type(arg.type)) for arg in formatter.get_parameters(node))}\ -):${formatter.format_type(node.retval.type)} { +${', '.join('%s: %s' % (arg.argname, formatter.format_type(arg.type, True)) for arg in formatter.get_in_parameters(node))}\ +): ${formatter.format_out_parameters(node)} { // Gjs wrapper for ${node.symbol}() } -</code></synopsis> -</%block> + </code></synopsis></%block> <%block name="details"> -% if formatter.get_parameters(node) or node.retval: +% if formatter.has_any_parameters(node): <terms> -% for arg in formatter.get_parameters(node): +% for arg in formatter.get_in_parameters(node): <item> <title><code>${arg.argname}</code></title> ${formatter.format(node, arg.doc)} </item> % endfor -% if node.retval and node.retval.type.ctype != 'void': +% for arg in formatter.get_out_parameters(node): <item> -<title><code>Returns</code></title> -${formatter.format(node, node.retval.doc)} +<title><code>${(arg.argname + ' (out)') if arg.direction == 'inout' else arg.argname}</code></title> +${formatter.format(node, arg.doc)} </item> -% endif +% endfor </terms> % endif </%block> diff --git a/giscanner/doctemplates/Gjs/interface.tmpl b/giscanner/doctemplates/Gjs/interface.tmpl new file mode 100644 index 00000000..2f01f20f --- /dev/null +++ b/giscanner/doctemplates/Gjs/interface.tmpl @@ -0,0 +1,17 @@ +<%inherit file="/class.tmpl"/> +<%block name="synopsis"> + <synopsis><code> +const ${namespace.name} = imports.gi.${namespace.name}; + +let ${formatter.to_underscores(node).lower()} = new ${namespace.name}.${node.name}(\ +% if len(node.properties) > 0: +{ +% for ix, property_ in enumerate(node.properties): +% if (property_.construct or property_.construct_only) and property_.writable: + <link xref='${namespace.name}.${node.name}-${property_.name}'>${property_.name.replace('-', '_')}</link>: value, +% endif +% endfor +}\ +% endif +); + </code></synopsis></%block> diff --git a/giscanner/doctemplates/Gjs/property.tmpl b/giscanner/doctemplates/Gjs/property.tmpl index 3316a00c..dda82469 100644 --- a/giscanner/doctemplates/Gjs/property.tmpl +++ b/giscanner/doctemplates/Gjs/property.tmpl @@ -4,7 +4,6 @@ <title type="link" role="topic">${node.name}</title> </%block> <%block name="synopsis"> -<synopsis><code mime="text/x-python"> -"${node.name}" ${formatter.format_type(node.type)} : ${formatter.format_property_flags(node)} -</code></synopsis> -</%block> + <synopsis><code mime="text/x-gjs"> +${node.parent.name}.${formatter.to_underscores(node)}: ${formatter.format_type(node.type, True)} (${formatter.format_property_flags(node)}) + </code></synopsis></%block> diff --git a/giscanner/doctemplates/Gjs/signal.tmpl b/giscanner/doctemplates/Gjs/signal.tmpl index 084d9743..7c508162 100644 --- a/giscanner/doctemplates/Gjs/signal.tmpl +++ b/giscanner/doctemplates/Gjs/signal.tmpl @@ -4,21 +4,22 @@ <title type="link" role="topic">${node.name}</title> </%block> <%block name="synopsis"> -<synopsis><code mime="text/x-python"> -function callback(${formatter.to_underscores(node.parent.name).lower()}, \ -% for arg in formatter.get_parameters(node): -${arg.argname}:${formatter.format_type(arg.type)}, \ + <synopsis><code mime="text/x-gjs"> +connect('${node.name}', function (${formatter.to_lower_camel_case(node.parent.name)}, \ +% for arg in formatter.get_in_parameters(node): +% if arg.type.target_fundamental != 'none': +${arg.argname}: ${formatter.format_type(arg.type, True)}, \ +% endif % endfor -):${formatter.format_type(node.retval.type)}; -</code></synopsis> -</%block> +): ${formatter.format_type(node.retval.type, True)}); + </code></synopsis></%block> <%block name="details"> <terms> <item> -<title><code>${formatter.to_underscores(node.parent.name).lower()}</code></title> +<title><code>${formatter.to_lower_camel_case(node.parent.name)}</code></title> <p>instance of ${formatter.format_xref(node.parent)} that is emitting the signal</p> </item> -% for arg in formatter.get_parameters(node): +% for arg in formatter.get_in_parameters(node): <item> <title><code>${arg.argname}</code></title> ${formatter.format(node, arg.doc)} diff --git a/giscanner/doctemplates/Gjs/vfunc.tmpl b/giscanner/doctemplates/Gjs/vfunc.tmpl index 1cbe511c..2bd1127d 100644 --- a/giscanner/doctemplates/Gjs/vfunc.tmpl +++ b/giscanner/doctemplates/Gjs/vfunc.tmpl @@ -1,16 +1,15 @@ <%inherit file="/base.tmpl"/> <%block name="synopsis"> -<synopsis><code mime="text/x-gjs"> + <synopsis><code mime="text/x-gjs"> function vfunc_${node.name}(\ -${', '.join('%s:%s' % (arg.argname, formatter.format_type(arg.type)) for arg in formatter.get_parameters(node))}\ -):${formatter.format_type(node.retval.type)} { +${', '.join('%s: %s' % (arg.argname, formatter.format_type(arg.type, True)) for arg in formatter.get_in_parameters(node))}\ +): ${formatter.format_out_parameters(node)} { } -</code></synopsis> -</%block> + </code></synopsis></%block> <%block name="details"> -% if formatter.get_parameters(node) or node.retval: +% if formatter.get_in_parameters(node) or node.retval: <terms> -% for arg in formatter.get_parameters(node): +% for arg in formatter.get_in_parameters(node): <item> <title><code>${arg.argname}</code></title> ${formatter.format(node, arg.doc)} @@ -25,3 +24,4 @@ ${formatter.format(node, node.retval.doc)} </terms> % endif </%block> + diff --git a/giscanner/doctemplates/Python/callback.tmpl b/giscanner/doctemplates/Python/callback.tmpl new file mode 100644 index 00000000..4fcbfe3b --- /dev/null +++ b/giscanner/doctemplates/Python/callback.tmpl @@ -0,0 +1,27 @@ +<%inherit file="/base.tmpl"/> +<%block name="synopsis"> + <synopsis><code mime="text/x-python"> +% if formatter.get_in_parameters(node): +@accepts(${', '.join((formatter.format_type(arg.type) for arg in formatter.get_in_parameters(node)))}) +% endif +@returns(${formatter.format_type(node.retval.type) | x}) +def on_${node.name}(${', '.join((arg.argname for arg in formatter.get_in_parameters(node)))}): + </code></synopsis></%block> +<%block name="details"> +% if formatter.get_in_parameters(node) or node.retval: +<terms> +% for arg in formatter.get_in_parameters(node): +<item> +<title><code>${arg.argname}</code></title> +${formatter.format(node, arg.doc)} +</item> +% endfor +% if node.retval and node.retval.type.ctype != 'void': +<item> +<title><code>Returns</code></title> +${formatter.format(node, node.retval.doc)} +</item> +% endif +</terms> +% endif +</%block> diff --git a/giscanner/doctemplates/Python/class.tmpl b/giscanner/doctemplates/Python/class.tmpl index 435b31a5..51d25a91 100644 --- a/giscanner/doctemplates/Python/class.tmpl +++ b/giscanner/doctemplates/Python/class.tmpl @@ -3,7 +3,8 @@ <synopsis><code> from gi.repository import ${namespace.name} -${formatter.to_underscores(node.name).lower()} = ${namespace.name}.${node.name}(\ +${formatter.to_underscores(node).lower()} = ${namespace.name}.${node.name}(\ +% if isinstance(node, (ast.Class, ast.Interface)): % for ix, property_ in enumerate(node.properties): % if property_.construct or property_.construct_only or property_.writable: <link xref='${namespace.name}.${node.name}-${property_.name}'>${property_.name.replace('-', '_')}</link>=value\ @@ -12,6 +13,6 @@ ${formatter.to_underscores(node.name).lower()} = ${namespace.name}.${node.name}( % endif % endif % endfor -)\ - </code></synopsis> -</%block> +% endif +) + </code></synopsis></%block> diff --git a/giscanner/doctemplates/Python/field.tmpl b/giscanner/doctemplates/Python/field.tmpl new file mode 100644 index 00000000..b66ae926 --- /dev/null +++ b/giscanner/doctemplates/Python/field.tmpl @@ -0,0 +1 @@ +<%inherit file="/base.tmpl"/> diff --git a/giscanner/doctemplates/Python/function.tmpl b/giscanner/doctemplates/Python/function.tmpl index 072a1185..7ad1ac04 100644 --- a/giscanner/doctemplates/Python/function.tmpl +++ b/giscanner/doctemplates/Python/function.tmpl @@ -6,7 +6,7 @@ <api:type>${formatter.format_type(node.retval.type) | x}</api:type> </api:returns> <api:name>${node.symbol}</api:name> -% for arg in formatter.get_parameters(node): +% for arg in formatter.get_in_parameters(node): % if arg.type.ctype == '<varargs>': <api:varargs/> % else: @@ -19,24 +19,18 @@ </api:function> </%block> <%block name="synopsis"> -<synopsis><code mime="text/x-python"> -% if formatter.get_parameters(node): -@accepts(\ -${', '.join((formatter.format_type(arg.type) for arg in formatter.get_parameters(node)))}\ -) + <synopsis><code mime="text/x-python"> +% if formatter.get_in_parameters(node): +@accepts(${', '.join((formatter.format_type(arg.type) for arg in formatter.get_in_parameters(node)))}) % endif @returns(${formatter.format_type(node.retval.type) | x}) -def \ -${node.name}(\ -${', '.join((formatter.format_parameter_name(node, arg) for arg in formatter.get_parameters(node)))}\ -): +def ${node.name}(${', '.join((formatter.format_parameter_name(node, arg) for arg in formatter.get_in_parameters(node)))}): # Python wrapper for ${node.symbol}() -</code></synopsis> -</%block> + </code></synopsis></%block> <%block name="details"> -% if formatter.get_parameters(node) or node.retval: +% if formatter.get_in_parameters(node) or node.retval: <terms> -% for ix, arg in enumerate(formatter.get_parameters(node)): +% for ix, arg in enumerate(formatter.get_in_parameters(node)): <item> <title><code>${formatter.format_parameter_name(node, arg)}</code></title> ${formatter.format(node, arg.doc)} diff --git a/giscanner/doctemplates/Python/interface.tmpl b/giscanner/doctemplates/Python/interface.tmpl new file mode 100644 index 00000000..b3596a8d --- /dev/null +++ b/giscanner/doctemplates/Python/interface.tmpl @@ -0,0 +1,16 @@ +<%inherit file="/class.tmpl"/> +<%block name="synopsis"> + <synopsis><code> +from gi.repository import ${namespace.name} + +${formatter.to_underscores(node).lower()} = ${namespace.name}.${node.name}(\ +% for ix, property_ in enumerate(node.properties): +% if property_.construct or property_.construct_only or property_.writable: +<link xref='${namespace.name}.${node.name}-${property_.name}'>${property_.name.replace('-', '_')}</link>=value\ +% if ix != len(node.properties) - 1: +, \ +% endif +% endif +% endfor +)\ + </code></synopsis></%block> diff --git a/giscanner/doctemplates/Python/property.tmpl b/giscanner/doctemplates/Python/property.tmpl index 3316a00c..c93d59b7 100644 --- a/giscanner/doctemplates/Python/property.tmpl +++ b/giscanner/doctemplates/Python/property.tmpl @@ -4,7 +4,6 @@ <title type="link" role="topic">${node.name}</title> </%block> <%block name="synopsis"> -<synopsis><code mime="text/x-python"> + <synopsis><code mime="text/x-python"> "${node.name}" ${formatter.format_type(node.type)} : ${formatter.format_property_flags(node)} -</code></synopsis> -</%block> + </code></synopsis></%block> diff --git a/giscanner/doctemplates/Python/signal.tmpl b/giscanner/doctemplates/Python/signal.tmpl index dc931107..c61b7229 100644 --- a/giscanner/doctemplates/Python/signal.tmpl +++ b/giscanner/doctemplates/Python/signal.tmpl @@ -4,21 +4,20 @@ <title type="link" role="topic">${node.name}</title> </%block> <%block name="synopsis"> -<synopsis><code mime="text/x-python"> -def callback(${formatter.to_underscores(node.parent.name).lower()}, \ -% for arg in formatter.get_parameters(node): + <synopsis><code mime="text/x-python"> +def callback(${formatter.to_underscores(node.parent).lower()}, \ +% for arg in formatter.get_in_parameters(node): ${arg.argname}, \ % endfor user_param1, ...) -</code></synopsis> -</%block> + </code></synopsis></%block> <%block name="details"> <terms> <item> -<title><code>${formatter.to_underscores(node.parent.name).lower()}</code></title> +<title><code>${formatter.to_underscores(node.parent).lower()}</code></title> <p>instance of ${formatter.format_xref(node.parent)} that is emitting the signal</p> </item> -% for arg in formatter.get_parameters(node): +% for arg in formatter.get_in_parameters(node): <item> <title><code>${arg.argname}</code></title> ${formatter.format(node, arg.doc)} diff --git a/giscanner/doctemplates/Python/vfunc.tmpl b/giscanner/doctemplates/Python/vfunc.tmpl index 98a30932..2c532e70 100644 --- a/giscanner/doctemplates/Python/vfunc.tmpl +++ b/giscanner/doctemplates/Python/vfunc.tmpl @@ -1,22 +1,16 @@ <%inherit file="/base.tmpl"/> <%block name="synopsis"> -<synopsis><code mime="text/x-python"> -% if formatter.get_parameters(node): -@accepts(\ -${', '.join((formatter.format_type(arg.type) for arg in formatter.get_parameters(node)))}\ -) + <synopsis><code mime="text/x-python"> +% if formatter.get_in_parameters(node): +@accepts(${', '.join((formatter.format_type(arg.type) for arg in formatter.get_in_parameters(node)))}) % endif @returns(${formatter.format_type(node.retval.type) | x}) -def \ -do_${node.name}(\ -${', '.join((arg.argname for arg in formatter.get_parameters(node)))}\ -): -</code></synopsis> -</%block> +def do_${node.name}(${', '.join((arg.argname for arg in formatter.get_in_parameters(node)))}): + </code></synopsis></%block> <%block name="details"> -% if formatter.get_parameters(node) or node.retval: +% if formatter.get_in_parameters(node) or node.retval: <terms> -% for arg in formatter.get_parameters(node): +% for arg in formatter.get_in_parameters(node): <item> <title><code>${arg.argname}</code></title> ${formatter.format(node, arg.doc)} diff --git a/giscanner/doctemplates/base.tmpl b/giscanner/doctemplates/base.tmpl index 78980773..7a1d8db2 100644 --- a/giscanner/doctemplates/base.tmpl +++ b/giscanner/doctemplates/base.tmpl @@ -6,24 +6,15 @@ xmlns="http://projectmallard.org/1.0/" xmlns:api="http://projectmallard.org/experimental/api/" xmlns:ui="http://projectmallard.org/1.0/ui/"> - <info> - <%block name="info"> - ${formatter.format_xref(node.parent, type="guide", group=page_kind)} - </%block> + <info><%block name="info"> + ${formatter.format_xref(node.parent, type="guide", group=page_kind)} +</%block>\ </info> - <title><%block name="title">${formatter.format_page_name(node)}</%block></title> - <%block name="synopsis"> - </%block> - <%block name="doc"> - ${formatter.format(node, node.doc)} - </%block> - <%block name="since_version"> - % if node.version: - <p>Since ${node.version}</p> - % endif - </%block> - <%block name="details"> - </%block> - <%block name="links"> - </%block> + <title><%block name="title">${formatter.format_page_name(node)}</%block></title><%block name="synopsis"></%block><%block name="doc"> +${formatter.format(node, node.doc)} +</%block><%block name="since_version">\ +% if node.version: + <p>Since ${node.version}</p>\ +% endif +</%block><%block name="details"></%block><%block name="links"></%block> </page> diff --git a/giscanner/doctemplates/class.tmpl b/giscanner/doctemplates/class.tmpl index 7f8b6869..86333866 100644 --- a/giscanner/doctemplates/class.tmpl +++ b/giscanner/doctemplates/class.tmpl @@ -1,6 +1,7 @@ <%! page_type="guide" %>\ <%inherit file="/base.tmpl"/> <%block name="details"> +% if isinstance(node, ast.Class): <synopsis> <title>Hierarchy</title> <tree> @@ -13,8 +14,23 @@ % endfor </tree> </synopsis> +% elif isinstance(node, ast.Interface): + <synopsis> + <title>Prerequisites</title> + <p>${node.name} requires ${formatter.format_prerequisites(node)}</p> + </synopsis> + <synopsis> + <title>Known Implementations</title> + <p>${formatter.format_known_implementations(node)}</p> + </synopsis> +% endif </%block> -<%block name="links"> +<%block name="links">\ + <links type="topic" ui:expanded="true" + api:type="function" api:mime="${formatter.mime_type}" + groups="constructor" style="linklist"> + <title>Constructors</title> + </links> <links type="topic" ui:expanded="true" api:type="function" api:mime="${formatter.mime_type}" groups="method" style="linklist"> @@ -23,8 +39,9 @@ <links type="topic" ui:expanded="true" api:type="function" api:mime="${formatter.mime_type}" groups="function" style="linklist"> - <title>Functions</title> + <title>Static Functions</title> </links> +% if isinstance(node, (ast.Class, ast.Interface)): <links type="topic" ui:expanded="true" groups="property" style="linklist"> <title>Properties</title> </links> @@ -34,7 +51,11 @@ <links type="topic" ui:expanded="true" groups="vfunc" style="linklist"> <title>Virtual functions</title> </links> +% endif + <links type="topic" ui:expanded="true" groups="field" style="linklist"> + <title>Fields</title> + </links> <links type="topic" ui:expanded="true" groups="#first #default #last" style="linklist"> <title>Other</title> - </links> + </links>\ </%block> diff --git a/giscanner/doctemplates/namespace.tmpl b/giscanner/doctemplates/namespace.tmpl index bb58bb16..d4edcec0 100644 --- a/giscanner/doctemplates/namespace.tmpl +++ b/giscanner/doctemplates/namespace.tmpl @@ -1,11 +1,9 @@ <%! page_type="guide" %>\ <%inherit file="/base.tmpl"/> -<%block name="doc"> -</%block> -<%block name="info"> -</%block> +<%block name="doc"></%block> +<%block name="info"></%block> <%block name="links"> - <links type="topic" ui:expanded="true" groups="class" style="linklist"> + <links type="topic" ui:expanded="true" groups="class interface" style="linklist"> <title>Classes</title> </links> <links type="topic" ui:expanded="true" groups="function" style="linklist"> @@ -15,5 +13,4 @@ <title>Other</title> </links> </%block> -<%block name="since_version"> -</%block> +<%block name="since_version"></%block> diff --git a/giscanner/docwriter.py b/giscanner/docwriter.py index a4c817e9..75a2b03b 100644 --- a/giscanner/docwriter.py +++ b/giscanner/docwriter.py @@ -47,7 +47,7 @@ def make_page_id(node, recursive=False): if parent is None: return '%s.%s' % (node.namespace.name, node.name) - if isinstance(node, (ast.Property, ast.Signal, ast.VFunction)): + if isinstance(node, (ast.Property, ast.Signal, ast.VFunction, ast.Field)): return '%s-%s' % (make_page_id(parent, recursive=True), node.name) else: return '%s.%s' % (make_page_id(parent, recursive=True), node.name) @@ -56,8 +56,10 @@ def make_page_id(node, recursive=False): def get_node_kind(node): if isinstance(node, ast.Namespace): node_kind = 'namespace' - elif isinstance(node, (ast.Class, ast.Interface)): + elif isinstance(node, (ast.Class, ast.Boxed, ast.Compound)): node_kind = 'class' + elif isinstance(node, ast.Interface): + node_kind = 'interface' elif isinstance(node, ast.Record): node_kind = 'record' elif isinstance(node, ast.Function): @@ -75,6 +77,10 @@ def get_node_kind(node): node_kind = 'signal' elif isinstance(node, ast.VFunction) and node.parent is not None: node_kind = 'vfunc' + elif isinstance(node, ast.Callable): + node_kind = 'callback' + elif isinstance(node, ast.Field): + node_kind = 'field' else: node_kind = 'default' @@ -170,9 +176,6 @@ class DocFormatter(object): return saxutils.escape(text) def should_render_node(self, node): - if isinstance(node, ast.Constant): - return False - if getattr(node, "private", False): return False @@ -184,7 +187,7 @@ class DocFormatter(object): result = '' for para in doc.split('\n\n'): - result += '<p>' + result += ' <p>' result += self.format_inline(node, para) result += '</p>' return result @@ -295,7 +298,7 @@ class DocFormatter(object): return dispatch[kind](node, match, props) - def get_parameters(self, node): + def get_in_parameters(self, node): raise NotImplementedError def format_inline(self, node, para): @@ -312,12 +315,12 @@ class DocFormatter(object): def format_function_name(self, func): raise NotImplementedError - def format_type(self, type_): + def format_type(self, type_, link=False): raise NotImplementedError def format_page_name(self, node): if isinstance(node, ast.Namespace): - return 'Index' + return node.name elif isinstance(node, ast.Function): return self.format_function_name(node) elif isinstance(node, ast.Property) and node.parent is not None: @@ -326,6 +329,8 @@ class DocFormatter(object): return '%s::%s' % (self.format_page_name(node.parent), node.name) elif isinstance(node, ast.VFunction) and node.parent is not None: return '%s::%s' % (self.format_page_name(node.parent), node.name) + elif isinstance(node, ast.Field) and node.parent is not None: + return '%s->%s' % (self.format_page_name(node.parent), node.name) else: return make_page_id(node) @@ -340,25 +345,46 @@ class DocFormatter(object): attrs = [('xref', make_page_id(node))] + attrdict.items() return xmlwriter.build_xml_tag('link', attrs) + def field_is_writable(self, field): + return True + def format_property_flags(self, property_, construct_only=False): flags = [] + if property_.readable and not construct_only: flags.append("Read") - if property_.writable and not construct_only: + if property_.writable and not construct_only and \ + self.field_is_writable(property_): flags.append("Write") - if property_.construct: - flags.append("Construct") - if property_.construct_only: - flags.append("Construct Only") + if isinstance(property_, ast.Property): + if property_.construct: + flags.append("Construct") + if property_.construct_only: + flags.append("Construct Only") return " / ".join(flags) - def to_underscores(self, string): - return to_underscores(string) + def to_underscores(self, node): + if isinstance(node, ast.Property): + return node.name.replace('-', '_') + elif node.name: + return to_underscores(node.name) + elif isinstance(node, ast.Callback): + return 'callback' + elif isinstance(node, ast.Union): + return 'anonymous_union' + elif isinstance(node, ast.Field): + return 'anonymous field' + else: + raise Exception('invalid node') + + def to_lower_camel_case(self, string): + return string[0].lower() + string[1:] def get_class_hierarchy(self, node): - parent_chain = [node] + assert isinstance(node, ast.Class) + parent_chain = [node] while node.parent_type: node = self._transformer.lookup_typenode(node.parent_type) parent_chain.append(node) @@ -366,6 +392,42 @@ class DocFormatter(object): parent_chain.reverse() return parent_chain + def format_prerequisites(self, node): + assert isinstance(node, ast.Interface) + + if len(node.prerequisites) > 0: + if len(node.prerequisites) > 1: + return ', '.join(node.prerequisites[:-1]) + \ + ' and ' + node.prerequisites[-1] + else: + return node.prerequisites[0] + else: + return 'GObject.Object' + + def format_known_implementations(self, node): + assert isinstance(node, ast.Interface) + + node_name = node.namespace.name + '.' + node.name + impl = [] + + for c in node.namespace.itervalues(): + if not isinstance(c, ast.Class): + continue + for implemented in c.interfaces: + if implemented.target_giname == node_name: + impl.append(c) + break + + if len(impl) == 0: + return 'None' + else: + out = '%s is implemented by ' % (node.name,) + if len(impl) == 1: + return out + impl[0].name + else: + return out + ', '.join(i.name for i in impl[:-1]) + \ + ' and ' + impl[-1].name + class DocFormatterC(DocFormatter): language = "C" @@ -377,7 +439,7 @@ class DocFormatterC(DocFormatter): "NULL": "NULL", } - def format_type(self, type_): + def format_type(self, type_, link=False): if isinstance(type_, ast.Array): return self.format_type(type_.element_type) + '*' elif type_.ctype is not None: @@ -394,7 +456,7 @@ class DocFormatterC(DocFormatter): else: return func.name - def get_parameters(self, node): + def get_in_parameters(self, node): return node.all_parameters @@ -466,7 +528,7 @@ class DocFormatterPython(DocFormatterIntrospectableBase): return fundamental_types.get(name, name) - def format_type(self, type_): + def format_type(self, type_, link=False): if isinstance(type_, (ast.List, ast.Array)): return '[' + self.format_type(type_.element_type) + ']' elif isinstance(type_, ast.Map): @@ -483,7 +545,7 @@ class DocFormatterPython(DocFormatterIntrospectableBase): else: return func.name - def get_parameters(self, node): + def get_in_parameters(self, node): return node.all_parameters @@ -506,61 +568,155 @@ class DocFormatterGjs(DocFormatterIntrospectableBase): return False + def resolve_gboxed_constructor(self, node): + zero_args_constructor = None + default_constructor = None + + for c in node.constructors: + if zero_args_constructor is None and \ + len(c.parameters) == 0: + zero_args_constructor = c + if default_constructor is None and \ + c.name == 'new': + default_constructor = c + if default_constructor is None: + default_constructor = zero_args_constructor + if default_constructor is None and \ + len(node.constructors) > 0: + default_constructor = node.constructors[0] + + node.gjs_default_constructor = default_constructor + node.gjs_zero_args_constructor = zero_args_constructor + + def should_render_node(self, node): + if isinstance(node, (ast.Compound, ast.Boxed)): + self.resolve_gboxed_constructor(node) + + if isinstance(node, ast.ErrorQuarkFunction): + return False + if isinstance(node, ast.Field): + if node.type is None: + return False + if isinstance(node.parent, ast.Class): + return False + if isinstance(node, ast.Union) and node.name is None: + return False + if isinstance(node, ast.Class): + is_gobject = False + parent = node + while parent: + if parent.namespace.name == 'GObject' and \ + parent.name == 'Object': + is_gobject = True + break + if not parent.parent_type: + break + parent = self._transformer.lookup_typenode(parent.parent_type) + is_gparam = node.namespace.name == 'GObject' and \ + node.name == 'ParamSpec' + if not is_gobject and not is_gparam: + return False + if isinstance(node, ast.Function) and node.is_constructor: + parent = node.parent + if isinstance(parent, (ast.Compound, ast.Boxed)): + if node == parent.gjs_default_constructor: + return False + if isinstance(parent, ast.Class): + return False + + return super(DocFormatterGjs, self).should_render_node(node) + def format_fundamental_type(self, name): fundamental_types = { + "none": "void", + "gpointer": "void", + "gboolean": "Boolean", + "gint8": "Number(gint8)", + "guint8": "Number(guint8)", + "gint16": "Number(gint16)", + "guint16": "Number(guint16)", + "gint32": "Number(gint32)", + "guint32": "Number(guint32)", + "gchar": "Number(gchar)", + "guchar": "Number(guchar)", + "gshort": "Number(gshort)", + "gint": "Number(gint)", + "guint": "Number(guint)", + "gfloat": "Number(gfloat)", + "gdouble": "Number(gdouble)", "utf8": "String", "gunichar": "String", - "gchar": "String", - "guchar": "String", - "gboolean": "Boolean", - "gint": "Number", - "guint": "Number", - "glong": "Number", - "gulong": "Number", - "gint64": "Number", - "guint64": "Number", - "gfloat": "Number", - "gdouble": "Number", - "gchararray": "String", - "GParam": "GLib.Param", - "PyObject": "Object", - "GStrv": "[String]", - "GVariant": "GLib.Variant"} + "filename": "String", + "GType": "GObject.Type", + "GVariant": "GLib.Variant", + # These cannot be fully represented in gjs + "gsize": "Number(gsize)", + "gssize": "Number(gssize)", + "gintptr": "Number(gintptr)", + "guintptr": "Number(guintptr)", + "glong": "Number(glong)", + "gulong": "Number(gulong)", + "gint64": "Number(gint64)", + "guint64": "Number(guint64)", + "long double": "Number(long double)", + "long long": "Number(long long)", + "unsigned long long": "Number(unsigned long long)"} return fundamental_types.get(name, name) - def format_type(self, type_): + def format_type(self, type_, link=False): if isinstance(type_, (ast.List, ast.Array)): - return '[' + self.format_type(type_.element_type) + ']' + return 'Array(' + self.format_type(type_.element_type, link) + ')' elif isinstance(type_, ast.Map): - return '{%s: %s}' % (self.format_type(type_.key_type), - self.format_type(type_.value_type)) - elif type_.target_fundamental == "none": + return '{%s: %s}' % (self.format_type(type_.key_type, link), + self.format_type(type_.value_type, link)) + elif not type_ or type_.target_fundamental == "none": return "void" elif type_.target_giname is not None: - return type_.target_giname + giname = type_.target_giname + if link: + nsname = self._transformer.namespace.name + if giname.startswith(nsname + '.'): + return '<link xref="%s">%s</link>' % (giname, giname) + else: + resolved = self._transformer.lookup_typenode(type_) + if resolved: + ns = resolved.namespace + return '<link href="../%s-%s/%s.page">%s</link>' % \ + (ns.name, str(ns.version), giname, giname) + return giname else: return self.format_fundamental_type(type_.target_fundamental) def format_function_name(self, func): if func.is_method: return "%s.prototype.%s" % (self.format_page_name(func.parent), func.name) - elif func.is_constructor: + elif func.parent is not None: return "%s.%s" % (self.format_page_name(func.parent), func.name) else: return func.name - def get_parameters(self, node): - skip = [] + def format_page_name(self, node): + if isinstance(node, (ast.Field, ast.Property)): + return '%s.%s' % (self.format_page_name(node.parent), self.to_underscores(node)) + else: + return DocFormatterIntrospectableBase.format_page_name(self, node) + + def has_any_parameters(self, node): + return len(node.parameters) > 0 or \ + node.retval.type.target_fundamental != 'none' + + def get_in_parameters(self, node): + skip = set() for param in node.parameters: if param.direction == ast.PARAM_DIRECTION_OUT: - skip.append(param) + skip.add(param) if param.closure_name is not None: - skip.append(node.get_parameter(param.closure_name)) + skip.add(node.get_parameter(param.closure_name)) if param.destroy_name is not None: - skip.append(node.get_parameter(param.destroy_name)) + skip.add(node.get_parameter(param.destroy_name)) if isinstance(param.type, ast.Array) and param.type.length_param_name is not None: - skip.append(node.get_parameter(param.type.length_param_name)) + skip.add(node.get_parameter(param.type.length_param_name)) params = [] for param in node.parameters: @@ -568,6 +724,109 @@ class DocFormatterGjs(DocFormatterIntrospectableBase): params.append(param) return params + def get_out_parameters(self, node): + skip = set() + for param in node.parameters: + if param.direction == ast.PARAM_DIRECTION_IN: + skip.add(param) + if param.closure_name is not None: + skip.add(node.get_parameter(param.closure_name)) + if param.destroy_name is not None: + skip.add(node.get_parameter(param.destroy_name)) + if isinstance(param.type, ast.Array) and param.type.length_param_name is not None: + skip.add(node.get_parameter(param.type.length_param_name)) + + params = [] + if node.retval.type.target_fundamental != 'none': + name = 'return_value' + if node.retval.type.target_fundamental == 'gboolean': + name = 'ok' + + params.append(ast.Parameter(name, node.retval.type, + ast.PARAM_DIRECTION_OUT)) + for param in node.parameters: + if param not in skip: + params.append(param) + + if len(params) == 1 and params[0].argname == 'return_value': + params[0].argname = 'Returns' + + return params + + def format_in_parameters(self, node): + in_params = self.get_in_parameters(node) + return ', '.join(('%s: %s' % (p.argname, self.format_type(p.type, True))) + for p in in_params) + + def format_out_parameters(self, node): + out_params = self.get_out_parameters(node) + + if len(out_params) == 0: + return 'void' + elif len(out_params) == 1: + return self.format_type(out_params[0].type, True) + else: + return '[' + ', '.join(('%s: %s' % (p.argname, self.format_type(p.type, True))) + for p in out_params) + ']' + + def field_is_writable(self, node): + if isinstance(node, ast.Field): + if node.type is None: + return False + if node.private: + return False + if node.type.target_fundamental not in \ + (None, 'none', 'gpointer', 'utf8', 'filename', 'va_list'): + return True + + resolved = self._transformer.lookup_typenode(node.type) + if resolved: + if isinstance(resolved, ast.Compound) and node.type.ctype[-1] != '*': + return self._struct_is_simple(resolved) + elif isinstance(resolved, ast.Enum): + return True + return False + else: + return True + + def _struct_is_simple(self, node): + for f in node.fields: + if not self.field_is_writable(f): + return False + return True + + def format_gboxed_constructor(self, node): + if node.namespace.name == 'GLib' and node.name == 'Variant': + return 'signature: String, value: Any' + + zero_args_constructor = node.gjs_default_constructor + default_constructor = node.gjs_zero_args_constructor + + can_allocate = zero_args_constructor is not None + if not can_allocate and isinstance(node, ast.Record): + can_allocate = self._struct_is_simple(node) + + # Small lie: if can_allocate is False, and + # default_constructor is None, then you cannot + # construct the boxed in any way. But let's + # pretend you can with the regular constructor + if can_allocate or default_constructor is None: + if isinstance(node, ast.Compound): + fields = filter(self.field_is_writable, node.fields) + out = '' + if len(fields) > 0: + out += "{\n" + for f in fields: + out += " <link xref='%s.%s-%s'>%s</link>: value\n" % \ + (node.namespace.name, node.name, f.name, f.name) + out += "}" + return out + else: + return '' + else: + construct_params = self.get_in_parameters(default_constructor) + return ', '.join(('%s: %s' % (p.argname, self.format_type(p.type))) + for p in construct_params) LANGUAGES = { "c": DocFormatterC, @@ -620,6 +879,14 @@ class DocWriter(object): return False if self._formatter.should_render_node(node): self._render_node(node, chain, output) + + # hack: fields are not Nodes in the ast, so we don't + # see them in the visit. Handle them manually here + if isinstance(node, (ast.Compound, ast.Class)): + chain.append(node) + for f in node.fields: + self._walk_node(output, f, chain) + chain.pop() return True return False @@ -638,7 +905,8 @@ class DocWriter(object): node=node, page_id=page_id, page_kind=page_kind, - formatter=self._formatter) + formatter=self._formatter, + ast=ast) output_file_name = os.path.join(os.path.abspath(output), page_id + '.page') |