~ubuntu-branches/ubuntu/trusty/anjuta/trusty

« back to all changes in this revision

Viewing changes to plugins/parser-cxx/parser-cxx-assist.c

  • Committer: Package Import Robot
  • Author(s): Jeremy Bicha
  • Date: 2012-08-17 23:48:26 UTC
  • mfrom: (1.1.50)
  • Revision ID: package-import@ubuntu.com-20120817234826-fvk3rfp6nmfaqi9p
Tags: 2:3.5.5-0ubuntu1
* New upstream release.
* debian/control.in:
  - Bump vala dependency to 0.18 series
  - Drop graphviz from build-depends
* debian/watch: Watch for unstable releases

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
 
2
/*
 
3
 * parser-cxx-assist.c
 
4
 * Copyright (C)  2007 Naba Kumar  <naba@gnome.org>
 
5
 *                     Johannes Schmid  <jhs@gnome.org>
 
6
 * 
 
7
 * anjuta is free software.
 
8
 * 
 
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)
 
12
 * any later version.
 
13
 * 
 
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.
 
18
 * 
 
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.
 
24
 */
 
25
 
 
26
#include <ctype.h>
 
27
#include <string.h>
 
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"
 
39
 
 
40
#define BRACE_SEARCH_LIMIT 500
 
41
#define SCOPE_CONTEXT_CHARACTERS "_.:>-0"
 
42
#define WORD_CHARACTER "_0"
 
43
 
 
44
static void iprovider_iface_init(IAnjutaProviderIface* iface);
 
45
static void ilanguage_provider_iface_init(IAnjutaLanguageProviderIface* iface);
 
46
 
 
47
G_DEFINE_TYPE_WITH_CODE (ParserCxxAssist,
 
48
                         parser_cxx_assist,
 
49
                         G_TYPE_OBJECT,
 
50
                         G_IMPLEMENT_INTERFACE (IANJUTA_TYPE_PROVIDER,
 
51
                                                            iprovider_iface_init)
 
52
                         G_IMPLEMENT_INTERFACE (IANJUTA_TYPE_LANGUAGE_PROVIDER,
 
53
                                                            ilanguage_provider_iface_init))
 
54
 
 
55
struct _ParserCxxAssistPriv {
 
56
        GSettings* settings;
 
57
        IAnjutaEditorAssist* iassist;
 
58
        IAnjutaEditorTip* itip;
 
59
        AnjutaLanguageProvider* lang_prov;
 
60
        
 
61
        const gchar* editor_filename;
 
62
 
 
63
        /* Calltips */
 
64
        gchar* calltip_context;
 
65
        IAnjutaIterable* calltip_iter;
 
66
        GList* tips;
 
67
        
 
68
        gint async_calltip_file;
 
69
        gint async_calltip_system;
 
70
        gint async_calltip_project;
 
71
 
 
72
        IAnjutaSymbolQuery *calltip_query_file;
 
73
        IAnjutaSymbolQuery *calltip_query_system;
 
74
        IAnjutaSymbolQuery *calltip_query_project;
 
75
 
 
76
        /* Autocompletion */
 
77
        GCompletion *completion_cache;
 
78
        gchar* pre_word;
 
79
        gboolean member_completion;
 
80
        gboolean autocompletion;
 
81
 
 
82
        gint async_file_id;
 
83
        gint async_system_id;
 
84
        gint async_project_id;
 
85
 
 
86
        IAnjutaSymbolQuery *ac_query_file;
 
87
        IAnjutaSymbolQuery *ac_query_system;
 
88
        IAnjutaSymbolQuery *ac_query_project;   
 
89
 
 
90
        /* Member autocompletion */
 
91
        IAnjutaSymbolQuery *query_members;
 
92
 
 
93
        /* Sync query */
 
94
        IAnjutaSymbolQuery *sync_query_file;
 
95
        IAnjutaSymbolQuery *sync_query_system;
 
96
        IAnjutaSymbolQuery *sync_query_project;
 
97
};
 
98
 
 
99
/**
 
100
 * parser_cxx_assist_proposal_new:
 
101
 * @symbol: IAnjutaSymbol to create the proposal for
 
102
 *
 
103
 * Creates a new IAnjutaEditorAssistProposal for symbol
 
104
 *
 
105
 * Returns: a newly allocated IAnjutaEditorAssistProposal
 
106
 */
 
107
static IAnjutaEditorAssistProposal*
 
108
parser_cxx_assist_proposal_new (IAnjutaSymbol* symbol)
 
109
{
 
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);
 
114
        switch (data->type)
 
115
        {
 
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;
 
122
                        break;
 
123
                default:
 
124
                        proposal->label = g_strdup (data->name);
 
125
                        data->is_func = FALSE;
 
126
        }
 
127
        data->has_para = FALSE;
 
128
        if (data->is_func)
 
129
        {
 
130
                const gchar* signature = ianjuta_symbol_get_string (symbol,
 
131
                                                                    IANJUTA_SYMBOL_FIELD_SIGNATURE,
 
132
                                                                    NULL);
 
133
                if (g_strcmp0 (signature, "(void)") || g_strcmp0 (signature, "()"))
 
134
                        data->has_para = TRUE;
 
135
                        
 
136
        }
 
137
        
 
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);
 
141
        return proposal;
 
142
}
 
143
 
 
144
/**
 
145
 * parser_cxx_assist_proposal_free:
 
146
 * @proposal: the proposal to free
 
147
 * 
 
148
 * Frees the proposal
 
149
 */
 
