sourceview: only cancel open operations when closing editor
[anjuta.git] / plugins / symbol-db / anjuta-tags / jscript.c
blobe7150e92d2475aa226cfb4fb9b0ca9d6099962ae
1 /*
2 Copyright (C) 2009 Maxim Ermilov <zaspire@rambler.ru>
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 #include "general.h" /* must always come first */
20 #include "debug.h"
21 #include "entry.h"
22 #include "keyword.h"
23 #include "parse.h"
24 #include "read.h"
25 #include "routines.h"
26 #include "vstring.h"
27 #include <assert.h>
28 #include "js-parser/jstypes.h"
29 #include <glib.h>
30 #include "js-parser/jsparse.h"
31 #include "js-parser/js-context.h"
32 #include "ctags-utils.h"
34 #include <string.h>
36 static JSTokenPos*
37 getTagPos (JSNode *node)
39 if (node->pn_type == TOK_NAME)
40 return &node->pn_pos;
41 return NULL;
44 #define PROTOTYPE ".prototype"
46 static GList *symbols = NULL;
47 static GList *tags = NULL;
49 static void
50 get_member_list (JSContext *my_cx)
52 GList *i;
54 g_assert (my_cx != NULL);
56 gint plen = strlen (PROTOTYPE);
58 for (i = my_cx->local_var; i; i = g_list_next (i))
60 gint len;
61 gchar *tstr;
62 Var *t = (Var *)i->data;
63 if (!t->name)
64 continue;
65 len = strlen (t->name);
66 if (len <= plen)
67 continue;
68 if (tstr = strstr (t->name, PROTOTYPE), tstr == NULL)
69 continue;
70 if (strlen (tstr) != plen)
72 //TODO:puts (t->name);
73 //Make tag
75 else
77 JSNode *node = t->node;
78 JSNode* iter;
80 g_assert (node->pn_type == TOK_RC);
82 for (iter = node->pn_u.list.head; iter != NULL; iter = iter->pn_next)
84 const gchar* name = js_node_get_name (iter->pn_u.binary.left);
85 const JSTokenPos* pos = getTagPos (iter->pn_u.binary.left);
86 if (!name)
87 g_assert_not_reached ();
88 else
90 gchar *rname = g_strndup (t->name, len - plen);
92 if (g_strcmp0 (name, "__proto__") == 0 )
94 GList *i;
95 Type *t = js_context_get_node_type (my_cx, JS_NODE (iter->pn_u.binary.right));
96 if (!t || !t->name)
97 continue;
98 for (i = tags; i != NULL; i = g_list_next (i))
99 if (g_strcmp0 (((tagEntryInfo *)i->data)->name, rname) == 0)
101 gchar *tn = g_strdup (t->name), *tstr;
102 if (tstr = strstr (tn, PROTOTYPE), tstr != NULL)
104 g_assert (strlen (tstr) == plen);
105 *tstr = '\0';
107 ((tagEntryInfo *)i->data)->extensionFields.inheritance = tn;
108 break;
111 else
113 tagEntryInfo *tag = (tagEntryInfo*)malloc (sizeof (tagEntryInfo));
115 symbols = g_list_append (symbols, g_strdup (name));
117 initTagEntry (tag, name);
118 tag->isFileScope = 1;
119 tag->kindName = "member";
120 tag->kind = 'm';
121 get_file_pos (pos->begin, &tag->filePosition, File.fp);
122 tag->lineNumber = pos->begin;
123 tag->extensionFields.scope[0]="class";
124 tag->extensionFields.scope[1]=rname;
125 JSNode *node = (JSNode *)iter->pn_u.binary.right;
126 if (node && node->pn_arity == PN_FUNC && node->pn_u.func.args)
128 gchar *str = NULL, *t;
129 JSNode *i = node->pn_u.func.args;
130 g_assert (i->pn_arity == PN_LIST);
131 for (i = (JSNode *)i->pn_u.list.head; i; i = (JSNode *)i->pn_next)
133 const gchar *name;
134 g_assert (i->pn_arity == PN_NAME);
135 name = js_node_get_name (i);
136 g_assert (name != NULL);
137 if (str == NULL)
138 str = g_strdup_printf ("( %s", name);
139 else
141 t = g_strdup_printf ("%s, %s", str, name);
142 g_free (str);
143 str = t;
146 t = g_strdup_printf ("%s)", str);
147 g_free (str);
148 str = t;
149 tag->extensionFields.signature = str;
151 makeTagEntry (tag);
157 for (i = my_cx->childs; i; i = g_list_next (i))
159 JSContext *t = (JSContext *)i->data;
160 get_member_list (t);
165 static kindOption JsKinds [] = {
166 { TRUE, 'f', "function", "functions"},
167 { TRUE, 'c', "class", "classes"},
168 { TRUE, 'm', "method", "methods"},
169 { TRUE, 'p', "property", "properties"},
170 { TRUE, 'v', "variable", "global variables"}
173 static void
174 initialize (const langType language)
176 g_type_init ();
179 static void
180 findTags (JSContext *my_cx)
182 GList *i;
183 g_assert (my_cx != NULL);
184 if (my_cx->func_name)
186 const char *name = my_cx->func_name;
187 gint line = my_cx->bline;
188 if (name)
190 tagEntryInfo *tag = (tagEntryInfo*)malloc (sizeof (tagEntryInfo));
191 initTagEntry (tag, name);
192 get_file_pos (line, &tag->filePosition, File.fp);
193 tag->lineNumber = line;
194 tag->isFileScope = 1;
195 tag->kindName = "class";
196 tag->kind = 'c';
198 symbols = g_list_append (symbols, g_strdup (name));
200 if (my_cx->ret_type)
201 tag->extensionFields.returnType = my_cx->ret_type->data;
202 if (my_cx->func_arg)
204 gchar *str = NULL, *t;
205 GList *i;
206 for (i = my_cx->func_arg; i; i = g_list_next (i))
208 g_assert (i->data != NULL);
209 if (i == my_cx->func_arg)
210 str = g_strdup_printf ("( %s", (gchar*)i->data);
211 else
213 t = g_strdup_printf ("%s, %s", str, (gchar*)i->data);
214 g_free (str);
215 str = t;
218 t = g_strdup_printf ("%s)", str);
219 g_free (str);
220 str = t;
221 tag->extensionFields.signature = str;
223 tags = g_list_append (tags, tag);
226 for (i = my_cx->childs; i; i = g_list_next (i))
228 findTags (i->data);
232 static void
233 findGlobal (JSContext *my_cx)
235 static int depth = 0;
236 GList *i;
238 g_assert (my_cx != NULL);
239 g_assert (depth <= 1);
241 for (i = my_cx->local_var; i; i = g_list_next (i))
243 const char *name = ((Var*)i->data)->name;
244 gint line = ((Var*)i->data)->line;
245 g_assert (name != NULL);
247 if (g_strstr_len (name, -1, PROTOTYPE) != NULL)
248 continue;
250 tagEntryInfo *tag = (tagEntryInfo*)malloc (sizeof (tagEntryInfo));
251 initTagEntry (tag, name);
252 get_file_pos (line, &tag->filePosition, File.fp);
253 tag->lineNumber = line;
254 tag->isFileScope = 1;
255 tag->kindName = "variable";
256 tag->kind = 'v';
257 Type *t = js_context_get_node_type (my_cx, ((Var*)i->data)->node);
258 if (t)
260 tag->extensionFields.typeRef [0] = "variable";
261 tag->extensionFields.typeRef [1] = t->name;
262 g_free (t);
264 if (my_cx->ret_type)
265 tag->extensionFields.returnType = my_cx->ret_type->data;
266 if (g_list_find_custom (symbols, name, (GCompareFunc)g_strcmp0) == NULL)
267 makeTagEntry (tag);
269 if (depth == 0)
271 depth++;
272 for (i = my_cx->childs; i; i = g_list_next (i))
274 findGlobal (i->data);
276 depth--;
280 static void
281 findJsTags (void)
283 g_assert (symbols == NULL);
284 g_assert (tags == NULL);
286 JSNode * global = js_node_new_from_file (getInputFileName());
288 JSContext *my_cx;
289 GList *calls = NULL;
290 my_cx = js_context_new_from_node (global, &calls);
291 findTags (my_cx);
293 /*Members*/
295 get_member_list (my_cx);
297 g_list_foreach (tags, (GFunc)makeTagEntry, NULL);
299 findGlobal (my_cx);
301 g_list_free (symbols);
302 symbols = NULL;
304 g_list_free (tags);
305 tags = NULL;
308 extern parserDefinition*
309 JavaScriptParser (void)
311 static const char *const extensions [] = { "js", NULL };
312 parserDefinition *const def = parserNew ("JavaScript");
313 def->extensions = extensions;
315 def->kinds = JsKinds;
316 def->kindCount = KIND_COUNT (JsKinds);
317 def->parser = findJsTags;
318 def->initialize = initialize;
320 return def;