glib-mkenums: allow optional 'since' tag

The glib-mkenums program allows generating code to handle enums/flags
with very different purposes. One of its purposes could be generating
per-enum/flag methods to be exposed in a library API, and while doing
that, it would be nice to have a way to specify in which API version
the enum/flag was introduced, so that the same version could be shown
in the generated API methods.

E.g. From the following code:

    /**
     * QmiWmsMessageProtocol:
     * @QMI_WMS_MESSAGE_PROTOCOL_CDMA: CDMA.
     * @QMI_WMS_MESSAGE_PROTOCOL_WCDMA: WCDMA.
     *
     * Type of message protocol.
     *
     * Since: 1.0
     */
    typedef enum { /*< since=1.0 >*/
        QMI_WMS_MESSAGE_PROTOCOL_CDMA  = 0x00,
        QMI_WMS_MESSAGE_PROTOCOL_WCDMA = 0x01
    } QmiWmsMessageProtocol;

The template would allow us to generate a method documented like this,
including the Since tag with the value given in the mkenums 'since' tag.

    /**
     * qmi_wms_message_protocol_get_string:
     * @val: a QmiWmsMessageProtocol.
     *
     * Gets the nickname string for the #QmiWmsMessageProtocol specified at @val.
     *
     * Returns: (transfer none): a string with the nickname, or %NULL if not found. Do not free the returned value.
     * Since: 1.0
     */
    const gchar *qmi_wms_message_protocol_get_string (QmiWmsMessageProtocol val);

Signed-off-by: Aleksander Morgado <aleksander@aleksander.es>
This commit is contained in:
Aleksander Morgado 2020-05-12 21:56:02 +02:00
parent 4d1132a945
commit ec6056e3ab
3 changed files with 46 additions and 5 deletions

View File

