class-gen: Use a simple hash table instead of NPWValue
[anjuta.git] / plugins / language-support-js / database-symbol.c
blob92cd26a9ef80dbe89e7c07564067367c897e0f87
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3 Copyright (C) 2009 Maxim Ermilov <zaspire@rambler.ru>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program 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
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 #include <string.h>
22 #include "local-symbol.h"
23 #include "std-symbol.h"
24 #include "import-symbol.h"
25 #include "database-symbol.h"
26 #include "util.h"
28 static void database_symbol_interface_init (IJsSymbolIface *iface);
29 static GList* database_symbol_get_arg_list (IJsSymbol *obj);
30 static gint database_symbol_get_base_type (IJsSymbol *obj);
31 static GList* database_symbol_get_func_ret_type (IJsSymbol *obj);
32 static IJsSymbol* database_symbol_get_member (IJsSymbol *obj, const gchar * name);
33 static const gchar * database_symbol_get_name (IJsSymbol *obj);
34 static GList* database_symbol_list_member (IJsSymbol *obj);
36 static IJsSymbol* find (const gchar* name, IJsSymbol *sym);
38 typedef struct _DatabaseSymbolPrivate DatabaseSymbolPrivate;
39 struct _DatabaseSymbolPrivate
41 GList *symbols;
42 LocalSymbol *local;
43 StdSymbol *global;
46 #define DATABASE_SYMBOL_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), DATABASE_TYPE_SYMBOL, DatabaseSymbolPrivate))
48 G_DEFINE_TYPE_WITH_CODE (DatabaseSymbol, database_symbol, G_TYPE_OBJECT,
49 G_IMPLEMENT_INTERFACE (IJS_TYPE_SYMBOL,
50 database_symbol_interface_init));
52 static void
53 database_symbol_init (DatabaseSymbol *object)
55 DatabaseSymbolPrivate *priv = DATABASE_SYMBOL_PRIVATE(object);
56 priv->symbols = NULL;
57 priv->local = NULL;
58 priv->global = NULL;
61 static void
62 database_symbol_finalize (GObject *object)
64 DatabaseSymbolPrivate *priv = DATABASE_SYMBOL_PRIVATE(object);
66 g_object_unref (priv->local);
67 g_object_unref (priv->global);
68 g_list_foreach (priv->symbols, (GFunc)g_object_unref, NULL);
69 g_list_free (priv->symbols);
70 G_OBJECT_CLASS (database_symbol_parent_class)->finalize (object);
73 static void
74 database_symbol_class_init (DatabaseSymbolClass *klass)
76 GObjectClass* object_class = G_OBJECT_CLASS (klass);
77 /* GObjectClass* parent_class = G_OBJECT_CLASS (klass);*/
79 g_type_class_add_private (klass, sizeof (DatabaseSymbolPrivate));
81 object_class->finalize = database_symbol_finalize;
84 void
85 database_symbol_set_file (DatabaseSymbol *object, const gchar* filename)
87 GList *missed;
88 g_assert (DATABASE_IS_SYMBOL (object));
89 DatabaseSymbolPrivate *priv = DATABASE_SYMBOL_PRIVATE (object);
91 if (priv->local)
93 g_object_unref (priv->local);
96 priv->local = local_symbol_new (filename);
97 missed = local_symbol_get_missed_semicolons (priv->local);
98 highlight_lines (missed);
101 DatabaseSymbol*
102 database_symbol_new ()
104 DatabaseSymbol* self = DATABASE_SYMBOL (g_object_new (DATABASE_TYPE_SYMBOL, NULL));
105 DatabaseSymbolPrivate *priv = DATABASE_SYMBOL_PRIVATE (self);
107 priv->global = std_symbol_new ();
108 priv->local = NULL;
109 priv->symbols = g_list_append (NULL, import_symbol_new ());
111 return self;
114 static void
115 database_symbol_interface_init (IJsSymbolIface *iface)
117 iface->get_arg_list = database_symbol_get_arg_list;
118 iface->get_base_type = database_symbol_get_base_type;
119 iface->get_func_ret_type = database_symbol_get_func_ret_type;
121 iface->get_member = database_symbol_get_member;
122 iface->get_name = database_symbol_get_name;
123 iface->list_member = database_symbol_list_member;
126 static GList*
127 database_symbol_get_arg_list (IJsSymbol *obj)
129 g_assert_not_reached ();
130 return NULL;
133 static gint
134 database_symbol_get_base_type (IJsSymbol *obj)
136 return BASE_CLASS;
139 static GList*
140 database_symbol_get_func_ret_type (IJsSymbol *obj)
142 g_assert_not_reached ();
143 return NULL;
146 static IJsSymbol*
147 database_symbol_get_member (IJsSymbol *obj, const gchar * name)
149 DatabaseSymbol* self = DATABASE_SYMBOL (obj);
150 DatabaseSymbolPrivate *priv = DATABASE_SYMBOL_PRIVATE (self);
152 if (!name || strlen (name) == 0)
154 g_object_ref (priv->local);
155 return IJS_SYMBOL (priv->local);
158 GList *i;
159 for (i = priv->symbols; i; i = g_list_next (i))
161 IJsSymbol *t = IJS_SYMBOL (i->data);
162 if (strncmp (name, ijs_symbol_get_name (t), strlen (ijs_symbol_get_name (t))) != 0 )
163 continue;
164 if (strlen (name + strlen (ijs_symbol_get_name (t))) == 0)
166 g_object_ref (t);
167 return t;
169 return find (name + strlen (ijs_symbol_get_name (t)) + 1, t);
172 IJsSymbol *ret = find (name, IJS_SYMBOL (priv->local));
173 if (!ret)
174 ret = find (name, IJS_SYMBOL (priv->global));
176 return ret;
179 static const gchar *
180 database_symbol_get_name (IJsSymbol *obj)
182 g_assert_not_reached ();
183 return NULL;
186 static GList*
187 database_symbol_list_member (IJsSymbol *obj)
189 DatabaseSymbol* self = DATABASE_SYMBOL (obj);
190 DatabaseSymbolPrivate *priv = DATABASE_SYMBOL_PRIVATE (self);
192 GList *ret = NULL;
193 ret = ijs_symbol_list_member (IJS_SYMBOL (priv->global));
194 if (priv->local)
195 ret = g_list_concat (ret, ijs_symbol_list_member (IJS_SYMBOL (priv->local)));
196 ret = g_list_append (ret, g_strdup ("imports"));
197 return ret;
200 GList*
201 database_symbol_list_local_member (DatabaseSymbol *object, gint line)
203 DatabaseSymbolPrivate *priv = DATABASE_SYMBOL_PRIVATE (object);
204 return local_symbol_list_member_with_line (priv->local, line);
207 GList*
208 database_symbol_list_member_with_line (DatabaseSymbol *object, gint line)
210 g_assert (DATABASE_IS_SYMBOL (object));
211 DatabaseSymbolPrivate *priv = DATABASE_SYMBOL_PRIVATE (object);
213 GList *ret = NULL;
214 ret = ijs_symbol_list_member (IJS_SYMBOL (priv->global));
215 if (priv->local)
216 ret = g_list_concat (ret, local_symbol_list_member_with_line (priv->local, line));
217 ret = g_list_append (ret, g_strdup ("imports"));
218 return ret;
221 static IJsSymbol*
222 find (const gchar* name, IJsSymbol *sym)
224 gchar *vname = NULL, *left = NULL;
225 if (!sym)
226 return NULL;
227 if (!name)
228 return NULL;
229 int i;
230 for (i = 0; i < strlen (name); i++)
232 if (name[i] != '.')
233 continue;
234 vname = g_strndup (name, i);
235 left = g_strdup (name + i + 1);
236 break;
238 if (!vname)
239 vname = g_strdup (name);
240 if (strlen (vname) == 0)
242 g_free (vname);
243 g_free (left);
244 return NULL;
246 gboolean is_func_call = *((vname + strlen (vname)) - 1) == ')';
247 if (is_func_call)
248 vname [strlen (vname) - 2] = '\0';
249 GList *j;////TODO
250 for (j = ijs_symbol_list_member (sym); j; j = g_list_next (j))
252 gchar *t = (gchar*)j->data;
253 //puts (t);
254 if (strcmp (vname, t) != 0 )
255 continue;
256 if (!is_func_call)
258 if (!left)
259 return ijs_symbol_get_member (sym, t);
260 IJsSymbol *tjs = ijs_symbol_get_member (sym, t);
261 IJsSymbol *ret = find (left, tjs);
262 g_object_unref (tjs);
263 return ret;
265 else
267 IJsSymbol *s = ijs_symbol_get_member (sym, t);
268 if (!s)
269 return NULL;
270 if (ijs_symbol_get_base_type (s) != BASE_FUNC)
272 g_object_unref (s);
273 return NULL;
275 GList* rets = ijs_symbol_get_func_ret_type (s);
276 g_object_unref (s);
277 if (rets == NULL)
279 return NULL;
281 //TODO: Fix
282 IJsSymbol *ret = global_search (rets->data);
283 if (!ret)
284 return NULL;
285 if (!left)
286 return ret;
287 s = find (left, ret);
288 g_object_unref (ret);
289 return s;
292 return NULL;