150
static void
 
151
parser_cxx_assist_proposal_free (IAnjutaEditorAssistProposal* proposal)
 
152
{
 
153
        AnjutaLanguageProposalData* data = proposal->data;
 
154
        anjuta_language_proposal_data_free (data);
 
155
        g_free (proposal->label);
 
156
        g_free (proposal);
 
157
}
 
158
 
 
159
/**
 
160
 * anjuta_propsal_completion_func:
 
161
 * @data: an IAnjutaEditorAssistProposal
 
162
 *
 
163
 * Returns: the name of the completion func
 
164
 */
 
165
static gchar*
 
166
anjuta_proposal_completion_func (gpointer data)
 
167
{
 
168
        IAnjutaEditorAssistProposal* proposal = data;
 
169
        AnjutaLanguageProposalData* prop_data = proposal->data;
 
170
        
 
171
        return prop_data->name;
 
172
}
 
173
 
 
174
/**
 
175
 * parser_cxx_assist_create_completion_from_symbols:
 
176
 * @symbols: Symbol iteration
 
177
 *
 
178
 * Create a list of IAnjutaEditorAssistProposals from a list of symbols
 
179
 *
 
180
 * Returns: a newly allocated GList of newly allocated proposals. Free
 
181
 * with cpp_java_assist_proposal_free()
 
182
 */
 
183
static GList*
 
184
parser_cxx_assist_create_completion_from_symbols (IAnjutaIterable* symbols)
 
185
{
 
186
        GList* list = NULL;
 
187
 
 
188
        if (!symbols)
 
189
                return NULL;
 
190
        do
 
191
        {
 
192
                IAnjutaSymbol* symbol = IANJUTA_SYMBOL (symbols);
 
193
                IAnjutaEditorAssistProposal* proposal = parser_cxx_assist_proposal_new (symbol);        
 
194
 
 
195
                list = g_list_append (list, proposal);
 
196
        }
 
197
        while (ianjuta_iterable_next (symbols, NULL));
 
198
 
 
199
        return list;
 
200
}
 
201
 
 
202
/**
 
203
 * parser_cxx_assist_update_pre_word:
 
204
 * @assist: self
 
205
 * @pre_word: new pre_word
 
206
 *
 
207
 * Updates the current pre_word
 
208
 */
 
209
static void
 
210
parser_cxx_assist_update_pre_word (ParserCxxAssist* assist,
 
211
                                   const gchar* pre_word)
 
212
{
 
213
        g_free (assist->priv->pre_word);
 
214
        if (pre_word == NULL)
 
215
                pre_word = "";
 
216
        assist->priv->pre_word = g_strdup (pre_word);
 
217
}
 
218
 
 
219
/**
 
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
 
224
 *
 
225
 * Checks if a character seperates a C/C++ expression. It can skip brances
 
226
 * because they might not really end the expression
 
227
 *
 
228
 * Returns: TRUE if the characters seperates an expression, FALSE otherwise
 
229
 */
 
230
static gboolean
 
231
parser_cxx_assist_is_expression_separator (gchar c,
 
232
                                           gboolean skip_braces,
 
233
                                           IAnjutaIterable* iter)
 
234
{
 
235
        IAnjutaEditorAttribute attrib = ianjuta_editor_cell_get_attribute (
 
236
                                                IANJUTA_EDITOR_CELL(iter), NULL);
 
237
        int i;
 
238
        const gchar separators[] = {',', ';', '\n', '\r', '\t', '(',
 
239
                                  '{', '}', '=', '<', '\v', '!',
 
240
                                  '&', '%', '*', '[', ']', '?', '/',
 
241
                                  '+', 0};
 
242
        
 
243
        if (attrib == IANJUTA_EDITOR_STRING ||
 
244
            attrib == IANJUTA_EDITOR_COMMENT)
 
245
        {
 
246
                return FALSE;
 
247
        }
 
248
        
 
249
        if (c == ')' && skip_braces)
 
250
        {
 
251
                anjuta_util_jump_to_matching_brace (iter, c, BRACE_SEARCH_LIMIT);
 
252
                return TRUE;
 
253
        }
 
254
        else if (c == ')' && !skip_braces)
 
255
                return FALSE;
 
256
        
 
257
        for (i = 0; separators[i] != 0; i++)
 
258
        {
 
259
                if (separators[i] == c)
 
260
                        return TRUE;
 
261
        }
 
262
 
 
263
        return FALSE;
 
264
}
 
265
 
 
266
/**
 
267
 * parser_cxx_assist_parse_expression:
 
268
 * @assist: self,
 
269
 * @iter: current cursor position
 
270
 * @start_iter: return location for the start of the completion
 
271
 * 
 
272
 * Returns: An iter of a list of IAnjutaSymbols or NULL
 
273
 */
 
274
static IAnjutaIterable*
 
275
parser_cxx_assist_parse_expression (ParserCxxAssist* assist, IAnjutaIterable* iter, IAnjutaIterable** start_iter)
 
