diff options
author | Dieter Verfaillie <dieterv@optionexplicit.be> | 2013-07-23 17:34:07 +0200 |
---|---|---|
committer | Dieter Verfaillie <dieterv@optionexplicit.be> | 2013-10-08 20:56:43 +0200 |
commit | 6a874b86a1b9aae0c50a30b8cd3033870797eb1c (patch) | |
tree | 03831e4e2c597381e1d6da2a8a7ea4d5fc4bf28a /giscanner | |
parent | 4b690b187bf8d0b7b571faaa050986b796e797a4 (diff) | |
download | gobject-introspection-6a874b86a1b9aae0c50a30b8cd3033870797eb1c.tar.gz |
giscanner: refactor GTK-Doc comment block serialization
Diffstat (limited to 'giscanner')
-rw-r--r-- | giscanner/annotationmain.py | 5 | ||||
-rw-r--r-- | giscanner/annotationparser.py | 298 |
2 files changed, 198 insertions, 105 deletions
diff --git a/giscanner/annotationmain.py b/giscanner/annotationmain.py index 8756dcdb..618cf47f 100644 --- a/giscanner/annotationmain.py +++ b/giscanner/annotationmain.py @@ -21,7 +21,7 @@ import optparse from giscanner import message -from giscanner.annotationparser import GtkDocCommentBlockParser +from giscanner.annotationparser import GtkDocCommentBlockParser, GtkDocCommentBlockWriter from giscanner.scannermain import (get_preprocessor_option_group, create_source_scanner, process_packages) @@ -59,13 +59,14 @@ def annotation_main(args): if options.extract: parser = GtkDocCommentBlockParser() + writer = GtkDocCommentBlockWriter(indent=False) blocks = parser.parse_comment_blocks(ss.get_comments()) print '/' + ('*' * 60) + '/' print '/* THIS FILE IS GENERATED DO NOT EDIT */' print '/' + ('*' * 60) + '/' print for block in sorted(blocks.values()): - print block.to_gtk_doc() + print writer.write(block) print print print '/' + ('*' * 60) + '/' diff --git a/giscanner/annotationparser.py b/giscanner/annotationparser.py index e37fbe82..84d3eb23 100644 --- a/giscanner/annotationparser.py +++ b/giscanner/annotationparser.py @@ -882,31 +882,6 @@ class GtkDocParameter(GtkDocAnnotatable): def __repr__(self): return '<GtkDocParameter %r %r>' % (self.name, self.annotations) - def _get_gtk_doc_value(self): - def serialize_one(option, value, fmt, fmt2): - if value: - if type(value) != str: - if isinstance(value, list): - value = ' '.join(value) - else: - value = ' '.join((serialize_one(k, v, '%s=%s', '%s') - for k, v in value.items())) - return fmt % (option, value) - else: - return fmt2 % (option, ) - serialized = '' - annotations = [] - for ann_name, options in self.annotations.items(): - annotations.append(serialize_one(ann_name, options, '(%s %s)', '(%s)')) - if annotations: - serialized += ' '.join(annotations) - if self.description and annotations: - serialized += ': ' - return serialized - - def to_gtk_doc(self): - return '@%s: %s%s' % (self.name, self._get_gtk_doc_value(), self.description) - class GtkDocTag(GtkDocAnnotatable): ''' @@ -933,37 +908,6 @@ class GtkDocTag(GtkDocAnnotatable): def __repr__(self): return '<GtkDocTag %r %r>' % (self.name, self.annotations) - def _get_gtk_doc_value(self): - def serialize_one(option, value, fmt, fmt2): - if value: - if type(value) != str: - if isinstance(value, list): - value = ' '.join(value) - else: - value = ' '.join((serialize_one(k, v, '%s=%s', '%s') - for k, v in value.items())) - return fmt % (option, value) - else: - return fmt2 % (option, ) - serialized = '' - annotations = [] - for ann_name, options in self.annotations.items(): - annotations.append(serialize_one(ann_name, options, '(%s %s)', '(%s)')) - if annotations: - serialized += ' '.join(annotations) - if self.value and annotations: - serialized += ': ' - if self.value: - serialized += self.value - if self.description and (annotations or self.value): - serialized += ': ' - return serialized - - def to_gtk_doc(self): - return '%s: %s%s' % (self.name.capitalize(), - self._get_gtk_doc_value(), - self.description or '') - class GtkDocCommentBlock(GtkDocAnnotatable): ''' @@ -1014,53 +958,6 @@ class GtkDocCommentBlock(GtkDocAnnotatable): def __repr__(self): return '<GtkDocCommentBlock %r %r>' % (self.name, self.annotations) - def to_gtk_doc(self): - def serialize_one(option, value, fmt, fmt2): - if value: - if type(value) != str: - if isinstance(value, list): - value = ' '.join(value) - else: - value = ' '.join((serialize_one(k, v, '%s=%s', '%s') - for k, v in value.items())) - return fmt % (option, value) - else: - return fmt2 % (option, ) - - lines = [self.name] - if 'SECTION' not in self.name: - lines[0] += ':' - - annotations = [] - for ann_name, options in self.annotations.items(): - annotations.append(serialize_one(ann_name, options, '(%s %s)', '(%s)')) - if annotations: - annotations = ' '.join(annotations) - lines[0] += ' ' + annotations - - for param in self.params.values(): - for l in param.to_gtk_doc().split('\n'): - lines.append(l) - if self.description: - lines.append('') - for l in self.description.split('\n'): - lines.append(l) - if self.tags: - lines.append('') - for tag in self.tags.values(): - for l in tag.to_gtk_doc().split('\n'): - lines.append(l) - - comment = '' - comment += '/**\n' - for line in lines: - if line: - comment += ' * %s\n' % (line, ) - else: - comment += ' *\n' - comment += ' */\n' - return comment - def validate(self): ''' Validate annotations applied to the :class:`GtkDocCommentBlock` identifier, parameters @@ -1957,3 +1854,198 @@ class GtkDocCommentBlockParser(object): position) return (annotations, description_field) + + +class GtkDocCommentBlockWriter(object): + ''' + Serialized :class:`GtkDocCommentBlock` objects into GTK-Doc comment blocks. + ''' + + def __init__(self, indent=True): + #: :const:`True` if the original indentation preceding the "``*``" needs to be retained, + #: :const:`False` otherwise. Default value is :const:`True`. + self.indent = indent + + def _serialize_annotations(self, annotations): + ''' + Serialize an annotation field. For example:: + + ┌──────────────────────────────────────────────────────────────┐ + │ {'name': {'opt1': 'value1', 'opt2':'value2', 'opt3':None} │ ◁─ GtkDocAnnotations + ├──────────────────────────────────────────────────────────────┤ + │ '(name opt1=value1 opt2=value2 opt3)' │ ─▷ serialized + └──────────────────────────────────────────────────────────────┘ + + ┌──────────────────────────────────────────────────────────────┐ + │ {'name': ['opt1', 'opt2']} │ ◁─ GtkDocAnnotations + ├──────────────────────────────────────────────────────────────┤ + │ '(name opt1 opt2)' │ ─▷ serialized + └──────────────────────────────────────────────────────────────┘ + + ┌──────────────────────────────────────────────────────────────┐ + │ {'unkownname': ['unknown list of options']} │ ◁─ GtkDocAnnotations + ├──────────────────────────────────────────────────────────────┤ + │ '(unkownname unknown list of options)' │ ─▷ serialized + └──────────────────────────────────────────────────────────────┘ + + :param annotations: :class:`GtkDocAnnotations` to be serialized + :returns: a string + ''' + + serialized = [] + + for ann_name, options in annotations.items(): + if options: + if isinstance(options, list): + serialize_options = ' '.join(options) + else: + serialize_options = '' + + for key, value in options.items(): + if value: + serialize_options += '%s=%s ' % (key, value) + else: + serialize_options += '%s ' % (key, ) + + serialize_options = serialize_options.strip() + + serialized.append('(%s %s)' % (ann_name, serialize_options)) + else: + serialized.append('(%s)' % (ann_name, )) + + return ' '.join(serialized) + + def _serialize_parameter(self, parameter): + ''' + Serialize a parameter. + + :param parameter: :class:`GtkDocParameter` to be serialized + :returns: a string + ''' + + # parameter_name field + serialized = '@%s' % (parameter.name, ) + + # annotations field + if parameter.annotations: + serialized += ': ' + self._serialize_annotations(parameter.annotations) + + # description field + if parameter.description: + if parameter.description.startswith('\n'): + serialized += ':' + parameter.description + else: + serialized += ': ' + parameter.description + else: + serialized += ':' + + return serialized.split('\n') + + def _serialize_tag(self, tag): + ''' + Serialize a tag. + + :param tag: :class:`GtkDocTag` to be serialized + :returns: a string + ''' + + # tag_name field + serialized = tag.name.capitalize() + + # annotations field + if tag.annotations: + serialized += ': ' + self._serialize_annotations(tag.annotations) + + # value field + if tag.value: + serialized += ': ' + tag.value + + # description field + if tag.description: + if tag.description.startswith('\n'): + serialized += ':' + tag.description + else: + serialized += ': ' + tag.description + + if not tag.value and not tag.description: + serialized += ':' + + return serialized.split('\n') + + def write(self, block): + ''' + Serialize a :class:`GtkDocCommentBlock` object. + + :param block: :class:`GtkDocCommentBlock` to be serialized + :returns: a string + ''' + + if block is None: + return '' + else: + lines = [] + + # Identifier part + if block.name.startswith('SECTION'): + lines.append(block.name) + else: + if block.annotations: + annotations = self._serialize_annotations(block.annotations) + lines.append('%s: %s' % (block.name, annotations)) + else: + # Note: this delimiter serves no purpose other than most people being used + # to reading/writing it. It is completely legal to ommit this. + lines.append('%s:' % (block.name, )) + + # Parameter parts + for param in block.params.values(): + lines.extend(self._serialize_parameter(param)) + + # Comment block description part + if block.description: + lines.append('') + for l in block.description.split('\n'): + lines.append(l) + + # Tag parts + if block.tags: + # Note: this empty line servers no purpose other than most people being used + # to reading/writing it. It is completely legal to ommit this. + lines.append('') + for tag in block.tags.values(): + lines.extend(self._serialize_tag(tag)) + + # Restore comment block indentation and * + if self.indent: + indent = Counter(block.indentation).most_common(1)[0][0] or ' ' + if indent.endswith('\t'): + start_indent = indent + line_indent = indent + ' ' + else: + start_indent = indent[:-1] + line_indent = indent + else: + start_indent = '' + line_indent = ' ' + + i = 0 + while i < len(lines): + line = lines[i] + if line: + lines[i] = '%s* %s\n' % (line_indent, line) + else: + lines[i] = '%s*\n' % (line_indent, ) + i += 1 + + # Restore comment block start and end tokens + lines.insert(0, '%s/**\n' % (start_indent, )) + lines.append('%s*/\n' % (line_indent, )) + + # Restore code before and after comment block start and end tokens + if block.code_before: + lines.insert(0, '%s\n' % (block.code_before, )) + + if block.code_after: + lines.append('%s\n' % (block.code_after, )) + + return ''.join(lines) |