Skip to content
This repository has been archived by the owner on Nov 17, 2020. It is now read-only.

Commit

Permalink
Bug 546739 – Introspection should know precise signal parameter types
Browse files Browse the repository at this point in the history
2009-01-12  Johan Dahlin  <jdahlin@async.com.br>

        Bug 546739 – Introspection should know precise signal parameter types

        * giscanner/annotationparser.py:
        * tests/scanner/annotation-1.0-expected.gir:
        * tests/scanner/annotation-1.0-expected.tgir:
        * tests/scanner/annotation.c (annotation_object_class_init):

        Annotations are parsed for signals, the (type) annotation is introduced.


svn path=/trunk/; revision=1026
  • Loading branch information
Johan Dahlin authored and Johan Dahlin committed Jan 12, 2009
1 parent 9256e91 commit 6de1b29
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 13 deletions.
11 changes: 11 additions & 0 deletions ChangeLog
@@ -1,3 +1,14 @@
2009-01-12 Johan Dahlin <jdahlin@async.com.br>

Bug 546739 – Introspection should know precise signal parameter types

* giscanner/annotationparser.py:
* tests/scanner/annotation-1.0-expected.gir:
* tests/scanner/annotation-1.0-expected.tgir:
* tests/scanner/annotation.c (annotation_object_class_init):

Annotations are parsed for signals, the (type) annotation is introduced.

2009-01-12 Johan Dahlin <jdahlin@async.com.br>

Bug 563591 – Flags not recognized when there is no introspection data
Expand Down
52 changes: 39 additions & 13 deletions giscanner/annotationparser.py
Expand Up @@ -21,7 +21,7 @@
# AnnotationParser - parses gtk-doc annotations

# All gtk-doc comments needs to start with this:
_COMMENT_HEADER = '*\n * '
_COMMENT_HEADER = '*\n '

from .ast import (Array, Callback, Class, Enum, Field, Function, Interface,
List, Map, Parameter, Record, Return, Type, Union, Varargs,
Expand All @@ -34,6 +34,7 @@
PARAM_TRANSFER_CONTAINER,
PARAM_TRANSFER_FULL,
TYPE_ANY, TYPE_NONE)
from .odict import odict
from .glibast import GLibBoxed


Expand All @@ -46,10 +47,10 @@ class DocBlock(object):
def __init__(self, name):
self.name = name
self.value = None
self.tags = {}
self.tags = odict()

def __repr__(self):
return '<Directive %r>' % (self.name, )
return '<DocBlock %r>' % (self.name, )

def get(self, name):
if name == 'Returns':
Expand Down Expand Up @@ -114,9 +115,15 @@ def parse(self):
aa.parse(self._namespace)

def _parse_comment(self, comment):
comment = comment.lstrip()
if not comment.startswith(_COMMENT_HEADER):
return
comment = comment[len(_COMMENT_HEADER):]
comment = comment.strip()
if not comment.startswith('* '):
return
comment = comment[2:]

pos = comment.index('\n ')

block_name = comment[:pos]
Expand All @@ -126,6 +133,7 @@ def _parse_comment(self, comment):
block = DocBlock(block_name[:-1])
content = comment[pos+1:]
for line in content.split('\n'):
line = line.lstrip()
line = line[2:].strip() # Skip ' *'
if not line:
continue
Expand Down Expand Up @@ -221,15 +229,15 @@ def _parse_class(self, class_):
self._parse_methods(class_.methods)
self._parse_methods(class_.static_methods)
self._parse_properties(class_.properties)
self._parse_signals(class_.signals)
self._parse_signals(class_, class_.signals)
self._parse_fields(class_, class_.fields)

def _parse_interface(self, interface):
block = self._blocks.get(interface.name)
self._parse_version(interface, block)
self._parse_methods(interface.methods)
self._parse_properties(interface.properties)
self._parse_signals(interface.signals)
self._parse_signals(interface, interface.signals)
self._parse_fields(interface, interface.fields)

def _parse_record(self, record):
Expand Down Expand Up @@ -273,9 +281,9 @@ def _parse_methods(self, methods):
for method in methods:
self._parse_function(method)

def _parse_signals(self, signals):
def _parse_signals(self, parent, signals):
for signal in signals:
self._parse_signal(signal)
self._parse_signal(parent, signal)

