Support simple generics for creation methods
[vala-lang.git] / vapigen / valavapicheck.vala
bloba59b010e2650ca77fdf8c24ae1ad0e45196d3a0f
1 /* valavapicheck.vala
3 * Copyright (C) 2007 Mathias Hasselmann
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 * Mathias Hasselmann <mathias.hasselmann@gmx.de>
23 using GLib;
25 class Vala.VAPICheck : Object {
26 public VAPICheck (string gidlname, CodeContext context = new CodeContext ()) {
27 gidl = new SourceFile (context, gidlname);
28 metadata = new SourceFile (context, gidlname.substring (0, gidlname.len () - 5) + ".metadata");
29 this.context = context;
32 public CodeContext context { get; private set; }
33 public SourceFile gidl { get; private set; }
34 public SourceFile metadata { get; private set; }
36 private List<string> _scope;
37 private Set<string> _symbols;
39 private void parse_gidl () {
40 _scope = new ArrayList<string> ();
41 _symbols = new HashSet<string> (str_hash, str_equal);
43 try {
44 foreach (weak IdlModule module in Idl.parse_file (gidl.filename)) {
45 parse_members (module.name, module.entries);
47 } catch (MarkupError e) {
48 stderr.printf ("%s: %s\n", gidl.filename, e.message);
52 private void add_symbol (string name, string? separator = null) {
54 if (null != separator) {
55 string fullname = get_scope () + separator + name;
56 _symbols.add (fullname);
57 } else {
58 _symbols.add (name);
62 private string get_scope () {
63 return _scope[_scope.size - 1];
66 private void enter_scope (string name) {
67 _scope.add (name);
68 add_symbol (name);
71 private void leave_scope () {
72 _scope.remove_at (_scope.size - 1);
75 private void parse_members (string name, GLib.List<IdlNode> members) {
76 enter_scope (name);
78 foreach (weak IdlNode node in members) {
79 switch (node.type) {
80 case IdlNodeTypeId.ENUM:
81 parse_members (((IdlNodeEnum) node).gtype_name,
82 ((IdlNodeEnum) node).values);
83 break;
85 case IdlNodeTypeId.FUNCTION:
86 parse_members (((IdlNodeFunction) node).symbol,
87 (GLib.List<IdlNode>) ((IdlNodeFunction) node).parameters);
88 break;
90 case IdlNodeTypeId.BOXED:
91 parse_members (((IdlNodeBoxed) node).gtype_name,
92 ((IdlNodeBoxed) node).members);
93 break;
95 case IdlNodeTypeId.INTERFACE:
96 case IdlNodeTypeId.OBJECT:
97 parse_members (((IdlNodeInterface) node).gtype_name,
98 ((IdlNodeInterface) node).members);
99 break;
101 case IdlNodeTypeId.FIELD:
102 case IdlNodeTypeId.PARAM:
103 add_symbol (node.name, ".");
104 break;
106 case IdlNodeTypeId.PROPERTY:
107 case IdlNodeTypeId.SIGNAL:
108 add_symbol (node.name, "::");
109 break;
111 case IdlNodeTypeId.STRUCT:
112 parse_members (node.name, ((IdlNodeStruct) node).members);
113 break;
115 case IdlNodeTypeId.VALUE:
116 case IdlNodeTypeId.VFUNC:
117 // Not appliable?
118 break;
120 default:
121 warning ("TODO: %s: Implement support for type %d nodes", node.name, node.type);
122 break;
126 leave_scope ();
129 private int check_metadata () {
130 try {
131 var metafile = new IOChannel.file (metadata.filename, "r");
132 string line;
133 int lineno = 1;
135 while (IOStatus.NORMAL == metafile.read_line (out line, null, null)) {
136 var tokens = line.split (" ", 2);
137 var symbol = tokens[0];
139 if (symbol.size () > 0 && !_symbols.contains (symbol)) {
140 var src = new SourceReference (metadata, lineno, 1, lineno, (int)symbol.len ());
141 Report.error (src, "Symbol `%s' not found".printf (symbol));
144 lineno += 1;
147 return 0;
148 } catch (Error error) {
149 Report.error (null, "%s: %s".printf (metadata.filename, error.message));
150 return 1;
154 public int run () {
155 if (!FileUtils.test (gidl.filename, FileTest.IS_REGULAR)) {
156 Report.error (null, "%s not found".printf (gidl.filename));
157 return 2;
160 if (!FileUtils.test (metadata.filename, FileTest.IS_REGULAR)) {
161 Report.error (null, "%s not found".printf (metadata.filename));
162 return 2;
165 parse_gidl ();
167 return check_metadata ();
170 static int main (string[] args) {
171 if (2 != args.length || !args[1].has_suffix (".gidl")) {
172 stdout.printf ("Usage: %s library.gidl\n",
173 Path.get_basename (args[0]));
174 return 2;
177 var vapicheck = new VAPICheck (args[1]);
178 return vapicheck.run ();