1
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
4
* Copyright (C) 2007 Naba Kumar <naba@gnome.org>
5
* Johannes Schmid <jhs@gnome.org>
7
* anjuta is free software.
9
* You may redistribute it and/or modify it under the terms of the
10
* GNU General Public License, as published by the Free Software
11
* Foundation; either version 2 of the License, or (at your option)
14
* anjuta is distributed in the hope that it will be useful,
15
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17
* See the GNU General Public License for more details.
19
* You should have received a copy of the GNU General Public License
20
* along with anjuta. If not, write to:
21
* The Free Software Foundation, Inc.,
22
* 51 Franklin Street, Fifth Floor
23
* Boston, MA 02110-1301, USA.
28
#include <libanjuta/anjuta-debug.h>
29
#include <libanjuta/anjuta-language-provider.h>
30
#include <libanjuta/anjuta-utils.h>
31
#include <libanjuta/interfaces/ianjuta-file.h>
32
#include <libanjuta/interfaces/ianjuta-editor-cell.h>
33
#include <libanjuta/interfaces/ianjuta-editor-assist.h>
34
#include <libanjuta/interfaces/ianjuta-editor-tip.h>
35
#include <libanjuta/interfaces/ianjuta-language-provider.h>
36
#include <libanjuta/interfaces/ianjuta-symbol-manager.h>
37
#include "parser-cxx-assist.h"
38
#include "cxxparser/engine-parser.h"
40
#define BRACE_SEARCH_LIMIT 500
41
#define SCOPE_CONTEXT_CHARACTERS "_.:>-0"
42
#define WORD_CHARACTER "_0"
44
static void iprovider_iface_init(IAnjutaProviderIface* iface);
45
static void ilanguage_provider_iface_init(IAnjutaLanguageProviderIface* iface);
47
G_DEFINE_TYPE_WITH_CODE (ParserCxxAssist,
50
G_IMPLEMENT_INTERFACE (IANJUTA_TYPE_PROVIDER,
52
G_IMPLEMENT_INTERFACE (IANJUTA_TYPE_LANGUAGE_PROVIDER,
53
ilanguage_provider_iface_init))
55
struct _ParserCxxAssistPriv {
57
IAnjutaEditorAssist* iassist;
58
IAnjutaEditorTip* itip;
59
AnjutaLanguageProvider* lang_prov;
61
const gchar* editor_filename;
64
gchar* calltip_context;
65
IAnjutaIterable* calltip_iter;
68
gint async_calltip_file;
69
gint async_calltip_system;
70
gint async_calltip_project;
72
IAnjutaSymbolQuery *calltip_query_file;
73
IAnjutaSymbolQuery *calltip_query_system;
74
IAnjutaSymbolQuery *calltip_query_project;
77
GCompletion *completion_cache;
79
gboolean member_completion;
80
gboolean autocompletion;
84
gint async_project_id;
86
IAnjutaSymbolQuery *ac_query_file;
87
IAnjutaSymbolQuery *ac_query_system;
88
IAnjutaSymbolQuery *ac_query_project;
90
/* Member autocompletion */
91
IAnjutaSymbolQuery *query_members;
94
IAnjutaSymbolQuery *sync_query_file;
95
IAnjutaSymbolQuery *sync_query_system;
96
IAnjutaSymbolQuery *sync_query_project;
100
* parser_cxx_assist_proposal_new:
101
* @symbol: IAnjutaSymbol to create the proposal for
103
* Creates a new IAnjutaEditorAssistProposal for symbol
105
* Returns: a newly allocated IAnjutaEditorAssistProposal
107
static IAnjutaEditorAssistProposal*
108
parser_cxx_assist_proposal_new (IAnjutaSymbol* symbol)
110
IAnjutaEditorAssistProposal* proposal = g_new0 (IAnjutaEditorAssistProposal, 1);
111
AnjutaLanguageProposalData* data =
112
anjuta_language_proposal_data_new (g_strdup (ianjuta_symbol_get_string (symbol, IANJUTA_SYMBOL_FIELD_NAME, NULL)));
113
data->type = ianjuta_symbol_get_sym_type (symbol, NULL);
116
case IANJUTA_SYMBOL_TYPE_PROTOTYPE:
117
case IANJUTA_SYMBOL_TYPE_FUNCTION:
118
case IANJUTA_SYMBOL_TYPE_METHOD:
119
case IANJUTA_SYMBOL_TYPE_MACRO_WITH_ARG:
120
proposal->label = g_strdup_printf ("%s()", data->name);
121
data->is_func = TRUE;
124
proposal->label = g_strdup (data->name);
125
data->is_func = FALSE;
127
data->has_para = FALSE;
130
const gchar* signature = ianjuta_symbol_get_string (symbol,
131
IANJUTA_SYMBOL_FIELD_SIGNATURE,
133
if (g_strcmp0 (signature, "(void)") || g_strcmp0 (signature, "()"))
134
data->has_para = TRUE;
138
proposal->data = data;
139
/* Icons are lifetime object of the symbol-db so we can cast here */
140
proposal->icon = (GdkPixbuf*) ianjuta_symbol_get_icon (symbol, NULL);
145
* parser_cxx_assist_proposal_free:
146
* @proposal: the proposal to free
151
parser_cxx_assist_proposal_free (IAnjutaEditorAssistProposal* proposal)
153
AnjutaLanguageProposalData* data = proposal->data;
154
anjuta_language_proposal_data_free (data);
155
g_free (proposal->label);
160
* anjuta_propsal_completion_func:
161
* @data: an IAnjutaEditorAssistProposal
163
* Returns: the name of the completion func
166
anjuta_proposal_completion_func (gpointer data)
168
IAnjutaEditorAssistProposal* proposal = data;
169
AnjutaLanguageProposalData* prop_data = proposal->data;
171
return prop_data->name;
175
* parser_cxx_assist_create_completion_from_symbols:
176
* @symbols: Symbol iteration
178
* Create a list of IAnjutaEditorAssistProposals from a list of symbols
180
* Returns: a newly allocated GList of newly allocated proposals. Free
181
* with cpp_java_assist_proposal_free()
184
parser_cxx_assist_create_completion_from_symbols (IAnjutaIterable* symbols)
192
IAnjutaSymbol* symbol = IANJUTA_SYMBOL (symbols);
193
IAnjutaEditorAssistProposal* proposal = parser_cxx_assist_proposal_new (symbol);
195
list = g_list_append (list, proposal);
197
while (ianjuta_iterable_next (symbols, NULL));
203
* parser_cxx_assist_update_pre_word:
205
* @pre_word: new pre_word
207
* Updates the current pre_word
210
parser_cxx_assist_update_pre_word (ParserCxxAssist* assist,
211
const gchar* pre_word)
213
g_free (assist->priv->pre_word);
214
if (pre_word == NULL)
216
assist->priv->pre_word = g_strdup (pre_word);
220
* parser_cxx_assist_is_expression_separator:
221
* @c: character to check
222
* @skip_braces: whether to skip closing braces
223
* @iter: current cursor position
225
* Checks if a character seperates a C/C++ expression. It can skip brances
226
* because they might not really end the expression
228
* Returns: TRUE if the characters seperates an expression, FALSE otherwise
231
parser_cxx_assist_is_expression_separator (gchar c,
232
gboolean skip_braces,
233
IAnjutaIterable* iter)
235
IAnjutaEditorAttribute attrib = ianjuta_editor_cell_get_attribute (
236
IANJUTA_EDITOR_CELL(iter), NULL);
238
const gchar separators[] = {',', ';', '\n', '\r', '\t', '(',
239
'{', '}', '=', '<', '\v', '!',
240
'&', '%', '*', '[', ']', '?', '/',
243
if (attrib == IANJUTA_EDITOR_STRING ||
244
attrib == IANJUTA_EDITOR_COMMENT)
249
if (c == ')' && skip_braces)
251
anjuta_util_jump_to_matching_brace (iter, c, BRACE_SEARCH_LIMIT);
254
else if (c == ')' && !skip_braces)
257
for (i = 0; separators[i] != 0; i++)
259
if (separators[i] == c)
267
* parser_cxx_assist_parse_expression:
269
* @iter: current cursor position
270
* @start_iter: return location for the start of the completion
272
* Returns: An iter of a list of IAnjutaSymbols or NULL
274
static IAnjutaIterable*
275
parser_cxx_assist_parse_expression (ParserCxxAssist* assist, IAnjutaIterable* iter, IAnjutaIterable** start_iter)
277
IAnjutaEditor* editor = IANJUTA_EDITOR (assist->priv->iassist);
278
IAnjutaIterable* res = NULL;
279
IAnjutaIterable* cur_pos = ianjuta_iterable_clone (iter, NULL);
280
gboolean op_start = FALSE;
281
gboolean ref_start = FALSE;
284
/* Cursor points after the current characters, move back */
285
ianjuta_iterable_previous (cur_pos, NULL);
287
/* Search for a operator in the current line */
290
gchar ch = ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL(cur_pos),
293
if (parser_cxx_assist_is_expression_separator(ch, FALSE, iter)) {
297
if (ch == '.' || (op_start && ch == '-') || (ref_start && ch == ':'))
299
/* Found an operator, get the statement and the pre_word */
300
IAnjutaIterable* pre_word_start = ianjuta_iterable_clone (cur_pos,
302
IAnjutaIterable* pre_word_end = ianjuta_iterable_clone (iter, NULL);
303
IAnjutaIterable* stmt_end = ianjuta_iterable_clone (pre_word_start,
307
/* we need to pass to the parser all the statement included the last
308
* operator, being it "." or "->" or "::"
309
* Increase the end bound of the statement.
311
ianjuta_iterable_next (stmt_end, NULL);
312
if (op_start == TRUE || ref_start == TRUE)
313
ianjuta_iterable_next (stmt_end, NULL);
316
/* Move one character forward so we have the start of the pre_word
317
* and not the last operator */
318
ianjuta_iterable_next (pre_word_start, NULL);
319
/* If this is a two character operator, skip the second character */
322
ianjuta_iterable_next (pre_word_start, NULL);
325
parser_cxx_assist_update_pre_word (assist, ianjuta_editor_get_text (
331
/* Try to get the name of the variable */
332
while (ianjuta_iterable_previous (cur_pos, NULL))
334
gchar word_ch = ianjuta_editor_cell_get_char (
335
IANJUTA_EDITOR_CELL(cur_pos), 0, NULL);
337
if (parser_cxx_assist_is_expression_separator(word_ch, FALSE,
341
ianjuta_iterable_next (cur_pos, NULL);
342
stmt = ianjuta_editor_get_text (editor,
343
cur_pos, stmt_end, NULL);
344
*start_iter = pre_word_start;
345
g_object_unref (stmt_end);
346
g_object_unref (pre_word_end);
359
while (ianjuta_iterable_previous (cur_pos, NULL));
365
IAnjutaIterable* start;
367
if (!assist->priv->editor_filename)
373
start = ianjuta_editor_get_start_position (editor, NULL);
374
above_text = ianjuta_editor_get_text (editor, start, iter, NULL);
375
g_object_unref (start);
377
lineno = ianjuta_editor_get_lineno (editor, NULL);
379
/* the parser works even for the "Gtk::" like expressions, so it
380
* shouldn't be created a specific case to handle this.
382
res = engine_parser_process_expression (stmt,
384
assist->priv->editor_filename,
388
g_object_unref (cur_pos);
393
* parser_cxx_assist_create_completion_cache:
396
* Create a new completion_cache object
399
parser_cxx_assist_create_completion_cache (ParserCxxAssist* assist)
401
g_assert (assist->priv->completion_cache == NULL);
402
assist->priv->completion_cache =
403
g_completion_new (anjuta_proposal_completion_func);
407
* parser_cxx_assist_cancel_queries:
410
* Abort all async operations
413
parser_cxx_assist_cancel_queries (ParserCxxAssist* assist)
415
ianjuta_symbol_query_cancel (assist->priv->ac_query_file, NULL);
416
ianjuta_symbol_query_cancel (assist->priv->ac_query_project, NULL);
417
ianjuta_symbol_query_cancel (assist->priv->ac_query_system, NULL);
418
assist->priv->async_file_id = 0;
419
assist->priv->async_project_id = 0;
420
assist->priv->async_system_id = 0;
424
* parser_cxx_assist_clear_completion_cache:
427
* Clear the completion cache, aborting all async operations
430
parser_cxx_assist_clear_completion_cache (ParserCxxAssist* assist)
432
parser_cxx_assist_cancel_queries (assist);
433
if (assist->priv->completion_cache)
435
g_list_foreach (assist->priv->completion_cache->items,
436
(GFunc) parser_cxx_assist_proposal_free, NULL);
437
g_completion_free (assist->priv->completion_cache);
439
assist->priv->completion_cache = NULL;
440
assist->priv->member_completion = FALSE;
441
assist->priv->autocompletion = FALSE;
445
* parser_cxx_assist_populate_real:
447
* @finished: TRUE if no more proposals are expected, FALSE otherwise
449
* Really invokes the completion interfaces and adds completions.
450
* Might be called from an async context
453
parser_cxx_assist_populate_real (ParserCxxAssist* assist, gboolean finished)
455
g_assert (assist->priv->pre_word != NULL);
456
GList* proposals = g_completion_complete (assist->priv->completion_cache,
457
assist->priv->pre_word,
459
ianjuta_editor_assist_proposals (assist->priv->iassist,
460
IANJUTA_PROVIDER(assist), proposals,
461
assist->priv->pre_word, finished, NULL);
465
* parser_cxx_assist_create_member_completion_cache
467
* @cursor: Current cursor position
469
* Create the completion_cache for member completion if possible
471
* Returns: the iter where a completion cache was build, NULL otherwise
473
static IAnjutaIterable*
474
parser_cxx_assist_create_member_completion_cache (ParserCxxAssist* assist,
475
IAnjutaIterable* cursor)
477
IAnjutaIterable* symbol = NULL;
478
IAnjutaIterable* start_iter = NULL;
479
symbol = parser_cxx_assist_parse_expression (assist, cursor, &start_iter);
483
/* Query symbol children */
484
IAnjutaIterable *children =
485
ianjuta_symbol_query_search_members (assist->priv->query_members,
486
IANJUTA_SYMBOL(symbol),
489
g_object_unref (symbol);
493
parser_cxx_assist_create_completion_from_symbols (children);
494
parser_cxx_assist_create_completion_cache (assist);
495
g_completion_add_items (assist->priv->completion_cache, proposals);
497
parser_cxx_assist_populate_real (assist, TRUE);
498
g_list_free (proposals);
499
g_object_unref (children);
504
g_object_unref (start_iter);
509
* on_symbol_search_complete:
510
* @search_id: id of this search
511
* @symbols: the returned symbols
514
* Called by the async search method when it found symbols
517
on_symbol_search_complete (IAnjutaSymbolQuery *query, IAnjutaIterable* symbols,
518
ParserCxxAssist* assist)
521
proposals = parser_cxx_assist_create_completion_from_symbols (symbols);
523
if (query == assist->priv->ac_query_file)
524
assist->priv->async_file_id = 0;
525
else if (query == assist->priv->ac_query_project)
526
assist->priv->async_project_id = 0;
527
else if (query == assist->priv->ac_query_system)
528
assist->priv->async_system_id = 0;
530
g_assert_not_reached ();
532
g_completion_add_items (assist->priv->completion_cache, proposals);
533
gboolean running = assist->priv->async_system_id
534
|| assist->priv->async_file_id
535
|| assist->priv->async_project_id;
537
parser_cxx_assist_populate_real (assist, TRUE);
538
g_list_free (proposals);
542
* parser_cxx_assist_create_autocompletion_cache:
544
* @cursor: Current cursor position
546
* Create completion cache for autocompletion. This is done async.
548
* Returns: the iter where a preword was detected, NULL otherwise
550
static IAnjutaIterable*
551
parser_cxx_assist_create_autocompletion_cache (ParserCxxAssist* assist,
552
IAnjutaIterable* cursor)
554
IAnjutaIterable* start_iter;
555
gchar* pre_word = anjuta_language_provider_get_pre_word (
556
assist->priv->lang_prov,
557
IANJUTA_EDITOR (assist->priv->iassist),
558
cursor, &start_iter, WORD_CHARACTER);
559
if (!pre_word || strlen (pre_word) <= 3)
562
g_object_unref (start_iter);
567
gchar *pattern = g_strconcat (pre_word, "%", NULL);
569
parser_cxx_assist_create_completion_cache (assist);
570
parser_cxx_assist_update_pre_word (assist, pre_word);
572
if (IANJUTA_IS_FILE (assist->priv->iassist))
574
GFile *file = ianjuta_file_get_file (
575
IANJUTA_FILE (assist->priv->iassist), NULL);
578
assist->priv->async_file_id = 1;
579
ianjuta_symbol_query_search_file (assist->priv->ac_query_file,
580
pattern, file, NULL);
581
g_object_unref (file);
584
/* This will avoid duplicates of FUNCTION and PROTOTYPE */
585
assist->priv->async_project_id = 1;
586
ianjuta_symbol_query_search (assist->priv->ac_query_project, pattern,
588
assist->priv->async_system_id = 1;
589
ianjuta_symbol_query_search (assist->priv->ac_query_system, pattern,
599
* parser_cxx_assist_get_calltip_context:
601
* @iter: current cursor position
602
* @e: Error propagation
604
* Searches for a calltip context
606
* Returns: name of the method to show a calltip for or NULL
609
parser_cxx_assist_get_calltip_context (IAnjutaLanguageProvider *self,
610
IAnjutaIterable *iter,
613
ParserCxxAssist* assist = PARSER_CXX_ASSIST (self);
614
gchar* calltip_context;
615
calltip_context = anjuta_language_provider_get_calltip_context (
616
assist->priv->lang_prov, assist->priv->itip, iter,
617
SCOPE_CONTEXT_CHARACTERS);
618
return calltip_context;
622
* parser_cxx_assist_create_calltips:
623
* @iter: List of symbols
624
* @merge: list of calltips to merge or NULL
626
* Create a list of Calltips (string) from a list of symbols
628
* A newly allocated GList* with newly allocated strings
631
parser_cxx_assist_create_calltips (IAnjutaIterable* iter, GList* merge)
638
IAnjutaSymbol* symbol = IANJUTA_SYMBOL (iter);
639
const gchar* name = ianjuta_symbol_get_string (
640
symbol,IANJUTA_SYMBOL_FIELD_NAME, NULL);
643
const gchar* args = ianjuta_symbol_get_string (
645
IANJUTA_SYMBOL_FIELD_SIGNATURE,
647
const gchar* rettype = ianjuta_symbol_get_string (
649
IANJUTA_SYMBOL_FIELD_RETURNTYPE,
654
gint white_count = 0;
659
white_count += strlen(rettype) + 1;
661
white_count += strlen(name) + 1;
663
white_name = g_strnfill (white_count, ' ');
664
separator = g_strjoin (NULL, ", \n", white_name, NULL);
669
argv = g_strsplit (args, ",", -1);
670
print_args = g_strjoinv (separator, argv);
671
gchar* tip = g_strdup_printf ("%s %s %s", rettype, name,
674
if (!g_list_find_custom (tips, tip, (GCompareFunc) strcmp))
675
tips = g_list_append (tips, tip);
685
while (ianjuta_iterable_next (iter, NULL));
691
* on_calltip_search_complete:
692
* @search_id: id of this search
693
* @symbols: the returned symbols
696
* Called by the async search method when it found calltips
699
on_calltip_search_complete (IAnjutaSymbolQuery *query, IAnjutaIterable* symbols,
700
ParserCxxAssist* assist)
702
assist->priv->tips = parser_cxx_assist_create_calltips (symbols,
704
if (query == assist->priv->calltip_query_file)
705
assist->priv->async_calltip_file = 0;
706
else if (query == assist->priv->calltip_query_project)
707
assist->priv->async_calltip_project = 0;
708
else if (query == assist->priv->calltip_query_system)
709
assist->priv->async_calltip_system = 0;
711
g_assert_not_reached ();
712
gboolean running = assist->priv->async_calltip_system
713
|| assist->priv->async_calltip_file
714
|| assist->priv->async_calltip_project;
716
DEBUG_PRINT ("Calltip search finished with %d items",
717
g_list_length (assist->priv->tips));
719
if (!running && assist->priv->tips)
721
ianjuta_editor_tip_show (IANJUTA_EDITOR_TIP(assist->priv->itip),
722
assist->priv->tips, assist->priv->calltip_iter,
728
* parser_cxx_assist_query_calltip:
730
* @call_context: name of method/function
731
* e: Error propagation
733
* Starts an async query for the calltip
736
parser_cxx_assist_query_calltip (ParserCxxAssist* assist,
737
const gchar *call_context,
738
IAnjutaIterable* calltip_iter)
741
if (IANJUTA_IS_FILE (assist->priv->itip))
743
GFile *file = ianjuta_file_get_file (IANJUTA_FILE (assist->priv->itip),
748
assist->priv->async_calltip_file = 1;
749
ianjuta_symbol_query_search_file (assist->priv->calltip_query_file,
750
call_context, file, NULL);
751
g_object_unref (file);
756
assist->priv->async_calltip_project = 1;
757
ianjuta_symbol_query_search (assist->priv->calltip_query_project,
761
assist->priv->async_calltip_system = 1;
762
ianjuta_symbol_query_search (assist->priv->calltip_query_system,
767
* parser_cxx_assist_create_calltip_context:
769
* @call_context: The context (method/function name)
770
* @position: iter where to show calltips
772
* Create the calltip context
775
parser_cxx_assist_create_calltip_context (ParserCxxAssist* assist,
776
const gchar* call_context,
777
IAnjutaIterable* position)
779
assist->priv->calltip_context = g_strdup (call_context);
780
assist->priv->calltip_iter = position;
784
* parser_cxx_assist_clear_calltip_context:
786
* @e: Error propagation
788
* Clears the calltip context and brings it back into a save state
791
parser_cxx_assist_clear_calltip_context (ParserCxxAssist* assist)
793
ianjuta_symbol_query_cancel (assist->priv->calltip_query_file, NULL);
794
ianjuta_symbol_query_cancel (assist->priv->calltip_query_project, NULL);
795
ianjuta_symbol_query_cancel (assist->priv->calltip_query_system, NULL);
797
assist->priv->async_calltip_file = 0;
798
assist->priv->async_calltip_project = 0;
799
assist->priv->async_calltip_system = 0;
801
g_list_foreach (assist->priv->tips, (GFunc) g_free, NULL);
802
g_list_free (assist->priv->tips);
803
assist->priv->tips = NULL;
805
g_free (assist->priv->calltip_context);
806
assist->priv->calltip_context = NULL;
808
if (assist->priv->calltip_iter)
809
g_object_unref (assist->priv->calltip_iter);
810
assist->priv->calltip_iter = NULL;
814
* parser_cxx_assist_cancelled:
815
* @iassist: IAnjutaEditorAssist that emitted the signal
816
* @assist: ParserCxxAssist object
818
* Stop any autocompletion queries when the cancelled signal was received
821
parser_cxx_assist_cancelled (IAnjutaEditorAssist* iassist,
822
ParserCxxAssist* assist)
824
parser_cxx_assist_cancel_queries (assist);
828
parser_cxx_assist_get_calltip_cache (IAnjutaLanguageProvider* self,
832
ParserCxxAssist* assist = PARSER_CXX_ASSIST (self);
833
if (!g_strcmp0 (call_context, assist->priv->calltip_context))
835
DEBUG_PRINT ("Calltip was found in the cache.");
836
return assist->priv->tips;
840
DEBUG_PRINT ("Calltip is not available in the cache!");
846
parser_cxx_assist_new_calltip (IAnjutaLanguageProvider* self,
848
IAnjutaIterable* cursor,
851
ParserCxxAssist* assist = PARSER_CXX_ASSIST (self);
852
parser_cxx_assist_clear_calltip_context (assist);
853
parser_cxx_assist_create_calltip_context (assist, call_context, cursor);
854
parser_cxx_assist_query_calltip (assist, call_context, cursor);
857
static IAnjutaIterable*
858
parser_cxx_assist_populate_completions (IAnjutaLanguageProvider* self,
859
IAnjutaIterable* cursor,
862
ParserCxxAssist* assist = PARSER_CXX_ASSIST (self);
863
IAnjutaIterable* start_iter = NULL;
865
/* Check if completion was in progress */
866
if (assist->priv->member_completion || assist->priv->autocompletion)
868
g_assert (assist->priv->completion_cache != NULL);
869
gchar* pre_word = anjuta_language_provider_get_pre_word (
870
assist->priv->lang_prov,
871
IANJUTA_EDITOR (assist->priv->iassist),
872
cursor, &start_iter, WORD_CHARACTER);
873
DEBUG_PRINT ("Preword: %s", pre_word);
874
if (pre_word && g_str_has_prefix (pre_word, assist->priv->pre_word))
876
DEBUG_PRINT ("Continue autocomplete for %s", pre_word);
878
/* Great, we just continue the current completion */
879
parser_cxx_assist_update_pre_word (assist, pre_word);
880
parser_cxx_assist_populate_real (assist, TRUE);
887
parser_cxx_assist_clear_completion_cache (assist);
889
/* Check for member completion */
890
start_iter = parser_cxx_assist_create_member_completion_cache (assist,
893
assist->priv->member_completion = TRUE;
896
start_iter = parser_cxx_assist_create_autocompletion_cache (assist,
899
assist->priv->autocompletion = TRUE;
906
* parser_cxx_assist_install:
907
* @assist: ParserCxxAssist object
908
* @ieditor: Editor to install support for
909
* @iparser: Parser to install support for
911
* Returns: Registers provider for editor
914
parser_cxx_assist_install (ParserCxxAssist *assist,
915
IAnjutaEditor *ieditor)
917
g_return_if_fail (assist->priv->iassist == NULL);
919
if (IANJUTA_IS_EDITOR_ASSIST (ieditor))
921
assist->priv->iassist = IANJUTA_EDITOR_ASSIST (ieditor);
922
ianjuta_editor_assist_add (IANJUTA_EDITOR_ASSIST (ieditor),
923
IANJUTA_PROVIDER(assist), NULL);
924
g_signal_connect (ieditor, "cancelled",
925
G_CALLBACK (parser_cxx_assist_cancelled), assist);
928
assist->priv->iassist = NULL;
930
if (IANJUTA_IS_EDITOR_TIP (ieditor))
931
assist->priv->itip = IANJUTA_EDITOR_TIP (ieditor);
933
assist->priv->itip = NULL;
935
if (IANJUTA_IS_FILE (assist->priv->iassist))
937
GFile *file = ianjuta_file_get_file (
938
IANJUTA_FILE (assist->priv->iassist), NULL);
941
assist->priv->editor_filename = g_file_get_path (file);
942
g_object_unref (file);
948
* parser_cxx_assist_uninstall:
949
* @self: ParserCxxAssist object
951
* Returns: Unregisters provider
954
parser_cxx_assist_uninstall (ParserCxxAssist *assist)
956
g_return_if_fail (assist->priv->iassist != NULL);
958
g_signal_handlers_disconnect_by_func (assist->priv->iassist,
959
parser_cxx_assist_cancelled, assist);
960
ianjuta_editor_assist_remove (assist->priv->iassist, IANJUTA_PROVIDER(assist), NULL);
961
assist->priv->iassist = NULL;
965
parser_cxx_assist_init (ParserCxxAssist *assist)
967
assist->priv = g_new0 (ParserCxxAssistPriv, 1);
971
parser_cxx_assist_finalize (GObject *object)
973
ParserCxxAssist *assist = PARSER_CXX_ASSIST (object);
974
ParserCxxAssistPriv* priv = assist->priv;
976
parser_cxx_assist_uninstall (assist);
977
parser_cxx_assist_clear_completion_cache (assist);
978
parser_cxx_assist_clear_calltip_context (assist);
981
if (priv->calltip_query_file)
982
g_object_unref (priv->calltip_query_file);
983
priv->calltip_query_file = NULL;
985
if (priv->calltip_query_system)
986
g_object_unref (priv->calltip_query_system);
987
priv->calltip_query_system = NULL;
989
if (priv->calltip_query_project)
990
g_object_unref (priv->calltip_query_project);
991
priv->calltip_query_project = NULL;
993
if (priv->ac_query_file)
994
g_object_unref (priv->ac_query_file);
995
priv->ac_query_file = NULL;
997
if (priv->ac_query_system)
998
g_object_unref (priv->ac_query_system);
999
priv->ac_query_system = NULL;
1001
if (priv->ac_query_project)
1002
g_object_unref (priv->ac_query_project);
1003
priv->ac_query_project = NULL;
1005
if (priv->query_members)
1006
g_object_unref (priv->query_members);
1007
priv->query_members = NULL;
1009
if (priv->sync_query_file)
1010
g_object_unref (priv->sync_query_file);
1011
priv->sync_query_file = NULL;
1013
if (priv->sync_query_system)
1014
g_object_unref (priv->sync_query_system);
1015
priv->sync_query_system = NULL;
1017
if (priv->sync_query_project)
1018
g_object_unref (priv->sync_query_project);
1019
priv->sync_query_project = NULL;
1021
engine_parser_deinit ();
1023
g_free (assist->priv);
1024
G_OBJECT_CLASS (parser_cxx_assist_parent_class)->finalize (object);
1028
parser_cxx_assist_class_init (ParserCxxAssistClass *klass)
1030
GObjectClass* object_class = G_OBJECT_CLASS (klass);
1032
object_class->finalize = parser_cxx_assist_finalize;
1036
parser_cxx_assist_new (IAnjutaEditor *ieditor,
1037
IAnjutaSymbolManager *isymbol_manager,
1038
GSettings* settings)
1040
ParserCxxAssist *assist;
1041
static IAnjutaSymbolField calltip_fields[] = {
1042
IANJUTA_SYMBOL_FIELD_ID,
1043
IANJUTA_SYMBOL_FIELD_NAME,
1044
IANJUTA_SYMBOL_FIELD_RETURNTYPE,
1045
IANJUTA_SYMBOL_FIELD_SIGNATURE
1047
static IAnjutaSymbolField ac_fields[] = {
1048
IANJUTA_SYMBOL_FIELD_ID,
1049
IANJUTA_SYMBOL_FIELD_NAME,
1050
IANJUTA_SYMBOL_FIELD_KIND,
1051
IANJUTA_SYMBOL_FIELD_TYPE,
1052
IANJUTA_SYMBOL_FIELD_ACCESS,
1053
IANJUTA_SYMBOL_FIELD_SIGNATURE
1056
if (!IANJUTA_IS_EDITOR_ASSIST (ieditor) && !IANJUTA_IS_EDITOR_TIP (ieditor))
1058
/* No assistance is available with the current editor */
1061
assist = g_object_new (TYPE_PARSER_CXX_ASSIST, NULL);
1062
assist->priv->settings = settings;
1064
/* Create call tip queries */
1065
/* Calltip in file */
1066
assist->priv->calltip_query_file =
1067
ianjuta_symbol_manager_create_query (isymbol_manager,
1068
IANJUTA_SYMBOL_QUERY_SEARCH_FILE,
1069
IANJUTA_SYMBOL_QUERY_DB_PROJECT,
1071
ianjuta_symbol_query_set_fields (assist->priv->calltip_query_file,
1072
G_N_ELEMENTS (calltip_fields),
1073
calltip_fields, NULL);
1074
ianjuta_symbol_query_set_filters (assist->priv->calltip_query_file,
1075
IANJUTA_SYMBOL_TYPE_PROTOTYPE |
1076
IANJUTA_SYMBOL_TYPE_FUNCTION |
1077
IANJUTA_SYMBOL_TYPE_METHOD |
1078
IANJUTA_SYMBOL_TYPE_MACRO_WITH_ARG,
1080
ianjuta_symbol_query_set_file_scope (assist->priv->calltip_query_file,
1081
IANJUTA_SYMBOL_QUERY_SEARCH_FS_PRIVATE,
1083
ianjuta_symbol_query_set_mode (assist->priv->calltip_query_file,
1084
IANJUTA_SYMBOL_QUERY_MODE_ASYNC, NULL);
1085
g_signal_connect (assist->priv->calltip_query_file, "async-result",
1086
G_CALLBACK (on_calltip_search_complete), assist);
1087
/* Calltip in project */
1088
assist->priv->calltip_query_project =
1089
ianjuta_symbol_manager_create_query (isymbol_manager,
1090
IANJUTA_SYMBOL_QUERY_SEARCH,
1091
IANJUTA_SYMBOL_QUERY_DB_PROJECT,
1093
ianjuta_symbol_query_set_fields (assist->priv->calltip_query_project,
1094
G_N_ELEMENTS (calltip_fields),
1095
calltip_fields, NULL);
1096
ianjuta_symbol_query_set_filters (assist->priv->calltip_query_project,
1097
IANJUTA_SYMBOL_TYPE_PROTOTYPE |
1098
IANJUTA_SYMBOL_TYPE_METHOD |
1099
IANJUTA_SYMBOL_TYPE_MACRO_WITH_ARG,
1101
ianjuta_symbol_query_set_file_scope (assist->priv->calltip_query_project,
1102
IANJUTA_SYMBOL_QUERY_SEARCH_FS_PUBLIC,
1104
ianjuta_symbol_query_set_mode (assist->priv->calltip_query_project,
1105
IANJUTA_SYMBOL_QUERY_MODE_ASYNC, NULL);
1106
g_signal_connect (assist->priv->calltip_query_project, "async-result",
1107
G_CALLBACK (on_calltip_search_complete), assist);
1108
/* Calltip in system */
1109
assist->priv->calltip_query_system =
1110
ianjuta_symbol_manager_create_query (isymbol_manager,
1111
IANJUTA_SYMBOL_QUERY_SEARCH,
1112
IANJUTA_SYMBOL_QUERY_DB_SYSTEM,
1114
ianjuta_symbol_query_set_fields (assist->priv->calltip_query_system,
1115
G_N_ELEMENTS (calltip_fields),
1116
calltip_fields, NULL);
1117
ianjuta_symbol_query_set_filters (assist->priv->calltip_query_system,
1118
IANJUTA_SYMBOL_TYPE_PROTOTYPE |
1119
IANJUTA_SYMBOL_TYPE_METHOD |
1120
IANJUTA_SYMBOL_TYPE_MACRO_WITH_ARG,
1122
ianjuta_symbol_query_set_file_scope (assist->priv->calltip_query_system,
1123
IANJUTA_SYMBOL_QUERY_SEARCH_FS_PUBLIC,
1125
ianjuta_symbol_query_set_mode (assist->priv->calltip_query_system,
1126
IANJUTA_SYMBOL_QUERY_MODE_ASYNC, NULL);
1127
g_signal_connect (assist->priv->calltip_query_system, "async-result",
1128
G_CALLBACK (on_calltip_search_complete), assist);
1130
/* Create autocomplete queries */
1132
assist->priv->ac_query_file =
1133
ianjuta_symbol_manager_create_query (isymbol_manager,
1134
IANJUTA_SYMBOL_QUERY_SEARCH_FILE,
1135
IANJUTA_SYMBOL_QUERY_DB_PROJECT,
1137
ianjuta_symbol_query_set_group_by (assist->priv->ac_query_file,
1138
IANJUTA_SYMBOL_FIELD_NAME, NULL);
1139
ianjuta_symbol_query_set_fields (assist->priv->ac_query_file,
1140
G_N_ELEMENTS (ac_fields),
1142
ianjuta_symbol_query_set_file_scope (assist->priv->ac_query_file,
1143
IANJUTA_SYMBOL_QUERY_SEARCH_FS_PRIVATE,
1145
ianjuta_symbol_query_set_mode (assist->priv->ac_query_file,
1146
IANJUTA_SYMBOL_QUERY_MODE_ASYNC, NULL);
1147
g_signal_connect (assist->priv->ac_query_file, "async-result",
1148
G_CALLBACK (on_symbol_search_complete), assist);
1150
assist->priv->ac_query_project =
1151
ianjuta_symbol_manager_create_query (isymbol_manager,
1152
IANJUTA_SYMBOL_QUERY_SEARCH,
1153
IANJUTA_SYMBOL_QUERY_DB_PROJECT,
1155
ianjuta_symbol_query_set_group_by (assist->priv->ac_query_project,
1156
IANJUTA_SYMBOL_FIELD_NAME, NULL);
1157
ianjuta_symbol_query_set_fields (assist->priv->ac_query_project,
1158
G_N_ELEMENTS (ac_fields),
1160
ianjuta_symbol_query_set_file_scope (assist->priv->ac_query_project,
1161
IANJUTA_SYMBOL_QUERY_SEARCH_FS_PUBLIC,
1163
ianjuta_symbol_query_set_mode (assist->priv->ac_query_project,
1164
IANJUTA_SYMBOL_QUERY_MODE_ASYNC, NULL);
1165
g_signal_connect (assist->priv->ac_query_project, "async-result",
1166
G_CALLBACK (on_symbol_search_complete), assist);
1168
assist->priv->ac_query_system =
1169
ianjuta_symbol_manager_create_query (isymbol_manager,
1170
IANJUTA_SYMBOL_QUERY_SEARCH,
1171
IANJUTA_SYMBOL_QUERY_DB_SYSTEM,
1173
ianjuta_symbol_query_set_group_by (assist->priv->ac_query_system,
1174
IANJUTA_SYMBOL_FIELD_NAME, NULL);
1175
ianjuta_symbol_query_set_fields (assist->priv->ac_query_system,
1176
G_N_ELEMENTS (ac_fields),
1178
ianjuta_symbol_query_set_file_scope (assist->priv->ac_query_system,
1179
IANJUTA_SYMBOL_QUERY_SEARCH_FS_PUBLIC,
1181
ianjuta_symbol_query_set_mode (assist->priv->ac_query_system,
1182
IANJUTA_SYMBOL_QUERY_MODE_ASYNC, NULL);
1183
g_signal_connect (assist->priv->ac_query_system, "async-result",
1184
G_CALLBACK (on_symbol_search_complete), assist);
1186
/* Members autocompletion */
1187
assist->priv->query_members =
1188
ianjuta_symbol_manager_create_query (isymbol_manager,
1189
IANJUTA_SYMBOL_QUERY_SEARCH_MEMBERS,
1190
IANJUTA_SYMBOL_QUERY_DB_PROJECT,
1192
ianjuta_symbol_query_set_fields (assist->priv->query_members,
1193
G_N_ELEMENTS (ac_fields),
1196
/* Create sync queries */
1197
/* Sync query in file */
1198
assist->priv->sync_query_file =
1199
ianjuta_symbol_manager_create_query (isymbol_manager,
1200
IANJUTA_SYMBOL_QUERY_SEARCH_FILE,
1201
IANJUTA_SYMBOL_QUERY_DB_PROJECT,
1203
ianjuta_symbol_query_set_fields (assist->priv->sync_query_file,
1204
G_N_ELEMENTS (calltip_fields),
1205
calltip_fields, NULL);
1206
ianjuta_symbol_query_set_filters (assist->priv->sync_query_file,
1207
IANJUTA_SYMBOL_TYPE_PROTOTYPE |
1208
IANJUTA_SYMBOL_TYPE_FUNCTION |
1209
IANJUTA_SYMBOL_TYPE_METHOD |
1210
IANJUTA_SYMBOL_TYPE_MACRO_WITH_ARG,
1212
ianjuta_symbol_query_set_file_scope (assist->priv->sync_query_file,
1213
IANJUTA_SYMBOL_QUERY_SEARCH_FS_PRIVATE,
1215
/* Sync query in project */
1216
assist->priv->sync_query_project =
1217
ianjuta_symbol_manager_create_query (isymbol_manager,
1218
IANJUTA_SYMBOL_QUERY_SEARCH,
1219
IANJUTA_SYMBOL_QUERY_DB_PROJECT,
1221
ianjuta_symbol_query_set_fields (assist->priv->sync_query_project,
1222
G_N_ELEMENTS (calltip_fields),
1223
calltip_fields, NULL);
1224
ianjuta_symbol_query_set_filters (assist->priv->sync_query_project,
1225
IANJUTA_SYMBOL_TYPE_PROTOTYPE |
1226
IANJUTA_SYMBOL_TYPE_METHOD |
1227
IANJUTA_SYMBOL_TYPE_MACRO_WITH_ARG,
1229
ianjuta_symbol_query_set_file_scope (assist->priv->sync_query_project,
1230
IANJUTA_SYMBOL_QUERY_SEARCH_FS_PUBLIC,
1232
/* Sync query in system */
1233
assist->priv->sync_query_system =
1234
ianjuta_symbol_manager_create_query (isymbol_manager,
1235
IANJUTA_SYMBOL_QUERY_SEARCH,
1236
IANJUTA_SYMBOL_QUERY_DB_SYSTEM,
1238
ianjuta_symbol_query_set_fields (assist->priv->sync_query_system,
1239
G_N_ELEMENTS (calltip_fields),
1240
calltip_fields, NULL);
1241
ianjuta_symbol_query_set_filters (assist->priv->sync_query_system,
1242
IANJUTA_SYMBOL_TYPE_PROTOTYPE |
1243
IANJUTA_SYMBOL_TYPE_METHOD |
1244
IANJUTA_SYMBOL_TYPE_MACRO_WITH_ARG,
1246
ianjuta_symbol_query_set_file_scope (assist->priv->sync_query_system,
1247
IANJUTA_SYMBOL_QUERY_SEARCH_FS_PUBLIC,
1250
/* Install support */
1251
parser_cxx_assist_install (assist, ieditor);
1252
assist->priv->lang_prov = g_object_new (ANJUTA_TYPE_LANGUAGE_PROVIDER, NULL);
1253
anjuta_language_provider_install (assist->priv->lang_prov, ieditor, settings);
1254
engine_parser_init (isymbol_manager);
1260
parser_cxx_assist_activate (IAnjutaProvider* self,
1261
IAnjutaIterable* iter,
1265
ParserCxxAssist* assist = PARSER_CXX_ASSIST (self);
1266
anjuta_language_provider_activate (assist->priv->lang_prov, self, iter,
1271
parser_cxx_assist_populate (IAnjutaProvider* self,
1272
IAnjutaIterable* cursor,
1275
ParserCxxAssist* assist = PARSER_CXX_ASSIST (self);
1276
anjuta_language_provider_populate (assist->priv->lang_prov, self, cursor);
1280
parser_cxx_assist_get_name (IAnjutaProvider* self,
1286
static IAnjutaIterable*
1287
parser_cxx_assist_get_start_iter (IAnjutaProvider* self,
1290
ParserCxxAssist* assist = PARSER_CXX_ASSIST (self);
1291
return anjuta_language_provider_get_start_iter (assist->priv->lang_prov);
1295
iprovider_iface_init (IAnjutaProviderIface* iface)
1297
iface->activate = parser_cxx_assist_activate;
1298
iface->populate = parser_cxx_assist_populate;
1299
iface->get_name = parser_cxx_assist_get_name;
1300
iface->get_start_iter = parser_cxx_assist_get_start_iter;
1304
ilanguage_provider_iface_init (IAnjutaLanguageProviderIface* iface)
1306
iface->get_calltip_cache = parser_cxx_assist_get_calltip_cache;
1307
iface->get_calltip_context = parser_cxx_assist_get_calltip_context;
1308
iface->new_calltip = parser_cxx_assist_new_calltip;
1309
iface->populate_completions = parser_cxx_assist_populate_completions;