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);
306 strncpy(clean_path
, includes
[idx_inc
] + 1, dirty_len
- 1);
307 clean_path
[dirty_len
- 2] = 0;
310 g_message ("[o][%s]\n", clean_path
);
312 glob(clean_path
, 0, NULL
, &globbuf
);
315 g_message ("matches: %d\n", globbuf
.gl_pathc
);
318 for(idx_glob
= 0; idx_glob
< globbuf
.gl_pathc
; idx_glob
++)
321 g_message (">>> %s\n", globbuf
.gl_pathv
[idx_glob
]);
323 if (!g_hash_table_lookup(includes_files_hash
,
324 globbuf
.gl_pathv
[idx_glob
]))
326 char* file_name_copy
= strdup(globbuf
.gl_pathv
[idx_glob
]);
327 g_hash_table_insert(includes_files_hash
, file_name_copy
,
330 g_message ("Added ...\n");
339 /* no glob support or globbing not wanted */
340 for(idx_inc
= 0; idx_inc
< includes_count
; idx_inc
++)
342 if (!g_hash_table_lookup(includes_files_hash
,
345 char* file_name_copy
= strdup(includes
[idx_inc
]);
346 g_hash_table_insert(includes_files_hash
, file_name_copy
,
351 /* Checks for duplicate file entries which would case trouble */
352 g_hash_table_foreach(includes_files_hash
, tm_move_entries_to_g_list
,
355 includes_files
= g_list_reverse (includes_files
);
358 g_message ("writing out files to %s\n", temp_file
);
360 if (pre_process
!= NULL
)
361 write_includes_file(fp
, includes_files
);
363 append_to_temp_file(fp
, includes_files
);
365 g_list_free (includes_files
);
366 g_hash_table_destroy(includes_files_hash
);
367 includes_files_hash
= NULL
;
368 includes_files
= NULL
;
371 /* FIXME: The following grep command removes the lines
372 * G_BEGIN_DECLS and G_END_DECLS from the header files. The reason is
373 * that in tagmanager, the files are not correctly parsed and the typedefs
374 * following these lines are incorrectly parsed. The real fix should,
375 * of course be in tagmanager (c) parser. This is just a temporary fix.
377 if (pre_process
!= NULL
)
380 command
= g_strdup_printf("%s %s | grep -v -E '^\\s*(G_BEGIN_DECLS|G_END_DECLS)\\s*$' > %s",
381 pre_process
, temp_file
, temp_file2
);
383 g_message("Executing: %s", command
);
385 ret
= system(command
);
392 /* no pre-processing needed, so temp_file2 = temp_file */
394 temp_file2
= temp_file
;
397 source_file
= tm_source_file_new(temp_file2
, TRUE
, tm_source_file_get_lang_name(lang
));
398 if (NULL
== source_file
)
400 g_unlink(temp_file2
);
403 g_unlink(temp_file2
);
405 if ((NULL
== source_file
->tags_array
) || (0 == source_file
->tags_array
->len
))
407 tm_source_file_free(source_file
);
410 tags_array
= tm_tags_extract(source_file
->tags_array
, tm_tag_max_t
);
411 if ((NULL
== tags_array
) || (0 == tags_array
->len
))
414 g_ptr_array_free(tags_array
, TRUE
);
415 tm_source_file_free(source_file
);
418 if (FALSE
== tm_tags_sort(tags_array
, global_tags_sort_attrs
, TRUE
))
420 tm_source_file_free(source_file
);
423 if (NULL
== (fp
= g_fopen(tags_file
, "w")))
425 tm_source_file_free(source_file
);
428 fprintf(fp
, "# format=tagmanager\n");
429 for (i
= 0; i
< tags_array
->len
; ++i
)
431 tm_tag_write(TM_TAG(tags_array
->pdata
[i
]), fp
, tm_tag_attr_type_t
432 | tm_tag_attr_scope_t
| tm_tag_attr_arglist_t
| tm_tag_attr_vartype_t
433 | tm_tag_attr_pointer_t
);
436 tm_source_file_free(source_file
);
437 g_ptr_array_free(tags_array
, TRUE
);
441 TMWorkObject
*tm_workspace_find_object(TMWorkObject
*work_object
, const char *file_name
442 , gboolean name_only
)
444 TMWorkObject
*w
= NULL
;
447 if (work_object
!= TM_WORK_OBJECT(theWorkspace
))
449 if ((NULL
== theWorkspace
) || (NULL
== theWorkspace
->work_objects
)
450 || (0 == theWorkspace
->work_objects
->len
))
452 for (i
= 0; i
< theWorkspace
->work_objects
->len
; ++i
)
454 if (NULL
!= (w
= tm_work_object_find(TM_WORK_OBJECT(theWorkspace
->work_objects
->pdata
[i
])
455 , file_name
, name_only
)))
461 void tm_workspace_recreate_tags_array(void)
465 TMTagAttrType sort_attrs
[] = { tm_tag_attr_name_t
, tm_tag_attr_file_t
466 , tm_tag_attr_scope_t
, tm_tag_attr_type_t
, tm_tag_attr_arglist_t
, 0};
469 g_message("Recreating workspace tags array");
472 if ((NULL
== theWorkspace
) || (NULL
== theWorkspace
->work_objects
))
474 if (NULL
!= theWorkspace
->work_object
.tags_array
)
475 g_ptr_array_set_size(theWorkspace
->work_object
.tags_array
, 0);
477 theWorkspace
->work_object
.tags_array
= g_ptr_array_new();
480 g_message("Total %d objects", theWorkspace
->work_objects
->len
);
482 for (i
=0; i
< theWorkspace
->work_objects
->len
; ++i
)
484 w
= TM_WORK_OBJECT(theWorkspace
->work_objects
->pdata
[i
]);
486 g_message("Adding tags of %s", w
->file_name
);
488 if ((NULL
!= w
) && (NULL
!= w
->tags_array
) && (w
->tags_array
->len
> 0))
490 for (j
= 0; j
< w
->tags_array
->len
; ++j
)
492 g_ptr_array_add(theWorkspace
->work_object
.tags_array
,
493 w
->tags_array
->pdata
[j
]);
498 g_message("Total: %d tags", theWorkspace
->work_object
.tags_array
->len
);
500 tm_tags_sort(theWorkspace
->work_object
.tags_array
, sort_attrs
, TRUE
);
503 gboolean
tm_workspace_update(TMWorkObject
*workspace
, gboolean force
504 , gboolean recurse
, gboolean __unused__ update_parent
)
507 gboolean update_tags
= force
;
510 g_message("Updating workspace");
513 if (workspace
!= TM_WORK_OBJECT(theWorkspace
))
515 if (NULL
== theWorkspace
)
517 if ((recurse
) && (theWorkspace
->work_objects
))
519 for (i
=0; i
< theWorkspace
->work_objects
->len
; ++i
)
521 if (TRUE
== tm_work_object_update(TM_WORK_OBJECT(
522 theWorkspace
->work_objects
->pdata
[i
]), FALSE
, TRUE
, FALSE
))
527 tm_workspace_recreate_tags_array();
528 /* workspace->analyze_time = time(NULL); */
532 void tm_workspace_dump(void)
537 g_message("Dumping TagManager workspace tree..");
539 tm_work_object_dump(TM_WORK_OBJECT(theWorkspace
));
540 if (theWorkspace
->work_objects
)
543 for (i
=0; i
< theWorkspace
->work_objects
->len
; ++i
)
545 if (IS_TM_PROJECT(TM_WORK_OBJECT(theWorkspace
->work_objects
->pdata
[i
])))
546 tm_project_dump(TM_PROJECT(theWorkspace
->work_objects
->pdata
[i
]));
548 tm_work_object_dump(TM_WORK_OBJECT(theWorkspace
->work_objects
->pdata
[i
]));
554 const GPtrArray
*tm_workspace_find(const char *name
, int type
, TMTagAttrType
*attrs
555 , gboolean partial
, langType lang
)
557 static GPtrArray
*tags
= NULL
;
559 int len
, tagCount
[2]={0,0}, tagIter
;
562 if ((!theWorkspace
) || (!name
))
568 g_ptr_array_set_size(tags
, 0);
570 tags
= g_ptr_array_new();
572 matches
[0] = tm_tags_find(theWorkspace
->work_object
.tags_array
, name
, partial
, &tagCount
[0]);
573 matches
[1] = tm_tags_find(theWorkspace
->global_tags
, name
, partial
, &tagCount
[1]);
576 if (matches
[0] && *matches
[0])
578 /* tag->atts.file.lang contains the line of the tag and
579 * tags->atts.entry.file->lang contains the language */
580 tags_lang
= (*matches
[0])->atts
.entry
.file
->lang
;
582 for (tagIter
=0;tagIter
<tagCount
[0];++tagIter
)
584 if ((type
& (*matches
[0])->type
) && (lang
== -1 || tags_lang
== lang
))
585 g_ptr_array_add(tags
, *matches
[0]);
588 if (0 != strncmp((*matches
[0])->name
, name
, len
))
593 if (0 != strcmp((*matches
[0])->name
, name
))
601 if (matches
[1] && *matches
[1])
603 int tags_lang_alt
= 0;
604 /* tag->atts.file.lang contains the language and
605 * tags->atts.entry.file is NULL */
606 tags_lang
= (*matches
[1])->atts
.file
.lang
;
607 /* tags_lang_alt is used to load C global tags only once for C and C++
608 * lang = 1 is C++, lang = 0 is C
609 * if we have lang 0, than accept also lang 1 for C++ */
610 if (tags_lang
== 0) /* C or C++ */
613 tags_lang_alt
= tags_lang
; /* otherwise just ignore it */
615 for (tagIter
=0;tagIter
<tagCount
[1];++tagIter
)
617 if ((type
& (*matches
[1])->type
) && (lang
== -1 ||
618 tags_lang
== lang
|| tags_lang_alt
== lang
))
619 g_ptr_array_add(tags
, *matches
[1]);
623 if (0 != strncmp((*matches
[1])->name
, name
, len
))
628 if (0 != strcmp((*matches
[1])->name
, name
))
636 tm_tags_sort(tags
, attrs
, TRUE
);
640 static gboolean
match_langs(gint lang
, const TMTag
*tag
)
642 if (tag
->atts
.entry
.file
)
643 { /* workspace tag */
644 if (lang
== tag
->atts
.entry
.file
->lang
)
649 if (lang
== tag
->atts
.file
.lang
)
655 /* scope can be NULL.
658 fill_find_tags_array (GPtrArray
*dst
, const GPtrArray
*src
,
659 const char *name
, const char *scope
, int type
, gboolean partial
,
660 gint lang
, gboolean first
)
665 if ((!src
) || (!dst
) || (!name
) || (!*name
))
668 match
= tm_tags_find (src
, name
, partial
, &count
);
669 if (count
&& match
&& *match
)
671 for (tagIter
= 0; tagIter
< count
; ++tagIter
)
673 if (! scope
|| (match
[tagIter
]->atts
.entry
.scope
&&
674 0 == strcmp(match
[tagIter
]->atts
.entry
.scope
, scope
)))
676 if (type
& match
[tagIter
]->type
)
677 if (lang
== -1 || match_langs(lang
, match
[tagIter
]))
679 g_ptr_array_add (dst
, match
[tagIter
]);
690 /* adapted from tm_workspace_find, Anjuta 2.02 */
692 tm_workspace_find_scoped (const char *name
, const char *scope
, gint type
,
693 TMTagAttrType
*attrs
, gboolean partial
, langType lang
, gboolean global_search
)
695 static GPtrArray
*tags
= NULL
;
701 g_ptr_array_set_size (tags
, 0);
703 tags
= g_ptr_array_new ();
705 fill_find_tags_array (tags
, theWorkspace
->work_object
.tags_array
,
706 name
, scope
, type
, partial
, lang
, FALSE
);
709 /* for a scoped tag, I think we always want the same language */
710 fill_find_tags_array (tags
, theWorkspace
->global_tags
,
711 name
, scope
, type
, partial
, lang
, FALSE
);
714 tm_tags_sort (tags
, attrs
, TRUE
);
720 tm_get_current_function (GPtrArray
* file_tags
, const gulong line
)
722 GPtrArray
*const local
= tm_tags_extract (file_tags
, tm_tag_function_t
);
723 if (local
&& local
->len
)
726 TMTag
*tag
, *function_tag
= NULL
;
727 gulong function_line
= 0;
730 for (i
= 0; (i
< local
->len
); ++i
)
732 tag
= TM_TAG (local
->pdata
[i
]);
733 delta
= line
- tag
->atts
.entry
.line
;
734 if (delta
>= 0 && (gulong
)delta
< line
- function_line
)
737 function_line
= tag
->atts
.entry
.line
;
740 g_ptr_array_free (local
, TRUE
);
748 find_scope_members_tags (const GPtrArray
* all
, GPtrArray
* tags
,
749 const langType langJava
, const char *name
,
750 const char *filename
, gboolean no_definitions
)
752 GPtrArray
*local
= g_ptr_array_new ();
755 size_t len
= strlen (name
);
756 for (i
= 0; (i
< all
->len
); ++i
)
758 tag
= TM_TAG (all
->pdata
[i
]);
759 if (no_definitions
&& filename
&& tag
->atts
.entry
.file
&&
760 0 != strcmp (filename
,
761 tag
->atts
.entry
.file
->work_object
.short_name
))
765 if (tag
&& tag
->atts
.entry
.scope
&& tag
->atts
.entry
.scope
[0] != '\0')
767 if (0 == strncmp (name
, tag
->atts
.entry
.scope
, len
))
769 g_ptr_array_add (local
, tag
);
778 char *s_backup
= NULL
;
779 char *var_type
= NULL
;
781 for (i
= 0; (i
< local
->len
); ++i
)
783 tag
= TM_TAG (local
->pdata
[i
]);
784 scope
= tag
->atts
.entry
.scope
;
785 if (scope
&& 0 == strcmp (name
, scope
))
787 g_ptr_array_add (tags
, tag
);
791 j
= 0; /* someone could write better code :P */
796 backup
= s_backup
[0];
798 if (0 == strcmp (name
, tag
->atts
.entry
.scope
))
801 s_backup
[0] = backup
;
805 if (tag
->atts
.entry
.file
806 && tag
->atts
.entry
.file
->lang
== langJava
)
808 scope
= strrchr (tag
->atts
.entry
.scope
, '.');
810 var_type
= scope
+ 1;
814 scope
= strrchr (tag
->atts
.entry
.scope
, ':');
817 var_type
= scope
+ 1;
823 s_backup
[0] = backup
;
829 backup
= s_backup
[0];
832 for (j
= 0; (j
< local
->len
); ++j
)
836 tag2
= TM_TAG (local
->pdata
[j
]);
837 if (tag2
->atts
.entry
.var_type
&&
838 0 == strcmp (var_type
, tag2
->atts
.entry
.var_type
))
844 s_backup
[0] = backup
;
854 g_ptr_array_add (tags
, tag
);
858 g_ptr_array_free (local
, TRUE
);
859 return (int) tags
->len
;
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 ();
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
))
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
);
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
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
;
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;
932 g_return_val_if_fail ((theWorkspace
&& name
&& name
[0] != '\0'), NULL
);
935 tags
= g_ptr_array_new ();
939 const GPtrArray
*tags2
;
940 int got
= 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
);
946 g_ptr_array_set_size (tags
, 0);
947 got
= fill_find_tags_array (tags
, file_tags
,
948 new_name
, NULL
, types
, FALSE
, -1, FALSE
);
958 TMTagAttrType attrs
[] = {
959 tm_tag_attr_name_t
, tm_tag_attr_type_t
,
962 tags2
= tm_workspace_find (new_name
, types
, attrs
, FALSE
, -1);
965 if ((tags2
) && (tags2
->len
== 1) && (tag
= TM_TAG (tags2
->pdata
[0])))
967 if (tag
->type
== tm_tag_typedef_t
&& tag
->atts
.entry
.var_type
968 && tag
->atts
.entry
.var_type
[0] != '\0')
970 new_name
= tag
->atts
.entry
.var_type
;
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')
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
,
987 new_name
= g_strdup_printf ("%s::%s",
988 tag
->atts
.entry
.scope
,
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
));
1011 local
= tm_tags_extract (theWorkspace
->work_object
.tags_array
,
1012 (tm_tag_function_t
| tm_tag_prototype_t
|
1014 tm_tag_field_t
| tm_tag_enumerator_t
|
1015 tm_tag_namespace_t
| tm_tag_class_t
));
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
,
1030 tm_tag_prototype_t
|
1034 tm_tag_enumerator_t
|
1035 tm_tag_namespace_t
|
1040 find_namespace_members_tags (global
, tags
, langJava
,
1041 new_name
, filename
);
1043 DEBUG_PRINT ("returning these");
1045 for (i=0; i < tags->len; i++) {
1048 cur_tag = (TMTag*)g_ptr_array_index (tags, i);
1049 tm_tag_print (cur_tag, stdout );
1052 g_ptr_array_free (global, TRUE);
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;
1079 /* langJava = getNamedLanguage ("Java"); */
1081 g_return_val_if_fail ((theWorkspace
&& name
&& name
[0] != '\0'), NULL
);
1084 tags
= g_ptr_array_new ();
1088 const GPtrArray
*tags2
;
1089 int got
= 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
);
1095 g_ptr_array_set_size (tags
, 0);
1096 got
= fill_find_tags_array (tags
, file_tags
,
1097 new_name
, NULL
, types
, FALSE
, -1, FALSE
);
1105 TMTagAttrType attrs
[] = {
1106 tm_tag_attr_name_t
, tm_tag_attr_type_t
,
1109 tags2
= tm_workspace_find (new_name
, types
, attrs
, FALSE
, -1);
1112 if ((tags2
) && (tags2
->len
== 1) && (tag
= TM_TAG (tags2
->pdata
[0])))
1114 if (tag
->type
== tm_tag_typedef_t
&& tag
->atts
.entry
.var_type
1115 && tag
->atts
.entry
.var_type
[0] != '\0')
1118 tmp_name
= tag
->atts
.entry
.var_type
;
1119 if (strcmp(tmp_name
, new_name
) == 0) {
1123 new_name
= tmp_name
;
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')
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
,
1141 new_name
= g_strdup_printf ("%s::%s",
1142 tag
->atts
.entry
.scope
,
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
));
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
));
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
,
1180 tm_tag_prototype_t
|
1185 |tm_tag_struct_t
| tm_tag_typedef_t
|
1186 tm_tag_union_t
| tm_tag_enum_t
));
1189 find_scope_members_tags (global
, tags
, langJava
, new_name
,
1190 filename
, no_definitions
);
1191 g_ptr_array_free (global
, TRUE
);
1202 const GPtrArray
*tm_workspace_get_parents(const gchar
*name
)
1204 static TMTagAttrType type
[] = { tm_tag_attr_name_t
, tm_tag_attr_none_t
};
1205 static GPtrArray
*parents
= NULL
;
1206 const GPtrArray
*matches
;
1213 g_return_val_if_fail(name
&& isalpha(*name
),NULL
);
1215 if (NULL
== parents
)
1216 parents
= g_ptr_array_new();
1218 g_ptr_array_set_size(parents
, 0);
1219 matches
= tm_workspace_find(name
, tm_tag_class_t
, type
, FALSE
, -1);
1220 if ((NULL
== matches
) || (0 == matches
->len
))
1222 g_ptr_array_add(parents
, matches
->pdata
[0]);
1223 while (i
< parents
->len
)
1225 tag
= TM_TAG(parents
->pdata
[i
]);
1226 if ((NULL
!= tag
->atts
.entry
.inheritance
) && (isalpha(tag
->atts
.entry
.inheritance
[0])))
1228 klasses
= g_strsplit(tag
->atts
.entry
.inheritance
, ",", 10);
1229 for (klass
= klasses
; (NULL
!= *klass
); ++ klass
)
1231 for (j
=0; j
< parents
->len
; ++j
)
1233 if (0 == strcmp(*klass
, TM_TAG(parents
->pdata
[j
])->name
))
1236 if (parents
->len
== j
)
1238 matches
= tm_workspace_find(*klass
, tm_tag_class_t
, type
, FALSE
, -1);
1239 if ((NULL
!= matches
) && (0 < matches
->len
))
1240 g_ptr_array_add(parents
, matches
->pdata
[0]);
1243 g_strfreev(klasses
);