summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohan Dahlin <johan@gnome.org>2010-09-24 09:59:43 -0300
committerJohan Dahlin <johan@gnome.org>2010-09-24 11:03:52 -0300
commit7c3d1e7c5d6d209c262789b22ea6a99b0636771d (patch)
treeb2caa2aa878d46e0b9456bf3d4836d693fb3e6c5
parent013937b79ce3467068352e6dd0179efaf2563ac7 (diff)
downloadgobject-introspection-7c3d1e7c5d6d209c262789b22ea6a99b0636771d.tar.gz
[annotationparser] Validate the rest of the annotations
All option annotations, which uses parenthesis are now properly validated for number of values they expect
-rw-r--r--giscanner/annotationparser.py106
-rw-r--r--tests/warn/Makefile.am3
-rw-r--r--tests/warn/invalid-element-type.h54
-rw-r--r--tests/warn/invalid-out.h8
-rw-r--r--tests/warn/unresolved-element-type.h11
5 files changed, 151 insertions, 31 deletions
diff --git a/giscanner/annotationparser.py b/giscanner/annotationparser.py
index 2bb2ee39..b8e8530c 100644
--- a/giscanner/annotationparser.py
+++ b/giscanner/annotationparser.py
@@ -1,6 +1,6 @@
# -*- Mode: Python -*-
# GObject-Introspection - a framework for introspecting GObject libraries
-# Copyright (C) 2008 Johan Dahlin
+# Copyright (C) 2008-2010 Johan Dahlin
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
@@ -18,7 +18,7 @@
# 02110-1301, USA.
#
-# AnnotationParser - parses gtk-doc annotations
+# AnnotationParser - extract annotations from gtk-doc comments
import re
@@ -134,21 +134,29 @@ class DocTag(object):
def __repr__(self):
return '<DocTag %r %r>' % (self.name, self.options)
- def _validate_option(self, name, value, required=False, n_params=None, choices=None):
+ def _validate_option(self, name, value, required=False,
+ n_params=None, choices=None):
if required and value is None:
- message.warn('%s annotation needs a value' % (name, ), self.position)
+ message.warn('%s annotation needs a value' % (
+ name, ), self.position)
return
- if n_params is not None and value.length() != n_params:
+ if n_params is not None:
if n_params == 0:
s = 'no value'
elif n_params == 1:
s = 'one value'
else:
s = '%d values' % (n_params, )
- message.warn('%s annotation needs %s, not %d' % (
- name, s, value.length()), self.position)
- return
+ if ((n_params > 0 and (value is None or value.length() != n_params)) or
+ n_params == 0 and value is not None):
+ if value is None:
+ length = 0
+ else:
+ length = value.length()
+ message.warn('%s annotation needs %s, not %d' % (
+ name, s, length), self.position)
+ return
if choices is not None:
valuestr = value.one()
@@ -157,20 +165,63 @@ class DocTag(object):
name, valuestr, ), self.position)
return
+ def set_position(self, position):
+ self.position = position
+ self.options.position = position
+
def validate(self):
for option in self.options:
- if not option in ALL_OPTIONS:
- message.warn('invalid annotation option: %s' % (option, ),
- positions=self.position)
value = self.options[option]
- if option == OPT_TRANSFER:
- self._validate_option(
- 'transfer', value, required=True,
- n_params=1,
- choices=[OPT_TRANSFER_FULL,
- OPT_TRANSFER_CONTAINER,
- OPT_TRANSFER_NONE])
-
+ if option == OPT_ALLOW_NONE:
+ self._validate_option('allow-none', value, n_params=0)
+ elif option == OPT_ARRAY:
+ if value is None:
+ continue
+ for v in value.all():
+ if v not in [OPT_ARRAY_LENGTH,
+ OPT_ARRAY_ZERO_TERMINATED,
+ OPT_ARRAY_FIXED_SIZE]:
+ message.warn(
+ 'invalid array annotation value: %r' % (
+ v, ), self.position)
+ elif option == OPT_ATTRIBUTE:
+ self._validate_option('attribute', value, n_params=2)
+ elif option == OPT_CLOSURE:
+ self._validate_option('closure', value, n_params=1)
+ elif option == OPT_DESTROY:
+ self._validate_option('destroy', value, n_params=1)
+ elif option == OPT_ELEMENT_TYPE:
+ self._validate_option('element-type', value, required=True)
+ if value is None:
+ message.warn(
+ 'element-type takes at least one value, none given',
+ self.position)
+ continue
+ if value.length() > 2:
+ message.warn(
+ 'element-type takes at maximium 2 values, %d given' % (
+ value.length()), self.position)
+ continue
+ elif option == OPT_FOREIGN:
+ self._validate_option('foreign', value, n_params=0)
+ elif option == OPT_IN:
+ self._validate_option('in', value, n_params=0)
+ elif option in [OPT_INOUT, OPT_INOUT_ALT]:
+ self._validate_option('inout', value, n_params=0)
+ elif option == OPT_OUT:
+ if value is None:
+ continue
+ if value.length() > 1:
+ message.warn(
+ 'out annotation takes at maximium 1 value, %d given' % (
+ value.length()), self.position)
+ continue
+ value_str = value.one()
+ if value_str not in [OPT_OUT_CALLEE_ALLOCATES,
+ OPT_OUT_CALLER_ALLOCATES]:
+ message.warn("out annotation value is invalid: %r" % (
+ value_str), self.position)
+ continue
elif option == OPT_SCOPE:
self._validate_option(
'scope', value, required=True,
@@ -178,6 +229,22 @@ class DocTag(object):
choices=[OPT_SCOPE_ASYNC,
OPT_SCOPE_CALL,
OPT_SCOPE_NOTIFIED])
+ elif option == OPT_SKIP:
+ self._validate_option('skip', value, n_params=0)
+ elif option == OPT_TRANSFER:
+ self._validate_option(
+ 'transfer', value, required=True,
+ n_params=1,
+ choices=[OPT_TRANSFER_FULL,
+ OPT_TRANSFER_CONTAINER,
+ OPT_TRANSFER_NONE])
+ elif option == OPT_TYPE:
+ self._validate_option('type', value, required=True,
+ n_params=1)
+ else:
+ message.warn('invalid annotation option: %s' % (option, ),
+ positions=self.position)
+
class DocOptions(object):
def __init__(self):
@@ -216,6 +283,7 @@ class DocOption(object):
self.tag = tag
self._array = []
self._dict = {}
+ # (annotation option1=value1 option2=value2) etc
for p in option.split(' '):
if '=' in p:
name, value = p.split('=', 1)
diff --git a/tests/warn/Makefile.am b/tests/warn/Makefile.am
index bdcc9707..26c2dcbb 100644
--- a/tests/warn/Makefile.am
+++ b/tests/warn/Makefile.am
@@ -4,10 +4,11 @@ TESTS = \
callback-invalid-scope.h \
callback-missing-scope.h \
return-gobject.h \
+ invalid-element-type.h \
invalid-option.h \
+ invalid-out.h \
invalid-transfer.h \
unknown-parameter.h \
- unresolved-element-type.h \
unresolved-type.h
EXTRA_DIST = warningtester.py common.h $(TESTS)
diff --git a/tests/warn/invalid-element-type.h b/tests/warn/invalid-element-type.h
new file mode 100644
index 00000000..f2cf2b93
--- /dev/null
+++ b/tests/warn/invalid-element-type.h
@@ -0,0 +1,54 @@
+#include "common.h"
+
+/**
+ * test_invalid_list_element_type:
+ * @l1: (element-type):
+ * @l2: (element-type int int):
+ */
+
+void test_invalid_list_element_type(GList *l1, GList *l2);
+
+// EXPECT:5: Warning: Test: element-type annotation needs a value
+// EXPECT:5: Warning: Test: element-type takes at least one value, none given
+
+/**
+ * test_invalid_array_element_type:
+ * @a1: (element-type):
+ * @a2: (element-type int int):
+ */
+
+void test_invalid_array_element_type(const char *a1, const char *a2);
+
+// EXPECT:16: Warning: Test: element-type annotation needs a value
+// EXPECT:16: Warning: Test: element-type takes at least one value, none given
+
+/**
+ * test_invalid_hash_element_type:
+ * @h1: (element-type):
+ * @h2: (element-type int):
+ * @h3: (element-type int int int):
+ */
+
+void test_invalid_hash_element_type(GHashTable *h1, GHashTable *h2, GHashTable *h3);
+
+// EXPECT:27: Warning: Test: element-type annotation needs a value
+// EXPECT:27: Warning: Test: element-type takes at least one value, none given
+// EXPECT:29: Warning: Test: element-type takes at maximium 2 values, 3 given
+
+/**
+ * test_unresolved_element_type:
+ *
+ * Returns: (element-type Unresolved) (transfer full):
+ */
+
+GList* test_unresolved_element_type(void);
+
+
+// EXPECT:5: Warning: Test: element-type annotation takes at least one option, none given
+// EXPECT:6: Warning: Test: element-type annotation for a list must have exactly one option, not 2 options
+// EXPECT:16: Warning: Test: element-type annotation takes at least one option, none given
+// EXPECT:20: Warning: Test: Unknown container Type(target_fundamental=utf8, ctype=char*) for element-type annotation
+// EXPECT:27: Warning: Test: element-type annotation takes at least one option, none given
+// EXPECT:28: Warning: Test: element-type annotation for a hash table must have exactly two options, not 1 option(s)
+// EXPECT:29: Warning: Test: element-type annotation for a hash table must have exactly two options, not 3 option(s)
+// EXPECT:41: Warning: Test: test_unresolved_element_type: Unknown type: 'Unresolved'
diff --git a/tests/warn/invalid-out.h b/tests/warn/invalid-out.h
new file mode 100644
index 00000000..fcb4f70f
--- /dev/null
+++ b/tests/warn/invalid-out.h
@@ -0,0 +1,8 @@
+/**
+ * test_invalid_out:
+ * @out: (out invalid):
+ */
+
+void test_invalid_out(int *out);
+
+// EXPECT:3: Warning: Test: out annotation value is invalid: 'invalid'
diff --git a/tests/warn/unresolved-element-type.h b/tests/warn/unresolved-element-type.h
deleted file mode 100644
index 26e13da9..00000000
--- a/tests/warn/unresolved-element-type.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#include "common.h"
-
-/**
- * test_unresolved_element_type:
- *
- * Returns: (element-type Unresolved) (transfer full):
- */
-
-GList* test_unresolved_element_type(void);
-
-// EXPECT:6: Warning: Test: test_unresolved_element_type: Unknown type: 'Unresolved'