diff options
author | Florian Brosch <flo.brosch@gmail.com> | 2014-07-10 20:35:22 +0200 |
---|---|---|
committer | Luca Bruno <lucabru@src.gnome.org> | 2014-12-25 13:52:29 +0100 |
commit | b1cb07d5d80bd713cffc8c2a92f2329c85ee326f (patch) | |
tree | 91bfbab6de52e057f91948c7f8625e6b5aed51e2 | |
parent | 6c268a67864fe594371925549b6fc94cfb25314f (diff) | |
download | vala-b1cb07d5d80bd713cffc8c2a92f2329c85ee326f.tar.gz |
Introduce [Version (...)]
Parameters:
since: string, version number
experimental: bool (was: [Experimental])
experimental_until: string, version number
deprecated_since: string, version number (was: [Deprecated (since="")])
replacement: string, symbol name (was: [Deprecated (replacement="")])
deprecated: bool (was: [Deprecated])
Used symbols labeled with [Version (since = "")] are checked
against the locally installed package version.
Use --disable-since-check to avoid this behaviour.
Fixes bug 678912.
-rw-r--r-- | codegen/valaccodebasemodule.vala | 6 | ||||
-rw-r--r-- | codegen/valaccodedelegatemodule.vala | 2 | ||||
-rw-r--r-- | codegen/valaccodemethodmodule.vala | 2 | ||||
-rw-r--r-- | codegen/valaccodestructmodule.vala | 4 | ||||
-rw-r--r-- | codegen/valagirwriter.vala | 11 | ||||
-rw-r--r-- | compiler/valacompiler.vala | 3 | ||||
-rw-r--r-- | vala/Makefile.am | 1 | ||||
-rw-r--r-- | vala/valaclass.vala | 6 | ||||
-rw-r--r-- | vala/valacodecontext.vala | 5 | ||||
-rw-r--r-- | vala/valacodewriter.vala | 20 | ||||
-rw-r--r-- | vala/valagirparser.vala | 17 | ||||
-rw-r--r-- | vala/valalambdaexpression.vala | 3 | ||||
-rw-r--r-- | vala/valamemberaccess.vala | 3 | ||||
-rw-r--r-- | vala/valaobjectcreationexpression.vala | 2 | ||||
-rw-r--r-- | vala/valasourcefile.vala | 64 | ||||
-rw-r--r-- | vala/valasymbol.vala | 104 | ||||
-rw-r--r-- | vala/valaversionattribute.vala | 231 | ||||
-rw-r--r-- | vapigen/valagidlparser.vala | 116 |
18 files changed, 430 insertions, 170 deletions
diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala index e1c6a6357..f22b62616 100644 --- a/codegen/valaccodebasemodule.vala +++ b/codegen/valaccodebasemodule.vala @@ -788,7 +788,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator { var cenum = new CCodeEnum (get_ccode_name (en)); - cenum.deprecated = en.deprecated; + cenum.deprecated = en.version.deprecated; int flag_shift = 0; foreach (EnumValue ev in en.get_values ()) { @@ -803,7 +803,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator { ev.value.emit (this); c_ev = new CCodeEnumValue (get_ccode_name (ev), get_cvalue (ev.value)); } - c_ev.deprecated = ev.deprecated; + c_ev.deprecated = ev.version.deprecated; cenum.add_value (c_ev); } @@ -1003,7 +1003,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator { } else { cdecl.modifiers = CCodeModifiers.EXTERN; } - if (f.deprecated) { + if (f.version.deprecated) { cdecl.modifiers |= CCodeModifiers.DEPRECATED; } decl_space.add_type_member_declaration (cdecl); diff --git a/codegen/valaccodedelegatemodule.vala b/codegen/valaccodedelegatemodule.vala index 744f63a1d..346f0a2a6 100644 --- a/codegen/valaccodedelegatemodule.vala +++ b/codegen/valaccodedelegatemodule.vala @@ -116,7 +116,7 @@ public class Vala.CCodeDelegateModule : CCodeArrayModule { } var ctypedef = new CCodeTypeDefinition (return_type_cname, cfundecl); - ctypedef.deprecated = d.deprecated; + ctypedef.deprecated = d.version.deprecated; decl_space.add_type_definition (ctypedef); } diff --git a/codegen/valaccodemethodmodule.vala b/codegen/valaccodemethodmodule.vala index dc70a58c4..49f99cc8b 100644 --- a/codegen/valaccodemethodmodule.vala +++ b/codegen/valaccodemethodmodule.vala @@ -169,7 +169,7 @@ public abstract class Vala.CCodeMethodModule : CCodeStructModule { function.modifiers |= CCodeModifiers.INTERNAL; } - if (m.deprecated) { + if (m.version.deprecated) { function.modifiers |= CCodeModifiers.DEPRECATED; } diff --git a/codegen/valaccodestructmodule.vala b/codegen/valaccodestructmodule.vala index fe2a7c2a7..3f226d55b 100644 --- a/codegen/valaccodestructmodule.vala +++ b/codegen/valaccodestructmodule.vala @@ -64,7 +64,7 @@ public abstract class Vala.CCodeStructModule : CCodeBaseModule { } var instance_struct = new CCodeStruct ("_%s".printf (get_ccode_name (st))); - instance_struct.deprecated = st.deprecated; + instance_struct.deprecated = st.version.deprecated; foreach (Field f in st.get_fields ()) { string field_ctype = get_ccode_name (f.variable_type); @@ -77,7 +77,7 @@ public abstract class Vala.CCodeStructModule : CCodeBaseModule { var suffix = get_ccode_declarator_suffix (f.variable_type); if (suffix != null) { - suffix.deprecated = f.deprecated; + suffix.deprecated = f.version.deprecated; } instance_struct.add_field (field_ctype, get_ccode_name (f), suffix); diff --git a/codegen/valagirwriter.vala b/codegen/valagirwriter.vala index f0a75e292..258f91064 100644 --- a/codegen/valagirwriter.vala +++ b/codegen/valagirwriter.vala @@ -277,12 +277,15 @@ public class Vala.GIRWriter : CodeVisitor { } private void write_symbol_attributes (Symbol symbol) { - if (symbol.deprecated) { - buffer.append_printf (" deprecated=\"%s\"", (symbol.replacement == null) ? "" : "Use %s".printf (symbol.replacement)); - if (symbol.deprecated_since != null) { - buffer.append_printf (" deprecated-version=\"%s\"", symbol.deprecated_since); + if (symbol.version.deprecated) { + buffer.append_printf (" deprecated=\"%s\"", (symbol.version.replacement == null) ? "" : "Use %s".printf (symbol.version.replacement)); + if (symbol.version.deprecated_since != null) { + buffer.append_printf (" deprecated-version=\"%s\"", symbol.version.deprecated_since); } } + if (symbol.version.since != null) { + buffer.append_printf (" version=\"%s\"", symbol.version.since); + } } public override void visit_class (Class cl) { diff --git a/compiler/valacompiler.vala b/compiler/valacompiler.vala index fe0fdb9ae..3c008d30c 100644 --- a/compiler/valacompiler.vala +++ b/compiler/valacompiler.vala @@ -70,6 +70,7 @@ class Vala.Compiler { static bool experimental; static bool experimental_non_null; static bool gobject_tracing; + static bool disable_since_check; static bool disable_warnings; static string cc_command; [CCode (array_length = false, array_null_terminated = true)] @@ -133,6 +134,7 @@ class Vala.Compiler { { "enable-experimental", 0, 0, OptionArg.NONE, ref experimental, "Enable experimental features", null }, { "disable-warnings", 0, 0, OptionArg.NONE, ref disable_warnings, "Disable warnings", null }, { "fatal-warnings", 0, 0, OptionArg.NONE, ref fatal_warnings, "Treat warnings as fatal", null }, + { "disable-since-check", 0, 0, OptionArg.NONE, ref disable_since_check, "Do not check whether used symbols exist in local packages", null }, { "enable-experimental-non-null", 0, 0, OptionArg.NONE, ref experimental_non_null, "Enable experimental enhancements for non-null types", null }, { "enable-gobject-tracing", 0, 0, OptionArg.NONE, ref gobject_tracing, "Enable GObject creation tracing", null }, { "cc", 0, 0, OptionArg.STRING, ref cc_command, "Use COMMAND as C compiler command", "COMMAND" }, @@ -197,6 +199,7 @@ class Vala.Compiler { context.assert = !disable_assert; context.checking = enable_checking; context.deprecated = deprecated; + context.since_check = !disable_since_check; context.hide_internal = hide_internal; context.experimental = experimental; context.experimental_non_null = experimental_non_null; diff --git a/vala/Makefile.am b/vala/Makefile.am index a5a99d173..bd16142d7 100644 --- a/vala/Makefile.am +++ b/vala/Makefile.am @@ -160,6 +160,7 @@ libvalacore_la_VALASOURCES = \ valausingdirective.vala \ valavaluetype.vala \ valavariable.vala \ + valaversionattribute.vala \ valavoidtype.vala \ valawhilestatement.vala \ valayieldstatement.vala \ diff --git a/vala/valaclass.vala b/vala/valaclass.vala index 12a82afd0..61a02acd7 100644 --- a/vala/valaclass.vala +++ b/vala/valaclass.vala @@ -793,8 +793,7 @@ public class Vala.Class : ObjectTypeSymbol { foreach (var impl in base_class.get_methods ()) { if (impl.name == m.name && (impl.base_interface_type == null || impl.base_interface_type.data_type == iface)) { // method is used as interface implementation, so it is not unused - impl.check_deprecated (source_reference); - impl.check_experimental (source_reference); + impl.version.check (source_reference); impl.used = true; implemented = true; break; @@ -820,8 +819,7 @@ public class Vala.Class : ObjectTypeSymbol { } if (sym is Property) { // property is used as interface implementation, so it is not unused - sym.check_deprecated (source_reference); - sym.check_experimental (source_reference); + sym.version.check (source_reference); sym.used = true; } else { error = true; diff --git a/vala/valacodecontext.vala b/vala/valacodecontext.vala index b9ac824c2..0906b480f 100644 --- a/vala/valacodecontext.vala +++ b/vala/valacodecontext.vala @@ -47,6 +47,11 @@ public class Vala.CodeContext { public bool hide_internal { get; set; } /** + * Do not check whether used symbols exist in local packages. + */ + public bool since_check { get; set; } + + /** * Do not warn when using experimental features. */ public bool experimental { get; set; } diff --git a/vala/valacodewriter.vala b/vala/valacodewriter.vala index 2fce86f71..ec48ed03d 100644 --- a/vala/valacodewriter.vala +++ b/vala/valacodewriter.vala @@ -1615,6 +1615,19 @@ public class Vala.CodeWriter : CodeVisitor { } } + private bool skip_since_tag_check (Symbol sym, string since_val) { + Symbol parent_symbol = sym; + + while (parent_symbol.parent_symbol != null) { + parent_symbol = parent_symbol.parent_symbol; + if (parent_symbol.version.since == since_val) { + return true; + } + } + + return false; + } + private void write_attributes (CodeNode node) { var sym = node as Symbol; @@ -1649,6 +1662,13 @@ public class Vala.CodeWriter : CodeVisitor { continue; } + if (sym != null && attr.args.size == 1 && attr.name == "Version") { + string since_val = attr.get_string ("since"); + if (since_val != null && skip_since_tag_check (sym, since_val)) { + continue; + } + } + if (!(node is Parameter) && !(node is PropertyAccessor)) { write_indent (); } diff --git a/vala/valagirparser.vala b/vala/valagirparser.vala index 9d8ef159c..b50a16c1b 100644 --- a/vala/valagirparser.vala +++ b/vala/valagirparser.vala @@ -52,6 +52,7 @@ public class Vala.GirParser : CodeVisitor { DEPRECATED, REPLACEMENT, DEPRECATED_SINCE, + SINCE, ARRAY, ARRAY_LENGTH_IDX, ARRAY_NULL_TERMINATED, @@ -1138,7 +1139,14 @@ public class Vala.GirParser : CodeVisitor { // experimental if (metadata.has_argument (ArgumentType.EXPERIMENTAL)) { - symbol.set_attribute ("Experimental", metadata.get_bool (ArgumentType.EXPERIMENTAL)); + symbol.set_attribute_bool ("Version", "experimental", metadata.get_bool (ArgumentType.EXPERIMENTAL)); + } + + // since + if (metadata.has_argument (ArgumentType.SINCE)) { + symbol.version.since = metadata.get_string (ArgumentType.SINCE); + } else if (symbol is Namespace == false && girdata["version"] != null) { + symbol.version.since = girdata.get ("version"); } if (parent.symbol is Namespace) { @@ -1178,13 +1186,13 @@ public class Vala.GirParser : CodeVisitor { } } if (node.deprecated) { - node.symbol.set_attribute ("Deprecated", true); + node.symbol.version.deprecated = true; } if (node.deprecated_since != null) { - node.symbol.set_attribute_string ("Deprecated", "since", node.deprecated_since); + node.symbol.version.deprecated_since = node.deprecated_since; } if (node.deprecated_replacement != null) { - node.symbol.set_attribute_string ("Deprecated", "replacement", node.deprecated_replacement); + node.symbol.version.replacement = node.deprecated_replacement; } if (node.new_symbol && !node.merged && !metadata.get_bool (ArgumentType.HIDDEN)) { @@ -1829,6 +1837,7 @@ public class Vala.GirParser : CodeVisitor { parse_include (); } else if (reader.name == "package") { var pkg = parse_package (); + this.current_source_file.package_name = pkg; if (context.has_package (pkg)) { // package already provided elsewhere, stop parsing this GIR return; diff --git a/vala/valalambdaexpression.vala b/vala/valalambdaexpression.vala index 691871056..1d6f95713 100644 --- a/vala/valalambdaexpression.vala +++ b/vala/valalambdaexpression.vala @@ -137,8 +137,7 @@ public class Vala.LambdaExpression : Expression { method = new Method (get_lambda_name (context), return_type, source_reference); // track usage for flow analyzer method.used = true; - method.check_deprecated (source_reference); - method.check_experimental (source_reference); + method.version.check (source_reference); if (!cb.has_target || !context.analyzer.is_in_instance_method ()) { method.binding = MemberBinding.STATIC; diff --git a/vala/valamemberaccess.vala b/vala/valamemberaccess.vala index 26a413ca9..2bab0b0df 100644 --- a/vala/valamemberaccess.vala +++ b/vala/valamemberaccess.vala @@ -694,8 +694,7 @@ public class Vala.MemberAccess : Expression { } member.used = true; - member.check_deprecated (source_reference); - member.check_experimental (source_reference); + member.version.check (source_reference); if (access == SymbolAccessibility.PROTECTED) { var target_type = (TypeSymbol) member.parent_symbol; diff --git a/vala/valaobjectcreationexpression.vala b/vala/valaobjectcreationexpression.vala index 6b18efddc..954f77c4c 100644 --- a/vala/valaobjectcreationexpression.vala +++ b/vala/valaobjectcreationexpression.vala @@ -257,7 +257,7 @@ public class Vala.ObjectCreationExpression : Expression { // track usage for flow analyzer symbol_reference.used = true; - symbol_reference.check_deprecated (source_reference); + symbol_reference.version.check (source_reference); } if (symbol_reference != null && symbol_reference.access == SymbolAccessibility.PRIVATE) { diff --git a/vala/valasourcefile.vala b/vala/valasourcefile.vala index e925a6ba2..f02d8443b 100644 --- a/vala/valasourcefile.vala +++ b/vala/valasourcefile.vala @@ -37,6 +37,70 @@ public class Vala.SourceFile { } } + private string _package_name; + + public string? package_name { + get { + if (file_type != SourceFileType.PACKAGE) { + return null; + } + + if (_package_name == null) { + _package_name = Path.get_basename (filename[0:filename.last_index_of_char ('.')]); + } + + return _package_name; + } + set { + _package_name = value; + } + } + + private string? _installed_version = null; + private bool _version_requested = false; + + /** + * The installed package version or null + */ + public string? installed_version { + get { + if (_version_requested) { + return _installed_version; + } + + _version_requested = true; + + string pkg_config_name = package_name; + if (pkg_config_name == null) { + return null; + } + + string? standard_output; + int exit_status; + + try { + Process.spawn_command_line_sync ("pkg-config --silence-errors --modversion %s".printf (pkg_config_name), out standard_output, null, out exit_status); + if (exit_status != 0) { + return null; + } + } catch (GLib.SpawnError err) { + return null; + } + + standard_output = standard_output[0:-1]; + if (standard_output != "") { + _installed_version = standard_output; + } + + return _installed_version; + } + set { + _version_requested = value != null; + _installed_version = value; + } + } + + /** * Specifies whether this file is a VAPI package file. */ diff --git a/vala/valasymbol.vala b/vala/valasymbol.vala index cc9211696..6d0c96300 100644 --- a/vala/valasymbol.vala +++ b/vala/valasymbol.vala @@ -68,62 +68,6 @@ public abstract class Vala.Symbol : CodeNode { public bool active { get; set; default = true; } /** - * Specifies whether this symbol has been deprecated. - */ - public bool deprecated { - get { - if (_deprecated == null) { - _deprecated = get_attribute ("Deprecated") != null; - } - return _deprecated; - } - set { - _deprecated = value; - set_attribute ("Deprecated", _deprecated); - } - } - - /** - * Specifies what version this symbol has been deprecated since. - */ - public string? deprecated_since { - owned get { - return get_attribute_string ("Deprecated", "since"); - } - set { - set_attribute_string ("Deprecated", "since", value); - } - } - - /** - * Specifies the replacement if this symbol has been deprecated. - */ - public string? replacement { - owned get { - return get_attribute_string ("Deprecated", "replacement"); - } - set { - set_attribute_string ("Deprecated", "replacement", value); - } - } - - /** - * Specifies whether this symbol is experimental. - */ - public bool experimental { - get { - if (_experimental == null) { - _experimental = get_attribute ("Experimental") != null; - } - return _experimental; - } - set { - _experimental = value; - set_attribute ("Experimental", value); - } - } - - /** * Specifies whether this symbol has been accessed. */ public bool used { get; set; } @@ -138,6 +82,22 @@ public abstract class Vala.Symbol : CodeNode { public Comment? comment { get; set; } + + private VersionAttribute _version; + + /** + * The associated [Version] attribute + */ + public VersionAttribute version { + get { + if (_version == null) { + _version = new VersionAttribute (this); + } + + return _version; + } + } + /** * Specifies whether this method explicitly hides a member of a base * type. @@ -228,8 +188,6 @@ public abstract class Vala.Symbol : CodeNode { private weak Scope _owner; private Scope _scope; - private bool? _deprecated; - private bool? _experimental; public Symbol (string? name, SourceReference? source_reference, Comment? comment = null) { this.name = name; @@ -413,36 +371,6 @@ public abstract class Vala.Symbol : CodeNode { return isclass; } - /** - * Check to see if the symbol has been deprecated, and emit a warning - * if it has. - */ - public bool check_deprecated (SourceReference? source_ref = null) { - if (external_package && deprecated) { - if (!CodeContext.get ().deprecated) { - Report.deprecated (source_ref, "%s %s%s".printf (get_full_name (), (deprecated_since == null) ? "is deprecated" : "has been deprecated since %s".printf (deprecated_since), (replacement == null) ? "" : ". Use %s".printf (replacement))); - } - return true; - } else { - return false; - } - } - - /** - * Check to see if the symbol is experimental, and emit a warning - * if it is. - */ - public bool check_experimental (SourceReference? source_ref = null) { - if (external_package && experimental) { - if (!CodeContext.get ().experimental) { - Report.experimental (source_ref, "%s is experimental".printf (get_full_name ())); - } - return true; - } else { - return false; - } - } - public Symbol? get_hidden_member () { Symbol sym = null; diff --git a/vala/valaversionattribute.vala b/vala/valaversionattribute.vala new file mode 100644 index 000000000..9c3df391f --- /dev/null +++ b/vala/valaversionattribute.vala @@ -0,0 +1,231 @@ +/* valaversionattribute.vala + * + * Copyright (C) 2013 Florian Brosch + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Author: + * Florian Brosch <flo.brosch@gmail.com> + */ + +using GLib; + + +/** + * Represents a [Version] attribute + */ +public class Vala.VersionAttribute { + private weak Symbol symbol; + + private bool? _deprecated; + private bool? _experimental; + + /** + * Constructs a new VersionAttribute. + * + * @param symbol the owner + * @return a new VersionAttribute + * @see Vala.Symbol + */ + public VersionAttribute (Symbol symbol) { + this.symbol = symbol; + } + + + + /** + * Specifies whether this symbol has been deprecated. + */ + public bool deprecated { + get { + if (_deprecated == null) { + _deprecated = symbol.get_attribute_bool ("Version", "deprecated", false) + || symbol.get_attribute_string ("Version", "deprecated_since") != null + || symbol.get_attribute_string ("Version", "replacement") != null + // [Deprecated] is deprecated + || symbol.get_attribute ("Deprecated") != null; + } + return _deprecated; + } + set { + _deprecated = value; + symbol.set_attribute_bool ("Version", "deprecated", _deprecated); + } + } + + /** + * Specifies what version this symbol has been deprecated since. + */ + public string? deprecated_since { + owned get { + return symbol.get_attribute_string ("Version", "deprecated_since") + // [Deprecated] is deprecated + ?? symbol.get_attribute_string ("Deprecated", "since"); + } + set { + symbol.set_attribute_string ("Version", "deprecated_since", value); + } + } + + /** + * Specifies the replacement if this symbol has been deprecated. + */ + public string? replacement { + owned get { + return symbol.get_attribute_string ("Version", "replacement") + // [Deprecated] is deprecated + ?? symbol.get_attribute_string ("Deprecated", "replacement"); + } + set { + symbol.set_attribute_string ("Version", "replacement", value); + } + } + + + + /** + * Specifies whether this symbol is experimental. + */ + public bool experimental { + get { + if (_experimental == null) { + _experimental = symbol.get_attribute_bool ("Version", "experimental", false) + || symbol.get_attribute_string ("Version", "experimental_until") != null + || symbol.get_attribute ("Experimental") != null; + } + return _experimental; + } + set { + _experimental = value; + symbol.set_attribute_bool ("Version", "experimental", value); + } + } + + /** + * Specifies until which version this symbol is experimental. + */ + public string? experimental_until { + owned get { + return symbol.get_attribute_string ("Version", "experimental_until"); + } + set { + symbol.set_attribute_string ("Version", "experimental_until", value); + } + } + + + + /** + * The minimum version for {@link Vala.VersionAttribute.symbol} + */ + public string? since { + owned get { + return symbol.get_attribute_string ("Version", "since"); + } + set { + symbol.set_attribute_string ("Version", "since", value); + } + } + + + + /** + * Check to see if the symbol is experimental, deprecated or not available + * and emit a warning if it is. + */ + public bool check (SourceReference? source_ref = null) { + bool result = false; + + // deprecation: + if (symbol.external_package && deprecated) { + if (!CodeContext.get ().deprecated) { + Report.deprecated (source_ref, "%s %s%s".printf (symbol.get_full_name (), (deprecated_since == null) ? "is deprecated" : "has been deprecated since %s".printf (deprecated_since), (replacement == null) ? "" : ". Use %s".printf (replacement))); + } + result = true; + } + + // availability: + if (symbol.external_package && since != null) { + string? package_version = symbol.source_reference.file.installed_version; + + if (CodeContext.get ().since_check && package_version != null && VersionAttribute.cmp_versions (package_version, since) < 0) { + unowned string filename = symbol.source_reference.file.filename; + string pkg = Path.get_basename (filename[0:filename.last_index_of_char ('.')]); + Report.error (source_ref, "%s is not available in %s %s. Use %s >= %s".printf (symbol.get_full_name (), pkg, package_version, pkg, since)); + } + result = true; + } + + // experimental: + if (symbol.external_package && experimental) { + if (!CodeContext.get ().experimental) { + string? package_version = symbol.source_reference.file.installed_version; + string? experimental_until = this.experimental_until; + + if (experimental_until == null || package_version == null || VersionAttribute.cmp_versions (package_version, experimental_until) < 0) { + Report.experimental (source_ref, "%s is experimental%s".printf (symbol.get_full_name (), (experimental_until != null) ? " until %s".printf (experimental_until) : "")); + } + } + result = true; + } + + return result; + } + + + /** + * A simple version comparison function. + * + * @param v1str a version number + * @param v2str a version number + * @return an integer less than, equal to, or greater than zero, if v1str is <, == or > than v2str + * @see GLib.CompareFunc + */ + public static int cmp_versions (string v1str, string v2str) { + string[] v1arr = v1str.split ("."); + string[] v2arr = v2str.split ("."); + int i = 0; + + while (v1arr[i] != null && v2arr[i] != null) { + int v1num = int.parse (v1arr[i]); + int v2num = int.parse (v2arr[i]); + + if (v1num < 0 || v2num < 0) { + // invalid format + return 0; + } + + if (v1num > v2num) { + return 1; + } + + if (v1num < v2num) { + return -1; + } + + i++; + } + + if (v1arr[i] != null && v2arr[i] == null) { + return 1; + } + + if (v1arr[i] == null && v2arr[i] != null) { + return -1; + } + + return 0; + } +} diff --git a/vapigen/valagidlparser.vala b/vapigen/valagidlparser.vala index 0dc7fe739..6b78d27fb 100644 --- a/vapigen/valagidlparser.vala +++ b/vapigen/valagidlparser.vala @@ -507,12 +507,12 @@ public class Vala.GIdlParser : CodeVisitor { ns.set_attribute_string ("CCode", "gir_version", eval (nv[1])); } else if (nv[0] == "deprecated") { if (eval (nv[1]) == "1") { - ns.set_attribute ("Deprecated", true); + ns.set_attribute_bool ("Version", "deprecated", true); } } else if (nv[0] == "replacement") { - ns.set_attribute_string ("Deprecated", "replacement", eval (nv[1])); + ns.set_attribute_string ("Version", "replacement", eval (nv[1])); } else if (nv[0] == "deprecated_since") { - ns.set_attribute_string ("Deprecated", "since", eval (nv[1])); + ns.set_attribute_string ("Version", "deprecated_since", eval (nv[1])); } } } @@ -618,12 +618,12 @@ public class Vala.GIdlParser : CodeVisitor { cb.return_type = return_type = parse_type_from_string (eval (nv[1]), return_type.value_owned); } else if (nv[0] == "deprecated") { if (eval (nv[1]) == "1") { - cb.set_attribute ("Deprecated", true); + cb.set_attribute_bool ("Version", "deprecated", true); } } else if (nv[0] == "replacement") { - cb.set_attribute_string ("Deprecated", "replacement", eval (nv[1])); + cb.set_attribute_string ("Version", "replacement", eval (nv[1])); } else if (nv[0] == "deprecated_since") { - cb.set_attribute_string ("Deprecated", "since", eval (nv[1])); + cb.set_attribute_string ("Version", "deprecated_since", eval (nv[1])); } else if (nv[0] == "type_arguments") { parse_type_arguments_from_string (return_type, eval (nv[1])); } else if (nv[0] == "instance_pos") { @@ -634,7 +634,7 @@ public class Vala.GIdlParser : CodeVisitor { } } else if (nv[0] == "experimental") { if (eval (nv[1]) == "1") { - cb.set_attribute ("Experimental", true); + cb.set_attribute_bool ("Version", "experimental", true); } } } @@ -820,19 +820,19 @@ public class Vala.GIdlParser : CodeVisitor { } } else if (nv[0] == "deprecated") { if (eval (nv[1]) == "1") { - st.set_attribute ("Deprecated", true); + st.set_attribute_bool ("Version", "deprecated", true); } } else if (nv[0] == "replacement") { - st.set_attribute_string ("Deprecated", "replacement", eval (nv[1])); + st.set_attribute_string ("Version", "replacement", eval (nv[1])); } else if (nv[0] == "deprecated_since") { - st.set_attribute_string ("Deprecated", "since", eval (nv[1])); + st.set_attribute_string ("Version", "deprecated_since", eval (nv[1])); } else if (nv[0] == "has_destroy_function") { if (eval (nv[1]) == "0") { st.set_attribute_bool ("CCode", "has_destroy_function", false); } } else if (nv[0] == "experimental") { if (eval (nv[1]) == "1") { - st.set_attribute ("Experimental", true); + st.set_attribute_bool ("Version", "experimental", true); } } } @@ -914,19 +914,19 @@ public class Vala.GIdlParser : CodeVisitor { } } else if (nv[0] == "deprecated") { if (eval (nv[1]) == "1") { - cl.set_attribute ("Deprecated", true); + cl.set_attribute_bool ("Version", "deprecated", true); } } else if (nv[0] == "replacement") { - cl.set_attribute_string ("Deprecated", "replacement", eval (nv[1])); + cl.set_attribute_string ("Version", "replacement", eval (nv[1])); } else if (nv[0] == "deprecated_since") { - cl.set_attribute_string ("Deprecated", "since", eval (nv[1])); + cl.set_attribute_string ("Version", "deprecated_since", eval (nv[1])); } else if (nv[0] == "type_parameters") { foreach (string type_param_name in eval (nv[1]).split (",")) { cl.add_type_parameter (new TypeParameter (type_param_name, current_source_reference)); } } else if (nv[0] == "experimental") { if (eval (nv[1]) == "1") { - cl.set_attribute ("Experimental", true); + cl.set_attribute_bool ("Version", "experimental", true); } } else if (nv[0] == "delegate_target_cname") { cl.set_attribute_string ("CCode", "delegate_target_cname", eval (nv[1])); @@ -1015,19 +1015,19 @@ public class Vala.GIdlParser : CodeVisitor { st.set_attribute_string ("CCode", "cheader_filename", eval (nv[1])); } else if (nv[0] == "deprecated") { if (eval (nv[1]) == "1") { - st.set_attribute ("Deprecated", true); + st.set_attribute_bool ("Version", "deprecated", true); } } else if (nv[0] == "replacement") { - st.set_attribute_string ("Deprecated", "replacement", eval (nv[1])); + st.set_attribute_string ("Version", "replacement", eval (nv[1])); } else if (nv[0] == "deprecated_since") { - st.set_attribute_string ("Deprecated", "since", eval (nv[1])); + st.set_attribute_string ("Version", "deprecated_since", eval (nv[1])); } else if (nv[0] == "hidden") { if (eval (nv[1]) == "1") { return; } } else if (nv[0] == "experimental") { if (eval (nv[1]) == "1") { - st.set_attribute ("Experimental", true); + st.set_attribute_bool ("Version", "experimental", true); } } } @@ -1160,12 +1160,12 @@ public class Vala.GIdlParser : CodeVisitor { st.set_attribute_string ("CCode", "cheader_filename", eval (nv[1])); } else if (nv[0] == "deprecated") { if (eval (nv[1]) == "1") { - st.set_attribute ("Deprecated", true); + st.set_attribute_bool ("Version", "deprecated", true); } } else if (nv[0] == "replacement") { - st.set_attribute_string ("Deprecated", "replacement", eval (nv[1])); + st.set_attribute_string ("Version", "replacement", eval (nv[1])); } else if (nv[0] == "deprecated_since") { - st.set_attribute_string ("Deprecated", "since", eval (nv[1])); + st.set_attribute_string ("Version", "deprecated_since", eval (nv[1])); } else if (nv[0] == "immutable") { if (eval (nv[1]) == "1") { st.set_attribute ("Immutable", true); @@ -1180,7 +1180,7 @@ public class Vala.GIdlParser : CodeVisitor { } } else if (nv[0] == "experimental") { if (eval (nv[1]) == "1") { - st.set_attribute ("Experimental", true); + st.set_attribute_bool ("Version", "experimental", true); } } } @@ -1239,12 +1239,12 @@ public class Vala.GIdlParser : CodeVisitor { } } else if (nv[0] == "deprecated") { if (eval (nv[1]) == "1") { - cl.set_attribute ("Deprecated", true); + cl.set_attribute_bool ("Version", "deprecated", true); } } else if (nv[0] == "replacement") { - cl.set_attribute_string ("Deprecated", "replacement", eval (nv[1])); + cl.set_attribute_string ("Version", "replacement", eval (nv[1])); } else if (nv[0] == "deprecated_since") { - cl.set_attribute_string ("Deprecated", "since", eval (nv[1])); + cl.set_attribute_string ("Version", "deprecated_since", eval (nv[1])); } else if (nv[0] == "const_cname") { cl.set_attribute_string ("CCode", "const_cname", eval (nv[1])); } else if (nv[0] == "free_function") { @@ -1261,7 +1261,7 @@ public class Vala.GIdlParser : CodeVisitor { } } else if (nv[0] == "experimental") { if (eval (nv[1]) == "1") { - cl.set_attribute ("Experimental", true); + cl.set_attribute_bool ("Version", "experimental", true); } } } @@ -1401,14 +1401,14 @@ public class Vala.GIdlParser : CodeVisitor { } } else if (nv[0] == "deprecated") { if (eval (nv[1]) == "1") { - en.set_attribute ("Deprecated", true); + en.set_attribute_bool ("Version", "deprecated", true); } } else if (nv[0] == "default_value") { en.set_attribute_string ("CCode", "default_value", eval (nv[1])); } else if (nv[0] == "replacement") { - en.set_attribute_string ("Deprecated", "replacement", eval (nv[1])); + en.set_attribute_string ("Version", "replacement", eval (nv[1])); } else if (nv[0] == "deprecated_since") { - en.set_attribute_string ("Deprecated", "since", eval (nv[1])); + en.set_attribute_string ("Version", "deprecated_since", eval (nv[1])); } else if (nv[0] == "rename_to") { en.name = eval (nv[1]); } else if (nv[0] == "errordomain") { @@ -1425,7 +1425,7 @@ public class Vala.GIdlParser : CodeVisitor { en.add_method (m); } else if (nv[0] == "experimental") { if (eval (nv[1]) == "1") { - en.set_attribute ("Experimental", true); + en.set_attribute_bool ("Version", "experimental", true); } } } @@ -1445,12 +1445,12 @@ public class Vala.GIdlParser : CodeVisitor { is_hidden = true; } else if (nv[0] == "deprecated") { if (eval (nv[1]) == "1") { - ev.set_attribute ("Deprecated", true); + ev.set_attribute_bool ("Version", "deprecated", true); } } else if (nv[0] == "replacement") { - ev.set_attribute_string ("Deprecated", "replacement", eval (nv[1])); + ev.set_attribute_string ("Version", "replacement", eval (nv[1])); } else if (nv[0] == "deprecated_since") { - ev.set_attribute_string ("Deprecated", "since", eval (nv[1])); + ev.set_attribute_string ("Version", "deprecated_since", eval (nv[1])); } } } @@ -1512,12 +1512,12 @@ public class Vala.GIdlParser : CodeVisitor { cl.set_attribute_string ("CCode", "type_check_function", eval (nv[1])); } else if (nv[0] == "deprecated") { if (eval (nv[1]) == "1") { - cl.set_attribute ("Deprecated", true); + cl.set_attribute_bool ("Version", "deprecated", true); } } else if (nv[0] == "replacement") { - cl.set_attribute_string ("Deprecated", "replacement", eval (nv[1])); + cl.set_attribute_string ("Version", "replacement", eval (nv[1])); } else if (nv[0] == "deprecated_since") { - cl.set_attribute_string ("Deprecated", "since", eval (nv[1])); + cl.set_attribute_string ("Version", "deprecated_since", eval (nv[1])); } else if (nv[0] == "type_id") { cl.set_attribute_string ("CCode", "type_id", eval (nv[1])); } else if (nv[0] == "abstract") { @@ -1526,7 +1526,7 @@ public class Vala.GIdlParser : CodeVisitor { } } else if (nv[0] == "experimental") { if (eval (nv[1]) == "1") { - cl.set_attribute ("Experimental", true); + cl.set_attribute_bool ("Version", "experimental", true); } } else if (nv[0] == "compact") { if (eval (nv[1]) == "1") { @@ -2307,12 +2307,12 @@ public class Vala.GIdlParser : CodeVisitor { parse_type_arguments_from_string (return_type, eval (nv[1])); } else if (nv[0] == "deprecated") { if (eval (nv[1]) == "1") { - m.set_attribute ("Deprecated", true); + m.set_attribute_bool ("Version", "deprecated", true); } } else if (nv[0] == "replacement") { - m.set_attribute_string ("Deprecated", "replacement", eval (nv[1])); + m.set_attribute_string ("Version", "replacement", eval (nv[1])); } else if (nv[0] == "deprecated_since") { - m.set_attribute_string ("Deprecated", "since", eval (nv[1])); + m.set_attribute_string ("Version", "deprecated_since", eval (nv[1])); } else if (nv[0] == "cheader_filename") { m.set_attribute_string ("CCode", "cheader_filename", eval (nv[1])); } else if (nv[0] == "abstract") { @@ -2340,7 +2340,7 @@ public class Vala.GIdlParser : CodeVisitor { } } else if (nv[0] == "experimental") { if (eval (nv[1]) == "1") { - m.set_attribute ("Experimental", true); + m.set_attribute_bool ("Version", "experimental", true); } } else if (nv[0] == "simple_generics") { if (eval (nv[1]) == "1") { @@ -2723,12 +2723,12 @@ public class Vala.GIdlParser : CodeVisitor { parse_type_arguments_from_string (prop.property_type, eval (nv[1])); } else if (nv[0] == "deprecated") { if (eval (nv[1]) == "1") { - prop.set_attribute ("Deprecated", true); + prop.set_attribute_bool ("Version", "deprecated", true); } } else if (nv[0] == "replacement") { - prop.set_attribute_string ("Deprecated", "replacement", eval (nv[1])); + prop.set_attribute_string ("Version", "replacement", eval (nv[1])); } else if (nv[0] == "deprecated_since") { - prop.set_attribute_string ("Deprecated", "since", eval (nv[1])); + prop.set_attribute_string ("Version", "deprecated_since", eval (nv[1])); } else if (nv[0] == "accessor_method") { if (eval (nv[1]) == "0") { prop.set_attribute ("NoAccessorMethod", true); @@ -2741,7 +2741,7 @@ public class Vala.GIdlParser : CodeVisitor { prop.property_type = parse_type_from_string (eval (nv[1]), false); } else if (nv[0] == "experimental") { if (eval (nv[1]) == "1") { - prop.set_attribute ("Experimental", true); + prop.set_attribute_bool ("Version", "experimental", true); } } else if (nv[0] == "nullable") { if (eval (nv[1]) == "1" && !(prop.property_type is VoidType)) { @@ -2781,19 +2781,19 @@ public class Vala.GIdlParser : CodeVisitor { c.set_attribute_string ("CCode", "cheader_filename", eval (nv[1])); } else if (nv[0] == "deprecated") { if (eval (nv[1]) == "1") { - c.set_attribute ("Deprecated", true); + c.set_attribute_bool ("Version", "deprecated", true); } } else if (nv[0] == "replacement") { - c.set_attribute_string ("Deprecated", "replacement", eval (nv[1])); + c.set_attribute_string ("Version", "replacement", eval (nv[1])); } else if (nv[0] == "deprecated_since") { - c.set_attribute_string ("Deprecated", "since", eval (nv[1])); + c.set_attribute_string ("Version", "deprecated_since", eval (nv[1])); } else if (nv[0] == "hidden") { if (eval (nv[1]) == "1") { return null; } } else if (nv[0] == "experimental") { if (eval (nv[1]) == "1") { - c.set_attribute ("Experimental", true); + c.set_attribute_bool ("Version", "experimental", true); } } } @@ -2907,19 +2907,19 @@ public class Vala.GIdlParser : CodeVisitor { } if (deprecated) { - field.set_attribute ("Deprecated", true); + field.set_attribute_bool ("Version", "deprecated", true); if (deprecated_since != null) { - field.set_attribute_string ("Deprecated", "since", deprecated_since); + field.set_attribute_string ("Version", "deprecated_since", deprecated_since); } if (replacement != null) { - field.set_attribute_string ("Deprecated", "replacement", replacement); + field.set_attribute_string ("Version", "replacement", replacement); } } if (experimental) { - field.set_attribute ("Experimental", true); + field.set_attribute_bool ("Version", "experimental", true); } if (ctype != null) { @@ -3049,12 +3049,12 @@ public class Vala.GIdlParser : CodeVisitor { } } else if (nv[0] == "deprecated") { if (eval (nv[1]) == "1") { - sig.set_attribute ("Deprecated", true); + sig.set_attribute_bool ("Version", "deprecated", true); } } else if (nv[0] == "replacement") { - sig.set_attribute_string ("Deprecated", "replacement", eval (nv[1])); + sig.set_attribute_string ("Version", "replacement", eval (nv[1])); } else if (nv[0] == "deprecated_since") { - sig.set_attribute_string ("Deprecated", "since", eval (nv[1])); + sig.set_attribute_string ("Version", "deprecated_since", eval (nv[1])); } else if (nv[0] == "transfer_ownership") { if (eval (nv[1]) == "1") { sig.return_type.value_owned = true; @@ -3067,7 +3067,7 @@ public class Vala.GIdlParser : CodeVisitor { parse_type_arguments_from_string (sig.return_type, eval (nv[1])); } else if (nv[0] == "experimental") { if (eval (nv[1]) == "1") { - sig.set_attribute ("Experimental", true); + sig.set_attribute_bool ("Version", "experimental", true); } } } |