748137bd1dfa648948d9d127aa3e27b6857db764 improved return types, but as
this test case was added in parallel it wasn't updated as needed for
the new, more correct, results.
The script reads the doxygen xml output and generates two headers (optionally
a single header) that contains all of the plugin API in gtk-doc format.
Two headers because it's preferrable to group Scintilla related stuff
into its own namespace. This is a lot easier if g-ir-scanner can
work with a separate header file. If we change minds later on the script is
prepared to generate only one header.
A script will use the xml to generate a gtkdoc'ized header of the plugin API.
The xml files are also installed so that external users can use the xml
that corresponds to the installed version of Geany.
For now a separet doxyfile is used because the gtkdoc'ized header needs
a few types to be documented which not desired to be documented generally.
We only perform search based on variable name so if a variable is e.g. of
the type std::Foo, we can drop the std:: prefix and search only for the
Foo type.
This is far from perfect and contains a lot of guessing. It showed
good results based on our tests cases, fixing several issues and not
introducing any more issues (admittedly, after working around a subtle
one regarding D static ifs).
Closes#845.
Also, don't perform subtractions to check pointer bounds, to avoid
unsigned value wraparound. This is very unlikely as it would either
mean a very large `nth` value or a very small value for the current
line pointer, but better safe than sorry.
See http://en.cppreference.com/w/cpp/language/string_literalCloses#877.
---
This contains a pretty ugly hack to fetch the previous character, in
order not to get fooled by string concatenation hidden behind a macro,
like in `FOUR"five"`, which is not a raw string literal but simply the
identifier `FOUR` followed by the string `"five"`.
While this may sound uncommon, it is not and lead to complaints [2][3]
when Scintilla [1] broke this when they introduced C++11 raw string
literal support themselves.
The implementation here still contains a bug with line continuations: a
raw literal of the form:
```c
const char *str = R\
"xxx(...)xxx";
```
is not properly recognized as such, although it's perfectly valid (yet
probably very uncommon). For the record, Scintilla has also suffers
from this but nobody complained about it yet.
[1] http://scintilla.org/
[2] https://sourceforge.net/p/scintilla/bugs/1207/
[3] https://sourceforge.net/p/scintilla/bugs/1454/
This script was used in the nightly builds to verify plugins will load
and have no undefined symbol references. Since the new way plugins
are built and linked, this is no longer necessary.
Additionally, this script won't work with new style geany_load_module()
plugins.
Because the stash_group_new() is an exported API, it has to be at least a boxed
type to be usable for gobject introspection. The boxed type uses reference
counting as opposed to memory duplication.
The obligatory stash_group_dup() is not exported (doesn't have to).
Because the tm_source_file_new() is an exported API, it has to be at least a
boxed type to be usable for gobject introspection. The boxed type uses
reference counting as opposed to memory duplication.
The obligatory tm_source_file_dup() is not exported (doesn't have to).
First, the search for existing type with the given scope should be done
also for namespaces.
Second, with the string operations we get no scope as empty string ""
but the rest of TM functions expect scope to be set to NULL in such
case. Fix that.
When we already have a struct-like type in namespace search,
we don't need any extra resolution - we already have the
right type. Skip the whole typedef resolution in this case.
Make sure the anonymous types are from the same file as the
variable of that type (or, when performing typedef resolution, from
the same file as the typedef).
On the way, simplify find_scope_members() a bit and fix some minor
problems.
Make the unused code compile and remove unused tm_get_current_function()
(we have similar symbols_get_current_function() and there's no reason
to keep it)
The main reason for separating m_workspace_find() into two parts is the
fact that when matching only the prefix, the result may contain too
many results and we need to go through all of them, return them and at the
end discard most of them.
For instance, when considering the linux kernel project with 2300000 tags
and when autocompletion is set to be invoked after typing a single character,
we get on average something like 100000 results (tag_num/alphabet_size).
But from these 100000 results, we get only the first 30 which we display
in the popup and discard the rest which means going through the list of
the 100000 tags and comparing them for no reason.
Thanks to using binary search for the start and the end of the sequence of
matching tags (added in a separate patch), we can get the start of the
sequence and the length of the sequence very quickly without going through
it.
For the prefix search we can limit the number of tags we are interested
in and go through at most this number of returned tags (to be precise,
times two, because we need to go both through the workspace array and
global tags array and remove the extras only after sorting the two).
It would be possible to combine both tm_workspace_find() and
tm_workspace_find_prefix() into a single function but the result is a bit
hard to read because some of the logic is used only in tm_workspace_find()
and some only in tm_workspace_find_prefix() so even though there is some
code duplication, I believe it's easier to understand this way.
Consider types with members to have the same properties everywhere (this
might differ language to language but this assumption should behave
reasonably for any language).
Don't check member type in find_scope_members_tags() - we already check
scope which should be sufficient and will work even if some language
uses function/variable instead of method/member/field.
When scope autocompletion list shows, start filtering it when
when the user types some more characters. As long as the list
is non-empty, don't switch to normal autocompletion and show
only the scope autocompletion results.
For instance, consider
class A {
int a;
int b;
}
class B {
A c;
void foo() {
c. //<---- (3)
}
}
int main() {
c. //<---- (1)
foo.c. //<---- (2)
}
Consider cases (1) and (2) first - in the case (1) scope completion
shouldn't be performed because c isn't a global variable; however,
in case (2) it should be performed because c is a member.
To fix this, we can check whether the typed variable ('c' in this case)
is preceeded by another dot - if it is, use member tags for scope
completion; otherwise don't use them.
There's one exception from this rule - in the case (3) we are accessing
a member variable from a member function at the same scope so the
function should have access to the variable. For this we can use the
scope at the position of the cursor. It should be
B::foo
in this case, more generally ...::class_name::function_name. We need
to check if class_name exists at the given scope and if the member
variable we are trying to access is inside ...::class_name - if so,
scope completion can be performed using member tags (without explicit
invocation on a member).