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-completion.h>
29 #include <libanjuta/anjuta-debug.h>
30 #include <libanjuta/anjuta-language-provider.h>
31 #include <libanjuta/anjuta-utils.h>
32 #include <libanjuta/interfaces/ianjuta-file.h>
33 #include <libanjuta/interfaces/ianjuta-editor-cell.h>
34 #include <libanjuta/interfaces/ianjuta-editor-assist.h>
35 #include <libanjuta/interfaces/ianjuta-editor-tip.h>
36 #include <libanjuta/interfaces/ianjuta-language-provider.h>
37 #include <libanjuta/interfaces/ianjuta-symbol-manager.h>
38 #include "parser-cxx-assist.h"
39 #include "cxxparser/engine-parser.h"
41 #define BRACE_SEARCH_LIMIT 500
42 #define SCOPE_CONTEXT_CHARACTERS "_.:>-0"
43 #define WORD_CHARACTER "_0"
45 static void iprovider_iface_init(IAnjutaProviderIface
* iface
);
46 static void ilanguage_provider_iface_init(IAnjutaLanguageProviderIface
* iface
);
48 G_DEFINE_TYPE_WITH_CODE (ParserCxxAssist
,
51 G_IMPLEMENT_INTERFACE (IANJUTA_TYPE_PROVIDER
,
53 G_IMPLEMENT_INTERFACE (IANJUTA_TYPE_LANGUAGE_PROVIDER
,
54 ilanguage_provider_iface_init
))
56 struct _ParserCxxAssistPriv
{
58 IAnjutaEditorAssist
* iassist
;
59 IAnjutaEditorTip
* itip
;
60 AnjutaLanguageProvider
* lang_prov
;
62 const gchar
* editor_filename
;
65 gchar
* calltip_context
;
66 IAnjutaIterable
* calltip_iter
;
69 gint async_calltip_file
;
70 gint async_calltip_system
;
71 gint async_calltip_project
;
73 IAnjutaSymbolQuery
*calltip_query_file
;
74 IAnjutaSymbolQuery
*calltip_query_system
;
75 IAnjutaSymbolQuery
*calltip_query_project
;
78 AnjutaCompletion
* completion_cache
;
80 gboolean member_completion
;
81 gboolean autocompletion
;
85 gint async_project_id
;
87 IAnjutaSymbolQuery
*ac_query_file
;
88 IAnjutaSymbolQuery
*ac_query_system
;
89 IAnjutaSymbolQuery
*ac_query_project
;
91 /* Member autocompletion */
92 IAnjutaSymbolQuery
*query_members
;
95 IAnjutaSymbolQuery
*sync_query_file
;
96 IAnjutaSymbolQuery
*sync_query_system
;
97 IAnjutaSymbolQuery
*sync_query_project
;
101 * parser_cxx_assist_proposal_new:
102 * @symbol: IAnjutaSymbol to create the proposal for
104 * Creates a new IAnjutaEditorAssistProposal for symbol
106 * Returns: a newly allocated IAnjutaEditorAssistProposal
108 static IAnjutaEditorAssistProposal
*
109 parser_cxx_assist_proposal_new (IAnjutaSymbol
* symbol
)
111 IAnjutaEditorAssistProposal
* proposal
= g_new0 (IAnjutaEditorAssistProposal
, 1);
112 AnjutaLanguageProposalData
* data
=
113 anjuta_language_proposal_data_new (g_strdup (ianjuta_symbol_get_string (symbol
, IANJUTA_SYMBOL_FIELD_NAME
, NULL
)));
114 data
->type
= ianjuta_symbol_get_sym_type (symbol
, NULL
);
117 case IANJUTA_SYMBOL_TYPE_PROTOTYPE
:
118 case IANJUTA_SYMBOL_TYPE_FUNCTION
:
119 case IANJUTA_SYMBOL_TYPE_METHOD
:
120 case IANJUTA_SYMBOL_TYPE_MACRO_WITH_ARG
:
121 proposal
->label
= g_strdup_printf ("%s()", data
->name
);
122 data
->is_func
= TRUE
;
125 proposal
->label
= g_strdup (data
->name
);
126 data
->is_func
= FALSE
;
128 data
->has_para
= FALSE
;
131 const gchar
* signature
= ianjuta_symbol_get_string (symbol
,
132 IANJUTA_SYMBOL_FIELD_SIGNATURE
,
134 if (g_strcmp0 (signature
, "(void)") || g_strcmp0 (signature
, "()"))
135 data
->has_para
= TRUE
;
139 proposal
->data
= data
;
140 /* Icons are lifetime object of the symbol-db so we can cast here */
141 proposal
->icon
= (GdkPixbuf
*) ianjuta_symbol_get_icon (symbol
, NULL
);
146 * parser_cxx_assist_proposal_free:
147 * @proposal: the proposal to free
152 parser_cxx_assist_proposal_free (IAnjutaEditorAssistProposal
* proposal
)
154 AnjutaLanguageProposalData
* data
= proposal
->data
;
155 anjuta_language_proposal_data_free (data
);
156 g_free (proposal
->label
);
161 * anjuta_propsal_completion_func:
162 * @item: an IAnjutaEditorAssistProposal
164 * Returns: the name of the completion func
167 anjuta_proposal_completion_func (const void* item
)
169 const IAnjutaEditorAssistProposal
* proposal
= item
;
170 AnjutaLanguageProposalData
* prop_data
= proposal
->data
;
172 return prop_data
->name
;
176 * parser_cxx_assist_add_completions_from_symbols:
178 * @symbols: Symbol iteration
180 * Add completions to the completions cache from @symbols.
184 parser_cxx_assist_add_completions_from_symbols (ParserCxxAssist
* assist
,
185 IAnjutaIterable
* symbols
)
191 IAnjutaSymbol
* symbol
= IANJUTA_SYMBOL (symbols
);
192 IAnjutaEditorAssistProposal
* proposal
= parser_cxx_assist_proposal_new (symbol
);
194 anjuta_completion_add_item (assist
->priv
->completion_cache
, proposal
);
196 while (ianjuta_iterable_next (symbols
, NULL
));
200 * parser_cxx_assist_update_pre_word:
202 * @pre_word: new pre_word
204 * Updates the current pre_word
207 parser_cxx_assist_update_pre_word (ParserCxxAssist
* assist
,
208 const gchar
* pre_word
)
210 g_free (assist
->priv
->pre_word
);
211 if (pre_word
== NULL
)
213 assist
->priv
->pre_word
= g_strdup (pre_word
);
217 * parser_cxx_assist_is_expression_separator:
218 * @c: character to check
219 * @skip_braces: whether to skip closing braces
220 * @iter: current cursor position
222 * Checks if a character seperates a C/C++ expression. It can skip brances
223 * because they might not really end the expression
225 * Returns: TRUE if the characters seperates an expression, FALSE otherwise
228 parser_cxx_assist_is_expression_separator (gchar c
,
229 gboolean skip_braces
,
230 IAnjutaIterable
* iter
)
232 IAnjutaEditorAttribute attrib
= ianjuta_editor_cell_get_attribute (
233 IANJUTA_EDITOR_CELL(iter
), NULL
);
235 const gchar separators
[] = {',', ';', '\n', '\r', '\t', '(',
236 '{', '}', '=', '<', '\v', '!',
237 '&', '%', '*', '[', ']', '?', '/',
240 if (attrib
== IANJUTA_EDITOR_STRING
||
241 attrib
== IANJUTA_EDITOR_COMMENT
)
246 if (c
== ')' && skip_braces
)
248 anjuta_util_jump_to_matching_brace (iter
, c
, BRACE_SEARCH_LIMIT
);
251 else if (c
== ')' && !skip_braces
)
254 for (i
= 0; separators
[i
] != 0; i
++)
256 if (separators
[i
] == c
)
264 * parser_cxx_assist_parse_expression:
266 * @iter: current cursor position
267 * @start_iter: return location for the start of the completion
269 * Returns: An iter of a list of IAnjutaSymbols or NULL
271 static IAnjutaIterable
*
272 parser_cxx_assist_parse_expression (ParserCxxAssist
* assist
, IAnjutaIterable
* iter
, IAnjutaIterable
** start_iter
)
274 IAnjutaEditor
* editor
= IANJUTA_EDITOR (assist
->priv
->iassist
);
275 IAnjutaIterable
* res
= NULL
;
276 IAnjutaIterable
* cur_pos
= ianjuta_iterable_clone (iter
, NULL
);
277 gboolean op_start
= FALSE
;
278 gboolean ref_start
= FALSE
;
281 /* Cursor points after the current characters, move back */
282 ianjuta_iterable_previous (cur_pos
, NULL
);
284 /* Search for a operator in the current line */
287 gchar ch
= ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL(cur_pos
),
290 if (parser_cxx_assist_is_expression_separator(ch
, FALSE
, iter
)) {
294 if (ch
== '.' || (op_start
&& ch
== '-') || (ref_start
&& ch
== ':'))
296 /* Found an operator, get the statement and the pre_word */
297 IAnjutaIterable
* pre_word_start
= ianjuta_iterable_clone (cur_pos
,
299 IAnjutaIterable
* pre_word_end
= ianjuta_iterable_clone (iter
, NULL
);
300 IAnjutaIterable
* stmt_end
= ianjuta_iterable_clone (pre_word_start
,
304 /* we need to pass to the parser all the statement included the last
305 * operator, being it "." or "->" or "::"
306 * Increase the end bound of the statement.
308 ianjuta_iterable_next (stmt_end
, NULL
);
309 if (op_start
== TRUE
|| ref_start
== TRUE
)
310 ianjuta_iterable_next (stmt_end
, NULL
);
313 /* Move one character forward so we have the start of the pre_word
314 * and not the last operator */
315 ianjuta_iterable_next (pre_word_start
, NULL
);
316 /* If this is a two character operator, skip the second character */
319 ianjuta_iterable_next (pre_word_start
, NULL
);
322 parser_cxx_assist_update_pre_word (assist
, ianjuta_editor_get_text (
328 /* Try to get the name of the variable */
329 while (ianjuta_iterable_previous (cur_pos
, NULL
))
331 gchar word_ch
= ianjuta_editor_cell_get_char (
332 IANJUTA_EDITOR_CELL(cur_pos
), 0, NULL
);
334 if (parser_cxx_assist_is_expression_separator(word_ch
, FALSE
,
338 ianjuta_iterable_next (cur_pos
, NULL
);
339 stmt
= ianjuta_editor_get_text (editor
,
340 cur_pos
, stmt_end
, NULL
);
341 *start_iter
= pre_word_start
;
342 g_object_unref (stmt_end
);
343 g_object_unref (pre_word_end
);
356 while (ianjuta_iterable_previous (cur_pos
, NULL
));
362 IAnjutaIterable
* start
;
364 if (!assist
->priv
->editor_filename
)
370 start
= ianjuta_editor_get_start_position (editor
, NULL
);
371 above_text
= ianjuta_editor_get_text (editor
, start
, iter
, NULL
);
372 g_object_unref (start
);
374 lineno
= ianjuta_editor_get_lineno (editor
, NULL
);
376 /* the parser works even for the "Gtk::" like expressions, so it
377 * shouldn't be created a specific case to handle this.
379 res
= engine_parser_process_expression (stmt
,
381 assist
->priv
->editor_filename
,
385 g_object_unref (cur_pos
);
390 * parser_cxx_assist_cancel_queries:
393 * Abort all async operations
396 parser_cxx_assist_cancel_queries (ParserCxxAssist
* assist
)
398 ianjuta_symbol_query_cancel (assist
->priv
->ac_query_file
, NULL
);
399 ianjuta_symbol_query_cancel (assist
->priv
->ac_query_project
, NULL
);
400 ianjuta_symbol_query_cancel (assist
->priv
->ac_query_system
, NULL
);
401 assist
->priv
->async_file_id
= 0;
402 assist
->priv
->async_project_id
= 0;
403 assist
->priv
->async_system_id
= 0;
407 * parser_cxx_assist_clear_completion_cache:
410 * Clear the completion cache, aborting all async operations
413 parser_cxx_assist_clear_completion_cache (ParserCxxAssist
* assist
)
415 parser_cxx_assist_cancel_queries (assist
);
416 anjuta_completion_clear (assist
->priv
->completion_cache
);
417 assist
->priv
->member_completion
= FALSE
;
418 assist
->priv
->autocompletion
= FALSE
;
422 * parser_cxx_assist_populate_real:
424 * @finished: TRUE if no more proposals are expected, FALSE otherwise
426 * Really invokes the completion interfaces and adds completions.
427 * Might be called from an async context
430 parser_cxx_assist_populate_real (ParserCxxAssist
* assist
, gboolean finished
)
432 g_assert (assist
->priv
->pre_word
!= NULL
);
433 GList
* proposals
= anjuta_completion_complete (assist
->priv
->completion_cache
,
434 assist
->priv
->pre_word
,
436 anjuta_language_provider_proposals (assist
->priv
->lang_prov
,
437 IANJUTA_PROVIDER(assist
), proposals
,
438 assist
->priv
->pre_word
, finished
);
439 g_list_free (proposals
);
443 * parser_cxx_assist_create_member_completion_cache
445 * @cursor: Current cursor position
447 * Create the completion_cache for member completion if possible
449 * Returns: the iter where a completion cache was build, NULL otherwise
451 static IAnjutaIterable
*
452 parser_cxx_assist_create_member_completion_cache (ParserCxxAssist
* assist
,
453 IAnjutaIterable
* cursor
)
455 IAnjutaIterable
* symbol
= NULL
;
456 IAnjutaIterable
* start_iter
= NULL
;
457 symbol
= parser_cxx_assist_parse_expression (assist
, cursor
, &start_iter
);
461 /* Query symbol children */
462 IAnjutaIterable
*children
=
463 ianjuta_symbol_query_search_members (assist
->priv
->query_members
,
464 IANJUTA_SYMBOL(symbol
),
467 g_object_unref (symbol
);
470 parser_cxx_assist_add_completions_from_symbols (assist
, children
);
472 parser_cxx_assist_populate_real (assist
, TRUE
);
473 g_object_unref (children
);
478 g_object_unref (start_iter
);
483 * on_symbol_search_complete:
484 * @search_id: id of this search
485 * @symbols: the returned symbols
488 * Called by the async search method when it found symbols
491 on_symbol_search_complete (IAnjutaSymbolQuery
*query
, IAnjutaIterable
* symbols
,
492 ParserCxxAssist
* assist
)
494 if (query
== assist
->priv
->ac_query_file
)
495 assist
->priv
->async_file_id
= 0;
496 else if (query
== assist
->priv
->ac_query_project
)
497 assist
->priv
->async_project_id
= 0;
498 else if (query
== assist
->priv
->ac_query_system
)
499 assist
->priv
->async_system_id
= 0;
501 g_assert_not_reached ();
503 parser_cxx_assist_add_completions_from_symbols (assist
, symbols
);
505 gboolean running
= assist
->priv
->async_system_id
506 || assist
->priv
->async_file_id
507 || assist
->priv
->async_project_id
;
509 parser_cxx_assist_populate_real (assist
, TRUE
);
513 * parser_cxx_assist_create_autocompletion_cache:
515 * @cursor: Current cursor position
517 * Create completion cache for autocompletion. This is done async.
519 * Returns: the iter where a preword was detected, NULL otherwise
521 static IAnjutaIterable
*
522 parser_cxx_assist_create_autocompletion_cache (ParserCxxAssist
* assist
,
523 IAnjutaIterable
* cursor
)
525 IAnjutaIterable
* start_iter
;
526 gchar
* pre_word
= anjuta_language_provider_get_pre_word (
527 assist
->priv
->lang_prov
,
528 IANJUTA_EDITOR (assist
->priv
->iassist
),
529 cursor
, &start_iter
, WORD_CHARACTER
);
530 if (!pre_word
|| strlen (pre_word
) <= 3)
533 g_object_unref (start_iter
);
538 gchar
*pattern
= g_strconcat (pre_word
, "%", NULL
);
540 parser_cxx_assist_update_pre_word (assist
, pre_word
);
542 if (IANJUTA_IS_FILE (assist
->priv
->iassist
))
544 GFile
*file
= ianjuta_file_get_file (
545 IANJUTA_FILE (assist
->priv
->iassist
), NULL
);
548 assist
->priv
->async_file_id
= 1;
549 ianjuta_symbol_query_search_file (assist
->priv
->ac_query_file
,
550 pattern
, file
, NULL
);
551 g_object_unref (file
);
554 /* This will avoid duplicates of FUNCTION and PROTOTYPE */
555 assist
->priv
->async_project_id
= 1;
556 ianjuta_symbol_query_search (assist
->priv
->ac_query_project
, pattern
,
558 assist
->priv
->async_system_id
= 1;
559 ianjuta_symbol_query_search (assist
->priv
->ac_query_system
, pattern
,
569 * parser_cxx_assist_get_calltip_context:
571 * @iter: current cursor position
572 * @e: Error propagation
574 * Searches for a calltip context
576 * Returns: name of the method to show a calltip for or NULL
579 parser_cxx_assist_get_calltip_context (IAnjutaLanguageProvider
*self
,
580 IAnjutaIterable
*iter
,
583 ParserCxxAssist
* assist
= PARSER_CXX_ASSIST (self
);
584 gchar
* calltip_context
;
585 calltip_context
= anjuta_language_provider_get_calltip_context (
586 assist
->priv
->lang_prov
, assist
->priv
->itip
, iter
,
587 SCOPE_CONTEXT_CHARACTERS
);
588 return calltip_context
;
592 * parser_cxx_assist_create_calltips:
593 * @iter: List of symbols
594 * @merge: list of calltips to merge or NULL
596 * Create a list of Calltips (string) from a list of symbols
598 * A newly allocated GList* with newly allocated strings
601 parser_cxx_assist_create_calltips (IAnjutaIterable
* iter
, GList
* merge
)
608 IAnjutaSymbol
* symbol
= IANJUTA_SYMBOL (iter
);
609 const gchar
* name
= ianjuta_symbol_get_string (
610 symbol
,IANJUTA_SYMBOL_FIELD_NAME
, NULL
);
613 const gchar
* args
= ianjuta_symbol_get_string (
615 IANJUTA_SYMBOL_FIELD_SIGNATURE
,
617 const gchar
* rettype
= ianjuta_symbol_get_string (
619 IANJUTA_SYMBOL_FIELD_RETURNTYPE
,
624 gint white_count
= 0;
629 white_count
+= strlen(rettype
) + 1;
631 white_count
+= strlen(name
) + 1;
633 white_name
= g_strnfill (white_count
, ' ');
634 separator
= g_strjoin (NULL
, ", \n", white_name
, NULL
);
639 argv
= g_strsplit (args
, ",", -1);
640 print_args
= g_strjoinv (separator
, argv
);
641 gchar
* tip
= g_strdup_printf ("%s %s %s", rettype
, name
,
644 if (!g_list_find_custom (tips
, tip
, (GCompareFunc
) strcmp
))
645 tips
= g_list_append (tips
, tip
);
655 while (ianjuta_iterable_next (iter
, NULL
));
661 * on_calltip_search_complete:
662 * @search_id: id of this search
663 * @symbols: the returned symbols
666 * Called by the async search method when it found calltips
669 on_calltip_search_complete (IAnjutaSymbolQuery
*query
, IAnjutaIterable
* symbols
,
670 ParserCxxAssist
* assist
)
672 assist
->priv
->tips
= parser_cxx_assist_create_calltips (symbols
,
674 if (query
== assist
->priv
->calltip_query_file
)
675 assist
->priv
->async_calltip_file
= 0;
676 else if (query
== assist
->priv
->calltip_query_project
)
677 assist
->priv
->async_calltip_project
= 0;
678 else if (query
== assist
->priv
->calltip_query_system
)
679 assist
->priv
->async_calltip_system
= 0;
681 g_assert_not_reached ();
682 gboolean running
= assist
->priv
->async_calltip_system
683 || assist
->priv
->async_calltip_file
684 || assist
->priv
->async_calltip_project
;
686 DEBUG_PRINT ("Calltip search finished with %d items",
687 g_list_length (assist
->priv
->tips
));
689 if (!running
&& assist
->priv
->tips
)
691 ianjuta_editor_tip_show (IANJUTA_EDITOR_TIP(assist
->priv
->itip
),
692 assist
->priv
->tips
, assist
->priv
->calltip_iter
,
698 * parser_cxx_assist_query_calltip:
700 * @call_context: name of method/function
701 * e: Error propagation
703 * Starts an async query for the calltip
706 parser_cxx_assist_query_calltip (ParserCxxAssist
* assist
,
707 const gchar
*call_context
,
708 IAnjutaIterable
* calltip_iter
)
711 if (IANJUTA_IS_FILE (assist
->priv
->itip
))
713 GFile
*file
= ianjuta_file_get_file (IANJUTA_FILE (assist
->priv
->itip
),
718 assist
->priv
->async_calltip_file
= 1;
719 ianjuta_symbol_query_search_file (assist
->priv
->calltip_query_file
,
720 call_context
, file
, NULL
);
721 g_object_unref (file
);
726 assist
->priv
->async_calltip_project
= 1;
727 ianjuta_symbol_query_search (assist
->priv
->calltip_query_project
,
731 assist
->priv
->async_calltip_system
= 1;
732 ianjuta_symbol_query_search (assist
->priv
->calltip_query_system
,
737 * parser_cxx_assist_create_calltip_context:
739 * @call_context: The context (method/function name)
740 * @position: iter where to show calltips
742 * Create the calltip context
745 parser_cxx_assist_create_calltip_context (ParserCxxAssist
* assist
,
746 const gchar
* call_context
,
747 IAnjutaIterable
* position
)
749 assist
->priv
->calltip_context
= g_strdup (call_context
);
750 assist
->priv
->calltip_iter
= position
;
754 * parser_cxx_assist_clear_calltip_context:
756 * @e: Error propagation
758 * Clears the calltip context and brings it back into a save state
761 parser_cxx_assist_clear_calltip_context (ParserCxxAssist
* assist
)
763 ianjuta_symbol_query_cancel (assist
->priv
->calltip_query_file
, NULL
);
764 ianjuta_symbol_query_cancel (assist
->priv
->calltip_query_project
, NULL
);
765 ianjuta_symbol_query_cancel (assist
->priv
->calltip_query_system
, NULL
);
767 assist
->priv
->async_calltip_file
= 0;
768 assist
->priv
->async_calltip_project
= 0;
769 assist
->priv
->async_calltip_system
= 0;
771 g_list_foreach (assist
->priv
->tips
, (GFunc
) g_free
, NULL
);
772 g_list_free (assist
->priv
->tips
);
773 assist
->priv
->tips
= NULL
;
775 g_free (assist
->priv
->calltip_context
);
776 assist
->priv
->calltip_context
= NULL
;
778 if (assist
->priv
->calltip_iter
)
779 g_object_unref (assist
->priv
->calltip_iter
);
780 assist
->priv
->calltip_iter
= NULL
;
784 * parser_cxx_assist_cancelled:
785 * @iassist: IAnjutaEditorAssist that emitted the signal
786 * @assist: ParserCxxAssist object
788 * Stop any autocompletion queries when the cancelled signal was received
791 parser_cxx_assist_cancelled (IAnjutaEditorAssist
* iassist
,
792 ParserCxxAssist
* assist
)
794 parser_cxx_assist_cancel_queries (assist
);
798 parser_cxx_assist_get_calltip_cache (IAnjutaLanguageProvider
* self
,
802 ParserCxxAssist
* assist
= PARSER_CXX_ASSIST (self
);
803 if (!g_strcmp0 (call_context
, assist
->priv
->calltip_context
))
805 DEBUG_PRINT ("Calltip was found in the cache.");
806 return assist
->priv
->tips
;
810 DEBUG_PRINT ("Calltip is not available in the cache!");
816 parser_cxx_assist_new_calltip (IAnjutaLanguageProvider
* self
,
818 IAnjutaIterable
* cursor
,
821 ParserCxxAssist
* assist
= PARSER_CXX_ASSIST (self
);
822 parser_cxx_assist_clear_calltip_context (assist
);
823 parser_cxx_assist_create_calltip_context (assist
, call_context
, cursor
);
824 parser_cxx_assist_query_calltip (assist
, call_context
, cursor
);
827 static IAnjutaIterable
*
828 parser_cxx_assist_populate_completions (IAnjutaLanguageProvider
* self
,
829 IAnjutaIterable
* cursor
,
832 ParserCxxAssist
* assist
= PARSER_CXX_ASSIST (self
);
833 IAnjutaIterable
* start_iter
= NULL
;
835 /* Check if completion was in progress */
836 if (assist
->priv
->member_completion
|| assist
->priv
->autocompletion
)
838 gchar
* pre_word
= anjuta_language_provider_get_pre_word (
839 assist
->priv
->lang_prov
,
840 IANJUTA_EDITOR (assist
->priv
->iassist
),
841 cursor
, &start_iter
, WORD_CHARACTER
);
842 DEBUG_PRINT ("Preword: %s", pre_word
);
843 if (pre_word
&& g_str_has_prefix (pre_word
, assist
->priv
->pre_word
))
845 DEBUG_PRINT ("Continue autocomplete for %s", pre_word
);
847 /* Great, we just continue the current completion */
848 parser_cxx_assist_update_pre_word (assist
, pre_word
);
849 parser_cxx_assist_populate_real (assist
, TRUE
);
856 parser_cxx_assist_clear_completion_cache (assist
);
858 /* Check for member completion */
859 start_iter
= parser_cxx_assist_create_member_completion_cache (assist
,
862 assist
->priv
->member_completion
= TRUE
;
865 start_iter
= parser_cxx_assist_create_autocompletion_cache (assist
,
868 assist
->priv
->autocompletion
= TRUE
;
875 * parser_cxx_assist_install:
876 * @assist: ParserCxxAssist object
877 * @ieditor: Editor to install support for
878 * @iparser: Parser to install support for
880 * Returns: Registers provider for editor
883 parser_cxx_assist_install (ParserCxxAssist
*assist
,
884 IAnjutaEditor
*ieditor
)
886 g_return_if_fail (assist
->priv
->iassist
== NULL
);
888 if (IANJUTA_IS_EDITOR_ASSIST (ieditor
))
890 assist
->priv
->iassist
= IANJUTA_EDITOR_ASSIST (ieditor
);
891 ianjuta_editor_assist_add (IANJUTA_EDITOR_ASSIST (ieditor
),
892 IANJUTA_PROVIDER(assist
), NULL
);
893 g_signal_connect (ieditor
, "cancelled",
894 G_CALLBACK (parser_cxx_assist_cancelled
), assist
);
897 assist
->priv
->iassist
= NULL
;
899 if (IANJUTA_IS_EDITOR_TIP (ieditor
))
900 assist
->priv
->itip
= IANJUTA_EDITOR_TIP (ieditor
);
902 assist
->priv
->itip
= NULL
;
904 if (IANJUTA_IS_FILE (assist
->priv
->iassist
))
906 GFile
*file
= ianjuta_file_get_file (
907 IANJUTA_FILE (assist
->priv
->iassist
), NULL
);
910 assist
->priv
->editor_filename
= g_file_get_path (file
);
911 g_object_unref (file
);
917 * parser_cxx_assist_uninstall:
918 * @self: ParserCxxAssist object
920 * Returns: Unregisters provider
923 parser_cxx_assist_uninstall (ParserCxxAssist
*assist
)
925 g_return_if_fail (assist
->priv
->iassist
!= NULL
);
927 g_signal_handlers_disconnect_by_func (assist
->priv
->iassist
,
928 parser_cxx_assist_cancelled
, assist
);
929 ianjuta_editor_assist_remove (assist
->priv
->iassist
, IANJUTA_PROVIDER(assist
), NULL
);
930 assist
->priv
->iassist
= NULL
;
934 parser_cxx_assist_init (ParserCxxAssist
*assist
)
936 ParserCxxAssistPriv
* priv
;
938 assist
->priv
= priv
= g_new0 (ParserCxxAssistPriv
, 1);
940 priv
->completion_cache
= anjuta_completion_new (anjuta_proposal_completion_func
);
941 anjuta_completion_set_item_destroy_func (priv
->completion_cache
,
942 (GDestroyNotify
)parser_cxx_assist_proposal_free
);
946 parser_cxx_assist_finalize (GObject
*object
)
948 ParserCxxAssist
*assist
= PARSER_CXX_ASSIST (object
);
949 ParserCxxAssistPriv
* priv
= assist
->priv
;
951 parser_cxx_assist_uninstall (assist
);
952 parser_cxx_assist_clear_calltip_context (assist
);
955 g_object_unref (priv
->completion_cache
);
956 g_free (priv
->pre_word
);
958 if (priv
->calltip_query_file
)
959 g_object_unref (priv
->calltip_query_file
);
960 priv
->calltip_query_file
= NULL
;
962 if (priv
->calltip_query_system
)
963 g_object_unref (priv
->calltip_query_system
);
964 priv
->calltip_query_system
= NULL
;
966 if (priv
->calltip_query_project
)
967 g_object_unref (priv
->calltip_query_project
);
968 priv
->calltip_query_project
= NULL
;
970 if (priv
->ac_query_file
)
971 g_object_unref (priv
->ac_query_file
);
972 priv
->ac_query_file
= NULL
;
974 if (priv
->ac_query_system
)
975 g_object_unref (priv
->ac_query_system
);
976 priv
->ac_query_system
= NULL
;
978 if (priv
->ac_query_project
)
979 g_object_unref (priv
->ac_query_project
);
980 priv
->ac_query_project
= NULL
;
982 if (priv
->query_members
)
983 g_object_unref (priv
->query_members
);
984 priv
->query_members
= NULL
;
986 if (priv
->sync_query_file
)
987 g_object_unref (priv
->sync_query_file
);
988 priv
->sync_query_file
= NULL
;
990 if (priv
->sync_query_system
)
991 g_object_unref (priv
->sync_query_system
);
992 priv
->sync_query_system
= NULL
;
994 if (priv
->sync_query_project
)
995 g_object_unref (priv
->sync_query_project
);
996 priv
->sync_query_project
= NULL
;
998 engine_parser_deinit ();
1000 g_free (assist
->priv
);
1001 G_OBJECT_CLASS (parser_cxx_assist_parent_class
)->finalize (object
);
1005 parser_cxx_assist_class_init (ParserCxxAssistClass
*klass
)
1007 GObjectClass
* object_class
= G_OBJECT_CLASS (klass
);
1009 object_class
->finalize
= parser_cxx_assist_finalize
;
1013 parser_cxx_assist_new (IAnjutaEditor
*ieditor
,
1014 IAnjutaSymbolManager
*isymbol_manager
,
1015 GSettings
* settings
)
1017 ParserCxxAssist
*assist
;
1018 static IAnjutaSymbolField calltip_fields
[] = {
1019 IANJUTA_SYMBOL_FIELD_ID
,
1020 IANJUTA_SYMBOL_FIELD_NAME
,
1021 IANJUTA_SYMBOL_FIELD_RETURNTYPE
,
1022 IANJUTA_SYMBOL_FIELD_SIGNATURE
1024 static IAnjutaSymbolField ac_fields
[] = {
1025 IANJUTA_SYMBOL_FIELD_ID
,
1026 IANJUTA_SYMBOL_FIELD_NAME
,
1027 IANJUTA_SYMBOL_FIELD_KIND
,
1028 IANJUTA_SYMBOL_FIELD_TYPE
,
1029 IANJUTA_SYMBOL_FIELD_ACCESS
,
1030 IANJUTA_SYMBOL_FIELD_SIGNATURE
1033 if (!IANJUTA_IS_EDITOR_ASSIST (ieditor
) && !IANJUTA_IS_EDITOR_TIP (ieditor
))
1035 /* No assistance is available with the current editor */
1038 assist
= g_object_new (TYPE_PARSER_CXX_ASSIST
, NULL
);
1039 assist
->priv
->settings
= settings
;
1041 /* Create call tip queries */
1042 /* Calltip in file */
1043 assist
->priv
->calltip_query_file
=
1044 ianjuta_symbol_manager_create_query (isymbol_manager
,
1045 IANJUTA_SYMBOL_QUERY_SEARCH_FILE
,
1046 IANJUTA_SYMBOL_QUERY_DB_PROJECT
,
1048 ianjuta_symbol_query_set_fields (assist
->priv
->calltip_query_file
,
1049 G_N_ELEMENTS (calltip_fields
),
1050 calltip_fields
, NULL
);
1051 ianjuta_symbol_query_set_filters (assist
->priv
->calltip_query_file
,
1052 IANJUTA_SYMBOL_TYPE_PROTOTYPE
|
1053 IANJUTA_SYMBOL_TYPE_FUNCTION
|
1054 IANJUTA_SYMBOL_TYPE_METHOD
|
1055 IANJUTA_SYMBOL_TYPE_MACRO_WITH_ARG
,
1057 ianjuta_symbol_query_set_file_scope (assist
->priv
->calltip_query_file
,
1058 IANJUTA_SYMBOL_QUERY_SEARCH_FS_PRIVATE
,
1060 ianjuta_symbol_query_set_mode (assist
->priv
->calltip_query_file
,
1061 IANJUTA_SYMBOL_QUERY_MODE_ASYNC
, NULL
);
1062 g_signal_connect_object (assist
->priv
->calltip_query_file
, "async-result",
1063 G_CALLBACK (on_calltip_search_complete
), assist
, 0);
1064 /* Calltip in project */
1065 assist
->priv
->calltip_query_project
=
1066 ianjuta_symbol_manager_create_query (isymbol_manager
,
1067 IANJUTA_SYMBOL_QUERY_SEARCH
,
1068 IANJUTA_SYMBOL_QUERY_DB_PROJECT
,
1070 ianjuta_symbol_query_set_fields (assist
->priv
->calltip_query_project
,
1071 G_N_ELEMENTS (calltip_fields
),
1072 calltip_fields
, NULL
);
1073 ianjuta_symbol_query_set_filters (assist
->priv
->calltip_query_project
,
1074 IANJUTA_SYMBOL_TYPE_PROTOTYPE
|
1075 IANJUTA_SYMBOL_TYPE_METHOD
|
1076 IANJUTA_SYMBOL_TYPE_MACRO_WITH_ARG
,
1078 ianjuta_symbol_query_set_file_scope (assist
->priv
->calltip_query_project
,
1079 IANJUTA_SYMBOL_QUERY_SEARCH_FS_PUBLIC
,
1081 ianjuta_symbol_query_set_mode (assist
->priv
->calltip_query_project
,
1082 IANJUTA_SYMBOL_QUERY_MODE_ASYNC
, NULL
);
1083 g_signal_connect_object (assist
->priv
->calltip_query_project
, "async-result",
1084 G_CALLBACK (on_calltip_search_complete
), assist
, 0);
1085 /* Calltip in system */
1086 assist
->priv
->calltip_query_system
=
1087 ianjuta_symbol_manager_create_query (isymbol_manager
,
1088 IANJUTA_SYMBOL_QUERY_SEARCH
,
1089 IANJUTA_SYMBOL_QUERY_DB_SYSTEM
,
1091 ianjuta_symbol_query_set_fields (assist
->priv
->calltip_query_system
,
1092 G_N_ELEMENTS (calltip_fields
),
1093 calltip_fields
, NULL
);
1094 ianjuta_symbol_query_set_filters (assist
->priv
->calltip_query_system
,
1095 IANJUTA_SYMBOL_TYPE_PROTOTYPE
|
1096 IANJUTA_SYMBOL_TYPE_METHOD
|
1097 IANJUTA_SYMBOL_TYPE_MACRO_WITH_ARG
,
1099 ianjuta_symbol_query_set_file_scope (assist
->priv
->calltip_query_system
,
1100 IANJUTA_SYMBOL_QUERY_SEARCH_FS_PUBLIC
,
1102 ianjuta_symbol_query_set_mode (assist
->priv
->calltip_query_system
,
1103 IANJUTA_SYMBOL_QUERY_MODE_ASYNC
, NULL
);
1104 g_signal_connect_object (assist
->priv
->calltip_query_system
, "async-result",
1105 G_CALLBACK (on_calltip_search_complete
), assist
, 0);
1107 /* Create autocomplete queries */
1109 assist
->priv
->ac_query_file
=
1110 ianjuta_symbol_manager_create_query (isymbol_manager
,
1111 IANJUTA_SYMBOL_QUERY_SEARCH_FILE
,
1112 IANJUTA_SYMBOL_QUERY_DB_PROJECT
,
1114 ianjuta_symbol_query_set_group_by (assist
->priv
->ac_query_file
,
1115 IANJUTA_SYMBOL_FIELD_NAME
, NULL
);
1116 ianjuta_symbol_query_set_fields (assist
->priv
->ac_query_file
,
1117 G_N_ELEMENTS (ac_fields
),
1119 ianjuta_symbol_query_set_file_scope (assist
->priv
->ac_query_file
,
1120 IANJUTA_SYMBOL_QUERY_SEARCH_FS_PRIVATE
,
1122 ianjuta_symbol_query_set_mode (assist
->priv
->ac_query_file
,
1123 IANJUTA_SYMBOL_QUERY_MODE_ASYNC
, NULL
);
1124 g_signal_connect_object (assist
->priv
->ac_query_file
, "async-result",
1125 G_CALLBACK (on_symbol_search_complete
), assist
, 0);
1127 assist
->priv
->ac_query_project
=
1128 ianjuta_symbol_manager_create_query (isymbol_manager
,
1129 IANJUTA_SYMBOL_QUERY_SEARCH
,
1130 IANJUTA_SYMBOL_QUERY_DB_PROJECT
,
1132 ianjuta_symbol_query_set_group_by (assist
->priv
->ac_query_project
,
1133 IANJUTA_SYMBOL_FIELD_NAME
, NULL
);
1134 ianjuta_symbol_query_set_fields (assist
->priv
->ac_query_project
,
1135 G_N_ELEMENTS (ac_fields
),
1137 ianjuta_symbol_query_set_file_scope (assist
->priv
->ac_query_project
,
1138 IANJUTA_SYMBOL_QUERY_SEARCH_FS_PUBLIC
,
1140 ianjuta_symbol_query_set_mode (assist
->priv
->ac_query_project
,
1141 IANJUTA_SYMBOL_QUERY_MODE_ASYNC
, NULL
);
1142 g_signal_connect_object (assist
->priv
->ac_query_project
, "async-result",
1143 G_CALLBACK (on_symbol_search_complete
), assist
, 0);
1145 assist
->priv
->ac_query_system
=
1146 ianjuta_symbol_manager_create_query (isymbol_manager
,
1147 IANJUTA_SYMBOL_QUERY_SEARCH
,
1148 IANJUTA_SYMBOL_QUERY_DB_SYSTEM
,
1150 ianjuta_symbol_query_set_group_by (assist
->priv
->ac_query_system
,
1151 IANJUTA_SYMBOL_FIELD_NAME
, NULL
);
1152 ianjuta_symbol_query_set_fields (assist
->priv
->ac_query_system
,
1153 G_N_ELEMENTS (ac_fields
),
1155 ianjuta_symbol_query_set_file_scope (assist
->priv
->ac_query_system
,
1156 IANJUTA_SYMBOL_QUERY_SEARCH_FS_PUBLIC
,
1158 ianjuta_symbol_query_set_mode (assist
->priv
->ac_query_system
,
1159 IANJUTA_SYMBOL_QUERY_MODE_ASYNC
, NULL
);
1160 g_signal_connect_object (assist
->priv
->ac_query_system
, "async-result",
1161 G_CALLBACK (on_symbol_search_complete
), assist
, 0);
1163 /* Members autocompletion */
1164 assist
->priv
->query_members
=
1165 ianjuta_symbol_manager_create_query (isymbol_manager
,
1166 IANJUTA_SYMBOL_QUERY_SEARCH_MEMBERS
,
1167 IANJUTA_SYMBOL_QUERY_DB_PROJECT
,
1169 ianjuta_symbol_query_set_fields (assist
->priv
->query_members
,
1170 G_N_ELEMENTS (ac_fields
),
1173 /* Create sync queries */
1174 /* Sync query in file */
1175 assist
->priv
->sync_query_file
=
1176 ianjuta_symbol_manager_create_query (isymbol_manager
,
1177 IANJUTA_SYMBOL_QUERY_SEARCH_FILE
,
1178 IANJUTA_SYMBOL_QUERY_DB_PROJECT
,
1180 ianjuta_symbol_query_set_fields (assist
->priv
->sync_query_file
,
1181 G_N_ELEMENTS (calltip_fields
),
1182 calltip_fields
, NULL
);
1183 ianjuta_symbol_query_set_filters (assist
->priv
->sync_query_file
,
1184 IANJUTA_SYMBOL_TYPE_PROTOTYPE
|
1185 IANJUTA_SYMBOL_TYPE_FUNCTION
|
1186 IANJUTA_SYMBOL_TYPE_METHOD
|
1187 IANJUTA_SYMBOL_TYPE_MACRO_WITH_ARG
,
1189 ianjuta_symbol_query_set_file_scope (assist
->priv
->sync_query_file
,
1190 IANJUTA_SYMBOL_QUERY_SEARCH_FS_PRIVATE
,
1192 /* Sync query in project */
1193 assist
->priv
->sync_query_project
=
1194 ianjuta_symbol_manager_create_query (isymbol_manager
,
1195 IANJUTA_SYMBOL_QUERY_SEARCH
,
1196 IANJUTA_SYMBOL_QUERY_DB_PROJECT
,
1198 ianjuta_symbol_query_set_fields (assist
->priv
->sync_query_project
,
1199 G_N_ELEMENTS (calltip_fields
),
1200 calltip_fields
, NULL
);
1201 ianjuta_symbol_query_set_filters (assist
->priv
->sync_query_project
,
1202 IANJUTA_SYMBOL_TYPE_PROTOTYPE
|
1203 IANJUTA_SYMBOL_TYPE_METHOD
|
1204 IANJUTA_SYMBOL_TYPE_MACRO_WITH_ARG
,
1206 ianjuta_symbol_query_set_file_scope (assist
->priv
->sync_query_project
,
1207 IANJUTA_SYMBOL_QUERY_SEARCH_FS_PUBLIC
,
1209 /* Sync query in system */
1210 assist
->priv
->sync_query_system
=
1211 ianjuta_symbol_manager_create_query (isymbol_manager
,
1212 IANJUTA_SYMBOL_QUERY_SEARCH
,
1213 IANJUTA_SYMBOL_QUERY_DB_SYSTEM
,
1215 ianjuta_symbol_query_set_fields (assist
->priv
->sync_query_system
,
1216 G_N_ELEMENTS (calltip_fields
),
1217 calltip_fields
, NULL
);
1218 ianjuta_symbol_query_set_filters (assist
->priv
->sync_query_system
,
1219 IANJUTA_SYMBOL_TYPE_PROTOTYPE
|
1220 IANJUTA_SYMBOL_TYPE_METHOD
|
1221 IANJUTA_SYMBOL_TYPE_MACRO_WITH_ARG
,
1223 ianjuta_symbol_query_set_file_scope (assist
->priv
->sync_query_system
,
1224 IANJUTA_SYMBOL_QUERY_SEARCH_FS_PUBLIC
,
1227 /* Install support */
1228 parser_cxx_assist_install (assist
, ieditor
);
1229 assist
->priv
->lang_prov
= g_object_new (ANJUTA_TYPE_LANGUAGE_PROVIDER
, NULL
);
1230 anjuta_language_provider_install (assist
->priv
->lang_prov
, ieditor
, settings
);
1231 engine_parser_init (isymbol_manager
);
1237 parser_cxx_assist_activate (IAnjutaProvider
* self
,
1238 IAnjutaIterable
* iter
,
1242 ParserCxxAssist
* assist
= PARSER_CXX_ASSIST (self
);
1243 anjuta_language_provider_activate (assist
->priv
->lang_prov
, self
, iter
,
1248 parser_cxx_assist_populate (IAnjutaProvider
* self
,
1249 IAnjutaIterable
* cursor
,
1252 ParserCxxAssist
* assist
= PARSER_CXX_ASSIST (self
);
1253 anjuta_language_provider_populate (assist
->priv
->lang_prov
, self
, cursor
);
1257 parser_cxx_assist_get_name (IAnjutaProvider
* self
,
1263 static IAnjutaIterable
*
1264 parser_cxx_assist_get_start_iter (IAnjutaProvider
* self
,
1267 ParserCxxAssist
* assist
= PARSER_CXX_ASSIST (self
);
1268 return anjuta_language_provider_get_start_iter (assist
->priv
->lang_prov
);
1272 iprovider_iface_init (IAnjutaProviderIface
* iface
)
1274 iface
->activate
= parser_cxx_assist_activate
;
1275 iface
->populate
= parser_cxx_assist_populate
;
1276 iface
->get_name
= parser_cxx_assist_get_name
;
1277 iface
->get_start_iter
= parser_cxx_assist_get_start_iter
;
1281 ilanguage_provider_iface_init (IAnjutaLanguageProviderIface
* iface
)
1283 iface
->get_calltip_cache
= parser_cxx_assist_get_calltip_cache
;
1284 iface
->get_calltip_context
= parser_cxx_assist_get_calltip_context
;
1285 iface
->new_calltip
= parser_cxx_assist_new_calltip
;
1286 iface
->populate_completions
= parser_cxx_assist_populate_completions
;