@ -195,6 +195,14 @@ Specifies the word separation used in the <function>*_get_type()</function>
function. For instance, <literal>/*&lt; underscore_name=gnome_vfs_uri_hide_options &gt;*/</literal>.
</para></listitem>
</varlistentry>
<varlistentry>
<term><literal>since</literal></term>
<listitem><para>
Specifies the version tag that will be used to substitute the <literal>@enumsince@</literal>
keyword in the template, useful when documenting methods generated from the enums
(e.g. <literal>Since: @enumsince@</literal>). (Since: 2.66)
</para></listitem>
</varlistentry>
</variablelist>
<para>The following options can be specified per value definition:</para>
@ -219,7 +227,7 @@ typedef enum /*&lt; skip &gt;*/
{
PREFIX_FOO
} PrefixThisEnumWillBeSkipped;
typedef enum /*&lt; flags,prefix=PREFIX &gt;*/
typedef enum /*&lt; flags,prefix=PREFIX,since=1.0 &gt;*/
{
PREFIX_THE_ZEROTH_VALUE, /*&lt; skip &gt;*/
PREFIX_THE_FIRST_VALUE,

View File

@ -130,6 +130,7 @@ option_lowercase_name = '' # DEPRECATED. A lower case name to use as part
# one that we guess. For instance, when an enum
# uses abnormal capitalization and we can not
# guess where to put the underscores.
option_since = '' # User provided version info for the enum.
seenbitshift = 0 # Have we seen bitshift operators?
enum_prefix = None # Prefix for this enumeration
enumname = '' # Name for this enumeration
@ -256,6 +257,7 @@ help_epilog = '''Production text substitutions:
\u0040ENUMNAME\u0040 PREFIX_THE_XENUM
\u0040ENUMSHORT\u0040 THE_XENUM
\u0040ENUMPREFIX\u0040 PREFIX
\u0040enumsince\u0040 the user-provided since value given
\u0040VALUENAME\u0040 PREFIX_THE_XVALUE
\u0040valuenick\u0040 the-xvalue
\u0040valuenum\u0040 the integer value (limited support, Since: 2.26)
@ -515,11 +517,13 @@ def process_file(curfilename):
flags = int(flags)
option_lowercase_name = options.get('lowercase_name', None)
option_underscore_name = options.get('underscore_name', None)
option_since = options.get('since', None)
else:
enum_prefix = None
flags = None
option_lowercase_name = None
option_underscore_name = None
option_since = None
if option_lowercase_name is not None:
if option_underscore_name is not None:
@ -620,6 +624,11 @@ def process_file(curfilename):
enumlong = enumname_prefix + "_" + enumshort
enumsym = enumlong.lower()
if option_since is not None:
enumsince = option_since
else:
enumsince = ""
if firstenum:
firstenum = False
@ -641,6 +650,7 @@ def process_file(curfilename):
prod = prod.replace('\u0040ENUMSHORT\u0040', enumshort)
prod = prod.replace('\u0040ENUMNAME\u0040', enumlong)
prod = prod.replace('\u0040ENUMPREFIX\u0040', enumname_prefix)
prod = prod.replace('\u0040enumsince\u0040', enumsince)
if flags:
prod = prod.replace('\u0040type\u0040', 'flags')
else:
@ -663,6 +673,7 @@ def process_file(curfilename):
prod = prod.replace('\u0040ENUMSHORT\u0040', enumshort)
prod = prod.replace('\u0040ENUMNAME\u0040', enumlong)
prod = prod.replace('\u0040ENUMPREFIX\u0040', enumname_prefix)
prod = prod.replace('\u0040enumsince\u0040', enumsince)
if flags:
prod = prod.replace('\u0040type\u0040', 'flags')
else:
@ -729,6 +740,7 @@ def process_file(curfilename):
prod = prod.replace('\u0040ENUMSHORT\u0040', enumshort)
prod = prod.replace('\u0040ENUMNAME\u0040', enumlong)
prod = prod.replace('\u0040ENUMPREFIX\u0040', enumname_prefix)
prod = prod.replace('\u0040enumsince\u0040', enumsince)
if flags:
prod = prod.replace('\u0040type\u0040', 'flags')
else:

View File

@ -153,6 +153,7 @@ enum_name: @enum_name@
ENUMNAME: @ENUMNAME@
ENUMSHORT: @ENUMSHORT@
ENUMPREFIX: @ENUMPREFIX@
enumsince: @enumsince@
type: @type@
Type: @Type@
TYPE: @TYPE@
@ -165,6 +166,7 @@ enum_name: @enum_name@
ENUMNAME: @ENUMNAME@
ENUMSHORT: @ENUMSHORT@
ENUMPREFIX: @ENUMPREFIX@
enumsince: @enumsince@
type: @type@
Type: @Type@
TYPE: @TYPE@
@ -187,6 +189,7 @@ enum_name: @enum_name@
ENUMNAME: @ENUMNAME@
ENUMSHORT: @ENUMSHORT@
ENUMPREFIX: @ENUMPREFIX@
enumsince: @enumsince@
type: @type@
Type: @Type@
TYPE: @TYPE@
@ -225,7 +228,7 @@ file-tail
def assertSingleEnum(self, result, enum_name_camel, enum_name_lower,
enum_name_upper, enum_name_short, enum_prefix,
type_lower, type_camel, type_upper,
enum_since, type_lower, type_camel, type_upper,
value_name, value_nick, value_num):
"""Assert that out (from runMkenumsWithHeader()) contains a single
enum and value matching the given arguments."""
@ -235,6 +238,7 @@ file-tail
'enum_name_upper': enum_name_upper,
'enum_name_short': enum_name_short,
'enum_prefix': enum_prefix,
'enum_since': enum_since,
'type_lower': type_lower,
'type_camel': type_camel,
'type_upper': type_upper,
@ -258,6 +262,7 @@ enum_name: {enum_name_lower}
ENUMNAME: {enum_name_upper}
ENUMSHORT: {enum_name_short}
ENUMPREFIX: {enum_prefix}
enumsince: {enum_since}
type: {type_lower}
Type: {type_camel}
TYPE: {type_upper}
@ -267,6 +272,7 @@ enum_name: {enum_name_lower}
ENUMNAME: {enum_name_upper}
ENUMSHORT: {enum_name_short}
ENUMPREFIX: {enum_prefix}
enumsince: {enum_since}
type: {type_lower}
Type: {type_camel}
TYPE: {type_upper}
@ -283,6 +289,7 @@ enum_name: {enum_name_lower}
ENUMNAME: {enum_name_upper}
ENUMSHORT: {enum_name_short}
ENUMPREFIX: {enum_prefix}
enumsince: {enum_since}
type: {type_lower}
Type: {type_camel}
TYPE: {type_upper}
@ -360,7 +367,7 @@ comment: {standard_bottom_comment}
self.assertEqual('', result.err)
self.assertSingleEnum(result, 'SomeEnumIdentifier',
'some_enum_identifier', 'SOME_ENUM_IDENTIFIER',
'ENUM_IDENTIFIER', 'SOME', 'enum', 'Enum',
'ENUM_IDENTIFIER', 'SOME', '', 'enum', 'Enum',
'ENUM', 'ENUM_VALUE', 'value', '0')
def test_non_utf8_encoding(self):
@ -375,7 +382,7 @@ comment: {standard_bottom_comment}
self.assertIn('WARNING: UnicodeWarning: ', result.err)
self.assertSingleEnum(result, 'SomeEnumIdentifier',
'some_enum_identifier', 'SOME_ENUM_IDENTIFIER',
'ENUM_IDENTIFIER', 'SOME', 'enum', 'Enum',
'ENUM_IDENTIFIER', 'SOME', '', 'enum', 'Enum',
'ENUM', 'ENUM_VALUE', 'value', '0')
def test_reproducible(self):
@ -430,7 +437,7 @@ comment: {standard_bottom_comment}
self.assertEqual('', result.err)
self.assertSingleEnum(result, 'GeglSamplerType',
'gegl_sampler_type', 'GEGL_SAMPLER_TYPE',
'SAMPLER_TYPE', 'GEGL', 'enum', 'Enum',
'SAMPLER_TYPE', 'GEGL', '', 'enum', 'Enum',
'ENUM', 'GEGL_SAMPLER_NEAREST', 'nearest', '0')
def test_filename_basename_in_fhead_ftail(self):
@ -477,6 +484,20 @@ comment
comment: {standard_bottom_comment}
'''.format(**result.subs).strip(), result.out)
def test_since(self):
"""Test user-provided 'since' version handling
https://gitlab.gnome.org/GNOME/glib/-/merge_requests/1492"""
h_contents = '''
typedef enum { /*< since=1.0 >*/
QMI_WMS_MESSAGE_PROTOCOL_CDMA = 0,
} QmiWmsMessageProtocol;
'''
result = self.runMkenumsWithHeader(h_contents)
self.assertEqual('', result.err)
self.assertSingleEnum(result, 'QmiWmsMessageProtocol',
'qmi_wms_message_protocol', 'QMI_WMS_MESSAGE_PROTOCOL',
'WMS_MESSAGE_PROTOCOL', 'QMI', '1.0', 'enum', 'Enum',
'ENUM', 'QMI_WMS_MESSAGE_PROTOCOL_CDMA', 'cdma', '0')
class TestRspMkenums(TestMkenums):
'''Run all tests again in @rspfile mode'''