Line data Source code
1 : /* valaversionattribute.vala
2 : *
3 : * Copyright (C) 2013 Florian Brosch
4 : *
5 : * This library is free software; you can redistribute it and/or
6 : * modify it under the terms of the GNU Lesser General Public
7 : * License as published by the Free Software Foundation; either
8 : * version 2.1 of the License, or (at your option) any later version.
9 : *
10 : * This library is distributed in the hope that it will be useful,
11 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 : * Lesser General Public License for more details.
14 : *
15 : * You should have received a copy of the GNU Lesser General Public
16 : * License along with this library; if not, write to the Free Software
17 : * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 : *
19 : * Author:
20 : * Florian Brosch <flo.brosch@gmail.com>
21 : */
22 :
23 : using GLib;
24 :
25 :
26 : /**
27 : * Represents a [Version] attribute
28 : */
29 1289275 : public class Vala.VersionAttribute {
30 : private weak Symbol symbol;
31 :
32 643926 : private bool? _deprecated;
33 643926 : private bool? _experimental;
34 :
35 : /**
36 : * Constructs a new VersionAttribute.
37 : *
38 : * @param symbol the owner
39 : * @return a new VersionAttribute
40 : * @see Vala.Symbol
41 : */
42 1287852 : public VersionAttribute (Symbol symbol) {
43 643926 : this.symbol = symbol;
44 : }
45 :
46 :
47 :
48 : /**
49 : * Specifies whether this symbol has been deprecated.
50 : */
51 : public bool deprecated {
52 1673010 : get {
53 1673010 : if (_deprecated == null) {
54 4350167 : _deprecated = symbol.get_attribute_bool ("Version", "deprecated", false)
55 624226 : || symbol.has_attribute_argument ("Version", "deprecated_since")
56 624225 : || symbol.has_attribute_argument ("Version", "replacement")
57 : // [Deprecated] is deprecated
58 624212 : || symbol.has_attribute ("Deprecated");
59 : }
60 1673010 : return _deprecated;
61 : }
62 1 : set {
63 1 : _deprecated = value;
64 1 : symbol.set_attribute_bool ("Version", "deprecated", _deprecated);
65 : }
66 : }
67 :
68 : /**
69 : * Specifies what version this symbol has been deprecated since.
70 : */
71 : public string? deprecated_since {
72 55 : owned get {
73 55 : return symbol.get_attribute_string ("Version", "deprecated_since")
74 : // [Deprecated] is deprecated
75 25 : ?? symbol.get_attribute_string ("Deprecated", "since");
76 : }
77 1 : set {
78 1 : symbol.set_attribute_string ("Version", "deprecated_since", value);
79 : }
80 : }
81 :
82 : /**
83 : * Specifies the replacement if this symbol has been deprecated.
84 : */
85 : public string? replacement {
86 43 : owned get {
87 43 : return symbol.get_attribute_string ("Version", "replacement")
88 : // [Deprecated] is deprecated
89 7 : ?? symbol.get_attribute_string ("Deprecated", "replacement");
90 : }
91 0 : set {
92 0 : symbol.set_attribute_string ("Version", "replacement", value);
93 : }
94 : }
95 :
96 :
97 :
98 : /**
99 : * Specifies whether this symbol is experimental.
100 : */
101 : public bool experimental {
102 1636288 : get {
103 1636288 : if (_experimental == null) {
104 1843497 : _experimental = symbol.get_attribute_bool ("Version", "experimental", false)
105 614499 : || symbol.has_attribute_argument ("Version", "experimental_until")
106 614499 : || symbol.has_attribute ("Experimental");
107 : }
108 1636288 : return _experimental;
109 : }
110 0 : set {
111 0 : _experimental = value;
112 0 : symbol.set_attribute_bool ("Version", "experimental", value);
113 : }
114 : }
115 :
116 : /**
117 : * Specifies until which version this symbol is experimental.
118 : */
119 : public string? experimental_until {
120 0 : owned get {
121 0 : return symbol.get_attribute_string ("Version", "experimental_until");
122 : }
123 0 : set {
124 0 : symbol.set_attribute_string ("Version", "experimental_until", value);
125 : }
126 : }
127 :
128 :
129 :
130 : /**
131 : * The minimum version for {@link Vala.VersionAttribute.symbol}
132 : */
133 : public string? since {
134 1649446 : owned get {
135 1649446 : return symbol.get_attribute_string ("Version", "since");
136 : }
137 1 : set {
138 1 : symbol.set_attribute_string ("Version", "since", value);
139 : }
140 : }
141 :
142 :
143 :
144 : /**
145 : * Check to see if the symbol is experimental, deprecated or not available
146 : * and emit a warning if it is.
147 : */
148 1731530 : public bool check (CodeContext context, SourceReference? source_ref = null) {
149 1731530 : bool result = false;
150 :
151 : // deprecation:
152 1731544 : if (symbol.external_package && deprecated) {
153 25 : string? package_version = symbol.source_reference.file.installed_version;
154 :
155 50 : if (!context.deprecated && (package_version == null || deprecated_since == null || VersionAttribute.cmp_versions (package_version, deprecated_since) >= 0)) {
156 50 : Report.deprecated (source_ref, "`%s' %s%s", symbol.get_full_name (), (deprecated_since == null) ? "is deprecated" : "has been deprecated since %s".printf (deprecated_since), (replacement == null) ? "" : ". Use %s".printf (replacement));
157 : }
158 25 : result = true;
159 : }
160 :
161 : // availability:
162 1745011 : if (symbol.external_package && since != null) {
163 13485 : string? package_version = symbol.source_reference.file.installed_version;
164 :
165 13495 : if (context.since_check && package_version != null && VersionAttribute.cmp_versions (package_version, since) < 0) {
166 10 : unowned string filename = symbol.source_reference.file.filename;
167 10 : string pkg = Path.get_basename (filename[0:filename.last_index_of_char ('.')]);
168 10 : Report.error (source_ref, "`%s' is not available in %s %s. Use %s >= %s", symbol.get_full_name (), pkg, package_version, pkg, since);
169 : }
170 13485 : result = true;
171 : }
172 :
173 : // experimental:
174 1731530 : if (symbol.external_package && experimental) {
175 0 : if (!context.experimental) {
176 0 : string? package_version = symbol.source_reference.file.installed_version;
177 0 : string? experimental_until = this.experimental_until;
178 :
179 0 : if (experimental_until == null || package_version == null || VersionAttribute.cmp_versions (package_version, experimental_until) < 0) {
180 0 : Report.experimental (source_ref, "`%s' is experimental%s", symbol.get_full_name (), (experimental_until != null) ? " until %s".printf (experimental_until) : "");
181 : }
182 : }
183 : result = true;
184 : }
185 :
186 : return result;
187 : }
188 :
189 :
190 : /**
191 : * A simple version comparison function.
192 : *
193 : * @param v1str a version number
194 : * @param v2str a version number
195 : * @return an integer less than, equal to, or greater than zero, if v1str is <, == or > than v2str
196 : * @see GLib.CompareFunc
197 : */
198 12849 : public static int cmp_versions (string v1str, string v2str) {
199 12849 : string[] v1arr = v1str.split (".");
200 12849 : string[] v2arr = v2str.split (".");
201 12849 : int i = 0;
202 :
203 25698 : while (v1arr[i] != null && v2arr[i] != null) {
204 25698 : int v1num = int.parse (v1arr[i]);
205 25698 : int v2num = int.parse (v2arr[i]);
206 :
207 25698 : if (v1num < 0 || v2num < 0) {
208 : // invalid format
209 0 : return 0;
210 : }
211 :
212 25698 : if (v1num > v2num) {
213 25678 : return 1;
214 : }
215 :
216 12859 : if (v1num < v2num) {
217 20 : return -1;
218 : }
219 :
220 12849 : i++;
221 : }
222 :
223 0 : if (v1arr[i] != null && v2arr[i] == null) {
224 0 : return 1;
225 : }
226 :
227 0 : if (v1arr[i] == null && v2arr[i] != null) {
228 0 : return -1;
229 : }
230 :
231 0 : return 0;
232 : }
233 : }
|