/// <summary> /// Adds a type to completion list. If it's a simple type like System.String it adds the simple /// C# type name "string" as well. /// </summary> static void AddAsCompletionData (CompletionDataCollector col, IType type) { if (type == null) return; string netName = CSharpAmbience.NetToCSharpTypeName (type.FullName); if (!string.IsNullOrEmpty (netName) && netName != type.FullName) col.Add (netName); if (!String.IsNullOrEmpty (type.Namespace) && !col.IsNamespaceInScope (type.Namespace)) { string[] ns = type.Namespace.Split ('.'); for (int i = 0; i < ns.Length; i++) { col.Add (new Namespace (ns[i])); if (!col.IsNamespaceInScope (ns[i])) return; } } col.Add (type); }
public ICompletionDataList HandleKeywordCompletion (CodeCompletionContext completionContext, ExpressionResult result, int wordStart, string word) { if (stateTracker.Engine.IsInsideDocLineComment || stateTracker.Engine.IsInsideOrdinaryCommentOrString) return null; DomLocation location = new DomLocation (completionContext.TriggerLine, completionContext.TriggerLineOffset); switch (word) { case "using": if (result.ExpressionContext != ExpressionContext.NamespaceNameExcepted) return null; return CreateCompletionData (location, new NamespaceResolveResult (""), result, null); case "namespace": result.ExpressionContext = ExpressionContext.NamespaceNameExcepted; return CreateCompletionData (location, new NamespaceResolveResult (""), result, null); case "case": return CreateCaseCompletionData (location, result); case ",": case ":": if (result.ExpressionContext == ExpressionContext.InheritableType) { IType cls = NRefactoryResolver.GetTypeAtCursor (Document.CompilationUnit, Document.FileName, new DomLocation (completionContext.TriggerLine, completionContext.TriggerLineOffset)); CompletionDataList completionList = new ProjectDomCompletionDataList (); List<string> namespaceList = GetUsedNamespaces (); CSharpTextEditorCompletion.CompletionDataCollector col = new CSharpTextEditorCompletion.CompletionDataCollector (dom, completionList, Document.CompilationUnit, null, location); bool isInterface = false; HashSet<string> baseTypeNames = new HashSet<string> (); if (cls != null) { baseTypeNames.Add (cls.Name); if (cls.ClassType == ClassType.Struct) isInterface = true; } int tokenIndex = completionContext.TriggerOffset; // Search base types " : [Type1, ... ,TypeN,] <Caret>" string token = null; do { token = GetPreviousToken (ref tokenIndex, false); if (string.IsNullOrEmpty (token)) break; token = token.Trim (); if (Char.IsLetterOrDigit (token[0]) || token[0] == '_') { IType baseType = dom.SearchType (Document.CompilationUnit, Document.CompilationUnit, token); if (baseType != null) { if (baseType.ClassType != ClassType.Interface) isInterface = true; baseTypeNames.Add (baseType.Name); } } } while (token != ":"); foreach (object o in dom.GetNamespaceContents (namespaceList, true, true)) { IType type = o as IType; if (type != null && (type.IsStatic || type.IsSealed || baseTypeNames.Contains (type.Name) || isInterface && type.ClassType != ClassType.Interface)) { continue; } if (o is Namespace && !namespaceList.Any (ns => ns.StartsWith (((Namespace)o).FullName))) continue; col.Add (o); } // Add inner classes Stack<IType> innerStack = new Stack<IType> (); innerStack.Push (cls); while (innerStack.Count > 0) { IType curType = innerStack.Pop (); if (curType == null) continue; foreach (IType innerType in curType.InnerTypes) { if (innerType != cls) // don't add the calling class as possible base type col.Add (innerType); } if (curType.DeclaringType != null) innerStack.Push (curType.DeclaringType); } return completionList; } break; case "is": case "as": { CompletionDataList completionList = new ProjectDomCompletionDataList (); ExpressionResult expressionResult = FindExpression (dom, completionContext, wordStart - textEditorData.Caret.Offset); NRefactoryResolver resolver = CreateResolver (); ResolveResult resolveResult = resolver.Resolve (expressionResult, new DomLocation (completionContext.TriggerLine, completionContext.TriggerLineOffset)); if (resolveResult != null && resolveResult.ResolvedType != null) { CompletionDataCollector col = new CompletionDataCollector (dom, completionList, Document.CompilationUnit, resolver.CallingType, location); IType foundType = null; if (word == "as") { ExpressionContext exactContext = new NewCSharpExpressionFinder (dom).FindExactContextForAsCompletion (textEditorData, Document.CompilationUnit, Document.FileName, resolver.CallingType); if (exactContext is ExpressionContext.TypeExpressionContext) { foundType = resolver.SearchType (((ExpressionContext.TypeExpressionContext)exactContext).Type); AddAsCompletionData (col, foundType); } } if (foundType == null) foundType = resolver.SearchType (resolveResult.ResolvedType); if (foundType != null) { if (foundType.ClassType == ClassType.Interface) foundType = resolver.SearchType (DomReturnType.Object); foreach (IType type in dom.GetSubclasses (foundType)) { if (type.IsSpecialName || type.Name.StartsWith ("<")) continue; AddAsCompletionData (col, type); } } List<string> namespaceList = GetUsedNamespaces (); foreach (object o in dom.GetNamespaceContents (namespaceList, true, true)) { if (o is IType) { IType type = (IType)o; if (type.ClassType != ClassType.Interface || type.IsSpecialName || type.Name.StartsWith ("<")) continue; // if (foundType != null && !dom.GetInheritanceTree (foundType).Any (x => x.FullName == type.FullName)) // continue; AddAsCompletionData (col, type); continue; } if (o is Namespace) continue; col.Add (o); } return completionList; } result.ExpressionContext = ExpressionContext.TypeName; return CreateCtrlSpaceCompletionData (completionContext, result); } case "override": // Look for modifiers, in order to find the beginning of the declaration int firstMod = wordStart; int i = wordStart; for (int n = 0; n < 3; n++) { string mod = GetPreviousToken (ref i, true); if (mod == "public" || mod == "protected" || mod == "private" || mod == "internal" || mod == "sealed") { firstMod = i; } else if (mod == "static") { // static methods are not overridable return null; } else break; } IType overrideCls = NRefactoryResolver.GetTypeAtCursor (Document.CompilationUnit, Document.FileName, new DomLocation (completionContext.TriggerLine, completionContext.TriggerLineOffset)); if (overrideCls == null) overrideCls = NRefactoryResolver.GetTypeAtCursor (Document.CompilationUnit, Document.FileName, new DomLocation (completionContext.TriggerLine - 1, 1)); if (overrideCls != null && (overrideCls.ClassType == ClassType.Class || overrideCls.ClassType == ClassType.Struct)) { string modifiers = textEditorData.GetTextBetween (firstMod, wordStart); return GetOverrideCompletionData (completionContext, overrideCls, modifiers); } return null; case "partial": // Look for modifiers, in order to find the beginning of the declaration firstMod = wordStart; i = wordStart; for (int n = 0; n < 3; n++) { string mod = GetPreviousToken (ref i, true); if (mod == "public" || mod == "protected" || mod == "private" || mod == "internal" || mod == "sealed") { firstMod = i; } else if (mod == "static") { // static methods are not overridable return null; } else break; } overrideCls = NRefactoryResolver.GetTypeAtCursor (Document.CompilationUnit, Document.FileName, new DomLocation (completionContext.TriggerLine, completionContext.TriggerLineOffset)); if (overrideCls != null && (overrideCls.ClassType == ClassType.Class || overrideCls.ClassType == ClassType.Struct)) { string modifiers = textEditorData.GetTextBetween (firstMod, wordStart); return GetPartialCompletionData (completionContext, overrideCls, modifiers); } return null; case "new": IType callingType = NRefactoryResolver.GetTypeAtCursor (Document.CompilationUnit, Document.FileName, new DomLocation (textEditorData.Caret.Line, textEditorData.Caret.Column)); ExpressionContext newExactContext = new NewCSharpExpressionFinder (dom).FindExactContextForNewCompletion (textEditorData, Document.CompilationUnit, Document.FileName, callingType); if (newExactContext is ExpressionContext.TypeExpressionContext) return CreateTypeCompletionData (location, callingType, newExactContext, ((ExpressionContext.TypeExpressionContext)newExactContext).Type, ((ExpressionContext.TypeExpressionContext)newExactContext).UnresolvedType); if (newExactContext == null) { int j = completionContext.TriggerOffset - 4; string token = GetPreviousToken (ref j, true); string yieldToken = GetPreviousToken (ref j, true); if (token == "return") { NRefactoryResolver resolver = CreateResolver (); resolver.SetupResolver (new DomLocation (completionContext.TriggerLine, completionContext.TriggerLineOffset)); IReturnType returnType = resolver.CallingMember.ReturnType; if (yieldToken == "yield" && returnType.GenericArguments.Count > 0) returnType = returnType.GenericArguments[0]; if (resolver.CallingMember != null) return CreateTypeCompletionData (location, callingType, newExactContext, null, returnType); } } return CreateCtrlSpaceCompletionData (completionContext, null); case "if": case "elif": if (stateTracker.Engine.IsInsidePreprocessorDirective) return GetDefineCompletionData (); return null; case "yield": CompletionDataList yieldDataList = new CompletionDataList (); yieldDataList.DefaultCompletionString = "return"; yieldDataList.Add ("break", "md-keyword"); yieldDataList.Add ("return", "md-keyword"); return yieldDataList; case "where": CompletionDataList whereDataList = new CompletionDataList (); NRefactoryResolver constraintResolver = CreateResolver (); constraintResolver.SetupResolver (new DomLocation (completionContext.TriggerLine, completionContext.TriggerLineOffset)); if (constraintResolver.CallingMember is IMethod) { foreach (ITypeParameter tp in ((IMethod)constraintResolver.CallingMember).TypeParameters) { whereDataList.Add (tp.Name, "md-keyword"); } } else { if (constraintResolver.CallingType != null) { foreach (ITypeParameter tp in constraintResolver.CallingType.TypeParameters) { whereDataList.Add (tp.Name, "md-keyword"); } } } return whereDataList; } if (IsInLinqContext (result)) { if (linqKeywords.Contains (word)) { if (word == "from") // after from no auto code completion. return null; result.Expression = ""; return CreateCtrlSpaceCompletionData (completionContext, result); } CompletionDataList dataList = new ProjectDomCompletionDataList (); CompletionDataCollector col = new CompletionDataCollector (dom, dataList, Document.CompilationUnit, null, new DomLocation (completionContext.TriggerLine, completionContext.TriggerLineOffset)); foreach (string kw in linqKeywords) { col.Add (kw, "md-keyword"); } return dataList; } return null; }
CompletionDataList CreateCtrlSpaceCompletionData (CodeCompletionContext ctx, ExpressionResult expressionResult) { NRefactoryResolver resolver = CreateResolver (); DomLocation cursorLocation = new DomLocation (ctx.TriggerLine, ctx.TriggerLineOffset); resolver.SetupResolver (cursorLocation); CompletionDataList result = new ProjectDomCompletionDataList (); CompletionDataCollector col = new CompletionDataCollector (dom, result, Document.CompilationUnit, resolver.CallingType, cursorLocation); if (expressionResult == null) { AddPrimitiveTypes (col); resolver.AddAccessibleCodeCompletionData (ExpressionContext.Global, col); } else if (expressionResult.ExpressionContext == ExpressionContext.TypeDeclaration) { AddPrimitiveTypes (col); AddNRefactoryKeywords (col, ICSharpCode.NRefactory.Parser.CSharp.Tokens.TypeLevel); resolver.AddAccessibleCodeCompletionData (expressionResult.ExpressionContext, col); } else if (expressionResult.ExpressionContext == ExpressionContext.InterfaceDeclaration) { AddPrimitiveTypes (col); AddNRefactoryKeywords (col, ICSharpCode.NRefactory.Parser.CSharp.Tokens.InterfaceLevel); resolver.AddAccessibleCodeCompletionData (expressionResult.ExpressionContext, col); } else if (expressionResult.ExpressionContext == ExpressionContext.MethodBody) { col.Add ("global", "md-keyword"); col.Add ("var", "md-keyword"); AddNRefactoryKeywords (col, ICSharpCode.NRefactory.Parser.CSharp.Tokens.StatementStart); AddPrimitiveTypes (col); resolver.AddAccessibleCodeCompletionData (expressionResult.ExpressionContext, col); } else if (expressionResult.ExpressionContext == ExpressionContext.InterfacePropertyDeclaration) { col.Add ("get", "md-keyword"); col.Add ("set", "md-keyword"); } else if (expressionResult.ExpressionContext == ExpressionContext.ConstraintsStart) { col.Add ("where", "md-keyword"); } else if (expressionResult.ExpressionContext == ExpressionContext.Constraints) { col.Add ("new", "md-keyword"); col.Add ("class", "md-keyword"); col.Add ("struct", "md-keyword"); AddPrimitiveTypes (col); resolver.AddAccessibleCodeCompletionData (expressionResult.ExpressionContext, col); } else if (expressionResult.ExpressionContext == ExpressionContext.Attribute) { col.Add ("assembly", "md-keyword"); col.Add ("module", "md-keyword"); col.Add ("type", "md-keyword"); col.Add ("method", "md-keyword"); col.Add ("field", "md-keyword"); col.Add ("property", "md-keyword"); col.Add ("event", "md-keyword"); col.Add ("param", "md-keyword"); col.Add ("return", "md-keyword"); resolver.AddAccessibleCodeCompletionData (expressionResult.ExpressionContext, col); } else if (expressionResult.ExpressionContext == ExpressionContext.BaseConstructorCall) { col.Add ("this", "md-keyword"); col.Add ("base", "md-keyword"); } else if (expressionResult.ExpressionContext == ExpressionContext.ParameterType || expressionResult.ExpressionContext == ExpressionContext.FirstParameterType) { col.Add ("ref", "md-keyword"); col.Add ("out", "md-keyword"); col.Add ("params", "md-keyword"); // C# 3.0 extension method if (expressionResult.ExpressionContext == ExpressionContext.FirstParameterType) col.Add ("this", "md-keyword"); AddPrimitiveTypes (col); resolver.AddAccessibleCodeCompletionData (expressionResult.ExpressionContext, col); } else if (expressionResult.ExpressionContext == ExpressionContext.PropertyDeclaration) { AddNRefactoryKeywords (col, ICSharpCode.NRefactory.Parser.CSharp.Tokens.InPropertyDeclaration); } else if (expressionResult.ExpressionContext == ExpressionContext.EventDeclaration) { col.Add ("add", "md-keyword"); col.Add ("remove", "md-keyword"); } //else if (expressionResult.ExpressionContext == ExpressionContext.FullyQualifiedType) {} else if (expressionResult.ExpressionContext == ExpressionContext.Default) { col.Add ("global", "md-keyword"); col.Add ("var", "md-keyword"); AddPrimitiveTypes (col); AddNRefactoryKeywords (col, ICSharpCode.NRefactory.Parser.CSharp.Tokens.ExpressionStart); AddNRefactoryKeywords (col, ICSharpCode.NRefactory.Parser.CSharp.Tokens.ExpressionContent); resolver.AddAccessibleCodeCompletionData (expressionResult.ExpressionContext, col); } else if (expressionResult.ExpressionContext == ExpressionContext.Global) { AddNRefactoryKeywords (col, ICSharpCode.NRefactory.Parser.CSharp.Tokens.GlobalLevel); CodeTemplateService.AddCompletionDataForMime ("text/x-csharp", result); } else if (expressionResult.ExpressionContext == ExpressionContext.ObjectInitializer) { ExpressionContext exactContext = new NewCSharpExpressionFinder (dom).FindExactContextForObjectInitializer (textEditorData, resolver.Unit, Document.FileName, resolver.CallingType); if (exactContext is ExpressionContext.TypeExpressionContext) { IReturnType objectInitializer = ((ExpressionContext.TypeExpressionContext)exactContext).UnresolvedType; if (objectInitializer.ArrayDimensions > 0 || objectInitializer.PointerNestingLevel > 0) { col.Add ("global", "md-keyword"); col.Add ("new", "md-keyword"); AddPrimitiveTypes (col); resolver.AddAccessibleCodeCompletionData (expressionResult.ExpressionContext, col); return result; } IType foundType = resolver.SearchType (objectInitializer); if (foundType == null) foundType = dom.GetType (objectInitializer); if (foundType != null) { bool includeProtected = DomType.IncludeProtected (dom, foundType, resolver.CallingType); foreach (IType type in dom.GetInheritanceTree (foundType)) { foreach (IProperty property in type.Properties) { if (property.IsAccessibleFrom (dom, resolver.CallingType, resolver.CallingMember, includeProtected)) { col.Add (property); } } foreach (var field in type.Fields) { if (field.IsAccessibleFrom (dom, resolver.CallingType, resolver.CallingMember, includeProtected)) { col.Add (field); } } } } } // result.Add ("global", "md-literal"); // AddPrimitiveTypes (result); // resolver.AddAccessibleCodeCompletionData (expressionResult.ExpressionContext, result); } else if (expressionResult.ExpressionContext == ExpressionContext.AttributeArguments) { col.Add ("global", "md-keyword"); AddPrimitiveTypes (col); string attributeName = NewCSharpExpressionFinder.FindAttributeName (textEditorData, Document.CompilationUnit, Document.FileName); if (attributeName != null) { IType type = resolver.SearchType (attributeName + "Attribute"); if (type == null) type = resolver.SearchType (attributeName); if (type != null) { foreach (var property in type.Properties) { col.Add (property); } foreach (var field in type.Fields) { if (field.IsPublic) col.Add (field); } } } resolver.AddAccessibleCodeCompletionData (expressionResult.ExpressionContext, col); } else if (expressionResult.ExpressionContext == ExpressionContext.IdentifierExpected) { if (!string.IsNullOrEmpty (expressionResult.Expression)) expressionResult.Expression = expressionResult.Expression.Trim (); MemberResolveResult resolveResult = resolver.Resolve (expressionResult, cursorLocation) as MemberResolveResult; if (resolveResult != null && resolveResult.ResolvedMember == null && resolveResult.ResolvedType != null) { string name = CSharpAmbience.NetToCSharpTypeName (resolveResult.ResolvedType.FullName); if (name != resolveResult.ResolvedType.FullName) { col.Add (Char.ToLower (name[0]).ToString (), "md-field"); } else { name = resolveResult.ResolvedType.Name; List<string> names = new List<string> (); int lastNameStart = 0; for (int i = 1; i < name.Length; i++) { if (Char.IsUpper (name[i])) { names.Add (name.Substring (lastNameStart, i - lastNameStart)); lastNameStart = i; } } names.Add (name.Substring (lastNameStart, name.Length - lastNameStart)); StringBuilder possibleName = new StringBuilder (); for (int i = 0; i < names.Count; i++) { possibleName.Length = 0; for (int j = i; j < names.Count; j++) { if (string.IsNullOrEmpty (names[j])) continue; if (j == i) names[j] = Char.ToLower (names[j][0]) + names[j].Substring (1); possibleName.Append (names[j]); } if (possibleName.Length > 0) col.Add (possibleName.ToString (), "md-field"); } result.IsSorted = true; } } else { col.Add ("global", "md-keyword"); AddPrimitiveTypes (col); resolver.AddAccessibleCodeCompletionData (expressionResult.ExpressionContext, col); if (expressionResult.ExpressionContext == ExpressionContext.Constraints) { col.Add ("struct", "md-keyword"); col.Add ("class", "md-keyword"); col.Add ("new()", "md-keyword"); } else { col.Add ("var", "md-keyword"); } } } else if (expressionResult.ExpressionContext == ExpressionContext.TypeName) { col.Add ("global", "md-keyword"); AddPrimitiveTypes (col); resolver.AddAccessibleCodeCompletionData (expressionResult.ExpressionContext, col); } else if (expressionResult.ExpressionContext == ExpressionContext.ForeachInToken) { col.Add ("in", "md-keyword"); } else { col.Add ("global", "md-keyword"); col.Add ("var", "md-keyword"); AddPrimitiveTypes (col); resolver.AddAccessibleCodeCompletionData (expressionResult.ExpressionContext, col); } if (resolver.CallingMember is IMethod) { foreach (ITypeParameter tp in ((IMethod)resolver.CallingMember).TypeParameters) { col.Add (tp.Name, "md-keyword"); } } return result; }
ICompletionDataList CreateCaseCompletionData (DomLocation location, ExpressionResult expressionResult) { NRefactoryResolver resolver = CreateResolver (); resolver.SetupResolver (location); SwitchFinder switchFinder = new SwitchFinder (location); if (resolver.MemberCompilationUnit != null) switchFinder.VisitCompilationUnit (resolver.MemberCompilationUnit, null); CompletionDataList result = new ProjectDomCompletionDataList (); if (switchFinder.SwitchStatement == null) return result; ResolveResult resolveResult = resolver.ResolveExpression (switchFinder.SwitchStatement.SwitchExpression, location); IType type = dom.GetType (resolveResult.ResolvedType); if (type != null && type.ClassType == ClassType.Enum) { OutputFlags flags = OutputFlags.None; var declaringType = resolver.CallingType; if (declaringType != null && dom != null) { foreach (IType t in new List<IType>(dom.GetInheritanceTree (declaringType))) { if (t.SearchMember (type.Name, true).Any (m => m.MemberType != MonoDevelop.Projects.Dom.MemberType.Type)) { flags |= OutputFlags.UseFullName; break; } } } // if (!foundType && (NamePrefix.Length == 0 || !type.Namespace.StartsWith (NamePrefix)) && !type.Namespace.EndsWith ("." + NamePrefix) && type.DeclaringType == null && NamePrefix != null && !NamePrefix.Contains ("::")) // flags |= OutputFlags.UseFullName; CompletionDataCollector cdc = new CompletionDataCollector (dom, result, Document.CompilationUnit, resolver.CallingType, location); cdc.Add (type, flags); } return result; }
static void AddPrimitiveTypes (CompletionDataCollector col) { foreach (string primitiveType in primitiveTypes) { col.Add (primitiveType, "md-keyword"); } }
static void AddNRefactoryKeywords (CompletionDataCollector col, System.Collections.BitArray keywords) { for (int i = 0; i < keywords.Length; i++) { if (keywords[i]) { string keyword = ICSharpCode.NRefactory.Parser.CSharp.Tokens.GetTokenString (i); if (keyword.IndexOf ('<') >= 0) continue; col.Add (keyword, "md-keyword"); } } }
CompletionDataList CreateTypeCompletionData (DomLocation location, IType callingType, ExpressionContext context, IReturnType returnType, IReturnType returnTypeUnresolved) { CompletionDataList result = new ProjectDomCompletionDataList (); // "var o = new " needs special treatment. if (returnType == null && returnTypeUnresolved != null && returnTypeUnresolved.FullName == "var") returnType = returnTypeUnresolved = DomReturnType.Object; // ExpressionContext.TypeExpressionContext tce = context as ExpressionContext.TypeExpressionContext; CompletionDataCollector col = new CompletionDataCollector (dom, result, Document.CompilationUnit, callingType, location); IType type = null; if (returnType != null) type = dom.GetType (returnType); if (type == null) type = dom.SearchType (Document.CompilationUnit, (MonoDevelop.Projects.Dom.INode)Document.CompilationUnit ?? callingType, returnTypeUnresolved); // special handling for nullable types: Bug 674516 - new completion for nullables should not include "Nullable" if (type is InstantiatedType && ((InstantiatedType)type).UninstantiatedType.FullName == "System.Nullable" && ((InstantiatedType)type).GenericParameters.Count == 1) { var genericParameter = ((InstantiatedType)type).GenericParameters[0]; returnType = returnTypeUnresolved = Document.CompilationUnit.ShortenTypeName (genericParameter, location); type = dom.SearchType (Document.CompilationUnit, (MonoDevelop.Projects.Dom.INode)Document.CompilationUnit ?? callingType, genericParameter); } if (type == null || !(type.IsAbstract || type.ClassType == ClassType.Interface)) { if (type == null || type.ConstructorCount == 0 || type.Methods.Any (c => c.IsConstructor && c.IsAccessibleFrom (dom, callingType, type, callingType != null && dom.GetInheritanceTree (callingType).Any (x => x.FullName == type.FullName)))) { if (returnTypeUnresolved != null) { col.FullyQualify = true; CompletionData unresovedCompletionData = col.Add (returnTypeUnresolved); col.FullyQualify = false; // don't set default completion string for arrays, since it interferes with: // string[] arr = new string[] vs new { "a"} if (returnTypeUnresolved.ArrayDimensions == 0) result.DefaultCompletionString = StripGenerics (unresovedCompletionData.CompletionText); } else { CompletionData unresovedCompletionData = col.Add (returnType); if (returnType.ArrayDimensions == 0) result.DefaultCompletionString = StripGenerics (unresovedCompletionData.CompletionText); } } } // if (tce != null && tce.Type != null) { // result.DefaultCompletionString = StripGenerics (col.AddCompletionData (result, tce.Type).CompletionString); // } // else { // } if (type == null) return result; HashSet<string> usedNamespaces = new HashSet<string> (GetUsedNamespaces ()); if (type.FullName == DomReturnType.Object.FullName) AddPrimitiveTypes (col); foreach (IType curType in dom.GetSubclasses (type)) { if (context != null && context.FilterEntry (curType)) continue; if ((curType.TypeModifier & TypeModifier.HasOnlyHiddenConstructors) == TypeModifier.HasOnlyHiddenConstructors) continue; if (usedNamespaces.Contains (curType.Namespace)) { if (curType.ConstructorCount > 0) { if (!(curType.Methods.Any (c => c.IsConstructor && c.IsAccessibleFrom (dom, curType, callingType, callingType != null && dom.GetInheritanceTree (callingType).Any (x => x.FullName == curType.FullName))))) continue; } col.Add (curType); } else { string nsName = curType.Namespace; int idx = nsName.IndexOf ('.'); if (idx >= 0) nsName = nsName.Substring (0, idx); col.Add (new Namespace (nsName)); } } // add aliases if (returnType != null) { foreach (IUsing u in Document.CompilationUnit.Usings) { foreach (KeyValuePair<string, IReturnType> alias in u.Aliases) { if (alias.Value.ToInvariantString () == returnType.ToInvariantString ()) result.Add (alias.Key, "md-class"); } } } return result; }
public override ICompletionDataList HandleCodeCompletion (CodeCompletionContext completionContext, char completionChar, ref int triggerWordLength) { if (textEditorData.CurrentMode is CompletionTextLinkMode) { if (!((CompletionTextLinkMode)textEditorData.CurrentMode).TriggerCodeCompletion) return null; } else if (textEditorData.CurrentMode is Mono.TextEditor.TextLinkEditMode) { return null; } // IDisposable timer = null; try { if (dom == null /*|| Document.CompilationUnit == null*/) return null; if (completionChar != '#' && stateTracker.Engine.IsInsidePreprocessorDirective) return null; // timer = Counters.ResolveTime.BeginTiming (); DomLocation location = new DomLocation (completionContext.TriggerLine, completionContext.TriggerLineOffset - 1); stateTracker.UpdateEngine (); ExpressionResult result; int cursor, newCursorOffset = 0; switch (completionChar) { case ':': case '.': if (stateTracker.Engine.IsInsideDocLineComment || stateTracker.Engine.IsInsideOrdinaryCommentOrString) return null; result = FindExpression (dom, completionContext); if (result == null || result.Expression == null) return null; int idx = result.Expression.LastIndexOf ('.'); if (idx > 0) result.Expression = result.Expression.Substring (0, idx); // don't parse expressions that end with more than 1 dot - see #646820 if (result.Expression.EndsWith (".")) return null; NRefactoryResolver resolver = CreateResolver (); ResolveResult resolveResult = resolver.Resolve (result, location); if (resolver.ResolvedExpression is ICSharpCode.NRefactory.Ast.PrimitiveExpression) { ICSharpCode.NRefactory.Ast.PrimitiveExpression pex = (ICSharpCode.NRefactory.Ast.PrimitiveExpression)resolver.ResolvedExpression; if (!tryToForceCompletion && !(pex.Value is string || pex.Value is char || pex.Value is bool)) return null; } return CreateCompletionData (location, resolveResult, result, resolver); case '#': if (stateTracker.Engine.IsInsidePreprocessorDirective) return GetDirectiveCompletionData (); return null; case '>': cursor = textEditorData.IsSomethingSelected ? textEditorData.SelectionRange.Offset : textEditorData.Caret.Offset; if (stateTracker.Engine.IsInsideDocLineComment) { string lineText = textEditorData.GetLineText (completionContext.TriggerLine); int startIndex = Math.Min (completionContext.TriggerLineOffset - 1, lineText.Length - 1); while (startIndex >= 0 && lineText[startIndex] != '<') { --startIndex; if (lineText[startIndex] == '/') { // already closed. startIndex = -1; break; } } if (startIndex >= 0) { int endIndex = startIndex; while (endIndex <= completionContext.TriggerLineOffset && endIndex < lineText.Length && !Char.IsWhiteSpace (lineText[endIndex])) { endIndex++; } string tag = endIndex - startIndex - 1 > 0 ? lineText.Substring (startIndex + 1, endIndex - startIndex - 2) : null; if (!String.IsNullOrEmpty (tag) && commentTags.IndexOf (tag) >= 0) { textEditorData.Insert (cursor, "</" + tag + ">"); textEditorData.Caret.Offset = cursor; return null; } } } return null; /* Disabled because it gives problems when declaring arrays - for example string [] should not pop up code completion. case '[': if (stateTracker.Engine.IsInsideDocLineComment || stateTracker.Engine.IsInsideOrdinaryCommentOrString) return null; result = FindExpression (dom, completionContext); if (result.ExpressionContext == ExpressionContext.Attribute) return CreateCtrlSpaceCompletionData (completionContext, result); return null;*/ case '<': if (stateTracker.Engine.IsInsideDocLineComment) return GetXmlDocumentationCompletionData (); return null; case '(': if (stateTracker.Engine.IsInsideDocLineComment || stateTracker.Engine.IsInsideOrdinaryCommentOrString) return null; result = FindExpression (dom, completionContext, -1); if (result == null || result.Expression == null) return null; resolver = CreateResolver (); resolveResult = resolver.Resolve (result, new DomLocation (completionContext.TriggerLine, completionContext.TriggerLineOffset - 2)); if (resolveResult != null && resolver.ResolvedExpression is ICSharpCode.NRefactory.Ast.TypeOfExpression) { CompletionDataList completionList = new ProjectDomCompletionDataList (); CompletionDataCollector col = new CompletionDataCollector (dom, completionList, Document.CompilationUnit, resolver.CallingType, location); AddPrimitiveTypes (col); foreach (object o in dom.GetNamespaceContents (GetUsedNamespaces (), true, true)) { col.Add (o); } if (resolver.CallingMember is IMethod) { foreach (ITypeParameter tp in ((IMethod)resolver.CallingMember).TypeParameters) { col.Add (tp.Name, "md-keyword"); } } if (resolver.CallingType != null) { foreach (ITypeParameter tp in resolver.CallingType.TypeParameters) { col.Add (tp.Name, "md-keyword"); } } return completionList; } return null; case '/': cursor = textEditorData.IsSomethingSelected ? textEditorData.SelectionRange.Offset : textEditorData.Caret.Offset; if (cursor < 2) break; if (stateTracker.Engine.IsInsideDocLineComment) { string lineText = textEditorData.GetLineText (completionContext.TriggerLine); bool startsDocComment = true; int slashes = 0; for (int i = 0; i < completionContext.TriggerLineOffset && i < lineText.Length; i++) { if (lineText[i] == '/') { slashes++; continue; } if (!Char.IsWhiteSpace (lineText[i])) { startsDocComment = false; break; } } // check if lines above already start a doc comment for (int i = completionContext.TriggerLine - 2; i >= 1; i--) { string text = textEditorData.GetLineText (i); if (text.Length == 0) continue; if (text.StartsWith ("///")) { startsDocComment = false; break; } break; } // check if following lines start a doc comment for (int i = completionContext.TriggerLine; i <= textEditorData.Document.LineCount; i++) { string text = textEditorData.GetLineText (i); if (text == null) break; text = text.Trim (); if (text.Length == 0) continue; if (text.StartsWith ("///")) { startsDocComment = false; break; } break; } if (!startsDocComment || slashes != 3) break; StringBuilder generatedComment = new StringBuilder (); bool generateStandardComment = true; ParsedDocument currentParsedDocument = Document.UpdateParseDocument (); IType insideClass = NRefactoryResolver.GetTypeAtCursor (currentParsedDocument.CompilationUnit, Document.FileName, location); if (insideClass != null) { string indent = textEditorData.Document.GetLineIndent (completionContext.TriggerLine); if (insideClass.ClassType == ClassType.Delegate) { AppendSummary (generatedComment, indent, out newCursorOffset); IMethod m = null; foreach (IMethod method in insideClass.Methods) m = method; AppendMethodComment (generatedComment, indent, m); generateStandardComment = false; } else { if (!IsInsideClassBody (insideClass, completionContext.TriggerLine, completionContext.TriggerLineOffset)) break; string body = GenerateBody (insideClass, completionContext.TriggerLine, indent, out newCursorOffset); if (!String.IsNullOrEmpty (body)) { generatedComment.Append (body); generateStandardComment = false; } } } if (generateStandardComment) { string indent = textEditorData.Document.GetLineIndent (completionContext.TriggerLine); AppendSummary (generatedComment, indent, out newCursorOffset); } textEditorData.Document.EndAtomicUndo (); textEditorData.Document.BeginAtomicUndo (); textEditorData.Insert (cursor, generatedComment.ToString ()); textEditorData.Caret.Offset = cursor + newCursorOffset; return null; } return null; // case '\n': // case '\r': { // if (stateTracker.Engine.IsInsideDocLineComment || stateTracker.Engine.IsInsideOrdinaryCommentOrString) // return null; // result = FindExpression (dom, completionContext); // if (result == null) // return null; // // // int tokenIndex = completionContext.TriggerOffset; // string token = GetPreviousToken (ref tokenIndex, false); // if (result.ExpressionContext == ExpressionContext.ObjectInitializer) { // if (token == "{" || token == ",") // return CreateCtrlSpaceCompletionData (completionContext, result); // } // return null; // } case ' ': if (stateTracker.Engine.IsInsideDocLineComment || stateTracker.Engine.IsInsideOrdinaryCommentOrString) return null; result = FindExpression (dom, completionContext); if (result == null) return null; int tokenIndex = completionContext.TriggerOffset; string token = GetPreviousToken (ref tokenIndex, false); if (result.ExpressionContext == ExpressionContext.ObjectInitializer) { resolver = CreateResolver (); ExpressionContext exactContext = new NewCSharpExpressionFinder (dom).FindExactContextForObjectInitializer (textEditorData, resolver.Unit, Document.FileName, resolver.CallingType); IReturnType objectInitializer = ((ExpressionContext.TypeExpressionContext)exactContext).UnresolvedType; if (objectInitializer != null && objectInitializer.ArrayDimensions == 0 && objectInitializer.PointerNestingLevel == 0 && (token == "{" || token == ",")) return CreateCtrlSpaceCompletionData (completionContext, result); } if (token == "=") { int j = tokenIndex; string prevToken = GetPreviousToken (ref j, false); if (prevToken == "=" || prevToken == "+" || prevToken == "-") { token = prevToken + token; tokenIndex = j; } } switch (token) { case "=": case "==": result = FindExpression (dom, completionContext, tokenIndex - completionContext.TriggerOffset - 1); resolver = CreateResolver (); resolveResult = resolver.Resolve (result, location); if (resolveResult != null) { IType resolvedType = dom.GetType (resolveResult.ResolvedType); if (resolvedType == null) return null; if (resolvedType.ClassType == ClassType.Enum) { CompletionDataList completionList = new ProjectDomCompletionDataList (); CompletionDataCollector cdc = new CompletionDataCollector (dom, completionList, Document.CompilationUnit, resolver.CallingType, location); IReturnType returnType = new DomReturnType (resolvedType); bool added = false; foreach (IUsing u in Document.CompilationUnit.Usings) { foreach (KeyValuePair<string, IReturnType> alias in u.Aliases) { if (alias.Value.ToInvariantString () == returnType.ToInvariantString ()) { cdc.Add (alias.Key, "md-class"); added = true; } } } if (!added) cdc.Add (returnType);/* foreach (object o in CreateCtrlSpaceCompletionData (completionContext, result)) { MemberCompletionData memberData = o as MemberCompletionData; if (memberData == null || memberData.Member == null) { completionList.Add (o as CompletionData); continue; } if (memberData.Member is IMember) { returnType = ((IMember)memberData.Member).ReturnType; } else if (memberData.Member is IParameter) { returnType = ((IParameter)memberData.Member).ReturnType; } else { returnType = ((LocalVariable)memberData.Member).ReturnType; } // filter out void types if (returnType != null && returnType.FullName != DomReturnType.Void.FullName) completionList.Add (memberData); }*/ completionList.AutoCompleteEmptyMatch = false; resolver.AddAccessibleCodeCompletionData (result.ExpressionContext, cdc); return completionList; } if (resolvedType.FullName == DomReturnType.Bool.FullName) { CompletionDataList completionList = new ProjectDomCompletionDataList (); CompletionDataCollector cdc = new CompletionDataCollector (dom, completionList, Document.CompilationUnit, resolver.CallingType, location); completionList.AutoCompleteEmptyMatch = false; cdc.Add ("true", "md-keyword"); cdc.Add ("false", "md-keyword"); /* foreach (object o in CreateCtrlSpaceCompletionData (completionContext, result)) { MemberCompletionData memberData = o as MemberCompletionData; if (memberData == null || memberData.Member == null) { completionList.Add (o as CompletionData); continue; } IReturnType returnType = null; if (memberData.Member is IMember) { returnType = ((IMember)memberData.Member).ReturnType; } else if (memberData.Member is IParameter) { returnType = ((IParameter)memberData.Member).ReturnType; } else { returnType = ((LocalVariable)memberData.Member).ReturnType; } // filter out void types if (returnType != null && returnType.FullName != DomReturnType.Void.FullName) completionList.Add (memberData); }*/ resolver.AddAccessibleCodeCompletionData (result.ExpressionContext, cdc); return completionList; } if (resolvedType.ClassType == ClassType.Delegate && token == "=") { IMethod delegateMethod = resolvedType.Methods.First (); CompletionDataList completionList = new ProjectDomCompletionDataList (); completionList.Add ("delegate", "md-keyword", GettextCatalog.GetString ("Creates anonymous delegate."), "delegate {" + Document.Editor.EolMarker + stateTracker.Engine.ThisLineIndent + TextEditorProperties.IndentString + "|" + Document.Editor.EolMarker + stateTracker.Engine.ThisLineIndent +"};"); StringBuilder sb = new StringBuilder ("("); for (int k = 0; k < delegateMethod.Parameters.Count; k++) { if (k > 0) sb.Append (", "); IType parameterType = dom.GetType (delegateMethod.Parameters[k].ReturnType); IReturnType returnType = parameterType != null ? new DomReturnType (parameterType) : delegateMethod.Parameters[k].ReturnType; sb.Append (CompletionDataCollector.ambience.GetString (Document.CompilationUnit.ShortenTypeName (returnType, textEditorData.Caret.Line, textEditorData.Caret.Column), OutputFlags.ClassBrowserEntries | OutputFlags.UseFullName | OutputFlags.UseFullInnerTypeName)); sb.Append (" "); sb.Append (delegateMethod.Parameters[k].Name); } sb.Append (")"); completionList.Add ("delegate" + sb, "md-keyword", GettextCatalog.GetString ("Creates anonymous delegate."), "delegate" + sb + " {" + Document.Editor.EolMarker + stateTracker.Engine.ThisLineIndent + TextEditorProperties.IndentString + "|" + Document.Editor.EolMarker + stateTracker.Engine.ThisLineIndent +"};"); string varName = GetPreviousToken (ref tokenIndex, false); varName = GetPreviousToken (ref tokenIndex, false); if (varName != ".") { varName = null; } else { List<string> names = new List<string> (); while (varName == ".") { varName = GetPreviousToken (ref tokenIndex, false); if (varName == "this") { names.Add ("handle"); } else if (varName != null) { string trimmedName = varName.Trim (); if (trimmedName.Length == 0) break; names.Insert (0, trimmedName); } varName = GetPreviousToken (ref tokenIndex, false); } varName = String.Join ("", names.ToArray ()); foreach (char ch in varName) { if (!char.IsLetterOrDigit (ch) && ch != '_') { varName = ""; break; } } } completionList.Add (new EventCreationCompletionData (textEditorData, varName, resolvedType, null, sb.ToString (), resolver.CallingMember, resolvedType)); return completionList; } } return null; case "+=": case "-=": if (stateTracker.Engine.IsInsideDocLineComment || stateTracker.Engine.IsInsideOrdinaryCommentOrString) return null; result = FindExpression (dom, completionContext, tokenIndex - completionContext.TriggerOffset); resolver = CreateResolver (); resolveResult = resolver.Resolve (result, location); if (resolveResult is MemberResolveResult) { MemberResolveResult mrr = resolveResult as MemberResolveResult; IEvent evt = mrr.ResolvedMember as IEvent; if (evt == null) return null; IType delegateType = resolver.SearchType (evt.ReturnType); if (delegateType == null || delegateType.ClassType != ClassType.Delegate) return null; CompletionDataList completionList = new ProjectDomCompletionDataList (); CompletionDataCollector cdc = new CompletionDataCollector (dom, completionList, Document.CompilationUnit, resolver.CallingType, location); IType declaringType = resolver.CallingType; if (Document.LastErrorFreeParsedDocument != null) { declaringType = Document.LastErrorFreeParsedDocument.CompilationUnit.GetType (declaringType.FullName, declaringType.TypeParameters.Count); } IType typeFromDatabase = null; if (declaringType != null) { typeFromDatabase = dom.GetType (declaringType.FullName, new DomReturnType (declaringType).GenericArguments) ?? declaringType; bool includeProtected = DomType.IncludeProtected (dom, typeFromDatabase, resolver.CallingType); foreach (IType type in dom.GetInheritanceTree (typeFromDatabase)) { foreach (IMethod method in type.Methods) { if (method.IsAccessibleFrom (dom, resolver.CallingType, resolver.CallingMember, includeProtected) && MatchDelegate (delegateType, method)) { CompletionData data = cdc.Add (method); data.SetText (data.CompletionText + ";"); } } } } if (token == "+=") { IMethod delegateMethod = delegateType.Methods.First (); completionList.Add ("delegate", "md-keyword", GettextCatalog.GetString ("Creates anonymous delegate."), "delegate {" + Document.Editor.EolMarker + stateTracker.Engine.ThisLineIndent + TextEditorProperties.IndentString + "|" + Document.Editor.EolMarker + stateTracker.Engine.ThisLineIndent +"};"); StringBuilder sb = new StringBuilder ("("); for (int k = 0; k < delegateMethod.Parameters.Count; k++) { if (k > 0) sb.Append (", "); IType parameterType = dom.GetType (delegateMethod.Parameters[k].ReturnType); IReturnType returnType = parameterType != null ? new DomReturnType (parameterType) : delegateMethod.Parameters[k].ReturnType; sb.Append (CompletionDataCollector.ambience.GetString (Document.CompilationUnit.ShortenTypeName (returnType, textEditorData.Caret.Line, textEditorData.Caret.Column), OutputFlags.ClassBrowserEntries | OutputFlags.UseFullName | OutputFlags.UseFullInnerTypeName)); sb.Append (" "); sb.Append (delegateMethod.Parameters[k].Name); } sb.Append (")"); completionList.Add ("delegate" + sb, "md-keyword", GettextCatalog.GetString ("Creates anonymous delegate."), "delegate" + sb + " {" + Document.Editor.EolMarker + stateTracker.Engine.ThisLineIndent + TextEditorProperties.IndentString + "|" + Document.Editor.EolMarker + stateTracker.Engine.ThisLineIndent +"};"); string varName = GetPreviousToken (ref tokenIndex, false); varName = GetPreviousToken (ref tokenIndex, false); if (varName != ".") { varName = null; } else { List<string> names = new List<string> (); while (varName == ".") { varName = GetPreviousToken (ref tokenIndex, false); if (varName == "this") { names.Add ("handle"); } else if (varName != null) { string trimmedName = varName.Trim (); if (trimmedName.Length == 0) break; names.Insert (0, trimmedName); } varName = GetPreviousToken (ref tokenIndex, false); } varName = String.Join ("", names.ToArray ()); foreach (char ch in varName) { if (!char.IsLetterOrDigit (ch) && ch != '_') { varName = ""; break; } } } completionList.Add (new EventCreationCompletionData (textEditorData, varName, delegateType, evt, sb.ToString (), resolver.CallingMember, typeFromDatabase)); } return completionList; } return null; } return HandleKeywordCompletion (completionContext, result, tokenIndex, token); default: if ((Char.IsLetter (completionChar) || completionChar == '_') && TextEditorProperties.EnableAutoCodeCompletion && !stateTracker.Engine.IsInsideDocLineComment && !stateTracker.Engine.IsInsideOrdinaryCommentOrString) { char prevCh = completionContext.TriggerOffset > 2 ? textEditorData.GetCharAt (completionContext.TriggerOffset - 2) : '\0'; char nextCh = completionContext.TriggerOffset < textEditorData.Length ? textEditorData.GetCharAt (completionContext.TriggerOffset) : ' '; const string allowedChars = ";,[(){}+-*/%^?:&|~!<>="; if (!Char.IsWhiteSpace (nextCh) && allowedChars.IndexOf (nextCh) < 0) return null; if (Char.IsWhiteSpace (prevCh) || allowedChars.IndexOf (prevCh) >= 0) { result = FindExpression (dom, completionContext, -1); if (result == null) return null; if (IsInLinqContext (result)) { tokenIndex = completionContext.TriggerOffset; token = GetPreviousToken (ref tokenIndex, false); // token last typed token = GetPreviousToken (ref tokenIndex, false); // possible linq keyword ? triggerWordLength = 1; if (linqKeywords.Contains (token)) { if (token == "from") // after from no auto code completion. return null; result.Expression = ""; return CreateCtrlSpaceCompletionData (completionContext, result); } CompletionDataList dataList = new ProjectDomCompletionDataList (); CompletionDataCollector col = new CompletionDataCollector (dom, dataList, Document.CompilationUnit, null, new DomLocation (completionContext.TriggerLine, completionContext.TriggerLineOffset)); foreach (string kw in linqKeywords) { col.Add (kw, "md-keyword"); } return dataList; } else if (result.ExpressionContext != ExpressionContext.IdentifierExpected) { triggerWordLength = 1; bool autoSelect = true; int cpos; if ((prevCh == ',' || prevCh == '(') && GetParameterCompletionCommandOffset (out cpos)) { CodeCompletionContext ctx = CompletionWidget.CreateCodeCompletionContext (cpos); NRefactoryParameterDataProvider provider = ParameterCompletionCommand (ctx) as NRefactoryParameterDataProvider; if (provider != null) { int i = provider.GetCurrentParameterIndex (CompletionWidget, ctx) - 1; if (i < provider.Methods[0].Parameters.Count) { IType returnType = dom.GetType (provider.Methods[0].Parameters[i].ReturnType); autoSelect = returnType == null || returnType.ClassType != ClassType.Delegate; } } } if (result.ExpressionContext == ExpressionContext.TypeName) autoSelect = false; CompletionDataList dataList = CreateCtrlSpaceCompletionData (completionContext, result); dataList.AutoSelect = autoSelect; return dataList; } else { result = FindExpression (dom, completionContext, 0); tokenIndex = completionContext.TriggerOffset; // check foreach case, unfortunately the expression finder is too dumb to handle full type names // should be overworked if the expression finder is replaced with a mcs ast based analyzer. var possibleForeachToken = GetPreviousToken (ref tokenIndex, false); // starting letter possibleForeachToken = GetPreviousToken (ref tokenIndex, false); // varname // read return types to '(' token possibleForeachToken = GetPreviousToken (ref tokenIndex, false); // varType if (possibleForeachToken == ">") { while (possibleForeachToken != "(") possibleForeachToken = GetPreviousToken (ref tokenIndex, false); } else { possibleForeachToken = GetPreviousToken (ref tokenIndex, false); // ( if (possibleForeachToken == ".") while (possibleForeachToken != "(") possibleForeachToken = GetPreviousToken (ref tokenIndex, false); } possibleForeachToken = GetPreviousToken (ref tokenIndex, false); // foreach if (possibleForeachToken == "foreach") { result.ExpressionContext = ExpressionContext.ForeachInToken; } else { return null; // result.ExpressionContext = ExpressionContext.IdentifierExpected; } result.Expression = ""; result.Region = DomRegion.Empty; // identifier has already started with the first letter completionContext.TriggerOffset--; completionContext.TriggerLineOffset--; completionContext.TriggerWordLength = 1; return CreateCtrlSpaceCompletionData (completionContext, result); } } } break; } } catch (Exception e) { LoggingService.LogError ("Unexpected code completion exception." + Environment.NewLine + "FileName: " + Document.FileName + Environment.NewLine + "Position: line=" + completionContext.TriggerLine + " col=" + completionContext.TriggerLineOffset + Environment.NewLine + "Line text: " + Document.Editor.GetLineText (completionContext.TriggerLine), e); } finally { // if (timer != null) // timer.Dispose (); } return null; }
ICompletionDataList CreateCompletionData (DomLocation location, ResolveResult resolveResult, ExpressionResult expressionResult, NRefactoryResolver resolver) { if (resolveResult == null || expressionResult == null || dom == null) return null; CompletionDataList result = new ProjectDomCompletionDataList (); IEnumerable<object> objects = resolveResult.CreateResolveResult (dom, resolver != null ? resolver.CallingMember : null); CompletionDataCollector col = new CompletionDataCollector (dom, result, Document.CompilationUnit, resolver != null ? resolver.CallingType : null, location); col.HideExtensionParameter = !resolveResult.StaticResolve; col.NamePrefix = expressionResult.Expression; bool showOnlyTypes = expressionResult.Contexts.Any (ctx => ctx == ExpressionContext.InheritableType || ctx == ExpressionContext.Constraints); if (objects != null) { foreach (object obj in objects) { if (expressionResult.ExpressionContext != null && expressionResult.ExpressionContext.FilterEntry (obj)) continue; if (expressionResult.ExpressionContext == ExpressionContext.NamespaceNameExcepted && !(obj is Namespace)) continue; if (showOnlyTypes && !(obj is IType)) continue; CompletionData data = col.Add (obj); if (data != null && expressionResult.ExpressionContext == ExpressionContext.Attribute && data.CompletionText != null && data.CompletionText.EndsWith ("Attribute")) { string newText = data.CompletionText.Substring (0, data.CompletionText.Length - "Attribute".Length); data.SetText (newText); } } } return result; }
void AddVirtuals (CodeCompletionContext ctx, Dictionary<string, bool> alreadyInserted, CompletionDataList completionList, IType type, string modifiers, IReturnType curType) { if (curType == null) return; IType searchType = dom.SearchType (Document.CompilationUnit, (MonoDevelop.Projects.Dom.INode)type ?? Document.CompilationUnit, curType); //System.Console.WriteLine("Add Virtuals for:" + searchType + " / " + curType); if (searchType == null) return; bool isInterface = type.ClassType == ClassType.Interface; bool includeOverriden = false; int declarationBegin = ctx.TriggerOffset; int j = declarationBegin; for (int i = 0; i < 3; i++) { switch (GetPreviousToken (ref j, true)) { case "public": case "protected": case "private": case "internal": case "sealed": case "override": declarationBegin = j; break; case "static": return; // don't add override completion for static members } } CompletionDataCollector col = new CompletionDataCollector (dom, completionList, Document.CompilationUnit, searchType, DomLocation.Empty); List<IType> inheritanceTree = new List<IType> (this.dom.GetInheritanceTree (searchType)); inheritanceTree.Sort ((l, r) => l.ClassType == r.ClassType ? 0 : (l.ClassType == ClassType.Interface ? 1 : (r.ClassType == ClassType.Interface ? -1 : 0))); foreach (IType t in inheritanceTree) { foreach (IMember m in t.Members) { if (!m.IsAccessibleFrom (dom, type, type, true) || m.IsSpecialName) continue; //System.Console.WriteLine ("scan:" + m); //if (m.IsSpecialName || (m.IsInternal && !m.IsProtectedOrInternal) || && searchType.SourceProject != Document.Project) // continue; if (t.ClassType == ClassType.Interface || (isInterface || m.IsVirtual || m.IsAbstract) && !m.IsSealed && (includeOverriden || !type.HasOverriden (m))) { // filter out the "Finalize" methods, because finalizers should be done with destructors. if (m is IMethod && m.Name == "Finalize") continue; //System.Console.WriteLine("add"); NewOverrideCompletionData data = new NewOverrideCompletionData (dom, textEditorData, declarationBegin, type, m); string text = CompletionDataCollector.ambience.GetString (m, OutputFlags.ClassBrowserEntries); // check if the member is already implemented bool foundMember = false; foreach (IMember member in type.Members) { if (text == CompletionDataCollector.ambience.GetString (member, OutputFlags.ClassBrowserEntries)) { foundMember = true; break; } } if (!foundMember && !alreadyInserted.ContainsKey (text)) { alreadyInserted[text] = true; data.CompletionCategory = col.GetCompletionCategory (t); completionList.Add (data); } } } } }
public CompletionDataList CreateParameterCompletion (NRefactoryResolver resolver, DomLocation location, ExpressionContext context, IEnumerable<IMethod> possibleMethods, int parameter) { CompletionDataList completionList = new ProjectDomCompletionDataList (); var addedEnums = new HashSet<string> (); var addedDelegates = new HashSet<string> (); IType resolvedType = null; foreach (var method in possibleMethods) { if (method.Parameters.Count <= parameter) continue; resolvedType = dom.GetType (method.Parameters [parameter].ReturnType); if (resolvedType == null) continue; switch (resolvedType.ClassType) { case MonoDevelop.Projects.Dom.ClassType.Enum: if (addedEnums.Contains (resolvedType.DecoratedFullName)) continue; addedEnums.Add (resolvedType.DecoratedFullName); AddEnumMembers (completionList, resolvedType); break; case MonoDevelop.Projects.Dom.ClassType.Delegate: if (addedDelegates.Contains (resolvedType.DecoratedFullName)) continue; addedDelegates.Add (resolvedType.DecoratedFullName); string parameterDefinition = AddDelegateHandlers (completionList, resolvedType, false, addedDelegates.Count == 1); string varName = "Handle" + method.Parameters [parameter].ReturnType.Name + method.Parameters [parameter].Name; completionList.Add (new EventCreationCompletionData (textEditorData, varName, resolvedType, null, parameterDefinition, resolver.Unit.GetMemberAt (location), resolvedType) { AddSemicolon = false }); break; } } if (addedEnums.Count + addedDelegates.Count == 0) return null; CompletionDataCollector cdc = new CompletionDataCollector (this, dom, completionList, Document.CompilationUnit, resolver.CallingType, location); completionList.AutoCompleteEmptyMatch = false; completionList.AutoSelect = false; resolver.AddAccessibleCodeCompletionData (ExpressionContext.MethodBody, cdc); if (addedDelegates.Count > 0) { foreach (var data in completionList) { if (data is MemberCompletionData) ((MemberCompletionData)data).IsDelegateExpected = true; } } return completionList; }
ICompletionDataList CreateCaseCompletionData (DomLocation location, ExpressionResult expressionResult) { NRefactoryResolver resolver = CreateResolver (); resolver.SetupResolver (location); SwitchFinder switchFinder = new SwitchFinder (location); if (resolver.MemberCompilationUnit != null) switchFinder.VisitCompilationUnit (resolver.MemberCompilationUnit, null); CompletionDataList result = new ProjectDomCompletionDataList (); if (switchFinder.SwitchStatement == null) return result; ResolveResult resolveResult = resolver.ResolveExpression (switchFinder.SwitchStatement.SwitchExpression, location); IType type = dom.GetType (resolveResult.ResolvedType); if (type != null && type.ClassType == ClassType.Enum) { CompletionDataCollector cdc = new CompletionDataCollector (dom, result, Document.CompilationUnit, resolver.CallingType, location); cdc.Add (type); } return result; }
public override ICompletionDataList HandleCodeCompletion(CodeCompletionContext completionContext, char completionChar, ref int triggerWordLength) { // IDisposable timer = null; try { if (dom == null /*|| Document.CompilationUnit == null*/) return null; if (completionChar != '#' && stateTracker.Engine.IsInsidePreprocessorDirective) return null; // timer = Counters.ResolveTime.BeginTiming (); DomLocation location = new DomLocation (completionContext.TriggerLine, completionContext.TriggerLineOffset - 1); stateTracker.UpdateEngine (); ExpressionResult result; int cursor, newCursorOffset = 0; switch (completionChar) { case ':': case '.': if (stateTracker.Engine.IsInsideDocLineComment || stateTracker.Engine.IsInsideOrdinaryCommentOrString) return null; result = FindExpression (dom, completionContext); if (result == null || result.Expression == null) return null; int idx = result.Expression.LastIndexOf ('.'); if (idx > 0) result.Expression = result.Expression.Substring (0, idx); NRefactoryResolver resolver = new NRefactoryResolver (dom, Document.CompilationUnit, ICSharpCode.NRefactory.SupportedLanguage.CSharp, Editor, Document.FileName); ResolveResult resolveResult = resolver.Resolve (result, location); if (resolver.ResolvedExpression is ICSharpCode.NRefactory.Ast.PrimitiveExpression) { ICSharpCode.NRefactory.Ast.PrimitiveExpression pex = (ICSharpCode.NRefactory.Ast.PrimitiveExpression)resolver.ResolvedExpression; if (!tryToForceCompletion && !(pex.Value is string || pex.Value is char || pex.Value is bool)) return null; } return CreateCompletionData (location, resolveResult, result, resolver); case '#': if (stateTracker.Engine.IsInsidePreprocessorDirective) return GetDirectiveCompletionData (); return null; case '>': cursor = Editor.SelectionStartPosition; if (stateTracker.Engine.IsInsideDocLineComment) { string lineText = Editor.GetLineText (completionContext.TriggerLine); int startIndex = Math.Min (completionContext.TriggerLineOffset - 1, lineText.Length - 1); while (startIndex >= 0 && lineText[startIndex] != '<') { --startIndex; if (lineText[startIndex] == '/') { // already closed. startIndex = -1; break; } } if (startIndex >= 0) { int endIndex = startIndex; while (endIndex <= completionContext.TriggerLineOffset && endIndex < lineText.Length && !Char.IsWhiteSpace (lineText[endIndex])) { endIndex++; } string tag = endIndex - startIndex - 1 > 0 ? lineText.Substring (startIndex + 1, endIndex - startIndex - 2) : null; if (!String.IsNullOrEmpty (tag) && commentTags.IndexOf (tag) >= 0) { Editor.InsertText (cursor, "</" + tag + ">"); Editor.CursorPosition = cursor; return null; } } } return null; /* Disabled because it gives problems when declaring arrays - for example string [] should not pop up code completion. case '[': if (stateTracker.Engine.IsInsideDocLineComment || stateTracker.Engine.IsInsideOrdinaryCommentOrString) return null; result = FindExpression (dom, completionContext); if (result.ExpressionContext == ExpressionContext.Attribute) return CreateCtrlSpaceCompletionData (completionContext, result); return null;*/ case '<': if (stateTracker.Engine.IsInsideDocLineComment) return GetXmlDocumentationCompletionData (); return null; case '(': if (stateTracker.Engine.IsInsideDocLineComment || stateTracker.Engine.IsInsideOrdinaryCommentOrString) return null; result = FindExpression (dom, completionContext, -1); if (result == null || result.Expression == null) return null; resolver = new NRefactoryResolver (dom, Document.CompilationUnit, ICSharpCode.NRefactory.SupportedLanguage.CSharp, Editor, Document.FileName); resolveResult = resolver.Resolve (result, new DomLocation (completionContext.TriggerLine, completionContext.TriggerLineOffset - 2)); if (resolveResult != null && resolver.ResolvedExpression is ICSharpCode.NRefactory.Ast.TypeOfExpression) { CompletionDataList completionList = new ProjectDomCompletionDataList (); CompletionDataCollector col = new CompletionDataCollector (completionList, Document.CompilationUnit, location); AddPrimitiveTypes (col); foreach (object o in dom.GetNamespaceContents (GetUsedNamespaces (), true, true)) { col.Add (o); } return completionList; } return null; case '/': cursor = Editor.SelectionStartPosition; if (cursor < 2) break; if (stateTracker.Engine.IsInsideDocLineComment) { string lineText = Editor.GetLineText (completionContext.TriggerLine); bool startsDocComment = true; int slashes = 0; for (int i = 0; i < completionContext.TriggerLineOffset && i < lineText.Length; i++) { if (lineText[i] == '/') { slashes++; continue; } if (!Char.IsWhiteSpace (lineText[i])) { startsDocComment = false; break; } } // check if lines above already start a doc comment for (int i = completionContext.TriggerLine - 1; i >= 0; i--) { string text = Editor.GetLineText (i).Trim (); if (text.Length == 0) continue; if (text.StartsWith ("///")) { startsDocComment = false; break; } break; } // check if following lines start a doc comment for (int i = completionContext.TriggerLine + 1; i < Editor.LineCount; i++) { string text = Editor.GetLineText (i); if (text == null) break; text = text.Trim (); if (text.Length == 0) continue; if (text.StartsWith ("///")) { startsDocComment = false; break; } break; } if (!startsDocComment || slashes != 3) break; StringBuilder generatedComment = new StringBuilder (); bool generateStandardComment = true; ParsedDocument currentParsedDocument = Document.UpdateParseDocument (); IType insideClass = NRefactoryResolver.GetTypeAtCursor (currentParsedDocument.CompilationUnit, Document.FileName, location); if (insideClass != null) { string indent = GetLineWhiteSpace (lineText); if (insideClass.ClassType == ClassType.Delegate) { AppendSummary (generatedComment, indent, out newCursorOffset); IMethod m = null; foreach (IMethod method in insideClass.Methods) m = method; AppendMethodComment (generatedComment, indent, m); generateStandardComment = false; } else { if (!IsInsideClassBody (insideClass, completionContext.TriggerLine, completionContext.TriggerLineOffset)) break; string body = GenerateBody (insideClass, completionContext.TriggerLine, indent, out newCursorOffset); if (!String.IsNullOrEmpty (body)) { generatedComment.Append (body); generateStandardComment = false; } } } if (generateStandardComment) { string indent = GetLineWhiteSpace (Editor.GetLineText (completionContext.TriggerLine)); AppendSummary (generatedComment, indent, out newCursorOffset); } Editor.EndAtomicUndo (); Editor.BeginAtomicUndo (); Editor.InsertText (cursor, generatedComment.ToString ()); Editor.CursorPosition = cursor + newCursorOffset; return null; } return null; case ' ': if (stateTracker.Engine.IsInsideDocLineComment || stateTracker.Engine.IsInsideOrdinaryCommentOrString) return null; result = FindExpression (dom, completionContext); if (result == null) return null; int tokenIndex = completionContext.TriggerOffset; string token = GetPreviousToken (ref tokenIndex, false); if (token == "=") { int j = tokenIndex; string prevToken = GetPreviousToken (ref j, false); if (prevToken == "=" || prevToken == "+" || prevToken == "-") { token = prevToken + token; tokenIndex = j; } } switch (token) { case "=": case "==": result = FindExpression (dom, completionContext, tokenIndex - completionContext.TriggerOffset - 1); resolver = new NRefactoryResolver (dom, Document.CompilationUnit, ICSharpCode.NRefactory.SupportedLanguage.CSharp, Editor, Document.FileName); resolveResult = resolver.Resolve (result, location); if (resolveResult != null) { IType resolvedType = dom.GetType (resolveResult.ResolvedType); if (resolvedType != null && resolvedType.ClassType == ClassType.Enum) { CompletionDataList completionList = new ProjectDomCompletionDataList (); CompletionDataCollector cdc = new CompletionDataCollector (completionList, Document.CompilationUnit, location); IReturnType returnType = new DomReturnType (resolvedType); bool added = false; foreach (IUsing u in Document.CompilationUnit.Usings) { foreach (KeyValuePair<string, IReturnType> alias in u.Aliases) { if (alias.Value.ToInvariantString () == returnType.ToInvariantString ()) { cdc.Add (alias.Key, "md-class"); added = true; } } } if (!added) cdc.Add (returnType); foreach (object o in CreateCtrlSpaceCompletionData (completionContext, result)) { MemberCompletionData memberData = o as MemberCompletionData; if (memberData == null || memberData.Member == null) continue; if (memberData.Member is IMember) { returnType = ((IMember)memberData.Member).ReturnType; } else if (memberData.Member is IParameter) { returnType = ((IParameter)memberData.Member).ReturnType; } else { returnType = ((LocalVariable)memberData.Member).ReturnType; } if (returnType != null && returnType.FullName == resolvedType.FullName) completionList.Add (memberData); } completionList.AutoCompleteEmptyMatch = false; return completionList; } } return null; case "+=": case "-=": if (stateTracker.Engine.IsInsideDocLineComment || stateTracker.Engine.IsInsideOrdinaryCommentOrString) return null; result = FindExpression (dom, completionContext, tokenIndex - completionContext.TriggerOffset); resolver = new NRefactoryResolver (dom, Document.CompilationUnit, ICSharpCode.NRefactory.SupportedLanguage.CSharp, Editor, Document.FileName); resolveResult = resolver.Resolve (result, location); if (resolveResult is MemberResolveResult) { MemberResolveResult mrr = resolveResult as MemberResolveResult; IEvent evt = mrr.ResolvedMember as IEvent; if (evt == null) return null; IType delegateType = dom.GetType (evt.ReturnType); if (delegateType == null || delegateType.ClassType != ClassType.Delegate) return null; CompletionDataList completionList = new ProjectDomCompletionDataList (); CompletionDataCollector cdc = new CompletionDataCollector (completionList, Document.CompilationUnit, location); IType declaringType = resolver.CallingType; if (Document.LastErrorFreeParsedDocument != null) { declaringType = Document.LastErrorFreeParsedDocument.CompilationUnit.GetType (declaringType.FullName, declaringType.TypeParameters.Count); } IType typeFromDatabase = dom.GetType (declaringType.FullName, new DomReturnType (declaringType).GenericArguments) ?? declaringType; bool includeProtected = DomType.IncludeProtected (dom, typeFromDatabase, resolver.CallingType); foreach (IType type in dom.GetInheritanceTree (typeFromDatabase)) { foreach (IMethod method in type.Methods) { if (method.IsAccessibleFrom (dom, resolver.CallingType, resolver.CallingMember, includeProtected) && MatchDelegate (delegateType, method)) { ICompletionData data = cdc.Add (method); data.SetText (data.CompletionText + ";"); } } } if (token == "+=") { IMethod delegateMethod = delegateType.Methods.First (); completionList.Add ("delegate", "md-keyword", GettextCatalog.GetString ("Creates anonymous delegate."), "delegate {\n" + stateTracker.Engine.ThisLineIndent + TextEditorProperties.IndentString + "|\n" + stateTracker.Engine.ThisLineIndent +"};"); StringBuilder sb = new StringBuilder ("("); for (int k = 0; k < delegateMethod.Parameters.Count; k++) { if (k > 0) sb.Append (", "); sb.Append (CompletionDataCollector.ambience.GetString (Document.CompilationUnit.ShortenTypeName (delegateMethod.Parameters[k].ReturnType, Document.TextEditor.CursorLine, Document.TextEditor.CursorColumn), OutputFlags.ClassBrowserEntries | OutputFlags.UseFullName)); sb.Append (" "); sb.Append (delegateMethod.Parameters[k].Name); } sb.Append (")"); completionList.Add ("delegate" + sb, "md-keyword", GettextCatalog.GetString ("Creates anonymous delegate."), "delegate" + sb + " {\n" + stateTracker.Engine.ThisLineIndent + TextEditorProperties.IndentString + "|\n" + stateTracker.Engine.ThisLineIndent +"};"); string varName = GetPreviousToken (ref tokenIndex, false); varName = GetPreviousToken (ref tokenIndex, false); if (varName != ".") { varName = null; } else { List<string> names = new List<string> (); while (varName == ".") { varName = GetPreviousToken (ref tokenIndex, false); if (varName == "this") { names.Add ("handle"); } else if (varName != null) { string trimmedName = varName.Trim (); if (trimmedName.Length == 0) break; names.Insert (0, trimmedName); } varName = GetPreviousToken (ref tokenIndex, false); } varName = String.Join ("", names.ToArray ()); } completionList.Add (new EventCreationCompletionData (((Mono.TextEditor.ITextEditorDataProvider)Document.GetContent<Mono.TextEditor.ITextEditorDataProvider> ()).GetTextEditorData (), varName, delegateType, evt, sb.ToString (), resolver.CallingMember, typeFromDatabase)); } return completionList; } return null; } return HandleKeywordCompletion (completionContext, result, tokenIndex, token); default: if ((Char.IsLetter (completionChar) || completionChar == '_') && TextEditorProperties.EnableAutoCodeCompletion && !stateTracker.Engine.IsInsideDocLineComment && !stateTracker.Engine.IsInsideOrdinaryCommentOrString) { char prevCh = completionContext.TriggerOffset > 2 ? Editor.GetCharAt (completionContext.TriggerOffset - 2) : '\0'; char nextCh = completionContext.TriggerOffset < Editor.TextLength ? Editor.GetCharAt (completionContext.TriggerOffset) : ' '; const string allowedChars = ";[(){}+-*/%^?:&|~!<>="; if (!Char.IsWhiteSpace (nextCh) && allowedChars.IndexOf (nextCh) < 0) return null; if (Char.IsWhiteSpace (prevCh) || allowedChars.IndexOf (prevCh) >= 0) { result = FindExpression (dom, completionContext, -1); if (result == null) return null; if (result.ExpressionContext != ExpressionContext.IdentifierExpected) { triggerWordLength = 1; bool autoSelect = true; int cpos; if ((prevCh == ',' || prevCh == '(') && GetParameterCompletionCommandOffset (out cpos)) { CodeCompletionContext ctx = CompletionWidget.CreateCodeCompletionContext (cpos); NRefactoryParameterDataProvider provider = ParameterCompletionCommand (ctx) as NRefactoryParameterDataProvider; if (provider != null) { int i = provider.GetCurrentParameterIndex (ctx) - 1; if (i < provider.Methods[0].Parameters.Count) { IType returnType = dom.GetType (provider.Methods[0].Parameters[i].ReturnType); autoSelect = returnType == null || returnType.ClassType != ClassType.Delegate; } } } CompletionDataList dataList = CreateCtrlSpaceCompletionData (completionContext, result); dataList.AutoSelect = autoSelect; return dataList; } } } break; } } catch (Exception e) { System.Console.WriteLine("cce: " +e); } finally { // if (timer != null) // timer.Dispose (); } return null; }
CompletionDataList CreateTypeCompletionData(DomLocation location, IType callingType, ExpressionContext context, IReturnType returnType, IReturnType returnTypeUnresolved) { CompletionDataList result = new ProjectDomCompletionDataList (); // "var o = new " needs special treatment. if (returnType == null && returnTypeUnresolved != null && returnTypeUnresolved.FullName == "var") returnType = returnTypeUnresolved = DomReturnType.Object; // ExpressionContext.TypeExpressionContext tce = context as ExpressionContext.TypeExpressionContext; CompletionDataCollector col = new CompletionDataCollector (result, Document.CompilationUnit, location); IType type = null; if (returnType != null) type = dom.GetType (returnType); if (type == null) type = dom.SearchType (new SearchTypeRequest (Document.CompilationUnit, returnTypeUnresolved, null)); if (type == null || !(type.IsAbstract || type.ClassType == ClassType.Interface)) { if (type == null || type.ConstructorCount == 0 || type.Methods.Any (c => c.IsConstructor && c.IsAccessibleFrom (dom, callingType, type, callingType != null && dom.GetInheritanceTree (callingType).Any (x => x.FullName == type.FullName)))) { if (returnTypeUnresolved != null) { col.FullyQualify = true; ICompletionData unresovedCompletionData = col.Add (returnTypeUnresolved); col.FullyQualify = false; result.DefaultCompletionString = StripGenerics (unresovedCompletionData.CompletionText); } else { ICompletionData unresovedCompletionData = col.Add (returnType); result.DefaultCompletionString = StripGenerics (unresovedCompletionData.CompletionText); } } } // if (tce != null && tce.Type != null) { // result.DefaultCompletionString = StripGenerics (col.AddCompletionData (result, tce.Type).CompletionString); // } // else { // } if (type == null) return result; HashSet<string> usedNamespaces = new HashSet<string> (GetUsedNamespaces ()); if (type.FullName == DomReturnType.Object.FullName) AddPrimitiveTypes (col); foreach (IType curType in dom.GetSubclasses (type)) { if (context != null && context.FilterEntry (curType)) continue; if ((curType.TypeModifier & TypeModifier.HasOnlyHiddenConstructors) == TypeModifier.HasOnlyHiddenConstructors) continue; if (usedNamespaces.Contains (curType.Namespace)) { if (curType.ConstructorCount > 0) { if (!(curType.Methods.Any (c => c.IsConstructor && c.IsAccessibleFrom (dom, curType, callingType, callingType != null && dom.GetInheritanceTree (callingType).Any (x => x.FullName == curType.FullName))))) continue; } col.Add (curType); } else { string nsName = curType.Namespace; int idx = nsName.IndexOf ('.'); if (idx >= 0) nsName = nsName.Substring (0, idx); col.Add (new Namespace (nsName)); } } // add aliases if (returnType != null) { foreach (IUsing u in Document.CompilationUnit.Usings) { foreach (KeyValuePair<string, IReturnType> alias in u.Aliases) { if (alias.Value.ToInvariantString () == returnType.ToInvariantString ()) result.Add (alias.Key, "md-class"); } } } return result; }
public CompletionDataList CreatePossibleEnumCompletion (NRefactoryResolver resolver, DomLocation location, ExpressionContext context, IEnumerable<IMethod> possibleMethods, int parameter) { CompletionDataList completionList = new ProjectDomCompletionDataList (); var addedEnums = new HashSet<string> (); IType resolvedType = null; foreach (var method in possibleMethods) { if (method.Parameters.Count <= parameter) continue; resolvedType = dom.GetType (method.Parameters [parameter].ReturnType); if (resolvedType == null || resolvedType.ClassType != ClassType.Enum) continue; if (addedEnums.Contains (resolvedType.DecoratedFullName)) continue; addedEnums.Add (resolvedType.DecoratedFullName); AddEnumMembers (completionList, resolvedType); } if (addedEnums.Count == 0) return null; CompletionDataCollector cdc = new CompletionDataCollector (dom, completionList, Document.CompilationUnit, resolver.CallingType, location); completionList.AutoCompleteEmptyMatch = false; //completionList.AutoSelect = false; resolver.AddAccessibleCodeCompletionData (context, cdc); return completionList; }