* src/anjuta.glade, src/anjuta.c, src/main.c, src/anjuta.h:
[anjuta-git-plugin.git] / tagmanager / tm_workspace.c
blob4ac5ea16e1e52032985df63c9a01676d5699ea84
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 match = tm_tags_find (src, name, partial, &count);
669 if (count && match && *match)
671 for (tagIter = 0; tagIter < count; ++tagIter)
673 if (type & match[tagIter]->type)
675 g_ptr_array_add (dst, match[tagIter]);
677 if (first)
679 if (partial)
681 if (0 != strncmp (match[tagIter]->name, name, len))
682 break;
684 else
686 if (0 != strcmp (match[tagIter]->name, name))
687 break;
692 return dst->len;
695 const GPtrArray *
696 tm_workspace_find (const char *name, int type, TMTagAttrType * attrs,
697 gboolean partial, gboolean global_search)
699 static GPtrArray *tags = NULL;
701 if ((!theWorkspace))
702 return NULL;
704 if (tags)
705 g_ptr_array_set_size (tags, 0);
706 else
707 tags = g_ptr_array_new ();
709 fill_find_tags_array (tags, theWorkspace->work_object.tags_array,
710 name, type, partial, TRUE);
711 if (global_search)
713 fill_find_tags_array (tags, theWorkspace->global_tags,
714 name, type, partial, TRUE);
716 if (attrs)
717 tm_tags_sort (tags, attrs, TRUE);
718 return tags;
721 const TMTag *
722 tm_get_current_function (GPtrArray * file_tags, const gulong line)
724 GPtrArray *const local = tm_tags_extract (file_tags, tm_tag_function_t);
725 if (local && local->len)
727 int i;
728 TMTag *tag, *function_tag = NULL;
729 gulong function_line = 0;
730 glong delta;
732 for (i = 0; (i < local->len); ++i)
734 tag = TM_TAG (local->pdata[i]);
735 delta = line - tag->atts.entry.line;
736 if (delta >= 0 && delta < line - function_line)
738 function_tag = tag;
739 function_line = tag->atts.entry.line;
742 g_ptr_array_free (local, TRUE);
743 return function_tag;
745 return NULL;
748 static int
749 find_scope_members_tags (const GPtrArray * all, GPtrArray * tags,
750 const langType langJava, const char *name,
751 const char *filename)
753 GPtrArray *local = g_ptr_array_new ();
754 unsigned int i;
755 TMTag *tag;
756 size_t len = strlen (name);
757 for (i = 0; (i < all->len); ++i)
759 tag = TM_TAG (all->pdata[i]);
760 if (filename && tag->atts.entry.file &&
761 0 != strcmp (filename,
762 tag->atts.entry.file->work_object.short_name))
764 continue;
766 if (tag && tag->atts.entry.scope && tag->atts.entry.scope[0] != '\0')
768 if (0 == strncmp (name, tag->atts.entry.scope, len))
770 g_ptr_array_add (local, tag);
774 if (local->len > 0)
776 unsigned int j;
777 TMTag *tag2;
778 char backup = 0;
779 char *s_backup = NULL;
780 char *var_type = NULL;
781 char *scope;
782 for (i = 0; (i < local->len); ++i)
784 tag = TM_TAG (local->pdata[i]);
785 scope = tag->atts.entry.scope;
786 if (scope && 0 == strcmp (name, scope))
788 g_ptr_array_add (tags, tag);
789 continue;
791 s_backup = NULL;
792 j = 0; /* someone could write better code :P */
793 while (scope)
795 if (s_backup)
797 backup = s_backup[0];
798 s_backup[0] = '\0';
799 if (0 == strcmp (name, tag->atts.entry.scope))
801 j = local->len;
802 s_backup[0] = backup;
803 break;
806 if (tag->atts.entry.file
807 && tag->atts.entry.file->lang == langJava)
809 scope = strrchr (tag->atts.entry.scope, '.');
810 if (scope)
811 var_type = scope + 1;
813 else
815 scope = strrchr (tag->atts.entry.scope, ':');
816 if (scope)
818 var_type = scope + 1;
819 scope--;
822 if (s_backup)
824 s_backup[0] = backup;
826 if (scope)
828 if (s_backup)
830 backup = s_backup[0];
831 s_backup[0] = '\0';
833 for (j = 0; (j < local->len); ++j)
835 if (i == j)
836 continue;
837 tag2 = TM_TAG (local->pdata[j]);
838 if (tag2->atts.entry.type_ref[1] &&
839 0 == strcmp (var_type, tag2->atts.entry.type_ref[1]))
841 break;
844 if (s_backup)
845 s_backup[0] = backup;
847 if (j < local->len)
849 break;
851 s_backup = scope;
853 if (j == local->len)
855 g_ptr_array_add (tags, tag);
859 g_ptr_array_free (local, TRUE);
860 return (int) tags->len;
864 static int
865 find_namespace_members_tags (const GPtrArray * all, GPtrArray * tags,
866 const langType langJava, const char *name,
867 const char *filename)
869 GPtrArray *local = g_ptr_array_new ();
870 unsigned int i;
871 TMTag *tag;
872 size_t len = strlen (name);
874 g_return_val_if_fail (all != NULL, 0);
876 for (i = 0; (i < all->len); ++i)
878 tag = TM_TAG (all->pdata[i]);
879 if (filename && tag->atts.entry.file &&
880 0 != strcmp (filename,
881 tag->atts.entry.file->work_object.short_name))
883 continue;
886 if (tag && tag->atts.entry.scope && tag->atts.entry.scope[0] != '\0')
888 if (0 == strncmp (name, tag->atts.entry.scope, len))
890 g_ptr_array_add (local, tag);
895 if (local->len > 0)
897 char *scope;
898 for (i = 0; (i < local->len); ++i)
900 tag = TM_TAG (local->pdata[i]);
901 scope = tag->atts.entry.scope;
903 /* if we wanna complete something like
904 * namespace1::
905 * we'll just return the tags that have "namespace1"
906 * as their scope. So we won't return classes/members/namespaces
907 * under, for example, namespace2, where namespace1::namespace2
909 if (scope && 0 == strcmp (name, scope))
911 g_ptr_array_add (tags, tag);
916 g_ptr_array_free (local, TRUE);
917 return (int) tags->len;
920 const GPtrArray *
921 tm_workspace_find_namespace_members (const GPtrArray * file_tags, const char *name,
922 gboolean search_global)
924 static GPtrArray *tags = NULL;
925 GPtrArray *local = NULL;
926 char *new_name = (char *) name;
927 char *filename = NULL;
928 int found = 0, del = 0;
929 static langType langJava = -1;
930 TMTag *tag = NULL;
932 g_return_val_if_fail ((theWorkspace && name && name[0] != '\0'), NULL);
934 if (!tags)
935 tags = g_ptr_array_new ();
937 while (1)
939 const GPtrArray *tags2;
940 int found = 0, types = (tm_tag_class_t | tm_tag_namespace_t |
941 tm_tag_struct_t | tm_tag_typedef_t |
942 tm_tag_union_t | tm_tag_enum_t);
944 if (file_tags)
946 g_ptr_array_set_size (tags, 0);
947 found = fill_find_tags_array (tags, file_tags,
948 new_name, types, FALSE, FALSE);
952 if (found)
954 tags2 = tags;
956 else
958 TMTagAttrType attrs[] = {
959 tm_tag_attr_name_t, tm_tag_attr_type_t,
960 tm_tag_attr_none_t
962 tags2 = tm_workspace_find (new_name, types, attrs, FALSE, TRUE);
965 if ((tags2) && (tags2->len == 1) && (tag = TM_TAG (tags2->pdata[0])))
967 if (tag->type == tm_tag_typedef_t && tag->atts.entry.type_ref[1]
968 && tag->atts.entry.type_ref[1][0] != '\0')
970 new_name = tag->atts.entry.type_ref[1];
971 continue;
973 filename = (tag->atts.entry.file ?
974 tag->atts.entry.file->work_object.short_name : NULL);
975 if (tag->atts.entry.scope && tag->atts.entry.scope[0] != '\0')
977 del = 1;
978 if (tag->atts.entry.file &&
979 tag->atts.entry.file->lang == langJava)
981 new_name = g_strdup_printf ("%s.%s",
982 tag->atts.entry.scope,
983 new_name);
985 else
987 new_name = g_strdup_printf ("%s::%s",
988 tag->atts.entry.scope,
989 new_name);
992 break;
994 else
996 return NULL;
1000 g_ptr_array_set_size (tags, 0);
1002 if (tag && tag->atts.entry.file)
1004 local = tm_tags_extract (tag->atts.entry.file->work_object.tags_array,
1005 (tm_tag_function_t |
1006 tm_tag_field_t | tm_tag_enumerator_t |
1007 tm_tag_namespace_t | tm_tag_class_t ));
1009 else
1011 local = tm_tags_extract (theWorkspace->work_object.tags_array,
1012 (tm_tag_function_t | tm_tag_prototype_t |
1013 tm_tag_member_t |
1014 tm_tag_field_t | tm_tag_enumerator_t |
1015 tm_tag_namespace_t | tm_tag_class_t ));
1018 if (local)
1020 found = find_namespace_members_tags (local, tags,
1021 langJava, new_name, filename);
1022 g_ptr_array_free (local, TRUE);
1026 if (!found && search_global)
1028 GPtrArray *global = tm_tags_extract (theWorkspace->global_tags,
1029 (tm_tag_member_t |
1030 tm_tag_prototype_t |
1031 tm_tag_field_t |
1032 tm_tag_method_t |
1033 tm_tag_function_t |
1034 tm_tag_enumerator_t |
1035 tm_tag_namespace_t |
1036 tm_tag_class_t ));
1038 if (global)
1040 find_namespace_members_tags (global, tags, langJava,
1041 new_name, filename);
1042 /*/
1043 DEBUG_PRINT ("returning these");
1044 gint i;
1045 for (i=0; i < tags->len; i++) {
1046 TMTag *cur_tag;
1048 cur_tag = (TMTag*)g_ptr_array_index (tags, i);
1049 tm_tag_print (cur_tag, stdout );
1051 /*/
1052 g_ptr_array_free (global, TRUE);
1057 if (del)
1059 g_free (new_name);
1062 return tags;
1067 const GPtrArray *
1068 tm_workspace_find_scope_members (const GPtrArray * file_tags, const char *name,
1069 gboolean search_global)
1071 static GPtrArray *tags = NULL;
1072 GPtrArray *local = NULL;
1073 char *new_name = (char *) name;
1074 char *filename = NULL;
1075 int found = 0, del = 0;
1076 static langType langJava = -1;
1077 TMTag *tag = NULL;
1079 /* FIXME */
1080 /* langJava = getNamedLanguage ("Java"); */
1082 g_return_val_if_fail ((theWorkspace && name && name[0] != '\0'), NULL);
1084 if (!tags)
1085 tags = g_ptr_array_new ();
1087 while (1)
1089 const GPtrArray *tags2;
1090 int found = 0, types = (tm_tag_class_t | tm_tag_namespace_t |
1091 tm_tag_struct_t | tm_tag_typedef_t |
1092 tm_tag_union_t | tm_tag_enum_t);
1094 if (file_tags)
1096 g_ptr_array_set_size (tags, 0);
1097 found = fill_find_tags_array (tags, file_tags,
1098 new_name, types, FALSE, FALSE);
1100 if (found)
1102 tags2 = tags;
1104 else
1106 TMTagAttrType attrs[] = {
1107 tm_tag_attr_name_t, tm_tag_attr_type_t,
1108 tm_tag_attr_none_t
1110 tags2 = tm_workspace_find (new_name, types, attrs, FALSE, TRUE);
1113 if ((tags2) && (tags2->len == 1) && (tag = TM_TAG (tags2->pdata[0])))
1115 if (tag->type == tm_tag_typedef_t && tag->atts.entry.type_ref[1]
1116 && tag->atts.entry.type_ref[1][0] != '\0')
1118 char *tmp_name;
1119 tmp_name = tag->atts.entry.type_ref[1];
1120 if (strcmp(tmp_name, new_name) == 0) {
1121 new_name = NULL;
1123 else {
1124 new_name = tmp_name;
1126 continue;
1128 filename = (tag->atts.entry.file ?
1129 tag->atts.entry.file->work_object.short_name : NULL);
1130 if (tag->atts.entry.scope && tag->atts.entry.scope[0] != '\0')
1132 del = 1;
1133 if (tag->atts.entry.file &&
1134 tag->atts.entry.file->lang == langJava)
1136 new_name = g_strdup_printf ("%s.%s",
1137 tag->atts.entry.scope,
1138 new_name);
1140 else
1142 new_name = g_strdup_printf ("%s::%s",
1143 tag->atts.entry.scope,
1144 new_name);
1147 break;
1149 else
1151 return NULL;
1155 g_ptr_array_set_size (tags, 0);
1157 if (tag && tag->atts.entry.file)
1159 local = tm_tags_extract (tag->atts.entry.file->work_object.tags_array,
1160 (tm_tag_function_t | tm_tag_prototype_t |
1161 tm_tag_member_t | tm_tag_field_t |
1162 tm_tag_method_t | tm_tag_enumerator_t));
1164 else
1166 local = tm_tags_extract (theWorkspace->work_object.tags_array,
1167 (tm_tag_function_t | tm_tag_prototype_t |
1168 tm_tag_member_t | tm_tag_field_t |
1169 tm_tag_method_t | tm_tag_enumerator_t));
1171 if (local)
1173 found = find_scope_members_tags (local, tags,
1174 langJava, new_name, filename);
1175 g_ptr_array_free (local, TRUE);
1177 if (!found && search_global)
1179 GPtrArray *global = tm_tags_extract (theWorkspace->global_tags,
1180 (tm_tag_member_t |
1181 tm_tag_prototype_t |
1182 tm_tag_field_t |
1183 tm_tag_method_t |
1184 tm_tag_function_t |
1185 tm_tag_enumerator_t
1188 |tm_tag_struct_t | tm_tag_typedef_t |
1189 tm_tag_union_t | tm_tag_enum_t));
1190 if (global)
1192 find_scope_members_tags (global, tags, langJava,
1193 new_name, filename);
1194 g_ptr_array_free (global, TRUE);
1197 if (del)
1199 g_free (new_name);
1202 return tags;
1205 const GPtrArray *
1206 tm_workspace_get_parents (const gchar * name)
1208 static TMTagAttrType type[] = { tm_tag_attr_name_t, tm_tag_attr_none_t };
1209 static GPtrArray *parents = NULL;
1210 const GPtrArray *matches;
1211 guint i = 0;
1212 guint j;
1213 gchar **klasses;
1214 gchar **klass;
1215 TMTag *tag;
1217 g_return_val_if_fail (name && isalpha (*name), NULL);
1219 if (NULL == parents)
1220 parents = g_ptr_array_new ();
1221 else
1222 g_ptr_array_set_size (parents, 0);
1223 matches = tm_workspace_find (name, tm_tag_class_t, type, FALSE, TRUE);
1224 if ((NULL == matches) || (0 == matches->len))
1225 return NULL;
1226 g_ptr_array_add (parents, matches->pdata[0]);
1227 while (i < parents->len)
1229 tag = TM_TAG (parents->pdata[i]);
1230 if ((NULL != tag->atts.entry.inheritance) &&
1231 (isalpha (tag->atts.entry.inheritance[0])))
1233 klasses = g_strsplit (tag->atts.entry.inheritance, ",", 10);
1234 for (klass = klasses; (NULL != *klass); ++klass)
1236 for (j = 0; j < parents->len; ++j)
1238 if (0 == strcmp (*klass, TM_TAG (parents->pdata[j])->name))
1239 break;
1241 if (parents->len == j)
1243 matches = tm_workspace_find (*klass, tm_tag_class_t,
1244 type, FALSE, TRUE);
1245 if ((NULL != matches) && (0 < matches->len))
1246 g_ptr_array_add (parents, matches->pdata[0]);
1249 g_strfreev (klasses);
1251 ++i;
1253 return parents;