276
{
 
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;
 
282
        gchar* stmt = NULL;
 
283
        
 
284
        /* Cursor points after the current characters, move back */
 
285
        ianjuta_iterable_previous (cur_pos, NULL);
 
286
        
 
287
        /* Search for a operator in the current line */
 
288
        do 
 
289
        {
 
290
                gchar ch = ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL(cur_pos),
 
291
                                                         0, NULL);
 
292
                
 
293
                if (parser_cxx_assist_is_expression_separator(ch, FALSE, iter)) {
 
294
                        break;
 
295
                }
 
296
 
 
297
                if (ch == '.' || (op_start && ch == '-') || (ref_start && ch == ':'))
 
298
                {
 
299
                        /* Found an operator, get the statement and the pre_word */
 
300
                        IAnjutaIterable* pre_word_start = ianjuta_iterable_clone (cur_pos,
 
301
                                                                                  NULL);
 
302
                        IAnjutaIterable* pre_word_end = ianjuta_iterable_clone (iter, NULL);
 
303
                        IAnjutaIterable* stmt_end = ianjuta_iterable_clone (pre_word_start,
 
304
                                                                            NULL);
 
305
 
 
306
                        
 
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.
 
310
                         */
 
311
                        ianjuta_iterable_next (stmt_end, NULL);
 
312
                        if (op_start == TRUE || ref_start == TRUE)
 
313
                                ianjuta_iterable_next (stmt_end, NULL);
 
314
                                
 
315
                        
 
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 */
 
320
                        if (op_start)
 
321
                        {
 
322
                                ianjuta_iterable_next (pre_word_start, NULL);
 
323
                        }
 
324
                        
 
325
                        parser_cxx_assist_update_pre_word (assist, ianjuta_editor_get_text (
 
326
                                                                           editor,
 
327
                                                                           pre_word_start,
 
328
                                                                           pre_word_end,
 
329
                                                                           NULL));
 
330
 
 
331
                        /* Try to get the name of the variable */
 
332
                        while (ianjuta_iterable_previous (cur_pos, NULL))
 
333
                        {
 
334
                                gchar word_ch = ianjuta_editor_cell_get_char (
 
335
                                                        IANJUTA_EDITOR_CELL(cur_pos), 0, NULL);
 
336
                                
 
337
                                if (parser_cxx_assist_is_expression_separator(word_ch, FALSE,
 
338
                                                                              cur_pos)) 
 
339
                                        break;                          
 
340
                        }
 
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);
 
347
                        break;
 
348
                }
 
349
                else if (ch == '>')
 
350
                        op_start = TRUE;
 
351
                else if (ch == ':')
 
352
                        ref_start = TRUE;
 
353
                else
 
354
                {
 
355
                        op_start = FALSE;
 
356
                        ref_start = FALSE;
 
357
                }
 
358
        }
 
359
        while (ianjuta_iterable_previous (cur_pos, NULL));
 
360
 
 
361
        if (stmt)
 
362
        {
 
363
                gint lineno;
 
364
                gchar *above_text;
 
365
                IAnjutaIterable* start;
 
366
                
 
367
                if (!assist->priv->editor_filename)
 
368
                {
 
369
                        g_free (stmt);
 
370
                        return NULL;
 
371
                }
 
372
                
 
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);
 
376
                
 
377
                lineno = ianjuta_editor_get_lineno (editor, NULL);
 
378
 
 
379
                /* the parser works even for the "Gtk::" like expressions, so it 
 
380
                 * shouldn't be created a specific case to handle this.
 
381
                 */
 
382
                res = engine_parser_process_expression (stmt,
 
383
                                                        above_text,
 
384
                                                        assist->priv->editor_filename,
 
385
                                                        lineno);
 
386
                g_free (stmt);
 
387
        }
 
388
        g_object_unref (cur_pos);
 
389
        return res;
 
390
}
 
391
 
 
392
/** 
 
393
 * parser_cxx_assist_create_completion_cache:
 
394
 * @assist: self
 
395
 *
 
396
 * Create a new completion_cache object
 
397
 */
 
398
static void
 
399
parser_cxx_assist_create_completion_cache (ParserCxxAssist* assist)
 
400
{
 
401
        g_assert (assist->priv->completion_cache == NULL);
 
402
        assist->priv->completion_cache = 
 
403
                g_completion_new (anjuta_proposal_completion_func);
 
404
}
 
405
 
 
406
/**
 
407
 * parser_cxx_assist_cancel_queries:
 
408
 * @assist: self
 
409
 *
 
410
 * Abort all async operations
 
411
 */
 
412
static void
 
413
parser_cxx_assist_cancel_queries (ParserCxxAssist* assist)
 
414
{
 
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;
 
421
}
 
422
 
 
423
/**
 
424
 * parser_cxx_assist_clear_completion_cache:
 
425
 * @assist: self
 
426
 *
 
427
 * Clear the completion cache, aborting all async operations
 
428
 */
 
429
static void
 
430
parser_cxx_assist_clear_completion_cache (ParserCxxAssist* assist)
 
431
{
 
432
        parser_cxx_assist_cancel_queries (assist);
 
433
        if (assist->priv->completion_cache)
 
434
        {       
 
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);
 
438
        }
 
439
        assist->priv->completion_cache = NULL;
 
440
        assist->priv->member_completion = FALSE;
 
441
        assist->priv->autocompletion = FALSE;
 
442
}
 
443
 
 
444
/**
 
445
 * parser_cxx_assist_populate_real:
 
446
 * @assist: self
 
447
 * @finished: TRUE if no more proposals are expected, FALSE otherwise
 
448
 *
 
449
 * Really invokes the completion interfaces and adds completions.
 
450
 * Might be called from an async context
 
451
 */
 
452
static void
 
