diff options
author | Johan Dahlin <johan@gnome.org> | 2010-09-23 17:13:29 -0300 |
---|---|---|
committer | Johan Dahlin <johan@gnome.org> | 2010-09-23 17:25:47 -0300 |
commit | e2b95cdb39d6e5f287e23dbf30a04031b49a230f (patch) | |
tree | b3d36b0a28cf358dc1ce40459d57e4638eb965b1 /giscanner | |
parent | 2525786185e0f9025f88c00769d948d2b83d646d (diff) | |
download | gobject-introspection-e2b95cdb39d6e5f287e23dbf30a04031b49a230f.tar.gz |
[scanner] Warn for invalid scanner annotations
Warn for invalid annotations.
Change so that custom attributes have to use the annotation
keyword.
Diffstat (limited to 'giscanner')
-rw-r--r-- | giscanner/annotationparser.py | 81 | ||||
-rw-r--r-- | giscanner/maintransformer.py | 14 |
2 files changed, 79 insertions, 16 deletions
diff --git a/giscanner/annotationparser.py b/giscanner/annotationparser.py index aad17e89..937b9be3 100644 --- a/giscanner/annotationparser.py +++ b/giscanner/annotationparser.py @@ -22,7 +22,7 @@ import re -from .message import Position +from . import message from .odict import odict # All gtk-doc comments needs to start with this: @@ -45,7 +45,11 @@ TAG_GET_VALUE_FUNC = 'get value func' # Options - annotations for parameters and return values OPT_ALLOW_NONE = 'allow-none' OPT_ARRAY = 'array' +OPT_ATTRIBUTE = 'attribute' +OPT_CLOSURE = 'closure' +OPT_DESTROY = 'destroy' OPT_ELEMENT_TYPE = 'element-type' +OPT_FOREIGN = 'foreign' OPT_IN = 'in' OPT_INOUT = 'inout' OPT_INOUT_ALT = 'in-out' @@ -53,10 +57,24 @@ OPT_OUT = 'out' OPT_SCOPE = 'scope' OPT_TRANSFER = 'transfer' OPT_TYPE = 'type' -OPT_CLOSURE = 'closure' -OPT_DESTROY = 'destroy' OPT_SKIP = 'skip' -OPT_FOREIGN = 'foreign' + +ALL_OPTIONS = [ + OPT_ALLOW_NONE, + OPT_ARRAY, + OPT_ATTRIBUTE, + OPT_CLOSURE, + OPT_DESTROY, + OPT_ELEMENT_TYPE, + OPT_FOREIGN, + OPT_IN, + OPT_INOUT, + OPT_INOUT_ALT, + OPT_OUT, + OPT_SCOPE, + OPT_TRANSFER, + OPT_TYPE, + OPT_SKIP] # Array options - array specific annotations OPT_ARRAY_FIXED_SIZE = 'fixed-size' @@ -71,11 +89,12 @@ class DocBlock(object): def __init__(self, name): self.name = name - self.options = {} + self.options = DocOptions() self.value = None self.tags = odict() self.comment = None self.params = [] + self.position = None def __repr__(self): return '<DocBlock %r %r>' % (self.name, self.options) @@ -83,19 +102,62 @@ class DocBlock(object): def get(self, name): return self.tags.get(name) + def validate(self): + for tag in self.tags.values(): + tag.validate() + class DocTag(object): def __init__(self, block, name): self.block = block self.name = name - self.options = {} + self.options = DocOptions() self.comment = None self.value = '' + self.position = None def __repr__(self): return '<DocTag %r %r>' % (self.name, self.options) + def validate(self): + for option in self.options: + if not option in ALL_OPTIONS: + message.warn('invalid option: %s' % (option, ), + positions=self.position) + + +class DocOptions(object): + def __init__(self): + self.values = [] + + def __getitem__(self, item): + for key, value in self.values: + if key == item: + return value + raise KeyError + + def __iter__(self): + return (k for k, v in self.values) + + def add(self, name, value): + self.values.append((name, value)) + + def get(self, item, default=None): + for key, value in self.values: + if key == item: + return value + return default + + def getall(self, item): + for key, value in self.values: + if key == item: + yield value + + def iteritems(self): + return iter(self.values) + + class DocOption(object): def __init__(self, tag, option): @@ -176,7 +238,7 @@ class AnnotationParser(object): if cpos: block_name = block_name[:cpos] block = DocBlock(block_name) - block.position = Position(filename, lineno) + block.position = message.Position(filename, lineno) if cpos: block.options = self.parse_options(block, block_header[cpos+2:]) comment_lines = [] @@ -271,6 +333,7 @@ class AnnotationParser(object): comment_lines.append(line) lineno += 1 block.comment = '\n'.join(comment_lines) + block.validate() self._blocks[block.name] = block @classmethod @@ -278,7 +341,7 @@ class AnnotationParser(object): # (foo) # (bar opt1 opt2...) opened = -1 - options = {} + options = DocOptions() last = None for i, c in enumerate(value): if c == '(' and opened == -1: @@ -295,7 +358,7 @@ class AnnotationParser(object): raise AssertionError if option is not None: option = DocOption(tag, option) - options[name] = option + options.add(name, option) last = i + 2 opened = -1 diff --git a/giscanner/maintransformer.py b/giscanner/maintransformer.py index a50951a3..605c5d35 100644 --- a/giscanner/maintransformer.py +++ b/giscanner/maintransformer.py @@ -25,8 +25,8 @@ from .annotationparser import (TAG_VFUNC, TAG_SINCE, TAG_DEPRECATED, TAG_RETURNS TAG_ATTRIBUTES, TAG_RENAME_TO, TAG_TYPE, TAG_TRANSFER, TAG_UNREF_FUNC, TAG_REF_FUNC, TAG_SET_VALUE_FUNC, TAG_GET_VALUE_FUNC) -from .annotationparser import (OPT_ALLOW_NONE, - OPT_ARRAY, OPT_ELEMENT_TYPE, OPT_IN, OPT_INOUT, +from .annotationparser import (OPT_ALLOW_NONE, OPT_ARRAY, OPT_ATTRIBUTE, + OPT_ELEMENT_TYPE, OPT_IN, OPT_INOUT, OPT_INOUT_ALT, OPT_OUT, OPT_SCOPE, OPT_TYPE, OPT_CLOSURE, OPT_DESTROY, OPT_SKIP, OPT_FOREIGN, OPT_ARRAY_FIXED_SIZE, @@ -114,6 +114,8 @@ usage is void (*_gtk_reserved1)(void);""" ast.Record, ast.Union)): return True for field in node.fields: + if field is None: + continue if (field.name.startswith('_') and field.anonymous_node is not None and isinstance(field.anonymous_node, ast.Callback)): @@ -506,11 +508,9 @@ usage is void (*_gtk_reserved1)(void);""" if tag is not None and tag.comment is not None: node.doc = tag.comment - for key in options: - if '.' in key: - value = options.get(key) - if value: - node.attributes.append((key, value.one())) + if options: + for attribute in options.getall(OPT_ATTRIBUTE): + node.attributes.append(attribute.flat()) def _apply_annotations_annotated(self, node, block): if block is None: |