2008-02-13 Johannes Schmid <jhs@gnome.org>
[anjuta-git-plugin.git] / tagmanager / tm_workspace.c
blob4c35514382eabb5923c2d4cd033c88b83ff2c727
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
4 * Copyright (c) 2001-2002, Biswapesh Chattopadhyay
6 * This source code is released for free distribution under the terms of the
7 * GNU General Public License.
9 */
11 #include "general.h"
13 /* #include <libanjuta/anjuta-debug.h> */
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <unistd.h>
18 #include <ctype.h>
19 #include <sys/types.h>
20 #include <string.h>
21 #include <glob.h>
22 #include <sys/stat.h>
24 #include "tm_tag.h"
25 #include "tm_workspace.h"
26 #include "tm_project.h"
29 static TMWorkspace *theWorkspace = NULL;
30 guint workspace_class_id = 0;
32 static gboolean
33 tm_create_workspace (void)
35 char *file_name = g_strdup_printf ("%s/anjuta_%ld.%d",
36 P_tmpdir, time (NULL), getpid ());
37 #ifdef TM_DEBUG
38 g_message ("Workspace created: %s", file_name);
39 #endif
41 workspace_class_id = tm_work_object_register (tm_workspace_free,
42 tm_workspace_update,
43 tm_workspace_find_object);
44 theWorkspace = g_new (TMWorkspace, 1);
45 if (FALSE == tm_work_object_init (TM_WORK_OBJECT (theWorkspace),
46 workspace_class_id, file_name, TRUE))
48 g_free (file_name);
49 g_free (theWorkspace);
50 theWorkspace = NULL;
51 g_warning ("Failed to initialize workspace");
52 return FALSE;
55 g_free (file_name);
56 theWorkspace->global_tags = NULL;
57 theWorkspace->work_objects = NULL;
58 return TRUE;
61 void
62 tm_workspace_free (gpointer workspace)
64 guint i;
66 if (workspace != theWorkspace)
67 return;
69 #ifdef TM_DEBUG
70 g_message ("Workspace destroyed");
71 #endif
73 if (theWorkspace)
75 if (theWorkspace->work_objects)
77 for (i = 0; i < theWorkspace->work_objects->len; ++i)
78 tm_work_object_free (theWorkspace->work_objects->pdata[i]);
79 g_ptr_array_free (theWorkspace->work_objects, TRUE);
81 if (theWorkspace->global_tags)
83 for (i = 0; i < theWorkspace->global_tags->len; ++i)
84 tm_tag_free (theWorkspace->global_tags->pdata[i]);
85 g_ptr_array_free (theWorkspace->global_tags, TRUE);
86 tm_tag_chunk_clean ();
88 unlink (theWorkspace->work_object.file_name);
89 tm_work_object_destroy (TM_WORK_OBJECT (theWorkspace));
90 g_free (theWorkspace);
91 theWorkspace = NULL;
95 const TMWorkspace *
96 tm_get_workspace (void)
98 if (NULL == theWorkspace)
99 tm_create_workspace ();
100 return theWorkspace;
103 gboolean
104 tm_workspace_add_object (TMWorkObject * work_object)
106 if (NULL == theWorkspace)
107 tm_create_workspace ();
108 if (NULL == theWorkspace->work_objects)
109 theWorkspace->work_objects = g_ptr_array_new ();
110 g_ptr_array_add (theWorkspace->work_objects, work_object);
111 work_object->parent = TM_WORK_OBJECT (theWorkspace);
112 return TRUE;
115 gboolean
116 tm_workspace_remove_object (TMWorkObject * w, gboolean free)
118 guint i;
119 if ((NULL == theWorkspace) || (NULL == theWorkspace->work_objects)
120 || (NULL == w))
121 return FALSE;
122 for (i = 0; i < theWorkspace->work_objects->len; ++i)
124 if (theWorkspace->work_objects->pdata[i] == w)
126 if (free)
127 tm_work_object_free (w);
128 g_ptr_array_remove_index_fast (theWorkspace->work_objects, i);
129 tm_workspace_update (TM_WORK_OBJECT (theWorkspace), TRUE,
130 FALSE, FALSE);
131 return TRUE;
134 return FALSE;
137 static GPtrArray *
138 tm_workspace_load_tags (GPtrArray * array, const char *tags_file)
140 FILE *fp;
141 TMTag *tag;
142 GPtrArray *tags;
144 if (NULL == (fp = fopen (tags_file, "r")))
145 return NULL;
146 if (array)
147 tags = array;
148 else
149 tags = g_ptr_array_new ();
150 while (NULL != (tag = tm_tag_new_from_file (NULL, fp)))
151 g_ptr_array_add (tags, tag);
152 fclose (fp);
153 return tags;
156 gboolean
157 tm_workspace_load_global_tags (const char *tags_file)
159 if (NULL == theWorkspace)
160 tm_create_workspace ();
161 if (NULL == theWorkspace->global_tags)
163 theWorkspace->global_tags = tm_workspace_load_tags (NULL, tags_file);
164 if (theWorkspace->global_tags)
165 return TRUE;
166 else
167 return FALSE;
169 else
171 if (tm_workspace_load_tags (theWorkspace->global_tags, tags_file))
172 return TRUE;
173 else
174 return FALSE;
178 gboolean
179 tm_workspace_reload_global_tags (const char *tags_file)
181 gint i;
182 if (NULL == theWorkspace)
183 tm_create_workspace ();
185 if (theWorkspace->global_tags)
187 for (i = 0; i < theWorkspace->global_tags->len; ++i)
188 tm_tag_free (theWorkspace->global_tags->pdata[i]);
189 g_ptr_array_free (theWorkspace->global_tags, TRUE);
190 tm_tag_chunk_clean ();
193 theWorkspace->global_tags = tm_workspace_load_tags (NULL, tags_file);
194 if (theWorkspace->global_tags)
195 return TRUE;
196 else
197 return FALSE;
200 static guint
201 tm_file_inode_hash (gconstpointer key)
203 struct stat file_stat;
204 const char *filename = (const char *) key;
205 if (stat (filename, &file_stat) == 0)
207 #ifdef TM_DEBUG
208 g_message ("Hash for '%s' is '%d'\n", filename, file_stat.st_ino);
209 #endif
210 return g_direct_hash (GUINT_TO_POINTER (file_stat.st_ino));
212 else
214 return 0;
218 static void
219 tm_move_entries_to_g_list (gpointer key, gpointer value, gpointer user_data)
221 if (user_data == NULL)
222 return;
224 GList **pp_list = (GList **) user_data;
226 *pp_list = g_list_prepend (*pp_list, value);
229 gboolean
230 tm_workspace_create_global_tags (const char *pre_process, const char **includes,
231 int includes_count, const char *tags_file)
233 glob_t globbuf;
234 int idx_inc;
235 int idx_glob;
236 char *command;
237 guint i;
238 FILE *fp;
239 TMWorkObject *source_file;
240 GPtrArray *tags_array;
241 GHashTable *includes_files_hash;
242 GList *includes_files = NULL;
243 GList *node;
244 char *temp_file = g_strdup_printf ("%s/%d_%ld_1.cpp", P_tmpdir, getpid (),
245 time (NULL));
246 char *temp_file2 = g_strdup_printf ("%s/%d_%ld_2.cpp", P_tmpdir, getpid (),
247 time (NULL));
248 TMTagAttrType sort_attrs[] = {
249 tm_tag_attr_name_t, tm_tag_attr_scope_t,
250 tm_tag_attr_type_t, 0
253 if (NULL == (fp = fopen (temp_file, "w")))
254 return FALSE;
256 globbuf.gl_offs = 0;
257 includes_files_hash = g_hash_table_new_full (tm_file_inode_hash,
258 g_direct_equal, NULL, g_free);
260 for (idx_inc = 0; idx_inc < includes_count; idx_inc++)
262 int dirty_len = strlen (includes[idx_inc]);
263 char *clean_path = malloc (dirty_len - 1);
264 strncpy (clean_path, includes[idx_inc] + 1, dirty_len - 1);
265 clean_path[dirty_len - 2] = 0;
267 #ifdef TM_DEBUG
268 g_message ("[o][%s]\n", clean_path);
269 #endif
270 glob (clean_path, 0, NULL, &globbuf);
272 #ifdef TM_DEBUG
273 g_message ("matches: %d\n", globbuf.gl_pathc);
274 #endif
276 for (idx_glob = 0; idx_glob < globbuf.gl_pathc; idx_glob++)
278 #ifdef TM_DEBUG
279 g_message (">>> %s\n", globbuf.gl_pathv[idx_glob]);
280 #endif
281 if (!g_hash_table_lookup (includes_files_hash,
282 globbuf.gl_pathv[idx_glob]))
284 char *file_name_copy = strdup (globbuf.gl_pathv[idx_glob]);
285 g_hash_table_insert (includes_files_hash, file_name_copy,
286 file_name_copy);
287 #ifdef TM_DEBUG
288 g_message ("Added ...\n");
289 #endif
292 globfree (&globbuf);
293 free (clean_path);
296 /* Checks for duplicate file entries which would case trouble */
297 g_hash_table_foreach (includes_files_hash, tm_move_entries_to_g_list,
298 &includes_files);
300 includes_files = g_list_reverse (includes_files);
302 #ifdef TM_DEBUG
303 g_message ("writing out files to %s\n", temp_file);
304 #endif
305 node = includes_files;
306 while (node)
308 char *str = g_strdup_printf ("#include \"%s\"\n", (char *) node->data);
309 int str_len = strlen (str);
311 fwrite (str, str_len, 1, fp);
312 free (str);
313 node = g_list_next (node);
316 g_list_free (includes_files);
317 g_hash_table_destroy (includes_files_hash);
318 includes_files_hash = NULL;
319 includes_files = NULL;
320 fclose (fp);
322 /* FIXME: The following grep command it be remove the lines
323 * G_BEGIN_DECLS and G_END_DECLS from the header files. The reason is
324 * that in tagmanager, the files are not correctly parsed and the typedefs
325 * following these lines are incorrectly parsed. The real fix should,
326 * of course be in tagmanager (c) parser. This is just a temporary fix.
328 command =
329 g_strdup_printf
330 ("%s %s | grep -v -E '^\\s*(G_BEGIN_DECLS|G_END_DECLS)\\s*$' > %s",
331 pre_process, temp_file, temp_file2);
333 #ifdef TM_DEBUG
334 g_message ("Executing: %s", command);
335 #endif
337 system (command);
338 g_free (command);
339 unlink (temp_file);
340 g_free (temp_file);
341 source_file = tm_source_file_new (temp_file2, TRUE);
342 if (NULL == source_file)
344 unlink (temp_file2);
345 return FALSE;
347 unlink (temp_file2);
348 g_free (temp_file2);
349 if ((NULL == source_file->tags_array) ||
350 (0 == source_file->tags_array->len))
352 tm_source_file_free (source_file);
353 return FALSE;
356 * tags_array = tm_tags_extract(source_file->tags_array, tm_tag_class_t |
357 * tm_tag_typedef_t | tm_tag_prototype_t |
358 * tm_tag_enum_t | tm_tag_macro_with_arg_t);
360 tags_array = tm_tags_extract (source_file->tags_array, tm_tag_max_t);
362 if ((NULL == tags_array) || (0 == tags_array->len))
364 if (tags_array)
365 g_ptr_array_free (tags_array, TRUE);
366 tm_source_file_free (source_file);
367 return FALSE;
369 if (FALSE == tm_tags_sort (tags_array, sort_attrs, TRUE))
371 tm_source_file_free (source_file);
372 return FALSE;
374 if (NULL == (fp = fopen (tags_file, "w")))
376 tm_source_file_free (source_file);
377 return FALSE;
379 for (i = 0; i < tags_array->len; ++i)
382 * tm_tag_write(TM_TAG(tags_array->pdata[i]), fp,
383 * (tm_tag_attr_type_t | tm_tag_attr_scope_t |
384 * tm_tag_attr_arglist_t | tm_tag_attr_vartype_t |
385 * tm_tag_attr_pointer_t));
387 tm_tag_write (TM_TAG (tags_array->pdata[i]), fp, tm_tag_max_t);
389 fclose (fp);
390 tm_source_file_free (source_file);
391 g_ptr_array_free (tags_array, TRUE);
392 return TRUE;
395 static gboolean
396 str_has_suffix (const char *haystack, const char *needle)
398 const char *h, *n;
400 if (needle == NULL)
402 return TRUE;
404 if (haystack == NULL)
406 return needle[0] == '\0';
409 /* Eat one character at a time. */
410 h = haystack + strlen (haystack);
411 n = needle + strlen (needle);
414 if (n == needle)
416 return TRUE;
418 if (h == haystack)
420 return FALSE;
423 while (*--h == *--n);
424 return FALSE;
427 /* Merges a set of tags files. Note that the passed files are gzipped files */
428 gboolean
429 tm_workspace_merge_global_tags (const gchar * output_file, GList * tag_files)
431 int i;
432 FILE *fp;
433 GList *node;
434 GPtrArray *merged_tags, *dedupped_tags;
435 TMTagAttrType sort_attrs[] = {
436 tm_tag_attr_name_t, tm_tag_attr_scope_t,
437 tm_tag_attr_type_t, 0
440 if (!tag_files || !output_file)
441 return FALSE;
443 merged_tags = g_ptr_array_sized_new (15000);
444 node = tag_files;
445 while (node)
447 char *temp_file;
449 if (str_has_suffix ((const char *) node->data, ".gz"))
451 char *command;
452 temp_file = g_strdup_printf ("%s/%d_%ld_1.anjutatags",
453 P_tmpdir, getpid (), time (NULL));
454 command = g_strdup_printf ("gunzip -c '%s' > %s",
455 (const char *) node->data, temp_file);
456 system (command);
457 g_free (command);
458 tm_workspace_load_tags (merged_tags, temp_file);
459 unlink (temp_file);
460 g_free (temp_file);
462 else
464 tm_workspace_load_tags (merged_tags, (const char *) node->data);
466 node = g_list_next (node);
468 if (merged_tags->len <= 0)
470 g_ptr_array_free (merged_tags, TRUE);
471 return FALSE;
474 /* Sort the tags */
475 dedupped_tags = tm_tags_extract (merged_tags, tm_tag_attr_max_t);
477 if (FALSE == tm_tags_sort (dedupped_tags, sort_attrs, TRUE))
479 g_ptr_array_free (dedupped_tags, TRUE);
480 tm_tags_array_free (merged_tags, TRUE);
481 tm_tag_chunk_clean ();
482 return FALSE;
485 /* Save the output */
486 if (NULL == (fp = fopen (output_file, "w")))
488 g_ptr_array_free (dedupped_tags, TRUE);
489 tm_tags_array_free (merged_tags, TRUE);
490 tm_tag_chunk_clean ();
491 return FALSE;
493 for (i = 0; i < dedupped_tags->len; ++i)
495 tm_tag_write (TM_TAG (dedupped_tags->pdata[i]), fp,
496 (tm_tag_attr_type_t | tm_tag_attr_scope_t |
497 tm_tag_attr_arglist_t | tm_tag_attr_vartype_t |
498 tm_tag_attr_pointer_t));
500 fclose (fp);
501 g_ptr_array_free (dedupped_tags, TRUE);
502 tm_tags_array_free (merged_tags, TRUE);
503 tm_tag_chunk_clean ();
504 return TRUE;
507 TMWorkObject *
508 tm_workspace_find_object (TMWorkObject * work_object, const char *file_name,
509 gboolean name_only)
511 TMWorkObject *w = NULL;
512 guint i;
514 if (work_object != TM_WORK_OBJECT (theWorkspace))
515 return NULL;
516 if ((NULL == theWorkspace) || (NULL == theWorkspace->work_objects)
517 || (0 == theWorkspace->work_objects->len))
518 return NULL;
519 for (i = 0; i < theWorkspace->work_objects->len; ++i)
521 if (NULL !=
522 (w =
523 tm_work_object_find (TM_WORK_OBJECT
524 (theWorkspace->work_objects->pdata[i]),
525 file_name, name_only)))
526 return w;
528 return NULL;
531 void
532 tm_workspace_recreate_tags_array (void)
534 guint i, j;
535 TMWorkObject *w;
536 TMTagAttrType sort_attrs[] =
537 { tm_tag_attr_name_t, tm_tag_attr_file_t, tm_tag_attr_scope_t,
538 tm_tag_attr_type_t, 0
541 #ifdef TM_DEBUG
542 g_message ("Recreating workspace tags array");
543 #endif
545 if ((NULL == theWorkspace) || (NULL == theWorkspace->work_objects))
546 return;
547 if (NULL != theWorkspace->work_object.tags_array)
548 g_ptr_array_set_size (theWorkspace->work_object.tags_array, 0);
549 else
550 theWorkspace->work_object.tags_array = g_ptr_array_new ();
552 #ifdef TM_DEBUG
553 g_message ("Total %d objects", theWorkspace->work_objects->len);
554 #endif
555 for (i = 0; i < theWorkspace->work_objects->len; ++i)
557 w = TM_WORK_OBJECT (theWorkspace->work_objects->pdata[i]);
558 #ifdef TM_DEBUG
559 g_message ("Adding tags of %s", w->file_name);
560 #endif
561 if ((NULL != w) && (NULL != w->tags_array) && (w->tags_array->len > 0))
563 for (j = 0; j < w->tags_array->len; ++j)
565 g_ptr_array_add (theWorkspace->work_object.tags_array,
566 w->tags_array->pdata[j]);
570 #ifdef TM_DEBUG
571 g_message ("Total: %d tags", theWorkspace->work_object.tags_array->len);
572 #endif
573 tm_tags_sort (theWorkspace->work_object.tags_array, sort_attrs, TRUE);
576 gboolean
577 tm_workspace_update (TMWorkObject * workspace, gboolean force,
578 gboolean recurse, gboolean __unused__ update_parent)
580 guint i;
581 gboolean update_tags = force;
583 #ifdef TM_DEBUG
584 g_message ("Updating workspace");
585 #endif
587 if (workspace != TM_WORK_OBJECT (theWorkspace))
588 return FALSE;
589 if (NULL == theWorkspace)
590 return TRUE;
591 if ((recurse) && (theWorkspace->work_objects))
593 for (i = 0; i < theWorkspace->work_objects->len; ++i)
595 if (TRUE ==
596 tm_work_object_update (TM_WORK_OBJECT
597 (theWorkspace->work_objects->pdata[i]),
598 FALSE, TRUE, FALSE))
599 update_tags = TRUE;
602 if (update_tags)
603 tm_workspace_recreate_tags_array ();
604 workspace->analyze_time = time (NULL);
605 return update_tags;
608 void
609 tm_workspace_dump (void)
611 if (theWorkspace)
613 #ifdef TM_DEBUG
614 g_message ("Dumping TagManager workspace tree..");
615 #endif
616 tm_work_object_dump (TM_WORK_OBJECT (theWorkspace));
617 if (theWorkspace->work_objects)
619 int i;
620 for (i = 0; i < theWorkspace->work_objects->len; ++i)
622 if (IS_TM_PROJECT
623 (TM_WORK_OBJECT (theWorkspace->work_objects->pdata[i])))
624 tm_project_dump (TM_PROJECT
625 (theWorkspace->work_objects->pdata[i]));
626 else
627 tm_work_object_dump (TM_WORK_OBJECT
628 (theWorkspace->work_objects->
629 pdata[i]));
635 static int
636 fill_find_tags_array (GPtrArray * dst, const GPtrArray * src,
637 const char *name, int type, gboolean partial,
638 gboolean first)
640 TMTag **match;
641 int tagIter, count;
642 size_t len;
644 if ((!src) || (!dst))
645 return 0;
647 if (name == NULL)
649 /* Simply copy all src tags to dst tags */
650 int i;
651 for (i = 0; i < src->len; i++)
653 if (TM_TAG (src->pdata[i])->type & type)
655 g_ptr_array_add (dst, src->pdata[i]);
658 return dst->len;
661 len = strlen (name);
662 if (first)
664 if (!len)
665 return 0;
668 count = 0;
669 match = tm_tags_find (src, name, partial, &count);
670 if (count && match && *match)
672 for (tagIter = 0; tagIter < count; ++tagIter)
674 if (type & match[tagIter]->type)
676 g_ptr_array_add (dst, match[tagIter]);
678 if (first)
680 if (partial)
682 if (0 != strncmp (match[tagIter]->name, name, len))
683 break;
685 else
687 if (0 != strcmp (match[tagIter]->name, name))
688 break;
693 return dst->len;
696 const GPtrArray *
697 tm_workspace_find (const char *name, int type, TMTagAttrType * attrs,
698 gboolean partial, gboolean global_search)
700 static GPtrArray *tags = NULL;
702 if ((!theWorkspace))
703 return NULL;
705 if (tags)
706 g_ptr_array_set_size (tags, 0);
707 else
708 tags = g_ptr_array_new ();
710 fill_find_tags_array (tags, theWorkspace->work_object.tags_array,
711 name, type, partial, TRUE);
712 if (global_search)
714 fill_find_tags_array (tags, theWorkspace->global_tags,
715 name, type, partial, TRUE);
717 if (attrs)
718 tm_tags_sort (tags, attrs, TRUE);
719 return tags;
722 const TMTag *
723 tm_get_current_function (GPtrArray * file_tags, const gulong line)
725 GPtrArray *const local = tm_tags_extract (file_tags, tm_tag_function_t);
726 if (local && local->len)
728 int i;
729 TMTag *tag, *function_tag = NULL;
730 gulong function_line = 0;
731 glong delta;
733 for (i = 0; (i < local->len); ++i)
735 tag = TM_TAG (local->pdata[i]);
736 delta = line - tag->atts.entry.line;
737 if (delta >= 0 && delta < line - function_line)
739 function_tag = tag;
740 function_line = tag->atts.entry.line;
743 g_ptr_array_free (local, TRUE);
744 return function_tag;
746 return NULL;
749 static int
750 find_scope_members_tags (const GPtrArray * all, GPtrArray * tags,
751 const langType langJava, const char *name,
752 const char *filename, gboolean no_definitions)
754 GPtrArray *local = g_ptr_array_new ();
755 unsigned int i;
756 TMTag *tag;
757 size_t len = strlen (name);
758 for (i = 0; (i < all->len); ++i)
760 tag = TM_TAG (all->pdata[i]);
761 if (no_definitions && filename && tag->atts.entry.file &&
762 0 != strcmp (filename,
763 tag->atts.entry.file->work_object.short_name))
765 continue;
767 if (tag && tag->atts.entry.scope && tag->atts.entry.scope[0] != '\0')
769 if (0 == strncmp (name, tag->atts.entry.scope, len))
771 g_ptr_array_add (local, tag);
775 if (local->len > 0)
777 unsigned int j;
778 TMTag *tag2;
779 char backup = 0;
780 char *s_backup = NULL;
781 char *var_type = NULL;
782 char *scope;
783 for (i = 0; (i < local->len); ++i)
785 tag = TM_TAG (local->pdata[i]);
786 scope = tag->atts.entry.scope;
787 if (scope && 0 == strcmp (name, scope))
789 g_ptr_array_add (tags, tag);
790 continue;
792 s_backup = NULL;
793 j = 0; /* someone could write better code :P */
794 while (scope)
796 if (s_backup)
798 backup = s_backup[0];
799 s_backup[0] = '\0';
800 if (0 == strcmp (name, tag->atts.entry.scope))
802 j = local->len;
803 s_backup[0] = backup;
804 break;
807 if (tag->atts.entry.file
808 && tag->atts.entry.file->lang == langJava)
810 scope = strrchr (tag->atts.entry.scope, '.');
811 if (scope)
812 var_type = scope + 1;
814 else
816 scope = strrchr (tag->atts.entry.scope, ':');
817 if (scope)
819 var_type = scope + 1;
820 scope--;
823 if (s_backup)
825 s_backup[0] = backup;
827 if (scope)
829 if (s_backup)
831 backup = s_backup[0];
832 s_backup[0] = '\0';
834 for (j = 0; (j < local->len); ++j)
836 if (i == j)
837 continue;
838 tag2 = TM_TAG (local->pdata[j]);
839 if (tag2->atts.entry.type_ref[1] &&
840 0 == strcmp (var_type, tag2->atts.entry.type_ref[1]))
842 break;
845 if (s_backup)
846 s_backup[0] = backup;
848 if (j < local->len)
850 break;
852 s_backup = scope;
854 if (j == local->len)
856 g_ptr_array_add (tags, tag);
860 g_ptr_array_free (local, TRUE);
861 return (int) tags->len;
865 static int
866 find_namespace_members_tags (const GPtrArray * all, GPtrArray * tags,
867 const langType langJava, const char *name,
868 const char *filename)
870 GPtrArray *local = g_ptr_array_new ();
871 unsigned int i;
872 TMTag *tag;
873 size_t len = strlen (name);
875 g_return_val_if_fail (all != NULL, 0);
877 for (i = 0; (i < all->len); ++i)
879 tag = TM_TAG (all->pdata[i]);
880 if (filename && tag->atts.entry.file &&
881 0 != strcmp (filename,
882 tag->atts.entry.file->work_object.short_name))
884 continue;
887 if (tag && tag->atts.entry.scope && tag->atts.entry.scope[0] != '\0')
889 if (0 == strncmp (name, tag->atts.entry.scope, len))
891 g_ptr_array_add (local, tag);
896 if (local->len > 0)
898 char *scope;
899 for (i = 0; (i < local->len); ++i)
901 tag = TM_TAG (local->pdata[i]);
902 scope = tag->atts.entry.scope;
904 /* if we wanna complete something like
905 * namespace1::
906 * we'll just return the tags that have "namespace1"
907 * as their scope. So we won't return classes/members/namespaces
908 * under, for example, namespace2, where namespace1::namespace2
910 if (scope && 0 == strcmp (name, scope))
912 g_ptr_array_add (tags, tag);
917 g_ptr_array_free (local, TRUE);
918 return (int) tags->len;
921 const GPtrArray *
922 tm_workspace_find_namespace_members (const GPtrArray * file_tags, const char *name,
923 gboolean search_global)
925 static GPtrArray *tags = NULL;
926 GPtrArray *local = NULL;
927 char *new_name = (char *) name;
928 char *filename = NULL;
929 int found = 0, del = 0;
930 static langType langJava = -1;
931 TMTag *tag = NULL;
933 g_return_val_if_fail ((theWorkspace && name && name[0] != '\0'), NULL);
935 if (!tags)
936 tags = g_ptr_array_new ();
938 while (1)
940 const GPtrArray *tags2;
941 int found = 0, types = (tm_tag_class_t | tm_tag_namespace_t |
942 tm_tag_struct_t | tm_tag_typedef_t |
943 tm_tag_union_t | tm_tag_enum_t);
945 if (file_tags)
947 g_ptr_array_set_size (tags, 0);
948 found = fill_find_tags_array (tags, file_tags,
949 new_name, types, FALSE, FALSE);
953 if (found)
955 tags2 = tags;
957 else
959 TMTagAttrType attrs[] = {
960 tm_tag_attr_name_t, tm_tag_attr_type_t,
961 tm_tag_attr_none_t
963 tags2 = tm_workspace_find (new_name, types, attrs, FALSE, TRUE);
966 if ((tags2) && (tags2->len == 1) && (tag = TM_TAG (tags2->pdata[0])))
968 if (tag->type == tm_tag_typedef_t && tag->atts.entry.type_ref[1]
969 && tag->atts.entry.type_ref[1][0] != '\0')
971 new_name = tag->atts.entry.type_ref[1];
972 continue;
974 filename = (tag->atts.entry.file ?
975 tag->atts.entry.file->work_object.short_name : NULL);
976 if (tag->atts.entry.scope && tag->atts.entry.scope[0] != '\0')
978 del = 1;
979 if (tag->atts.entry.file &&
980 tag->atts.entry.file->lang == langJava)
982 new_name = g_strdup_printf ("%s.%s",
983 tag->atts.entry.scope,
984 new_name);
986 else
988 new_name = g_strdup_printf ("%s::%s",
989 tag->atts.entry.scope,
990 new_name);
993 break;
995 else
997 return NULL;
1001 g_ptr_array_set_size (tags, 0);
1003 if (tag && tag->atts.entry.file)
1005 local = tm_tags_extract (tag->atts.entry.file->work_object.tags_array,
1006 (tm_tag_function_t |
1007 tm_tag_field_t | tm_tag_enumerator_t |
1008 tm_tag_namespace_t | tm_tag_class_t ));
1010 else
1012 local = tm_tags_extract (theWorkspace->work_object.tags_array,
1013 (tm_tag_function_t | tm_tag_prototype_t |
1014 tm_tag_member_t |
1015 tm_tag_field_t | tm_tag_enumerator_t |
1016 tm_tag_namespace_t | tm_tag_class_t ));
1019 if (local)
1021 found = find_namespace_members_tags (local, tags,
1022 langJava, new_name, filename);
1023 g_ptr_array_free (local, TRUE);
1027 if (!found && search_global)
1029 GPtrArray *global = tm_tags_extract (theWorkspace->global_tags,
1030 (tm_tag_member_t |
1031 tm_tag_prototype_t |
1032 tm_tag_field_t |
1033 tm_tag_method_t |
1034 tm_tag_function_t |
1035 tm_tag_enumerator_t |
1036 tm_tag_namespace_t |
1037 tm_tag_class_t ));
1039 if (global)
1041 find_namespace_members_tags (global, tags, langJava,
1042 new_name, filename);
1043 /*/
1044 DEBUG_PRINT ("returning these");
1045 gint i;
1046 for (i=0; i < tags->len; i++) {
1047 TMTag *cur_tag;
1049 cur_tag = (TMTag*)g_ptr_array_index (tags, i);
1050 tm_tag_print (cur_tag, stdout );
1052 /*/
1053 g_ptr_array_free (global, TRUE);
1058 if (del)
1060 g_free (new_name);
1063 return tags;
1066 const GPtrArray *
1067 tm_workspace_find_scope_members (const GPtrArray * file_tags, const char *name,
1068 gboolean search_global, gboolean no_definitions)
1070 static GPtrArray *tags = NULL;
1071 GPtrArray *local = NULL;
1072 char *new_name = (char *) name;
1073 char *filename = NULL;
1074 int found = 0, del = 0;
1075 static langType langJava = -1;
1076 TMTag *tag = NULL;
1078 /* FIXME */
1079 /* langJava = getNamedLanguage ("Java"); */
1081 g_return_val_if_fail ((theWorkspace && name && name[0] != '\0'), NULL);
1083 if (!tags)
1084 tags = g_ptr_array_new ();
1086 while (1)
1088 const GPtrArray *tags2;
1089 int found = 0, types = (tm_tag_class_t | tm_tag_namespace_t |
1090 tm_tag_struct_t | tm_tag_typedef_t |
1091 tm_tag_union_t | tm_tag_enum_t);
1093 if (file_tags)
1095 g_ptr_array_set_size (tags, 0);
1096 found = fill_find_tags_array (tags, file_tags,
1097 new_name, types, FALSE, FALSE);
1099 if (found)
1101 tags2 = tags;
1103 else
1105 TMTagAttrType attrs[] = {
1106 tm_tag_attr_name_t, tm_tag_attr_type_t,
1107 tm_tag_attr_none_t
1109 tags2 = tm_workspace_find (new_name, types, attrs, FALSE, TRUE);
1112 if ((tags2) && (tags2->len == 1) && (tag = TM_TAG (tags2->pdata[0])))
1114 if (tag->type == tm_tag_typedef_t && tag->atts.entry.type_ref[1]
1115 && tag->atts.entry.type_ref[1][0] != '\0')
1117 char *tmp_name;
1118 tmp_name = tag->atts.entry.type_ref[1];
1119 if (strcmp(tmp_name, new_name) == 0) {
1120 new_name = NULL;
1122 else {
1123 new_name = tmp_name;
1125 continue;
1127 filename = (tag->atts.entry.file ?
1128 tag->atts.entry.file->work_object.short_name : NULL);
1129 if (tag->atts.entry.scope && tag->atts.entry.scope[0] != '\0')
1131 del = 1;
1132 if (tag->atts.entry.file &&
1133 tag->atts.entry.file->lang == langJava)
1135 new_name = g_strdup_printf ("%s.%s",
1136 tag->atts.entry.scope,
1137 new_name);
1139 else
1141 new_name = g_strdup_printf ("%s::%s",
1142 tag->atts.entry.scope,
1143 new_name);
1146 break;
1148 else
1150 return NULL;
1154 g_ptr_array_set_size (tags, 0);
1156 if (no_definitions && tag && tag->atts.entry.file)
1158 local = tm_tags_extract (tag->atts.entry.file->work_object.tags_array,
1159 (tm_tag_function_t | tm_tag_prototype_t |
1160 tm_tag_member_t | tm_tag_field_t |
1161 tm_tag_method_t | tm_tag_enumerator_t));
1163 else
1165 local = tm_tags_extract (theWorkspace->work_object.tags_array,
1166 (tm_tag_function_t | tm_tag_prototype_t |
1167 tm_tag_member_t | tm_tag_field_t |
1168 tm_tag_method_t | tm_tag_enumerator_t));
1170 if (local)
1172 found = find_scope_members_tags (local, tags, langJava, new_name,
1173 filename, no_definitions);
1174 g_ptr_array_free (local, TRUE);
1176 if (!found && search_global)
1178 GPtrArray *global = tm_tags_extract (theWorkspace->global_tags,
1179 (tm_tag_member_t |
1180 tm_tag_prototype_t |
1181 tm_tag_field_t |
1182 tm_tag_method_t |
1183 tm_tag_function_t |
1184 tm_tag_enumerator_t
1185 |tm_tag_struct_t | tm_tag_typedef_t |
1186 tm_tag_union_t | tm_tag_enum_t));
1187 if (global)
1189 find_scope_members_tags (global, tags, langJava, new_name,
1190 filename, no_definitions);
1191 g_ptr_array_free (global, TRUE);
1194 if (del)
1196 g_free (new_name);
1199 return tags;
1202 const GPtrArray *
1203 tm_workspace_get_parents (const gchar * name)
1205 static TMTagAttrType type[] = { tm_tag_attr_name_t, tm_tag_attr_none_t };
1206 static GPtrArray *parents = NULL;
1207 const GPtrArray *matches;
1208 guint i = 0;
1209 guint j;
1210 gchar **klasses;
1211 gchar **klass;
1212 TMTag *tag;
1214 g_return_val_if_fail (name && isalpha (*name), NULL);
1216 if (NULL == parents)
1217 parents = g_ptr_array_new ();
1218 else
1219 g_ptr_array_set_size (parents, 0);
1220 matches = tm_workspace_find (name, tm_tag_class_t, type, FALSE, TRUE);
1221 if ((NULL == matches) || (0 == matches->len))
1222 return NULL;
1223 g_ptr_array_add (parents, matches->pdata[0]);
1224 while (i < parents->len)
1226 tag = TM_TAG (parents->pdata[i]);
1227 if ((NULL != tag->atts.entry.inheritance) &&
1228 (isalpha (tag->atts.entry.inheritance[0])))
1230 klasses = g_strsplit (tag->atts.entry.inheritance, ",", 10);
1231 for (klass = klasses; (NULL != *klass); ++klass)
1233 for (j = 0; j < parents->len; ++j)
1235 if (0 == strcmp (*klass, TM_TAG (parents->pdata[j])->name))
1236 break;
1238 if (parents->len == j)
1240 matches = tm_workspace_find (*klass, tm_tag_class_t,
1241 type, FALSE, TRUE);
1242 if ((NULL != matches) && (0 < matches->len))
1243 g_ptr_array_add (parents, matches->pdata[0]);
1246 g_strfreev (klasses);
1248 ++i;
1250 return parents;