453
parser_cxx_assist_populate_real (ParserCxxAssist* assist, gboolean finished)
 
454
{
 
455
        g_assert (assist->priv->pre_word != NULL);
 
456
        GList* proposals = g_completion_complete (assist->priv->completion_cache,
 
457
                                                  assist->priv->pre_word,
 
458
                                                  NULL);
 
459
        ianjuta_editor_assist_proposals (assist->priv->iassist,
 
460
                                         IANJUTA_PROVIDER(assist), proposals,
 
461
                                         assist->priv->pre_word, finished, NULL);
 
462
}
 
463
 
 
464
/**
 
465
 * parser_cxx_assist_create_member_completion_cache
 
466
 * @assist: self
 
467
 * @cursor: Current cursor position
 
468
 * 
 
469
 * Create the completion_cache for member completion if possible
 
470
 *
 
471
 * Returns: the iter where a completion cache was build, NULL otherwise
 
472
 */
 
473
static IAnjutaIterable*
 
474
parser_cxx_assist_create_member_completion_cache (ParserCxxAssist* assist,
 
475
                                                  IAnjutaIterable* cursor)
 
476
{
 
477
        IAnjutaIterable* symbol = NULL;
 
478
        IAnjutaIterable* start_iter = NULL;
 
479
        symbol = parser_cxx_assist_parse_expression (assist, cursor, &start_iter);
 
480
 
 
481
        if (symbol)
 
482
        {
 
483
                /* Query symbol children */
 
484
                IAnjutaIterable *children = 
 
485
                        ianjuta_symbol_query_search_members (assist->priv->query_members,
 
486
                                                            IANJUTA_SYMBOL(symbol),
 
487
                                                            NULL);
 
488
                                                            
 
489
                g_object_unref (symbol);
 
490
                if (children)
 
491
                {
 
492
                        GList* proposals =
 
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);
 
496
 
 
497
                        parser_cxx_assist_populate_real (assist, TRUE);
 
498
                        g_list_free (proposals);
 
499
                        g_object_unref (children);
 
500
                        return start_iter;
 
501
                }
 
502
        }
 
503
        else if (start_iter)
 
504
                g_object_unref (start_iter);
 
505
        return NULL;
 
506
}
 
507
 
 
508
/**
 
509
 * on_symbol_search_complete:
 
510
 * @search_id: id of this search
 
511
 * @symbols: the returned symbols
 
512
 * @assist: self
 
513
 *
 
514
 * Called by the async search method when it found symbols
 
515
 */
 
516
static void
 
517
on_symbol_search_complete (IAnjutaSymbolQuery *query, IAnjutaIterable* symbols,
 
518
                                                   ParserCxxAssist* assist)
 
519
{
 
520
        GList* proposals;
 
521
        proposals = parser_cxx_assist_create_completion_from_symbols (symbols);
 
522
 
 
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;
 
529
        else
 
530
                g_assert_not_reached ();
 
531
        
 
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;
 
536
        if (!running)
 
537
                parser_cxx_assist_populate_real (assist, TRUE);
 
538
        g_list_free (proposals);
 
539
}
 
540
 
 
541
/**
 
542
 * parser_cxx_assist_create_autocompletion_cache:
 
543
 * @assist: self
 
544
 * @cursor: Current cursor position
 
545
 * 
 
546
 * Create completion cache for autocompletion. This is done async.
 
547
 *
 
548
 * Returns: the iter where a preword was detected, NULL otherwise
 
549
 */ 
 
550
static IAnjutaIterable*
 
551
parser_cxx_assist_create_autocompletion_cache (ParserCxxAssist* assist,
 
552
                                               IAnjutaIterable* cursor)
 
553
{
 
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)
 
560
        {
 
561
                if (start_iter)
 
562
                        g_object_unref (start_iter);
 
563
                return NULL;
 
564
        }
 
565
        else
 
566
        {
 
567
                gchar *pattern = g_strconcat (pre_word, "%", NULL);
 
568
                
 
569
                parser_cxx_assist_create_completion_cache (assist);
 
570
                parser_cxx_assist_update_pre_word (assist, pre_word);
 
571
 
 
572
                if (IANJUTA_IS_FILE (assist->priv->iassist))
 
573
                {
 
574
                        GFile *file = ianjuta_file_get_file (
 
575
                                              IANJUTA_FILE (assist->priv->iassist), NULL);
 
576
                        if (file != NULL)
 
577
                        {
 
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);
 
582
                        }
 
583
                }
 
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,
 
587
                                             NULL);
 
588
                assist->priv->async_system_id = 1;
 
589
                ianjuta_symbol_query_search (assist->priv->ac_query_system, pattern,
 
590
                                             NULL);
 
591
                g_free (pre_word);
 
592
                g_free (pattern);
 
593
                
 
594
                return start_iter;
 
595
        }
 
596
}
 
597
 
 
598
/**
 
599
 * parser_cxx_assist_get_calltip_context:
 
600
 * @self: Self
 
601
 * @iter: current cursor position
 
602
 * @e: Error propagation
 
603
 *
 
604
 * Searches for a calltip context
 
605
 *
 
606
 * Returns: name of the method to show a calltip for or NULL
 
607
 */
 
608
static gchar*
 
609
parser_cxx_assist_get_calltip_context (IAnjutaLanguageProvider *self,
 
610
                                       IAnjutaIterable *iter,
 
611
                                       GError** e)
 
612
{
 
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;
 
619
}
 