def _parse_property(self, prop):
pass
Expand All @@ -293,10 +301,28 @@ def _parse_function(self, func):
self._parse_params(func, func.parameters, block)
self._parse_return(func, func.retval, block)

def _parse_signal(self, signal):
block = self._blocks.get(signal.name)
def _parse_signal(self, parent, signal):
block = self._blocks.get('%s::%s' % (parent.type_name, signal.name))
self._parse_version(signal, block)
self._parse_params(signal, signal.parameters, 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
# than the number of signal parameters
if block and len(block.tags) > len(signal.parameters):
names = block.tags.items()
else:
names = []
for i, param in enumerate(signal.parameters):
if names:
name, tag = names[i+1]
param.name = name
options = getattr(tag, 'options', {})
param_type = options.get('type')
if param_type:
param.type.name = param_type.one()
else:
tag = None
self._parse_param(signal, param, tag)
self._parse_return(signal, signal.retval, block)

def _parse_field(self, parent, field):
Expand All @@ -305,15 +331,15 @@ def _parse_field(self, parent, field):

def _parse_params(self, parent, params, block):
for param in params:
self._parse_param(parent, param, block)
tag = self._get_tag(block, param.name)
self._parse_param(parent, param, tag)

def _parse_return(self, parent, return_, block):
tag = self._get_tag(block, 'Returns')
options = getattr(tag, 'options', {})
self._parse_param_ret_common(parent, return_, options)

def _parse_param(self, parent, param, block):
tag = self._get_tag(block, param.name)
def _parse_param(self, parent, param, tag):
options = getattr(tag, 'options', {})

if isinstance(parent, Function):
Expand Down
13 changes: 13 additions & 0 deletions tests/scanner/annotation-1.0-expected.gir
Expand Up @@ -317,6 +317,19 @@
<field name="parent_instance">
<type name="GObject.Object" c:type="GObject"/>
</field>
<glib:signal name="string-signal"
version="1.0"
deprecated="Use other-signal instead"
deprecated-version="1.2">
<return-value transfer-ownership="full">
<type name="none" c:type="void"/>
</return-value>
<parameters>
<parameter name="string" transfer-ownership="none">
<type name="utf8" c:type="gpointer"/>
</parameter>
</parameters>
</glib:signal>
</class>
<record name="ObjectClass" c:type="AnnotationObjectClass">
<field name="parent_class">
Expand Down
10 changes: 10 additions & 0 deletions tests/scanner/annotation-1.0-expected.tgir
Expand Up @@ -297,6 +297,16 @@
<type name="GObject.Object"/>
</return-value>
</method>
<glib:signal name="string-signal" when="LAST">
<return-value transfer-ownership="full">
<type name="none"/>
</return-value>
<parameters>
<parameter name="string" transfer-ownership="none">
<type name="utf8"/>
</parameter>
</parameters>
</glib:signal>
</class>
<record name="ObjectClass">
<field name="parent_class">
Expand Down
30 changes: 30 additions & 0 deletions tests/scanner/annotation.c
Expand Up @@ -4,9 +4,39 @@ static char backslash_parsing_tester = '\\';

G_DEFINE_TYPE (AnnotationObject, annotation_object, G_TYPE_OBJECT);

enum {
STRING_SIGNAL,
LAST_SIGNAL
};

static guint annotation_object_signals[LAST_SIGNAL] = { 0 };

static void
annotation_object_class_init (AnnotationObjectClass *klass)
{
GObjectClass *gobject_class;

gobject_class = G_OBJECT_CLASS (klass);

/**
* AnnotationObject::string-signal:
* @annotation: the annotation object
* @string: (type utf8): a string
*
* This is a signal which has a broken signal handler,
* it says it's pointer but it's actually a string.
*
* Since: 1.0
* Deprecated: 1.2: Use other-signal instead
*/
annotation_object_signals[STRING_SIGNAL] =
g_signal_new ("string-signal",
G_OBJECT_CLASS_TYPE (gobject_class),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
(GSignalCMarshaller)g_cclosure_marshal_VOID__POINTER,
G_TYPE_NONE, 1, G_TYPE_POINTER);

}

Expand Down

0 comments on commit 6de1b29

Please sign in to comment.