From a1ec815afd2dd4379ce443efbb4d4aca4cf97c33 Mon Sep 17 00:00:00 2001 From: "Jasper St. Pierre" Date: Wed, 27 Mar 2013 17:09:16 -0400 Subject: giscanner: Create AST nodes for SECTION: doc blocks; add a GIR node These will eventually be paired with the sections file parser to create a set of sections. --- girepository/girparser.c | 7 +++++++ giscanner/annotationparser.py | 8 ++++++-- giscanner/ast.py | 16 ++++++++++++++++ giscanner/docwriter.py | 2 ++ giscanner/girparser.py | 26 +++++++++++++++++++++++++- giscanner/girwriter.py | 21 +++++++++++++++++++++ giscanner/scannermain.py | 2 ++ giscanner/transformer.py | 24 ++++++++++++++++++++++++ tests/scanner/Regress-1.0-expected.gir | 8 ++++++++ tests/scanner/regress.c | 22 ++++++++++++++++++++++ 10 files changed, 133 insertions(+), 3 deletions(-) diff --git a/girepository/girparser.c b/girepository/girparser.c index 6c768669..fb6a18f1 100644 --- a/girepository/girparser.c +++ b/girepository/girparser.c @@ -3004,6 +3004,13 @@ start_element_handler (GMarkupParseContext *context, goto out; break; + case 's': + if (strcmp (element_name, "section") == 0) + { + state_switch (ctx, STATE_PASSTHROUGH); + goto out; + } + case 'u': if (start_union (context, element_name, attribute_names, attribute_values, diff --git a/giscanner/annotationparser.py b/giscanner/annotationparser.py index afeca9ce..758f606f 100644 --- a/giscanner/annotationparser.py +++ b/giscanner/annotationparser.py @@ -1007,8 +1007,8 @@ class GtkDocCommentBlock(GtkDocAnnotatable): Represents a GTK-Doc comment block. ''' - __slots__ = ('code_before', 'code_after', 'indentation', - 'name', 'params', 'description', 'tags') + __slots__ = ('code_before', 'code_after', 'indentation', 'name', + 'params', 'lower_params', 'description', 'tags') #: Valid annotation names for the GTK-Doc comment block identifier part. valid_annotations = (ANN_ATTRIBUTES, ANN_CONSTRUCTOR, ANN_FOREIGN, ANN_GET_VALUE_FUNC, @@ -1035,6 +1035,9 @@ class GtkDocCommentBlock(GtkDocAnnotatable): #: applied to this :class:`GtkDocCommentBlock`. self.params = OrderedDict() + #: Like params, but all of its keys are in lower-case. + self.lower_params = OrderedDict() + #: The GTK-Doc comment block description part. self.description = None @@ -1405,6 +1408,7 @@ class GtkDocCommentBlockParser(object): parameter.description = result.description comment_block.params[param_name] = parameter + comment_block.lower_params[param_name.lower()] = parameter current_part = parameter continue diff --git a/giscanner/ast.py b/giscanner/ast.py index a9537e8d..671db72e 100644 --- a/giscanner/ast.py +++ b/giscanner/ast.py @@ -1137,3 +1137,19 @@ class Callback(Callable): def __init__(self, name, retval, parameters, throws, ctype=None): Callable.__init__(self, name, retval, parameters, throws) self.ctype = ctype + + +class Section(Node): + + def __init__(self, name, short_description, long_description, + see_also, title, stability, section_id, include, + image): + Node.__init__(self, name) + self.short_description = short_description + self.long_description = long_description + self.see_also = see_also + self.title = title + self.stability = stability + self.section_id = section_id + self.include = include + self.image = image diff --git a/giscanner/docwriter.py b/giscanner/docwriter.py index d888c81b..abcab71e 100644 --- a/giscanner/docwriter.py +++ b/giscanner/docwriter.py @@ -918,6 +918,8 @@ class DocWriter(object): self._transformer.namespace.walk(lambda node, chain: self._walk_node(output, node, chain)) def _walk_node(self, output, node, chain): + if isinstance(node, ast.Section): + return False if isinstance(node, ast.Function) and node.moved_to is not None: return False if self._formatter.should_render_node(node): diff --git a/giscanner/girparser.py b/giscanner/girparser.py index 40bc49e0..61fcc100 100644 --- a/giscanner/girparser.py +++ b/giscanner/girparser.py @@ -136,7 +136,9 @@ class GIRParser(object): _corens('interface'): self._parse_object_interface, _corens('record'): self._parse_record, _corens('union'): self._parse_union, - _glibns('boxed'): self._parse_boxed} + _corens('section'): self._parse_section, + _glibns('boxed'): self._parse_boxed, + } if not self._types_only: parser_methods[_corens('constant')] = self._parse_constant @@ -559,6 +561,28 @@ class GIRParser(object): self._parse_generic_attribs(node, constant) self._namespace.append(constant) + def _parse_section(self, node): + def find_child(name): + child = node.find(_corens(name)) + if child is not None: + return child.text + else: + return None + + long_description = find_child('long-description') + short_description = find_child('short-description') + see_also = find_child('see-also') + section = ast.Section(node.attrib['name'], + short_description, + long_description, + see_also, + node.attrib.get('title'), + node.attrib.get('stability'), + node.attrib.get('section-id'), + node.attrib.get('include'), + node.attrib.get('image')) + self._namespace.append(section) + def _parse_enumeration_bitfield(self, node): name = node.attrib.get('name') ctype = node.attrib.get(_cns('type')) diff --git a/giscanner/girwriter.py b/giscanner/girwriter.py index 3bea2a1c..79799c39 100644 --- a/giscanner/girwriter.py +++ b/giscanner/girwriter.py @@ -115,6 +115,8 @@ class GIRWriter(XMLWriter): self._write_alias(node) elif isinstance(node, ast.Constant): self._write_constant(node) + elif isinstance(node, ast.Section): + self._write_section(node) else: print 'WRITER: Unhandled node', node @@ -402,6 +404,25 @@ class GIRWriter(XMLWriter): self._write_generic(constant) self._write_type(constant.value_type) + def _write_section(self, section): + attrs = [('name', section.name), + ('title', section.title), + ('include', section.include), + ('image', section.image), + ('section-id', section.section_id)] + self._append_node_generic(section, attrs) + + with self.tagcontext('section', attrs): + self._write_generic(section) + + def write_child(name, content): + if content: + self.write_tag(name, [('xml:whitespace', 'preserve')], content) + + write_child('short-description', section.short_description) + write_child('long-description', section.long_description) + write_child('see-also', section.see_also) + def _write_class(self, node): attrs = [('name', node.name), ('c:symbol-prefix', node.c_symbol_prefix), diff --git a/giscanner/scannermain.py b/giscanner/scannermain.py index ac340305..d284d730 100755 --- a/giscanner/scannermain.py +++ b/giscanner/scannermain.py @@ -497,6 +497,8 @@ def scanner_main(args): transformer.namespace.shared_libraries = shlibs + transformer.fabricate_special_blocks(blocks) + main = MainTransformer(transformer, blocks) main.transform() diff --git a/giscanner/transformer.py b/giscanner/transformer.py index 8c5e9087..8e1001be 100644 --- a/giscanner/transformer.py +++ b/giscanner/transformer.py @@ -151,6 +151,30 @@ class Transformer(object): self._namespace.includes.add(include) self._parse_include(include_path, uninstalled=True) + def _fabricate_section(self, block): + def get_param(name): + param = block.lower_params.get(name) + if param: + return param.description + else: + return None + + section = ast.Section(block.name, + get_param('short_description'), + get_param('long_description'), + get_param('see_also'), + get_param('title'), + get_param('stability'), + get_param('section_id'), + get_param('include'), + get_param('image')) + self._append_new_node(section) + + def fabricate_special_blocks(self, blocks): + for name, block in blocks.iteritems(): + if name.startswith("SECTION:"): + self._fabricate_section(block) + def lookup_giname(self, name): """Given a name of the form Foo or Bar.Foo, return the corresponding ast.Node, or None if none diff --git a/tests/scanner/Regress-1.0-expected.gir b/tests/scanner/Regress-1.0-expected.gir index 1c9c300f..9ed048a5 100644 --- a/tests/scanner/Regress-1.0-expected.gir +++ b/tests/scanner/Regress-1.0-expected.gir @@ -2046,6 +2046,14 @@ exposed to language bindings. c:type="REGRESS_NEGATIVE_INT_CONSTANT"> +
+ One test section + two +
+
+ Another test section + one +
diff --git a/tests/scanner/regress.c b/tests/scanner/regress.c index 1bad36e3..00e21e3b 100644 --- a/tests/scanner/regress.c +++ b/tests/scanner/regress.c @@ -6,6 +6,28 @@ #include "regress.h" +/** + * SECTION:one + * @Short_description: One test section + * @Title: Test One! + * @See_also: two + * + * Testing some docs. + * + * Do not sound the alarm. + */ + +/** + * SECTION:two + * @Short_description: Another test section + * @Title: Test Another! + * @See_also: one + * + * Testing some more docs. + * + * Oh hey, this is still a test! + */ + static gboolean abort_on_error = TRUE; #define ASSERT_VALUE(condition) \ -- cgit v1.2.1