620
 
 
621
/**
 
622
 * parser_cxx_assist_create_calltips:
 
623
 * @iter: List of symbols
 
624
 * @merge: list of calltips to merge or NULL
 
625
 *
 
626
 * Create a list of Calltips (string) from a list of symbols
 
627
 *
 
628
 * A newly allocated GList* with newly allocated strings
 
629
 */
 
630
static GList*
 
631
parser_cxx_assist_create_calltips (IAnjutaIterable* iter, GList* merge)
 
632
{
 
633
        GList* tips = merge;
 
634
        if (iter)
 
635
        {
 
636
                do
 
637
                {
 
638
                        IAnjutaSymbol* symbol = IANJUTA_SYMBOL (iter);
 
639
                        const gchar* name = ianjuta_symbol_get_string (
 
640
                                                    symbol,IANJUTA_SYMBOL_FIELD_NAME, NULL);
 
641
                        if (name != NULL)
 
642
                        {
 
643
                                const gchar* args = ianjuta_symbol_get_string (
 
644
                                                                symbol,
 
645
                                                                IANJUTA_SYMBOL_FIELD_SIGNATURE,
 
646
                                                                NULL);
 
647
                                const gchar* rettype = ianjuta_symbol_get_string (
 
648
                                                               symbol,
 
649
                                                               IANJUTA_SYMBOL_FIELD_RETURNTYPE,
 
650
                                                               NULL);
 
651
                                gchar* print_args;
 
652
                                gchar* separator;
 
653
                                gchar* white_name;
 
654
                                gint white_count = 0;
 
655
 
 
656
                                if (!rettype)
 
657
                                        rettype = "";
 
658
                                else
 
659
                                        white_count += strlen(rettype) + 1;
 
660
                                
 
661
                                white_count += strlen(name) + 1;
 
662
                                
 
663
                                white_name = g_strnfill (white_count, ' ');
 
664
                                separator = g_strjoin (NULL, ", \n", white_name, NULL);
 
665
                                gchar** argv;
 
666
                                if (!args)
 
667
                                        args = "()";
 
668
                                
 
669
                                argv = g_strsplit (args, ",", -1);
 
670
                                print_args = g_strjoinv (separator, argv);
 
671
                                gchar* tip = g_strdup_printf ("%s %s %s", rettype, name,
 
672
                                                              print_args);
 
673
                                
 
674
                                if (!g_list_find_custom (tips, tip, (GCompareFunc) strcmp))
 
675
                                        tips = g_list_append (tips, tip);
 
676
                                
 
677
                                g_strfreev (argv);
 
678
                                g_free (print_args);
 
679
                                g_free (separator);
 
680
                                g_free (white_name);
 
681
                        }
 
682
                        else
 
683
                                break;
 
684
                }
 
685
                while (ianjuta_iterable_next (iter, NULL));
 
686
        }
 
687
        return tips;
 
688
}
 
689
 
 
690
/**
 
691
 * on_calltip_search_complete:
 
692
 * @search_id: id of this search
 
693
 * @symbols: the returned symbols
 
694
 * @assist: self
 
695
 *
 
696
 * Called by the async search method when it found calltips
 
697
 */
 
698
static void
 
699
on_calltip_search_complete (IAnjutaSymbolQuery *query, IAnjutaIterable* symbols,
 
700
                                                        ParserCxxAssist* assist)
 
701
{
 
702
        assist->priv->tips = parser_cxx_assist_create_calltips (symbols,
 
703
                                                                assist->priv->tips);
 
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;
 
710
        else
 
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;
 
715
 
 
716
        DEBUG_PRINT ("Calltip search finished with %d items",
 
717
                     g_list_length (assist->priv->tips));
 
718
        
 
719
        if (!running && assist->priv->tips)
 
720
        {
 
721
                ianjuta_editor_tip_show (IANJUTA_EDITOR_TIP(assist->priv->itip),
 
722
                                         assist->priv->tips, assist->priv->calltip_iter,
 
723
                                         NULL);
 
724
        }
 
725
}
 
726
 
 
727
/**
 
728
 * parser_cxx_assist_query_calltip:
 
729
 * @self: Self
 
730
 * @call_context: name of method/function
 
731
 * e: Error propagation
 
732
 *
 
733
 * Starts an async query for the calltip
 
734
 */
 
735
static void
 
736
parser_cxx_assist_query_calltip (ParserCxxAssist* assist,
 
737
                                 const gchar *call_context,
 
738
                                 IAnjutaIterable* calltip_iter)
 
739
{
 
740
        /* Search file */
 
741
        if (IANJUTA_IS_FILE (assist->priv->itip))
 
742
        {
 
743
                GFile *file = ianjuta_file_get_file (IANJUTA_FILE (assist->priv->itip),
 
744
                                                     NULL);
 
745
 
 
746
                if (file != NULL)
 
747
                {
 
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);
 
752
                }
 
753
        }
 
754
 
 
755
        /* Search Project */
 
756
        assist->priv->async_calltip_project = 1;
 
757
        ianjuta_symbol_query_search (assist->priv->calltip_query_project,
 
758
                                     call_context, NULL);
 
759
        
 
760
        /* Search system */
 
761
        assist->priv->async_calltip_system = 1;
 
762
        ianjuta_symbol_query_search (assist->priv->calltip_query_system,
 
763
                                         call_context, NULL);
 
764
}
 
