Supports getting the expression including context from the cursor position.
Inheritance: IExpressionFinder
コード例 #1
0
 ExpressionResult FindExpression(ProjectDom dom, CodeCompletionContext ctx)
 {
     NewFSharpExpressionFinder expressionFinder = new NewFSharpExpressionFinder (dom);
     try {
         return expressionFinder.FindExpression (Editor.Text, ctx.TriggerOffset);
     } catch (Exception ex) {
         LoggingService.LogWarning (ex.Message, ex);
         return null;
     }
 }
コード例 #2
0
        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 ();
                    FSharpTextEditorCompletion.CompletionDataCollector col = new FSharpTextEditorCompletion.CompletionDataCollector (completionList, Document.CompilationUnit, 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 (new SearchTypeRequest (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;
                        }
                        col.Add (o);
                    }
                    // Add inner classes
                    Stack<IType> innerStack = new Stack<IType> ();
                    innerStack.Push (cls);
                    while (innerStack.Count > 0) {
                        IType curType = innerStack.Pop ();
                        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 - Editor.CursorPosition);
                    NRefactoryResolver resolver = new NRefactoryResolver (dom, Document.CompilationUnit, ICSharpCode.NRefactory.SupportedLanguage.CSharp, Editor, Document.FileName);
                    ResolveResult resolveResult = resolver.Resolve (expressionResult, new DomLocation (completionContext.TriggerLine, completionContext.TriggerLineOffset));
                    if (resolveResult != null && resolveResult.ResolvedType != null) {
                        CompletionDataCollector col = new CompletionDataCollector (completionList, Document.CompilationUnit, location);
                        IType foundType = null;
                        if (word == "as") {
                            ExpressionContext exactContext = new NewFSharpExpressionFinder (dom).FindExactContextForAsCompletion (Editor, Document.CompilationUnit, Document.FileName, resolver.CallingType);
                            if (exactContext is ExpressionContext.TypeExpressionContext) {
                                foundType = dom.SearchType (new SearchTypeRequest (resolver.Unit, ((ExpressionContext.TypeExpressionContext)exactContext).Type, resolver.CallingType));

                                AddAsCompletionData (col, foundType);
                            }
                        }

                        if (foundType == null)
                            foundType = dom.SearchType (new SearchTypeRequest (resolver.Unit, resolveResult.ResolvedType, resolver.CallingType));

                        if (foundType != null) {
                            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.ClassType == ClassType.Class || overrideCls.ClassType == ClassType.Struct)) {
                    string modifiers = Editor.GetText (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 = Editor.GetText (firstMod, wordStart);
                    return GetPartialCompletionData (completionContext, overrideCls, modifiers);
                }
                return null;

            case "new":
                IType callingType = NRefactoryResolver.GetTypeAtCursor (Document.CompilationUnit, Document.FileName, new DomLocation (Editor.CursorLine, Editor.CursorColumn));
                ExpressionContext newExactContext = new NewFSharpExpressionFinder (dom).FindExactContextForNewCompletion (Editor, 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 = new NRefactoryResolver (dom, Document.CompilationUnit, ICSharpCode.NRefactory.SupportedLanguage.CSharp, Editor, Document.FileName);
                        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;
            }
            return null;
        }
コード例 #3
0
        CompletionDataList CreateCtrlSpaceCompletionData(CodeCompletionContext ctx, ExpressionResult expressionResult)
        {
            //	Console.WriteLine (Environment.StackTrace);
            //	Console.WriteLine ("---------");
            NRefactoryResolver resolver = new NRefactoryResolver (dom, Document.CompilationUnit, ICSharpCode.NRefactory.SupportedLanguage.CSharp, Editor, Document.FileName);

            DomLocation cursorLocation = new DomLocation (ctx.TriggerLine, ctx.TriggerLineOffset);
            resolver.SetupResolver (cursorLocation);
            //			System.Console.WriteLine ("ctrl+space expression result:" + expressionResult);
            CompletionDataList result = new ProjectDomCompletionDataList ();
            CompletionDataCollector col = new CompletionDataCollector (result, Document.CompilationUnit, 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.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-fsharp", result);
            } else if (expressionResult.ExpressionContext == ExpressionContext.ObjectInitializer) {
                ExpressionContext exactContext = new NewFSharpExpressionFinder (dom).FindExactContextForObjectInitializer (Editor, resolver.Unit, Document.FileName, resolver.CallingType);
                if (exactContext is ExpressionContext.TypeExpressionContext) {
                    IReturnType objectInitializer = ((ExpressionContext.TypeExpressionContext)exactContext).UnresolvedType;

                    IType foundType = dom.SearchType (new SearchTypeRequest (Document.CompilationUnit, objectInitializer, resolver.CallingType));
                    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);
                                }
                            }
                        }
                    }
                }
            //				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 = NewFSharpExpressionFinder.FindAttributeName (Editor, Document.CompilationUnit, Document.FileName);
                if (attributeName != null) {
                    IType type = dom.SearchType (new SearchTypeRequest (resolver.Unit, new DomReturnType (attributeName + "Attribute"), resolver.CallingType));
                    if (type == null)
                        type = dom.SearchType (new SearchTypeRequest (resolver.Unit, new DomReturnType (attributeName), resolver.CallingType));
                    if (type != null) {
                        foreach (IProperty property in type.Properties) {
                            col.Add (property);
                        }
                    }
                }
            } 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 = FSharpAmbience.NetToFSharpTypeName (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");
                    col.Add ("var", "md-keyword");
                    AddPrimitiveTypes (col);
                    resolver.AddAccessibleCodeCompletionData (expressionResult.ExpressionContext, col);
                }
            } else if (expressionResult.ExpressionContext == ExpressionContext.TypeName) {
                col.Add ("global", "md-keyword");
                AddPrimitiveTypes (col);
                resolver.AddAccessibleCodeCompletionData (expressionResult.ExpressionContext, col);
            } 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;
        }