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
== theWorkspace
)
152 if (NULL
== (fp
= g_fopen(tags_file
, "r")))
154 if (NULL
== theWorkspace
->global_tags
)
155 theWorkspace
->global_tags
= g_ptr_array_new();
156 if ((NULL
== fgets((gchar
*) buf
, BUFSIZ
, fp
)) || ('\0' == *buf
))
159 return FALSE
; /* early out on error */
162 { /* We read the first line for the format specification. */
163 if (buf
[0] == '#' && strstr((gchar
*) buf
, "format=pipe") != NULL
)
165 else if (buf
[0] == '#' && strstr((gchar
*) buf
, "format=tagmanager") != NULL
)
168 { /* We didn't find a valid format specification, so we try to auto-detect the format
169 * by counting the pipe characters on the first line and asumme pipe format when
170 * we find more than one pipe on the line. */
171 guint i
, pipe_cnt
= 0;
172 for (i
= 0; i
< BUFSIZ
&& buf
[i
] != '\0' && pipe_cnt
< 2; i
++)
177 format_pipe
= (pipe_cnt
> 1);
179 rewind(fp
); /* reset the file pointer, to start reading again from the beginning */
181 while (NULL
!= (tag
= tm_tag_new_from_file(NULL
, fp
, mode
, format_pipe
)))
182 g_ptr_array_add(theWorkspace
->global_tags
, tag
);
185 /* resort the whole array, because tm_tags_find expects a sorted array and it is not sorted
186 * when c99.tags, php.tags and latex.tags are loaded at the same time */
187 tm_tags_sort(theWorkspace
->global_tags
, global_tags_sort_attrs
, TRUE
);
192 static guint
tm_file_inode_hash(gconstpointer key
)
194 struct stat file_stat
;
195 const char *filename
= (const char*)key
;
196 if (g_stat(filename
, &file_stat
) == 0)
199 g_message ("Hash for '%s' is '%d'\n", filename
, file_stat
.st_ino
);
201 return g_direct_hash (GUINT_TO_POINTER (file_stat
.st_ino
));
207 static void tm_move_entries_to_g_list(gpointer key
, gpointer value
, gpointer user_data
)
209 GList
**pp_list
= (GList
**)user_data
;
211 if (user_data
== NULL
)
214 *pp_list
= g_list_prepend(*pp_list
, value
);
217 static void write_includes_file(FILE *fp
, GList
*includes_files
)
221 node
= includes_files
;
224 char *str
= g_strdup_printf("#include \"%s\"\n", (char*)node
->data
);
225 int str_len
= strlen(str
);
228 size
= fwrite(str
, str_len
, 1, fp
);
230 node
= g_list_next (node
);
235 static void append_to_temp_file(FILE *fp
, GList
*file_list
)
242 const char *fname
= node
->data
;
247 if (! g_file_get_contents(fname
, &contents
, &length
, &err
))
249 fprintf(stderr
, "Unable to read file: %s\n", err
->message
);
255 size
= fwrite(contents
, length
, 1, fp
);
256 size
= fwrite("\n", 1, 1, fp
); /* in case file doesn't end in newline (e.g. windows). */
259 node
= g_list_next (node
);
263 gboolean
tm_workspace_create_global_tags(const char *config_dir
, const char *pre_process
,
264 const char **includes
, int includes_count
, const char *tags_file
, int lang
)
274 TMWorkObject
*source_file
;
275 GPtrArray
*tags_array
;
276 GHashTable
*includes_files_hash
;
277 GList
*includes_files
= 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
));
282 char *temp_file
= g_strdup_printf("%s/%d_%ld_1.cpp", config_dir
, getpid(), time(NULL
));
283 char *temp_file2
= g_strdup_printf("%s/%d_%ld_2.cpp", config_dir
, getpid(), time(NULL
));
286 if (NULL
== theWorkspace
|| NULL
== (fp
= g_fopen(temp_file
, "w")))
293 includes_files_hash
= g_hash_table_new_full (tm_file_inode_hash
,
300 if (includes
[0][0] == '"') /* leading \" char for glob matching */
301 for(idx_inc
= 0; idx_inc
< includes_count
; idx_inc
++)
303 int dirty_len
= strlen(includes
[idx_inc
]);
304 char *clean_path
= g_malloc(dirty_len
- 1);
305 strncpy(clean_path
, includes
[idx_inc
] + 1, dirty_len
- 1);
306 clean_path
[dirty_len
- 2] = 0;
309 g_message ("[o][%s]\n", clean_path
);
311 glob(clean_path
, 0, NULL
, &globbuf
);
314 g_message ("matches: %d\n", globbuf
.gl_pathc
);
317 for(idx_glob
= 0; idx_glob
< globbuf
.gl_pathc
; idx_glob
++)
320 g_message (">>> %s\n", globbuf
.gl_pathv
[idx_glob
]);
322 if (!g_hash_table_lookup(includes_files_hash
,
323 globbuf
.gl_pathv
[idx_glob
]))
325 char* file_name_copy
= strdup(globbuf
.gl_pathv
[idx_glob
]);
326 g_hash_table_insert(includes_files_hash
, file_name_copy
,
329 g_message ("Added ...\n");
338 /* no glob support or globbing not wanted */
339 for(idx_inc
= 0; idx_inc
< includes_count
; idx_inc
++)
341 if (!g_hash_table_lookup(includes_files_hash
,
344 char* file_name_copy
= strdup(includes
[idx_inc
]);
345 g_hash_table_insert(includes_files_hash
, file_name_copy
,
350 /* Checks for duplicate file entries which would case trouble */
351 g_hash_table_foreach(includes_files_hash
, tm_move_entries_to_g_list
,
354 includes_files
= g_list_reverse (includes_files
);
357 g_message ("writing out files to %s\n", temp_file
);
359 if (pre_process
!= NULL
)
360 write_includes_file(fp
, includes_files
);
362 append_to_temp_file(fp
, includes_files
);
364 g_list_free (includes_files
);
365 g_hash_table_destroy(includes_files_hash
);
366 includes_files_hash
= NULL
;
367 includes_files
= NULL
;
370 /* FIXME: The following grep command removes the lines
371 * G_BEGIN_DECLS and G_END_DECLS from the header files. The reason is
372 * that in tagmanager, the files are not correctly parsed and the typedefs
373 * following these lines are incorrectly parsed. The real fix should,
374 * of course be in tagmanager (c) parser. This is just a temporary fix.
376 if (pre_process
!= NULL
)
379 command
= g_strdup_printf("%s %s | grep -v -E '^\\s*(G_BEGIN_DECLS|G_END_DECLS)\\s*$' > %s",
380 pre_process
, temp_file
, temp_file2
);
382 g_message("Executing: %s", command
);
384 ret
= system(command
);
391 /* no pre-processing needed, so temp_file2 = temp_file */
393 temp_file2
= temp_file
;
396 source_file
= tm_source_file_new(temp_file2
, TRUE
, tm_source_file_get_lang_name(lang
));
397 if (NULL
== source_file
)
399 g_unlink(temp_file2
);
402 g_unlink(temp_file2
);
404 if ((NULL
== source_file
->tags_array
) || (0 == source_file
->tags_array
->len
))
406 tm_source_file_free(source_file
);
409 tags_array
= tm_tags_extract(source_file
->tags_array
, tm_tag_max_t
);
410 if ((NULL
== tags_array
) || (0 == tags_array
->len
))
413 g_ptr_array_free(tags_array
, TRUE
);
414 tm_source_file_free(source_file
);
417 if (FALSE
== tm_tags_sort(tags_array
, global_tags_sort_attrs
, TRUE
))
419 tm_source_file_free(source_file
);
422 if (NULL
== (fp
= g_fopen(tags_file
, "w")))
424 tm_source_file_free(source_file
);
427 fprintf(fp
, "# format=tagmanager\n");
428 for (i
= 0; i
< tags_array
->len
; ++i
)
430 tm_tag_write(TM_TAG(tags_array
->pdata
[i
]), fp
, tm_tag_attr_type_t
431 | tm_tag_attr_scope_t
| tm_tag_attr_arglist_t
| tm_tag_attr_vartype_t
432 | tm_tag_attr_pointer_t
);
435 tm_source_file_free(source_file
);
436 g_ptr_array_free(tags_array
, TRUE
);
440 TMWorkObject
*tm_workspace_find_object(TMWorkObject
*work_object
, const char *file_name
441 , gboolean name_only
)
443 TMWorkObject
*w
= NULL
;
446 if (work_object
!= TM_WORK_OBJECT(theWorkspace
))
448 if ((NULL
== theWorkspace
) || (NULL
== theWorkspace
->work_objects
)
449 || (0 == theWorkspace
->work_objects
->len
))
451 for (i
= 0; i
< theWorkspace
->work_objects
->len
; ++i
)
453 if (NULL
!= (w
= tm_work_object_find(TM_WORK_OBJECT(theWorkspace
->work_objects
->pdata
[i
])
454 , file_name
, name_only
)))
460 void tm_workspace_recreate_tags_array(void)
464 TMTagAttrType sort_attrs
[] = { tm_tag_attr_name_t
, tm_tag_attr_file_t
465 , tm_tag_attr_scope_t
, tm_tag_attr_type_t
, tm_tag_attr_arglist_t
, 0};
468 g_message("Recreating workspace tags array");
471 if ((NULL
== theWorkspace
) || (NULL
== theWorkspace
->work_objects
))
473 if (NULL
!= theWorkspace
->work_object
.tags_array
)
474 g_ptr_array_set_size(theWorkspace
->work_object
.tags_array
, 0);
476 theWorkspace
->work_object
.tags_array
= g_ptr_array_new();
479 g_message("Total %d objects", theWorkspace
->work_objects
->len
);
481 for (i
=0; i
< theWorkspace
->work_objects
->len
; ++i
)
483 w
= TM_WORK_OBJECT(theWorkspace
->work_objects
->pdata
[i
]);
485 g_message("Adding tags of %s", w
->file_name
);
487 if ((NULL
!= w
) && (NULL
!= w
->tags_array
) && (w
->tags_array
->len
> 0))
489 for (j
= 0; j
< w
->tags_array
->len
; ++j
)
491 g_ptr_array_add(theWorkspace
->work_object
.tags_array
,
492 w
->tags_array
->pdata
[j
]);
497 g_message("Total: %d tags", theWorkspace
->work_object
.tags_array
->len
);
499 tm_tags_sort(theWorkspace
->work_object
.tags_array
, sort_attrs
, TRUE
);
502 gboolean
tm_workspace_update(TMWorkObject
*workspace
, gboolean force
503 , gboolean recurse
, gboolean __unused__ update_parent
)
506 gboolean update_tags
= force
;
509 g_message("Updating workspace");
512 if (workspace
!= TM_WORK_OBJECT(theWorkspace
))
514 if (NULL
== theWorkspace
)
516 if ((recurse
) && (theWorkspace
->work_objects
))
518 for (i
=0; i
< theWorkspace
->work_objects
->len
; ++i
)
520 if (TRUE
== tm_work_object_update(TM_WORK_OBJECT(
521 theWorkspace
->work_objects
->pdata
[i
]), FALSE
, TRUE
, FALSE
))
526 tm_workspace_recreate_tags_array();
527 /* workspace->analyze_time = time(NULL); */
531 void tm_workspace_dump(void)
536 g_message("Dumping TagManager workspace tree..");
538 tm_work_object_dump(TM_WORK_OBJECT(theWorkspace
));
539 if (theWorkspace
->work_objects
)
542 for (i
=0; i
< theWorkspace
->work_objects
->len
; ++i
)
544 if (IS_TM_PROJECT(TM_WORK_OBJECT(theWorkspace
->work_objects
->pdata
[i
])))
545 tm_project_dump(TM_PROJECT(theWorkspace
->work_objects
->pdata
[i
]));
547 tm_work_object_dump(TM_WORK_OBJECT(theWorkspace
->work_objects
->pdata
[i
]));
553 const GPtrArray
*tm_workspace_find(const char *name
, int type
, TMTagAttrType
*attrs
554 , gboolean partial
, langType lang
)
556 static GPtrArray
*tags
= NULL
;
558 int len
, tagCount
[2]={0,0}, tagIter
;
561 if ((!theWorkspace
) || (!name
))
567 g_ptr_array_set_size(tags
, 0);
569 tags
= g_ptr_array_new();
571 matches
[0] = tm_tags_find(theWorkspace
->work_object
.tags_array
, name
, partial
, &tagCount
[0]);
572 matches
[1] = tm_tags_find(theWorkspace
->global_tags
, name
, partial
, &tagCount
[1]);
575 if (matches
[0] && *matches
[0])
577 /* tag->atts.file.lang contains the line of the tag and
578 * tags->atts.entry.file->lang contains the language */
579 tags_lang
= (*matches
[0])->atts
.entry
.file
->lang
;
581 for (tagIter
=0;tagIter
<tagCount
[0];++tagIter
)
583 if ((type
& (*matches
[0])->type
) && (lang
== -1 || tags_lang
== lang
))
584 g_ptr_array_add(tags
, *matches
[0]);
587 if (0 != strncmp((*matches
[0])->name
, name
, len
))
592 if (0 != strcmp((*matches
[0])->name
, name
))
600 if (matches
[1] && *matches
[1])
602 int tags_lang_alt
= 0;
603 /* tag->atts.file.lang contains the language and
604 * tags->atts.entry.file is NULL */
605 tags_lang
= (*matches
[1])->atts
.file
.lang
;
606 /* tags_lang_alt is used to load C global tags only once for C and C++
607 * lang = 1 is C++, lang = 0 is C
608 * if we have lang 0, than accept also lang 1 for C++ */
609 if (tags_lang
== 0) /* C or C++ */
612 tags_lang_alt
= tags_lang
; /* otherwise just ignore it */
614 for (tagIter
=0;tagIter
<tagCount
[1];++tagIter
)
616 if ((type
& (*matches
[1])->type
) && (lang
== -1 ||
617 tags_lang
== lang
|| tags_lang_alt
== lang
))
618 g_ptr_array_add(tags
, *matches
[1]);
622 if (0 != strncmp((*matches
[1])->name
, name
, len
))
627 if (0 != strcmp((*matches
[1])->name
, name
))
635 tm_tags_sort(tags
, attrs
, TRUE
);
639 static gboolean
match_langs(gint lang
, const TMTag
*tag
)
641 if (tag
->atts
.entry
.file
)
642 { /* workspace tag */
643 if (lang
== tag
->atts
.entry
.file
->lang
)
648 if (lang
== tag
->atts
.file
.lang
)
654 /* scope can be NULL.
657 fill_find_tags_array (GPtrArray
*dst
, const GPtrArray
*src
,
658 const char *name
, const char *scope
, int type
, gboolean partial
,
659 gint lang
, gboolean first
)
664 if ((!src
) || (!dst
) || (!name
) || (!*name
))
667 match
= tm_tags_find (src
, name
, partial
, &count
);
668 if (count
&& match
&& *match
)
670 for (tagIter
= 0; tagIter
< count
; ++tagIter
)
672 if (! scope
|| (match
[tagIter
]->atts
.entry
.scope
&&
673 0 == strcmp(match
[tagIter
]->atts
.entry
.scope
, scope
)))
675 if (type
& match
[tagIter
]->type
)
676 if (lang
== -1 || match_langs(lang
, match
[tagIter
]))
678 g_ptr_array_add (dst
, match
[tagIter
]);
689 /* adapted from tm_workspace_find, Anjuta 2.02 */
691 tm_workspace_find_scoped (const char *name
, const char *scope
, gint type
,
692 TMTagAttrType
*attrs
, gboolean partial
, langType lang
, gboolean global_search
)
694 static GPtrArray
*tags
= NULL
;
700 g_ptr_array_set_size (tags
, 0);
702 tags
= g_ptr_array_new ();
704 fill_find_tags_array (tags
, theWorkspace
->work_object
.tags_array
,
705 name
, scope
, type
, partial
, lang
, FALSE
);
708 /* for a scoped tag, I think we always want the same language */
709 fill_find_tags_array (tags
, theWorkspace
->global_tags
,
710 name
, scope
, type
, partial
, lang
, FALSE
);
713 tm_tags_sort (tags
, attrs
, TRUE
);
719 tm_get_current_function (GPtrArray
* file_tags
, const gulong line
)
721 GPtrArray
*const local
= tm_tags_extract (file_tags
, tm_tag_function_t
);
722 if (local
&& local
->len
)
725 TMTag
*tag
, *function_tag
= NULL
;
726 gulong function_line
= 0;
729 for (i
= 0; (i
< local
->len
); ++i
)
731 tag
= TM_TAG (local
->pdata
[i
]);
732 delta
= line
- tag
->atts
.entry
.line
;
733 if (delta
>= 0 && (gulong
)delta
< line
- function_line
)
736 function_line
= tag
->atts
.entry
.line
;
739 g_ptr_array_free (local
, TRUE
);
747 find_scope_members_tags (const GPtrArray
* all
, GPtrArray
* tags
,
748 const langType langJava
, const char *name
,
749 const char *filename
, gboolean no_definitions
)
751 GPtrArray
*local
= g_ptr_array_new ();
754 size_t len
= strlen (name
);
755 for (i
= 0; (i
< all
->len
); ++i
)
757 tag
= TM_TAG (all
->pdata
[i
]);
758 if (no_definitions
&& filename
&& tag
->atts
.entry
.file
&&
759 0 != strcmp (filename
,
760 tag
->atts
.entry
.file
->work_object
.short_name
))
764 if (tag
&& tag
->atts
.entry
.scope
&& tag
->atts
.entry
.scope
[0] != '\0')
766 if (0 == strncmp (name
, tag
->atts
.entry
.scope
, len
))
768 g_ptr_array_add (local
, tag
);
777 char *s_backup
= NULL
;
778 char *var_type
= NULL
;
780 for (i
= 0; (i
< local
->len
); ++i
)
782 tag
= TM_TAG (local
->pdata
[i
]);
783 scope
= tag
->atts
.entry
.scope
;
784 if (scope
&& 0 == strcmp (name
, scope
))
786 g_ptr_array_add (tags
, tag
);
790 j
= 0; /* someone could write better code :P */
795 backup
= s_backup
[0];
797 if (0 == strcmp (name
, tag
->atts
.entry
.scope
))
800 s_backup
[0] = backup
;
804 if (tag
->atts
.entry
.file
805 && tag
->atts
.entry
.file
->lang
== langJava
)
807 scope
= strrchr (tag
->atts
.entry
.scope
, '.');
809 var_type
= scope
+ 1;
813 scope
= strrchr (tag
->atts
.entry
.scope
, ':');
816 var_type
= scope
+ 1;
822 s_backup
[0] = backup
;
828 backup
= s_backup
[0];
831 for (j
= 0; (j
< local
->len
); ++j
)
835 tag2
= TM_TAG (local
->pdata
[j
]);
836 if (tag2
->atts
.entry
.var_type
&&
837 0 == strcmp (var_type
, tag2
->atts
.entry
.var_type
))
843 s_backup
[0] = backup
;
853 g_ptr_array_add (tags
, tag
);
857 g_ptr_array_free (local
, TRUE
);
858 return (int) tags
->len
;
864 find_namespace_members_tags (const GPtrArray
* all
, GPtrArray
* tags
,
865 const langType langJava
, const char *name
,
866 const char *filename
)
868 GPtrArray
*local
= g_ptr_array_new ();
871 size_t len
= strlen (name
);
873 g_return_val_if_fail (all
!= NULL
, 0);
875 for (i
= 0; (i
< all
->len
); ++i
)
877 tag
= TM_TAG (all
->pdata
[i
]);
878 if (filename
&& tag
->atts
.entry
.file
&&
879 0 != strcmp (filename
,
880 tag
->atts
.entry
.file
->work_object
.short_name
))
885 if (tag
&& tag
->atts
.entry
.scope
&& tag
->atts
.entry
.scope
[0] != '\0')
887 if (0 == strncmp (name
, tag
->atts
.entry
.scope
, len
))
889 g_ptr_array_add (local
, tag
);
897 for (i
= 0; (i
< local
->len
); ++i
)
899 tag
= TM_TAG (local
->pdata
[i
]);
900 scope
= tag
->atts
.entry
.scope
;
902 /* if we wanna complete something like
904 * we'll just return the tags that have "namespace1"
905 * as their scope. So we won't return classes/members/namespaces
906 * under, for example, namespace2, where namespace1::namespace2
908 if (scope
&& 0 == strcmp (name
, scope
))
910 g_ptr_array_add (tags
, tag
);
915 g_ptr_array_free (local
, TRUE
);
916 return (int) tags
->len
;
920 tm_workspace_find_namespace_members (const GPtrArray
* file_tags
, const char *name
,
921 gboolean search_global
)
923 static GPtrArray
*tags
= NULL
;
924 GPtrArray
*local
= NULL
;
925 char *new_name
= (char *) name
;
926 char *filename
= NULL
;
927 int found
= 0, del
= 0;
928 static langType langJava
= -1;
931 g_return_val_if_fail ((theWorkspace
&& name
&& name
[0] != '\0'), NULL
);
934 tags
= g_ptr_array_new ();
938 const GPtrArray
*tags2
;
939 int got
= 0, types
= (tm_tag_class_t
| tm_tag_namespace_t
|
940 tm_tag_struct_t
| tm_tag_typedef_t
|
941 tm_tag_union_t
| tm_tag_enum_t
);
945 g_ptr_array_set_size (tags
, 0);
946 got
= fill_find_tags_array (tags
, file_tags
,
947 new_name
, NULL
, types
, FALSE
, -1, FALSE
);
957 TMTagAttrType attrs
[] = {
958 tm_tag_attr_name_t
, tm_tag_attr_type_t
,
961 tags2
= tm_workspace_find (new_name
, types
, attrs
, FALSE
, -1);
964 if ((tags2
) && (tags2
->len
== 1) && (tag
= TM_TAG (tags2
->pdata
[0])))
966 if (tag
->type
== tm_tag_typedef_t
&& tag
->atts
.entry
.var_type
967 && tag
->atts
.entry
.var_type
[0] != '\0')
969 new_name
= tag
->atts
.entry
.var_type
;
972 filename
= (tag
->atts
.entry
.file
?
973 tag
->atts
.entry
.file
->work_object
.short_name
: NULL
);
974 if (tag
->atts
.entry
.scope
&& tag
->atts
.entry
.scope
[0] != '\0')
977 if (tag
->atts
.entry
.file
&&
978 tag
->atts
.entry
.file
->lang
== langJava
)
980 new_name
= g_strdup_printf ("%s.%s",
981 tag
->atts
.entry
.scope
,
986 new_name
= g_strdup_printf ("%s::%s",
987 tag
->atts
.entry
.scope
,
999 g_ptr_array_set_size (tags
, 0);
1001 if (tag
&& tag
->atts
.entry
.file
)
1003 local
= tm_tags_extract (tag
->atts
.entry
.file
->work_object
.tags_array
,
1004 (tm_tag_function_t
|
1005 tm_tag_field_t
| tm_tag_enumerator_t
|
1006 tm_tag_namespace_t
| tm_tag_class_t
));
1010 local
= tm_tags_extract (theWorkspace
->work_object
.tags_array
,
1011 (tm_tag_function_t
| tm_tag_prototype_t
|
1013 tm_tag_field_t
| tm_tag_enumerator_t
|
1014 tm_tag_namespace_t
| tm_tag_class_t
));
1019 found
= find_namespace_members_tags (local
, tags
,
1020 langJava
, new_name
, filename
);
1021 g_ptr_array_free (local
, TRUE
);
1025 if (!found
&& search_global
)
1027 GPtrArray
*global
= tm_tags_extract (theWorkspace
->global_tags
,
1029 tm_tag_prototype_t
|
1033 tm_tag_enumerator_t
|
1034 tm_tag_namespace_t
|
1039 find_namespace_members_tags (global
, tags
, langJava
,
1040 new_name
, filename
);
1042 DEBUG_PRINT ("returning these");
1044 for (i=0; i < tags->len; i++) {
1047 cur_tag = (TMTag*)g_ptr_array_index (tags, i);
1048 tm_tag_print (cur_tag, stdout );
1051 g_ptr_array_free (global, TRUE);
1066 tm_workspace_find_scope_members (const GPtrArray * file_tags, const char *name,
1067 gboolean search_global, gboolean no_definitions)
1069 static GPtrArray *tags = NULL;
1070 GPtrArray *local = NULL;
1071 char *new_name = (char *) name;
1072 char *filename = NULL;
1073 int found = 0, del = 0;
1074 static langType langJava = -1;
1078 /* langJava = getNamedLanguage ("Java"); */
1080 g_return_val_if_fail ((theWorkspace
&& name
&& name
[0] != '\0'), NULL
);
1083 tags
= g_ptr_array_new ();
1087 const GPtrArray
*tags2
;
1088 int got
= 0, types
= (tm_tag_class_t
| tm_tag_namespace_t
|
1089 tm_tag_struct_t
| tm_tag_typedef_t
|
1090 tm_tag_union_t
| tm_tag_enum_t
);
1094 g_ptr_array_set_size (tags
, 0);
1095 got
= fill_find_tags_array (tags
, file_tags
,
1096 new_name
, NULL
, types
, FALSE
, -1, FALSE
);
1104 TMTagAttrType attrs
[] = {
1105 tm_tag_attr_name_t
, tm_tag_attr_type_t
,
1108 tags2
= tm_workspace_find (new_name
, types
, attrs
, FALSE
, -1);
1111 if ((tags2
) && (tags2
->len
== 1) && (tag
= TM_TAG (tags2
->pdata
[0])))
1113 if (tag
->type
== tm_tag_typedef_t
&& tag
->atts
.entry
.var_type
1114 && tag
->atts
.entry
.var_type
[0] != '\0')
1117 tmp_name
= tag
->atts
.entry
.var_type
;
1118 if (strcmp(tmp_name
, new_name
) == 0) {
1122 new_name
= tmp_name
;
1126 filename
= (tag
->atts
.entry
.file
?
1127 tag
->atts
.entry
.file
->work_object
.short_name
: NULL
);
1128 if (tag
->atts
.entry
.scope
&& tag
->atts
.entry
.scope
[0] != '\0')
1131 if (tag
->atts
.entry
.file
&&
1132 tag
->atts
.entry
.file
->lang
== langJava
)
1134 new_name
= g_strdup_printf ("%s.%s",
1135 tag
->atts
.entry
.scope
,
1140 new_name
= g_strdup_printf ("%s::%s",
1141 tag
->atts
.entry
.scope
,
1153 g_ptr_array_set_size (tags
, 0);
1155 if (no_definitions
&& tag
&& tag
->atts
.entry
.file
)
1157 local
= tm_tags_extract (tag
->atts
.entry
.file
->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 local
= tm_tags_extract (theWorkspace
->work_object
.tags_array
,
1165 (tm_tag_function_t
| tm_tag_prototype_t
|
1166 tm_tag_member_t
| tm_tag_field_t
|
1167 tm_tag_method_t
| tm_tag_enumerator_t
));
1171 found
= find_scope_members_tags (local
, tags
, langJava
, new_name
,
1172 filename
, no_definitions
);
1173 g_ptr_array_free (local
, TRUE
);
1175 if (!found
&& search_global
)
1177 GPtrArray
*global
= tm_tags_extract (theWorkspace
->global_tags
,
1179 tm_tag_prototype_t
|
1184 |tm_tag_struct_t
| tm_tag_typedef_t
|
1185 tm_tag_union_t
| tm_tag_enum_t
));
1188 find_scope_members_tags (global
, tags
, langJava
, new_name
,
1189 filename
, no_definitions
);
1190 g_ptr_array_free (global
, TRUE
);
1201 const GPtrArray
*tm_workspace_get_parents(const gchar
*name
)
1203 static TMTagAttrType type
[] = { tm_tag_attr_name_t
, tm_tag_attr_none_t
};
1204 static GPtrArray
*parents
= NULL
;
1205 const GPtrArray
*matches
;
1212 g_return_val_if_fail(name
&& isalpha(*name
),NULL
);
1214 if (NULL
== parents
)
1215 parents
= g_ptr_array_new();
1217 g_ptr_array_set_size(parents
, 0);
1218 matches
= tm_workspace_find(name
, tm_tag_class_t
, type
, FALSE
, -1);
1219 if ((NULL
== matches
) || (0 == matches
->len
))
1221 g_ptr_array_add(parents
, matches
->pdata
[0]);
1222 while (i
< parents
->len
)
1224 tag
= TM_TAG(parents
->pdata
[i
]);
1225 if ((NULL
!= tag
->atts
.entry
.inheritance
) && (isalpha(tag
->atts
.entry
.inheritance
[0])))
1227 klasses
= g_strsplit(tag
->atts
.entry
.inheritance
, ",", 10);
1228 for (klass
= klasses
; (NULL
!= *klass
); ++ klass
)
1230 for (j
=0; j
< parents
->len
; ++j
)
1232 if (0 == strcmp(*klass
, TM_TAG(parents
->pdata
[j
])->name
))
1235 if (parents
->len
== j
)
1237 matches
= tm_workspace_find(*klass
, tm_tag_class_t
, type
, FALSE
, -1);
1238 if ((NULL
!= matches
) && (0 < matches
->len
))
1239 g_ptr_array_add(parents
, matches
->pdata
[0]);
1242 g_strfreev(klasses
);