765
 
 
766
/**
 
767
 * parser_cxx_assist_create_calltip_context:
 
768
 * @assist: self
 
769
 * @call_context: The context (method/function name)
 
770
 * @position: iter where to show calltips
 
771
 *
 
772
 * Create the calltip context
 
773
 */
 
774
static void
 
775
parser_cxx_assist_create_calltip_context (ParserCxxAssist* assist,
 
776
                                          const gchar* call_context,
 
777
                                          IAnjutaIterable* position)
 
778
{
 
779
        assist->priv->calltip_context = g_strdup (call_context);
 
780
        assist->priv->calltip_iter = position;
 
781
}
 
782
 
 
783
/**
 
784
 * parser_cxx_assist_clear_calltip_context:
 
785
 * @self: Self
 
786
 * @e: Error propagation
 
787
 *
 
788
 * Clears the calltip context and brings it back into a save state
 
789
 */
 
790
static void
 
791
parser_cxx_assist_clear_calltip_context (ParserCxxAssist* assist)
 
792
{
 
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);
 
796
 
 
797
        assist->priv->async_calltip_file = 0;
 
798
        assist->priv->async_calltip_project = 0;
 
799
        assist->priv->async_calltip_system = 0;
 
800
        
 
801
        g_list_foreach (assist->priv->tips, (GFunc) g_free, NULL);
 
802
        g_list_free (assist->priv->tips);
 
803
        assist->priv->tips = NULL;
 
804
        
 
805
        g_free (assist->priv->calltip_context);
 
806
        assist->priv->calltip_context = NULL;
 
807
        
 
808
        if (assist->priv->calltip_iter)
 
809
                g_object_unref (assist->priv->calltip_iter);
 
810
        assist->priv->calltip_iter = NULL;
 
811
}
 
812
 
 
813
/**
 
814
 * parser_cxx_assist_cancelled:
 
815
 * @iassist: IAnjutaEditorAssist that emitted the signal
 
816
 * @assist: ParserCxxAssist object
 
817
 *
 
818
 * Stop any autocompletion queries when the cancelled signal was received
 
819
 */
 
820
static void
 
821
parser_cxx_assist_cancelled (IAnjutaEditorAssist* iassist,
 
822
                             ParserCxxAssist* assist)
 
823
{
 
824
        parser_cxx_assist_cancel_queries (assist);
 
825
}
 
826
 
 
827
static GList*
 
828
parser_cxx_assist_get_calltip_cache (IAnjutaLanguageProvider* self,
 
829
                                     gchar* call_context,
 
830
                                     GError** e)
 
831
{
 
832
        ParserCxxAssist* assist = PARSER_CXX_ASSIST (self);
 
833
        if (!g_strcmp0 (call_context, assist->priv->calltip_context))
 
834
        {
 
835
                DEBUG_PRINT ("Calltip was found in the cache.");
 
836
                return assist->priv->tips;
 
837
        }
 
838
        else
 
839
        {
 
840
                DEBUG_PRINT ("Calltip is not available in the cache!");
 
841
                return NULL;
 
842
        }
 
843
}
 
844
 
 
845
static void
 
846
parser_cxx_assist_new_calltip (IAnjutaLanguageProvider* self,
 
847
                               gchar* call_context,
 
848
                               IAnjutaIterable* cursor,
 
849
                               GError** e)
 
850
{
 
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);
 
855
}
 
856
 
 
857
static IAnjutaIterable*
 
858
parser_cxx_assist_populate_completions (IAnjutaLanguageProvider* self,
 
859
                                        IAnjutaIterable* cursor,
 
860
                                        GError** e)
 
861
{
 
862
        ParserCxxAssist* assist = PARSER_CXX_ASSIST (self);
 
863
        IAnjutaIterable* start_iter = NULL;
 
864
        
 
865
        /* Check if completion was in progress */
 
866
        if (assist->priv->member_completion || assist->priv->autocompletion)
 
867
        {
 
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))
 
875
                {
 
876
                        DEBUG_PRINT ("Continue autocomplete for %s", pre_word);
 
877
                        
 
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);
 
881
                        g_free (pre_word);
 
882
                        return start_iter;
 
883
                }                       
 
884
                g_free (pre_word);
 
885
        }
 
886
        
 
887
        parser_cxx_assist_clear_completion_cache (assist);
 
888
        
 
889
        /* Check for member completion */
 
890
        start_iter = parser_cxx_assist_create_member_completion_cache (assist,
 
891
                                                                       cursor);
 
892
        if (start_iter)
 
893
                assist->priv->member_completion = TRUE;
 
894
        else
 
895
        {
 
896
                start_iter = parser_cxx_assist_create_autocompletion_cache (assist,
 
897
                                                                            cursor);
 
898
                if (start_iter)
 
899
                        assist->priv->autocompletion = TRUE;
 
900
        }
 
901
        
 
902
        return start_iter;
 
903
}
 
904
 
 
905
/**
 
906
 * parser_cxx_assist_install:
 
907
 * @assist: ParserCxxAssist object
 
908
 * @ieditor: Editor to install support for
 
909
 * @iparser: Parser to install support for
 
910
 *
 
911
 * Returns: Registers provider for editor
 
912
 */
 
913
static void
 
914
parser_cxx_assist_install (ParserCxxAssist *assist,
 
915
                           IAnjutaEditor *ieditor)
 
