Use the same (or compatible) sorting criteria everywhere.
Add tm_tag_attr_line_t to sort options so even after merging file tags
into workspace tags, the same tags defined at different lines are preserved
and not removed as duplicates.
Sort type before scope because it's cheaper to compare (string vs int comparison).
For some reason, the above changes make the sorting performance worse.
Simplify the tag comparison function a bit and reorder the case statements
in the switch to match the sort order. This (again not sure why), makes the
performance like before.
Previously, after finishing the while loop TRUE was returned - this is
wrong because the while was running because parsing was unsuccessful.
Make it work the same way as in ctags (parser() always succeeds,
parser2() returns whether to retry or not).
(The return value actually isn't used, it's just to make sure we know
what we are doing.)
With the previous TMWorkspace API it was possible to make the workspace
inconsistent by e.g. removing source files and forgetting to update
workspace. This could lead to non-obvious and not immediately visible
crashes.
The new set of the public (but also Geany private) API calls always
updates the workspace accordingly and neither of the calls can lead
to an inconsistent state of the workspace.
In addition, perform some minor cleanups and simplifications - unify
parsing from buffer and from file, support "parsing" of 0-sized buffers
and improve documentation.
Manage the list the same way as workspace tags_array by the fast tag removal
and merge. Thanks to this, typename tags don't have to be extracted from
tags_array periodically, which speeds up editing.
Even though the binary search requires expensive string comparisons,
there are just log(n) of them to find the tag in the workspace array
and the result is much faster than scanning the array linearly (this
of course works only under the condition that
len(source_file->tags_array) << len(workspace_array)
This is however satisfied for big projects (and doesn't matter for small
projects).
Also make the tm_tags_find() function more user friendly by returning
tagCount 0 when no tags found.
Instead of qsort() it's possible to use g_ptr_array_sort_with_data() with
similar performance. Unfortunately it seems there's no bsearch_with_data()
anywhere so the patch uses a modified bsearch() implementation from libc
(still probably cleaner than passing arguments using static variables).
Lazy initializing various member pointers doesn't bring any real performance
improvement but it requires lots of additional NULL checks - get rid of
this.
Make some more cleanups on the way.
In addition, remove success/failure return values from tm_workspace_add_source_file()
and tm_workspace_remove_source_file() which have no real use.
Avoid "utility" parameters like do_free for which we already have API calls
and which actually don't perform any free if the source file isn't
in TM. Clarify when to set the update_workspace parameter.
The placement of this function in tm_source_file is not right - by moving
it to the workspace we can make the source file unaware of the existence
of the workspace (no inclusion of tm_workspace.h in tm_source_file any
more). Also change tm_source_file_new() so it doesn't offer the source file
update.
After this change
* TMWorkspace knows TMSourceFile and TMTag
* TMSourceFile knows TMTag
* TMTag knows TMSourceFile
Set them also when they are NULL in the project (which happens when new
project is created) because otherwise there are left-over values from
the previous project.
This allows the compilers to check that the plugin's symbols have the
proper prototype. Doing so can avoid subtle and hard-to-find bugs in
case a plugin's symbol has incorrect signature as dlsym() can't check
if the signature is actually the one we expect.
As a bonus, it helps when using -Wmissing-prototypes as it provides the
prototypes.
This makes it less confusing for code accessing TMTag so it can always
find the language in tag->lang and there is no need to access it through
tag->file.lang.
The union on TMTag is very confusing and rather dangerous. The fields
file/timestamp and line/lang overlap. Some implicit assumptions are made
in the code - timestamp is never set so when file is NULL, the file
struct should be used to get the lang member. Rather avoid using unions
and move the lang member to the entry struct together with the other
attributes.
Similarly, add #if TM_DEBUG around various unused debugging functions.
The #if 0 surrounded functions are good candidate for future removal
if decided they are not needed any more.