aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--find-modules/Qt5Ruleset.py7
-rwxr-xr-xfind-modules/rules_engine.py76
-rw-r--r--find-modules/sip_generator.py19
-rw-r--r--tests/GenerateSipBindings/cpplib.cpp7
-rw-r--r--tests/GenerateSipBindings/cpplib.h16
-rw-r--r--tests/GenerateSipBindings/rules_SipTest.py7
6 files changed, 126 insertions, 6 deletions
diff --git a/find-modules/Qt5Ruleset.py b/find-modules/Qt5Ruleset.py
index 8ce6f8da..9392ae18 100644
--- a/find-modules/Qt5Ruleset.py
+++ b/find-modules/Qt5Ruleset.py
@@ -104,6 +104,9 @@ def variable_rules():
[".*", "d", ".*Private.*", rules_engine.variable_discard],
]
+def typedef_rules():
+ return []
+
class RuleSet(rules_engine.RuleSet):
"""
SIP file generator rules. This is a set of (short, non-public) functions
@@ -113,6 +116,7 @@ class RuleSet(rules_engine.RuleSet):
self._container_db = rules_engine.ContainerRuleDb(container_rules)
self._fn_db = rules_engine.FunctionRuleDb(function_rules)
self._param_db = rules_engine.ParameterRuleDb(parameter_rules)
+ self._typedef_db = rules_engine.TypedefRuleDb(typedef_rules)
self._var_db = rules_engine.VariableRuleDb(variable_rules)
self._methodcode = rules_engine.MethodCodeDb({})
self._modulecode = rules_engine.ModuleCodeDb({})
@@ -126,6 +130,9 @@ class RuleSet(rules_engine.RuleSet):
def parameter_rules(self):
return self._param_db
+ def typedef_rules(self):
+ return self._typedef_db
+
def variable_rules(self):
return self._var_db
diff --git a/find-modules/rules_engine.py b/find-modules/rules_engine.py
index 3bd6ccfc..64ce1d97 100755
--- a/find-modules/rules_engine.py
+++ b/find-modules/rules_engine.py
@@ -386,6 +386,68 @@ class ParameterRuleDb(AbstractCompiledRuleDb):
return None
+class TypedefRuleDb(AbstractCompiledRuleDb):
+ """
+ THE RULES FOR TYPEDEFS.
+
+ These are used to customise the behaviour of the SIP generator by allowing
+ the declaration for any typedef to be customised, for example to add SIP
+ compiler annotations.
+
+ Each entry in the raw rule database must be a list with members as follows:
+
+ 0. A regular expression which matches the fully-qualified name of the
+ "container" enclosing the typedef.
+
+ 1. A regular expression which matches the typedef name.
+
+ 2. A function.
+
+ In use, the database is walked in order from the first entry. If the regular
+ expressions are matched, the function is called, and no further entries are
+ walked. The function is called with the following contract:
+
+ def typedef_xxx(container, typedef, sip, matcher):
+ '''
+ Return a modified declaration for the given function.
+
+ :param container: The clang.cindex.Cursor for the container.
+ :param typedef: The clang.cindex.Cursor for the typedef.
+ :param sip: A dict with the following keys:
+
+ name The name of the typedef.
+ annotations Any SIP annotations.
+
+ :param matcher: The re.Match object. This contains named
+ groups corresponding to the key names above
+ EXCEPT annotations.
+
+ :return: An updated set of sip.xxx values. Setting sip.name to the
+ empty string will cause the container to be suppressed.
+ '''
+
+ :return: The compiled form of the rules.
+ """
+ def __init__(self, db):
+ super(TypedefRuleDb, self).__init__(db, ["container", "typedef"])
+
+ def apply(self, container, typedef, sip):
+ """
+ Walk over the rules database for typedefs, applying the first matching transformation.
+
+ :param container: The clang.cindex.Cursor for the container.
+ :param typedef: The clang.cindex.Cursor for the typedef.
+ :param sip: The SIP dict.
+ """
+ parents = _parents(typedef)
+ matcher, rule = self._match(parents, sip["name"])
+ if matcher:
+ before = deepcopy(sip)
+ rule.fn(container, typedef, sip, matcher)
+ return rule.trace_result(parents, typedef, before, sip)
+ return None
+
+
class VariableRuleDb(AbstractCompiledRuleDb):
"""
THE RULES FOR VARIABLES.
@@ -727,6 +789,15 @@ class RuleSet(object):
raise NotImplemented(_("Missing subclass implementation"))
@abstractmethod
+ def typedef_rules(self):
+ """
+ Return a compiled list of rules for typedefs.
+
+ :return: A TypedefRuleDb instance
+ """
+ raise NotImplemented(_("Missing subclass implementation"))
+
+ @abstractmethod
def variable_rules(self):
"""
Return a compiled list of rules for variables.
@@ -761,7 +832,7 @@ class RuleSet(object):
else:
logger.warn(_("Rule {} was not used".format(rule)))
- for db in [self.container_rules(), self.function_rules(), self.parameter_rules(),
+ for db in [self.container_rules(), self.function_rules(), self.parameter_rules(), self.typedef_rules(),
self.variable_rules(), self.methodcode_rules(), self.modulecode_rules()]:
db.dump_usage(dumper)
@@ -808,6 +879,9 @@ def function_discard_impl(container, function, sip, matcher):
if function.extent.start.column == 1:
sip["name"] = ""
+def typedef_discard(container, typedef, sip, matcher):
+ sip["name"] = ""
+
def rules(project_rules):
"""
Constructor.
diff --git a/find-modules/sip_generator.py b/find-modules/sip_generator.py
index e5e807ed..a8c164b5 100644
--- a/find-modules/sip_generator.py
+++ b/find-modules/sip_generator.py
@@ -228,7 +228,7 @@ class SipGenerator(object):
elif member.kind == CursorKind.CXX_ACCESS_SPEC_DECL:
decl = self._get_access_specifier(member, level + 1)
elif member.kind == CursorKind.TYPEDEF_DECL:
- decl = self._typedef_get(member, level + 1)
+ decl = self._typedef_get(container, member, level + 1)
elif member.kind == CursorKind.CXX_BASE_SPECIFIER:
#
# Strip off the leading "class". Except for TypeKind.UNEXPOSED...
@@ -627,7 +627,7 @@ class SipGenerator(object):
return _get_param_value(text, parameterType)
return ""
- def _typedef_get(self, typedef, level):
+ def _typedef_get(self, container, typedef, level):
"""
Generate the translation for a typedef.
@@ -637,10 +637,19 @@ class SipGenerator(object):
:return: A string.
"""
- pad = " " * (level * 4)
+ sip = {
+ "name": typedef.displayname,
+ "annotations": set(),
+ }
+
+ self.rules.typedef_rules().apply(container, typedef, sip)
- decl = pad + "typedef {} {}".format(typedef.underlying_typedef_type.spelling, typedef.displayname)
- decl += ";\n"
+ pad = " " * (level * 4)
+ if sip["name"]:
+ decl = pad + "typedef {} {}".format(typedef.underlying_typedef_type.spelling, typedef.displayname)
+ decl += ";\n"
+ else:
+ decl = pad + "// Discarded {}\n".format(SipGenerator.describe(typedef))
return decl
def _var_get(self, container, variable, level):
diff --git a/tests/GenerateSipBindings/cpplib.cpp b/tests/GenerateSipBindings/cpplib.cpp
index 7eb15939..f996c998 100644
--- a/tests/GenerateSipBindings/cpplib.cpp
+++ b/tests/GenerateSipBindings/cpplib.cpp
@@ -161,3 +161,10 @@ int anotherCustomMethod(QList<int> const& nums)
{
return 0;
}
+
+void TypedefUser::setTagPattern(const QString &tagName,
+ SomeNS::TagFormatter formatter,
+ int leadingNewlines)
+{
+
+}
diff --git a/tests/GenerateSipBindings/cpplib.h b/tests/GenerateSipBindings/cpplib.h
index b69480ee..34167ad3 100644
--- a/tests/GenerateSipBindings/cpplib.h
+++ b/tests/GenerateSipBindings/cpplib.h
@@ -128,8 +128,24 @@ qreal useEnum(MyFlags flags = EnumValueOne);
int customMethod(QList<int> const& nums);
+typedef QString(*TagFormatter)(const QStringList &languages,
+ const QString &tagName,
+ const QHash<QString, QString> &attributes,
+ const QString &text,
+ const QStringList &tagPath,
+ SomeNS::MyFlagType format);
+
}
+class TypedefUser
+{
+public:
+
+ void setTagPattern(const QString &tagName,
+ SomeNS::TagFormatter formatter = NULL,
+ int leadingNewlines = 0);
+};
+
int anotherCustomMethod(QList<int> const& nums);
enum __attribute__((visibility("default"))) EnumWithAttributes {
diff --git a/tests/GenerateSipBindings/rules_SipTest.py b/tests/GenerateSipBindings/rules_SipTest.py
index 1331da41..73c5451b 100644
--- a/tests/GenerateSipBindings/rules_SipTest.py
+++ b/tests/GenerateSipBindings/rules_SipTest.py
@@ -9,6 +9,12 @@ def local_function_rules():
return [
["MyObject", "fwdDecl", ".*", ".*", ".*", rules_engine.function_discard],
["MyObject", "fwdDeclRef", ".*", ".*", ".*", rules_engine.function_discard],
+ ["TypedefUser", "setTagPattern", ".*", ".*", ".*", rules_engine.function_discard],
+ ]
+
+def local_typedef_rules():
+ return [
+ [".*", "TagFormatter", rules_engine.typedef_discard],
]
def methodGenerator(function, sip, entry):
@@ -23,6 +29,7 @@ class RuleSet(Qt5Ruleset.RuleSet):
def __init__(self):
Qt5Ruleset.RuleSet.__init__(self)
self._fn_db = rules_engine.FunctionRuleDb(lambda: local_function_rules() + Qt5Ruleset.function_rules())
+ self._typedef_db = rules_engine.TypedefRuleDb(lambda: local_typedef_rules() + Qt5Ruleset.typedef_rules())
self._modulecode = rules_engine.ModuleCodeDb({
"cpplib.h": {
"code": """