Updated Makefile.am files after make -f git.mk
[anjuta.git] / plugins / language-support-vala / provider.vala
blob366a5a6c990ee3b28199f7b33454733de21cdad9
1 /*
2 * Copyright (C) 2008-2010 Abderrahim Kitouni
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 public class ValaProvider : Object, IAnjuta.Provider {
19 IAnjuta.Iterable start_pos;
20 weak ValaPlugin plugin;
22 static Regex member_access;
23 static Regex member_access_split;
24 static Regex function_call;
26 const string PREF_AUTOCOMPLETE_ENABLE = "completion-enable";
27 const string PREF_SPACE_AFTER_FUNC = "completion-space-after-func";
28 const string PREF_BRACE_AFTER_FUNC = "completion-brace-after-func";
29 internal const string PREF_CALLTIP_ENABLE = "calltip-enable";
31 static construct {
32 try {
33 member_access = new Regex("""((?:\w+(?:\s*\([^()]*\))?\.)*)(\w*)$""");
34 member_access_split = new Regex ("""(\s*\([^()]*\))?\.""");
35 function_call = new Regex("""(new )?((?:\w+(?:\s*\([^()]*\))?\.)*)(\w+)\s*\(([^(,)]+,)*([^(,)]*)$""");
36 } catch(RegexError err) {
37 critical("Regular expressions failed to compile : %s", err.message);
41 public ValaProvider(ValaPlugin plugin) {
42 this.plugin = plugin;
44 public unowned string get_name () throws GLib.Error {
45 return "Vala";
47 public void populate (IAnjuta.Iterable iter) throws GLib.Error {
48 if (!plugin.settings.get_boolean (PREF_AUTOCOMPLETE_ENABLE))
49 return;
51 var editor = plugin.current_editor as IAnjuta.EditorAssist;
52 var line_start = editor.get_line_begin_position(editor.get_lineno());
53 var current_text = editor.get_text(line_start, iter);
55 MatchInfo match_info;
56 if (! member_access.match(current_text, 0, out match_info))
57 return;
58 if (match_info.fetch(0).length < 2)
59 return;
61 start_pos = iter.clone();
62 start_pos.set_position(iter.get_position() - (int) match_info.fetch(2).length);
64 var names = member_access_split.split (match_info.fetch(1));
66 var syms = plugin.lookup_symbol (construct_member_access (names), match_info.fetch(2),
67 true, plugin.get_current_context (editor) as Vala.Block);
69 var proposals = new GLib.List<IAnjuta.EditorAssistProposal?>();
70 foreach (var symbol in syms) {
71 if (symbol is Vala.LocalVariable
72 && symbol.source_reference.begin.line > editor.get_lineno())
73 continue;
75 var prop = IAnjuta.EditorAssistProposal();
76 prop.data = symbol;
77 prop.label = symbol.name;
78 proposals.prepend(prop);
80 proposals.reverse();
81 editor.proposals(this, proposals, null, true);
83 public unowned IAnjuta.Iterable get_start_iter () throws GLib.Error {
84 return start_pos;
86 public void activate (IAnjuta.Iterable iter, void* data) {
87 var sym = data as Vala.Symbol;
88 var editor = plugin.current_editor as IAnjuta.EditorAssist;
89 var assist = sym.name;
90 var is_func = false;
91 var calltip = false;
93 if (sym is Vala.Method || sym is Vala.Signal) {
94 is_func = true;
95 } else if (sym is Vala.Variable) {
96 if (((Vala.Variable) sym).variable_type is Vala.DelegateType) {
97 is_func = true;
101 if (is_func) {
102 if (plugin.settings.get_boolean (PREF_SPACE_AFTER_FUNC)) {
103 assist += " ";
105 if (plugin.settings.get_boolean (PREF_BRACE_AFTER_FUNC)) {
106 assist += "(";
107 if (plugin.settings.get_boolean (PREF_CALLTIP_ENABLE)) {
108 calltip = true;
113 (editor as IAnjuta.Document).begin_undo_action();
114 editor.erase(start_pos, iter);
115 editor.insert(start_pos, assist, -1);
116 (editor as IAnjuta.Document).end_undo_action();
118 if (calltip && editor is IAnjuta.EditorTip) {
119 show_call_tip ((IAnjuta.EditorTip) editor);
123 public void show_call_tip (IAnjuta.EditorTip editor) {
124 var current_position = editor.get_position ();
125 var line_start = editor.get_line_begin_position(editor.get_lineno());
126 var to_complete = editor.get_text(line_start, current_position);
128 List<string> tips = null;
130 MatchInfo match_info;
131 if (! function_call.match(to_complete, 0, out match_info))
132 return;
134 var creation_method = (match_info.fetch(1) != "");
135 var names = member_access_split.split (match_info.fetch(2));
136 var syms = plugin.lookup_symbol (construct_member_access (names), match_info.fetch(3),
137 false, plugin.get_current_context (editor) as Vala.Block);
138 foreach (var sym in syms) {
139 var calltip = new StringBuilder ();
140 Vala.List<Vala.Parameter> parameters = null;
141 if (sym is Vala.Method) {
142 parameters = ((Vala.Method) sym).get_parameters ();
143 calltip.append (((Vala.Method) sym).return_type.to_qualified_string() + " ");
144 } else if (sym is Vala.Signal) {
145 parameters = ((Vala.Signal) sym).get_parameters ();
146 } else if (creation_method && sym is Vala.Class) {
147 parameters = ((Vala.Class) sym).default_construction_method.get_parameters ();
148 } else if (sym is Vala.Variable) {
149 var var_type = ((Vala.Variable) sym).variable_type;
150 if (var_type is Vala.DelegateType) {
151 var delegate_sym = ((Vala.DelegateType) var_type).delegate_symbol;
152 parameters = delegate_sym.get_parameters ();
153 calltip.append (delegate_sym.return_type.to_qualified_string() + " ");
154 } else {
155 return;
157 } else {
158 return;
161 calltip.append (sym.get_full_name ());
162 calltip.append(" (");
163 var prestring = "".nfill (calltip.len, ' ');
164 var first = true;
165 foreach (var p in parameters) {
166 if(first) {
167 first = false;
168 } else {
169 calltip.append (",\n");
170 calltip.append (prestring);
172 if (p.ellipsis) {
173 calltip.append ("...");
174 } else {
175 calltip.append (p.variable_type.to_qualified_string());
176 calltip.append (" ").append (p.name);
179 calltip.append (")");
180 tips.append (calltip.str);
182 editor.show (tips, editor.get_position ());
184 Vala.Expression construct_member_access (string[] names) {
185 Vala.Expression expr = null;
187 for (var i = 0; names[i] != null; i++) {
188 if (names[i] != "") {
189 expr = new Vala.MemberAccess (expr, names[i]);
190 if (names[i+1] != null && names[i+1].chug ().has_prefix ("(")) {
191 expr = new Vala.MethodCall (expr);
192 i++;
197 return expr;