summaryrefslogtreecommitdiff
path: root/giscanner
diff options
context:
space:
mode:
authorColin Walters <walters@verbum.org>2009-02-19 21:48:51 -0500
committerColin Walters <walters@verbum.org>2009-03-03 17:26:37 -0500
commitd5215b23315e7c9c22c6a32218bb6f8027a9dd4c (patch)
treee8d9e360099c756677ad23a1039f4d05533008b9 /giscanner
parent2bdd2bf9303ae0e718c00ec84078336e722138f1 (diff)
downloadgobject-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.py60
-rw-r--r--giscanner/ast.py1
-rw-r--r--giscanner/girwriter.py15
-rw-r--r--giscanner/xmlwriter.py2
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,