916
{
 
917
        g_return_if_fail (assist->priv->iassist == NULL);
 
918
 
 
919
        if (IANJUTA_IS_EDITOR_ASSIST (ieditor))
 
920
        {
 
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);
 
926
        }
 
927
        else
 
928
                assist->priv->iassist = NULL;
 
929
 
 
930
        if (IANJUTA_IS_EDITOR_TIP (ieditor))
 
931
                assist->priv->itip = IANJUTA_EDITOR_TIP (ieditor);
 
932
        else
 
933
                assist->priv->itip = NULL;
 
934
                
 
935
        if (IANJUTA_IS_FILE (assist->priv->iassist))
 
936
        {
 
937
                GFile *file = ianjuta_file_get_file (
 
938
                                          IANJUTA_FILE (assist->priv->iassist), NULL);
 
939
                if (file != NULL)
 
940
                {
 
941
                        assist->priv->editor_filename = g_file_get_path (file);
 
942
                        g_object_unref (file);
 
943
                }
 
944
        }
 
945
}
 
946
 
 
947
/**
 
948
 * parser_cxx_assist_uninstall:
 
949
 * @self: ParserCxxAssist object
 
950
 *
 
951
 * Returns: Unregisters provider
 
952
 */
 
953
static void
 
954
parser_cxx_assist_uninstall (ParserCxxAssist *assist)
 
955
{
 
956
        g_return_if_fail (assist->priv->iassist != NULL);
 
957
        
 
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;
 
962
}
 
963
 
 
964
static void
 
965
parser_cxx_assist_init (ParserCxxAssist *assist)
 
966
{
 
967
        assist->priv = g_new0 (ParserCxxAssistPriv, 1);
 
968
}
 
969
 
 
970
static void
 
971
parser_cxx_assist_finalize (GObject *object)
 
972
{
 
973
        ParserCxxAssist *assist = PARSER_CXX_ASSIST (object);
 
974
        ParserCxxAssistPriv* priv = assist->priv;
 
975
        
 
976
        parser_cxx_assist_uninstall (assist);
 
977
        parser_cxx_assist_clear_completion_cache (assist);
 
978
        parser_cxx_assist_clear_calltip_context (assist);
 
979
 
 
980
 
 
981
        if (priv->calltip_query_file)
 
982
                g_object_unref (priv->calltip_query_file);
 
983
        priv->calltip_query_file = NULL;
 
984
                                
 
985
        if (priv->calltip_query_system)
 
986
                g_object_unref (priv->calltip_query_system);
 
987
        priv->calltip_query_system = NULL;
 
988
        
 
989
        if (priv->calltip_query_project)
 
990
                g_object_unref (priv->calltip_query_project);
 
991
        priv->calltip_query_project = NULL;
 
992
        
 
993
        if (priv->ac_query_file)
 
994
                g_object_unref (priv->ac_query_file);
 
995
        priv->ac_query_file = NULL;
 
996
        
 
997
        if (priv->ac_query_system)
 
998
                g_object_unref (priv->ac_query_system);
 
999
        priv->ac_query_system = NULL;
 
1000
                                
 
1001
        if (priv->ac_query_project)
 
1002
                g_object_unref (priv->ac_query_project);
 
1003
        priv->ac_query_project = NULL;
 
1004
                                
 
1005
        if (priv->query_members)
 
1006
                g_object_unref (priv->query_members);
 
1007
        priv->query_members = NULL; 
 
1008
 
 
1009
        if (priv->sync_query_file)
 
1010
                g_object_unref (priv->sync_query_file);
 
1011
        priv->sync_query_file = NULL;
 
1012
 
 
1013
        if (priv->sync_query_system)
 
1014
                g_object_unref (priv->sync_query_system);
 
1015
        priv->sync_query_system = NULL;
 
1016
 
 
1017
        if (priv->sync_query_project)
 
1018
                g_object_unref (priv->sync_query_project);
 
1019
        priv->sync_query_project = NULL;
 
1020
 
 
1021
        engine_parser_deinit ();
 
1022
        
 
1023
        g_free (assist->priv);
 
1024
        G_OBJECT_CLASS (parser_cxx_assist_parent_class)->finalize (object);
 
1025
}
 
1026
 
 
1027
static void
 
1028
parser_cxx_assist_class_init (ParserCxxAssistClass *klass)
 
1029
{
 
1030
        GObjectClass* object_class = G_OBJECT_CLASS (klass);
 
1031
 
 
1032
        object_class->finalize = parser_cxx_assist_finalize;
 
1033
}
 
1034
 
 
1035
ParserCxxAssist *
 
1036
parser_cxx_assist_new (IAnjutaEditor *ieditor,
 
1037
                       IAnjutaSymbolManager *isymbol_manager,
 
1038
                       GSettings* settings)
 
1039
{
 
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
 
1046
        };
 
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
 
1054
        };
 
1055
 
 
1056
        if (!IANJUTA_IS_EDITOR_ASSIST (ieditor) && !IANJUTA_IS_EDITOR_TIP (ieditor))
 
1057
        {
 
1058
                /* No assistance is available with the current editor */
 
1059
                return NULL;
 
1060
        }
 
1061
        assist = g_object_new (TYPE_PARSER_CXX_ASSIST, NULL);
 
1062
        assist->priv->settings = settings;
 
1063
        
 
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,
 
1070
                                                     NULL);
 
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,
 
1079
                                          TRUE, NULL);
 
