Regenerate GIR-based bindings
[vala-gnome.git] / vala / valasourcefile.vala
blob621281dc560ee2c8d0f75643ea7a9acfdd1cfb2b
1 /* valasourcefile.vala
3 * Copyright (C) 2006-2009 Jürg Billeter
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.
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.
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
19 * Author:
20 * Jürg Billeter <j@bitron.ch>
23 using GLib;
25 /**
26 * Represents a Vala source or VAPI package file.
28 public class Vala.SourceFile {
29 /**
30 * The name of this source file.
32 public string filename { get; set; }
34 public string? relative_filename {
35 set {
36 this._relative_filename = value;
40 private string _package_name;
42 public string? package_name {
43 get {
44 if (file_type != SourceFileType.PACKAGE) {
45 return null;
48 if (_package_name == null) {
49 _package_name = Path.get_basename (filename[0:filename.last_index_of_char ('.')]);
52 return _package_name;
54 set {
55 _package_name = value;
59 private string? _installed_version = null;
60 private bool _version_requested = false;
62 /**
63 * The installed package version or null
65 public string? installed_version {
66 get {
67 if (_version_requested) {
68 return _installed_version;
71 _version_requested = true;
73 string pkg_config_name = package_name;
74 if (pkg_config_name == null) {
75 return null;
78 string? standard_output;
79 int exit_status;
81 try {
82 Process.spawn_command_line_sync ("pkg-config --silence-errors --modversion %s".printf (pkg_config_name), out standard_output, null, out exit_status);
83 if (exit_status != 0) {
84 return null;
86 } catch (GLib.SpawnError err) {
87 return null;
90 standard_output = standard_output[0:-1];
91 if (standard_output != "") {
92 _installed_version = standard_output;
95 return _installed_version;
97 set {
98 _version_requested = value != null;
99 _installed_version = value;
105 * Specifies whether this file is a VAPI package file.
107 public SourceFileType file_type { get; set; }
110 * Specifies whether this file came from the command line directly.
112 public bool from_commandline { get; set; }
115 * GIR Namespace for this source file, if it's a VAPI package
118 public string gir_namespace { get; set; }
121 * GIR Namespace version for this source file, if it's a VAPI package
124 public string gir_version { get; set; }
127 * The context this source file belongs to.
129 public weak CodeContext context { get; set; }
131 public string? content {
132 get { return this._content; }
133 set {
134 this._content = value;
135 this.source_array = null;
140 * If the file has been used (ie: if anything in the file has
141 * been emitted into C code as a definition or declaration).
143 public bool used { get; set; }
146 * Whether this source-file was explicitly passed on the commandline.
148 public bool explicit { get; set; }
150 private ArrayList<Comment> comments = new ArrayList<Comment> ();
152 public List<UsingDirective> current_using_directives { get; set; default = new ArrayList<UsingDirective> (); }
154 private List<CodeNode> nodes = new ArrayList<CodeNode> ();
156 string? _relative_filename;
158 private string csource_filename = null;
159 private string cinclude_filename = null;
161 private ArrayList<string> source_array = null;
163 private MappedFile mapped_file = null;
165 private string? _content = null;
168 * Creates a new source file.
170 * @param filename source file name
171 * @return newly created source file
173 public SourceFile (CodeContext context, SourceFileType type, string filename, string? content = null, bool cmdline = false) {
174 this.context = context;
175 this.file_type = type;
176 this.filename = filename;
177 this.content = content;
178 this.from_commandline = cmdline;
182 * Adds a header comment to this source file.
184 public void add_comment (Comment comment) {
185 comments.add (comment);
189 * Returns a copy of the list of header comments.
191 * @return list of comments
193 public List<Comment> get_comments () {
194 return comments;
198 * Adds a new using directive with the specified namespace.
200 * @param ns reference to namespace
202 public void add_using_directive (UsingDirective ns) {
203 // do not modify current_using_directives, it should be considered immutable
204 // for correct symbol resolving
205 var old_using_directives = current_using_directives;
206 current_using_directives = new ArrayList<UsingDirective> ();
207 foreach (var using_directive in old_using_directives) {
208 current_using_directives.add (using_directive);
210 current_using_directives.add (ns);
214 * Adds the specified code node to this source file.
216 * @param node a code node
218 public void add_node (CodeNode node) {
219 nodes.add (node);
222 public void remove_node (CodeNode node) {
223 nodes.remove (node);
227 * Returns a copy of the list of code nodes.
229 * @return code node list
231 public List<CodeNode> get_nodes () {
232 return nodes;
235 public void accept (CodeVisitor visitor) {
236 visitor.visit_source_file (this);
239 public void accept_children (CodeVisitor visitor) {
240 foreach (CodeNode node in nodes) {
241 node.accept (visitor);
245 private string get_subdir () {
246 if (context.basedir == null) {
247 return "";
250 // filename and basedir are already canonicalized
251 if (filename.has_prefix (context.basedir + "/")) {
252 var basename = Path.get_basename (filename);
253 var subdir = filename.substring (context.basedir.length, filename.length - context.basedir.length - basename.length);
254 while (subdir[0] == '/') {
255 subdir = subdir.substring (1);
257 return subdir;
259 return "";
262 private string get_destination_directory () {
263 if (context.directory == null) {
264 return get_subdir ();
266 return Path.build_path ("/", context.directory, get_subdir ());
269 private string get_basename () {
270 int dot = filename.last_index_of_char ('.');
271 return Path.get_basename (filename.substring (0, dot));
274 public string get_relative_filename () {
275 if (_relative_filename != null) {
276 return _relative_filename;
277 } else {
278 return Path.get_basename (filename);
283 * Returns the filename to use when generating C source files.
285 * @return generated C source filename
287 public string get_csource_filename () {
288 if (csource_filename == null) {
289 if (context.run_output) {
290 csource_filename = context.output + ".c";
291 } else if (context.ccode_only || context.save_csources) {
292 csource_filename = Path.build_path ("/", get_destination_directory (), get_basename () + ".c");
293 } else {
294 // temporary file
295 csource_filename = Path.build_path ("/", get_destination_directory (), get_basename () + ".vala.c");
298 return csource_filename;
302 * Returns the filename to use when including the generated C header
303 * file.
305 * @return C header filename to include
307 public string get_cinclude_filename () {
308 if (cinclude_filename == null) {
309 if (context.header_filename != null) {
310 cinclude_filename = Path.get_basename (context.header_filename);
311 if (context.includedir != null) {
312 cinclude_filename = Path.build_path ("/", context.includedir, cinclude_filename);
314 } else {
315 cinclude_filename = Path.build_path ("/", get_subdir (), get_basename () + ".h");
318 return cinclude_filename;
322 * Returns the requested line from this file, loading it if needed.
324 * @param lineno 1-based line number
325 * @return the specified source line
327 public string? get_source_line (int lineno) {
328 if (source_array == null) {
329 if (content != null) {
330 read_source_lines (content);
331 } else {
332 read_source_file ();
335 if (lineno < 1 || lineno > source_array.size) {
336 return null;
338 return source_array.get (lineno - 1);
342 * Parses the input file into ::source_array.
344 private void read_source_file () {
345 string cont;
346 try {
347 FileUtils.get_contents (filename, out cont);
348 } catch (FileError fe) {
349 return;
351 read_source_lines (cont);
354 private void read_source_lines (string cont)
356 source_array = new ArrayList<string> ();
357 string[] lines = cont.split ("\n", 0);
358 int idx;
359 for (idx = 0; lines[idx] != null; ++idx) {
360 source_array.add (lines[idx]);
364 public char* get_mapped_contents () {
365 if (content != null) {
366 return (char*) content;
369 if (mapped_file == null) {
370 try {
371 mapped_file = new MappedFile (filename, false);
372 } catch (FileError e) {
373 Report.error (null, "Unable to map file `%s': %s".printf (filename, e.message));
374 return null;
378 return mapped_file.get_contents ();
381 public size_t get_mapped_length () {
382 if (content != null) {
383 return content.length;
386 return mapped_file.get_length ();
389 public bool check (CodeContext context) {
390 foreach (CodeNode node in nodes) {
391 node.check (context);
393 return true;
397 public enum Vala.SourceFileType {
398 NONE,
399 SOURCE,
400 PACKAGE,
401 FAST