~ubuntu-branches/ubuntu/oneiric/monodevelop/oneiric

« back to all changes in this revision

Viewing changes to src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/CSharpTextEditorCompletion.cs

  • Committer: Bazaar Package Importer
  • Author(s): Jo Shields
  • Date: 2011-06-27 17:03:13 UTC
  • mto: (1.8.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 54.
  • Revision ID: james.westby@ubuntu.com-20110627170313-6cvz3s19x6e9hqe9
ImportĀ upstreamĀ versionĀ 2.5.92+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
46
46
 
47
47
using MonoDevelop.CSharp.Formatting;
48
48
using MonoDevelop.CSharp.Parser;
49
 
using MonoDevelop.CSharp.Dom;
 
49
using MonoDevelop.CSharp.Ast;
50
50
using MonoDevelop.CSharp.Project;
51
51
using MonoDevelop.CSharp.Resolver;
 
52
using MonoDevelop.Components;
 
53
using Gtk;
 
54
using MonoDevelop.Ide;
52
55
 
53
56
namespace MonoDevelop.CSharp.Completion
54
57
{
55
 
        public class CSharpTextEditorCompletion : CompletionTextEditorExtension
 
58
        public class CSharpTextEditorCompletion : CompletionTextEditorExtension, IPathedDocument
56
59
        {
57
60
                ProjectDom dom;
58
61
                DocumentStateTracker<CSharpIndentEngine> stateTracker;
79
82
                {
80
83
                        base.Initialize ();
81
84
                        dom = Document.Dom;
82
 
                        textEditorData = Document.TextEditorData;
 
85
                        textEditorData = Document.Editor;
83
86
                        
84
87
                        InitTracker ();
85
88
                        IEnumerable<string> types = MonoDevelop.Ide.DesktopService.GetMimeTypeInheritanceChain (CSharpFormatter.MimeType);
86
89
                        if (dom != null && dom.Project != null)
87
 
                                policy = base.Document.Project.Policies.Get<CSharpFormattingPolicy> (types);
 
90
                                policy = dom.Project.Policies.Get<CSharpFormattingPolicy> (types);
 
91
                        UpdatePath (null, null);
 
92
                        textEditorData.Caret.PositionChanged += UpdatePath;
 
93
                        Document.DocumentParsed += HandleDocumentDocumentParsed;
 
94
                }
 
95
 
 
96
                void HandleDocumentDocumentParsed (object sender, EventArgs e)
 
97
                {
 
98
                        UpdatePath (null, null);
 
99
                }
 
100
 
 
101
                public override void Dispose ()
 
102
                {
 
103
                        textEditorData.Caret.PositionChanged -= UpdatePath;
 
104
                        Document.DocumentParsed -= HandleDocumentDocumentParsed;
 
105
                        base.Dispose ();
88
106
                }
89
107
                
90
108
                public override bool ExtendsEditor (MonoDevelop.Ide.Gui.Document doc, IEditableTextBuffer editor)
113
131
                {
114
132
                        NewCSharpExpressionFinder expressionFinder = new NewCSharpExpressionFinder (dom);
115
133
                        try {
116
 
                                return expressionFinder.FindExpression (Editor.Text, Math.Max (ctx.TriggerOffset + offset, 0));
 
134
                                return expressionFinder.FindExpression (textEditorData, Math.Max (ctx.TriggerOffset + offset, 0));
117
135
                        } catch (Exception ex) {
118
136
                                LoggingService.LogWarning (ex.Message, ex);
119
137
                                return null;
124
142
                {
125
143
                        NewCSharpExpressionFinder expressionFinder = new NewCSharpExpressionFinder (dom);
126
144
                        try {
127
 
                                return expressionFinder.FindExpression (Editor.Text, ctx.TriggerOffset);
 
145
                                return expressionFinder.FindExpression (textEditorData, ctx.TriggerOffset);
128
146
                        } catch (Exception ex) {
129
147
                                LoggingService.LogWarning (ex.Message, ex);
130
148
                                return null;
151
169
                                base.RunParameterCompletionCommand ();
152
170
                        
153
171
                        if (stateTracker.Engine.IsInsideComment) {
154
 
                                ParameterInformationWindowManager.HideWindow ();
 
172
                                ParameterInformationWindowManager.HideWindow (CompletionWidget);
155
173
                        }/* else {
156
174
                                int cpos;
157
175
                                if (key == Gdk.Key.Return && CanRunParameterCompletionCommand () && GetParameterCompletionCommandOffset (out cpos))  {
173
191
                                return null;
174
192
                        }
175
193
 
176
 
        //              IDisposable timer = null;
177
 
                try {
178
 
                        if (dom == null /*|| Document.CompilationUnit == null*/)
179
 
                                return null;
180
 
                        if (completionChar != '#' && stateTracker.Engine.IsInsidePreprocessorDirective)
181
 
                                return null;
182
 
                //      timer = Counters.ResolveTime.BeginTiming ();
183
 
                        DomLocation location = new DomLocation (completionContext.TriggerLine, completionContext.TriggerLineOffset - 1);
184
 
                        stateTracker.UpdateEngine ();
185
 
                        ExpressionResult result;
186
 
                        int cursor, newCursorOffset = 0;
187
 
                        switch (completionChar) {
188
 
                        case ':':
189
 
                        case '.':
190
 
                                if (stateTracker.Engine.IsInsideDocLineComment || stateTracker.Engine.IsInsideOrdinaryCommentOrString)
191
 
                                        return null;
192
 
                                result = FindExpression (dom, completionContext);
193
 
                                if (result == null || result.Expression == null)
194
 
                                        return null;
195
 
                                int idx = result.Expression.LastIndexOf ('.');
196
 
                                if (idx > 0)
197
 
                                        result.Expression = result.Expression.Substring (0, idx);
198
 
                                NRefactoryResolver resolver = CreateResolver ();
199
 
                                ResolveResult resolveResult = resolver.Resolve (result, location);
200
 
                                if (resolver.ResolvedExpression is ICSharpCode.NRefactory.Ast.PrimitiveExpression) {
201
 
                                        ICSharpCode.NRefactory.Ast.PrimitiveExpression pex = (ICSharpCode.NRefactory.Ast.PrimitiveExpression)resolver.ResolvedExpression;
202
 
                                        if (!tryToForceCompletion && !(pex.Value is string || pex.Value is char || pex.Value is bool))
203
 
                                                return null;
204
 
                                }
205
 
                                        
206
 
                                return CreateCompletionData (location, resolveResult, result, resolver);
207
 
                        case '#':
208
 
                                if (stateTracker.Engine.IsInsidePreprocessorDirective) 
209
 
                                        return GetDirectiveCompletionData ();
210
 
                                return null;
211
 
                        case '>':
212
 
                                cursor = Editor.SelectionStartPosition;
213
 
                                
214
 
                                if (stateTracker.Engine.IsInsideDocLineComment) {
215
 
                                        string lineText = Editor.GetLineText (completionContext.TriggerLine);
216
 
                                        int startIndex = Math.Min (completionContext.TriggerLineOffset - 1, lineText.Length - 1);
217
 
                                        
218
 
                                        while (startIndex >= 0 && lineText[startIndex] != '<') {
219
 
                                                --startIndex;
220
 
                                                if (lineText[startIndex] == '/') { // already closed.
221
 
                                                        startIndex = -1;
222
 
                                                        break;
223
 
                                                }
224
 
                                        }
225
 
                                        
226
 
                                        if (startIndex >= 0) {
227
 
                                                int endIndex = startIndex;
228
 
                                                while (endIndex <= completionContext.TriggerLineOffset && endIndex < lineText.Length && !Char.IsWhiteSpace (lineText[endIndex])) {
229
 
                                                        endIndex++;
230
 
                                                }
231
 
                                                string tag = endIndex - startIndex - 1 > 0 ? lineText.Substring (startIndex + 1, endIndex - startIndex - 2) : null;
232
 
                                                if (!String.IsNullOrEmpty (tag) && commentTags.IndexOf (tag) >= 0) {
233
 
                                                        Editor.InsertText (cursor, "</" + tag + ">");
234
 
                                                        Editor.CursorPosition = cursor; 
 
194
//              IDisposable timer = null;
 
195
                        try {
 
196
                                if (dom == null /*|| Document.CompilationUnit == null*/)
 
197
                                        return null;
 
198
                                if (completionChar != '#' && stateTracker.Engine.IsInsidePreprocessorDirective)
 
199
                                        return null;
 
200
                                //      timer = Counters.ResolveTime.BeginTiming ();
 
201
                                DomLocation location = new DomLocation (completionContext.TriggerLine, completionContext.TriggerLineOffset - 1);
 
202
                                stateTracker.UpdateEngine ();
 
203
                                ExpressionResult result;
 
204
                                int cursor, newCursorOffset = 0, cpos;
 
205
                                IType resolvedType;
 
206
                                CodeCompletionContext ctx;
 
207
                                NRefactoryParameterDataProvider provider;
 
208
                                
 
209
                                
 
210
                                switch (completionChar) {
 
211
                                case ':':
 
212
                                case '.':
 
213
                                        if (stateTracker.Engine.IsInsideDocLineComment || stateTracker.Engine.IsInsideOrdinaryCommentOrString)
 
214
                                                return null;
 
215
                                        result = FindExpression (dom, completionContext);
 
216
                                        if (result == null || result.Expression == null)
 
217
                                                return null;
 
218
                                        int idx = result.Expression.LastIndexOf ('.');
 
219
                                        if (idx > 0)
 
220
                                                result.Expression = result.Expression.Substring (0, idx);
 
221
                                        // don't parse expressions that end with more than 1 dot - see #646820
 
222
                                        if (result.Expression.EndsWith ("."))
 
223
                                                return null;
 
224
                                        NRefactoryResolver resolver = CreateResolver ();
 
225
                                        ResolveResult resolveResult = resolver.Resolve (result, location);
 
226
                                        if (resolver.ResolvedExpression is ICSharpCode.NRefactory.Ast.PrimitiveExpression) {
 
227
                                                ICSharpCode.NRefactory.Ast.PrimitiveExpression pex = (ICSharpCode.NRefactory.Ast.PrimitiveExpression)resolver.ResolvedExpression;
 
228
                                                if (!tryToForceCompletion && !(pex.Value is string || pex.Value is char || pex.Value is bool))
235
229
                                                        return null;
 
230
                                        }
 
231
                                        
 
232
                                        return CreateCompletionData (location, resolveResult, result, resolver);
 
233
                                case '#':
 
234
                                        if (stateTracker.Engine.IsInsidePreprocessorDirective) 
 
235
                                                return GetDirectiveCompletionData ();
 
236
                                        return null;
 
237
                                case '>':
 
238
                                        cursor = textEditorData.IsSomethingSelected ? textEditorData.SelectionRange.Offset : textEditorData.Caret.Offset;
 
239
                                
 
240
                                        if (stateTracker.Engine.IsInsideDocLineComment) {
 
241
                                                string lineText = textEditorData.GetLineText (completionContext.TriggerLine);
 
242
                                                int startIndex = Math.Min (completionContext.TriggerLineOffset - 1, lineText.Length - 1);
 
243
                                        
 
244
                                                while (startIndex >= 0 && lineText [startIndex] != '<') {
 
245
                                                        --startIndex;
 
246
                                                        if (lineText [startIndex] == '/') { // already closed.
 
247
                                                                startIndex = -1;
 
248
                                                                break;
 
249
                                                        }
236
250
                                                }
237
 
                                        }
238
 
                                }
239
 
                                return null;
 
251
                                        
 
252
                                                if (startIndex >= 0) {
 
253
                                                        int endIndex = startIndex;
 
254
                                                        while (endIndex <= completionContext.TriggerLineOffset && endIndex < lineText.Length && !Char.IsWhiteSpace (lineText [endIndex])) {
 
255
                                                                endIndex++;
 
256
                                                        }
 
257
                                                        string tag = endIndex - startIndex - 1 > 0 ? lineText.Substring (startIndex + 1, endIndex - startIndex - 2) : null;
 
258
                                                        if (!String.IsNullOrEmpty (tag) && commentTags.IndexOf (tag) >= 0) {
 
259
                                                                textEditorData.Insert (cursor, "</" + tag + ">");
 
260
                                                                textEditorData.Caret.Offset = cursor; 
 
261
                                                                return null;
 
262
                                                        }
 
263
                                                }
 
264
                                        }
 
265
                                        return null;
240
266
/* Disabled because it gives problems when declaring arrays - for example string [] should not pop up code completion.
241
267
                        case '[':
242
268
                                if (stateTracker.Engine.IsInsideDocLineComment || stateTracker.Engine.IsInsideOrdinaryCommentOrString)
245
271
                                if (result.ExpressionContext == ExpressionContext.Attribute)
246
272
                                        return CreateCtrlSpaceCompletionData (completionContext, result);
247
273
                                return null;*/
248
 
                        case '<':
249
 
                                if (stateTracker.Engine.IsInsideDocLineComment) 
250
 
                                        return GetXmlDocumentationCompletionData ();
251
 
                                return null;
252
 
                        case '(':
253
 
                                if (stateTracker.Engine.IsInsideDocLineComment || stateTracker.Engine.IsInsideOrdinaryCommentOrString)
254
 
                                        return null;
255
 
                                result = FindExpression (dom, completionContext, -1);
256
 
                                if (result == null || result.Expression == null)
257
 
                                        return null;
258
 
                                resolver = CreateResolver ();
259
 
                                resolveResult = resolver.Resolve (result, new DomLocation (completionContext.TriggerLine, completionContext.TriggerLineOffset - 2));
260
 
                                
261
 
                                if (resolveResult != null && resolver.ResolvedExpression is ICSharpCode.NRefactory.Ast.TypeOfExpression) {
262
 
                                        CompletionDataList completionList = new ProjectDomCompletionDataList ();
263
 
                                        
264
 
                                        CompletionDataCollector col = new CompletionDataCollector (dom, completionList, Document.CompilationUnit, resolver.CallingType, location);
265
 
                                        AddPrimitiveTypes (col);
266
 
                                        foreach (object o in dom.GetNamespaceContents (GetUsedNamespaces (), true, true)) {
267
 
                                                col.Add (o);
268
 
                                        }
269
 
                                        if (resolver.CallingMember is IMethod) {
270
 
                                                foreach (ITypeParameter tp in ((IMethod)resolver.CallingMember).TypeParameters) {
271
 
                                                        col.Add (tp.Name, "md-keyword");
272
 
                                                }
273
 
                                        }
274
 
                                        if (resolver.CallingType != null) {
275
 
                                                foreach (ITypeParameter tp in resolver.CallingType.TypeParameters) {
276
 
                                                        col.Add (tp.Name, "md-keyword");
277
 
                                                }
278
 
                                        }
279
 
                                        return completionList;
280
 
                                }
281
 
                                return null;
282
 
                        case '/':
283
 
                                cursor = Editor.SelectionStartPosition;
284
 
                                if (cursor < 2)
 
274
                                case '<':
 
275
                                        if (stateTracker.Engine.IsInsideDocLineComment) 
 
276
                                                return GetXmlDocumentationCompletionData ();
 
277
                                        return null;
 
278
                                case '(':
 
279
                                        if (stateTracker.Engine.IsInsideDocLineComment || stateTracker.Engine.IsInsideOrdinaryCommentOrString)
 
280
                                                return null;
 
281
                                        result = FindExpression (dom, completionContext, -1);
 
282
                                        if (result == null || result.Expression == null)
 
283
                                                return null;
 
284
                                        resolver = CreateResolver ();
 
285
                                        resolveResult = resolver.Resolve (result, new DomLocation (completionContext.TriggerLine, completionContext.TriggerLineOffset - 2));
 
286
                                        if (resolveResult == null)
 
287
                                                return null;
 
288
                                        
 
289
                                        if (resolver.ResolvedExpression is ICSharpCode.NRefactory.Ast.TypeOfExpression) {
 
290
                                                CompletionDataList completionList = new ProjectDomCompletionDataList ();
 
291
                                        
 
292
                                                CompletionDataCollector col = new CompletionDataCollector (dom, completionList, Document.CompilationUnit, resolver.CallingType, location);
 
293
                                                AddPrimitiveTypes (col);
 
294
                                                foreach (object o in dom.GetNamespaceContents (GetUsedNamespaces (), true, true)) {
 
295
                                                        col.Add (o);
 
296
                                                }
 
297
                                                if (resolver.CallingMember is IMethod) {
 
298
                                                        foreach (ITypeParameter tp in ((IMethod)resolver.CallingMember).TypeParameters) {
 
299
                                                                col.Add (tp.Name, "md-keyword");
 
300
                                                        }
 
301
                                                }
 
302
                                                if (resolver.CallingType != null) {
 
303
                                                        foreach (ITypeParameter tp in resolver.CallingType.TypeParameters) {
 
304
                                                                col.Add (tp.Name, "md-keyword");
 
305
                                                        }
 
306
                                                }
 
307
                                                return completionList;
 
308
                                        }
 
309
                                        if (resolveResult is MethodResolveResult) {
 
310
                                                var methodResolveResult = resolveResult as MethodResolveResult;
 
311
                                                return CreateParameterCompletion (resolver, location, result.ExpressionContext, methodResolveResult.Methods, 0);        
 
312
                                        }
 
313
                                        return null;
 
314
                                case ',':
 
315
                                        if (!GetParameterCompletionCommandOffset (out cpos)) 
 
316
                                                return null;
 
317
                                        ctx = CompletionWidget.CreateCodeCompletionContext (cpos);
 
318
                                        provider = ParameterCompletionCommand (ctx) as NRefactoryParameterDataProvider;
 
319
                                        if (provider != null) {
 
320
                                                int currentParameter = provider.GetCurrentParameterIndex (CompletionWidget, ctx) - 1;
 
321
                                                return CreateParameterCompletion (CreateResolver (), location, ExpressionContext.MethodBody, provider.Methods, currentParameter);       
 
322
                                        }
285
323
                                        break;
 
324
                                case '/':
 
325
                                        cursor = textEditorData.IsSomethingSelected ? textEditorData.SelectionRange.Offset : textEditorData.Caret.Offset;
 
326
                                        if (cursor < 2)
 
327
                                                break;
286
328
                                        
287
 
                                if (stateTracker.Engine.IsInsideDocLineComment) {
288
 
                                        string lineText = Editor.GetLineText (completionContext.TriggerLine);
289
 
                                        bool startsDocComment = true;
290
 
                                        int slashes = 0;
291
 
                                        for (int i = 0; i < completionContext.TriggerLineOffset && i < lineText.Length; i++) {
292
 
                                                if (lineText[i] == '/') {
293
 
                                                        slashes++;
294
 
                                                        continue;
295
 
                                                }
296
 
                                                if (!Char.IsWhiteSpace (lineText[i])) {
297
 
                                                        startsDocComment = false;
298
 
                                                        break;
299
 
                                                }
300
 
                                        }
301
 
                                        // check if lines above already start a doc comment
302
 
                                        for (int i = completionContext.TriggerLine - 1; i >= 0; i--) {
303
 
                                                string text = Editor.GetLineText (i).Trim ();
304
 
                                                if (text.Length == 0)
305
 
                                                        continue;
306
 
                                                if (text.StartsWith ("///")) {
307
 
                                                        startsDocComment = false;
308
 
                                                        break;
309
 
                                                }
310
 
                                                break;
311
 
                                        }
 
329
                                        if (stateTracker.Engine.IsInsideDocLineComment) {
 
330
                                                string lineText = textEditorData.GetLineText (completionContext.TriggerLine);
 
331
                                                bool startsDocComment = true;
 
332
                                                int slashes = 0;
 
333
                                                for (int i = 0; i < completionContext.TriggerLineOffset && i < lineText.Length; i++) {
 
334
                                                        if (lineText [i] == '/') {
 
335
                                                                slashes++;
 
336
                                                                continue;
 
337
                                                        }
 
338
                                                        if (!Char.IsWhiteSpace (lineText [i])) {
 
339
                                                                startsDocComment = false;
 
340
                                                                break;
 
341
                                                        }
 
342
                                                }
 
343
// check if lines above already start a doc comment
 
344
                                                for (int i = completionContext.TriggerLine - 2; i >= 1; i--) {
 
345
                                                        string text = textEditorData.GetLineText (i);
 
346
                                                        if (text.Length == 0)
 
347
                                                                continue;
 
348
                                                        if (text.StartsWith ("///")) {
 
349
                                                                startsDocComment = false;
 
350
                                                                break;
 
351
                                                        }
 
352
                                                        break;
 
353
                                                }
312
354
                                                
313
 
                                        // check if following lines start a doc comment
314
 
                                        for (int i = completionContext.TriggerLine + 1; i < Editor.LineCount; i++) {
315
 
                                                string text = Editor.GetLineText (i);
316
 
                                                if (text == null)
317
 
                                                        break;
318
 
                                                text = text.Trim ();
319
 
                                                if (text.Length == 0)
320
 
                                                        continue;
321
 
                                                if (text.StartsWith ("///")) {
322
 
                                                        startsDocComment = false;
 
355
// check if following lines start a doc comment
 
356
                                                for (int i = completionContext.TriggerLine; i <= textEditorData.Document.LineCount; i++) {
 
357
                                                        string text = textEditorData.GetLineText (i);
 
358
                                                        if (text == null)
 
359
                                                                break;
 
360
                                                        text = text.Trim ();
 
361
                                                        if (text.Length == 0)
 
362
                                                                continue;
 
363
                                                        if (text.StartsWith ("///")) {
 
364
                                                                startsDocComment = false;
 
365
                                                                break;
 
366
                                                        }
323
367
                                                        break;
324
368
                                                }
325
 
                                                break;
326
 
                                        }
327
369
                                        
328
 
                                        if (!startsDocComment || slashes != 3)
329
 
                                                break;
330
 
                                        StringBuilder generatedComment = new StringBuilder ();
331
 
                                        bool generateStandardComment = true;
332
 
                                        ParsedDocument currentParsedDocument = Document.UpdateParseDocument ();
333
 
                                        IType insideClass = NRefactoryResolver.GetTypeAtCursor (currentParsedDocument.CompilationUnit, Document.FileName, location);
334
 
                                        if (insideClass != null) {
335
 
                                                string indent = GetLineWhiteSpace (lineText);
336
 
                                                if (insideClass.ClassType == ClassType.Delegate) {
 
370
                                                if (!startsDocComment || slashes != 3)
 
371
                                                        break;
 
372
                                                StringBuilder generatedComment = new StringBuilder ();
 
373
                                                bool generateStandardComment = true;
 
374
                                                ParsedDocument currentParsedDocument = Document.UpdateParseDocument ();
 
375
                                                IType insideClass = NRefactoryResolver.GetTypeAtCursor (currentParsedDocument.CompilationUnit, Document.FileName, location);
 
376
                                                if (insideClass != null) {
 
377
                                                        string indent = textEditorData.Document.GetLineIndent (completionContext.TriggerLine);
 
378
                                                        if (insideClass.ClassType == ClassType.Delegate) {
 
379
                                                                AppendSummary (generatedComment, indent, out newCursorOffset);
 
380
                                                                IMethod m = null;
 
381
                                                                foreach (IMethod method in insideClass.Methods)
 
382
                                                                        m = method;
 
383
                                                                AppendMethodComment (generatedComment, indent, m);
 
384
                                                                generateStandardComment = false;
 
385
                                                        } else {
 
386
                                                                if (!IsInsideClassBody (insideClass, completionContext.TriggerLine, completionContext.TriggerLineOffset))
 
387
                                                                        break;
 
388
                                                                string body = GenerateBody (insideClass, completionContext.TriggerLine, indent, out newCursorOffset);
 
389
                                                                if (!String.IsNullOrEmpty (body)) {
 
390
                                                                        generatedComment.Append (body);
 
391
                                                                        generateStandardComment = false;
 
392
                                                                }
 
393
                                                        }
 
394
                                                }
 
395
                                                if (generateStandardComment) {
 
396
                                                        string indent = textEditorData.Document.GetLineIndent (completionContext.TriggerLine);
337
397
                                                        AppendSummary (generatedComment, indent, out newCursorOffset);
338
 
                                                        IMethod m = null;
339
 
                                                        foreach (IMethod method in insideClass.Methods)
340
 
                                                                m = method;
341
 
                                                        AppendMethodComment (generatedComment, indent, m);
342
 
                                                        generateStandardComment = false;
343
 
                                                } else {
344
 
                                                        if (!IsInsideClassBody (insideClass, completionContext.TriggerLine, completionContext.TriggerLineOffset))
345
 
                                                                break;
346
 
                                                        string body = GenerateBody (insideClass, completionContext.TriggerLine, indent, out newCursorOffset);
347
 
                                                        if (!String.IsNullOrEmpty (body)) {
348
 
                                                                generatedComment.Append (body);
349
 
                                                                generateStandardComment = false;
350
 
                                                        }
351
398
                                                }
352
 
                                        }
353
 
                                        if (generateStandardComment) {
354
 
                                                string indent = GetLineWhiteSpace (Editor.GetLineText (completionContext.TriggerLine));
355
 
                                                AppendSummary (generatedComment, indent, out newCursorOffset);
356
 
                                        }
357
 
                                        Editor.EndAtomicUndo ();
358
 
                                        Editor.BeginAtomicUndo ();
359
 
                                        Editor.InsertText (cursor, generatedComment.ToString ());
360
 
                                        Editor.CursorPosition = cursor + newCursorOffset;
 
399
                                                textEditorData.Document.EndAtomicUndo ();
 
400
                                                textEditorData.Document.BeginAtomicUndo ();
 
401
                                                textEditorData.Insert (cursor, generatedComment.ToString ());
 
402
                                                textEditorData.Caret.Offset = cursor + newCursorOffset;
 
403
                                                return null;
 
404
                                        }
361
405
                                        return null;
362
 
                                }
363
 
                                return null;
364
406
//                      case '\n':
365
407
//                      case '\r': {
366
408
//                              if (stateTracker.Engine.IsInsideDocLineComment || stateTracker.Engine.IsInsideOrdinaryCommentOrString)
378
420
//                              } 
379
421
//                              return null;
380
422
//                              }
381
 
                        case ' ':
382
 
                                if (stateTracker.Engine.IsInsideDocLineComment || stateTracker.Engine.IsInsideOrdinaryCommentOrString)
383
 
                                        return null;
384
 
                                result = FindExpression (dom, completionContext);
385
 
                                if (result == null)
386
 
                                        return null;
387
 
                                        
388
 
                                        
389
 
                                int tokenIndex = completionContext.TriggerOffset;
390
 
                                string token = GetPreviousToken (ref tokenIndex, false);
391
 
                                if (result.ExpressionContext == ExpressionContext.ObjectInitializer) {
392
 
                                        resolver = CreateResolver ();
393
 
                                        ExpressionContext exactContext = new NewCSharpExpressionFinder (dom).FindExactContextForObjectInitializer (Editor, resolver.Unit, Document.FileName, resolver.CallingType);
394
 
                                        IReturnType objectInitializer = ((ExpressionContext.TypeExpressionContext)exactContext).UnresolvedType;
395
 
                                        if (objectInitializer != null && objectInitializer.ArrayDimensions == 0 && objectInitializer.PointerNestingLevel == 0 && (token == "{" || token == ","))
396
 
                                                return CreateCtrlSpaceCompletionData (completionContext, result); 
397
 
                                }
398
 
                                if (token == "=") {
399
 
                                        int j = tokenIndex;
400
 
                                        string prevToken = GetPreviousToken (ref j, false);
401
 
                                        if (prevToken == "=" || prevToken == "+" || prevToken == "-") {
402
 
                                                token = prevToken + token;
403
 
                                                tokenIndex = j;
404
 
                                        }
405
 
                                }
406
 
                                switch (token) {
407
 
                                case "=":
408
 
                                case "==":
409
 
                                        result = FindExpression (dom, completionContext, tokenIndex - completionContext.TriggerOffset - 1);
410
 
                                        resolver = CreateResolver ();
411
 
                                        resolveResult = resolver.Resolve (result, location);
412
 
                                        if (resolveResult != null) {
413
 
                                                IType resolvedType = dom.GetType (resolveResult.ResolvedType);
414
 
                                                if (resolvedType == null) 
415
 
                                                        return null;
416
 
                                                if (resolvedType.ClassType == ClassType.Enum) {
417
 
                                                        CompletionDataList completionList = new ProjectDomCompletionDataList ();
418
 
                                                        CompletionDataCollector cdc = new CompletionDataCollector (dom, completionList, Document.CompilationUnit, resolver.CallingType, location);
419
 
                                                        IReturnType returnType = new DomReturnType (resolvedType);
420
 
                                                        bool added = false;
421
 
                                                        foreach (IUsing u in Document.CompilationUnit.Usings) {
422
 
                                                                foreach (KeyValuePair<string, IReturnType> alias in u.Aliases) {
423
 
                                                                        if (alias.Value.ToInvariantString () == returnType.ToInvariantString ()) {
424
 
                                                                                cdc.Add (alias.Key, "md-class");
425
 
                                                                                added = true;
 
423
                                case ' ':
 
424
                                        if (stateTracker.Engine.IsInsideDocLineComment || stateTracker.Engine.IsInsideOrdinaryCommentOrString)
 
425
                                                return null;
 
426
                                        result = FindExpression (dom, completionContext);
 
427
                                        if (result == null)
 
428
                                                return null;
 
429
                                        
 
430
                                        int tokenIndex = completionContext.TriggerOffset;
 
431
                                        string token = GetPreviousToken (ref tokenIndex, false);
 
432
                                        if (result.ExpressionContext == ExpressionContext.ObjectInitializer) {
 
433
                                                resolver = CreateResolver ();
 
434
                                                ExpressionContext exactContext = new NewCSharpExpressionFinder (dom).FindExactContextForObjectInitializer (textEditorData, resolver.Unit, Document.FileName, resolver.CallingType);
 
435
                                                IReturnType objectInitializer = ((ExpressionContext.TypeExpressionContext)exactContext).UnresolvedType;
 
436
                                                if (objectInitializer != null && objectInitializer.ArrayDimensions == 0 && objectInitializer.PointerNestingLevel == 0 && (token == "{" || token == ","))
 
437
                                                        return CreateCtrlSpaceCompletionData (completionContext, result); 
 
438
                                        }
 
439
                                        if (token == "=") {
 
440
                                                int j = tokenIndex;
 
441
                                                string prevToken = GetPreviousToken (ref j, false);
 
442
                                                if (prevToken == "=" || prevToken == "+" || prevToken == "-") {
 
443
                                                        token = prevToken + token;
 
444
                                                        tokenIndex = j;
 
445
                                                }
 
446
                                        }
 
447
                                        switch (token) {
 
448
                                        case "(":
 
449
                                        case ",":
 
450
                                                if (!GetParameterCompletionCommandOffset (out cpos)) 
 
451
                                                        break;
 
452
                                                ctx = CompletionWidget.CreateCodeCompletionContext (cpos);
 
453
                                                provider = ParameterCompletionCommand (ctx) as NRefactoryParameterDataProvider;
 
454
                                                if (provider != null) {
 
455
                                                        int currentParameter = provider.GetCurrentParameterIndex (CompletionWidget, ctx) - 1;
 
456
                                                        return CreateParameterCompletion (CreateResolver (), location, ExpressionContext.IdentifierExpected, provider.Methods, currentParameter);       
 
457
                                                }
 
458
                                                break;
 
459
                                        case "=":
 
460
                                        case "==":
 
461
                                                result = FindExpression (dom, completionContext, tokenIndex - completionContext.TriggerOffset - 1);
 
462
                                                resolver = CreateResolver ();
 
463
                                                resolveResult = resolver.Resolve (result, location);
 
464
                                                if (resolveResult != null) {
 
465
                                                        resolvedType = dom.GetType (resolveResult.ResolvedType);
 
466
                                                        if (resolvedType == null) 
 
467
                                                                return null;
 
468
                                                        if (resolvedType.ClassType == ClassType.Enum) {
 
469
                                                                CompletionDataList completionList = new ProjectDomCompletionDataList ();
 
470
                                                                CompletionDataCollector cdc = new CompletionDataCollector (dom, completionList, Document.CompilationUnit, resolver.CallingType, location);
 
471
                                                                IReturnType returnType = new DomReturnType (resolvedType);
 
472
                                                                bool added = false;
 
473
                                                                foreach (IUsing u in Document.CompilationUnit.Usings) {
 
474
                                                                        foreach (KeyValuePair<string, IReturnType> alias in u.Aliases) {
 
475
                                                                                if (alias.Value.ToInvariantString () == returnType.ToInvariantString ()) {
 
476
                                                                                        cdc.Add (alias.Key, "md-class");
 
477
                                                                                        added = true;
 
478
                                                                                }
426
479
                                                                        }
427
480
                                                                }
428
 
                                                        }
429
 
                                                        if (!added)
430
 
                                                                cdc.Add (returnType);
 
481
                                                                if (!added && !string.IsNullOrEmpty (returnType.Namespace))
 
482
                                                                        cdc.Add (returnType);/*
431
483
                                                        foreach (object o in CreateCtrlSpaceCompletionData (completionContext, result)) {
432
484
                                                                MemberCompletionData memberData = o as MemberCompletionData;
433
 
                                                                if (memberData == null || memberData.Member == null)
 
485
                                                                if (memberData == null || memberData.Member == null) {
 
486
                                                                        completionList.Add (o as CompletionData);
434
487
                                                                        continue;
 
488
                                                                }
435
489
                                                                if (memberData.Member is IMember) {
436
490
                                                                        returnType = ((IMember)memberData.Member).ReturnType;
437
491
                                                                } else if (memberData.Member is IParameter) {
439
493
                                                                } else {
440
494
                                                                        returnType = ((LocalVariable)memberData.Member).ReturnType;
441
495
                                                                }
442
 
                                                                if (returnType != null && returnType.FullName == resolvedType.FullName)
 
496
                                                                // filter out void types
 
497
                                                                if (returnType != null && returnType.FullName != DomReturnType.Void.FullName)
443
498
                                                                        completionList.Add (memberData);
 
499
                                                        }*/
 
500
                                                                completionList.AutoCompleteEmptyMatch = false;
 
501
                                                                resolver.AddAccessibleCodeCompletionData (result.ExpressionContext, cdc);
 
502
                                                                AddEnumMembers (completionList, resolvedType);
 
503
                                                                return completionList;
444
504
                                                        }
445
 
                                                        completionList.AutoCompleteEmptyMatch = false;
446
 
                                                        return completionList;
447
 
                                                } else if (resolvedType.FullName == DomReturnType.Bool.FullName) {
448
 
                                                        CompletionDataList completionList = new ProjectDomCompletionDataList ();
449
 
                                                        CompletionDataCollector cdc = new CompletionDataCollector (dom, completionList, Document.CompilationUnit, resolver.CallingType, location);
450
 
                                                        completionList.AutoCompleteEmptyMatch = false;
451
 
                                                        cdc.Add ("true", "md-keyword");
452
 
                                                        cdc.Add ("false", "md-keyword");
453
 
                                                        
454
 
                                                        foreach (object o in CreateCtrlSpaceCompletionData (completionContext, result)) {
 
505
                                                
 
506
                                                        if (resolvedType.FullName == DomReturnType.Bool.FullName) {
 
507
                                                                CompletionDataList completionList = new ProjectDomCompletionDataList ();
 
508
                                                                CompletionDataCollector cdc = new CompletionDataCollector (dom, completionList, Document.CompilationUnit, resolver.CallingType, location);
 
509
                                                                completionList.AutoCompleteEmptyMatch = false;
 
510
                                                                cdc.Add ("true", "md-keyword");
 
511
                                                                cdc.Add ("false", "md-keyword");
 
512
/*                                                      foreach (object o in CreateCtrlSpaceCompletionData (completionContext, result)) {
455
513
                                                                MemberCompletionData memberData = o as MemberCompletionData;
456
 
                                                                if (memberData == null || memberData.Member == null)
 
514
                                                                if (memberData == null || memberData.Member == null) {
 
515
                                                                        completionList.Add (o as CompletionData);
457
516
                                                                        continue;
 
517
                                                                }
458
518
                                                                IReturnType returnType = null;
459
519
                                                                if (memberData.Member is IMember) {
460
520
                                                                        returnType = ((IMember)memberData.Member).ReturnType;
463
523
                                                                } else {
464
524
                                                                        returnType = ((LocalVariable)memberData.Member).ReturnType;
465
525
                                                                }
466
 
                                                                if (returnType != null && returnType.FullName == DomReturnType.Bool.FullName)
 
526
                                                                // filter out void types
 
527
                                                                if (returnType != null && returnType.FullName != DomReturnType.Void.FullName)
467
528
                                                                        completionList.Add (memberData);
468
 
                                                        }
 
529
                                                        }*/
 
530
                                                                resolver.AddAccessibleCodeCompletionData (result.ExpressionContext, cdc);
 
531
                                                                return completionList;
 
532
                                                        }
 
533
                                                        if (resolvedType.ClassType == ClassType.Delegate && token == "=") {
 
534
                                                                CompletionDataList completionList = new ProjectDomCompletionDataList ();
 
535
                                                                string parameterDefinition = AddDelegateHandlers (completionList, resolvedType);
 
536
                                                                string varName = GetPreviousMemberReferenceExpression (tokenIndex);
 
537
                                                                completionList.Add (new EventCreationCompletionData (textEditorData, varName, resolvedType, null, parameterDefinition, resolver.CallingMember, resolvedType));
 
538
                                                                return completionList;
 
539
                                                        }
 
540
                                                }
 
541
                                                return null;
 
542
                                        case "+=":
 
543
                                        case "-=":
 
544
                                                if (stateTracker.Engine.IsInsideDocLineComment || stateTracker.Engine.IsInsideOrdinaryCommentOrString)
 
545
                                                        return null;
 
546
                                                result = FindExpression (dom, completionContext, tokenIndex - completionContext.TriggerOffset);
 
547
                                                resolver = CreateResolver ();
 
548
                                                resolveResult = resolver.Resolve (result, location);
 
549
                                        
 
550
                                                if (resolveResult is MemberResolveResult) {
 
551
                                                        MemberResolveResult mrr = resolveResult as MemberResolveResult;
 
552
                                                        IEvent evt = mrr.ResolvedMember as IEvent;
 
553
                                                        if (evt == null)
 
554
                                                                return null;
 
555
                                                        IType delegateType = resolver.SearchType (evt.ReturnType);
 
556
                                                        if (delegateType == null || delegateType.ClassType != ClassType.Delegate)
 
557
                                                                return null;
 
558
                                                        CompletionDataList completionList = new ProjectDomCompletionDataList ();
 
559
                                                        CompletionDataCollector cdc = new CompletionDataCollector (dom, completionList, Document.CompilationUnit, resolver.CallingType, location);
 
560
                                                
 
561
                                                        IType declaringType = resolver.CallingType;
 
562
                                                        if (Document.LastErrorFreeParsedDocument != null) {
 
563
                                                                declaringType = Document.LastErrorFreeParsedDocument.CompilationUnit.GetType (declaringType.FullName, declaringType.TypeParameters.Count);
 
564
                                                        }
 
565
                                                        IType typeFromDatabase = null;
 
566
                                                        if (declaringType != null) {
 
567
                                                                typeFromDatabase = dom.GetType (declaringType.FullName, new DomReturnType (declaringType).GenericArguments) ?? declaringType;
 
568
                                                                bool includeProtected = DomType.IncludeProtected (dom, typeFromDatabase, resolver.CallingType);
 
569
                                                                foreach (IType type in dom.GetInheritanceTree (typeFromDatabase)) {
 
570
                                                                        foreach (IMethod method in type.Methods) {
 
571
                                                                                if (method.IsAccessibleFrom (dom, resolver.CallingType, resolver.CallingMember, includeProtected) && MatchDelegate (delegateType, method)) {
 
572
                                                                                        CompletionData data = cdc.Add (method);
 
573
                                                                                        data.SetText (data.CompletionText + ";");
 
574
                                                                                }
 
575
                                                                        }
 
576
                                                                }
 
577
                                                        }
 
578
                                                        if (token == "+=") {
 
579
                                                                string parameterDefinition = AddDelegateHandlers (completionList, delegateType);
 
580
                                                                string varName = GetPreviousMemberReferenceExpression (tokenIndex);
 
581
                                                                completionList.Add (new EventCreationCompletionData (textEditorData, varName, delegateType, evt, parameterDefinition, resolver.CallingMember, typeFromDatabase));
 
582
                                                        }
 
583
                                                
469
584
                                                        return completionList;
470
585
                                                }
 
586
                                                return null;
471
587
                                        }
472
 
                                        return null;
473
 
                                case "+=":
474
 
                                case "-=":
475
 
                                        if (stateTracker.Engine.IsInsideDocLineComment || stateTracker.Engine.IsInsideOrdinaryCommentOrString)
476
 
                                                return null;
477
 
                                        result = FindExpression (dom, completionContext, tokenIndex - completionContext.TriggerOffset);
478
 
                                        resolver = CreateResolver ();
479
 
                                        resolveResult = resolver.Resolve (result, location);
480
 
                                        
481
 
                                        if (resolveResult is MemberResolveResult) {
482
 
                                                MemberResolveResult mrr = resolveResult as MemberResolveResult;
483
 
                                                IEvent evt = mrr.ResolvedMember as IEvent;
484
 
                                                if (evt == null)
485
 
                                                        return null;
486
 
                                                IType delegateType = resolver.SearchType (evt.ReturnType);
487
 
                                                if (delegateType == null || delegateType.ClassType != ClassType.Delegate)
488
 
                                                        return null;
489
 
                                                CompletionDataList completionList = new ProjectDomCompletionDataList ();
490
 
                                                CompletionDataCollector cdc = new CompletionDataCollector (dom, completionList, Document.CompilationUnit, resolver.CallingType, location);
491
 
                                                
492
 
                                                IType declaringType = resolver.CallingType;
493
 
                                                if (Document.LastErrorFreeParsedDocument != null) {
494
 
                                                        declaringType = Document.LastErrorFreeParsedDocument.CompilationUnit.GetType (declaringType.FullName, declaringType.TypeParameters.Count);
495
 
                                                }
496
 
                                                IType typeFromDatabase = dom.GetType (declaringType.FullName, new DomReturnType (declaringType).GenericArguments) ?? declaringType;
497
 
                                                bool includeProtected = DomType.IncludeProtected (dom, typeFromDatabase, resolver.CallingType);
498
 
                                                foreach (IType type in dom.GetInheritanceTree (typeFromDatabase)) {
499
 
                                                        foreach (IMethod method in type.Methods) {
500
 
                                                                if (method.IsAccessibleFrom (dom, resolver.CallingType, resolver.CallingMember, includeProtected) && MatchDelegate (delegateType, method)) {
501
 
                                                                        CompletionData data = cdc.Add (method);
502
 
                                                                        data.SetText (data.CompletionText + ";");
503
 
                                                                }
504
 
                                                        }
505
 
                                                }
506
 
                                                if (token == "+=") {
507
 
                                                        IMethod delegateMethod = delegateType.Methods.First ();
508
 
                                                        completionList.Add ("delegate", "md-keyword", GettextCatalog.GetString ("Creates anonymous delegate."), "delegate {\n" + stateTracker.Engine.ThisLineIndent  + TextEditorProperties.IndentString + "|\n" + stateTracker.Engine.ThisLineIndent +"};");
509
 
                                                        StringBuilder sb = new StringBuilder ("(");
510
 
                                                        for (int k = 0; k < delegateMethod.Parameters.Count; k++) {
511
 
                                                                if (k > 0)
512
 
                                                                        sb.Append (", ");
513
 
                                                                IType parameterType = dom.GetType (delegateMethod.Parameters[k].ReturnType);
514
 
                                                                IReturnType returnType = parameterType != null ? new DomReturnType (parameterType) : delegateMethod.Parameters[k].ReturnType;
515
 
                                                                sb.Append (CompletionDataCollector.ambience.GetString (Document.CompilationUnit.ShortenTypeName (returnType, Document.TextEditor.CursorLine, Document.TextEditor.CursorColumn), OutputFlags.ClassBrowserEntries | OutputFlags.UseFullName  | OutputFlags.UseFullInnerTypeName));
516
 
                                                                sb.Append (" ");
517
 
                                                                sb.Append (delegateMethod.Parameters[k].Name);
518
 
                                                        }
519
 
                                                        sb.Append (")");
520
 
                                                        completionList.Add ("delegate" + sb, "md-keyword", GettextCatalog.GetString ("Creates anonymous delegate."), "delegate" + sb + " {\n" + stateTracker.Engine.ThisLineIndent  + TextEditorProperties.IndentString + "|\n" + stateTracker.Engine.ThisLineIndent +"};");
521
 
                                                        string varName = GetPreviousToken (ref tokenIndex, false);
522
 
                                                        varName = GetPreviousToken (ref tokenIndex, false);
523
 
                                                        if (varName != ".") {
524
 
                                                                varName = null;
 
588
                                        return HandleKeywordCompletion (completionContext, result, tokenIndex, token);
 
589
                                default:
 
590
                                        if ((Char.IsLetter (completionChar) || completionChar == '_') && TextEditorProperties.EnableAutoCodeCompletion && !stateTracker.Engine.IsInsideDocLineComment && !stateTracker.Engine.IsInsideOrdinaryCommentOrString) {
 
591
                                                char prevCh = completionContext.TriggerOffset > 2 ? textEditorData.GetCharAt (completionContext.TriggerOffset - 2) : '\0';
 
592
                                                char nextCh = completionContext.TriggerOffset < textEditorData.Length ? textEditorData.GetCharAt (completionContext.TriggerOffset) : ' ';
 
593
                                                const string allowedChars = ";,[(){}+-*/%^?:&|~!<>=";
 
594
                                                if (!Char.IsWhiteSpace (nextCh) && allowedChars.IndexOf (nextCh) < 0)
 
595
                                                        return null;
 
596
                                                if (Char.IsWhiteSpace (prevCh) || allowedChars.IndexOf (prevCh) >= 0) {
 
597
                                                        result = FindExpression (dom, completionContext, -1);
 
598
                                                        if (result == null)
 
599
                                                                return null;
 
600
                                                        if (IsInLinqContext (result)) {
 
601
                                                                tokenIndex = completionContext.TriggerOffset;
 
602
                                                                token = GetPreviousToken (ref tokenIndex, false); // token last typed
 
603
                                                                token = GetPreviousToken (ref tokenIndex, false); // possible linq keyword ?
 
604
                                                                triggerWordLength = 1;
 
605
                                                        
 
606
                                                                if (linqKeywords.Contains (token)) {
 
607
                                                                        if (token == "from") // after from no auto code completion.
 
608
                                                                                return null;
 
609
                                                                        result.Expression = "";
 
610
                                                                        return CreateCtrlSpaceCompletionData (completionContext, result);
 
611
                                                                }
 
612
                                                                CompletionDataList dataList = new ProjectDomCompletionDataList ();
 
613
                                                                CompletionDataCollector col = new CompletionDataCollector (dom, dataList, Document.CompilationUnit, null, new DomLocation (completionContext.TriggerLine, completionContext.TriggerLineOffset));
 
614
                                                                foreach (string kw in linqKeywords) {
 
615
                                                                        col.Add (kw, "md-keyword");
 
616
                                                                }
 
617
                                                                return dataList;
 
618
                                                        } else if (result.ExpressionContext != ExpressionContext.IdentifierExpected) {
 
619
                                                                triggerWordLength = 1;
 
620
                                                                bool autoSelect = true;
 
621
                                                                IType returnType = null;
 
622
                                                                if ((prevCh == ',' || prevCh == '(') && GetParameterCompletionCommandOffset (out cpos)) {
 
623
                                                                        ctx = CompletionWidget.CreateCodeCompletionContext (cpos);
 
624
                                                                        NRefactoryParameterDataProvider dataProvider = ParameterCompletionCommand (ctx) as NRefactoryParameterDataProvider;
 
625
                                                                        if (dataProvider != null) {
 
626
                                                                                int i = dataProvider.GetCurrentParameterIndex (CompletionWidget, ctx) - 1;
 
627
                                                                                foreach (var method in dataProvider.Methods) {
 
628
                                                                                        if (i < method.Parameters.Count) {
 
629
                                                                                                returnType = dom.GetType (method.Parameters [i].ReturnType);
 
630
                                                                                                autoSelect = returnType == null || returnType.ClassType != ClassType.Delegate;
 
631
                                                                                                break;
 
632
                                                                                        }
 
633
                                                                                }
 
634
                                                                        }
 
635
                                                                }
 
636
                                                                // Bug 677531 - Auto-complete doesn't always highlight generic parameter in method signature
 
637
                                                                //if (result.ExpressionContext == ExpressionContext.TypeName)
 
638
                                                                //      autoSelect = false;
 
639
                                                                CompletionDataList dataList = CreateCtrlSpaceCompletionData (completionContext, result);
 
640
                                                                AddEnumMembers (dataList, returnType);
 
641
                                                                dataList.AutoSelect = autoSelect;
 
642
                                                                return dataList;
525
643
                                                        } else {
526
 
                                                                List<string> names = new List<string> ();
527
 
                                                                while (varName == ".") {
528
 
                                                                        varName = GetPreviousToken (ref tokenIndex, false);
529
 
                                                                        if (varName == "this") {
530
 
                                                                                names.Add ("handle");
531
 
                                                                        } else if (varName != null) {
532
 
                                                                                string trimmedName = varName.Trim ();
533
 
                                                                                if (trimmedName.Length == 0)
534
 
                                                                                        break;
535
 
                                                                                names.Insert (0, trimmedName);
536
 
                                                                        }
537
 
                                                                        varName = GetPreviousToken (ref tokenIndex, false);
538
 
                                                                }
539
 
                                                                varName = String.Join ("", names.ToArray ());
540
 
                                                                foreach (char ch in varName) {
541
 
                                                                        if (!char.IsLetterOrDigit (ch) && ch != '_') {
542
 
                                                                                varName = "";
543
 
                                                                                break;
544
 
                                                                        }
545
 
                                                                }
546
 
                                                        }
 
644
                                                                result = FindExpression (dom, completionContext, 0);
 
645
                                                                tokenIndex = completionContext.TriggerOffset;
547
646
                                                                
548
 
                                                        completionList.Add (new EventCreationCompletionData (textEditorData, varName, delegateType, evt, sb.ToString (), resolver.CallingMember, typeFromDatabase));
549
 
                                                }
550
 
                                                return completionList;
551
 
                                        }
552
 
                                        return null;
553
 
                                }
554
 
                                return HandleKeywordCompletion (completionContext, result, tokenIndex, token);
555
 
                        default:
556
 
                                if ((Char.IsLetter (completionChar) || completionChar == '_') && TextEditorProperties.EnableAutoCodeCompletion
557
 
                                            && !stateTracker.Engine.IsInsideDocLineComment
558
 
                                            && !stateTracker.Engine.IsInsideOrdinaryCommentOrString)
559
 
                                {
560
 
                                        char prevCh = completionContext.TriggerOffset > 2
561
 
                                                        ? Editor.GetCharAt (completionContext.TriggerOffset - 2)
562
 
                                                        : '\0';
563
 
                                        
564
 
                                        char nextCh = completionContext.TriggerOffset < Editor.TextLength
565
 
                                                        ? Editor.GetCharAt (completionContext.TriggerOffset)
566
 
                                                        : ' ';
567
 
                                        const string allowedChars = ";,[(){}+-*/%^?:&|~!<>=";
568
 
                                        if (!Char.IsWhiteSpace (nextCh) && allowedChars.IndexOf (nextCh) < 0)
569
 
                                                return null;
570
 
                                        if (Char.IsWhiteSpace (prevCh) || allowedChars.IndexOf (prevCh) >= 0)
571
 
                                        {
572
 
                                                result = FindExpression (dom, completionContext, -1);
573
 
                                                if (result == null)
574
 
                                                        return null;
575
 
                                                if (IsInLinqContext (result)) {
576
 
                                                        tokenIndex = completionContext.TriggerOffset;
577
 
                                                        token = GetPreviousToken (ref tokenIndex, false); // token last typed
578
 
                                                        token = GetPreviousToken (ref tokenIndex, false); // possible linq keyword ?
579
 
                                                        triggerWordLength = 1;
580
 
                                                        
581
 
                                                        if (linqKeywords.Contains (token)) {
582
 
                                                                if (token == "from") // after from no auto code completion.
 
647
                                                                // check foreach case, unfortunately the expression finder is too dumb to handle full type names
 
648
                                                                // should be overworked if the expression finder is replaced with a mcs ast based analyzer.
 
649
                                                                var possibleForeachToken = GetPreviousToken (ref tokenIndex, false); // starting letter
 
650
                                                                possibleForeachToken = GetPreviousToken (ref tokenIndex, false); // varname
 
651
                                                        
 
652
                                                                // read return types to '(' token
 
653
                                                                possibleForeachToken = GetPreviousToken (ref tokenIndex, false); // varType
 
654
                                                                if (possibleForeachToken == ">") {
 
655
                                                                        while (possibleForeachToken != null && possibleForeachToken != "(") {
 
656
                                                                                possibleForeachToken = GetPreviousToken (ref tokenIndex, false);
 
657
                                                                        }
 
658
                                                                } else {
 
659
                                                                        possibleForeachToken = GetPreviousToken (ref tokenIndex, false); // (
 
660
                                                                        if (possibleForeachToken == ".")
 
661
                                                                                while (possibleForeachToken != null && possibleForeachToken != "(")
 
662
                                                                                        possibleForeachToken = GetPreviousToken (ref tokenIndex, false);
 
663
                                                                }
 
664
                                                                possibleForeachToken = GetPreviousToken (ref tokenIndex, false); // foreach
 
665
                                                        
 
666
                                                                if (possibleForeachToken == "foreach") {
 
667
                                                                        result.ExpressionContext = ExpressionContext.ForeachInToken;
 
668
                                                                } else {
583
669
                                                                        return null;
 
670
                                                                        //                                                              result.ExpressionContext = ExpressionContext.IdentifierExpected;
 
671
                                                                }
584
672
                                                                result.Expression = "";
 
673
                                                                result.Region = DomRegion.Empty;
 
674
                                                        
 
675
                                                                // identifier has already started with the first letter
 
676
                                                                completionContext.TriggerOffset--;
 
677
                                                                completionContext.TriggerLineOffset--;
 
678
                                                                completionContext.TriggerWordLength = 1;
585
679
                                                                return CreateCtrlSpaceCompletionData (completionContext, result);
586
680
                                                        }
587
 
                                                        CompletionDataList dataList = new ProjectDomCompletionDataList ();
588
 
                                                        CompletionDataCollector col = new CompletionDataCollector (dom, dataList, Document.CompilationUnit, null, new DomLocation (completionContext.TriggerLine, completionContext.TriggerLineOffset));
589
 
                                                        foreach (string kw in linqKeywords) {
590
 
                                                                col.Add (kw, "md-keyword");
591
 
                                                        }
592
 
                                                        return dataList;
593
 
                                                } else if (result.ExpressionContext != ExpressionContext.IdentifierExpected) {
594
 
                                                        triggerWordLength = 1;
595
 
                                                        bool autoSelect = true;
596
 
                                                        int cpos;
597
 
                                                        if ((prevCh == ',' || prevCh == '(') && GetParameterCompletionCommandOffset (out cpos)) {
598
 
                                                                CodeCompletionContext ctx = CompletionWidget.CreateCodeCompletionContext (cpos);
599
 
                                                                NRefactoryParameterDataProvider provider = ParameterCompletionCommand (ctx) as NRefactoryParameterDataProvider;
600
 
                                                                if (provider != null) {
601
 
                                                                        int i = provider.GetCurrentParameterIndex (ctx) - 1;
602
 
                                                                        if (i < provider.Methods[0].Parameters.Count) {
603
 
                                                                                IType returnType = dom.GetType (provider.Methods[0].Parameters[i].ReturnType);
604
 
                                                                                autoSelect = returnType == null || returnType.ClassType != ClassType.Delegate;
605
 
                                                                        }
606
 
                                                                }
607
 
                                                        }
608
 
                                                        if (result.ExpressionContext == ExpressionContext.TypeName)
609
 
                                                                autoSelect = false;
610
 
                                                        CompletionDataList dataList = CreateCtrlSpaceCompletionData (completionContext, result);
611
 
                                                        dataList.AutoSelect = autoSelect;
612
 
                                                        return dataList;
613
681
                                                }
614
682
                                        }
 
683
                                        break;
615
684
                                }
616
 
                                break;
617
 
                        }
618
685
                        } catch (Exception e) {
619
 
                                System.Console.WriteLine("cce: " +e);
 
686
                                LoggingService.LogError ("Unexpected code completion exception." + Environment.NewLine + 
 
687
                                        "FileName: " + Document.FileName + Environment.NewLine + 
 
688
                                        "Position: line=" + completionContext.TriggerLine + " col=" + completionContext.TriggerLineOffset + Environment.NewLine + 
 
689
                                        "Line text: " + Document.Editor.GetLineText (completionContext.TriggerLine), 
 
690
                                        e);
620
691
                        } finally {
621
 
        //                      if (timer != null)
622
 
        //                              timer.Dispose ();
 
692
                                //                      if (timer != null)
 
693
                                //                              timer.Dispose ();
623
694
                        }
624
695
                        return null;
625
696
                }
 
697
 
 
698
                public string GetPreviousMemberReferenceExpression (int tokenIndex)
 
699
                {
 
700
                        string result = GetPreviousToken (ref tokenIndex, false);
 
701
                        result = GetPreviousToken (ref tokenIndex, false);
 
702
                        if (result != ".") {
 
703
                                result = null;
 
704
                        } else {
 
705
                                List<string > names = new List<string> ();
 
706
                                while (result == ".") {
 
707
                                        result = GetPreviousToken (ref tokenIndex, false);
 
708
                                        if (result == "this") {
 
709
                                                names.Add ("handle");
 
710
                                        } else if (result != null) {
 
711
                                                string trimmedName = result.Trim ();
 
712
                                                if (trimmedName.Length == 0)
 
713
                                                        break;
 
714
                                                names.Insert (0, trimmedName);
 
715
                                        }
 
716
                                        result = GetPreviousToken (ref tokenIndex, false);
 
717
                                }
 
718
                                result = String.Join ("", names.ToArray ());
 
719
                                foreach (char ch in result) {
 
720
                                        if (!char.IsLetterOrDigit (ch) && ch != '_') {
 
721
                                                result = "";
 
722
                                                break;
 
723
                                        }
 
724
                                }
 
725
                        }
 
726
                        return result;
 
727
                }
 
728
 
 
729
                string AddDelegateHandlers (CompletionDataList completionList, IType delegateType, bool addSemicolon = true, bool addDefault = true)
 
730
                {
 
731
                        IMethod delegateMethod = delegateType.Methods.First ();
 
732
                        string delegateEndString = Document.Editor.EolMarker + stateTracker.Engine.ThisLineIndent + "}" + (addSemicolon ? ";" : "");
 
733
                        bool containsDelegateData = completionList.Any (d => d.DisplayText.StartsWith ("delegate("));
 
734
                        if (addDefault)
 
735
                                completionList.Add ("delegate", "md-keyword", GettextCatalog.GetString ("Creates anonymous delegate."), "delegate {" + Document.Editor.EolMarker + stateTracker.Engine.ThisLineIndent + TextEditorProperties.IndentString + "|" + delegateEndString);
 
736
                        
 
737
                        StringBuilder sb = new StringBuilder ("(");
 
738
                        StringBuilder sbWithoutTypes = new StringBuilder ("(");
 
739
                        for (int k = 0; k < delegateMethod.Parameters.Count; k++) {
 
740
                                if (k > 0) {
 
741
                                        sb.Append (", ");
 
742
                                        sbWithoutTypes.Append (", ");
 
743
                                }
 
744
                                IType parameterType = dom.GetType (delegateMethod.Parameters [k].ReturnType);
 
745
                                IReturnType returnType = parameterType != null ? new DomReturnType (parameterType) : delegateMethod.Parameters [k].ReturnType;
 
746
                                sb.Append (CompletionDataCollector.ambience.GetString (Document.CompilationUnit.ShortenTypeName (returnType, textEditorData.Caret.Line, textEditorData.Caret.Column), OutputFlags.ClassBrowserEntries | OutputFlags.UseFullName | OutputFlags.UseFullInnerTypeName));
 
747
                                sb.Append (" ");
 
748
                                sb.Append (delegateMethod.Parameters [k].Name);
 
749
                                sbWithoutTypes.Append (delegateMethod.Parameters [k].Name);
 
750
                        }
 
751
                        sb.Append (")");
 
752
                        sbWithoutTypes.Append (")");
 
753
                        completionList.Add ("delegate" + sb, "md-keyword", GettextCatalog.GetString ("Creates anonymous delegate."), "delegate" + sb + " {" + Document.Editor.EolMarker + stateTracker.Engine.ThisLineIndent + TextEditorProperties.IndentString + "|" + delegateEndString);
 
754
                        completionList.Add (sbWithoutTypes.ToString (), "md-keyword", GettextCatalog.GetString ("Creates lambda expression."), sbWithoutTypes + " => |" + (addSemicolon ? ";" : ""));
 
755
                        
 
756
                        // It's  needed to temporarly disable inserting auto matching bracket because the anonymous delegates are selectable with '('
 
757
                        // otherwise we would end up with () => )
 
758
                        if (!containsDelegateData) {
 
759
                                var savedValue = MonoDevelop.SourceEditor.DefaultSourceEditorOptions.Instance.AutoInsertMatchingBracket;
 
760
                                MonoDevelop.SourceEditor.DefaultSourceEditorOptions.Instance.AutoInsertMatchingBracket = false;
 
761
                                completionList.CompletionListClosed += delegate {
 
762
                                        MonoDevelop.SourceEditor.DefaultSourceEditorOptions.Instance.AutoInsertMatchingBracket = savedValue;
 
763
                                };
 
764
                        }
 
765
                        return sb.ToString ();
 
766
                }
 
767
                
 
768
                public void AddEnumMembers (CompletionDataList completionList, IType resolvedType)
 
769
                {
 
770
                        if (resolvedType == null || resolvedType.ClassType != ClassType.Enum)
 
771
                                return;
 
772
                        string typeString = Document.CompilationUnit.ShortenTypeName (new DomReturnType (resolvedType), new DomLocation (Document.Editor.Caret.Line, Document.Editor.Caret.Column)).ToInvariantString ();
 
773
                        if (typeString.Contains ("."))
 
774
                                completionList.Add (typeString, resolvedType.StockIcon);
 
775
                        foreach (var field in resolvedType.Fields) {
 
776
                                if (field.IsConst || field.IsStatic)
 
777
                                        completionList.Add (typeString + "." + field.Name, field.StockIcon);
 
778
                        }
 
779
                        completionList.DefaultCompletionString = typeString;
 
780
                }
 
781
 
 
782
                public CompletionDataList CreateParameterCompletion (NRefactoryResolver resolver, DomLocation location, ExpressionContext context, IEnumerable<IMethod> possibleMethods, int parameter)
 
783
                {
 
784
                        CompletionDataList completionList = new ProjectDomCompletionDataList ();
 
785
                        var addedEnums = new HashSet<string> ();
 
786
                        var addedDelegates = new HashSet<string> ();
 
787
                        IType resolvedType = null;
 
788
                        foreach (var method in possibleMethods) {
 
789
                                if (method.Parameters.Count <= parameter)
 
790
                                        continue;
 
791
                                resolvedType = dom.GetType (method.Parameters [parameter].ReturnType);
 
792
                                if (resolvedType == null)
 
793
                                        continue;
 
794
                                switch (resolvedType.ClassType) {
 
795
                                case ClassType.Enum:
 
796
                                        if (addedEnums.Contains (resolvedType.DecoratedFullName))
 
797
                                                continue;
 
798
                                        addedEnums.Add (resolvedType.DecoratedFullName);
 
799
                                        AddEnumMembers (completionList, resolvedType);
 
800
                                        break;
 
801
                                case ClassType.Delegate:
 
802
                                        if (addedDelegates.Contains (resolvedType.DecoratedFullName))
 
803
                                                continue;
 
804
                                        addedDelegates.Add (resolvedType.DecoratedFullName);
 
805
                                        string parameterDefinition = AddDelegateHandlers (completionList, resolvedType, false, addedDelegates.Count == 1);
 
806
                                        string varName = "Handle" + method.Parameters [parameter].ReturnType.Name + method.Parameters [parameter].Name;
 
807
                                        completionList.Add (new EventCreationCompletionData (textEditorData, varName, resolvedType, null, parameterDefinition, resolver.Unit.GetMemberAt (location), resolvedType) { AddSemicolon = false });
 
808
                                        break;
 
809
                                }
 
810
                        }
 
811
                        if (addedEnums.Count + addedDelegates.Count == 0)
 
812
                                return null;
 
813
                        CompletionDataCollector cdc = new CompletionDataCollector (dom, completionList, Document.CompilationUnit, resolver.CallingType, location);
 
814
                        completionList.AutoCompleteEmptyMatch = false;
 
815
                        completionList.AutoSelect = false;
 
816
                        resolver.AddAccessibleCodeCompletionData (context, cdc);
 
817
                        return completionList;
 
818
                }
626
819
                
627
820
                public bool IsInLinqContext (ExpressionResult result)
628
821
                {
682
875
                int GetMemberStartPosition (IMember mem)
683
876
                {
684
877
                        if (mem is IField)
685
 
                                return Editor.GetPositionFromLineColumn (mem.Location.Line, mem.Location.Column);
686
 
                        else if (mem != null)
687
 
                                return Editor.GetPositionFromLineColumn (mem.BodyRegion.Start.Line, mem.BodyRegion.Start.Column);
688
 
                        else
689
 
                                return 0;
 
878
                                return textEditorData.Document.LocationToOffset (mem.Location.Line, mem.Location.Column);
 
879
                        if (mem != null)
 
880
                                return textEditorData.Document.LocationToOffset (mem.BodyRegion.Start.Line, mem.BodyRegion.Start.Column);
 
881
                        return 0;
690
882
                }
691
883
 
692
 
                IMember GetMemberAtPosition (int pos)
693
 
                {
694
 
                        int lin, col;
695
 
                        Editor.GetLineColumnFromPosition (pos, out lin, out col);
696
 
                        if (Document.ParsedDocument != null) {
697
 
                                foreach (IType t in Document.ParsedDocument.CompilationUnit.Types) {
698
 
                                        if (t.BodyRegion.Contains (lin, col)) {
699
 
                                                IMember mem = GetMemberAtPosition (t, lin, col);
700
 
                                                if (mem != null)
701
 
                                                        return mem;
702
 
                                                else
703
 
                                                        return t;
704
 
                                        }
705
 
                                }
706
 
                        }
707
 
                        return null;
708
 
                }
709
 
                
710
 
                IMember GetMemberAtPosition (IType t, int lin, int col)
711
 
                {
712
 
                        foreach (IMember mem in t.Members) {
713
 
                                if (mem.BodyRegion.Contains (lin, col)) {
714
 
                                        if (mem is IType) {
715
 
                                                IMember tm = GetMemberAtPosition ((IType)mem, lin, col);
716
 
                                                if (tm != null)
717
 
                                                        return tm;
718
 
                                        }
719
 
                                        return mem;
720
 
                                }
721
 
                                else if (mem is IField && ((IField)mem).Location.Line == lin)
722
 
                                        return mem;
723
 
                        }
724
 
                        return null;
725
 
                }
726
 
                
727
884
                public override bool GetParameterCompletionCommandOffset (out int cpos)
728
885
                {
729
 
                        // Start calculating the parameter offset from the beginning of the
730
 
                        // current member, instead of the beginning of the file. 
731
 
                        cpos = Editor.CursorPosition - 1;
732
 
                        IMember mem = GetMemberAtPosition (cpos);
 
886
// Start calculating the parameter offset from the beginning of the
 
887
// current member, instead of the beginning of the file. 
 
888
                        cpos = textEditorData.Caret.Offset - 1;
 
889
                        IMember mem = Document.ParsedDocument.CompilationUnit.GetMemberAt (textEditorData.Caret.Line, textEditorData.Caret.Column);
733
890
                        if (mem == null || (mem is IType))
734
891
                                return false;
735
892
                        int startPos = GetMemberStartPosition (mem);
736
893
                        int parenDepth = 0;
737
894
                        int chevronDepth = 0;
738
895
                        while (cpos > startPos) {
739
 
                                char c = Editor.GetCharAt (cpos);
 
896
                                char c = textEditorData.GetCharAt (cpos);
740
897
                                if (c == ')')
741
898
                                        parenDepth++;
742
899
                                if (c == '>')
743
900
                                        chevronDepth++;
744
901
                                if (parenDepth == 0 && c == '(' || chevronDepth == 0 && c == '<') {
745
 
                                        int p = NRefactoryParameterDataProvider.GetCurrentParameterIndex (Editor, cpos + 1, startPos);
 
902
                                        int p = NRefactoryParameterDataProvider.GetCurrentParameterIndex (CompletionWidget, cpos + 1, startPos);
746
903
                                        if (p != -1) {
747
904
                                                cpos++;
748
905
                                                return true;
762
919
                public ICSharpCode.NRefactory.Ast.CompilationUnit ParsedUnit { get; set; }
763
920
                NRefactoryResolver CreateResolver ()
764
921
                {
765
 
                        NRefactoryResolver result = new NRefactoryResolver (dom, Document.CompilationUnit, ICSharpCode.NRefactory.SupportedLanguage.CSharp, Editor, Document.FileName);
 
922
                        NRefactoryResolver result = new NRefactoryResolver (dom, Document.CompilationUnit, ICSharpCode.NRefactory.SupportedLanguage.CSharp, textEditorData, Document.FileName);
766
923
                        if (ParsedUnit != null)
767
924
                                result.SetupParsedCompilationUnit (ParsedUnit);
768
925
                        return result;
779
936
                        ExpressionResult result = FindExpression (dom, completionContext, -1);
780
937
                        if (result == null)
781
938
                                return null;
 
939
                        
782
940
 
783
941
                        //DomLocation location = new DomLocation (completionContext.TriggerLine, completionContext.TriggerLineOffset - 2);
784
942
                        NRefactoryResolver resolver = CreateResolver ();
785
943
 
786
944
                        if (result.ExpressionContext is ExpressionContext.TypeExpressionContext)
787
 
                                result.ExpressionContext = new NewCSharpExpressionFinder (dom).FindExactContextForNewCompletion (Editor, Document.CompilationUnit, Document.FileName, resolver.CallingType) ?? result.ExpressionContext;
788
 
 
 
945
                                result.ExpressionContext = new NewCSharpExpressionFinder (dom).FindExactContextForNewCompletion (textEditorData, Document.CompilationUnit, Document.FileName, resolver.CallingType) ?? result.ExpressionContext;
 
946
                        
789
947
                        switch (completionChar) {
790
948
                        case '<':
791
949
                                if (string.IsNullOrEmpty (result.Expression))
792
950
                                        return null;
793
 
                                return new NRefactoryTemplateParameterDataProvider (Editor, resolver, GetUsedNamespaces (), result, new DomLocation (completionContext.TriggerLine, completionContext.TriggerLineOffset));
 
951
                                return new NRefactoryTemplateParameterDataProvider (textEditorData, resolver, GetUsedNamespaces (), result, new DomLocation (completionContext.TriggerLine, completionContext.TriggerLineOffset));
794
952
                        case '[': {
795
953
                                ResolveResult resolveResult = resolver.Resolve (result, new DomLocation (completionContext.TriggerLine, completionContext.TriggerLineOffset));
796
954
                                if (resolveResult != null && !resolveResult.StaticResolve) {
797
955
                                        IType type = dom.GetType (resolveResult.ResolvedType);
798
956
                                        if (type != null)
799
 
                                                return new NRefactoryIndexerParameterDataProvider (Editor, type, result.Expression);
 
957
                                                return new NRefactoryIndexerParameterDataProvider (textEditorData, type, result.Expression);
800
958
                                }
801
959
                                return null;
802
960
                        }
806
964
                                        if (result.ExpressionContext == ExpressionContext.Attribute) {
807
965
                                                IReturnType returnType = resolveResult.ResolvedType;
808
966
                                                
809
 
                                                
810
967
                                                IType type = resolver.SearchType (result.Expression.Trim () + "Attribute");
811
968
                                                if (type == null) 
812
969
                                                        type = resolver.SearchType (returnType);
813
970
                                                if (type != null && returnType != null && returnType.GenericArguments != null)
814
971
                                                        type = dom.CreateInstantiatedGenericType (type, returnType.GenericArguments);
815
 
                                                return new NRefactoryParameterDataProvider (Editor, resolver, type);
 
972
                                                return new NRefactoryParameterDataProvider (textEditorData, resolver, type);
816
973
                                        }
817
974
                                        
818
975
//                                      System.Console.WriteLine("resolveResult:" + resolveResult);
823
980
                                                IType type = resolver.SearchType (returnType);
824
981
                                                if (type != null && returnType.GenericArguments != null)
825
982
                                                        type = dom.CreateInstantiatedGenericType (type, returnType.GenericArguments);
826
 
                                                return new NRefactoryParameterDataProvider (Editor, resolver, type);
 
983
                                                return new NRefactoryParameterDataProvider (textEditorData, resolver, type);
827
984
                                        }
828
985
                                        
829
986
                                        if (resolveResult is MethodResolveResult)
830
 
                                                return new NRefactoryParameterDataProvider (Editor, resolver, resolveResult as MethodResolveResult);
 
987
                                                return new NRefactoryParameterDataProvider (textEditorData, resolver, resolveResult as MethodResolveResult);
831
988
                                        if (result.ExpressionContext == ExpressionContext.BaseConstructorCall) {
832
989
                                                if (resolveResult is ThisResolveResult)
833
 
                                                        return new NRefactoryParameterDataProvider (Editor, resolver, resolveResult as ThisResolveResult);
 
990
                                                        return new NRefactoryParameterDataProvider (textEditorData, resolver, resolveResult as ThisResolveResult);
834
991
                                                if (resolveResult is BaseResolveResult)
835
 
                                                        return new NRefactoryParameterDataProvider (Editor, resolver, resolveResult as BaseResolveResult);
 
992
                                                        return new NRefactoryParameterDataProvider (textEditorData, resolver, resolveResult as BaseResolveResult);
836
993
                                        }
837
994
                                        IType resolvedType = resolver.SearchType (resolveResult.ResolvedType);
838
995
                                        if (resolvedType != null && resolvedType.ClassType == ClassType.Delegate) {
839
 
                                                return new NRefactoryParameterDataProvider (Editor, result.Expression, resolvedType);
 
996
                                                return new NRefactoryParameterDataProvider (textEditorData, result.Expression, resolvedType);
840
997
                                        }
841
998
                                }
842
999
                                break;
923
1080
                                                        break;
924
1081
                                                token = token.Trim ();
925
1082
                                                if (Char.IsLetterOrDigit (token[0]) || token[0] == '_') {
926
 
                                                        IType baseType = dom.SearchType (Document.CompilationUnit, token);
 
1083
                                                        IType baseType = dom.SearchType (Document.CompilationUnit, cls, result.Region.Start, token);
927
1084
                                                        if (baseType != null) {
928
1085
                                                                if (baseType.ClassType != ClassType.Interface)
929
1086
                                                                        isInterface = true;
936
1093
                                                if (type != null && (type.IsStatic || type.IsSealed || baseTypeNames.Contains (type.Name) || isInterface && type.ClassType != ClassType.Interface)) {
937
1094
                                                        continue;
938
1095
                                                }
 
1096
                                                if (o is Namespace && !namespaceList.Any (ns => ns.StartsWith (((Namespace)o).FullName)))
 
1097
                                                        continue;
939
1098
                                                col.Add (o);
940
1099
                                        }
941
1100
                                        // Add inner classes
961
1120
                                
962
1121
                                {
963
1122
                                        CompletionDataList completionList = new ProjectDomCompletionDataList ();
964
 
                                        ExpressionResult expressionResult = FindExpression (dom, completionContext, wordStart - Editor.CursorPosition);
 
1123
                                        ExpressionResult expressionResult = FindExpression (dom, completionContext, wordStart - textEditorData.Caret.Offset);
965
1124
                                        NRefactoryResolver resolver = CreateResolver ();
966
1125
                                        ResolveResult resolveResult = resolver.Resolve (expressionResult, new DomLocation (completionContext.TriggerLine, completionContext.TriggerLineOffset));
967
1126
                                        if (resolveResult != null && resolveResult.ResolvedType != null) {
968
1127
                                                CompletionDataCollector col = new CompletionDataCollector (dom, completionList, Document.CompilationUnit, resolver.CallingType, location);
969
1128
                                                IType foundType = null;
970
1129
                                                if (word == "as") {
971
 
                                                        ExpressionContext exactContext = new NewCSharpExpressionFinder (dom).FindExactContextForAsCompletion (Editor, Document.CompilationUnit, Document.FileName, resolver.CallingType);
 
1130
                                                        ExpressionContext exactContext = new NewCSharpExpressionFinder (dom).FindExactContextForAsCompletion (textEditorData, Document.CompilationUnit, Document.FileName, resolver.CallingType);
972
1131
                                                        if (exactContext is ExpressionContext.TypeExpressionContext) {
973
1132
                                                                foundType = resolver.SearchType (((ExpressionContext.TypeExpressionContext)exactContext).Type);
974
1133
                                                                AddAsCompletionData (col, foundType);
1023
1182
                                                break;
1024
1183
                                }
1025
1184
                                IType overrideCls = NRefactoryResolver.GetTypeAtCursor (Document.CompilationUnit, Document.FileName, new DomLocation (completionContext.TriggerLine, completionContext.TriggerLineOffset));
 
1185
                                if (overrideCls == null)
 
1186
                                        overrideCls = NRefactoryResolver.GetTypeAtCursor (Document.CompilationUnit, Document.FileName, new DomLocation (completionContext.TriggerLine - 1, 1));
1026
1187
                                if (overrideCls != null && (overrideCls.ClassType == ClassType.Class || overrideCls.ClassType == ClassType.Struct)) {
1027
 
                                        string modifiers = Editor.GetText (firstMod, wordStart);
 
1188
                                        string modifiers = textEditorData.GetTextBetween (firstMod, wordStart);
1028
1189
                                        return GetOverrideCompletionData (completionContext, overrideCls, modifiers);
1029
1190
                                }
1030
1191
                                return null;
1044
1205
                                }
1045
1206
                                overrideCls = NRefactoryResolver.GetTypeAtCursor (Document.CompilationUnit, Document.FileName, new DomLocation (completionContext.TriggerLine, completionContext.TriggerLineOffset));
1046
1207
                                if (overrideCls != null && (overrideCls.ClassType == ClassType.Class || overrideCls.ClassType == ClassType.Struct)) {
1047
 
                                        string modifiers = Editor.GetText (firstMod, wordStart);
 
1208
                                        string modifiers = textEditorData.GetTextBetween (firstMod, wordStart);
1048
1209
                                        return GetPartialCompletionData (completionContext, overrideCls, modifiers);
1049
1210
                                }
1050
1211
                                return null;
1051
1212
                                
1052
1213
                        case "new":
1053
 
                                IType callingType = NRefactoryResolver.GetTypeAtCursor (Document.CompilationUnit, Document.FileName, new DomLocation (Editor.CursorLine, Editor.CursorColumn));
1054
 
                                ExpressionContext newExactContext = new NewCSharpExpressionFinder (dom).FindExactContextForNewCompletion (Editor, Document.CompilationUnit, Document.FileName, callingType);
 
1214
                                IType callingType = NRefactoryResolver.GetTypeAtCursor (Document.CompilationUnit, Document.FileName, new DomLocation (textEditorData.Caret.Line, textEditorData.Caret.Column));
 
1215
                                ExpressionContext newExactContext = new NewCSharpExpressionFinder (dom).FindExactContextForNewCompletion (textEditorData, Document.CompilationUnit, Document.FileName, callingType);
1055
1216
                                if (newExactContext is ExpressionContext.TypeExpressionContext)
1056
1217
                                        return CreateTypeCompletionData (location, callingType, newExactContext, ((ExpressionContext.TypeExpressionContext)newExactContext).Type, ((ExpressionContext.TypeExpressionContext)newExactContext).UnresolvedType);
1057
1218
                                if (newExactContext == null) {
1068
1229
                                                        return CreateTypeCompletionData (location, callingType, newExactContext, null, returnType);
1069
1230
                                        }
1070
1231
                                }
1071
 
                                
1072
1232
                                return CreateCtrlSpaceCompletionData (completionContext, null);
1073
1233
                        case "if":
1074
1234
                        case "elif":
1124
1284
                                return null;
1125
1285
                        
1126
1286
                        do {
1127
 
                                c = Editor.GetCharAt (--i);
 
1287
                                c = textEditorData.GetCharAt (--i);
1128
1288
                        } while (i > 0 && char.IsWhiteSpace (c) && (allowLineChange ? true : c != '\n'));
1129
1289
                        
1130
1290
                        if (i == 0)
1136
1296
                        int endOffset = i + 1;
1137
1297
                        
1138
1298
                        do {
1139
 
                                c = Editor.GetCharAt (i - 1);
 
1299
                                c = textEditorData.GetCharAt (i - 1);
1140
1300
                                if (!(char.IsLetterOrDigit (c) || c == '_'))
1141
1301
                                        break;
1142
1302
                                
1143
1303
                                i--;
1144
1304
                        } while (i > 0);
1145
1305
                        
1146
 
                        return Editor.GetText (i, endOffset);
 
1306
                        return textEditorData.GetTextBetween (i, endOffset);
1147
1307
                }
1148
1308
                
1149
1309
                public override ICompletionDataList CodeCompletionCommand (CodeCompletionContext completionContext)
1151
1311
                        if (stateTracker.Engine.IsInsidePreprocessorDirective || stateTracker.Engine.IsInsideOrdinaryCommentOrString || stateTracker.Engine.IsInsideDocLineComment)
1152
1312
                                return null;
1153
1313
                        int pos = completionContext.TriggerOffset;
1154
 
                        string txt = Editor.GetText (pos - 1, pos);
1155
 
                        if (txt.Length > 0) {
 
1314
                        if (pos > 0) {
 
1315
                                char ch = textEditorData.GetCharAt (pos - 1);
1156
1316
                                int triggerWordLength = 0; 
1157
1317
                                tryToForceCompletion = true;
1158
 
                                ICompletionDataList cp = this.HandleCodeCompletion (completionContext, txt[0], ref triggerWordLength);
 
1318
                                ICompletionDataList cp = this.HandleCodeCompletion (completionContext, ch, ref triggerWordLength);
1159
1319
                                tryToForceCompletion = false;
1160
1320
                                if (cp != null) {
1161
1321
                                        ((CompletionDataList)cp).AutoCompleteUniqueMatch = true;
1162
1322
                                        return cp;
1163
1323
                                }
1164
1324
                        }
1165
 
 
1166
1325
                        ExpressionResult result = FindExpression (dom, completionContext);
1167
1326
                                                
1168
1327
                        if (result == null)
1193
1352
                        }
1194
1353
                        
1195
1354
                        Dictionary<string, List<MemberCompletionData>> data = new Dictionary<string, List<MemberCompletionData>> ();
 
1355
                        HashSet<string> namespacesInList = new HashSet<string> ();
 
1356
                        
1196
1357
                        HashSet<string> namespacesInScope = new HashSet<string> ();
1197
1358
                        internal static CSharpAmbience ambience = new CSharpAmbience ();
1198
 
                        DomLocation location;
 
1359
//                      DomLocation location;
1199
1360
                        ICompilationUnit unit;
1200
1361
                        IType declaringType;
1201
1362
                        List<IType> inheritanceTree;
1238
1399
                                        hideExtensionParameter = value;
1239
1400
                                }
1240
1401
                        }
1241
 
                        public class NegateKeyHandler : ICompletionKeyHandler
 
1402
/*                      public class NegateKeyHandler : ICompletionKeyHandler
1242
1403
                        {
1243
1404
                                public bool ProcessKey (CompletionListWindow window, Gdk.Key key, char keyChar, Gdk.ModifierType modifier, out KeyActions keyAction)
1244
1405
                                {
1273
1434
                                        
1274
1435
                                        return true;
1275
1436
                                }
1276
 
                        }
 
1437
                        }*/
1277
1438
                        
1278
1439
                        public CompletionDataCollector (ProjectDom dom, CompletionDataList completionList, ICompilationUnit unit, IType declaringType, DomLocation location)
1279
1440
                        {
1281
1442
                                this.unit = unit;
1282
1443
                                this.dom = dom;
1283
1444
                                this.FullyQualify = false;
1284
 
                                this.location = location;
 
1445
//                              this.location = location;
1285
1446
                                this.declaringType = declaringType;
1286
 
                                completionList.AddKeyHandler (new NegateKeyHandler ());
 
1447
//                              completionList.AddKeyHandler (new NegateKeyHandler ());
1287
1448
                                // Get a list of all namespaces in scope
1288
1449
                                if (unit != null) {
1289
1450
                                        foreach (IUsing u in unit.Usings) {
1352
1513
                                MemberCompletionData newData = new MemberCompletionData (member as INode, flags);
1353
1514
                                newData.HideExtensionParameter = HideExtensionParameter;
1354
1515
                                string memberKey = newData.CompletionText;
 
1516
                                if (memberKey == null)
 
1517
                                        return null;
1355
1518
                                if (member is IMember) {
1356
1519
                                        newData.CompletionCategory = GetCompletionCategory (((IMember)member).DeclaringType);
1357
1520
                                }
1358
1521
                                List<MemberCompletionData> existingData;
1359
 
                                if (data.TryGetValue (memberKey, out existingData)) {
1360
 
                                        if (existingData == null)
1361
 
                                                return null;
 
1522
                                data.TryGetValue (memberKey, out existingData);
 
1523
                                
 
1524
                                if (existingData != null) {
1362
1525
                                        IBaseMember a = member as IBaseMember;
1363
1526
                                        foreach (MemberCompletionData md in existingData) {
1364
1527
                                                IBaseMember b = md.Member as IBaseMember;
1382
1545
                        
1383
1546
                        public CompletionData Add (string name, string icon)
1384
1547
                        {
1385
 
                                if (data.ContainsKey (name))
1386
 
                                        return null;
1387
 
                                data.Add (name, null);
1388
 
                                
 
1548
                                if (!data.ContainsKey (name))
 
1549
                                        data.Add (name, null);
1389
1550
                                return CompletionList.Add (name, icon);
1390
1551
                        }
1391
1552
                        
1398
1559
                        {
1399
1560
                                Namespace ns = obj as Namespace;
1400
1561
                                if (ns != null) {
1401
 
                                        if (data.ContainsKey (ns.Name))
 
1562
                                        if (!data.ContainsKey (ns.Name))
 
1563
                                                data.Add (ns.Name, null);
 
1564
                                        if (namespacesInList.Contains (ns.Name)) {
1402
1565
                                                return null;
1403
 
                                        data.Add (ns.Name, null);
 
1566
                                        }
 
1567
                                        namespacesInList.Add (ns.Name);
1404
1568
                                        return CompletionList.Add (ns.Name, ns.StockIcon, ns.Documentation);
1405
1569
                                }
1406
1570
                                
1410
1574
                                        bool foundNamespace = IsNamespaceInScope (rt.Namespace);
1411
1575
                                        if (FullyQualify || !foundNamespace && (NamePrefix.Length == 0 || !rt.Namespace.StartsWith (NamePrefix)) && !rt.Namespace.EndsWith ("." + NamePrefix))
1412
1576
                                                flags |= OutputFlags.UseFullName;
 
1577
                                        IType resolvedType = dom.GetType (rt);
 
1578
                                        if (inheritanceTree == null && declaringType != null)
 
1579
                                                inheritanceTree = new List<IType>(dom.GetInheritanceTree (declaringType));
 
1580
                                        if (resolvedType != null && resolvedType.DeclaringType != null && inheritanceTree != null && inheritanceTree.Any (t => resolvedType.DeclaringType.DecoratedFullName == t.DecoratedFullName)) {
 
1581
                                                return CompletionList.Add (rt.Name, "md-class");
 
1582
                                        }
1413
1583
                                        string returnTypeString = ambience.GetString (rt, flags);
1414
 
                                        if (data.ContainsKey (returnTypeString))
1415
 
                                                return null;
1416
 
                                        data.Add (returnTypeString, null);
 
1584
                                        
 
1585
                                        if (!data.ContainsKey (returnTypeString))
 
1586
                                                data.Add (returnTypeString, null);
1417
1587
                                        return CompletionList.Add (returnTypeString, "md-class");
1418
1588
                                }
1419
1589
                                
1428
1598
                                
1429
1599
                                if (obj is string) {
1430
1600
                                        string str = (string)obj;
1431
 
                                        if (data.ContainsKey (str))
1432
 
                                                return null;
1433
 
                                        data.Add (str, null);
 
1601
                                        if (!data.ContainsKey (str))
 
1602
                                                data.Add (str, null);
1434
1603
                                        return CompletionList.Add (str, "md-literal");
1435
1604
                                }
1436
1605
                                return null;
1454
1623
                        CompletionDataCollector col = new CompletionDataCollector (dom, result, Document.CompilationUnit, resolver != null ? resolver.CallingType : null, location);
1455
1624
                        col.HideExtensionParameter = !resolveResult.StaticResolve;
1456
1625
                        col.NamePrefix = expressionResult.Expression;
 
1626
                        bool showOnlyTypes = expressionResult.Contexts.Any (ctx => ctx == ExpressionContext.InheritableType || ctx == ExpressionContext.Constraints);
1457
1627
                        if (objects != null) {
1458
1628
                                foreach (object obj in objects) {
1459
1629
                                        if (expressionResult.ExpressionContext != null && expressionResult.ExpressionContext.FilterEntry (obj))
1460
1630
                                                continue;
1461
1631
                                        if (expressionResult.ExpressionContext == ExpressionContext.NamespaceNameExcepted && !(obj is Namespace))
1462
1632
                                                continue;
 
1633
                                        if (showOnlyTypes && !(obj is IType))
 
1634
                                                continue;
1463
1635
                                        CompletionData data = col.Add (obj);
1464
1636
                                        if (data != null && expressionResult.ExpressionContext == ExpressionContext.Attribute && data.CompletionText != null && data.CompletionText.EndsWith ("Attribute")) {
1465
1637
                                                string newText = data.CompletionText.Substring (0, data.CompletionText.Length - "Attribute".Length);
1470
1642
                        
1471
1643
                        return result;
1472
1644
                }
1473
 
                
1474
 
                static string GetLineWhiteSpace (string line)
1475
 
                {
1476
 
                        int trimmedLength = line.TrimStart ().Length;
1477
 
                        return line.Substring (0, line.Length - trimmedLength);
1478
 
                }
1479
 
                
 
1645
 
1480
1646
                void AddVirtuals (CodeCompletionContext ctx, Dictionary<string, bool> alreadyInserted, CompletionDataList completionList, IType type, string modifiers, IReturnType curType)
1481
1647
                {
1482
1648
                        if (curType == null)
1483
1649
                                return;
1484
 
                        IType searchType = dom.SearchType ((MonoDevelop.Projects.Dom.INode)type ?? Document.CompilationUnit, curType);
 
1650
                        IType searchType = dom.SearchType (Document.CompilationUnit, type, new DomLocation (ctx.TriggerLine, ctx.TriggerLineOffset + 1), curType);
1485
1651
                        //System.Console.WriteLine("Add Virtuals for:" + searchType + " / " + curType);
1486
1652
                        if (searchType == null)
1487
1653
                                return;
1505
1671
                                }
1506
1672
                        }
1507
1673
                        CompletionDataCollector col = new CompletionDataCollector (dom, completionList, Document.CompilationUnit, searchType, DomLocation.Empty);
1508
 
                        
1509
 
                        List<IType> inheritanceTree = new List<IType> (this.dom.GetInheritanceTree (searchType));
1510
 
                        inheritanceTree.Sort ((l, r) => l.ClassType == r.ClassType ? 0 : (l.ClassType == ClassType.Interface ? 1 : (r.ClassType == ClassType.Interface ? -1 : 0)));
1511
 
                        foreach (IType t in inheritanceTree) {
 
1674
                        var inheritanceTree = new List<IType> (this.dom.GetInheritanceTree (searchType));
 
1675
                        var sortedTree = inheritanceTree.Where (c => c.ClassType != ClassType.Interface).Concat (inheritanceTree.Where (c => c.ClassType == ClassType.Interface));
 
1676
                        foreach (IType t in sortedTree) {
1512
1677
                                foreach (IMember m in t.Members) {
1513
 
                                        if (!m.IsAccessibleFrom (dom, type, type, true) || m.IsSpecialName)
 
1678
                                        if (/*!m.IsAccessibleFrom (dom, type, type, true) ||*/ m.IsSpecialName)
1514
1679
                                                continue;
1515
 
                                        //System.Console.WriteLine ("scan:" + m);
1516
1680
                                        //if (m.IsSpecialName || (m.IsInternal && !m.IsProtectedOrInternal) || && searchType.SourceProject != Document.Project)
1517
1681
                                        //      continue;
1518
1682
                                        if (t.ClassType == ClassType.Interface || (isInterface || m.IsVirtual || m.IsAbstract) && !m.IsSealed && (includeOverriden || !type.HasOverriden (m))) {
1564
1728
                        if (returnType != null)
1565
1729
                                type = dom.GetType (returnType);
1566
1730
                        if (type == null)
1567
 
                                type = dom.SearchType ((MonoDevelop.Projects.Dom.INode)Document.CompilationUnit ?? callingType, returnTypeUnresolved);
 
1731
                                type = dom.SearchType (Document.CompilationUnit, callingType, location, returnTypeUnresolved);
 
1732
                        
 
1733
                        // special handling for nullable types: Bug 674516 - new completion for nullables should not include "Nullable"
 
1734
                        if (type is InstantiatedType && ((InstantiatedType)type).UninstantiatedType.FullName == "System.Nullable" && ((InstantiatedType)type).GenericParameters.Count == 1) {
 
1735
                                var genericParameter = ((InstantiatedType)type).GenericParameters [0];
 
1736
                                returnType = returnTypeUnresolved = Document.CompilationUnit.ShortenTypeName (genericParameter, location);
 
1737
                                type = dom.SearchType (Document.CompilationUnit, callingType, location, genericParameter);
 
1738
                        }
1568
1739
                        
1569
1740
                        if (type == null || !(type.IsAbstract || type.ClassType == ClassType.Interface)) {
1570
1741
                                if (type == null || type.ConstructorCount == 0 || type.Methods.Any (c => c.IsConstructor && c.IsAccessibleFrom (dom, callingType, type, callingType != null && dom.GetInheritanceTree (callingType).Any (x => x.FullName == type.FullName)))) {
1572
1743
                                                col.FullyQualify = true;
1573
1744
                                                CompletionData unresovedCompletionData = col.Add (returnTypeUnresolved);
1574
1745
                                                col.FullyQualify = false;
1575
 
                                                result.DefaultCompletionString = StripGenerics (unresovedCompletionData.CompletionText);
 
1746
                                                // don't set default completion string for arrays, since it interferes with: 
 
1747
                                                // string[] arr = new string[] vs new { "a"}
 
1748
                                                if (returnTypeUnresolved.ArrayDimensions == 0)
 
1749
                                                        result.DefaultCompletionString = StripGenerics (unresovedCompletionData.CompletionText);
1576
1750
                                        } else {
1577
1751
                                                CompletionData unresovedCompletionData = col.Add (returnType);
1578
 
                                                result.DefaultCompletionString = StripGenerics (unresovedCompletionData.CompletionText);
 
1752
                                                if (returnType.ArrayDimensions == 0)
 
1753
                                                        result.DefaultCompletionString = StripGenerics (unresovedCompletionData.CompletionText);
1579
1754
                                        }
1580
1755
                                }
1581
1756
                        }
 
1757
                        
1582
1758
                        //                              if (tce != null && tce.Type != null) {
1583
1759
                        //                                      result.DefaultCompletionString = StripGenerics (col.AddCompletionData (result, tce.Type).CompletionString);
1584
1760
                        //                              } 
1585
1761
                        //                      else {
1586
1762
                        //                      }
1587
 
 
1588
1763
                        if (type == null)
1589
1764
                                return result;
1590
 
                        HashSet<string> usedNamespaces = new HashSet<string> (GetUsedNamespaces ());
 
1765
                        HashSet<string > usedNamespaces = new HashSet<string> (GetUsedNamespaces ());
1591
1766
                        if (type.FullName == DomReturnType.Object.FullName) 
1592
1767
                                AddPrimitiveTypes (col);
 
1768
                        
1593
1769
                        foreach (IType curType in dom.GetSubclasses (type)) {
1594
1770
                                if (context != null && context.FilterEntry (curType))
1595
1771
                                        continue;
1619
1795
                                        }
1620
1796
                                }
1621
1797
                        }
 
1798
                        result.AutoCompleteEmptyMatch = true;
1622
1799
                        return result;
1623
1800
                }
1624
1801
                
1724
1901
                
1725
1902
                CompletionDataList CreateCtrlSpaceCompletionData (CodeCompletionContext ctx, ExpressionResult expressionResult)
1726
1903
                {
1727
 
                        //      Console.WriteLine (Environment.StackTrace);
1728
 
                        //      Console.WriteLine ("---------");
1729
1904
                        NRefactoryResolver resolver = CreateResolver ();
1730
 
                        
1731
1905
                        DomLocation cursorLocation = new DomLocation (ctx.TriggerLine, ctx.TriggerLineOffset);
1732
1906
                        resolver.SetupResolver (cursorLocation);
1733
1907
                        CompletionDataList result = new ProjectDomCompletionDataList ();
1753
1927
                        } else if (expressionResult.ExpressionContext == ExpressionContext.InterfacePropertyDeclaration) {
1754
1928
                                col.Add ("get", "md-keyword");
1755
1929
                                col.Add ("set", "md-keyword");
 
1930
                        } else if (expressionResult.ExpressionContext == ExpressionContext.ConstraintsStart) {
 
1931
                                col.Add ("where", "md-keyword");
 
1932
                        } else if (expressionResult.ExpressionContext == ExpressionContext.Constraints) {
 
1933
                                col.Add ("new", "md-keyword");
 
1934
                                col.Add ("class", "md-keyword");
 
1935
                                col.Add ("struct", "md-keyword");
 
1936
                                AddPrimitiveTypes (col);
 
1937
                                resolver.AddAccessibleCodeCompletionData (expressionResult.ExpressionContext, col);
1756
1938
                        } else if (expressionResult.ExpressionContext == ExpressionContext.Attribute) {
1757
1939
                                col.Add ("assembly", "md-keyword");
1758
1940
                                col.Add ("module", "md-keyword");
1793
1975
                                AddNRefactoryKeywords (col, ICSharpCode.NRefactory.Parser.CSharp.Tokens.GlobalLevel);
1794
1976
                                CodeTemplateService.AddCompletionDataForMime ("text/x-csharp", result);
1795
1977
                        } else if (expressionResult.ExpressionContext == ExpressionContext.ObjectInitializer) {
1796
 
                                ExpressionContext exactContext = new NewCSharpExpressionFinder (dom).FindExactContextForObjectInitializer (Editor, resolver.Unit, Document.FileName, resolver.CallingType);
 
1978
                                ExpressionContext exactContext = new NewCSharpExpressionFinder (dom).FindExactContextForObjectInitializer (textEditorData, resolver.Unit, Document.FileName, resolver.CallingType);
1797
1979
                                if (exactContext is ExpressionContext.TypeExpressionContext) {
1798
1980
                                        IReturnType objectInitializer = ((ExpressionContext.TypeExpressionContext)exactContext).UnresolvedType;
1799
1981
                                        if (objectInitializer.ArrayDimensions > 0 || objectInitializer.PointerNestingLevel > 0) {
1800
1982
                                                col.Add ("global", "md-keyword");
 
1983
                                                col.Add ("new", "md-keyword");
1801
1984
                                                AddPrimitiveTypes (col);
1802
1985
                                                resolver.AddAccessibleCodeCompletionData (expressionResult.ExpressionContext, col);
1803
1986
                                                return result;
1815
1998
                                                                        col.Add (property);
1816
1999
                                                                }
1817
2000
                                                        }
 
2001
                                                        foreach (var field in type.Fields) {
 
2002
                                                                if (field.IsAccessibleFrom (dom, resolver.CallingType, resolver.CallingMember, includeProtected)) {
 
2003
                                                                        col.Add (field);
 
2004
                                                                }
 
2005
                                                        }
1818
2006
                                                }
1819
2007
                                        }
1820
2008
                                }
1824
2012
                        } else if (expressionResult.ExpressionContext == ExpressionContext.AttributeArguments) {
1825
2013
                                col.Add ("global", "md-keyword");
1826
2014
                                AddPrimitiveTypes (col);
1827
 
                                string attributeName = NewCSharpExpressionFinder.FindAttributeName (Editor, Document.CompilationUnit, Document.FileName);
 
2015
                                string attributeName = NewCSharpExpressionFinder.FindAttributeName (textEditorData, Document.CompilationUnit, Document.FileName);
1828
2016
                                if (attributeName != null) {
1829
2017
                                        IType type = resolver.SearchType (attributeName + "Attribute");
1830
2018
                                        if (type == null) 
1831
2019
                                                type = resolver.SearchType (attributeName);
1832
2020
                                        if (type != null) {
1833
 
                                                foreach (IProperty property in type.Properties) {
 
2021
                                                foreach (var property in type.Properties) {
1834
2022
                                                        col.Add (property);
1835
2023
                                                }
 
2024
                                                foreach (var field in type.Fields) {
 
2025
                                                        if (field.IsPublic)
 
2026
                                                                col.Add (field);
 
2027
                                                }
1836
2028
                                        }
1837
2029
                                }
 
2030
                                resolver.AddAccessibleCodeCompletionData (expressionResult.ExpressionContext, col);
1838
2031
                        } else if (expressionResult.ExpressionContext == ExpressionContext.IdentifierExpected) {
1839
2032
                                if (!string.IsNullOrEmpty (expressionResult.Expression))
1840
2033
                                        expressionResult.Expression = expressionResult.Expression.Trim ();
1886
2079
                                col.Add ("global", "md-keyword");
1887
2080
                                AddPrimitiveTypes (col);
1888
2081
                                resolver.AddAccessibleCodeCompletionData (expressionResult.ExpressionContext, col);
 
2082
                        } else if (expressionResult.ExpressionContext == ExpressionContext.ForeachInToken) {
 
2083
                                col.Add ("in", "md-keyword");
1889
2084
                        } else {
1890
2085
                                col.Add ("global", "md-keyword");
1891
2086
                                col.Add ("var", "md-keyword");
1921
2116
                                var declaringType = resolver.CallingType;
1922
2117
                                if (declaringType != null && dom != null) {
1923
2118
                                        foreach (IType t in new List<IType>(dom.GetInheritanceTree (declaringType))) {
1924
 
                                                if (t.SearchMember (type.Name, true).Any (m => m.MemberType != MemberType.Type)) {
 
2119
                                                if (t.SearchMember (type.Name, true).Any (m => m.MemberType != MonoDevelop.Projects.Dom.MemberType.Type)) {
1925
2120
                                                        flags |= OutputFlags.UseFullName;
1926
2121
                                                        break;
1927
2122
                                                }
2143
2338
                        return cp;
2144
2339
                }
2145
2340
                #endregion
 
2341
                
 
2342
                
 
2343
                #region IPathedDocument implementation
 
2344
                public event EventHandler<DocumentPathChangedEventArgs> PathChanged;
 
2345
 
 
2346
                protected virtual void OnPathChanged (DocumentPathChangedEventArgs e)
 
2347
                {
 
2348
                        EventHandler<DocumentPathChangedEventArgs> handler = this.PathChanged;
 
2349
                        if (handler != null)
 
2350
                                handler (this, e);
 
2351
                }
 
2352
                
 
2353
                public class DataProvider : DropDownBoxListWindow.IListDataProvider
 
2354
                {
 
2355
                        object tag;
 
2356
                        Ambience amb;
 
2357
                        List<IMember> memberList = new List<IMember> ();
 
2358
                        
 
2359
                        Document Document {
 
2360
                                get;
 
2361
                                set;
 
2362
                        }
 
2363
                        
 
2364
                        public DataProvider (Document doc, object tag, Ambience amb)
 
2365
                        {
 
2366
                                this.Document = doc;
 
2367
                                this.tag = ((INode)tag).Parent;
 
2368
                                this.amb = amb;
 
2369
                                Reset ();
 
2370
                        }
 
2371
                        
 
2372
                        #region IListDataProvider implementation
 
2373
                        public void Reset ()
 
2374
                        {
 
2375
                                memberList.Clear ();
 
2376
                                if (tag is ICompilationUnit) {
 
2377
                                        Stack<IType> types = new Stack<IType> (((ICompilationUnit)tag).Types);
 
2378
                                        while (types.Count > 0) {
 
2379
                                                IType type = types.Pop ();
 
2380
                                                memberList.Add (type);
 
2381
                                                foreach (IType innerType in type.InnerTypes)
 
2382
                                                        types.Push (innerType);
 
2383
                                        }
 
2384
                                } else  if (tag is IType) {
 
2385
                                        memberList.AddRange (((IType)tag).Members);
 
2386
                                }
 
2387
                                memberList.Sort ((x, y) => String.Compare (GetString (amb, x), GetString (amb, y), StringComparison.OrdinalIgnoreCase));
 
2388
                        }
 
2389
                        
 
2390
                        string GetString (Ambience amb, IMember x)
 
2391
                        {
 
2392
                                if (tag is ICompilationUnit)
 
2393
                                        return amb.GetString (x, OutputFlags.IncludeGenerics | OutputFlags.IncludeParameters | OutputFlags.UseFullInnerTypeName | OutputFlags.ReformatDelegates);
 
2394
                                return amb.GetString (x, OutputFlags.IncludeGenerics | OutputFlags.IncludeParameters | OutputFlags.ReformatDelegates);
 
2395
                        }
 
2396
                        
 
2397
                        public string GetText (int n)
 
2398
                        {
 
2399
                                return GetString (amb, memberList[n]);
 
2400
                        }
 
2401
 
 
2402
                        public Gdk.Pixbuf GetIcon (int n)
 
2403
                        {
 
2404
                                return ImageService.GetPixbuf (memberList[n].StockIcon, IconSize.Menu);
 
2405
                        }
 
2406
 
 
2407
                        public object GetTag (int n)
 
2408
                        {
 
2409
                                return memberList[n];
 
2410
                        }
 
2411
 
 
2412
                        public void ActivateItem (int n)
 
2413
                        {
 
2414
                                var member = memberList[n];
 
2415
                                MonoDevelop.Ide.Gui.Content.IExtensibleTextEditor extEditor = Document.GetContent<MonoDevelop.Ide.Gui.Content.IExtensibleTextEditor> ();
 
2416
                                if (extEditor != null)
 
2417
                                        extEditor.SetCaretTo (Math.Max (1, member.Location.Line), member.Location.Column);
 
2418
                        }
 
2419
 
 
2420
                        public int IconCount {
 
2421
                                get {
 
2422
                                        return memberList.Count;
 
2423
                                }
 
2424
                        }
 
2425
                        #endregion
 
2426
                }
 
2427
                
 
2428
                        
 
2429
                public class CompilationUnitDataProvider : DropDownBoxListWindow.IListDataProvider
 
2430
                {
 
2431
                        Document Document {
 
2432
                                get;
 
2433
                                set;
 
2434
                        }
 
2435
                        
 
2436
                        public CompilationUnitDataProvider (Document document)
 
2437
                        {
 
2438
                                this.Document = document;
 
2439
                        }
 
2440
                        
 
2441
                        #region IListDataProvider implementation
 
2442
                        public void Reset ()
 
2443
                        {
 
2444
                        }
 
2445
                        
 
2446
                        public string GetText (int n)
 
2447
                        {
 
2448
                                return Document.ParsedDocument.UserRegions.ElementAt (n).Name;
 
2449
                        }
 
2450
                        
 
2451
                        internal static Gdk.Pixbuf Pixbuf {
 
2452
                                get {
 
2453
                                        return ImageService.GetPixbuf (Gtk.Stock.Add, IconSize.Menu);
 
2454
                                }
 
2455
                        }
 
2456
                        
 
2457
                        public Gdk.Pixbuf GetIcon (int n)
 
2458
                        {
 
2459
                                return Pixbuf;
 
2460
                        }
 
2461
                        
 
2462
                        public object GetTag (int n)
 
2463
                        {
 
2464
                                return Document.ParsedDocument.UserRegions.ElementAt (n);
 
2465
                        }
 
2466
                        
 
2467
                        
 
2468
                        public void ActivateItem (int n)
 
2469
                        {
 
2470
                                var reg = Document.ParsedDocument.UserRegions.ElementAt (n);
 
2471
                                MonoDevelop.Ide.Gui.Content.IExtensibleTextEditor extEditor = Document.GetContent<MonoDevelop.Ide.Gui.Content.IExtensibleTextEditor> ();
 
2472
                                if (extEditor != null)
 
2473
                                        extEditor.SetCaretTo (Math.Max (1, reg.Region.Start.Line), reg.Region.Start.Column);
 
2474
                        }
 
2475
                        
 
2476
                        public int IconCount {
 
2477
                                get {
 
2478
                                        if (Document.ParsedDocument == null)
 
2479
                                                return 0;
 
2480
                                        return Document.ParsedDocument.UserRegions.Count ();
 
2481
                                }
 
2482
                        }
 
2483
                        
 
2484
                        #endregion
 
2485
                }
 
2486
                
 
2487
                public Gtk.Widget CreatePathWidget (int index)
 
2488
                {
 
2489
                        PathEntry[] path = CurrentPath;
 
2490
                        if (path == null || index < 0 || index >= path.Length)
 
2491
                                return null;
 
2492
                        var tag = path[index].Tag;
 
2493
                        DropDownBoxListWindow window = new DropDownBoxListWindow (tag is ICompilationUnit ? (DropDownBoxListWindow.IListDataProvider)new CompilationUnitDataProvider (Document) : new DataProvider (Document, tag, GetAmbience ()));
 
2494
                        window.SelectItem (path[index].Tag);
 
2495
                        return window;
 
2496
                }
 
2497
                
 
2498
                public PathEntry[] CurrentPath {
 
2499
                        get;
 
2500
                        private set;
 
2501
                }
 
2502
                
 
2503
                class CustomNode : MonoDevelop.Projects.Dom.AbstractNode
 
2504
                {
 
2505
                        public CustomNode (INode parent)
 
2506
                        {
 
2507
                                this.Parent = parent;
 
2508
                        }
 
2509
                }
 
2510
                
 
2511
                void UpdatePath (object sender, Mono.TextEditor.DocumentLocationEventArgs e)
 
2512
                {
 
2513
                        var unit = Document.CompilationUnit;
 
2514
                        if (unit == null)
 
2515
                                return;
 
2516
                        
 
2517
                        var loc = textEditorData.Caret.Location;
 
2518
                        IType type = unit.GetTypeAt (loc.Line, loc.Column);
 
2519
                        IMember member = type != null && type.ClassType != ClassType.Delegate ? type.GetMemberAt (loc.Line, loc.Column) : null;
 
2520
                        
 
2521
                        List<PathEntry> result = new List<PathEntry> ();
 
2522
                        var amb = GetAmbience ();
 
2523
                        INode node = member ?? type ?? (INode)unit;
 
2524
                        while (node != null) {
 
2525
                                PathEntry entry;
 
2526
                                if (node is ICompilationUnit) {
 
2527
                                        if (!Document.ParsedDocument.UserRegions.Any ())
 
2528
                                                break;
 
2529
                                        FoldingRegion reg = Document.ParsedDocument.UserRegions.Where (r => r.Region.Contains (loc.Line, loc.Column)).LastOrDefault ();
 
2530
                                        if (reg == null) {
 
2531
                                                entry = new PathEntry (GettextCatalog.GetString ("No region"));
 
2532
                                        } else {
 
2533
                                                entry = new PathEntry (CompilationUnitDataProvider.Pixbuf,
 
2534
                                                                       reg.Name);
 
2535
                                        }
 
2536
                                        entry.Position = EntryPosition.Right;
 
2537
                                } else {
 
2538
                                        entry = new PathEntry (ImageService.GetPixbuf (((IMember)node).StockIcon, IconSize.Menu), amb.GetString ((IMember)node, OutputFlags.IncludeGenerics | OutputFlags.IncludeParameters | OutputFlags.ReformatDelegates));
 
2539
                                }
 
2540
                                entry.Tag = node;
 
2541
                                result.Insert (0, entry);
 
2542
                                node = node.Parent;
 
2543
                        }
 
2544
                        PathEntry noSelection = null;
 
2545
                        if (type == null) {
 
2546
                                noSelection = new PathEntry (GettextCatalog.GetString ("No selection")) { Tag = new CustomNode (Document.CompilationUnit) };
 
2547
                        } else if (member == null && type.ClassType != ClassType.Delegate) 
 
2548
                                noSelection = new PathEntry (GettextCatalog.GetString ("No selection")) { Tag = new CustomNode (type) };
 
2549
                        if (noSelection != null) {
 
2550
/*                              if (result.Count > 0 && result[result.Count - 1].Tag is ICompilationUnit) {
 
2551
                                        result.Insert (result.Count - 1, noSelection);
 
2552
                                } else {*/
 
2553
                                        result.Add (noSelection);
 
2554
//                              }
 
2555
                        }
 
2556
                        var prev = CurrentPath;
 
2557
                        CurrentPath = result.ToArray ();
 
2558
                        OnPathChanged (new DocumentPathChangedEventArgs (prev));
 
2559
                }
 
2560
                #endregion
2146
2561
        }
2147
2562
}