1080
        ianjuta_symbol_query_set_file_scope (assist->priv->calltip_query_file,
 
1081
                                             IANJUTA_SYMBOL_QUERY_SEARCH_FS_PRIVATE,
 
1082
                                             NULL);
 
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,
 
1092
                                                     NULL);
 
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,
 
1100
                                          TRUE, NULL);
 
1101
        ianjuta_symbol_query_set_file_scope (assist->priv->calltip_query_project,
 
1102
                                             IANJUTA_SYMBOL_QUERY_SEARCH_FS_PUBLIC,
 
1103
                                             NULL);
 
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,
 
1113
                                                     NULL);
 
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,
 
1121
                                          TRUE, NULL);
 
1122
        ianjuta_symbol_query_set_file_scope (assist->priv->calltip_query_system,
 
1123
                                             IANJUTA_SYMBOL_QUERY_SEARCH_FS_PUBLIC,
 
1124
                                             NULL);
 
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);
 
1129
 
 
1130
        /* Create autocomplete queries */
 
1131
        /* AC in file */
 
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,
 
1136
                                                     NULL);
 
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),
 
1141
                                         ac_fields, NULL);
 
1142
        ianjuta_symbol_query_set_file_scope (assist->priv->ac_query_file,
 
1143
                                             IANJUTA_SYMBOL_QUERY_SEARCH_FS_PRIVATE,
 
1144
                                             NULL);
 
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);
 
1149
        /* AC in project */
 
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,
 
1154
                                                     NULL);
 
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),
 
1159
                                         ac_fields, NULL);
 
1160
        ianjuta_symbol_query_set_file_scope (assist->priv->ac_query_project,
 
1161
                                             IANJUTA_SYMBOL_QUERY_SEARCH_FS_PUBLIC,
 
1162
                                             NULL);
 
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);
 
1167
        /* AC in system */
 
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,
 
1172
                                                     NULL);
 
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),
 
1177
                                         ac_fields, NULL);
 
1178
        ianjuta_symbol_query_set_file_scope (assist->priv->ac_query_system,
 
1179
                                             IANJUTA_SYMBOL_QUERY_SEARCH_FS_PUBLIC,
 
1180
                                             NULL);
 
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);
 
1185
 
 
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,
 
1191
                                                     NULL);
 
1192
        ianjuta_symbol_query_set_fields (assist->priv->query_members,
 
1193
                                         G_N_ELEMENTS (ac_fields),
 
1194
                                         ac_fields, NULL);
 
1195
 
 
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,
 
1202
                                                     NULL);
 
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,
 
1211
                                          TRUE, NULL);
 
1212
        ianjuta_symbol_query_set_file_scope (assist->priv->sync_query_file,
 
1213
                                             IANJUTA_SYMBOL_QUERY_SEARCH_FS_PRIVATE,
 
1214
                                             NULL);
 
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,
 
1220
                                                     NULL);
 
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,
 
1228
                                          TRUE, NULL);
 
1229
        ianjuta_symbol_query_set_file_scope (assist->priv->sync_query_project,
 
1230
                                             IANJUTA_SYMBOL_QUERY_SEARCH_FS_PUBLIC,
 
1231
                                             NULL);
 
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,
 
1237
                                                     NULL);
 
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,
 
1245
                                          TRUE, NULL);
 
1246
        ianjuta_symbol_query_set_file_scope (assist->priv->sync_query_system,
 
1247
                                             IANJUTA_SYMBOL_QUERY_SEARCH_FS_PUBLIC,
 
1248
                                             NULL);
 
1249
 
 
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);
 
1255
        
 
1256
        return assist;
 
1257
}
 
1258
 
 
1259
static void
 
1260
parser_cxx_assist_activate (IAnjutaProvider* self,
 
1261
                            IAnjutaIterable* iter,
 
1262
                            gpointer data,
 
1263
                            GError** e)
 
1264
{
 
1265
        ParserCxxAssist* assist = PARSER_CXX_ASSIST (self);
 
1266
        anjuta_language_provider_activate (assist->priv->lang_prov, self, iter,
 
1267
                                           data);
 
1268
}
 
1269
 
 
1270
static void
 
1271
parser_cxx_assist_populate (IAnjutaProvider* self,
 
1272
                            IAnjutaIterable* cursor,
 
1273
                            GError** e)
 
1274
{
 
1275
        ParserCxxAssist* assist = PARSER_CXX_ASSIST (self);
 
1276
        anjuta_language_provider_populate (assist->priv->lang_prov, self, cursor);
 
1277
}
 
1278
 
 
1279
static const gchar*
 
1280
parser_cxx_assist_get_name (IAnjutaProvider* self,
 
1281
                            GError** e)
 
1282
{
 
1283
        return _("C/C++");
 
1284
}
 
1285
 
 
1286
static IAnjutaIterable*
 
1287
parser_cxx_assist_get_start_iter (IAnjutaProvider* self,
 
1288
                                  GError** e)
 
1289
{
 
1290
        ParserCxxAssist* assist = PARSER_CXX_ASSIST (self);
 
1291
        return anjuta_language_provider_get_start_iter (assist->priv->lang_prov);
 
1292
}
 
1293
 
 
1294
static void
 
1295
iprovider_iface_init (IAnjutaProviderIface* iface)
 
1296
{
 
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;
 
1301
}
 
1302
 
 
1303
static void
 
1304
ilanguage_provider_iface_init (IAnjutaLanguageProviderIface* iface)
 
1305
{
 
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;
 
1310
}