Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/HeuristicLab.ExtLibs/HeuristicLab.NRefactory/5.5.0/NRefactory.CSharp-5.5.0/Completion/CSharpCompletionEngine.cs @ 17197

Last change on this file since 17197 was 11700, checked in by jkarder, 10 years ago

#2077: created branch and added first version

File size: 127.3 KB
Line 
1//
2// CSharpCompletionEngine.cs
3// 
4// Author:
5//       Mike KrÃŒger <mkrueger@xamarin.com>
6//
7// Copyright (c) 2011 Xamarin Inc. (http://xamarin.com)
8//
9// Permission is hereby granted, free of charge, to any person obtaining a copy
10// of this software and associated documentation files (the "Software"), to deal
11// in the Software without restriction, including without limitation the rights
12// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13// copies of the Software, and to permit persons to whom the Software is
14// furnished to do so, subject to the following conditions:
15//
16// The above copyright notice and this permission notice shall be included in
17// all copies or substantial portions of the Software.
18//
19// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25// THE SOFTWARE.
26using System;
27using System.Collections.Generic;
28using System.Linq;
29using System.Text;
30using ICSharpCode.NRefactory.Completion;
31using ICSharpCode.NRefactory.CSharp.Refactoring;
32using ICSharpCode.NRefactory.CSharp.Resolver;
33using ICSharpCode.NRefactory.Editor;
34using ICSharpCode.NRefactory.Semantics;
35using ICSharpCode.NRefactory.TypeSystem;
36using ICSharpCode.NRefactory.CSharp.TypeSystem;
37
38namespace ICSharpCode.NRefactory.CSharp.Completion
39{
40  public enum EditorBrowsableBehavior
41  {
42    Ignore,
43    Normal,
44    IncludeAdvanced
45  }
46
47  public class CompletionEngineCache
48  {
49    public List<INamespace>  namespaces;
50    public ICompletionData[] importCompletion;
51  }
52
53  public class CSharpCompletionEngine : CSharpCompletionEngineBase
54  {
55    internal ICompletionDataFactory factory;
56
57    #region Additional input properties
58
59    public CSharpFormattingOptions FormattingPolicy { get; set; }
60
61    public string EolMarker { get; set; }
62
63    public string IndentString { get; set; }
64
65    public bool AutomaticallyAddImports { get; set; }
66
67    public bool IncludeKeywordsInCompletionList { get; set; }
68
69    public EditorBrowsableBehavior EditorBrowsableBehavior { get; set; }
70
71    public CompletionEngineCache CompletionEngineCache { get; set; }
72
73    #endregion
74
75    #region Result properties
76
77    public bool AutoCompleteEmptyMatch;
78    /// <summary>
79    /// The auto complete empty match on curly bracket. (only taken into account when AutoCompleteEmptyMatch is true )
80    /// </summary>
81    public bool AutoCompleteEmptyMatchOnCurlyBracket = true;
82    public bool AutoSelect;
83    public string DefaultCompletionString;
84    public bool CloseOnSquareBrackets;
85    public readonly List<IMethod> PossibleDelegates = new List<IMethod>();
86
87    #endregion
88
89    public CSharpCompletionEngine(IDocument document, ICompletionContextProvider completionContextProvider, ICompletionDataFactory factory, IProjectContent content, CSharpTypeResolveContext ctx) : base(content, completionContextProvider, ctx)
90    {
91      if (document == null) {
92        throw new ArgumentNullException("document");
93      }
94      if (factory == null) {
95        throw new ArgumentNullException("factory");
96      }
97      this.document = document;
98      this.factory = factory;
99      // Set defaults for additional input properties
100      this.FormattingPolicy = FormattingOptionsFactory.CreateMono();
101      this.EolMarker = Environment.NewLine;
102      this.IncludeKeywordsInCompletionList = true;
103      EditorBrowsableBehavior = EditorBrowsableBehavior.IncludeAdvanced;
104      this.IndentString = "\t";
105    }
106
107    public bool TryGetCompletionWord(int offset, out int startPos, out int wordLength)
108    {
109      startPos = wordLength = 0;
110      int pos = offset - 1;
111      while (pos >= 0) {
112        char c = document.GetCharAt(pos);
113        if (!char.IsLetterOrDigit(c) && c != '_')
114          break;
115        pos--;
116      }
117      if (pos == -1)
118        return false;
119
120      pos++;
121      startPos = pos;
122
123      while (pos < document.TextLength) {
124        char c = document.GetCharAt(pos);
125        if (!char.IsLetterOrDigit(c) && c != '_')
126          break;
127        pos++;
128      }
129      wordLength = pos - startPos;
130      return true;
131    }
132
133    public IEnumerable<ICompletionData> GetCompletionData(int offset, bool controlSpace)
134    {
135      this.AutoCompleteEmptyMatch = true;
136      this.AutoSelect = true;
137      this.DefaultCompletionString = null;
138      SetOffset(offset);
139      if (offset > 0) {
140        char lastChar = document.GetCharAt(offset - 1);
141        bool isComplete = false;
142        var result = MagicKeyCompletion(lastChar, controlSpace, out isComplete) ?? Enumerable.Empty<ICompletionData>();
143        if (!isComplete && controlSpace && char.IsWhiteSpace(lastChar)) {
144          offset -= 2;
145          while (offset >= 0 && char.IsWhiteSpace(document.GetCharAt(offset))) {
146            offset--;
147          }
148          if (offset > 0) {
149            var nonWsResult = MagicKeyCompletion(
150              document.GetCharAt(offset),
151              controlSpace,
152              out isComplete
153            );
154            if (nonWsResult != null) {
155              var text = new HashSet<string>(result.Select(r => r.CompletionText));
156              result = result.Concat(nonWsResult.Where(r => !text.Contains(r.CompletionText)));
157            }
158          }
159        }
160
161        return result;
162      }
163      return Enumerable.Empty<ICompletionData>();
164    }
165
166    /// <summary>
167    /// Gets the types that needs to be imported via using or full type name.
168    /// </summary>
169    public IEnumerable<ICompletionData> GetImportCompletionData(int offset)
170    {
171      var generalLookup = new MemberLookup(null, Compilation.MainAssembly);
172      SetOffset(offset);
173
174      // flatten usings
175      var namespaces = new List<INamespace>();
176      for (var n = ctx.CurrentUsingScope; n != null; n = n.Parent) {
177        namespaces.Add(n.Namespace);
178        foreach (var u in n.Usings)
179          namespaces.Add(u);
180      }
181
182      foreach (var type in Compilation.GetAllTypeDefinitions ()) {
183        if (!generalLookup.IsAccessible(type, false))
184          continue;
185        if (namespaces.Any(n => n.FullName == type.Namespace))
186          continue;
187        bool useFullName = false;
188        foreach (var ns in namespaces) {
189          if (ns.GetTypeDefinition(type.Name, type.TypeParameterCount) != null) {
190            useFullName = true;
191            break;
192          }
193        }
194        yield return factory.CreateImportCompletionData(type, useFullName, false);
195      }
196    }
197
198    IEnumerable<string> GenerateNameProposals(AstType type)
199    {
200      if (type is PrimitiveType) {
201        var pt = (PrimitiveType)type;
202        switch (pt.Keyword) {
203          case "object":
204            yield return "o";
205            yield return "obj";
206            break;
207          case "bool":
208            yield return "b";
209            yield return "pred";
210            break;
211          case "double":
212          case "float":
213          case "decimal":
214            yield return "d";
215            yield return "f";
216            yield return "m";
217            break;
218          default:
219            yield return "i";
220            yield return "j";
221            yield return "k";
222            break;
223        }
224        yield break;
225      }
226      string name;
227      if (type is SimpleType) {
228        name = ((SimpleType)type).Identifier;
229      } else if (type is MemberType) {
230        name = ((MemberType)type).MemberName;
231      } else {
232        yield break;
233      }
234
235      var names = WordParser.BreakWords(name);
236
237      var possibleName = new StringBuilder();
238      for (int i = 0; i < names.Count; i++) {
239        possibleName.Length = 0;
240        for (int j = i; j < names.Count; j++) {
241          if (string.IsNullOrEmpty(names [j])) {
242            continue;
243          }
244          if (j == i) {
245            names [j] = Char.ToLower(names [j] [0]) + names [j].Substring(1);
246          }
247          possibleName.Append(names [j]);
248        }
249        yield return possibleName.ToString();
250      }
251    }
252
253    IEnumerable<ICompletionData> HandleMemberReferenceCompletion(ExpressionResult expr)
254    {
255      if (expr == null)
256        return null;
257
258      // do not auto select <number>. (but <number>.<number>.) (0.ToString() is valid)
259      if (expr.Node is PrimitiveExpression) {
260        var pexpr = (PrimitiveExpression)expr.Node;
261        if (!(pexpr.Value is string || pexpr.Value is char) && !pexpr.LiteralValue.Contains('.')) {
262          AutoSelect = false;
263        }
264      }
265      var resolveResult = ResolveExpression(expr);
266
267      if (resolveResult == null) {
268        return null;
269      }
270      if (expr.Node is AstType) {
271
272        // check for namespace names
273        if (expr.Node.AncestorsAndSelf
274          .TakeWhile(n => n is AstType)
275          .Any(m => m.Role == NamespaceDeclaration.NamespaceNameRole))
276          return null;
277
278        // need to look at paren.parent because of "catch (<Type>.A" expression
279        if (expr.Node.Parent != null && expr.Node.Parent.Parent is CatchClause)
280          return HandleCatchClauseType(expr);
281        return CreateTypeAndNamespaceCompletionData(
282          location,
283          resolveResult.Result,
284          expr.Node,
285          resolveResult.Resolver
286        );
287      }
288
289
290      return CreateCompletionData(
291        location,
292        resolveResult.Result,
293        expr.Node,
294        resolveResult.Resolver
295      );
296    }
297
298    bool IsInPreprocessorDirective()
299    {
300      var text = GetMemberTextToCaret().Item1;
301      var miniLexer = new MiniLexer(text);
302      miniLexer.Parse();
303      return miniLexer.IsInPreprocessorDirective;
304    }
305
306    IEnumerable<ICompletionData> HandleObjectInitializer(SyntaxTree unit, AstNode n)
307    {
308      var p = n.Parent;
309      while (p != null && !(p is ObjectCreateExpression)) {
310        p = p.Parent;
311      }
312      var parent = n.Parent as ArrayInitializerExpression;
313      if (parent == null)
314        return null;
315      if (parent.IsSingleElement)
316        parent = (ArrayInitializerExpression)parent.Parent;
317      if (p != null) {
318        var contextList = new CompletionDataWrapper(this);
319        var initializerResult = ResolveExpression(p);
320        IType initializerType = null;
321
322        if (initializerResult.Result is DynamicInvocationResolveResult) {
323          var dr = (DynamicInvocationResolveResult)initializerResult.Result;
324          var constructor = (dr.Target as MethodGroupResolveResult).Methods.FirstOrDefault();
325          if (constructor != null)
326            initializerType = constructor.DeclaringType;
327        } else {
328          initializerType = initializerResult != null ? initializerResult.Result.Type : null;
329        }
330
331
332        if (initializerType != null && initializerType.Kind != TypeKind.Unknown) {
333          // check 3 cases:
334          // 1) New initalizer { xpr
335          // 2) Object initializer { prop = val1, field = val2, xpr
336          // 3) Array initializer { new Foo (), a, xpr
337          // in case 1 all object/array initializer options should be given - in the others not.
338
339          AstNode prev = null;
340          if (parent.Elements.Count > 1) {
341            prev = parent.Elements.First();
342            if (prev is ArrayInitializerExpression && ((ArrayInitializerExpression)prev).IsSingleElement)
343              prev = ((ArrayInitializerExpression)prev).Elements.FirstOrDefault();
344          }
345
346          if (prev != null && !(prev is NamedExpression)) {
347            AddContextCompletion(contextList, GetState(), n);
348            // case 3)
349            return contextList.Result;
350          }
351          var lookup = new MemberLookup(ctx.CurrentTypeDefinition, Compilation.MainAssembly);
352          var list = typeof(System.Collections.IList).ToTypeReference().Resolve(Compilation);
353          var list1 = typeof(System.Collections.Generic.IList<>).ToTypeReference().Resolve(Compilation);
354          bool isProtectedAllowed = ctx.CurrentTypeDefinition != null && initializerType.GetDefinition() != null ?
355            ctx.CurrentTypeDefinition.IsDerivedFrom(initializerType.GetDefinition()) :
356            false;
357          foreach (var m in initializerType.GetMembers (m => m.SymbolKind == SymbolKind.Field)) {
358            var f = m as IField;
359            if (f != null && (f.IsReadOnly || f.IsConst))
360              continue;
361            if (lookup.IsAccessible(m, isProtectedAllowed)) {
362              var data = contextList.AddMember(m);
363              if (data != null)
364                data.DisplayFlags |= DisplayFlags.NamedArgument;
365            }
366          }
367
368          foreach (IProperty m in initializerType.GetMembers (m => m.SymbolKind == SymbolKind.Property)) {
369            if (m.CanSet && lookup.IsAccessible(m.Setter, isProtectedAllowed)  ||
370              m.CanGet && lookup.IsAccessible(m.Getter, isProtectedAllowed) && m.ReturnType.GetDefinition() != null &&
371              (m.ReturnType.GetDefinition().IsDerivedFrom(list.GetDefinition()) || m.ReturnType.GetDefinition().IsDerivedFrom(list1.GetDefinition()))) {
372              var data = contextList.AddMember(m);
373              if (data != null)
374                data.DisplayFlags |= DisplayFlags.NamedArgument;
375            }
376          }
377
378          if (prev != null && (prev is NamedExpression)) {
379            // case 2)
380            return contextList.Result;
381          }
382
383          // case 1)
384
385          // check if the object is a list, if not only provide object initalizers
386          if (initializerType.Kind != TypeKind.Array && list != null) {
387            var def = initializerType.GetDefinition();
388            if (def != null && !def.IsDerivedFrom(list.GetDefinition()) && !def.IsDerivedFrom(list1.GetDefinition()))
389              return contextList.Result;
390          }
391
392          AddContextCompletion(contextList, GetState(), n);
393          return contextList.Result;
394        }
395      }
396      return null;
397    }
398
399    static readonly DateTime curDate = DateTime.Now;
400
401    IEnumerable<ICompletionData> GenerateNumberFormatitems(bool isFloatingPoint)
402    {
403      yield return factory.CreateFormatItemCompletionData("D", "decimal", 123);
404      yield return factory.CreateFormatItemCompletionData("D5", "decimal", 123);
405      yield return factory.CreateFormatItemCompletionData("C", "currency", 123);
406      yield return factory.CreateFormatItemCompletionData("C0", "currency", 123);
407      yield return factory.CreateFormatItemCompletionData("E", "exponential", 1.23E4);
408      yield return factory.CreateFormatItemCompletionData("E2", "exponential", 1.234);
409      yield return factory.CreateFormatItemCompletionData("e2", "exponential", 1.234);
410      yield return factory.CreateFormatItemCompletionData("F", "fixed-point", 123.45);
411      yield return factory.CreateFormatItemCompletionData("F1", "fixed-point", 123.45);
412      yield return factory.CreateFormatItemCompletionData("G", "general", 1.23E+56);
413      yield return factory.CreateFormatItemCompletionData("g2", "general", 1.23E+56);
414      yield return factory.CreateFormatItemCompletionData("N", "number", 12345.68);
415      yield return factory.CreateFormatItemCompletionData("N1", "number", 12345.68);
416      yield return factory.CreateFormatItemCompletionData("P", "percent", 12.34);
417      yield return factory.CreateFormatItemCompletionData("P1", "percent", 12.34);
418      yield return factory.CreateFormatItemCompletionData("R", "round-trip", 0.1230000001);
419      yield return factory.CreateFormatItemCompletionData("X", "hexadecimal", 1234);
420      yield return factory.CreateFormatItemCompletionData("x8", "hexadecimal", 1234);
421      yield return factory.CreateFormatItemCompletionData("0000", "custom", 123);
422      yield return factory.CreateFormatItemCompletionData("####", "custom", 123);
423      yield return factory.CreateFormatItemCompletionData("##.###", "custom", 1.23);
424      yield return factory.CreateFormatItemCompletionData("##.000", "custom", 1.23);
425      yield return factory.CreateFormatItemCompletionData("## 'items'", "custom", 12);
426    }
427
428    IEnumerable<ICompletionData> GenerateDateTimeFormatitems()
429    {
430      yield return factory.CreateFormatItemCompletionData("D", "long date", curDate);
431      yield return factory.CreateFormatItemCompletionData("d", "short date", curDate);
432      yield return factory.CreateFormatItemCompletionData("F", "full date long", curDate);
433      yield return factory.CreateFormatItemCompletionData("f", "full date short", curDate);
434      yield return factory.CreateFormatItemCompletionData("G", "general long", curDate);
435      yield return factory.CreateFormatItemCompletionData("g", "general short", curDate);
436      yield return factory.CreateFormatItemCompletionData("M", "month", curDate);
437      yield return factory.CreateFormatItemCompletionData("O", "ISO 8601", curDate);
438      yield return factory.CreateFormatItemCompletionData("R", "RFC 1123", curDate);
439      yield return factory.CreateFormatItemCompletionData("s", "sortable", curDate);
440      yield return factory.CreateFormatItemCompletionData("T", "long time", curDate);
441      yield return factory.CreateFormatItemCompletionData("t", "short time", curDate);
442      yield return factory.CreateFormatItemCompletionData("U", "universal full", curDate);
443      yield return factory.CreateFormatItemCompletionData("u", "universal sortable", curDate);
444      yield return factory.CreateFormatItemCompletionData("Y", "year month", curDate);
445      yield return factory.CreateFormatItemCompletionData("yy-MM-dd", "custom", curDate);
446      yield return factory.CreateFormatItemCompletionData("yyyy MMMMM dd", "custom", curDate);
447      yield return factory.CreateFormatItemCompletionData("yy-MMM-dd ddd", "custom", curDate);
448      yield return factory.CreateFormatItemCompletionData("yyyy-M-d dddd", "custom", curDate);
449      yield return factory.CreateFormatItemCompletionData("hh:mm:ss t z", "custom", curDate);
450      yield return factory.CreateFormatItemCompletionData("hh:mm:ss tt zz", "custom", curDate);
451      yield return factory.CreateFormatItemCompletionData("HH:mm:ss tt zz", "custom", curDate);
452      yield return factory.CreateFormatItemCompletionData("HH:m:s tt zz", "custom", curDate);
453
454    }
455
456    [Flags]
457    enum TestEnum
458    {
459      EnumCaseName = 0,
460      Flag1 = 1,
461      Flag2 = 2,
462      Flags
463
464    }
465
466    IEnumerable<ICompletionData> GenerateEnumFormatitems()
467    {
468      yield return factory.CreateFormatItemCompletionData("G", "string value", TestEnum.EnumCaseName);
469      yield return factory.CreateFormatItemCompletionData("F", "flags value", TestEnum.Flags);
470      yield return factory.CreateFormatItemCompletionData("D", "integer value", TestEnum.Flags);
471      yield return factory.CreateFormatItemCompletionData("X", "hexadecimal", TestEnum.Flags);
472    }
473
474    IEnumerable<ICompletionData> GenerateTimeSpanFormatitems()
475    {
476      yield return factory.CreateFormatItemCompletionData("c", "invariant", new TimeSpan(0, 1, 23, 456));
477      yield return factory.CreateFormatItemCompletionData("G", "general long", new TimeSpan(0, 1, 23, 456));
478      yield return factory.CreateFormatItemCompletionData("g", "general short", new TimeSpan(0, 1, 23, 456));
479    }
480
481    static Guid defaultGuid = Guid.NewGuid();
482
483    IEnumerable<ICompletionData> GenerateGuidFormatitems()
484    {
485      yield return factory.CreateFormatItemCompletionData("N", "digits", defaultGuid);
486      yield return factory.CreateFormatItemCompletionData("D", "hypens", defaultGuid);
487      yield return factory.CreateFormatItemCompletionData("B", "braces", defaultGuid);
488      yield return factory.CreateFormatItemCompletionData("P", "parentheses", defaultGuid);
489    }
490
491    int GetFormatItemNumber()
492    {
493      int number = 0;
494      var o = offset - 2;
495      while (o > 0) {
496        char ch = document.GetCharAt(o);
497        if (ch == '{')
498          return number;
499        if (!char.IsDigit(ch))
500          break;
501        number = number * 10 + ch - '0';
502        o--;
503      }
504      return -1;
505    }
506
507    IEnumerable<ICompletionData> HandleStringFormatItems()
508    {
509      var formatArgument = GetFormatItemNumber();
510      if (formatArgument < 0)
511        return Enumerable.Empty<ICompletionData>();
512      var followUp = new StringBuilder();
513
514      var o = offset;
515      while (o < document.TextLength) {
516        char ch = document.GetCharAt(o);
517        followUp.Append(ch);
518        o++;
519        if (ch == ';')
520          break;
521      }
522      var unit = ParseStub(followUp.ToString(), false);
523
524      var invoke = unit.GetNodeAt<InvocationExpression>(location);
525
526      if (invoke != null) {
527        var resolveResult = ResolveExpression(new ExpressionResult(invoke, unit));
528        var invokeResult = resolveResult.Result as InvocationResolveResult;
529        if (invokeResult != null) {
530          var arg = formatArgument + 1; // First argument is the format string
531          if (arg < invoke.Arguments.Count) {
532            var invokeArgument = ResolveExpression(new ExpressionResult(invoke.Arguments.ElementAt(arg), unit));
533            if (invokeArgument != null) {
534              var provider = GetFormatCompletionData(invokeArgument.Result.Type);
535              if (provider != null)
536                return provider;
537              if (!invokeArgument.Result.Type.IsKnownType(KnownTypeCode.Object))
538                return Enumerable.Empty<ICompletionData>();
539            }
540          }
541        }
542      }
543      return HandleStringFormatItemsFallback();
544    }
545
546    IEnumerable<ICompletionData> HandleStringFormatItemsFallback()
547    {
548      var unit = ParseStub("a}\");", false);
549
550      var invoke = unit.GetNodeAt<InvocationExpression>(location);
551
552      if (invoke == null)
553        return Enumerable.Empty<ICompletionData>();
554
555      var resolveResult = ResolveExpression(new ExpressionResult(invoke, unit));
556      var invokeResult = resolveResult.Result as CSharpInvocationResolveResult;
557      if (invokeResult == null)
558        return Enumerable.Empty<ICompletionData>();
559
560      Expression fmtArgumets;
561      IList<Expression> args;
562      if (FormatStringHelper.TryGetFormattingParameters(invokeResult, invoke, out fmtArgumets, out args, null)) {
563        return GenerateNumberFormatitems(false)
564          .Concat(GenerateDateTimeFormatitems())
565          .Concat(GenerateTimeSpanFormatitems())
566          .Concat(GenerateEnumFormatitems())
567          .Concat(GenerateGuidFormatitems());
568      }
569      return Enumerable.Empty<ICompletionData>();
570
571    }
572
573    IEnumerable<ICompletionData> GetFormatCompletionData(IType type)
574    {
575      if (type.Namespace != "System")
576        return null;
577      switch (type.Name) {
578        case "Int64":
579        case "UInt64":
580        case "Int32":
581        case "UInt32":
582        case "Int16":
583        case "UInt16":
584        case "Byte":
585        case "SByte":
586          return GenerateNumberFormatitems(false);
587        case "Single":
588        case "Double":
589        case "Decimal":
590          return GenerateNumberFormatitems(true);
591        case "Enum":
592          return GenerateEnumFormatitems();
593        case "DateTime":
594          return GenerateDateTimeFormatitems();
595        case "TimeSpan":
596          return GenerateTimeSpanFormatitems();
597        case "Guid":
598          return GenerateGuidFormatitems();
599      }
600      return null;
601    }
602
603    IEnumerable<ICompletionData> HandleToStringFormatItems()
604    {
605      var unit = ParseStub("\");", false);
606
607      var invoke = unit.GetNodeAt<InvocationExpression>(location);
608      if (invoke == null)
609        return Enumerable.Empty<ICompletionData>();
610
611      var resolveResult = ResolveExpression(new ExpressionResult(invoke, unit));
612      var invokeResult = resolveResult.Result as InvocationResolveResult;
613      if (invokeResult == null)
614        return Enumerable.Empty<ICompletionData>();
615      if (invokeResult.Member.Name == "ToString")
616        return GetFormatCompletionData(invokeResult.Member.DeclaringType) ?? Enumerable.Empty<ICompletionData>();
617      return Enumerable.Empty<ICompletionData>();
618    }
619
620    IEnumerable<ICompletionData> MagicKeyCompletion(char completionChar, bool controlSpace, out bool isComplete)
621    {
622      isComplete = false;
623      ExpressionResolveResult resolveResult;
624      switch (completionChar) {
625        // Magic key completion
626        case ':':
627          var text = GetMemberTextToCaret();
628          var lexer = new MiniLexer(text.Item1);
629          lexer.Parse();
630          if (lexer.IsInSingleComment ||
631            lexer.IsInChar ||
632            lexer.IsInMultiLineComment ||
633            lexer.IsInPreprocessorDirective) {
634            return Enumerable.Empty<ICompletionData>();
635          }
636
637          if (lexer.IsInString || lexer.IsInVerbatimString)
638            return HandleStringFormatItems();
639          return HandleMemberReferenceCompletion(GetExpressionBeforeCursor());
640        case '"':
641          text = GetMemberTextToCaret();
642          lexer = new MiniLexer(text.Item1);
643          lexer.Parse();
644          if (lexer.IsInSingleComment ||
645            lexer.IsInChar ||
646            lexer.IsInMultiLineComment ||
647            lexer.IsInPreprocessorDirective) {
648            return Enumerable.Empty<ICompletionData>();
649          }
650
651          if (lexer.IsInString || lexer.IsInVerbatimString)
652            return HandleToStringFormatItems();
653          return Enumerable.Empty<ICompletionData>();
654        case '.':
655          if (IsInsideCommentStringOrDirective()) {
656            return Enumerable.Empty<ICompletionData>();
657          }
658          return HandleMemberReferenceCompletion(GetExpressionBeforeCursor());
659        case '#':
660          if (!IsInPreprocessorDirective())
661            return null;
662          return GetDirectiveCompletionData();
663          // XML doc completion
664        case '<':
665          if (IsInsideDocComment()) {
666            return GetXmlDocumentationCompletionData();
667          }
668          if (controlSpace) {
669            return DefaultControlSpaceItems(ref isComplete);
670          }
671          return null;
672        case '>':
673          if (!IsInsideDocComment()) {
674            if (offset > 2 && document.GetCharAt(offset - 2) == '-' && !IsInsideCommentStringOrDirective()) {
675              return HandleMemberReferenceCompletion(GetExpressionBeforeCursor());
676            }
677            return null;
678          }
679          return null;
680
681          // Parameter completion
682        case '(':
683          if (IsInsideCommentStringOrDirective()) {
684            return null;
685          }
686          var invoke = GetInvocationBeforeCursor(true);
687          if (invoke == null) {
688            if (controlSpace)
689              return DefaultControlSpaceItems(ref isComplete, invoke);
690            return null;
691          }
692          if (invoke.Node is TypeOfExpression) {
693            return CreateTypeList();
694          }
695          var invocationResult = ResolveExpression(invoke);
696          if (invocationResult == null) {
697            return null;
698          }
699          var methodGroup = invocationResult.Result as MethodGroupResolveResult;
700          if (methodGroup != null) {
701            return CreateParameterCompletion(
702              methodGroup,
703              invocationResult.Resolver,
704              invoke.Node,
705              invoke.Unit,
706              0,
707              controlSpace
708            );
709          }
710
711          if (controlSpace) {
712            return DefaultControlSpaceItems(ref isComplete, invoke);
713          }
714          return null;
715        case '=':
716          return controlSpace ? DefaultControlSpaceItems(ref isComplete) : null;
717        case ',':
718          int cpos2;
719          if (!GetParameterCompletionCommandOffset(out cpos2)) {
720            return null;
721          }
722          //  completionContext = CompletionWidget.CreateCodeCompletionContext (cpos2);
723          //  int currentParameter2 = MethodParameterDataProvider.GetCurrentParameterIndex (CompletionWidget, completionContext) - 1;
724          //        return CreateParameterCompletion (CreateResolver (), location, ExpressionContext.MethodBody, provider.Methods, currentParameter);
725          break;
726
727          // Completion on space:
728        case ' ':
729          int tokenIndex = offset;
730          string token = GetPreviousToken(ref tokenIndex, false);
731          if (IsInsideCommentStringOrDirective()) {
732            return null;
733          }
734          // check propose name, for context <variable name> <ctrl+space> (but only in control space context)
735          //IType isAsType = null;
736          var isAsExpression = GetExpressionAt(offset);
737          if (controlSpace && isAsExpression != null && isAsExpression.Node is VariableDeclarationStatement && token != "new") {
738            var parent = isAsExpression.Node as VariableDeclarationStatement;
739            var proposeNameList = new CompletionDataWrapper(this);
740            if (parent.Variables.Count != 1)
741              return DefaultControlSpaceItems(ref isComplete, isAsExpression, controlSpace);
742
743            foreach (var possibleName in GenerateNameProposals (parent.Type)) {
744              if (possibleName.Length > 0) {
745                proposeNameList.Result.Add(factory.CreateLiteralCompletionData(possibleName.ToString()));
746              }
747            }
748
749            AutoSelect = false;
750            AutoCompleteEmptyMatch = false;
751            isComplete = true;
752            return proposeNameList.Result;
753          }
754          //        int tokenIndex = offset;
755          //        string token = GetPreviousToken (ref tokenIndex, false);
756          //        if (result.ExpressionContext == ExpressionContext.ObjectInitializer) {
757          //          resolver = CreateResolver ();
758          //          ExpressionContext exactContext = new NewCSharpExpressionFinder (dom).FindExactContextForObjectInitializer (document, resolver.Unit, Document.FileName, resolver.CallingType);
759          //          IReturnType objectInitializer = ((ExpressionContext.TypeExpressionContext)exactContext).UnresolvedType;
760          //          if (objectInitializer != null && objectInitializer.ArrayDimensions == 0 && objectInitializer.PointerNestingLevel == 0 && (token == "{" || token == ","))
761          //            return CreateCtrlSpaceCompletionData (completionContext, result);
762          //        }
763          if (token == "=") {
764            int j = tokenIndex;
765            string prevToken = GetPreviousToken(ref j, false);
766            if (prevToken == "=" || prevToken == "+" || prevToken == "-" || prevToken == "!") {
767              token = prevToken + token;
768              tokenIndex = j;
769            }
770          }
771          switch (token) {
772            case "(":
773            case ",":
774              int cpos;
775              if (!GetParameterCompletionCommandOffset(out cpos)) {
776                break;
777              }
778              int currentParameter = GetCurrentParameterIndex(cpos - 1, this.offset) - 1;
779              if (currentParameter < 0) {
780                return null;
781              }
782              invoke = GetInvocationBeforeCursor(token == "(");
783              if (invoke == null) {
784                return null;
785              }
786              invocationResult = ResolveExpression(invoke);
787              if (invocationResult == null) {
788                return null;
789              }
790              methodGroup = invocationResult.Result as MethodGroupResolveResult;
791              if (methodGroup != null) {
792                return CreateParameterCompletion(
793                  methodGroup,
794                  invocationResult.Resolver,
795                  invoke.Node,
796                  invoke.Unit,
797                  currentParameter,
798                  controlSpace);
799              }
800              return null;
801            case "=":
802            case "==":
803            case "!=":
804              GetPreviousToken(ref tokenIndex, false);
805              var expressionOrVariableDeclaration = GetExpressionAt(tokenIndex);
806              if (expressionOrVariableDeclaration == null) {
807                return null;
808              }
809              resolveResult = ResolveExpression(expressionOrVariableDeclaration);
810              if (resolveResult == null) {
811                return null;
812              }
813              if (resolveResult.Result.Type.Kind == TypeKind.Enum) {
814                var wrapper = new CompletionDataWrapper(this);
815                AddContextCompletion(
816                  wrapper,
817                  resolveResult.Resolver,
818                  expressionOrVariableDeclaration.Node);
819                AddEnumMembers(wrapper, resolveResult.Result.Type, resolveResult.Resolver);
820                AutoCompleteEmptyMatch = false;
821                return wrapper.Result;
822              }
823              //       
824              //          if (resolvedType.FullName == DomReturnType.Bool.FullName) {
825              //            CompletionDataList completionList = new ProjectDomCompletionDataList ();
826              //            CompletionDataCollector cdc = new CompletionDataCollector (this, dom, completionList, Document.CompilationUnit, resolver.CallingType, location);
827              //            completionList.AutoCompleteEmptyMatch = false;
828              //            cdc.Add ("true", "md-keyword");
829              //            cdc.Add ("false", "md-keyword");
830              //            resolver.AddAccessibleCodeCompletionData (result.ExpressionContext, cdc);
831              //            return completionList;
832              //          }
833              //          if (resolvedType.ClassType == ClassType.Delegate && token == "=") {
834              //            CompletionDataList completionList = new ProjectDomCompletionDataList ();
835              //            string parameterDefinition = AddDelegateHandlers (completionList, resolvedType);
836              //            string varName = GetPreviousMemberReferenceExpression (tokenIndex);
837              //            completionList.Add (new EventCreationCompletionData (document, varName, resolvedType, null, parameterDefinition, resolver.CallingMember, resolvedType));
838              //           
839              //            CompletionDataCollector cdc = new CompletionDataCollector (this, dom, completionList, Document.CompilationUnit, resolver.CallingType, location);
840              //            resolver.AddAccessibleCodeCompletionData (result.ExpressionContext, cdc);
841              //            foreach (var data in completionList) {
842              //              if (data is MemberCompletionData)
843              //                ((MemberCompletionData)data).IsDelegateExpected = true;
844              //            }
845              //            return completionList;
846              //          }
847              return null;
848            case "+=":
849            case "-=":
850              var curTokenIndex = tokenIndex;
851              GetPreviousToken(ref tokenIndex, false);
852
853              expressionOrVariableDeclaration = GetExpressionAt(tokenIndex);
854              if (expressionOrVariableDeclaration == null) {
855                return null;
856              }
857
858              resolveResult = ResolveExpression(expressionOrVariableDeclaration);
859              if (resolveResult == null) {
860                return null;
861              }
862
863
864              var mrr = resolveResult.Result as MemberResolveResult;
865              if (mrr != null) {
866                var evt = mrr.Member as IEvent;
867                if (evt == null) {
868                  return null;
869                }
870                var delegateType = evt.ReturnType;
871                if (delegateType.Kind != TypeKind.Delegate) {
872                  return null;
873                }
874
875                var wrapper = new CompletionDataWrapper(this);
876                if (currentType != null) {
877                  //              bool includeProtected = DomType.IncludeProtected (dom, typeFromDatabase, resolver.CallingType);
878                  foreach (var method in ctx.CurrentTypeDefinition.Methods) {
879                    if (MatchDelegate(delegateType, method) /*                    && method.IsAccessibleFrom (dom, resolver.CallingType, resolver.CallingMember, includeProtected) &&*/) {
880                      wrapper.AddMember(method);
881                      //                  data.SetText (data.CompletionText + ";");
882                    }
883                  }
884                }
885                if (token == "+=") {
886                  string parameterDefinition = AddDelegateHandlers(
887                    wrapper,
888                    delegateType,
889                    optDelegateName: GuessEventHandlerMethodName(curTokenIndex, (currentType == null) ? null : currentType.Name)
890                  );
891                }
892
893                return wrapper.Result;
894              }
895              return null;
896            case ":":
897              if (currentMember == null) {
898                token = GetPreviousToken(ref tokenIndex, false);
899                token = GetPreviousToken(ref tokenIndex, false);
900                if (token == "enum")
901                  return HandleEnumContext();
902                var wrapper = new CompletionDataWrapper(this);
903                AddTypesAndNamespaces(
904                  wrapper,
905                  GetState(),
906                  null,
907                  t =>  {
908                    if (currentType != null && currentType.ReflectionName.Equals(t.ReflectionName))
909                      return null;
910                    var def = t.GetDefinition();
911                    if (def != null && t.Kind != TypeKind.Interface && (def.IsSealed ||def.IsStatic))
912                      return null;
913                    return t;
914                  }
915                );
916                return wrapper.Result;
917              }
918              return null;
919          }
920
921          var keywordCompletion = HandleKeywordCompletion(tokenIndex, token);
922          if (keywordCompletion == null && controlSpace) {
923            goto default;
924          }
925          return keywordCompletion;
926          // Automatic completion
927        default:
928          if (IsInsideCommentStringOrDirective()) {
929            tokenIndex = offset;
930            token = GetPreviousToken(ref tokenIndex, false);
931            if (IsInPreprocessorDirective() && (token.Length == 1 && char.IsLetter(completionChar) || controlSpace)) {
932              while (token != null && document.GetCharAt(tokenIndex - 1) != '#') {
933                token = GetPreviousToken(ref tokenIndex, false);
934              }
935              if (token != null)
936                return HandleKeywordCompletion(tokenIndex, token);
937            }
938            return null;
939          }
940          char prevCh = offset > 2 ? document.GetCharAt(offset - 2) : ';';
941          char nextCh = offset < document.TextLength ? document.GetCharAt(offset) : ' ';
942          const string allowedChars = ";,.[](){}+-*/%^?:&|~!<>=";
943
944          if ((!Char.IsWhiteSpace(nextCh) && allowedChars.IndexOf(nextCh) < 0) || !(Char.IsWhiteSpace(prevCh) || allowedChars.IndexOf(prevCh) >= 0)) {
945            if (!controlSpace)
946              return null;
947          }
948
949          if (IsInLinqContext(offset)) {
950            if (!controlSpace && !(char.IsLetter(completionChar) || completionChar == '_')) {
951              return null;
952            }
953            tokenIndex = offset;
954            token = GetPreviousToken(ref tokenIndex, false);
955            // token last typed
956            if (!char.IsWhiteSpace(completionChar) && !linqKeywords.Contains(token)) {
957              token = GetPreviousToken(ref tokenIndex, false);
958            }
959            // token last typed
960
961            if (linqKeywords.Contains(token)) {
962              if (token == "from") {
963                // after from no auto code completion.
964                return null;
965              }
966              return DefaultControlSpaceItems(ref isComplete);
967            }
968            var dataList = new CompletionDataWrapper(this);
969            AddKeywords(dataList, linqKeywords);
970            return dataList.Result;
971          }
972          if (currentType != null && currentType.Kind == TypeKind.Enum) {
973            if (!char.IsLetter(completionChar))
974              return null;
975            return HandleEnumContext();
976          }
977          var contextList = new CompletionDataWrapper(this);
978          var identifierStart = GetExpressionAtCursor();
979          if (!(char.IsLetter(completionChar) || completionChar == '_') && (!controlSpace || identifierStart == null)) {
980            return controlSpace ? HandleAccessorContext() ?? DefaultControlSpaceItems(ref isComplete, identifierStart) : null;
981          }
982
983          if (identifierStart != null) {
984            if (identifierStart.Node is TypeParameterDeclaration) {
985              return null;
986            }
987
988            if (identifierStart.Node is MemberReferenceExpression) {
989              return HandleMemberReferenceCompletion(
990                new ExpressionResult(
991                  ((MemberReferenceExpression)identifierStart.Node).Target,
992                  identifierStart.Unit
993                )
994              );
995            }
996
997            if (identifierStart.Node is Identifier) {
998              if (identifierStart.Node.Parent is GotoStatement)
999                return null;
1000
1001              // May happen in variable names
1002              return controlSpace ? DefaultControlSpaceItems(ref isComplete, identifierStart) : null;
1003            }
1004            if (identifierStart.Node is VariableInitializer && location <= ((VariableInitializer)identifierStart.Node).NameToken.EndLocation) {
1005              return controlSpace ? HandleAccessorContext() ?? DefaultControlSpaceItems(ref isComplete, identifierStart) : null;
1006            }
1007            if (identifierStart.Node is CatchClause) {
1008              if (((CatchClause)identifierStart.Node).VariableNameToken.IsInside(location)) {
1009                return null;
1010              }
1011            }
1012            if (identifierStart.Node is AstType && identifierStart.Node.Parent is CatchClause) {
1013              return HandleCatchClauseType(identifierStart);
1014            }
1015
1016            var pDecl = identifierStart.Node as ParameterDeclaration;
1017            if (pDecl != null && pDecl.Parent is LambdaExpression) {
1018              return null;
1019            }
1020          }
1021
1022
1023          // Do not pop up completion on identifier identifier (should be handled by keyword completion).
1024          tokenIndex = offset - 1;
1025          token = GetPreviousToken(ref tokenIndex, false);
1026          if (token == "class" || token == "interface" || token == "struct" || token == "enum" || token == "namespace") {
1027            // after these always follows a name
1028            return null;
1029          }
1030          var keywordresult = HandleKeywordCompletion(tokenIndex, token);
1031          if (keywordresult != null) {
1032            return keywordresult;
1033          }
1034
1035          if ((!Char.IsWhiteSpace(nextCh) && allowedChars.IndexOf(nextCh) < 0) || !(Char.IsWhiteSpace(prevCh) || allowedChars.IndexOf(prevCh) >= 0)) {
1036            if (controlSpace)
1037              return DefaultControlSpaceItems(ref isComplete, identifierStart);
1038          }
1039
1040          int prevTokenIndex = tokenIndex;
1041          var prevToken2 = GetPreviousToken(ref prevTokenIndex, false);
1042          if (prevToken2 == "delegate") {
1043            // after these always follows a name
1044            return null;
1045          }
1046
1047          if (identifierStart == null && !string.IsNullOrEmpty(token) && !IsInsideCommentStringOrDirective() && (prevToken2 == ";" || prevToken2 == "{" || prevToken2 == "}")) {
1048            char last = token [token.Length - 1];
1049            if (char.IsLetterOrDigit(last) || last == '_' || token == ">") {
1050              return HandleKeywordCompletion(tokenIndex, token);
1051            }
1052          }
1053          if (identifierStart == null) {
1054            var accCtx = HandleAccessorContext();
1055            if (accCtx != null) {
1056              return accCtx;
1057            }
1058            return DefaultControlSpaceItems(ref isComplete, null, controlSpace);
1059          }
1060          CSharpResolver csResolver;
1061          AstNode n = identifierStart.Node;
1062          if (n.Parent is NamedArgumentExpression)
1063            n = n.Parent;
1064
1065          if (n != null && n.Parent is AnonymousTypeCreateExpression) {
1066            AutoSelect = false;
1067          }
1068
1069          // new { b$ }
1070          if (n is IdentifierExpression && n.Parent is AnonymousTypeCreateExpression)
1071            return null;
1072
1073          // Handle foreach (type name _
1074          if (n is IdentifierExpression) {
1075            var prev = n.GetPrevNode() as ForeachStatement;
1076            while (prev != null && prev.EmbeddedStatement is ForeachStatement)
1077              prev = (ForeachStatement)prev.EmbeddedStatement;
1078            if (prev != null && prev.InExpression.IsNull) {
1079              if (IncludeKeywordsInCompletionList)
1080                contextList.AddCustom("in");
1081              return contextList.Result;
1082            }
1083          }
1084          // Handle object/enumerable initialzer expressions: "new O () { P$"
1085          if (n is IdentifierExpression && n.Parent is ArrayInitializerExpression && !(n.Parent.Parent is ArrayCreateExpression)) {
1086            var result = HandleObjectInitializer(identifierStart.Unit, n);
1087            if (result != null)
1088              return result;
1089          }
1090
1091          if (n != null && n.Parent is InvocationExpression ||
1092            n.Parent is ParenthesizedExpression && n.Parent.Parent is InvocationExpression) {
1093            if (n.Parent is ParenthesizedExpression)
1094              n = n.Parent;
1095            var invokeParent = (InvocationExpression)n.Parent;
1096            var invokeResult = ResolveExpression(
1097              invokeParent.Target
1098            );
1099            var mgr = invokeResult != null ? invokeResult.Result as MethodGroupResolveResult : null;
1100            if (mgr != null) {
1101              int idx = 0;
1102              foreach (var arg in invokeParent.Arguments) {
1103                if (arg == n) {
1104                  break;
1105                }
1106                idx++;
1107              }
1108
1109              foreach (var method in mgr.Methods) {
1110                if (idx < method.Parameters.Count && method.Parameters [idx].Type.Kind == TypeKind.Delegate) {
1111                  AutoSelect = false;
1112                  AutoCompleteEmptyMatch = false;
1113                }
1114                foreach (var p in method.Parameters) {
1115                  contextList.AddNamedParameterVariable(p);
1116                }
1117              }
1118              idx++;
1119              foreach (var list in mgr.GetEligibleExtensionMethods (true)) {
1120                foreach (var method in list) {
1121                  if (idx < method.Parameters.Count && method.Parameters [idx].Type.Kind == TypeKind.Delegate) {
1122                    AutoSelect = false;
1123                    AutoCompleteEmptyMatch = false;
1124                  }
1125                }
1126              }
1127            }
1128          }
1129
1130          if (n != null && n.Parent is ObjectCreateExpression) {
1131            var invokeResult = ResolveExpression(n.Parent);
1132            var mgr = invokeResult != null ? invokeResult.Result as ResolveResult : null;
1133            if (mgr != null) {
1134              foreach (var constructor in mgr.Type.GetConstructors ()) {
1135                foreach (var p in constructor.Parameters) {
1136                  contextList.AddVariable(p);
1137                }
1138              }
1139            }
1140          }
1141
1142          if (n is IdentifierExpression) {
1143            var bop = n.Parent as BinaryOperatorExpression;
1144            Expression evaluationExpr = null;
1145
1146            if (bop != null && bop.Right == n && (bop.Operator == BinaryOperatorType.Equality || bop.Operator == BinaryOperatorType.InEquality)) {
1147              evaluationExpr = bop.Left;
1148            }
1149            // check for compare to enum case
1150            if (evaluationExpr != null) {
1151              resolveResult = ResolveExpression(evaluationExpr);
1152              if (resolveResult != null && resolveResult.Result.Type.Kind == TypeKind.Enum) {
1153                var wrapper = new CompletionDataWrapper(this);
1154                AddContextCompletion(
1155                  wrapper,
1156                  resolveResult.Resolver,
1157                  evaluationExpr
1158                );
1159                AddEnumMembers(wrapper, resolveResult.Result.Type, resolveResult.Resolver);
1160                AutoCompleteEmptyMatch = false;
1161                return wrapper.Result;
1162              }
1163            }
1164          }
1165
1166          if (n is Identifier && n.Parent is ForeachStatement) {
1167            if (controlSpace) {
1168              return DefaultControlSpaceItems(ref isComplete);
1169            }
1170            return null;
1171          }
1172
1173          if (n is ArrayInitializerExpression) {
1174            // check for new [] {...} expression -> no need to resolve the type there
1175            var parent = n.Parent as ArrayCreateExpression;
1176            if (parent != null && parent.Type.IsNull) {
1177              return DefaultControlSpaceItems(ref isComplete);
1178            }
1179
1180            var initalizerResult = ResolveExpression(n.Parent);
1181
1182            var concreteNode = identifierStart.Unit.GetNodeAt<IdentifierExpression>(location);
1183            // check if we're on the right side of an initializer expression
1184            if (concreteNode != null && concreteNode.Parent != null && concreteNode.Parent.Parent != null && concreteNode.Identifier != "a" && concreteNode.Parent.Parent is NamedExpression) {
1185              return DefaultControlSpaceItems(ref isComplete);
1186            }
1187            if (initalizerResult != null && initalizerResult.Result.Type.Kind != TypeKind.Unknown) {
1188
1189              foreach (var property in initalizerResult.Result.Type.GetProperties ()) {
1190                if (!property.IsPublic) {
1191                  continue;
1192                }
1193                var data = contextList.AddMember(property);
1194                if (data != null)
1195                  data.DisplayFlags |= DisplayFlags.NamedArgument;
1196              }
1197              foreach (var field in initalizerResult.Result.Type.GetFields ()) {       
1198                if (!field.IsPublic) {
1199                  continue;
1200                }
1201                var data = contextList.AddMember(field);
1202                if (data != null)
1203                  data.DisplayFlags |= DisplayFlags.NamedArgument;
1204              }
1205              return contextList.Result;
1206            }
1207            return DefaultControlSpaceItems(ref isComplete);
1208          }
1209
1210          if (IsAttributeContext(n)) {
1211            // add attribute targets
1212            if (currentType == null) {
1213              contextList.AddCustom("assembly");
1214              contextList.AddCustom("module");
1215              contextList.AddCustom("type");
1216            } else {
1217              contextList.AddCustom("param");
1218              contextList.AddCustom("field");
1219              contextList.AddCustom("property");
1220              contextList.AddCustom("method");
1221              contextList.AddCustom("event");
1222            }
1223            contextList.AddCustom("return");
1224          }
1225          if (n is MemberType) {
1226            resolveResult = ResolveExpression(
1227              ((MemberType)n).Target
1228            );
1229            return CreateTypeAndNamespaceCompletionData(
1230              location,
1231              resolveResult.Result,
1232              ((MemberType)n).Target,
1233              resolveResult.Resolver
1234            );
1235          }
1236          if (n != null/*          && !(identifierStart.Item2 is TypeDeclaration)*/) {
1237            csResolver = new CSharpResolver(ctx);
1238            var nodes = new List<AstNode>();
1239            nodes.Add(n);
1240            if (n.Parent is ICSharpCode.NRefactory.CSharp.Attribute) {
1241              nodes.Add(n.Parent);
1242            }
1243            var astResolver = CompletionContextProvider.GetResolver(csResolver, identifierStart.Unit);
1244            astResolver.ApplyNavigator(new NodeListResolveVisitorNavigator(nodes));
1245            try {
1246              csResolver = astResolver.GetResolverStateBefore(n);
1247            } catch (Exception) {
1248              csResolver = GetState();
1249            }
1250            // add attribute properties.
1251            if (n.Parent is ICSharpCode.NRefactory.CSharp.Attribute) {
1252              var rr = ResolveExpression(n.Parent);
1253              if (rr != null)
1254                AddAttributeProperties(contextList, rr.Result);
1255            }
1256          } else {
1257            csResolver = GetState();
1258          }
1259          // identifier has already started with the first letter
1260          offset--;
1261          AddContextCompletion(
1262            contextList,
1263            csResolver,
1264            identifierStart.Node
1265          );
1266          return contextList.Result;
1267          //        if (stub.Parent is BlockStatement)
1268
1269          //        result = FindExpression (dom, completionContext, -1);
1270          //        if (result == null)
1271          //          return null;
1272          //         else if (result.ExpressionContext != ExpressionContext.IdentifierExpected) {
1273          //          triggerWordLength = 1;
1274          //          bool autoSelect = true;
1275          //          IType returnType = null;
1276          //          if ((prevCh == ',' || prevCh == '(') && GetParameterCompletionCommandOffset (out cpos)) {
1277          //            ctx = CompletionWidget.CreateCodeCompletionContext (cpos);
1278          //            NRefactoryParameterDataProvider dataProvider = ParameterCompletionCommand (ctx) as NRefactoryParameterDataProvider;
1279          //            if (dataProvider != null) {
1280          //              int i = dataProvider.GetCurrentParameterIndex (CompletionWidget, ctx) - 1;
1281          //              foreach (var method in dataProvider.Methods) {
1282          //                if (i < method.Parameters.Count) {
1283          //                  returnType = dom.GetType (method.Parameters [i].ReturnType);
1284          //                  autoSelect = returnType == null || returnType.ClassType != ClassType.Delegate;
1285          //                  break;
1286          //                }
1287          //              }
1288          //            }
1289          //          }
1290          //          // Bug 677531 - Auto-complete doesn't always highlight generic parameter in method signature
1291          //          //if (result.ExpressionContext == ExpressionContext.TypeName)
1292          //          //  autoSelect = false;
1293          //          CompletionDataList dataList = CreateCtrlSpaceCompletionData (completionContext, result);
1294          //          AddEnumMembers (dataList, returnType);
1295          //          dataList.AutoSelect = autoSelect;
1296          //          return dataList;
1297          //        } else {
1298          //          result = FindExpression (dom, completionContext, 0);
1299          //          tokenIndex = offset;
1300          //         
1301          //          // check foreach case, unfortunately the expression finder is too dumb to handle full type names
1302          //          // should be overworked if the expression finder is replaced with a mcs ast based analyzer.
1303          //          var possibleForeachToken = GetPreviousToken (ref tokenIndex, false); // starting letter
1304          //          possibleForeachToken = GetPreviousToken (ref tokenIndex, false); // varname
1305          //       
1306          //          // read return types to '(' token
1307          //          possibleForeachToken = GetPreviousToken (ref tokenIndex, false); // varType
1308          //          if (possibleForeachToken == ">") {
1309          //            while (possibleForeachToken != null && possibleForeachToken != "(") {
1310          //              possibleForeachToken = GetPreviousToken (ref tokenIndex, false);
1311          //            }
1312          //          } else {
1313          //            possibleForeachToken = GetPreviousToken (ref tokenIndex, false); // (
1314          //            if (possibleForeachToken == ".")
1315          //              while (possibleForeachToken != null && possibleForeachToken != "(")
1316          //                possibleForeachToken = GetPreviousToken (ref tokenIndex, false);
1317          //          }
1318          //          possibleForeachToken = GetPreviousToken (ref tokenIndex, false); // foreach
1319          //       
1320          //          if (possibleForeachToken == "foreach") {
1321          //            result.ExpressionContext = ExpressionContext.ForeachInToken;
1322          //          } else {
1323          //            return null;
1324          //            //                result.ExpressionContext = ExpressionContext.IdentifierExpected;
1325          //          }
1326          //          result.Expression = "";
1327          //          result.Region = DomRegion.Empty;
1328          //       
1329          //          return CreateCtrlSpaceCompletionData (completionContext, result);
1330          //        }
1331          //        break;
1332      }
1333      return null;
1334
1335    }
1336
1337    IEnumerable<ICompletionData> HandleCatchClauseType(ExpressionResult identifierStart)
1338    {
1339      Func<IType, IType> typePred = delegate (IType type) {
1340        if (type.GetAllBaseTypes().Any(t => t.ReflectionName == "System.Exception"))
1341          return type;
1342        return null;
1343      };
1344      if (identifierStart.Node.Parent is CatchClause) {
1345        var wrapper = new CompletionDataWrapper(this);
1346        AddTypesAndNamespaces(
1347          wrapper,
1348          GetState(),
1349          identifierStart.Node,
1350          typePred,
1351          m => false
1352        );
1353        return wrapper.Result;
1354      }
1355
1356      var resolveResult = ResolveExpression(identifierStart);
1357      return CreateCompletionData(
1358        location,
1359        resolveResult.Result,
1360        identifierStart.Node,
1361        resolveResult.Resolver,
1362        typePred
1363      );
1364    }
1365
1366    string[] validEnumBaseTypes = {
1367      "byte",
1368      "sbyte",
1369      "short",
1370      "int",
1371      "long",
1372      "ushort",
1373      "uint",
1374      "ulong"
1375    };
1376
1377    IEnumerable<ICompletionData> HandleEnumContext()
1378    {
1379      var syntaxTree = ParseStub("a", false);
1380      if (syntaxTree == null) {
1381        return null;
1382      }
1383
1384      var curType = syntaxTree.GetNodeAt<TypeDeclaration>(location);
1385      if (curType == null || curType.ClassType != ClassType.Enum) {
1386        syntaxTree = ParseStub("a {}", false);
1387        var node = syntaxTree.GetNodeAt<AstType>(location);
1388        if (node != null) {
1389          var wrapper = new CompletionDataWrapper(this);
1390          AddKeywords(wrapper, validEnumBaseTypes);
1391          return wrapper.Result;
1392        }
1393      }
1394
1395      var member = syntaxTree.GetNodeAt<EnumMemberDeclaration>(location);
1396      if (member != null && member.NameToken.EndLocation < location) {
1397        if (currentMember == null && currentType != null) {
1398          foreach (var a in currentType.Members)
1399            if (a.Region.Begin < location && (currentMember == null || a.Region.Begin > currentMember.Region.Begin))
1400              currentMember = a;
1401        }
1402        bool isComplete = false;
1403        return DefaultControlSpaceItems(ref isComplete);
1404      }
1405
1406      var attribute = syntaxTree.GetNodeAt<Attribute>(location);
1407      if (attribute != null) {
1408        var contextList = new CompletionDataWrapper(this);
1409        var astResolver = CompletionContextProvider.GetResolver(GetState(), syntaxTree);
1410        var csResolver = astResolver.GetResolverStateBefore(attribute);
1411        AddContextCompletion(
1412          contextList,
1413          csResolver,
1414          attribute
1415        );
1416        return contextList.Result;
1417      }
1418      return null;
1419    }
1420
1421    bool IsInLinqContext(int offset)
1422    {
1423      string token;
1424      while (null != (token = GetPreviousToken(ref offset, true)) && !IsInsideCommentStringOrDirective()) {
1425
1426        if (token == "from") {
1427          return !IsInsideCommentStringOrDirective(offset);
1428        }
1429        if (token == ";" || token == "{") {
1430          return false;
1431        }
1432      }
1433      return false;
1434    }
1435
1436    IEnumerable<ICompletionData> HandleAccessorContext()
1437    {
1438      var unit = ParseStub("get; }", false);
1439      var node = unit.GetNodeAt(location, cn => !(cn is CSharpTokenNode));
1440      if (node is Accessor) {
1441        node = node.Parent;
1442      }
1443      var contextList = new CompletionDataWrapper(this);
1444      if (node is PropertyDeclaration || node is IndexerDeclaration) {
1445        if (IncludeKeywordsInCompletionList) {
1446          contextList.AddCustom("get");
1447          contextList.AddCustom("set");
1448          AddKeywords(contextList, accessorModifierKeywords);
1449        }
1450      } else if (node is CustomEventDeclaration) {
1451        if (IncludeKeywordsInCompletionList) {
1452          contextList.AddCustom("add");
1453          contextList.AddCustom("remove");
1454        }
1455      } else {
1456        return null;
1457      }
1458
1459      return contextList.Result;
1460    }
1461
1462    class IfVisitor :DepthFirstAstVisitor
1463    {
1464      TextLocation loc;
1465      ICompletionContextProvider completionContextProvider;
1466      public bool IsValid;
1467
1468      public IfVisitor(TextLocation loc, ICompletionContextProvider completionContextProvider)
1469      {
1470        this.loc = loc;
1471        this.completionContextProvider = completionContextProvider;
1472
1473        this.IsValid = true;
1474      }
1475
1476      void Check(string argument)
1477      {
1478        // TODO: evaluate #if epressions
1479        if (argument.Any(c => !(char.IsLetterOrDigit(c) || c == '_')))
1480          return;
1481        IsValid &= completionContextProvider.ConditionalSymbols.Contains(argument);
1482      }
1483
1484      Stack<PreProcessorDirective> ifStack = new Stack<PreProcessorDirective>();
1485
1486      public override void VisitPreProcessorDirective(PreProcessorDirective preProcessorDirective)
1487      {
1488        if (preProcessorDirective.Type == PreProcessorDirectiveType.If) {
1489          ifStack.Push(preProcessorDirective);
1490        } else if (preProcessorDirective.Type == PreProcessorDirectiveType.Endif) {
1491          if (ifStack.Count == 0)
1492            return;
1493          var ifDirective = ifStack.Pop();
1494          if (ifDirective.StartLocation < loc && loc < preProcessorDirective.EndLocation) {
1495            Check(ifDirective.Argument);
1496          }
1497
1498        }
1499
1500        base.VisitPreProcessorDirective(preProcessorDirective);
1501      }
1502
1503      public void End()
1504      {
1505        while (ifStack.Count > 0) {
1506          Check(ifStack.Pop().Argument);
1507        }
1508      }
1509    }
1510
1511    IEnumerable<ICompletionData> DefaultControlSpaceItems(ref bool isComplete, ExpressionResult xp = null, bool controlSpace = true)
1512    {
1513      var wrapper = new CompletionDataWrapper(this);
1514      if (offset >= document.TextLength) {
1515        offset = document.TextLength - 1;
1516      }
1517      while (offset > 1 && char.IsWhiteSpace(document.GetCharAt(offset))) {
1518        offset--;
1519      }
1520      location = document.GetLocation(offset);
1521
1522      if (xp == null) {
1523        xp = GetExpressionAtCursor();
1524      }
1525      AstNode node;
1526      SyntaxTree unit;
1527      ExpressionResolveResult rr;
1528      if (xp != null) {
1529        node = xp.Node;
1530        rr = ResolveExpression(node);
1531        unit = xp.Unit;
1532      } else {
1533        unit = ParseStub("foo", false);
1534        node = unit.GetNodeAt(
1535          location.Line,
1536          location.Column + 2,
1537          n => n is Expression || n is AstType || n is NamespaceDeclaration || n is Attribute
1538        );
1539        rr = ResolveExpression(node);
1540      }
1541      var ifvisitor = new IfVisitor(location, CompletionContextProvider);
1542      unit.AcceptVisitor(ifvisitor);
1543      ifvisitor.End();
1544      if (!ifvisitor.IsValid)
1545        return null;
1546      // namespace name case
1547      var ns = node as NamespaceDeclaration;
1548      if (ns != null) {
1549        var last = ns.NamespaceName;
1550        if (last != null && location < last.EndLocation)
1551          return null;
1552      }
1553      if (node is Identifier && node.Parent is ForeachStatement) {
1554        var foreachStmt = (ForeachStatement)node.Parent;
1555        foreach (var possibleName in GenerateNameProposals (foreachStmt.VariableType)) {
1556          if (possibleName.Length > 0) {
1557            wrapper.Result.Add(factory.CreateLiteralCompletionData(possibleName.ToString()));
1558          }
1559        }
1560
1561        AutoSelect = false;
1562        AutoCompleteEmptyMatch = false;
1563        isComplete = true;
1564        return wrapper.Result;
1565      }
1566
1567      if (node is Identifier && node.Parent is ParameterDeclaration) {
1568        if (!controlSpace) {
1569          return null;
1570        }
1571        // Try Parameter name case
1572        var param = node.Parent as ParameterDeclaration;
1573        if (param != null) {
1574          foreach (var possibleName in GenerateNameProposals (param.Type)) {
1575            if (possibleName.Length > 0) {
1576              wrapper.Result.Add(factory.CreateLiteralCompletionData(possibleName.ToString()));
1577            }
1578          }
1579          AutoSelect = false;
1580          AutoCompleteEmptyMatch = false;
1581          isComplete = true;
1582          return wrapper.Result;
1583        }
1584      }
1585      var pDecl = node as ParameterDeclaration;
1586      if (pDecl != null && pDecl.Parent is LambdaExpression) {
1587        return null;
1588      }
1589      /*            if (Unit != null && (node == null || node is TypeDeclaration)) {
1590        var constructor = Unit.GetNodeAt<ConstructorDeclaration>(
1591          location.Line,
1592          location.Column - 3
1593        );
1594        if (constructor != null && !constructor.ColonToken.IsNull && constructor.Initializer.IsNull) {
1595          wrapper.AddCustom("this");
1596          wrapper.AddCustom("base");
1597          return wrapper.Result;
1598        }
1599      }*/
1600
1601      var initializer = node != null ? node.Parent as ArrayInitializerExpression : null;
1602      if (initializer != null) {
1603        var result = HandleObjectInitializer(unit, initializer);
1604        if (result != null)
1605          return result;
1606      }
1607      CSharpResolver csResolver = null;
1608      if (rr != null) {
1609        csResolver = rr.Resolver;
1610      }
1611
1612      if (csResolver == null) {
1613        if (node != null) {
1614          csResolver = GetState();
1615          //var astResolver = new CSharpAstResolver (csResolver, node, xp != null ? xp.Item1 : CSharpUnresolvedFile);
1616
1617          try {
1618            //csResolver = astResolver.GetResolverStateBefore (node);
1619            Console.WriteLine(csResolver.LocalVariables.Count());
1620          } catch (Exception  e) {
1621            Console.WriteLine("E!!!" + e);
1622          }
1623
1624        } else {
1625          csResolver = GetState();
1626        }
1627      }
1628
1629      if (node is Attribute) {
1630        // add attribute properties.
1631        var astResolver = CompletionContextProvider.GetResolver(csResolver, unit);
1632        var resolved = astResolver.Resolve(node);
1633        AddAttributeProperties(wrapper, resolved);
1634      }
1635
1636
1637      if (node == null) {
1638        // try lambda
1639        unit = ParseStub("foo) => {}", true);
1640        var pd = unit.GetNodeAt<ParameterDeclaration>(
1641          location.Line,
1642          location.Column
1643        );
1644        if (pd != null) {
1645          var astResolver = unit != null ? CompletionContextProvider.GetResolver(GetState(), unit) : null;
1646          var parameterType = astResolver.Resolve(pd.Type);
1647          // Type <name> is always a name context -> return null
1648          if (parameterType != null && !parameterType.IsError)
1649            return null;
1650        }
1651      }
1652
1653      AddContextCompletion(wrapper, csResolver, node);
1654
1655      return wrapper.Result;
1656    }
1657
1658    static void AddAttributeProperties(CompletionDataWrapper wrapper, ResolveResult resolved)
1659    {
1660      if (resolved == null || resolved.Type.Kind == TypeKind.Unknown)
1661        return;
1662
1663      foreach (var property in resolved.Type.GetProperties (p => p.Accessibility == Accessibility.Public)) {
1664        var data = wrapper.AddMember(property);
1665        if (data != null)
1666          data.DisplayFlags |= DisplayFlags.NamedArgument;
1667      }
1668      foreach (var field in resolved.Type.GetFields (p => p.Accessibility == Accessibility.Public)) {
1669        var data = wrapper.AddMember(field);
1670        if (data != null)
1671          data.DisplayFlags |= DisplayFlags.NamedArgument;
1672      }
1673      foreach (var constructor in resolved.Type.GetConstructors (p => p.Accessibility == Accessibility.Public)) {
1674        foreach (var p in constructor.Parameters) {
1675          wrapper.AddNamedParameterVariable(p);
1676        }
1677      }
1678    }
1679
1680    void AddContextCompletion(CompletionDataWrapper wrapper, CSharpResolver state, AstNode node)
1681    {
1682      int i = offset - 1;
1683      var isInGlobalDelegate = node == null && state.CurrentTypeDefinition == null && GetPreviousToken(ref i, true) == "delegate";
1684
1685      if (state != null && !(node is AstType)) {
1686        foreach (var variable in state.LocalVariables) {
1687          if (variable.Region.IsInside(location.Line, location.Column - 1)) {
1688            continue;
1689          }
1690          wrapper.AddVariable(variable);
1691        }
1692      }
1693
1694      if (state.CurrentMember is IParameterizedMember && !(node is AstType)) {
1695        var param = (IParameterizedMember)state.CurrentMember;
1696        foreach (var p in param.Parameters) {
1697          wrapper.AddVariable(p);
1698        }
1699      }
1700
1701      if (state.CurrentMember is IMethod) {
1702        var method = (IMethod)state.CurrentMember;
1703        foreach (var p in method.TypeParameters) {
1704          wrapper.AddTypeParameter(p);
1705        }
1706      }
1707
1708      Func<IType, IType> typePred = null;
1709      if (IsAttributeContext(node)) {
1710        var attribute = Compilation.FindType(KnownTypeCode.Attribute);
1711        typePred = t => t.GetAllBaseTypeDefinitions().Any(bt => bt.Equals(attribute)) ? t : null;
1712      }
1713      if (node != null && node.Role == Roles.BaseType) {
1714        typePred = t => {
1715          var def = t.GetDefinition();
1716          if (def != null && t.Kind != TypeKind.Interface && (def.IsSealed || def.IsStatic))
1717            return null;
1718          return t;
1719        };
1720      }
1721
1722      if (node != null && !(node is NamespaceDeclaration) || state.CurrentTypeDefinition != null || isInGlobalDelegate) {
1723        AddTypesAndNamespaces(wrapper, state, node, typePred);
1724
1725        wrapper.Result.Add(factory.CreateLiteralCompletionData("global"));
1726      }
1727
1728      if (!(node is AstType)) {
1729        if (currentMember != null || node is Expression) {
1730          AddKeywords(wrapper, statementStartKeywords);
1731          if (LanguageVersion.Major >= 5)
1732            AddKeywords(wrapper, new [] { "await" });
1733          AddKeywords(wrapper, expressionLevelKeywords);
1734          if (node == null || node is TypeDeclaration)
1735            AddKeywords(wrapper, typeLevelKeywords);
1736        } else if (currentType != null) {
1737          AddKeywords(wrapper, typeLevelKeywords);
1738        } else {
1739          if (!isInGlobalDelegate && !(node is Attribute))
1740            AddKeywords(wrapper, globalLevelKeywords);
1741        }
1742        var prop = currentMember as IUnresolvedProperty;
1743        if (prop != null && prop.Setter != null && prop.Setter.Region.IsInside(location)) {
1744          wrapper.AddCustom("value");
1745        }
1746        if (currentMember is IUnresolvedEvent) {
1747          wrapper.AddCustom("value");
1748        }
1749
1750        if (IsInSwitchContext(node)) {
1751          if (IncludeKeywordsInCompletionList)
1752            wrapper.AddCustom("case");
1753        }
1754      } else {
1755        if (((AstType)node).Parent is ParameterDeclaration) {
1756          AddKeywords(wrapper, parameterTypePredecessorKeywords);
1757        }
1758      }
1759
1760      if (node != null || state.CurrentTypeDefinition != null || isInGlobalDelegate)
1761        AddKeywords(wrapper, primitiveTypesKeywords);
1762      if (currentMember != null && (node is IdentifierExpression || node is SimpleType) && (node.Parent is ExpressionStatement || node.Parent is ForeachStatement || node.Parent is UsingStatement)) {
1763        if (IncludeKeywordsInCompletionList) {
1764          wrapper.AddCustom("var");
1765          wrapper.AddCustom("dynamic");
1766        }
1767      }
1768      wrapper.Result.AddRange(factory.CreateCodeTemplateCompletionData());
1769      if (node != null && node.Role == Roles.Argument) {
1770        var resolved = ResolveExpression(node.Parent);
1771        var invokeResult = resolved != null ? resolved.Result as CSharpInvocationResolveResult : null;
1772        if (invokeResult != null) {
1773          int argNum = 0;
1774          foreach (var arg in node.Parent.Children.Where (c => c.Role == Roles.Argument)) {
1775            if (arg == node) {
1776              break;
1777            }
1778            argNum++;
1779          }
1780          var param = argNum < invokeResult.Member.Parameters.Count ? invokeResult.Member.Parameters [argNum] : null;
1781          if (param != null && param.Type.Kind == TypeKind.Enum) {
1782            AddEnumMembers(wrapper, param.Type, state);
1783          }
1784        }
1785      }
1786
1787      if (node is Expression) {
1788        var root = node;
1789        while (root.Parent != null)
1790          root = root.Parent;
1791        var astResolver = CompletionContextProvider.GetResolver(state, root);
1792        foreach (var type in TypeGuessing.GetValidTypes(astResolver, (Expression)node)) {
1793          if (type.Kind == TypeKind.Enum) {
1794            AddEnumMembers(wrapper, type, state);
1795          } else if (type.Kind == TypeKind.Delegate) {
1796            AddDelegateHandlers(wrapper, type, false, true);
1797            AutoSelect = false;
1798            AutoCompleteEmptyMatch = false;
1799          }
1800        }
1801      }
1802
1803      // Add 'this' keyword for first parameter (extension method case)
1804      if (node != null && node.Parent is ParameterDeclaration &&
1805        node.Parent.PrevSibling != null && node.Parent.PrevSibling.Role == Roles.LPar && IncludeKeywordsInCompletionList) {
1806        wrapper.AddCustom("this");
1807      }
1808    }
1809
1810    static bool IsInSwitchContext(AstNode node)
1811    {
1812      var n = node;
1813      while (n != null && !(n is EntityDeclaration)) {
1814        if (n is SwitchStatement) {
1815          return true;
1816        }
1817        if (n is BlockStatement) {
1818          return false;
1819        }
1820        n = n.Parent;
1821      }
1822      return false;
1823    }
1824
1825    static bool ListEquals(List<INamespace> curNamespaces, List<INamespace> oldNamespaces)
1826    {
1827      if (oldNamespaces == null || curNamespaces.Count != oldNamespaces.Count)
1828        return false;
1829      for (int i = 0; i < curNamespaces.Count; i++) {
1830        if (curNamespaces [i].FullName != oldNamespaces [i].FullName) {
1831          return false;
1832        }
1833      }
1834      return true;
1835    }
1836
1837    void AddTypesAndNamespaces(CompletionDataWrapper wrapper, CSharpResolver state, AstNode node, Func<IType, IType> typePred = null, Predicate<IMember> memberPred = null, Action<ICompletionData, IType> callback = null, bool onlyAddConstructors = false)
1838    {
1839      var lookup = new MemberLookup(ctx.CurrentTypeDefinition, Compilation.MainAssembly);
1840
1841      if (currentType != null) {
1842        for (var ct = ctx.CurrentTypeDefinition; ct != null; ct = ct.DeclaringTypeDefinition) {
1843          foreach (var nestedType in ct.GetNestedTypes ()) {
1844            if (!lookup.IsAccessible(nestedType.GetDefinition(), true))
1845              continue;
1846            if (onlyAddConstructors) {
1847              if (!nestedType.GetConstructors().Any(c => lookup.IsAccessible(c, true)))
1848                continue;
1849            }
1850
1851            if (typePred == null) {
1852              if (onlyAddConstructors)
1853                wrapper.AddConstructors(nestedType, false, IsAttributeContext(node));
1854              else
1855                wrapper.AddType(nestedType, false, IsAttributeContext(node));
1856              continue;
1857            }
1858
1859            var type = typePred(nestedType);
1860            if (type != null) {
1861              var a2 = onlyAddConstructors ? wrapper.AddConstructors(type, false, IsAttributeContext(node)) : wrapper.AddType(type, false, IsAttributeContext(node));
1862              if (a2 != null && callback != null) {
1863                callback(a2, type);
1864              }
1865            }
1866            continue;
1867          }
1868        }
1869
1870        if (this.currentMember != null && !(node is AstType)) {
1871          var def = ctx.CurrentTypeDefinition;
1872          if (def == null && currentType != null)
1873            def = Compilation.MainAssembly.GetTypeDefinition(currentType.FullTypeName);
1874          if (def != null) {
1875            bool isProtectedAllowed = true;
1876
1877            foreach (var member in def.GetMembers (m => currentMember.IsStatic ? m.IsStatic : true)) {
1878              if (member is IMethod && ((IMethod)member).FullName == "System.Object.Finalize") {
1879                continue;
1880              }
1881              if (member.SymbolKind == SymbolKind.Operator) {
1882                continue;
1883              }
1884              if (member.IsExplicitInterfaceImplementation) {
1885                continue;
1886              }
1887              if (!lookup.IsAccessible(member, isProtectedAllowed)) {
1888                continue;
1889              }
1890              if (memberPred == null || memberPred(member)) {
1891                wrapper.AddMember(member);
1892              }
1893            }
1894            var declaring = def.DeclaringTypeDefinition;
1895            while (declaring != null) {
1896              foreach (var member in declaring.GetMembers (m => m.IsStatic)) {
1897                if (memberPred == null || memberPred(member)) {
1898                  wrapper.AddMember(member);
1899                }
1900              }
1901              declaring = declaring.DeclaringTypeDefinition;
1902            }
1903          }
1904        }
1905        if (ctx.CurrentTypeDefinition != null) {
1906          foreach (var p in ctx.CurrentTypeDefinition.TypeParameters) {
1907            wrapper.AddTypeParameter(p);
1908          }
1909        }
1910      }
1911      var scope = ctx.CurrentUsingScope;
1912
1913      for (var n = scope; n != null; n = n.Parent) {
1914        foreach (var pair in n.UsingAliases) {
1915          wrapper.AddAlias(pair.Key);
1916        }
1917        foreach (var alias in n.ExternAliases) {
1918          wrapper.AddAlias(alias);
1919        }
1920        foreach (var u in n.Usings) {
1921          foreach (var type in u.Types) {
1922            if (!lookup.IsAccessible(type, false))
1923              continue;
1924
1925            IType addType = typePred != null ? typePred(type) : type;
1926
1927            if (onlyAddConstructors && addType != null) {
1928              if (!addType.GetConstructors().Any(c => lookup.IsAccessible(c, true)))
1929                continue;
1930            }
1931
1932            if (addType != null) {
1933              var a = onlyAddConstructors ? wrapper.AddConstructors(addType, false, IsAttributeContext(node)) : wrapper.AddType(addType, false, IsAttributeContext(node));
1934              if (a != null && callback != null) {
1935                callback(a, type);
1936              }
1937            }
1938          }
1939        }
1940
1941        foreach (var type in n.Namespace.Types) {
1942          if (!lookup.IsAccessible(type, false))
1943            continue;
1944          IType addType = typePred != null ? typePred(type) : type;
1945          if (onlyAddConstructors && addType != null) {
1946            if (!addType.GetConstructors().Any(c => lookup.IsAccessible(c, true)))
1947              continue;
1948          }
1949
1950          if (addType != null) {
1951            var a2 = onlyAddConstructors ? wrapper.AddConstructors(addType, false, IsAttributeContext(node)) : wrapper.AddType(addType, false);
1952            if (a2 != null && callback != null) {
1953              callback(a2, type);
1954            }
1955          }
1956        }
1957      }
1958
1959      for (var n = scope; n != null; n = n.Parent) {
1960        foreach (var curNs in n.Namespace.ChildNamespaces) {
1961          wrapper.AddNamespace(lookup, curNs);
1962        }
1963      }
1964
1965      if (node is AstType && node.Parent is Constraint && IncludeKeywordsInCompletionList) {
1966        wrapper.AddCustom("new()");
1967      }
1968
1969      if (AutomaticallyAddImports) {
1970        state = GetState();
1971        ICompletionData[] importData;
1972
1973        var namespaces = new List<INamespace>();
1974        for (var n = ctx.CurrentUsingScope; n != null; n = n.Parent) {
1975          namespaces.Add(n.Namespace);
1976          foreach (var u in n.Usings)
1977            namespaces.Add(u);
1978        }
1979
1980        if (this.CompletionEngineCache != null && ListEquals(namespaces, CompletionEngineCache.namespaces)) {
1981          importData = CompletionEngineCache.importCompletion;
1982        } else {
1983          // flatten usings
1984          var importList = new List<ICompletionData>();
1985          var dict = new Dictionary<string, Dictionary<string, ICompletionData>>();
1986          foreach (var type in Compilation.GetTopLevelTypeDefinitons ()) {
1987            if (!lookup.IsAccessible(type, false))
1988              continue;
1989            if (namespaces.Any(n => n.FullName == type.Namespace))
1990              continue;
1991            bool useFullName = false;
1992            foreach (var ns in namespaces) {
1993              if (ns.GetTypeDefinition(type.Name, type.TypeParameterCount) != null) {
1994                useFullName = true;
1995                break;
1996              }
1997            }
1998
1999            if (onlyAddConstructors) {
2000              if (!type.GetConstructors().Any(c => lookup.IsAccessible(c, true)))
2001                continue;
2002            }
2003            var data = factory.CreateImportCompletionData(type, useFullName, onlyAddConstructors);
2004            Dictionary<string, ICompletionData> createdDict;
2005            if (!dict.TryGetValue(type.Name, out createdDict)) {
2006              createdDict = new Dictionary<string, ICompletionData>();
2007              dict.Add(type.Name, createdDict);
2008            }
2009            ICompletionData oldData;
2010            if (!createdDict.TryGetValue(type.Namespace, out oldData)) {
2011              importList.Add(data);
2012              createdDict.Add(type.Namespace, data);
2013            } else {
2014              oldData.AddOverload(data);
2015            }
2016          }
2017
2018          importData = importList.ToArray();
2019          if (CompletionEngineCache != null) {
2020            CompletionEngineCache.namespaces = namespaces;
2021            CompletionEngineCache.importCompletion = importData;
2022          }
2023        }
2024        foreach (var data in importData) {
2025          wrapper.Result.Add(data);
2026        }
2027
2028
2029      }
2030
2031    }
2032
2033    IEnumerable<ICompletionData> HandleKeywordCompletion(int wordStart, string word)
2034    {
2035      if (IsInsideCommentStringOrDirective()) {
2036        if (IsInPreprocessorDirective()) {
2037          if (word == "if" || word == "elif") {
2038            if (wordStart > 0 && document.GetCharAt(wordStart - 1) == '#') {
2039              return factory.CreatePreProcessorDefinesCompletionData();
2040            }
2041          }
2042        }
2043        return null;
2044      }
2045      switch (word) {
2046        case "namespace":
2047          return null;
2048        case "using":
2049          if (currentType != null) {
2050            return null;
2051          }
2052          var wrapper = new CompletionDataWrapper(this);
2053          AddTypesAndNamespaces(wrapper, GetState(), null, t => null);
2054          return wrapper.Result;
2055        case "case":
2056          return CreateCaseCompletionData(location);
2057          //        case ",":
2058          //        case ":":
2059          //          if (result.ExpressionContext == ExpressionContext.InheritableType) {
2060          //            IType cls = NRefactoryResolver.GetTypeAtCursor (Document.CompilationUnit, Document.FileName, new TextLocation (completionContext.TriggerLine, completionContext.TriggerLineOffset));
2061          //            CompletionDataList completionList = new ProjectDomCompletionDataList ();
2062          //            List<string > namespaceList = GetUsedNamespaces ();
2063          //            var col = new CSharpTextEditorCompletion.CompletionDataCollector (this, dom, completionList, Document.CompilationUnit, null, location);
2064          //            bool isInterface = false;
2065          //            HashSet<string > baseTypeNames = new HashSet<string> ();
2066          //            if (cls != null) {
2067          //              baseTypeNames.Add (cls.Name);
2068          //              if (cls.ClassType == ClassType.Struct)
2069          //                isInterface = true;
2070          //            }
2071          //            int tokenIndex = offset;
2072          // 
2073          //            // Search base types " : [Type1, ... ,TypeN,] <Caret>"
2074          //            string token = null;
2075          //            do {
2076          //              token = GetPreviousToken (ref tokenIndex, false);
2077          //              if (string.IsNullOrEmpty (token))
2078          //                break;
2079          //              token = token.Trim ();
2080          //              if (Char.IsLetterOrDigit (token [0]) || token [0] == '_') {
2081          //                IType baseType = dom.SearchType (Document.CompilationUnit, cls, result.Region.Start, token);
2082          //                if (baseType != null) {
2083          //                  if (baseType.ClassType != ClassType.Interface)
2084          //                    isInterface = true;
2085          //                  baseTypeNames.Add (baseType.Name);
2086          //                }
2087          //              }
2088          //            } while (token != ":");
2089          //            foreach (object o in dom.GetNamespaceContents (namespaceList, true, true)) {
2090          //              IType type = o as IType;
2091          //              if (type != null && (type.IsStatic || type.IsSealed || baseTypeNames.Contains (type.Name) || isInterface && type.ClassType != ClassType.Interface)) {
2092          //                continue;
2093          //              }
2094          //              if (o is Namespace && !namespaceList.Any (ns => ns.StartsWith (((Namespace)o).FullName)))
2095          //                continue;
2096          //              col.Add (o);
2097          //            }
2098          //            // Add inner classes
2099          //            Stack<IType > innerStack = new Stack<IType> ();
2100          //            innerStack.Push (cls);
2101          //            while (innerStack.Count > 0) {
2102          //              IType curType = innerStack.Pop ();
2103          //              if (curType == null)
2104          //                continue;
2105          //              foreach (IType innerType in curType.InnerTypes) {
2106          //                if (innerType != cls)
2107          //                  // don't add the calling class as possible base type
2108          //                  col.Add (innerType);
2109          //              }
2110          //              if (curType.DeclaringType != null)
2111          //                innerStack.Push (curType.DeclaringType);
2112          //            }
2113          //            return completionList;
2114          //          }
2115          //          break;
2116        case "is":
2117        case "as":
2118          if (currentType == null) {
2119            return null;
2120          }
2121          IType isAsType = null;
2122          var isAsExpression = GetExpressionAt(wordStart);
2123          if (isAsExpression != null) {
2124            var parent = isAsExpression.Node.Parent;
2125            if (parent is VariableInitializer) {
2126              parent = parent.Parent;
2127            }
2128            var varDecl = parent as VariableDeclarationStatement;
2129            if (varDecl != null) {
2130              ExpressionResolveResult resolved;
2131              if (varDecl.Type.IsVar()) {
2132                resolved = null;
2133              } else {
2134                resolved = ResolveExpression(parent);
2135              }
2136              if (resolved != null) {
2137                isAsType = resolved.Result.Type;
2138              }
2139            }
2140          }
2141          var isAsWrapper = new CompletionDataWrapper(this);
2142          var def = isAsType != null ? isAsType.GetDefinition() : null;
2143          AddTypesAndNamespaces(
2144            isAsWrapper,
2145            GetState(),
2146            null,
2147            t => t.GetDefinition() == null || def == null || t.GetDefinition().IsDerivedFrom(def) ? t : null,
2148            m => false);
2149          AddKeywords(isAsWrapper, primitiveTypesKeywords);
2150          return isAsWrapper.Result;
2151          //          {
2152          //            CompletionDataList completionList = new ProjectDomCompletionDataList ();
2153          //            ExpressionResult expressionResult = FindExpression (dom, completionContext, wordStart - document.Caret.Offset);
2154          //            NRefactoryResolver resolver = CreateResolver ();
2155          //            ResolveResult resolveResult = resolver.Resolve (expressionResult, new TextLocation (completionContext.TriggerLine, completionContext.TriggerLineOffset));
2156          //            if (resolveResult != null && resolveResult.ResolvedType != null) {
2157          //              CompletionDataCollector col = new CompletionDataCollector (this, dom, completionList, Document.CompilationUnit, resolver.CallingType, location);
2158          //              IType foundType = null;
2159          //              if (word == "as") {
2160          //                ExpressionContext exactContext = new NewCSharpExpressionFinder (dom).FindExactContextForAsCompletion (document, Document.CompilationUnit, Document.FileName, resolver.CallingType);
2161          //                if (exactContext is ExpressionContext.TypeExpressionContext) {
2162          //                  foundType = resolver.SearchType (((ExpressionContext.TypeExpressionContext)exactContext).Type);
2163          //                  AddAsCompletionData (col, foundType);
2164          //                }
2165          //              }
2166          //           
2167          //              if (foundType == null)
2168          //                foundType = resolver.SearchType (resolveResult.ResolvedType);
2169          //           
2170          //              if (foundType != null) {
2171          //                if (foundType.ClassType == ClassType.Interface)
2172          //                  foundType = resolver.SearchType (DomReturnType.Object);
2173          //             
2174          //                foreach (IType type in dom.GetSubclasses (foundType)) {
2175          //                  if (type.IsSpecialName || type.Name.StartsWith ("<"))
2176          //                    continue;
2177          //                  AddAsCompletionData (col, type);
2178          //                }
2179          //              }
2180          //              List<string > namespaceList = GetUsedNamespaces ();
2181          //              foreach (object o in dom.GetNamespaceContents (namespaceList, true, true)) {
2182          //                if (o is IType) {
2183          //                  IType type = (IType)o;
2184          //                  if (type.ClassType != ClassType.Interface || type.IsSpecialName || type.Name.StartsWith ("<"))
2185          //                    continue;
2186          //  //                if (foundType != null && !dom.GetInheritanceTree (foundType).Any (x => x.FullName == type.FullName))
2187          //  //                  continue;
2188          //                  AddAsCompletionData (col, type);
2189          //                  continue;
2190          //                }
2191          //                if (o is Namespace)
2192          //                  continue;
2193          //                col.Add (o);
2194          //              }
2195          //              return completionList;
2196          //            }
2197          //            result.ExpressionContext = ExpressionContext.TypeName;
2198          //            return CreateCtrlSpaceCompletionData (completionContext, result);
2199          //          }
2200        case "override":
2201          // Look for modifiers, in order to find the beginning of the declaration
2202          int firstMod = wordStart;
2203          int i = wordStart;
2204          for (int n = 0; n < 3; n++) {
2205            string mod = GetPreviousToken(ref i, true);
2206            if (mod == "public" || mod == "protected" || mod == "private" || mod == "internal" || mod == "sealed") {
2207              firstMod = i;
2208            } else if (mod == "static") {
2209              // static methods are not overridable
2210              return null;
2211            } else {
2212              break;
2213            }
2214          }
2215          if (!IsLineEmptyUpToEol()) {
2216            return null;
2217          }
2218          if (currentType != null && (currentType.Kind == TypeKind.Class || currentType.Kind == TypeKind.Struct)) {
2219            string modifiers = document.GetText(firstMod, wordStart - firstMod);
2220            return GetOverrideCompletionData(currentType, modifiers);
2221          }
2222          return null;
2223        case "partial":
2224          // Look for modifiers, in order to find the beginning of the declaration
2225          firstMod = wordStart;
2226          i = wordStart;
2227          for (int n = 0; n < 3; n++) {
2228            string mod = GetPreviousToken(ref i, true);
2229            if (mod == "public" || mod == "protected" || mod == "private" || mod == "internal" || mod == "sealed") {
2230              firstMod = i;
2231            } else if (mod == "static") {
2232              // static methods are not overridable
2233              return null;
2234            } else {
2235              break;
2236            }
2237          }
2238          if (!IsLineEmptyUpToEol()) {
2239            return null;
2240          }
2241          var state = GetState();
2242
2243          if (state.CurrentTypeDefinition != null && (state.CurrentTypeDefinition.Kind == TypeKind.Class || state.CurrentTypeDefinition.Kind == TypeKind.Struct)) {
2244            string modifiers = document.GetText(firstMod, wordStart - firstMod);
2245            return GetPartialCompletionData(state.CurrentTypeDefinition, modifiers);
2246          }
2247          return null;
2248
2249        case "public":
2250        case "protected":
2251        case "private":
2252        case "internal":
2253        case "sealed":
2254        case "static":
2255          var accessorContext = HandleAccessorContext();
2256          if (accessorContext != null) {
2257            return accessorContext;
2258          }
2259          return null;
2260        case "new":
2261          int j = offset - 4;
2262          //        string token = GetPreviousToken (ref j, true);
2263
2264          IType hintType = null;
2265          var expressionOrVariableDeclaration = GetNewExpressionAt(j);
2266          if (expressionOrVariableDeclaration == null)
2267            return null;
2268          var astResolver = CompletionContextProvider.GetResolver(GetState(), expressionOrVariableDeclaration.Node.Ancestors.FirstOrDefault(n => n is EntityDeclaration || n is SyntaxTree));
2269          hintType = TypeGuessing.GetValidTypes(
2270            astResolver,
2271            expressionOrVariableDeclaration.Node
2272          ).FirstOrDefault();
2273
2274          return CreateConstructorCompletionData(hintType);
2275        case "yield":
2276          var yieldDataList = new CompletionDataWrapper(this);
2277          DefaultCompletionString = "return";
2278          if (IncludeKeywordsInCompletionList) {
2279            yieldDataList.AddCustom("break");
2280            yieldDataList.AddCustom("return");
2281          }
2282          return yieldDataList.Result;
2283        case "in":
2284          var inList = new CompletionDataWrapper(this);
2285
2286          var expr = GetExpressionAtCursor();
2287          if (expr == null)
2288            return null;
2289          var rr = ResolveExpression(expr);
2290
2291          AddContextCompletion(
2292            inList,
2293            rr != null ? rr.Resolver : GetState(),
2294            expr.Node
2295          );
2296          return inList.Result;
2297      }
2298      return null;
2299    }
2300
2301    bool IsLineEmptyUpToEol()
2302    {
2303      var line = document.GetLineByNumber(location.Line);
2304      for (int j = offset; j < line.EndOffset; j++) {
2305        char ch = document.GetCharAt(j);
2306        if (!char.IsWhiteSpace(ch)) {
2307          return false;
2308        }
2309      }
2310      return true;
2311    }
2312
2313    string GetLineIndent(int lineNr)
2314    {
2315      var line = document.GetLineByNumber(lineNr);
2316      for (int j = line.Offset; j < line.EndOffset; j++) {
2317        char ch = document.GetCharAt(j);
2318        if (!char.IsWhiteSpace(ch)) {
2319          return document.GetText(line.Offset, j - line.Offset);
2320        }
2321      }
2322      return "";
2323    }
2324    //    static CSharpAmbience amb = new CSharpAmbience();
2325    class Category : CompletionCategory
2326    {
2327      public Category(string displayText, string icon) : base(displayText, icon)
2328      {
2329      }
2330
2331      public override int CompareTo(CompletionCategory other)
2332      {
2333        return 0;
2334      }
2335    }
2336
2337    IEnumerable<ICompletionData> CreateConstructorCompletionData(IType hintType)
2338    {
2339      var wrapper = new CompletionDataWrapper(this);
2340      var state = GetState();
2341      Func<IType, IType> pred = null;
2342      Action<ICompletionData, IType> typeCallback = null;
2343      var inferredTypesCategory = new Category("Inferred Types", null);
2344      var derivedTypesCategory = new Category("Derived Types", null);
2345
2346      if (hintType != null && (hintType.Kind != TypeKind.TypeParameter || IsTypeParameterInScope(hintType))) {
2347        if (hintType.Kind != TypeKind.Unknown) {
2348          var lookup = new MemberLookup(
2349            ctx.CurrentTypeDefinition,
2350            Compilation.MainAssembly
2351          );
2352          typeCallback = (data, t) => {
2353            //check if type is in inheritance tree.
2354            if (hintType.GetDefinition() != null &&
2355              t.GetDefinition() != null &&
2356              t.GetDefinition().IsDerivedFrom(hintType.GetDefinition())) {
2357              data.CompletionCategory = derivedTypesCategory;
2358            }
2359          };
2360          pred = t => {
2361            if (t.Kind == TypeKind.Interface && hintType.Kind != TypeKind.Array) {
2362              return null;
2363            }
2364            // check for valid constructors
2365            if (t.GetConstructors().Any()) {
2366              bool isProtectedAllowed = currentType != null ?
2367                currentType.Resolve(ctx).GetDefinition().IsDerivedFrom(t.GetDefinition()) : false;
2368              if (!t.GetConstructors().Any(m => lookup.IsAccessible(m, isProtectedAllowed))) {
2369                return null;
2370              }
2371            }
2372
2373            // check derived types
2374            var typeDef = t.GetDefinition();
2375            var hintDef = hintType.GetDefinition();
2376            if (typeDef != null && hintDef != null && typeDef.IsDerivedFrom(hintDef)) {
2377              var newType = wrapper.AddType(t, true);
2378              if (newType != null) {
2379                newType.CompletionCategory = inferredTypesCategory;
2380              }
2381            }
2382
2383            // check type inference
2384            var typeInference = new TypeInference(Compilation);
2385            typeInference.Algorithm = TypeInferenceAlgorithm.ImprovedReturnAllResults;
2386
2387            var inferedType = typeInference.FindTypeInBounds(new [] { t }, new [] { hintType });
2388            if (inferedType != SpecialType.UnknownType) {
2389              var newType = wrapper.AddType(inferedType, true);
2390              if (newType != null) {
2391                newType.CompletionCategory = inferredTypesCategory;
2392              }
2393              return null;
2394            }
2395            return t;
2396          };
2397          if (!(hintType.Kind == TypeKind.Interface && hintType.Kind != TypeKind.Array)) {
2398            var hint = wrapper.AddType(hintType, true);
2399            if (hint != null) {
2400              DefaultCompletionString = hint.DisplayText;
2401              hint.CompletionCategory = derivedTypesCategory;
2402            }
2403          }
2404          if (hintType is ParameterizedType && hintType.TypeParameterCount == 1 && hintType.FullName == "System.Collections.Generic.IEnumerable") {
2405            var arg = ((ParameterizedType)hintType).TypeArguments.FirstOrDefault();
2406            if (arg.Kind != TypeKind.TypeParameter) {
2407              var array = new ArrayType(ctx.Compilation, arg, 1);
2408              wrapper.AddType(array, true);
2409            }
2410          }
2411        } else {
2412          var hint = wrapper.AddType(hintType, true);
2413          if (hint != null) {
2414            DefaultCompletionString = hint.DisplayText;
2415            hint.CompletionCategory = derivedTypesCategory;
2416          }
2417        }
2418      }
2419      AddTypesAndNamespaces(wrapper, state, null, pred, m => false, typeCallback, true);
2420      if (hintType == null || hintType == SpecialType.UnknownType) {
2421        AddKeywords(wrapper, primitiveTypesKeywords.Where(k => k != "void"));
2422      }
2423
2424      CloseOnSquareBrackets = true;
2425      AutoCompleteEmptyMatch = true;
2426      AutoCompleteEmptyMatchOnCurlyBracket = false;
2427      return wrapper.Result;
2428    }
2429
2430    bool IsTypeParameterInScope(IType hintType)
2431    {
2432      var tp = hintType as ITypeParameter;
2433      var ownerName = tp.Owner.ReflectionName;
2434      if (currentMember != null && ownerName == currentMember.ReflectionName)
2435        return true;
2436      var ot = currentType;
2437      while (ot != null) {
2438        if (ownerName == ot.ReflectionName)
2439          return true;
2440        ot = ot.DeclaringTypeDefinition;
2441      }
2442      return false;
2443    }
2444
2445    IEnumerable<ICompletionData> GetOverrideCompletionData(IUnresolvedTypeDefinition type, string modifiers)
2446    {
2447      var wrapper = new CompletionDataWrapper(this);
2448      var alreadyInserted = new List<IMember>();
2449      //bool addedVirtuals = false;
2450
2451      int declarationBegin = offset;
2452      int j = declarationBegin;
2453      for (int i = 0; i < 3; i++) {
2454        switch (GetPreviousToken(ref j, true)) {
2455          case "public":
2456          case "protected":
2457          case "private":
2458          case "internal":
2459          case "sealed":
2460          case "override":
2461          case "partial":
2462          case "async":
2463            declarationBegin = j;
2464            break;
2465          case "static":
2466            return null; // don't add override completion for static members
2467        }
2468      }
2469      AddVirtuals(
2470        alreadyInserted,
2471        wrapper,
2472        modifiers,
2473        type.Resolve(ctx),
2474        declarationBegin
2475      );
2476      return wrapper.Result;
2477    }
2478
2479    IEnumerable<ICompletionData> GetPartialCompletionData(ITypeDefinition type, string modifiers)
2480    {
2481      var wrapper = new CompletionDataWrapper(this);
2482      int declarationBegin = offset;
2483      int j = declarationBegin;
2484      for (int i = 0; i < 3; i++) {
2485        switch (GetPreviousToken(ref j, true)) {
2486          case "public":
2487          case "protected":
2488          case "private":
2489          case "internal":
2490          case "sealed":
2491          case "override":
2492          case "partial":
2493          case "async":
2494            declarationBegin = j;
2495            break;
2496          case "static":
2497            return null; // don't add override completion for static members
2498        }
2499      }
2500
2501      var methods = new List<IUnresolvedMethod>();
2502
2503      foreach (var part in type.Parts) {
2504        foreach (var method in part.Methods) {
2505          if (method.BodyRegion.IsEmpty) {
2506            if (GetImplementation(type, method) != null) {
2507              continue;
2508            }
2509            methods.Add(method);
2510          }
2511        }
2512      }
2513
2514      foreach (var method in methods) {
2515        wrapper.Add(factory.CreateNewPartialCompletionData(
2516          declarationBegin,
2517          method.DeclaringTypeDefinition,
2518          method
2519        )
2520        );
2521      }
2522
2523      return wrapper.Result;
2524    }
2525
2526    IMethod GetImplementation(ITypeDefinition type, IUnresolvedMethod method)
2527    {
2528      foreach (var cur in type.Methods) {
2529        if (cur.Name == method.Name && cur.Parameters.Count == method.Parameters.Count && !cur.BodyRegion.IsEmpty) {
2530          bool equal = true;
2531          /*          for (int i = 0; i < cur.Parameters.Count; i++) {
2532            if (!cur.Parameters [i].Type.Equals (method.Parameters [i].Type)) {
2533              equal = false;
2534              break;
2535            }
2536          }*/
2537          if (equal) {
2538            return cur;
2539          }
2540        }
2541      }
2542      return null;
2543    }
2544
2545    protected virtual void AddVirtuals(List<IMember> alreadyInserted, CompletionDataWrapper col, string modifiers, IType curType, int declarationBegin)
2546    {
2547      if (curType == null) {
2548        return;
2549      }
2550      foreach (var m in curType.GetMembers ().Reverse ()) {
2551        if (curType.Kind != TypeKind.Interface && !m.IsOverridable) {
2552          continue;
2553        }
2554        // filter out the "Finalize" methods, because finalizers should be done with destructors.
2555        if (m is IMethod && m.Name == "Finalize") {
2556          continue;
2557        }
2558
2559        var data = factory.CreateNewOverrideCompletionData(
2560          declarationBegin,
2561          currentType,
2562          m
2563        );
2564        // check if the member is already implemented
2565        bool foundMember = curType.GetMembers().Any(cm => SignatureComparer.Ordinal.Equals(
2566          cm,
2567          m
2568        ) && cm.DeclaringTypeDefinition == curType.GetDefinition()
2569        );
2570        if (foundMember) {
2571          continue;
2572        }
2573        if (alreadyInserted.Any(cm => SignatureComparer.Ordinal.Equals(cm, m)))
2574          continue;
2575        alreadyInserted.Add(m);
2576        data.CompletionCategory = col.GetCompletionCategory(m.DeclaringTypeDefinition);
2577        col.Add(data);
2578      }
2579    }
2580
2581    void AddKeywords(CompletionDataWrapper wrapper, IEnumerable<string> keywords)
2582    {
2583      if (!IncludeKeywordsInCompletionList)
2584        return;
2585      foreach (string keyword in keywords) {
2586        if (wrapper.Result.Any(data => data.DisplayText == keyword))
2587          continue;
2588        wrapper.AddCustom(keyword);
2589      }
2590    }
2591
2592    public string GuessEventHandlerMethodName(int tokenIndex, string surroundingTypeName)
2593    {
2594      var names = new List<string>();
2595     
2596      string eventName = GetPreviousToken(ref tokenIndex, false);
2597      string result = GetPreviousToken(ref tokenIndex, false);
2598      if (result != ".") {
2599        if (surroundingTypeName == null) {
2600          eventName = "Handle" + eventName;
2601        } else {
2602          names.Add(surroundingTypeName);
2603        }
2604      }
2605      while (result == ".") {
2606        result = GetPreviousToken(ref tokenIndex, false);
2607        if (result == "this") {
2608          if (names.Count == 0) {
2609            if (surroundingTypeName == null) {
2610              eventName = "Handle" + eventName;
2611            } else {
2612              names.Add(surroundingTypeName);
2613            }
2614          }
2615        } else if (result != null) {
2616          string trimmedName = result.Trim();
2617          if (trimmedName.Length == 0) {
2618            break;
2619          }
2620          names.Insert(0, trimmedName);
2621        }
2622        result = GetPreviousToken(ref tokenIndex, false);
2623      }
2624      if (!string.IsNullOrEmpty(eventName)) {
2625        names.Add(eventName);
2626      }
2627      result = String.Join("_", names.ToArray());
2628      foreach (char ch in result) {
2629        if (!char.IsLetterOrDigit(ch) && ch != '_') {
2630          result = "";
2631          break;
2632        }
2633      }
2634      return result;
2635    }
2636
2637    bool MatchDelegate(IType delegateType, IMethod method)
2638    {
2639      if (method.SymbolKind != SymbolKind.Method)
2640        return false;
2641      var delegateMethod = delegateType.GetDelegateInvokeMethod();
2642      if (delegateMethod == null || delegateMethod.Parameters.Count != method.Parameters.Count) {
2643        return false;
2644      }
2645
2646      for (int i = 0; i < delegateMethod.Parameters.Count; i++) {
2647        if (!delegateMethod.Parameters [i].Type.Equals(method.Parameters [i].Type)) {
2648          return false;
2649        }
2650      }
2651      return true;
2652    }
2653
2654    string AddDelegateHandlers(CompletionDataWrapper completionList, IType delegateType, bool addSemicolon = true, bool addDefault = true, string optDelegateName = null)
2655    {
2656      IMethod delegateMethod = delegateType.GetDelegateInvokeMethod();
2657      PossibleDelegates.Add(delegateMethod);
2658      var thisLineIndent = GetLineIndent(location.Line);
2659      string delegateEndString = EolMarker + thisLineIndent + "}" + (addSemicolon ? ";" : "");
2660      //bool containsDelegateData = completionList.Result.Any(d => d.DisplayText.StartsWith("delegate("));
2661      if (addDefault && !completionList.AnonymousDelegateAdded) {
2662        completionList.AnonymousDelegateAdded = true;
2663        var oldDelegate = completionList.Result.FirstOrDefault(cd => cd.DisplayText == "delegate");
2664        if (oldDelegate != null)
2665          completionList.Result.Remove(oldDelegate);
2666        completionList.AddCustom(
2667          "delegate",
2668          "Creates anonymous delegate.",
2669          "delegate {" + EolMarker + thisLineIndent + IndentString + "|" + delegateEndString
2670        ).DisplayFlags |= DisplayFlags.MarkedBold;
2671        if (LanguageVersion.Major >= 5) {
2672          completionList.AddCustom(
2673            "async delegate",
2674            "Creates anonymous async delegate.",
2675            "async delegate {" + EolMarker + thisLineIndent + IndentString + "|" + delegateEndString
2676          ).DisplayFlags |= DisplayFlags.MarkedBold;
2677        }
2678      }
2679      var sb = new StringBuilder("(");
2680      var sbWithoutTypes = new StringBuilder("(");
2681      var state = GetState();
2682      var builder = new TypeSystemAstBuilder(state);
2683
2684      for (int k = 0; k < delegateMethod.Parameters.Count; k++) {
2685
2686        if (k > 0) {
2687          sb.Append(", ");
2688          sbWithoutTypes.Append(", ");
2689        }
2690        var convertedParameter = builder.ConvertParameter(delegateMethod.Parameters [k]);
2691        if (convertedParameter.ParameterModifier == ParameterModifier.Params)
2692          convertedParameter.ParameterModifier = ParameterModifier.None;
2693        sb.Append(convertedParameter.ToString(FormattingPolicy));
2694        sbWithoutTypes.Append(delegateMethod.Parameters [k].Name);
2695      }
2696
2697      sb.Append(")");
2698      sbWithoutTypes.Append(")");
2699      var signature = sb.ToString();
2700      if (!completionList.HasAnonymousDelegateAdded(signature)) {
2701        completionList.AddAnonymousDelegateAdded(signature);
2702
2703        completionList.AddCustom(
2704          "delegate" + signature,
2705          "Creates anonymous delegate.",
2706          "delegate" + signature + " {" + EolMarker + thisLineIndent + IndentString + "|" + delegateEndString
2707        ).DisplayFlags |= DisplayFlags.MarkedBold;
2708        if (LanguageVersion.Major >= 5) {
2709          completionList.AddCustom(
2710            "async delegate" + signature,
2711            "Creates anonymous async delegate.",
2712            "async delegate" + signature + " {" + EolMarker + thisLineIndent + IndentString + "|" + delegateEndString
2713          ).DisplayFlags |= DisplayFlags.MarkedBold;
2714        }
2715        if (!completionList.Result.Any(data => data.DisplayText == sb.ToString())) {
2716          completionList.AddCustom(
2717            signature,
2718            "Creates typed lambda expression.",
2719            signature + " => |" + (addSemicolon ? ";" : "")
2720          ).DisplayFlags |= DisplayFlags.MarkedBold;
2721          if (LanguageVersion.Major >= 5) {
2722            completionList.AddCustom(
2723              "async " + signature,
2724              "Creates typed async lambda expression.",
2725              "async " + signature + " => |" + (addSemicolon ? ";" : "")
2726            ).DisplayFlags |= DisplayFlags.MarkedBold;
2727          }
2728
2729          if (!delegateMethod.Parameters.Any(p => p.IsOut || p.IsRef) && !completionList.Result.Any(data => data.DisplayText == sbWithoutTypes.ToString())) {
2730            completionList.AddCustom(
2731              sbWithoutTypes.ToString(),
2732              "Creates lambda expression.",
2733              sbWithoutTypes + " => |" + (addSemicolon ? ";" : "")
2734            ).DisplayFlags |= DisplayFlags.MarkedBold;
2735            if (LanguageVersion.Major >= 5) {
2736              completionList.AddCustom(
2737                "async " + sbWithoutTypes,
2738                "Creates async lambda expression.",
2739                "async " + sbWithoutTypes + " => |" + (addSemicolon ? ";" : "")
2740              ).DisplayFlags |= DisplayFlags.MarkedBold;
2741            }
2742          }
2743        }
2744
2745      }
2746
2747      string varName = optDelegateName ?? "Handle" + delegateType.Name;
2748
2749      var ecd = factory.CreateEventCreationCompletionData(varName, delegateType, null, signature, currentMember, currentType);
2750      ecd.DisplayFlags |= DisplayFlags.MarkedBold;
2751      completionList.Add(ecd);
2752
2753      return sb.ToString();
2754    }
2755
2756    bool IsAccessibleFrom(IEntity member, ITypeDefinition calledType, IMember currentMember, bool includeProtected)
2757    {
2758      if (currentMember == null) {
2759        return member.IsStatic || member.IsPublic;
2760      }
2761      //      if (currentMember is MonoDevelop.Projects.Dom.BaseResolveResult.BaseMemberDecorator)
2762      //        return member.IsPublic | member.IsProtected;
2763      //    if (member.IsStatic && !IsStatic)
2764      //      return false;
2765      if (member.IsPublic || calledType != null && calledType.Kind == TypeKind.Interface && !member.IsProtected) {
2766        return true;
2767      }
2768      if (member.DeclaringTypeDefinition != null) {
2769        if (member.DeclaringTypeDefinition.Kind == TypeKind.Interface) {
2770          return IsAccessibleFrom(
2771            member.DeclaringTypeDefinition,
2772            calledType,
2773            currentMember,
2774            includeProtected
2775          );
2776        }
2777
2778        if (member.IsProtected && !(member.DeclaringTypeDefinition.IsProtectedOrInternal && !includeProtected)) {
2779          return includeProtected;
2780        }
2781      }
2782      if (member.IsInternal || member.IsProtectedAndInternal || member.IsProtectedOrInternal) {
2783        //var type1 = member is ITypeDefinition ? (ITypeDefinition)member : member.DeclaringTypeDefinition;
2784        //var type2 = currentMember is ITypeDefinition ? (ITypeDefinition)currentMember : currentMember.DeclaringTypeDefinition;
2785        bool result = true;
2786        // easy case, projects are the same
2787        /*        //        if (type1.ProjectContent == type2.ProjectContent) {
2788        //          result = true;
2789        //        } else
2790        if (type1.ProjectContent != null) {
2791          // maybe type2 hasn't project dom set (may occur in some cases), check if the file is in the project
2792          //TODO !!
2793          //          result = type1.ProjectContent.Annotation<MonoDevelop.Projects.Project> ().GetProjectFile (type2.Region.FileName) != null;
2794          result = false;
2795        } else if (type2.ProjectContent != null) {
2796          //TODO!!
2797          //          result = type2.ProjectContent.Annotation<MonoDevelop.Projects.Project> ().GetProjectFile (type1.Region.FileName) != null;
2798          result = false;
2799        } else {
2800          // should never happen !
2801          result = true;
2802        }*/
2803        return member.IsProtectedAndInternal ? includeProtected && result : result;
2804      }
2805
2806      if (!(currentMember is IType) && (currentMember.DeclaringTypeDefinition == null || member.DeclaringTypeDefinition == null)) {
2807        return false;
2808      }
2809
2810      // inner class
2811      var declaringType = currentMember.DeclaringTypeDefinition;
2812      while (declaringType != null) {
2813        if (declaringType.ReflectionName == currentMember.DeclaringType.ReflectionName) {
2814          return true;
2815        }
2816        declaringType = declaringType.DeclaringTypeDefinition;
2817      }
2818
2819
2820      return currentMember.DeclaringTypeDefinition != null && member.DeclaringTypeDefinition.FullName == currentMember.DeclaringTypeDefinition.FullName;
2821    }
2822
2823    static bool IsAttributeContext(AstNode node)
2824    {
2825      AstNode n = node;
2826      while (n is AstType) {
2827        n = n.Parent;
2828      }
2829      return n is Attribute;
2830    }
2831
2832    IEnumerable<ICompletionData> CreateTypeAndNamespaceCompletionData(TextLocation location, ResolveResult resolveResult, AstNode resolvedNode, CSharpResolver state)
2833    {
2834      if (resolveResult == null || resolveResult.IsError) {
2835        return null;
2836      }
2837      var exprParent = resolvedNode.GetParent<Expression>();
2838      var unit = exprParent != null ? exprParent.GetParent<SyntaxTree>() : null;
2839
2840      var astResolver = unit != null ? CompletionContextProvider.GetResolver(state, unit) : null;
2841      IType hintType = exprParent != null && astResolver != null ?
2842        TypeGuessing.GetValidTypes(astResolver, exprParent).FirstOrDefault() :
2843        null;
2844      var result = new CompletionDataWrapper(this);
2845      var lookup = new MemberLookup(
2846        ctx.CurrentTypeDefinition,
2847        Compilation.MainAssembly
2848      );
2849      if (resolveResult is NamespaceResolveResult) {
2850        var nr = (NamespaceResolveResult)resolveResult;
2851        if (!(resolvedNode.Parent is UsingDeclaration || resolvedNode.Parent != null && resolvedNode.Parent.Parent is UsingDeclaration)) {
2852          foreach (var cl in nr.Namespace.Types) {
2853            if (hintType != null && hintType.Kind != TypeKind.Array && cl.Kind == TypeKind.Interface) {
2854              continue;
2855            }
2856            if (!lookup.IsAccessible(cl, false))
2857              continue;
2858            result.AddType(cl, false, IsAttributeContext(resolvedNode));
2859          }
2860        }
2861        foreach (var ns in nr.Namespace.ChildNamespaces) {
2862          result.AddNamespace(lookup, ns);
2863        }
2864      } else if (resolveResult is TypeResolveResult) {
2865        var type = resolveResult.Type;
2866        foreach (var nested in type.GetNestedTypes ()) {
2867          if (hintType != null && hintType.Kind != TypeKind.Array && nested.Kind == TypeKind.Interface) {
2868            continue;
2869          }
2870          var def = nested.GetDefinition();
2871          if (def != null && !lookup.IsAccessible(def, false))
2872            continue;
2873          result.AddType(nested, false);
2874        }
2875      }
2876      return result.Result;
2877    }
2878
2879    IEnumerable<ICompletionData> CreateTypeList()
2880    {
2881      foreach (var cl in Compilation.RootNamespace.Types) {
2882        yield return factory.CreateTypeCompletionData(cl, false, false, false);
2883      }
2884
2885      foreach (var ns in Compilation.RootNamespace.ChildNamespaces) {
2886        yield return factory.CreateNamespaceCompletionData(ns);
2887      }
2888    }
2889
2890    void CreateParameterForInvocation(CompletionDataWrapper result, IMethod method, CSharpResolver state, int parameter, HashSet<string> addedEnums, HashSet<string> addedDelegates)
2891    {
2892      if (method.Parameters.Count <= parameter) {
2893        return;
2894      }
2895      var resolvedType = method.Parameters [parameter].Type;
2896      if (resolvedType.Kind == TypeKind.Enum) {
2897        if (addedEnums.Contains(resolvedType.ReflectionName)) {
2898          return;
2899        }
2900        addedEnums.Add(resolvedType.ReflectionName);
2901        AddEnumMembers(result, resolvedType, state);
2902        return;
2903      }
2904
2905      if (resolvedType.Kind == TypeKind.Delegate) {
2906        if (addedDelegates.Contains(resolvedType.ReflectionName))
2907          return;
2908        AddDelegateHandlers(result, resolvedType, false, true, "Handle" + method.Parameters [parameter].Type.Name + method.Parameters [parameter].Name);
2909      }
2910    }
2911
2912    IEnumerable<ICompletionData> CreateParameterCompletion(MethodGroupResolveResult resolveResult, CSharpResolver state, AstNode invocation, SyntaxTree unit, int parameter, bool controlSpace)
2913    {
2914      var result = new CompletionDataWrapper(this);
2915      var addedEnums = new HashSet<string>();
2916      var addedDelegates = new HashSet<string>();
2917
2918      foreach (var method in resolveResult.Methods) {
2919        CreateParameterForInvocation(result, method, state, parameter, addedEnums, addedDelegates);
2920      }
2921      foreach (var methods in resolveResult.GetEligibleExtensionMethods (true)) {
2922        foreach (var method in methods) {
2923          if (resolveResult.Methods.Contains(method))
2924            continue;
2925          CreateParameterForInvocation(result, new ReducedExtensionMethod(method), state, parameter, addedEnums, addedDelegates);
2926        }
2927      }
2928
2929      foreach (var method in resolveResult.Methods) {
2930        if (parameter < method.Parameters.Count && method.Parameters [parameter].Type.Kind == TypeKind.Delegate) {
2931          AutoSelect = false;
2932          AutoCompleteEmptyMatch = false;
2933        }
2934        foreach (var p in method.Parameters) {
2935          result.AddNamedParameterVariable(p);
2936        }
2937      }
2938
2939      if (!controlSpace) {
2940        if (addedEnums.Count + addedDelegates.Count == 0) {
2941          return Enumerable.Empty<ICompletionData>();
2942        }
2943        AutoCompleteEmptyMatch = false;
2944        AutoSelect = false;
2945      }
2946      AddContextCompletion(result, state, invocation);
2947
2948      //      resolver.AddAccessibleCodeCompletionData (ExpressionContext.MethodBody, cdc);
2949      //      if (addedDelegates.Count > 0) {
2950      //        foreach (var data in result.Result) {
2951      //          if (data is MemberCompletionData)
2952      //            ((MemberCompletionData)data).IsDelegateExpected = true;
2953      //        }
2954      //      }
2955      return result.Result;
2956    }
2957
2958    void AddEnumMembers(CompletionDataWrapper completionList, IType resolvedType, CSharpResolver state)
2959    {
2960      if (resolvedType.Kind != TypeKind.Enum) {
2961        return;
2962      }
2963      var type = completionList.AddEnumMembers(resolvedType, state);
2964      if (type != null)
2965        DefaultCompletionString = type.DisplayText;
2966    }
2967
2968    IEnumerable<ICompletionData> CreateCompletionData(TextLocation location, ResolveResult resolveResult, AstNode resolvedNode, CSharpResolver state, Func<IType, IType> typePred = null)
2969    {
2970      if (resolveResult == null /*      || resolveResult.IsError*/) {
2971        return null;
2972      }
2973
2974      var lookup = new MemberLookup(
2975        ctx.CurrentTypeDefinition,
2976        Compilation.MainAssembly
2977      );
2978
2979      if (resolveResult is NamespaceResolveResult) {
2980        var nr = (NamespaceResolveResult)resolveResult;
2981        var namespaceContents = new CompletionDataWrapper(this);
2982
2983        foreach (var cl in nr.Namespace.Types) {
2984          if (!lookup.IsAccessible(cl, false))
2985            continue;
2986          IType addType = typePred != null ? typePred(cl) : cl;
2987          if (addType != null)
2988            namespaceContents.AddType(addType, false);
2989        }
2990
2991        foreach (var ns in nr.Namespace.ChildNamespaces) {
2992          namespaceContents.AddNamespace(lookup, ns);
2993        }
2994        return namespaceContents.Result;
2995      }
2996      IType type = resolveResult.Type;
2997
2998      if (type.Namespace == "System" && type.Name == "Void")
2999        return null;
3000
3001      if (resolvedNode.Parent is PointerReferenceExpression && (type is PointerType)) {
3002        resolveResult = new OperatorResolveResult(((PointerType)type).ElementType, System.Linq.Expressions.ExpressionType.Extension, resolveResult);
3003      }
3004
3005      //var typeDef = resolveResult.Type.GetDefinition();
3006      var result = new CompletionDataWrapper(this);
3007      bool includeStaticMembers = false;
3008
3009      if (resolveResult is LocalResolveResult) {
3010        if (resolvedNode is IdentifierExpression) {
3011          var mrr = (LocalResolveResult)resolveResult;
3012          includeStaticMembers = mrr.Variable.Name == mrr.Type.Name;
3013        }
3014      }
3015      if (resolveResult is TypeResolveResult && type.Kind == TypeKind.Enum) {
3016        foreach (var field in type.GetFields ()) {
3017          if (!lookup.IsAccessible(field, false))
3018            continue;
3019          result.AddMember(field);
3020        }
3021        return result.Result;
3022      }
3023
3024      bool isProtectedAllowed = lookup.IsProtectedAccessAllowed(resolveResult);
3025      bool skipNonStaticMembers = (resolveResult is TypeResolveResult);
3026
3027      if (resolveResult is MemberResolveResult && resolvedNode is IdentifierExpression) {
3028        var mrr = (MemberResolveResult)resolveResult;
3029        includeStaticMembers = mrr.Member.Name == mrr.Type.Name;
3030
3031        TypeResolveResult trr;
3032        if (state.IsVariableReferenceWithSameType(
3033          resolveResult,
3034          ((IdentifierExpression)resolvedNode).Identifier,
3035          out trr
3036        )) {
3037          if (currentMember != null && mrr.Member.IsStatic ^ currentMember.IsStatic) {
3038            skipNonStaticMembers = true;
3039
3040            if (trr.Type.Kind == TypeKind.Enum) {
3041              foreach (var field in trr.Type.GetFields ()) {
3042                if (lookup.IsAccessible(field, false))
3043                  result.AddMember(field);
3044              }
3045              return result.Result;
3046            }
3047          }
3048        }
3049        // ADD Aliases
3050        var scope = ctx.CurrentUsingScope;
3051
3052        for (var n = scope; n != null; n = n.Parent) {
3053          foreach (var pair in n.UsingAliases) {
3054            if (pair.Key == mrr.Member.Name) {
3055              foreach (var r in CreateCompletionData (location, pair.Value, resolvedNode, state)) {
3056                if (r is IEntityCompletionData && ((IEntityCompletionData)r).Entity is IMember) {
3057                  result.AddMember((IMember)((IEntityCompletionData)r).Entity);
3058                } else {
3059                  result.Add(r);
3060                }
3061              }
3062            }
3063          }
3064        }       
3065
3066
3067      }
3068      if (resolveResult is TypeResolveResult && (resolvedNode is IdentifierExpression || resolvedNode is MemberReferenceExpression)) {
3069        includeStaticMembers = true;
3070      }
3071
3072      //      Console.WriteLine ("type:" + type +"/"+type.GetType ());
3073      //      Console.WriteLine ("current:" + ctx.CurrentTypeDefinition);
3074      //      Console.WriteLine ("IS PROT ALLOWED:" + isProtectedAllowed + " static: "+ includeStaticMembers);
3075      //      Console.WriteLine (resolveResult);
3076      //      Console.WriteLine ("node:" + resolvedNode);
3077      //      Console.WriteLine (currentMember !=  null ? currentMember.IsStatic : "currentMember == null");
3078
3079      if (resolvedNode.Annotation<ObjectCreateExpression>() == null) {
3080        //tags the created expression as part of an object create expression.
3081        /*       
3082        var filteredList = new List<IMember>();
3083        foreach (var member in type.GetMembers ()) {
3084          filteredList.Add(member);
3085        }
3086       
3087        foreach (var member in filteredList) {
3088          //          Console.WriteLine ("add:" + member + "/" + member.IsStatic);
3089          result.AddMember(member);
3090        }*/
3091        foreach (var member in lookup.GetAccessibleMembers (resolveResult)) {
3092          if (member.SymbolKind == SymbolKind.Indexer || member.SymbolKind == SymbolKind.Operator || member.SymbolKind == SymbolKind.Constructor || member.SymbolKind == SymbolKind.Destructor) {
3093            continue;
3094          }
3095          if (resolvedNode is BaseReferenceExpression && member.IsAbstract) {
3096            continue;
3097          }
3098          if (member is IType) {
3099            if (resolveResult is TypeResolveResult || includeStaticMembers) {
3100              if (!lookup.IsAccessible(member, isProtectedAllowed))
3101                continue;
3102              result.AddType((IType)member, false);
3103              continue;
3104            }
3105          }
3106          bool memberIsStatic = member.IsStatic;
3107          if (!includeStaticMembers && memberIsStatic && !(resolveResult is TypeResolveResult)) {
3108            //            Console.WriteLine ("skip static member: " + member.FullName);
3109            continue;
3110          }
3111
3112          var field = member as IField;
3113          if (field != null) {
3114            memberIsStatic |= field.IsConst;
3115          }
3116          if (!memberIsStatic && skipNonStaticMembers) {
3117            continue;
3118          }
3119
3120          if (member is IMethod && ((IMethod)member).FullName == "System.Object.Finalize") {
3121            continue;
3122          }
3123          if (member.SymbolKind == SymbolKind.Operator) {
3124            continue;
3125          }
3126
3127          if (member is IMember) {
3128            result.AddMember((IMember)member);
3129          }
3130        }
3131      }
3132
3133      if (!(resolveResult is TypeResolveResult || includeStaticMembers)) {
3134        foreach (var meths in state.GetExtensionMethods (type)) {
3135          foreach (var m in meths) {
3136            if (!lookup.IsAccessible(m, isProtectedAllowed))
3137              continue;
3138            result.AddMember(new ReducedExtensionMethod(m));
3139          }
3140        }
3141      }
3142
3143      //      IEnumerable<object> objects = resolveResult.CreateResolveResult (dom, resolver != null ? resolver.CallingMember : null);
3144      //      CompletionDataCollector col = new CompletionDataCollector (this, dom, result, Document.CompilationUnit, resolver != null ? resolver.CallingType : null, location);
3145      //      col.HideExtensionParameter = !resolveResult.StaticResolve;
3146      //      col.NamePrefix = expressionResult.Expression;
3147      //      bool showOnlyTypes = expressionResult.Contexts.Any (ctx => ctx == ExpressionContext.InheritableType || ctx == ExpressionContext.Constraints);
3148      //      if (objects != null) {
3149      //        foreach (object obj in objects) {
3150      //          if (expressionResult.ExpressionContext != null && expressionResult.ExpressionContext.FilterEntry (obj))
3151      //            continue;
3152      //          if (expressionResult.ExpressionContext == ExpressionContext.NamespaceNameExcepted && !(obj is Namespace))
3153      //            continue;
3154      //          if (showOnlyTypes && !(obj is IType))
3155      //            continue;
3156      //          CompletionData data = col.Add (obj);
3157      //          if (data != null && expressionResult.ExpressionContext == ExpressionContext.Attribute && data.CompletionText != null && data.CompletionText.EndsWith ("Attribute")) {
3158      //            string newText = data.CompletionText.Substring (0, data.CompletionText.Length - "Attribute".Length);
3159      //            data.SetText (newText);
3160      //          }
3161      //        }
3162      //      }
3163
3164      return result.Result;
3165    }
3166
3167    IEnumerable<ICompletionData> CreateCaseCompletionData(TextLocation location)
3168    {
3169      var unit = ParseStub("a: break;");
3170      if (unit == null) {
3171        return null;
3172      }
3173      var s = unit.GetNodeAt<SwitchStatement>(location);
3174      if (s == null) {
3175        return null;
3176      }
3177
3178      var offset = document.GetOffset(s.Expression.StartLocation);
3179      var expr = GetExpressionAt(offset);
3180      if (expr == null) {
3181        return null;
3182      }
3183
3184      var resolveResult = ResolveExpression(expr);
3185      if (resolveResult == null || resolveResult.Result.Type.Kind != TypeKind.Enum) {
3186        return null;
3187      }
3188      var wrapper = new CompletionDataWrapper(this);
3189      AddEnumMembers(wrapper, resolveResult.Result.Type, resolveResult.Resolver);
3190      AutoCompleteEmptyMatch = false;
3191      return wrapper.Result;
3192    }
3193
3194    #region Parsing methods
3195
3196    ExpressionResult GetExpressionBeforeCursor()
3197    {
3198      SyntaxTree baseUnit;
3199      if (currentMember == null) {
3200        baseUnit = ParseStub("a", false);
3201        var type = baseUnit.GetNodeAt<MemberType>(location);
3202        if (type == null) {
3203          baseUnit = ParseStub("a;", false);
3204          type = baseUnit.GetNodeAt<MemberType>(location);
3205        }
3206
3207        if (type == null) {
3208          baseUnit = ParseStub("A a;", false);
3209          type = baseUnit.GetNodeAt<MemberType>(location);
3210        }
3211        if (type != null) {
3212          return new ExpressionResult((AstNode)type.Target, baseUnit);
3213        }
3214      }
3215
3216      baseUnit = ParseStub("ToString()", false);
3217      var curNode = baseUnit.GetNodeAt(location);
3218      // hack for local variable declaration missing ';' issue - remove that if it works.
3219      if (curNode is EntityDeclaration || baseUnit.GetNodeAt<Expression>(location) == null && baseUnit.GetNodeAt<MemberType>(location) == null) {
3220        baseUnit = ParseStub("a");
3221        curNode = baseUnit.GetNodeAt(location);
3222      }
3223
3224      // Hack for handle object initializer continuation expressions
3225      if (curNode is EntityDeclaration || baseUnit.GetNodeAt<Expression>(location) == null && baseUnit.GetNodeAt<MemberType>(location) == null) {
3226        baseUnit = ParseStub("a};");
3227      }
3228      var mref = baseUnit.GetNodeAt<MemberReferenceExpression>(location);
3229      if (currentMember == null && currentType == null) {
3230        if (mref != null) {
3231          return new ExpressionResult((AstNode)mref.Target, baseUnit);
3232        }
3233        return null;
3234      }
3235
3236      //var memberLocation = currentMember != null ? currentMember.Region.Begin : currentType.Region.Begin;
3237      if (mref == null) {
3238        var type = baseUnit.GetNodeAt<MemberType>(location);
3239        if (type != null) {
3240          return new ExpressionResult((AstNode)type.Target, baseUnit);
3241        }
3242
3243        var pref = baseUnit.GetNodeAt<PointerReferenceExpression>(location);
3244        if (pref != null) {
3245          return new ExpressionResult((AstNode)pref.Target, baseUnit);
3246        }
3247      }
3248
3249      if (mref == null) {
3250        baseUnit = ParseStub("A a;", false);
3251        var type = baseUnit.GetNodeAt<MemberType>(location);
3252        if (type != null) {
3253          return new ExpressionResult((AstNode)type.Target, baseUnit);
3254        }
3255      }
3256
3257      AstNode expr = null;
3258      if (mref != null) {
3259        expr = mref.Target;
3260      } else {
3261        Expression tref = baseUnit.GetNodeAt<TypeReferenceExpression>(location);
3262        MemberType memberType = tref != null ? ((TypeReferenceExpression)tref).Type as MemberType : null;
3263        if (memberType == null) {
3264          memberType = baseUnit.GetNodeAt<MemberType>(location);
3265          if (memberType != null) {
3266            if (memberType.Parent is ObjectCreateExpression) {
3267              var mt = memberType.Target.Clone();
3268              memberType.ReplaceWith(mt);
3269              expr = mt;
3270              goto exit;
3271            } else {
3272              tref = baseUnit.GetNodeAt<Expression>(location);
3273              if (tref == null) {
3274                tref = new TypeReferenceExpression(memberType.Clone());
3275                memberType.Parent.AddChild(tref, Roles.Expression);
3276              }
3277              if (tref is ObjectCreateExpression) {
3278                expr = memberType.Target.Clone();
3279                expr.AddAnnotation(new ObjectCreateExpression());
3280              }
3281            }
3282          }
3283        }
3284
3285        if (memberType == null) {
3286          return null;
3287        }
3288        if (expr == null) {
3289          expr = memberType.Target.Clone();
3290        }
3291        tref.ReplaceWith(expr);
3292      }
3293      exit:
3294      return new ExpressionResult((AstNode)expr, baseUnit);
3295    }
3296
3297    ExpressionResult GetExpressionAtCursor()
3298    {
3299      //      TextLocation memberLocation;
3300      //      if (currentMember != null) {
3301      //        memberLocation = currentMember.Region.Begin;
3302      //      } else if (currentType != null) {
3303      //        memberLocation = currentType.Region.Begin;
3304      //      } else {
3305      //        memberLocation = location;
3306      //      }
3307      var baseUnit = ParseStub("a");
3308      var tmpUnit = baseUnit;
3309      AstNode expr = baseUnit.GetNodeAt(
3310        location,
3311        n => n is IdentifierExpression || n is MemberReferenceExpression
3312      );
3313
3314      if (expr == null) {
3315        expr = baseUnit.GetNodeAt<AstType>(location.Line, location.Column - 1);
3316      }
3317      if (expr == null)
3318        expr = baseUnit.GetNodeAt<Identifier>(location.Line, location.Column - 1);
3319      // try insertStatement
3320      if (expr == null && baseUnit.GetNodeAt<EmptyStatement>(location.Line, location.Column) != null) {
3321        tmpUnit = baseUnit = ParseStub("a();", false);
3322        expr = baseUnit.GetNodeAt<InvocationExpression>(
3323          location.Line,
3324          location.Column + 1
3325        );
3326      }
3327
3328      if (expr == null) {
3329        baseUnit = ParseStub("()");
3330        expr = baseUnit.GetNodeAt<IdentifierExpression>(
3331          location.Line,
3332          location.Column - 1
3333        );
3334        if (expr == null) {
3335          expr = baseUnit.GetNodeAt<MemberType>(location.Line, location.Column - 1);
3336        }
3337      }
3338
3339      if (expr == null) {
3340        baseUnit = ParseStub("a", false);
3341        expr = baseUnit.GetNodeAt(
3342          location,
3343          n => n is IdentifierExpression || n is MemberReferenceExpression || n is CatchClause
3344        );
3345      }
3346
3347      // try statement
3348      if (expr == null) {
3349        expr = tmpUnit.GetNodeAt<SwitchStatement>(
3350          location.Line,
3351          location.Column - 1
3352        );
3353        baseUnit = tmpUnit;
3354      }
3355
3356      if (expr == null) {
3357        var block = tmpUnit.GetNodeAt<BlockStatement>(location);
3358        var node = block != null ? block.Statements.LastOrDefault() : null;
3359
3360        var forStmt = node != null ? node.PrevSibling as ForStatement : null;
3361        if (forStmt != null && forStmt.EmbeddedStatement.IsNull) {
3362          expr = forStmt;
3363          var id = new IdentifierExpression("stub");
3364          forStmt.EmbeddedStatement = new BlockStatement() { Statements = { new ExpressionStatement(id) } };
3365          expr = id;
3366          baseUnit = tmpUnit;
3367        }
3368      }
3369
3370      if (expr == null) {
3371        var forStmt = tmpUnit.GetNodeAt<ForeachStatement>(
3372          location.Line,
3373          location.Column - 3
3374        );
3375        if (forStmt != null && forStmt.EmbeddedStatement.IsNull) {
3376          forStmt.VariableNameToken = Identifier.Create("stub");
3377          expr = forStmt.VariableNameToken;
3378          baseUnit = tmpUnit;
3379        }
3380      }
3381      if (expr == null) {
3382        expr = tmpUnit.GetNodeAt<VariableInitializer>(
3383          location.Line,
3384          location.Column - 1
3385        );
3386        baseUnit = tmpUnit;
3387      }
3388
3389      // try parameter declaration type
3390      if (expr == null) {
3391        baseUnit = ParseStub(">", false, "{}");
3392        expr = baseUnit.GetNodeAt<TypeParameterDeclaration>(
3393          location.Line,
3394          location.Column - 1
3395        );
3396      }
3397
3398      // try parameter declaration method
3399      if (expr == null) {
3400        baseUnit = ParseStub("> ()", false, "{}");
3401        expr = baseUnit.GetNodeAt<TypeParameterDeclaration>(
3402          location.Line,
3403          location.Column - 1
3404        );
3405      }
3406
3407      // try expression in anonymous type "new { sample = x$" case
3408      if (expr == null) {
3409        baseUnit = ParseStub("a", false);
3410        expr = baseUnit.GetNodeAt<AnonymousTypeCreateExpression>(
3411          location.Line,
3412          location.Column
3413        );
3414        if (expr != null) {
3415          expr = baseUnit.GetNodeAt<Expression>(location.Line, location.Column) ?? expr;
3416        }
3417        if (expr == null) {
3418          expr = baseUnit.GetNodeAt<AstType>(location.Line, location.Column);
3419        }
3420      }
3421
3422      // try lambda
3423      if (expr == null) {
3424        baseUnit = ParseStub("foo) => {}", false);
3425        expr = baseUnit.GetNodeAt<ParameterDeclaration>(
3426          location.Line,
3427          location.Column
3428        );
3429      }
3430
3431      if (expr == null)
3432        return null;
3433      return new ExpressionResult(expr, baseUnit);
3434    }
3435
3436    ExpressionResult GetExpressionAt(int offset)
3437    {
3438      var parser = new CSharpParser();
3439      var text = GetMemberTextToCaret();
3440
3441      int closingBrackets = 0, generatedLines = 0;
3442      var sb = CreateWrapper("a;", false, "", text.Item1, text.Item2, ref closingBrackets, ref generatedLines);
3443
3444      var completionUnit = parser.Parse(sb.ToString());
3445      var offsetLocation = document.GetLocation(offset);
3446      var loc = new TextLocation(offsetLocation.Line - text.Item2.Line + generatedLines + 1, offsetLocation.Column);
3447
3448      var expr = completionUnit.GetNodeAt(
3449        loc,
3450        n => n is Expression || n is VariableDeclarationStatement
3451      );
3452      if (expr == null)
3453        return null;
3454      return new ExpressionResult(expr, completionUnit);
3455    }
3456
3457    ExpressionResult GetNewExpressionAt(int offset)
3458    {
3459      var parser = new CSharpParser();
3460      var text = GetMemberTextToCaret();
3461      int closingBrackets = 0, generatedLines = 0;
3462      var sb = CreateWrapper("a ();", false, "", text.Item1, text.Item2, ref closingBrackets, ref generatedLines);
3463
3464      var completionUnit = parser.Parse(sb.ToString());
3465      var offsetLocation = document.GetLocation(offset);
3466      var loc = new TextLocation(offsetLocation.Line - text.Item2.Line + generatedLines + 1, offsetLocation.Column);
3467
3468      var expr = completionUnit.GetNodeAt(loc, n => n is Expression);
3469      if (expr == null) {
3470        // try without ";"
3471        sb = CreateWrapper("a ()", false, "", text.Item1, text.Item2, ref closingBrackets, ref generatedLines);
3472        completionUnit = parser.Parse(sb.ToString());
3473
3474        expr = completionUnit.GetNodeAt(loc, n => n is Expression);
3475        if (expr == null) {
3476          return null;
3477        }
3478      }
3479      return new ExpressionResult(expr, completionUnit);
3480    }
3481
3482    #endregion
3483
3484    #region Helper methods
3485
3486    string GetPreviousToken(ref int i, bool allowLineChange)
3487    {
3488      char c;
3489      if (i <= 0) {
3490        return null;
3491      }
3492
3493      do {
3494        c = document.GetCharAt(--i);
3495      } while (i > 0 && char.IsWhiteSpace(c) && (allowLineChange ? true : c != '\n'));
3496
3497      if (i == 0) {
3498        return null;
3499      }
3500
3501      if (!char.IsLetterOrDigit(c)) {
3502        return new string(c, 1);
3503      }
3504
3505      int endOffset = i + 1;
3506
3507      do {
3508        c = document.GetCharAt(i - 1);
3509        if (!(char.IsLetterOrDigit(c) || c == '_')) {
3510          break;
3511        }
3512
3513        i--;
3514      } while (i > 0);
3515
3516      return document.GetText(i, endOffset - i);
3517    }
3518
3519    #endregion
3520
3521    #region Preprocessor
3522
3523    IEnumerable<ICompletionData> GetDirectiveCompletionData()
3524    {
3525      yield return factory.CreateLiteralCompletionData("if");
3526      yield return factory.CreateLiteralCompletionData("else");
3527      yield return factory.CreateLiteralCompletionData("elif");
3528      yield return factory.CreateLiteralCompletionData("endif");
3529      yield return factory.CreateLiteralCompletionData("define");
3530      yield return factory.CreateLiteralCompletionData("undef");
3531      yield return factory.CreateLiteralCompletionData("warning");
3532      yield return factory.CreateLiteralCompletionData("error");
3533      yield return factory.CreateLiteralCompletionData("pragma");
3534      yield return factory.CreateLiteralCompletionData("line");
3535      yield return factory.CreateLiteralCompletionData("line hidden");
3536      yield return factory.CreateLiteralCompletionData("line default");
3537      yield return factory.CreateLiteralCompletionData("region");
3538      yield return factory.CreateLiteralCompletionData("endregion");
3539    }
3540
3541    #endregion
3542
3543    #region Xml Comments
3544
3545    static readonly List<string> commentTags = new List<string>(new string[] {
3546      "c",
3547      "code",
3548      "example",
3549      "exception",
3550      "include",
3551      "list",
3552      "listheader",
3553      "item",
3554      "term",
3555      "description",
3556      "para",
3557      "param",
3558      "paramref",
3559      "permission",
3560      "remarks",
3561      "returns",
3562      "see",
3563      "seealso",
3564      "summary",
3565      "value"
3566    }
3567    );
3568
3569    public static IEnumerable<string> CommentTags {
3570      get {
3571        return commentTags;
3572      }
3573    }
3574
3575    string GetLastClosingXmlCommentTag()
3576    {
3577      var line = document.GetLineByNumber(location.Line);
3578
3579      restart:
3580      string lineText = document.GetText(line);
3581      if (!lineText.Trim().StartsWith("///", StringComparison.Ordinal))
3582        return null;
3583      int startIndex = Math.Min(location.Column - 1, lineText.Length - 1) - 1;
3584      while (startIndex > 0 && lineText [startIndex] != '<') {
3585        --startIndex;
3586        if (lineText [startIndex] == '/') {
3587          // already closed.
3588          startIndex = -1;
3589          break;
3590        }
3591      }
3592      if (startIndex < 0 && line.PreviousLine != null) {
3593        line = line.PreviousLine;
3594        goto restart;
3595      }
3596
3597      if (startIndex >= 0) {
3598        int endIndex = startIndex;
3599        while (endIndex + 1 < lineText.Length && lineText [endIndex] != '>' && !char.IsWhiteSpace(lineText [endIndex])) {
3600          endIndex++;
3601        }
3602        string tag = endIndex - startIndex - 1 > 0 ? lineText.Substring(
3603          startIndex + 1,
3604          endIndex - startIndex - 1
3605        ) : null;
3606        if (!string.IsNullOrEmpty(tag) && commentTags.IndexOf(tag) >= 0) {
3607          return tag;
3608        }
3609      }
3610      return null;
3611    }
3612
3613    IEnumerable<ICompletionData> GetXmlDocumentationCompletionData()
3614    {
3615      var closingTag = GetLastClosingXmlCommentTag();
3616      if (closingTag != null) {
3617        yield return factory.CreateLiteralCompletionData(
3618          "/" + closingTag + ">"
3619        );
3620      }
3621
3622      yield return factory.CreateXmlDocCompletionData(
3623        "c",
3624        "Set text in a code-like font"
3625      );
3626      yield return factory.CreateXmlDocCompletionData(
3627        "code",
3628        "Set one or more lines of source code or program output"
3629      );
3630      yield return factory.CreateXmlDocCompletionData(
3631        "example",
3632        "Indicate an example"
3633      );
3634      yield return factory.CreateXmlDocCompletionData(
3635        "exception",
3636        "Identifies the exceptions a method can throw",
3637        "exception cref=\"|\"></exception"
3638      );
3639      yield return factory.CreateXmlDocCompletionData(
3640        "include",
3641        "Includes comments from a external file",
3642        "include file=\"|\" path=\"\""
3643      );
3644      yield return factory.CreateXmlDocCompletionData(
3645        "inheritdoc",
3646        "Inherit documentation from a base class or interface",
3647        "inheritdoc/"
3648      );
3649      yield return factory.CreateXmlDocCompletionData(
3650        "list",
3651        "Create a list or table",
3652        "list type=\"|\""
3653      );
3654      yield return factory.CreateXmlDocCompletionData(
3655        "listheader",
3656        "Define the heading row"
3657      );
3658      yield return factory.CreateXmlDocCompletionData(
3659        "item",
3660        "Defines list or table item"
3661      );
3662
3663      yield return factory.CreateXmlDocCompletionData("term", "A term to define");
3664      yield return factory.CreateXmlDocCompletionData(
3665        "description",
3666        "Describes a list item"
3667      );
3668      yield return factory.CreateXmlDocCompletionData(
3669        "para",
3670        "Permit structure to be added to text"
3671      );
3672
3673      yield return factory.CreateXmlDocCompletionData(
3674        "param",
3675        "Describe a parameter for a method or constructor",
3676        "param name=\"|\""
3677      );
3678      yield return factory.CreateXmlDocCompletionData(
3679        "paramref",
3680        "Identify that a word is a parameter name",
3681        "paramref name=\"|\"/"
3682      );
3683
3684      yield return factory.CreateXmlDocCompletionData(
3685        "permission",
3686        "Document the security accessibility of a member",
3687        "permission cref=\"|\""
3688      );
3689      yield return factory.CreateXmlDocCompletionData(
3690        "remarks",
3691        "Describe a type"
3692      );
3693      yield return factory.CreateXmlDocCompletionData(
3694        "returns",
3695        "Describe the return value of a method"
3696      );
3697      yield return factory.CreateXmlDocCompletionData(
3698        "see",
3699        "Specify a link",
3700        "see cref=\"|\"/"
3701      );
3702      yield return factory.CreateXmlDocCompletionData(
3703        "seealso",
3704        "Generate a See Also entry",
3705        "seealso cref=\"|\"/"
3706      );
3707      yield return factory.CreateXmlDocCompletionData(
3708        "summary",
3709        "Describe a member of a type"
3710      );
3711      yield return factory.CreateXmlDocCompletionData(
3712        "typeparam",
3713        "Describe a type parameter for a generic type or method"
3714      );
3715      yield return factory.CreateXmlDocCompletionData(
3716        "typeparamref",
3717        "Identify that a word is a type parameter name"
3718      );
3719      yield return factory.CreateXmlDocCompletionData(
3720        "value",
3721        "Describe a property"
3722      );
3723
3724    }
3725
3726    #endregion
3727
3728    #region Keywords
3729
3730    static string[] expressionLevelKeywords = new string [] {
3731      "as",
3732      "is",
3733      "else",
3734      "out",
3735      "ref",
3736      "null",
3737      "delegate",
3738      "default"
3739    };
3740    static string[] primitiveTypesKeywords = new string [] {
3741      "void",
3742      "object",
3743      "bool",
3744      "byte",
3745      "sbyte",
3746      "char",
3747      "short",
3748      "int",
3749      "long",
3750      "ushort",
3751      "uint",
3752      "ulong",
3753      "float",
3754      "double",
3755      "decimal",
3756      "string"
3757    };
3758    static string[] statementStartKeywords = new string [] { "base", "new", "sizeof", "this",
3759      "true", "false", "typeof", "checked", "unchecked", "from", "break", "checked",
3760      "unchecked", "const", "continue", "do", "finally", "fixed", "for", "foreach",
3761      "goto", "if", "lock", "return", "stackalloc", "switch", "throw", "try", "unsafe",
3762      "using", "while", "yield",
3763      "catch"
3764    };
3765    static string[] globalLevelKeywords = new string [] {
3766      "namespace", "using", "extern", "public", "internal",
3767      "class", "interface", "struct", "enum", "delegate",
3768      "abstract", "sealed", "static", "unsafe", "partial"
3769    };
3770    static string[] accessorModifierKeywords = new string [] {
3771      "public", "internal", "protected", "private", "async"
3772    };
3773    static string[] typeLevelKeywords = new string [] {
3774      "public", "internal", "protected", "private", "async",
3775      "class", "interface", "struct", "enum", "delegate",
3776      "abstract", "sealed", "static", "unsafe", "partial",
3777      "const", "event", "extern", "fixed", "new",
3778      "operator", "explicit", "implicit",
3779      "override", "readonly", "virtual", "volatile"
3780    };
3781    static string[] linqKeywords = new string[] {
3782      "from",
3783      "where",
3784      "select",
3785      "group",
3786      "into",
3787      "orderby",
3788      "join",
3789      "let",
3790      "in",
3791      "on",
3792      "equals",
3793      "by",
3794      "ascending",
3795      "descending"
3796    };
3797    static string[] parameterTypePredecessorKeywords = new string[] {
3798      "out",
3799      "ref",
3800      "params"
3801    };
3802
3803    #endregion
3804
3805  }
3806}
3807
Note: See TracBrowser for help on using the repository browser.