diff options
author | Colin Walters <walters@verbum.org> | 2009-02-19 21:48:51 -0500 |
---|---|---|
committer | Colin Walters <walters@verbum.org> | 2009-03-03 17:26:37 -0500 |
commit | d5215b23315e7c9c22c6a32218bb6f8027a9dd4c (patch) | |
tree | e8d9e360099c756677ad23a1039f4d05533008b9 /giscanner | |
parent | 2bdd2bf9303ae0e718c00ec84078336e722138f1 (diff) | |
download | gobject-introspection-d5215b23315e7c9c22c6a32218bb6f8027a9dd4c.tar.gz |
Bug 571548 - Generic attributes
We now support an extensible mechanism where arbitrary key-value
pairs may be associated with almost all items, including objects,
methods, and properties.
These attributes appear in both the .gir and the .typelib.
Diffstat (limited to 'giscanner')
-rw-r--r-- | giscanner/annotationparser.py | 60 | ||||
-rw-r--r-- | giscanner/ast.py | 1 | ||||
-rw-r--r-- | giscanner/girwriter.py | 15 | ||||
-rw-r--r-- | giscanner/xmlwriter.py | 2 |
4 files changed, 59 insertions, 19 deletions
diff --git a/giscanner/annotationparser.py b/giscanner/annotationparser.py index 003ff2c1..0798b80f 100644 --- a/giscanner/annotationparser.py +++ b/giscanner/annotationparser.py @@ -20,6 +20,8 @@ # AnnotationParser - parses gtk-doc annotations +import sys + from .ast import (Array, Bitfield, Callback, Class, Enum, Field, Function, Interface, List, Map, Parameter, Record, Return, Type, Union, Varargs, @@ -43,6 +45,7 @@ TAG_SINCE = 'since' TAG_DEPRECATED = 'deprecated' TAG_RETURNS = 'returns' TAG_RETURNS_ALT = 'return value' +TAG_ATTRIBUTES = 'attributes' # Options - annotations for parameters and return values OPT_ALLOW_NONE = 'allow-none' @@ -92,7 +95,7 @@ class DocTag(object): def __init__(self, name): self.name = name - self.options = [] + self.options = {} self.comment = None @@ -178,23 +181,31 @@ class AnnotationParser(object): elif not ': ' in line: comment_lines.append(line) continue - tag = self._parse_tag(line) - block.tags[tag.name.lower()] = tag + tag_name, value = self._split_tag_namevalue(line) + canon_name = tag_name.lower() + if canon_name in block.tags: + print >>sys.stderr, "Multiple definition of tag %r" \ + % (canon_name, ) + block.tags[canon_name] = self._create_tag(canon_name, value) block.comment = '\n'.join(comment_lines) self._blocks[block.name] = block - def _parse_tag(self, raw): - # Tag: bar - # Tag: bar opt1 opt2 + def _split_tag_namevalue(self, raw): + """Split a line into tag name and value""" parts = raw.split(': ', 1) if len(parts) == 1: tag_name = parts[0] value = '' else: tag_name, value = parts - options, rest = self._parse_options(value) + return (tag_name, value) + + def _create_tag(self, tag_name, value): + # Tag: bar + # Tag: bar opt1 opt2 tag = DocTag(tag_name) tag.value = value + options, rest = self._parse_options(tag.value) tag.options = options tag.comment = rest return tag @@ -271,7 +282,7 @@ class AnnotationApplier(object): def _parse_class(self, class_): block = self._blocks.get(class_.type_name) - self._parse_version(class_, block) + self._parse_node_common(class_, block) self._parse_constructors(class_.constructors) self._parse_methods(class_.methods) self._parse_methods(class_.static_methods) @@ -283,7 +294,7 @@ class AnnotationApplier(object): def _parse_interface(self, interface): block = self._blocks.get(interface.type_name) - self._parse_version(interface, block) + self._parse_node_common(interface, block) self._parse_methods(interface.methods) self._parse_properties(interface, interface.properties) self._parse_signals(interface, interface.signals) @@ -293,7 +304,7 @@ class AnnotationApplier(object): def _parse_record(self, record): block = self._blocks.get(record.symbol) - self._parse_version(record, block) + self._parse_node_common(record, block) self._parse_constructors(record.constructors) self._parse_methods(record.methods) self._parse_fields(record, record.fields) @@ -302,7 +313,7 @@ class AnnotationApplier(object): def _parse_boxed(self, boxed): block = self._blocks.get(boxed.name) - self._parse_version(boxed, block) + self._parse_node_common(boxed, block) self._parse_constructors(boxed.constructors) self._parse_methods(boxed.methods) if block: @@ -310,6 +321,7 @@ class AnnotationApplier(object): def _parse_union(self, union): block = self._blocks.get(union.name) + self._parse_node_common(union, block) self._parse_fields(union, union.fields) self._parse_constructors(union.constructors) self._parse_methods(union.methods) @@ -318,13 +330,13 @@ class AnnotationApplier(object): def _parse_enum(self, enum): block = self._blocks.get(enum.symbol) - self._parse_version(enum, block) + self._parse_node_common(enum, block) if block: enum.doc = block.comment def _parse_bitfield(self, bitfield): block = self._blocks.get(bitfield.symbol) - self._parse_version(bitfield, block) + self._parse_node_common(bitfield, block) if block: bitfield.doc = block.comment @@ -350,14 +362,13 @@ class AnnotationApplier(object): def _parse_property(self, parent, prop): block = self._blocks.get('%s:%s' % (parent.type_name, prop.name)) - self._parse_version(prop, block) - self._parse_deprecated(prop, block) + self._parse_node_common(prop, block) if block: prop.doc = block.comment def _parse_callback(self, callback): block = self._blocks.get(callback.ctype) - self._parse_version(callback, block) + self._parse_node_common(callback, block) self._parse_params(callback, callback.parameters, block) self._parse_return(callback, callback.retval, block) if block: @@ -365,8 +376,7 @@ class AnnotationApplier(object): def _parse_function(self, func): block = self._blocks.get(func.symbol) - self._parse_version(func, block) - self._parse_deprecated(func, block) + self._parse_node_common(func, block) self._parse_params(func, func.parameters, block) self._parse_return(func, func.retval, block) if block: @@ -374,7 +384,7 @@ class AnnotationApplier(object): def _parse_signal(self, parent, signal): block = self._blocks.get('%s::%s' % (parent.type_name, signal.name)) - self._parse_version(signal, block) + self._parse_node_common(signal, block) self._parse_deprecated(signal, block) # We're only attempting to name the signal parameters if # the number of parameter tags (@foo) is the same or greater @@ -552,6 +562,11 @@ class AnnotationApplier(object): "none, container, full." % (node, parent.name, transfer)) return transfer + def _parse_node_common(self, node, block): + self._parse_version(node, block) + self._parse_deprecated(node, block) + self._parse_attributes(node, block) + def _parse_version(self, node, block): since_tag = self._get_tag(block, TAG_SINCE) if since_tag is None: @@ -572,6 +587,13 @@ class AnnotationApplier(object): if version is not None: node.deprecated_version = version + def _parse_attributes(self, node, block): + annos_tag = self._get_tag(block, TAG_ATTRIBUTES) + if annos_tag is None: + return + for key, value in annos_tag.options.iteritems(): + node.attributes.append((key, value.one())) + def _guess_direction(self, node): if node.direction: return node.direction diff --git a/giscanner/ast.py b/giscanner/ast.py index e708258c..d2bae873 100644 --- a/giscanner/ast.py +++ b/giscanner/ast.py @@ -147,6 +147,7 @@ class Node(object): def __init__(self, name=None): self.name = name + self.attributes = [] # (key, value)* self.deprecated = None self.deprecated_version = None self.version = None diff --git a/giscanner/girwriter.py b/giscanner/girwriter.py index df527090..88510b04 100644 --- a/giscanner/girwriter.py +++ b/giscanner/girwriter.py @@ -137,6 +137,10 @@ and/or use gtk-doc annotations. ''') if node.version: attrs.append(('version', node.version)) + def _write_attributes(self, node): + for key, value in node.attributes: + self.write_tag('attribute', [('name', key), ('value', value)]) + def _append_deprecated(self, node, attrs): if node.deprecated: attrs.append(('deprecated', node.deprecated)) @@ -163,6 +167,7 @@ and/or use gtk-doc annotations. ''') self._append_deprecated(func, attrs) self._append_throws(func, attrs) with self.tagcontext(tag_name, attrs): + self._write_attributes(func) self._write_return_type(func.retval) self._write_parameters(func.parameters) @@ -280,6 +285,7 @@ and/or use gtk-doc annotations. ''') attrs.append(('c:type', enum.symbol)) with self.tagcontext('enumeration', attrs): + self._write_attributes(enum) for member in enum.members: self._write_member(member) @@ -296,6 +302,7 @@ and/or use gtk-doc annotations. ''') else: attrs.append(('c:type', bitfield.symbol)) with self.tagcontext('bitfield', attrs): + self._write_attributes(bitfield) for member in bitfield.members: self._write_member(member) @@ -335,6 +342,7 @@ and/or use gtk-doc annotations. ''') if node.glib_type_struct: attrs.append(('glib:type-struct', node.glib_type_struct.name)) with self.tagcontext(tag_name, attrs): + self._write_attributes(node) if isinstance(node, GLibObject): for iface in node.interfaces: self.write_tag('implements', [('name', iface)]) @@ -362,6 +370,7 @@ and/or use gtk-doc annotations. ''') attrs.append(('doc', boxed.doc)) attrs.extend(self._boxed_attrs(boxed)) with self.tagcontext('glib:boxed', attrs): + self._write_attributes(boxed) for method in boxed.constructors: self._write_constructor(method) for method in boxed.methods: @@ -383,6 +392,7 @@ and/or use gtk-doc annotations. ''') if prop.doc: attrs.append(('doc', prop.doc)) with self.tagcontext('property', attrs): + self._write_attributes(prop) self._write_type(prop.type) def _write_callback(self, callback): @@ -394,6 +404,7 @@ and/or use gtk-doc annotations. ''') self._append_deprecated(callback, attrs) self._append_throws(callback, attrs) with self.tagcontext('callback', attrs): + self._write_attributes(callback) self._write_return_type(callback.retval) self._write_parameters(callback.parameters) @@ -420,6 +431,7 @@ and/or use gtk-doc annotations. ''') if isinstance(record, GLibBoxed): attrs.extend(self._boxed_attrs(record)) with self.tagcontext('record', attrs): + self._write_attributes(record) if record.fields: for field in record.fields: self._write_field(field) @@ -441,6 +453,7 @@ and/or use gtk-doc annotations. ''') if isinstance(union, GLibBoxed): attrs.extend(self._boxed_attrs(union)) with self.tagcontext('union', attrs): + self._write_attributes(union) if union.fields: for field in union.fields: self._write_field(field) @@ -471,6 +484,7 @@ and/or use gtk-doc annotations. ''') if field.bits: attrs.append(('bits', str(field.bits))) with self.tagcontext('field', attrs): + self._write_attributes(field) self._write_type(field.type) def _write_signal(self, signal): @@ -480,5 +494,6 @@ and/or use gtk-doc annotations. ''') self._append_version(signal, attrs) self._append_deprecated(signal, attrs) with self.tagcontext('glib:signal', attrs): + self._write_attributes(signal) self._write_return_type(signal.retval) self._write_parameters(signal.parameters) diff --git a/giscanner/xmlwriter.py b/giscanner/xmlwriter.py index 9f222e9e..3068e62e 100644 --- a/giscanner/xmlwriter.py +++ b/giscanner/xmlwriter.py @@ -84,6 +84,8 @@ class XMLWriter(object): # Private def _open_tag(self, tag_name, attributes=None): + if attributes is None: + attributes = [] attrs = collect_attributes( tag_name, attributes, self._indent, self._indent_char, |