3 * Copyright (c) 2001-2002, Biswapesh Chattopadhyay
5 * This source code is released for free distribution under the terms of the
6 * GNU General Public License.
11 * @file tm_workspace.h
12 The TMWorkspace structure is meant to be used as a singleton to store application
15 The workspace is intended to contain a list of global tags
16 and a set of work objects (projects or individual files). You need not use the
17 workspace, though, to use tag manager, unless you need things like global tags
18 and a place to store all current open projects and individual files. TMWorkspace
19 is derived from TMWorkObject.
28 #include <sys/types.h>
34 #include <glib/gstdio.h>
37 #include "tm_workspace.h"
38 #include "tm_project.h"
41 static TMWorkspace
*theWorkspace
= NULL
;
42 guint workspace_class_id
= 0;
44 static gboolean
tm_create_workspace(void)
46 workspace_class_id
= tm_work_object_register(tm_workspace_free
, tm_workspace_update
47 , tm_workspace_find_object
);
48 theWorkspace
= g_new(TMWorkspace
, 1);
49 if (FALSE
== tm_work_object_init(TM_WORK_OBJECT(theWorkspace
),
50 workspace_class_id
, NULL
, TRUE
))
54 g_warning("Failed to initialize workspace");
58 theWorkspace
->global_tags
= NULL
;
59 theWorkspace
->work_objects
= NULL
;
63 void tm_workspace_free(gpointer workspace
)
67 if (workspace
!= theWorkspace
)
71 g_message("Workspace destroyed");
76 if (theWorkspace
->work_objects
)
78 for (i
=0; i
< theWorkspace
->work_objects
->len
; ++i
)
79 tm_work_object_free(theWorkspace
->work_objects
->pdata
[i
]);
80 g_ptr_array_free(theWorkspace
->work_objects
, TRUE
);
82 if (theWorkspace
->global_tags
)
84 for (i
=0; i
< theWorkspace
->global_tags
->len
; ++i
)
85 tm_tag_free(theWorkspace
->global_tags
->pdata
[i
]);
86 g_ptr_array_free(theWorkspace
->global_tags
, TRUE
);
88 tm_work_object_destroy(TM_WORK_OBJECT(theWorkspace
));
94 const TMWorkspace
*tm_get_workspace()
96 if (NULL
== theWorkspace
)
97 tm_create_workspace();
101 gboolean
tm_workspace_add_object(TMWorkObject
*work_object
)
103 /* theWorkspace should already have been created otherwise something went wrong */
104 if (NULL
== theWorkspace
)
106 if (NULL
== theWorkspace
->work_objects
)
107 theWorkspace
->work_objects
= g_ptr_array_new();
108 g_ptr_array_add(theWorkspace
->work_objects
, work_object
);
109 work_object
->parent
= TM_WORK_OBJECT(theWorkspace
);
113 gboolean
tm_workspace_remove_object(TMWorkObject
*w
, gboolean do_free
, gboolean update
)
116 if ((NULL
== theWorkspace
) || (NULL
== theWorkspace
->work_objects
)
121 for (i
=0; i
< theWorkspace
->work_objects
->len
; ++i
)
123 if (theWorkspace
->work_objects
->pdata
[i
] == w
)
126 tm_work_object_free(w
);
127 g_ptr_array_remove_index_fast(theWorkspace
->work_objects
, i
);
129 tm_workspace_update(TM_WORK_OBJECT(theWorkspace
), TRUE
, FALSE
, FALSE
);
137 static TMTagAttrType global_tags_sort_attrs
[] =
139 tm_tag_attr_name_t
, tm_tag_attr_scope_t
,
140 tm_tag_attr_type_t
, tm_tag_attr_arglist_t
, 0
143 gboolean
tm_workspace_load_global_tags(const char *tags_file
, gint mode
)
148 gboolean format_pipe
= FALSE
;
150 if (NULL
== (fp
= g_fopen(tags_file
, "r")))
152 if (NULL
== theWorkspace
)
154 if (NULL
== theWorkspace
->global_tags
)
155 theWorkspace
->global_tags
= g_ptr_array_new();
156 if ((NULL
== fgets((gchar
*) buf
, BUFSIZ
, fp
)) || ('\0' == *buf
))
157 return FALSE
; /* early out on error */
159 { /* We read the first line for the format specification. */
160 if (buf
[0] == '#' && strstr((gchar
*) buf
, "format=pipe") != NULL
)
162 else if (buf
[0] == '#' && strstr((gchar
*) buf
, "format=tagmanager") != NULL
)
165 { /* We didn't find a valid format specification, so we try to auto-detect the format
166 * by counting the pipe characters on the first line and asumme pipe format when
167 * we find more than one pipe on the line. */
168 guint i
, pipe_cnt
= 0;
169 for (i
= 0; i
< BUFSIZ
&& buf
[i
] != '\0' && pipe_cnt
< 2; i
++)
174 format_pipe
= (pipe_cnt
> 1);
176 rewind(fp
); /* reset the file pointer, to start reading again from the beginning */
178 while (NULL
!= (tag
= tm_tag_new_from_file(NULL
, fp
, mode
, format_pipe
)))
179 g_ptr_array_add(theWorkspace
->global_tags
, tag
);
182 /* resort the whole array, because tm_tags_find expects a sorted array and it is not sorted
183 * when c99.tags, php.tags and latex.tags are loaded at the same time */
184 tm_tags_sort(theWorkspace
->global_tags
, global_tags_sort_attrs
, TRUE
);
189 static guint
tm_file_inode_hash(gconstpointer key
)
191 struct stat file_stat
;
192 const char *filename
= (const char*)key
;
193 if (g_stat(filename
, &file_stat
) == 0)
196 g_message ("Hash for '%s' is '%d'\n", filename
, file_stat
.st_ino
);
198 return g_direct_hash (GUINT_TO_POINTER (file_stat
.st_ino
));
204 static void tm_move_entries_to_g_list(gpointer key
, gpointer value
, gpointer user_data
)
206 GList
**pp_list
= (GList
**)user_data
;
208 if (user_data
== NULL
)
211 *pp_list
= g_list_prepend(*pp_list
, value
);
214 static void write_includes_file(FILE *fp
, GList
*includes_files
)
218 node
= includes_files
;
221 char *str
= g_strdup_printf("#include \"%s\"\n", (char*)node
->data
);
222 int str_len
= strlen(str
);
225 size
= fwrite(str
, str_len
, 1, fp
);
227 node
= g_list_next (node
);
232 static void append_to_temp_file(FILE *fp
, GList
*file_list
)
239 const char *fname
= node
->data
;
244 if (! g_file_get_contents(fname
, &contents
, &length
, &err
))
246 fprintf(stderr
, "Unable to read file: %s\n", err
->message
);
252 size
= fwrite(contents
, length
, 1, fp
);
253 size
= fwrite("\n", 1, 1, fp
); /* in case file doesn't end in newline (e.g. windows). */
256 node
= g_list_next (node
);
260 gboolean
tm_workspace_create_global_tags(const char *config_dir
, const char *pre_process
,
261 const char **includes
, int includes_count
, const char *tags_file
, int lang
)
271 TMWorkObject
*source_file
;
272 GPtrArray
*tags_array
;
273 GHashTable
*includes_files_hash
;
274 GList
*includes_files
= NULL
;
276 char *temp_file
= g_strdup_printf("%s\\_%d_%ld_1.cpp", config_dir
, getpid(), time(NULL
));
277 char *temp_file2
= g_strdup_printf("%s\\_%d_%ld_2.cpp", config_dir
, getpid(), time(NULL
));
279 char *temp_file
= g_strdup_printf("%s/%d_%ld_1.cpp", config_dir
, getpid(), time(NULL
));
280 char *temp_file2
= g_strdup_printf("%s/%d_%ld_2.cpp", config_dir
, getpid(), time(NULL
));
283 if (NULL
== theWorkspace
|| NULL
== (fp
= g_fopen(temp_file
, "w")))
286 includes_files_hash
= g_hash_table_new_full (tm_file_inode_hash
,
293 if (includes
[0][0] == '"') /* leading \" char for glob matching */
294 for(idx_inc
= 0; idx_inc
< includes_count
; idx_inc
++)
296 int dirty_len
= strlen(includes
[idx_inc
]);
297 char *clean_path
= g_malloc(dirty_len
- 1);
298 strncpy(clean_path
, includes
[idx_inc
] + 1, dirty_len
- 1);
299 clean_path
[dirty_len
- 2] = 0;
302 g_message ("[o][%s]\n", clean_path
);
304 glob(clean_path
, 0, NULL
, &globbuf
);
307 g_message ("matches: %d\n", globbuf
.gl_pathc
);
310 for(idx_glob
= 0; idx_glob
< globbuf
.gl_pathc
; idx_glob
++)
313 g_message (">>> %s\n", globbuf
.gl_pathv
[idx_glob
]);
315 if (!g_hash_table_lookup(includes_files_hash
,
316 globbuf
.gl_pathv
[idx_glob
]))
318 char* file_name_copy
= strdup(globbuf
.gl_pathv
[idx_glob
]);
319 g_hash_table_insert(includes_files_hash
, file_name_copy
,
322 g_message ("Added ...\n");
331 /* no glob support or globbing not wanted */
332 for(idx_inc
= 0; idx_inc
< includes_count
; idx_inc
++)
334 if (!g_hash_table_lookup(includes_files_hash
,
337 char* file_name_copy
= strdup(includes
[idx_inc
]);
338 g_hash_table_insert(includes_files_hash
, file_name_copy
,
343 /* Checks for duplicate file entries which would case trouble */
344 g_hash_table_foreach(includes_files_hash
, tm_move_entries_to_g_list
,
347 includes_files
= g_list_reverse (includes_files
);
350 g_message ("writing out files to %s\n", temp_file
);
352 if (pre_process
!= NULL
)
353 write_includes_file(fp
, includes_files
);
355 append_to_temp_file(fp
, includes_files
);
357 g_list_free (includes_files
);
358 g_hash_table_destroy(includes_files_hash
);
359 includes_files_hash
= NULL
;
360 includes_files
= NULL
;
363 /* FIXME: The following grep command removes the lines
364 * G_BEGIN_DECLS and G_END_DECLS from the header files. The reason is
365 * that in tagmanager, the files are not correctly parsed and the typedefs
366 * following these lines are incorrectly parsed. The real fix should,
367 * of course be in tagmanager (c) parser. This is just a temporary fix.
369 if (pre_process
!= NULL
)
372 command
= g_strdup_printf("%s %s | grep -v -E '^\\s*(G_BEGIN_DECLS|G_END_DECLS)\\s*$' > %s",
373 pre_process
, temp_file
, temp_file2
);
375 g_message("Executing: %s", command
);
377 ret
= system(command
);
384 /* no pre-processing needed, so temp_file2 = temp_file */
386 temp_file2
= temp_file
;
389 source_file
= tm_source_file_new(temp_file2
, TRUE
, tm_source_file_get_lang_name(lang
));
390 if (NULL
== source_file
)
392 g_unlink(temp_file2
);
395 g_unlink(temp_file2
);
397 if ((NULL
== source_file
->tags_array
) || (0 == source_file
->tags_array
->len
))
399 tm_source_file_free(source_file
);
402 tags_array
= tm_tags_extract(source_file
->tags_array
, tm_tag_max_t
);
403 if ((NULL
== tags_array
) || (0 == tags_array
->len
))
406 g_ptr_array_free(tags_array
, TRUE
);
407 tm_source_file_free(source_file
);
410 if (FALSE
== tm_tags_sort(tags_array
, global_tags_sort_attrs
, TRUE
))
412 tm_source_file_free(source_file
);
415 if (NULL
== (fp
= g_fopen(tags_file
, "w")))
417 tm_source_file_free(source_file
);
420 fprintf(fp
, "# format=tagmanager\n");
421 for (i
= 0; i
< tags_array
->len
; ++i
)
423 tm_tag_write(TM_TAG(tags_array
->pdata
[i
]), fp
, tm_tag_attr_type_t
424 | tm_tag_attr_scope_t
| tm_tag_attr_arglist_t
| tm_tag_attr_vartype_t
425 | tm_tag_attr_pointer_t
);
428 tm_source_file_free(source_file
);
429 g_ptr_array_free(tags_array
, TRUE
);
433 TMWorkObject
*tm_workspace_find_object(TMWorkObject
*work_object
, const char *file_name
434 , gboolean name_only
)
436 TMWorkObject
*w
= NULL
;
439 if (work_object
!= TM_WORK_OBJECT(theWorkspace
))
441 if ((NULL
== theWorkspace
) || (NULL
== theWorkspace
->work_objects
)
442 || (0 == theWorkspace
->work_objects
->len
))
444 for (i
= 0; i
< theWorkspace
->work_objects
->len
; ++i
)
446 if (NULL
!= (w
= tm_work_object_find(TM_WORK_OBJECT(theWorkspace
->work_objects
->pdata
[i
])
447 , file_name
, name_only
)))
453 void tm_workspace_recreate_tags_array(void)
457 TMTagAttrType sort_attrs
[] = { tm_tag_attr_name_t
, tm_tag_attr_file_t
458 , tm_tag_attr_scope_t
, tm_tag_attr_type_t
, tm_tag_attr_arglist_t
, 0};
461 g_message("Recreating workspace tags array");
464 if ((NULL
== theWorkspace
) || (NULL
== theWorkspace
->work_objects
))
466 if (NULL
!= theWorkspace
->work_object
.tags_array
)
467 g_ptr_array_set_size(theWorkspace
->work_object
.tags_array
, 0);
469 theWorkspace
->work_object
.tags_array
= g_ptr_array_new();
472 g_message("Total %d objects", theWorkspace
->work_objects
->len
);
474 for (i
=0; i
< theWorkspace
->work_objects
->len
; ++i
)
476 w
= TM_WORK_OBJECT(theWorkspace
->work_objects
->pdata
[i
]);
478 g_message("Adding tags of %s", w
->file_name
);
480 if ((NULL
!= w
) && (NULL
!= w
->tags_array
) && (w
->tags_array
->len
> 0))
482 for (j
= 0; j
< w
->tags_array
->len
; ++j
)
484 g_ptr_array_add(theWorkspace
->work_object
.tags_array
,
485 w
->tags_array
->pdata
[j
]);
490 g_message("Total: %d tags", theWorkspace
->work_object
.tags_array
->len
);
492 tm_tags_sort(theWorkspace
->work_object
.tags_array
, sort_attrs
, TRUE
);
495 gboolean
tm_workspace_update(TMWorkObject
*workspace
, gboolean force
496 , gboolean recurse
, gboolean __unused__ update_parent
)
499 gboolean update_tags
= force
;
502 g_message("Updating workspace");
505 if (workspace
!= TM_WORK_OBJECT(theWorkspace
))
507 if (NULL
== theWorkspace
)
509 if ((recurse
) && (theWorkspace
->work_objects
))
511 for (i
=0; i
< theWorkspace
->work_objects
->len
; ++i
)
513 if (TRUE
== tm_work_object_update(TM_WORK_OBJECT(
514 theWorkspace
->work_objects
->pdata
[i
]), FALSE
, TRUE
, FALSE
))
519 tm_workspace_recreate_tags_array();
520 /* workspace->analyze_time = time(NULL); */
524 void tm_workspace_dump(void)
529 g_message("Dumping TagManager workspace tree..");
531 tm_work_object_dump(TM_WORK_OBJECT(theWorkspace
));
532 if (theWorkspace
->work_objects
)
535 for (i
=0; i
< theWorkspace
->work_objects
->len
; ++i
)
537 if (IS_TM_PROJECT(TM_WORK_OBJECT(theWorkspace
->work_objects
->pdata
[i
])))
538 tm_project_dump(TM_PROJECT(theWorkspace
->work_objects
->pdata
[i
]));
540 tm_work_object_dump(TM_WORK_OBJECT(theWorkspace
->work_objects
->pdata
[i
]));
546 const GPtrArray
*tm_workspace_find(const char *name
, int type
, TMTagAttrType
*attrs
547 , gboolean partial
, langType lang
)
549 static GPtrArray
*tags
= NULL
;
551 int len
, tagCount
[2]={0,0}, tagIter
;
554 if ((!theWorkspace
) || (!name
))
560 g_ptr_array_set_size(tags
, 0);
562 tags
= g_ptr_array_new();
564 matches
[0] = tm_tags_find(theWorkspace
->work_object
.tags_array
, name
, partial
, &tagCount
[0]);
565 matches
[1] = tm_tags_find(theWorkspace
->global_tags
, name
, partial
, &tagCount
[1]);
568 if (matches
[0] && *matches
[0])
570 /* tag->atts.file.lang contains the line of the tag and
571 * tags->atts.entry.file->lang contains the language */
572 tags_lang
= (*matches
[0])->atts
.entry
.file
->lang
;
574 for (tagIter
=0;tagIter
<tagCount
[0];++tagIter
)
576 if ((type
& (*matches
[0])->type
) && (lang
== -1 || tags_lang
== lang
))
577 g_ptr_array_add(tags
, *matches
[0]);
580 if (0 != strncmp((*matches
[0])->name
, name
, len
))
585 if (0 != strcmp((*matches
[0])->name
, name
))
593 if (matches
[1] && *matches
[1])
595 int tags_lang_alt
= 0;
596 /* tag->atts.file.lang contains the language and
597 * tags->atts.entry.file is NULL */
598 tags_lang
= (*matches
[1])->atts
.file
.lang
;
599 /* tags_lang_alt is used to load C global tags only once for C and C++
600 * lang = 1 is C++, lang = 0 is C
601 * if we have lang 0, than accept also lang 1 for C++ */
602 if (tags_lang
== 0) /* C or C++ */
605 tags_lang_alt
= tags_lang
; /* otherwise just ignore it */
607 for (tagIter
=0;tagIter
<tagCount
[1];++tagIter
)
609 if ((type
& (*matches
[1])->type
) && (lang
== -1 ||
610 tags_lang
== lang
|| tags_lang_alt
== lang
))
611 g_ptr_array_add(tags
, *matches
[1]);
615 if (0 != strncmp((*matches
[1])->name
, name
, len
))
620 if (0 != strcmp((*matches
[1])->name
, name
))
628 tm_tags_sort(tags
, attrs
, TRUE
);
632 static gboolean
match_langs(gint lang
, const TMTag
*tag
)
634 if (tag
->atts
.entry
.file
)
635 { /* workspace tag */
636 if (lang
== tag
->atts
.entry
.file
->lang
)
641 if (lang
== tag
->atts
.file
.lang
)
647 /* scope can be NULL.
650 fill_find_tags_array (GPtrArray
*dst
, const GPtrArray
*src
,
651 const char *name
, const char *scope
, int type
, gboolean partial
,
652 gint lang
, gboolean first
)
657 if ((!src
) || (!dst
) || (!name
) || (!*name
))
660 match
= tm_tags_find (src
, name
, partial
, &count
);
661 if (count
&& match
&& *match
)
663 for (tagIter
= 0; tagIter
< count
; ++tagIter
)
665 if (! scope
|| (match
[tagIter
]->atts
.entry
.scope
&&
666 0 == strcmp(match
[tagIter
]->atts
.entry
.scope
, scope
)))
668 if (type
& match
[tagIter
]->type
)
669 if (lang
== -1 || match_langs(lang
, match
[tagIter
]))
671 g_ptr_array_add (dst
, match
[tagIter
]);
682 /* adapted from tm_workspace_find, Anjuta 2.02 */
684 tm_workspace_find_scoped (const char *name
, const char *scope
, gint type
,
685 TMTagAttrType
*attrs
, gboolean partial
, langType lang
, gboolean global_search
)
687 static GPtrArray
*tags
= NULL
;
693 g_ptr_array_set_size (tags
, 0);
695 tags
= g_ptr_array_new ();
697 fill_find_tags_array (tags
, theWorkspace
->work_object
.tags_array
,
698 name
, scope
, type
, partial
, lang
, FALSE
);
701 /* for a scoped tag, I think we always want the same language */
702 fill_find_tags_array (tags
, theWorkspace
->global_tags
,
703 name
, scope
, type
, partial
, lang
, FALSE
);
706 tm_tags_sort (tags
, attrs
, TRUE
);
712 tm_get_current_function (GPtrArray
* file_tags
, const gulong line
)
714 GPtrArray
*const local
= tm_tags_extract (file_tags
, tm_tag_function_t
);
715 if (local
&& local
->len
)
718 TMTag
*tag
, *function_tag
= NULL
;
719 gulong function_line
= 0;
722 for (i
= 0; (i
< local
->len
); ++i
)
724 tag
= TM_TAG (local
->pdata
[i
]);
725 delta
= line
- tag
->atts
.entry
.line
;
726 if (delta
>= 0 && (gulong
)delta
< line
- function_line
)
729 function_line
= tag
->atts
.entry
.line
;
732 g_ptr_array_free (local
, TRUE
);
740 find_scope_members_tags (const GPtrArray
* all
, GPtrArray
* tags
,
741 const langType langJava
, const char *name
,
742 const char *filename
, gboolean no_definitions
)
744 GPtrArray
*local
= g_ptr_array_new ();
747 size_t len
= strlen (name
);
748 for (i
= 0; (i
< all
->len
); ++i
)
750 tag
= TM_TAG (all
->pdata
[i
]);
751 if (no_definitions
&& filename
&& tag
->atts
.entry
.file
&&
752 0 != strcmp (filename
,
753 tag
->atts
.entry
.file
->work_object
.short_name
))
757 if (tag
&& tag
->atts
.entry
.scope
&& tag
->atts
.entry
.scope
[0] != '\0')
759 if (0 == strncmp (name
, tag
->atts
.entry
.scope
, len
))
761 g_ptr_array_add (local
, tag
);
770 char *s_backup
= NULL
;
771 char *var_type
= NULL
;
773 for (i
= 0; (i
< local
->len
); ++i
)
775 tag
= TM_TAG (local
->pdata
[i
]);
776 scope
= tag
->atts
.entry
.scope
;
777 if (scope
&& 0 == strcmp (name
, scope
))
779 g_ptr_array_add (tags
, tag
);
783 j
= 0; /* someone could write better code :P */
788 backup
= s_backup
[0];
790 if (0 == strcmp (name
, tag
->atts
.entry
.scope
))
793 s_backup
[0] = backup
;
797 if (tag
->atts
.entry
.file
798 && tag
->atts
.entry
.file
->lang
== langJava
)
800 scope
= strrchr (tag
->atts
.entry
.scope
, '.');
802 var_type
= scope
+ 1;
806 scope
= strrchr (tag
->atts
.entry
.scope
, ':');
809 var_type
= scope
+ 1;
815 s_backup
[0] = backup
;
821 backup
= s_backup
[0];
824 for (j
= 0; (j
< local
->len
); ++j
)
828 tag2
= TM_TAG (local
->pdata
[j
]);
829 if (tag2
->atts
.entry
.var_type
&&
830 0 == strcmp (var_type
, tag2
->atts
.entry
.var_type
))
836 s_backup
[0] = backup
;
846 g_ptr_array_add (tags
, tag
);
850 g_ptr_array_free (local
, TRUE
);
851 return (int) tags
->len
;
857 find_namespace_members_tags (const GPtrArray
* all
, GPtrArray
* tags
,
858 const langType langJava
, const char *name
,
859 const char *filename
)
861 GPtrArray
*local
= g_ptr_array_new ();
864 size_t len
= strlen (name
);
866 g_return_val_if_fail (all
!= NULL
, 0);
868 for (i
= 0; (i
< all
->len
); ++i
)
870 tag
= TM_TAG (all
->pdata
[i
]);
871 if (filename
&& tag
->atts
.entry
.file
&&
872 0 != strcmp (filename
,
873 tag
->atts
.entry
.file
->work_object
.short_name
))
878 if (tag
&& tag
->atts
.entry
.scope
&& tag
->atts
.entry
.scope
[0] != '\0')
880 if (0 == strncmp (name
, tag
->atts
.entry
.scope
, len
))
882 g_ptr_array_add (local
, tag
);
890 for (i
= 0; (i
< local
->len
); ++i
)
892 tag
= TM_TAG (local
->pdata
[i
]);
893 scope
= tag
->atts
.entry
.scope
;
895 /* if we wanna complete something like
897 * we'll just return the tags that have "namespace1"
898 * as their scope. So we won't return classes/members/namespaces
899 * under, for example, namespace2, where namespace1::namespace2
901 if (scope
&& 0 == strcmp (name
, scope
))
903 g_ptr_array_add (tags
, tag
);
908 g_ptr_array_free (local
, TRUE
);
909 return (int) tags
->len
;
913 tm_workspace_find_namespace_members (const GPtrArray
* file_tags
, const char *name
,
914 gboolean search_global
)
916 static GPtrArray
*tags
= NULL
;
917 GPtrArray
*local
= NULL
;
918 char *new_name
= (char *) name
;
919 char *filename
= NULL
;
920 int found
= 0, del
= 0;
921 static langType langJava
= -1;
924 g_return_val_if_fail ((theWorkspace
&& name
&& name
[0] != '\0'), NULL
);
927 tags
= g_ptr_array_new ();
931 const GPtrArray
*tags2
;
932 int got
= 0, types
= (tm_tag_class_t
| tm_tag_namespace_t
|
933 tm_tag_struct_t
| tm_tag_typedef_t
|
934 tm_tag_union_t
| tm_tag_enum_t
);
938 g_ptr_array_set_size (tags
, 0);
939 got
= fill_find_tags_array (tags
, file_tags
,
940 new_name
, NULL
, types
, FALSE
, -1, FALSE
);
950 TMTagAttrType attrs
[] = {
951 tm_tag_attr_name_t
, tm_tag_attr_type_t
,
954 tags2
= tm_workspace_find (new_name
, types
, attrs
, FALSE
, -1);
957 if ((tags2
) && (tags2
->len
== 1) && (tag
= TM_TAG (tags2
->pdata
[0])))
959 if (tag
->type
== tm_tag_typedef_t
&& tag
->atts
.entry
.var_type
960 && tag
->atts
.entry
.var_type
[0] != '\0')
962 new_name
= tag
->atts
.entry
.var_type
;
965 filename
= (tag
->atts
.entry
.file
?
966 tag
->atts
.entry
.file
->work_object
.short_name
: NULL
);
967 if (tag
->atts
.entry
.scope
&& tag
->atts
.entry
.scope
[0] != '\0')
970 if (tag
->atts
.entry
.file
&&
971 tag
->atts
.entry
.file
->lang
== langJava
)
973 new_name
= g_strdup_printf ("%s.%s",
974 tag
->atts
.entry
.scope
,
979 new_name
= g_strdup_printf ("%s::%s",
980 tag
->atts
.entry
.scope
,
992 g_ptr_array_set_size (tags
, 0);
994 if (tag
&& tag
->atts
.entry
.file
)
996 local
= tm_tags_extract (tag
->atts
.entry
.file
->work_object
.tags_array
,
998 tm_tag_field_t
| tm_tag_enumerator_t
|
999 tm_tag_namespace_t
| tm_tag_class_t
));
1003 local
= tm_tags_extract (theWorkspace
->work_object
.tags_array
,
1004 (tm_tag_function_t
| tm_tag_prototype_t
|
1006 tm_tag_field_t
| tm_tag_enumerator_t
|
1007 tm_tag_namespace_t
| tm_tag_class_t
));
1012 found
= find_namespace_members_tags (local
, tags
,
1013 langJava
, new_name
, filename
);
1014 g_ptr_array_free (local
, TRUE
);
1018 if (!found
&& search_global
)
1020 GPtrArray
*global
= tm_tags_extract (theWorkspace
->global_tags
,
1022 tm_tag_prototype_t
|
1026 tm_tag_enumerator_t
|
1027 tm_tag_namespace_t
|
1032 find_namespace_members_tags (global
, tags
, langJava
,
1033 new_name
, filename
);
1035 DEBUG_PRINT ("returning these");
1037 for (i=0; i < tags->len; i++) {
1040 cur_tag = (TMTag*)g_ptr_array_index (tags, i);
1041 tm_tag_print (cur_tag, stdout );
1044 g_ptr_array_free (global, TRUE);
1059 tm_workspace_find_scope_members (const GPtrArray * file_tags, const char *name,
1060 gboolean search_global, gboolean no_definitions)
1062 static GPtrArray *tags = NULL;
1063 GPtrArray *local = NULL;
1064 char *new_name = (char *) name;
1065 char *filename = NULL;
1066 int found = 0, del = 0;
1067 static langType langJava = -1;
1071 /* langJava = getNamedLanguage ("Java"); */
1073 g_return_val_if_fail ((theWorkspace
&& name
&& name
[0] != '\0'), NULL
);
1076 tags
= g_ptr_array_new ();
1080 const GPtrArray
*tags2
;
1081 int got
= 0, types
= (tm_tag_class_t
| tm_tag_namespace_t
|
1082 tm_tag_struct_t
| tm_tag_typedef_t
|
1083 tm_tag_union_t
| tm_tag_enum_t
);
1087 g_ptr_array_set_size (tags
, 0);
1088 got
= fill_find_tags_array (tags
, file_tags
,
1089 new_name
, NULL
, types
, FALSE
, -1, FALSE
);
1097 TMTagAttrType attrs
[] = {
1098 tm_tag_attr_name_t
, tm_tag_attr_type_t
,
1101 tags2
= tm_workspace_find (new_name
, types
, attrs
, FALSE
, -1);
1104 if ((tags2
) && (tags2
->len
== 1) && (tag
= TM_TAG (tags2
->pdata
[0])))
1106 if (tag
->type
== tm_tag_typedef_t
&& tag
->atts
.entry
.var_type
1107 && tag
->atts
.entry
.var_type
[0] != '\0')
1110 tmp_name
= tag
->atts
.entry
.var_type
;
1111 if (strcmp(tmp_name
, new_name
) == 0) {
1115 new_name
= tmp_name
;
1119 filename
= (tag
->atts
.entry
.file
?
1120 tag
->atts
.entry
.file
->work_object
.short_name
: NULL
);
1121 if (tag
->atts
.entry
.scope
&& tag
->atts
.entry
.scope
[0] != '\0')
1124 if (tag
->atts
.entry
.file
&&
1125 tag
->atts
.entry
.file
->lang
== langJava
)
1127 new_name
= g_strdup_printf ("%s.%s",
1128 tag
->atts
.entry
.scope
,
1133 new_name
= g_strdup_printf ("%s::%s",
1134 tag
->atts
.entry
.scope
,
1146 g_ptr_array_set_size (tags
, 0);
1148 if (no_definitions
&& tag
&& tag
->atts
.entry
.file
)
1150 local
= tm_tags_extract (tag
->atts
.entry
.file
->work_object
.tags_array
,
1151 (tm_tag_function_t
| tm_tag_prototype_t
|
1152 tm_tag_member_t
| tm_tag_field_t
|
1153 tm_tag_method_t
| tm_tag_enumerator_t
));
1157 local
= tm_tags_extract (theWorkspace
->work_object
.tags_array
,
1158 (tm_tag_function_t
| tm_tag_prototype_t
|
1159 tm_tag_member_t
| tm_tag_field_t
|
1160 tm_tag_method_t
| tm_tag_enumerator_t
));
1164 found
= find_scope_members_tags (local
, tags
, langJava
, new_name
,
1165 filename
, no_definitions
);
1166 g_ptr_array_free (local
, TRUE
);
1168 if (!found
&& search_global
)
1170 GPtrArray
*global
= tm_tags_extract (theWorkspace
->global_tags
,
1172 tm_tag_prototype_t
|
1177 |tm_tag_struct_t
| tm_tag_typedef_t
|
1178 tm_tag_union_t
| tm_tag_enum_t
));
1181 find_scope_members_tags (global
, tags
, langJava
, new_name
,
1182 filename
, no_definitions
);
1183 g_ptr_array_free (global
, TRUE
);
1194 const GPtrArray
*tm_workspace_get_parents(const gchar
*name
)
1196 static TMTagAttrType type
[] = { tm_tag_attr_name_t
, tm_tag_attr_none_t
};
1197 static GPtrArray
*parents
= NULL
;
1198 const GPtrArray
*matches
;
1205 g_return_val_if_fail(name
&& isalpha(*name
),NULL
);
1207 if (NULL
== parents
)
1208 parents
= g_ptr_array_new();
1210 g_ptr_array_set_size(parents
, 0);
1211 matches
= tm_workspace_find(name
, tm_tag_class_t
, type
, FALSE
, -1);
1212 if ((NULL
== matches
) || (0 == matches
->len
))
1214 g_ptr_array_add(parents
, matches
->pdata
[0]);
1215 while (i
< parents
->len
)
1217 tag
= TM_TAG(parents
->pdata
[i
]);
1218 if ((NULL
!= tag
->atts
.entry
.inheritance
) && (isalpha(tag
->atts
.entry
.inheritance
[0])))
1220 klasses
= g_strsplit(tag
->atts
.entry
.inheritance
, ",", 10);
1221 for (klass
= klasses
; (NULL
!= *klass
); ++ klass
)
1223 for (j
=0; j
< parents
->len
; ++j
)
1225 if (0 == strcmp(*klass
, TM_TAG(parents
->pdata
[j
])->name
))
1228 if (parents
->len
== j
)
1230 matches
= tm_workspace_find(*klass
, tm_tag_class_t
, type
, FALSE
, -1);
1231 if ((NULL
!= matches
) && (0 < matches
->len
))
1232 g_ptr_array_add(parents
, matches
->pdata
[0]);
1235 g_strfreev(klasses
);