Exemplo n.º 1
0
        protected Tuple <ResolveResult, CSharpResolver> ResolveExpression(CSharpParsedFile file, AstNode expr, CompilationUnit unit)
        {
            if (expr == null)
            {
                return(null);
            }
            AstNode resolveNode;

            if (expr is Expression || expr is AstType)
            {
                resolveNode = expr;
            }
            else if (expr is VariableDeclarationStatement)
            {
                resolveNode = ((VariableDeclarationStatement)expr).Type;
            }
            else
            {
                resolveNode = expr;
            }

//			var newContent = ProjectContent.UpdateProjectContent (CSharpParsedFile, file);

            var csResolver = new CSharpResolver(ctx);

            var navigator = new NodeListResolveVisitorNavigator(new[] { resolveNode });
            var visitor   = new ResolveVisitor(csResolver, CSharpParsedFile, navigator);

            visitor.Scan(unit);
            var state  = visitor.GetResolverStateBefore(resolveNode);
            var result = visitor.GetResolveResult(resolveNode);

            return(Tuple.Create(result, state));
        }
Exemplo n.º 2
0
 /// <summary>
 /// Gets the resolver state immediately before the specified node.
 /// That is, if the node is a variable declaration, the returned state will not contain the newly declared variable.
 /// </summary>
 public CppResolver GetResolverStateBefore(AstNode node, CancellationToken cancellationToken = default(CancellationToken))
 {
     if (node == null || node.IsNull)
     {
         throw new ArgumentNullException("node");
     }
     InitResolver();
     resolveVisitor.cancellationToken = cancellationToken;
     try {
         CppResolver resolver = resolveVisitor.GetResolverStateBefore(node);
         Debug.Assert(resolver != null);
         return(resolver);
     } finally {
         resolveVisitor.cancellationToken = CancellationToken.None;
     }
 }
Exemplo n.º 3
0
        IEnumerable<ICompletionData> MagicKeyCompletion(char completionChar, bool controlSpace)
        {
            switch (completionChar) {
            // Magic key completion
            case ':':
            case '.':
                if (IsInsideCommentOrString ())
                    return Enumerable.Empty<ICompletionData> ();
                var expr = GetExpressionBeforeCursor ();
                if (expr == null)
                    return null;
                // do not complete <number>. (but <number>.<number>.)
                if (expr.Item2 is PrimitiveExpression) {
                    var pexpr = (PrimitiveExpression)expr.Item2;
                    if (!(pexpr.Value is string || pexpr.Value is char) && !pexpr.LiteralValue.Contains ('.'))
                        return null;
                }

                var resolveResult = ResolveExpression (expr.Item1, expr.Item2, expr.Item3);

                if (resolveResult == null)
                    return null;
                if (expr.Item2 is AstType)
                    return CreateTypeAndNamespaceCompletionData (location, resolveResult.Item1, expr.Item2, resolveResult.Item2);
                return CreateCompletionData (location, resolveResult.Item1, expr.Item2, resolveResult.Item2);
            case '#':
                if (IsInsideCommentOrString ())
                    return null;
                return GetDirectiveCompletionData ();

            // XML doc completion
            case '<':
                if (IsInsideDocComment ())
                    return GetXmlDocumentationCompletionData ();
                if (controlSpace)
                    return DefaultControlSpaceItems ();
                return null;
            case '>':
                if (!IsInsideDocComment ())
                    return null;
                string lineText = document.GetText (document.GetLineByNumber (location.Line));
                int startIndex = Math.Min (location.Column - 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 <= location.Column && 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)
                        document.Insert (offset, "</" + tag + ">");
                }
                return null;

            // Parameter completion
            case '(':
                if (IsInsideCommentOrString ())
                    return null;
                var invoke = GetInvocationBeforeCursor (true);
                if (invoke == null)
                    return null;
                if (invoke.Item2 is TypeOfExpression)
                    return CreateTypeList ();
                var invocationResult = ResolveExpression (invoke.Item1, invoke.Item2, invoke.Item3);
                if (invocationResult == null)
                    return null;
                var methodGroup = invocationResult.Item1 as MethodGroupResolveResult;
                if (methodGroup != null)
                    return CreateParameterCompletion (methodGroup, invocationResult.Item2, invoke.Item2, 0, controlSpace);

                if (controlSpace)
                    return DefaultControlSpaceItems (invoke);

                return null;
            case '=':
                return controlSpace ? DefaultControlSpaceItems () : null;
            case ',':
                int cpos2;
                if (!GetParameterCompletionCommandOffset (out cpos2))
                    return null;
            //	completionContext = CompletionWidget.CreateCodeCompletionContext (cpos2);
            //	int currentParameter2 = MethodParameterDataProvider.GetCurrentParameterIndex (CompletionWidget, completionContext) - 1;
            //				return CreateParameterCompletion (CreateResolver (), location, ExpressionContext.MethodBody, provider.Methods, currentParameter);
                break;

            // Completion on space:
            case ' ':
                if (IsInsideCommentOrString ())
                    return null;

                int tokenIndex = offset;
                string token = GetPreviousToken (ref tokenIndex, false);
                // check propose name, for context <variable name> <ctrl+space> (but only in control space context)
                //IType isAsType = null;
                var isAsExpression = GetExpressionAt (offset);
                if (controlSpace && isAsExpression != null && isAsExpression.Item2 is VariableDeclarationStatement && token != "new") {
                    var parent = isAsExpression.Item2 as VariableDeclarationStatement;
                    var proposeNameList = new CompletionDataWrapper (this);

                    foreach (var possibleName in GenerateNameProposals (parent.Type)) {
                        if (possibleName.Length > 0)
                            proposeNameList.Result.Add (factory.CreateLiteralCompletionData (possibleName.ToString ()));
                    }

                    AutoSelect = false;
                    AutoCompleteEmptyMatch = false;
                    return proposeNameList.Result;
                }
            //				int tokenIndex = offset;
            //				string token = GetPreviousToken (ref tokenIndex, false);
            //				if (result.ExpressionContext == ExpressionContext.ObjectInitializer) {
            //					resolver = CreateResolver ();
            //					ExpressionContext exactContext = new NewCSharpExpressionFinder (dom).FindExactContextForObjectInitializer (document, 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 ",":
                    int cpos;
                    if (!GetParameterCompletionCommandOffset (out cpos))
                        break;
                    int currentParameter = GetCurrentParameterIndex (cpos, 0) - 1;
                    if (currentParameter < 0)
                        return null;
                    invoke = GetInvocationBeforeCursor (token == "(");
                    if (invoke == null)
                        return null;
                    invocationResult = ResolveExpression (invoke.Item1, invoke.Item2, invoke.Item3);
                    if (invocationResult == null)
                        return null;
                    methodGroup = invocationResult.Item1 as MethodGroupResolveResult;
                    if (methodGroup != null)
                        return CreateParameterCompletion (methodGroup, invocationResult.Item2, invoke.Item2, currentParameter, controlSpace);
                    return null;
                case "=":
                case "==":
                    GetPreviousToken (ref tokenIndex, false);

                    var expressionOrVariableDeclaration = GetExpressionAt (tokenIndex);
                    if (expressionOrVariableDeclaration == null)
                        return null;

                    resolveResult = ResolveExpression (expressionOrVariableDeclaration.Item1, expressionOrVariableDeclaration.Item2, expressionOrVariableDeclaration.Item3);
                    if (resolveResult == null)
                        return null;
                    if (resolveResult.Item1.Type.Kind == TypeKind.Enum) {
                        var wrapper = new CompletionDataWrapper (this);
                        AddContextCompletion (wrapper, resolveResult.Item2, expressionOrVariableDeclaration.Item2);
                        AddEnumMembers (wrapper, resolveResult.Item1.Type, resolveResult.Item2);
                        AutoCompleteEmptyMatch = false;
                        return wrapper.Result;
                    }
            //
            //					if (resolvedType.FullName == DomReturnType.Bool.FullName) {
            //						CompletionDataList completionList = new ProjectDomCompletionDataList ();
            //						CompletionDataCollector cdc = new CompletionDataCollector (this, dom, completionList, Document.CompilationUnit, resolver.CallingType, location);
            //						completionList.AutoCompleteEmptyMatch = false;
            //						cdc.Add ("true", "md-keyword");
            //						cdc.Add ("false", "md-keyword");
            //						resolver.AddAccessibleCodeCompletionData (result.ExpressionContext, cdc);
            //						return completionList;
            //					}
            //					if (resolvedType.ClassType == ClassType.Delegate && token == "=") {
            //						CompletionDataList completionList = new ProjectDomCompletionDataList ();
            //						string parameterDefinition = AddDelegateHandlers (completionList, resolvedType);
            //						string varName = GetPreviousMemberReferenceExpression (tokenIndex);
            //						completionList.Add (new EventCreationCompletionData (document, varName, resolvedType, null, parameterDefinition, resolver.CallingMember, resolvedType));
            //
            //						CompletionDataCollector cdc = new CompletionDataCollector (this, dom, completionList, Document.CompilationUnit, resolver.CallingType, location);
            //						resolver.AddAccessibleCodeCompletionData (result.ExpressionContext, cdc);
            //						foreach (var data in completionList) {
            //							if (data is MemberCompletionData)
            //								((MemberCompletionData)data).IsDelegateExpected = true;
            //						}
            //						return completionList;
            //					}
                    return null;
                case "+=":
                case "-=":
                    GetPreviousToken (ref tokenIndex, false);

                    expressionOrVariableDeclaration = GetExpressionAt (tokenIndex);
                    if (expressionOrVariableDeclaration == null)
                        return null;

                    resolveResult = ResolveExpression (expressionOrVariableDeclaration.Item1, expressionOrVariableDeclaration.Item2, expressionOrVariableDeclaration.Item3);
                    if (resolveResult == null)
                        return null;

                    var mrr = resolveResult.Item1 as MemberResolveResult;
                    if (mrr != null) {
                        var evt = mrr.Member as IEvent;
                        if (evt == null)
                            return null;
                        var delegateType = evt.ReturnType;
                        if (delegateType.Kind != TypeKind.Delegate)
                            return null;

                        var wrapper = new CompletionDataWrapper (this);
                        if (currentType != null) {
            //							bool includeProtected = DomType.IncludeProtected (dom, typeFromDatabase, resolver.CallingType);
                            foreach (var method in currentType.Methods) {
                                if (MatchDelegate (delegateType, method) /*&& method.IsAccessibleFrom (dom, resolver.CallingType, resolver.CallingMember, includeProtected) &&*/) {
                                    wrapper.AddMember (method);
            //									data.SetText (data.CompletionText + ";");
                                }
                            }
                        }
                        if (token == "+=") {
                            string parameterDefinition = AddDelegateHandlers (wrapper, delegateType);
                            string varName = GetPreviousMemberReferenceExpression (tokenIndex);
                            wrapper.Result.Add (factory.CreateEventCreationCompletionData (varName, delegateType, evt, parameterDefinition, currentMember, currentType));
                        }

                        return wrapper.Result;
                    }
                    return null;
                case ":":
                    if (currentMember == null) {
                        var wrapper = new CompletionDataWrapper (this);
                        AddTypesAndNamespaces (wrapper, GetState (), null, t => currentType != null ? !currentType.Equals (t) : true);
                        return wrapper.Result;
                    }
                    return null;
                }

                var keywordCompletion = HandleKeywordCompletion (tokenIndex, token);
                if (keywordCompletion == null && controlSpace)
                    goto default;
                return keywordCompletion;
            // Automatic completion
            default:
                if (IsInsideCommentOrString ())
                    return null;
                if (IsInLinqContext (offset)) {
                    tokenIndex = offset;
                    token = GetPreviousToken (ref tokenIndex, false); // token last typed
                    if (linqKeywords.Contains (token)) {
                        if (token == "from") // after from no auto code completion.
                            return null;
                        return DefaultControlSpaceItems ();
                    }
                    var dataList = new CompletionDataWrapper (this);
                    AddKeywords (dataList, linqKeywords);
                    return dataList.Result;
                }

                if (currentType != null && currentType.Kind == TypeKind.Enum)
                    return HandleEnumContext ();

                var contextList = new CompletionDataWrapper (this);
                var identifierStart = GetExpressionAtCursor ();
                if (identifierStart != null && identifierStart.Item2 is TypeParameterDeclaration)
                    return null;

                if (identifierStart != null && identifierStart.Item2 is VariableInitializer && location <= ((VariableInitializer)identifierStart.Item2).NameToken.EndLocation) {
                    return controlSpace ? HandleAccessorContext () ?? DefaultControlSpaceItems (identifierStart) : null;
                }
                if (!(char.IsLetter (completionChar) || completionChar == '_') && (!controlSpace || identifierStart == null || !(identifierStart.Item2 is ArrayInitializerExpression))) {
                    return controlSpace ? HandleAccessorContext () ?? DefaultControlSpaceItems (identifierStart) : null;
                }
                char prevCh = offset > 2 ? document.GetCharAt (offset - 2) : ';';
                char nextCh = offset < document.TextLength ? document.GetCharAt (offset) : ' ';
                const string allowedChars = ";,[](){}+-*/%^?:&|~!<>=";
                if (!Char.IsWhiteSpace (nextCh) && allowedChars.IndexOf (nextCh) < 0)
                    return null;
                if (!(Char.IsWhiteSpace (prevCh) || allowedChars.IndexOf (prevCh) >= 0))
                    return null;
                // Do not pop up completion on identifier identifier (should be handled by keyword completion).
                tokenIndex = offset - 1;
                token = GetPreviousToken (ref tokenIndex, false);
                int prevTokenIndex = tokenIndex;
                var prevToken2 = GetPreviousToken (ref prevTokenIndex, false);
                if (identifierStart == null && !string.IsNullOrEmpty (token) && !(IsInsideComment (tokenIndex) || IsInsideString (tokenIndex)) && (prevToken2 == ";" || prevToken2 == "{" || prevToken2 == "}")) {
                    char last = token [token.Length - 1];
                    if (char.IsLetterOrDigit (last) || last == '_' || token == ">") {
                        return HandleKeywordCompletion (tokenIndex, token);
                    }
                }

                if (identifierStart == null)
                    return HandleAccessorContext () ?? DefaultControlSpaceItems ();

                CSharpResolver csResolver;
                AstNode n = identifierStart.Item2;
                // Handle foreach (type name _
                if (n is IdentifierExpression) {
                    var prev = n.GetPrevNode () as ForeachStatement;
                    if (prev != null && prev.InExpression.IsNull) {
                        if (controlSpace) {
                            contextList.AddCustom ("in");
                            return contextList.Result;
                        }
                        return null;
                    }
                }

                if (n is Identifier && n.Parent is ForeachStatement) {
                    if (controlSpace)
                        return DefaultControlSpaceItems ();
                    return null;
                }
                if (n is ArrayInitializerExpression) {
                    // check for new [] {...} expression -> no need to resolve the type there
                    var parent = n.Parent as ArrayCreateExpression;
                    if (parent != null && parent.Type.IsNull)
                        return DefaultControlSpaceItems ();

                    var initalizerResult = ResolveExpression (identifierStart.Item1, n.Parent, identifierStart.Item3);

                    var concreteNode = identifierStart.Item3.GetNodeAt<IdentifierExpression> (location);
                    // check if we're on the right side of an initializer expression
                    if (concreteNode != null && concreteNode.Parent != null && concreteNode.Parent.Parent != null && concreteNode.Identifier != "a" && concreteNode.Parent.Parent is NamedExpression) {
                        return DefaultControlSpaceItems ();
                    }

                    if (initalizerResult != null && initalizerResult.Item1.Type.Kind != TypeKind.Unknown) {

                        foreach (var property in initalizerResult.Item1.Type.GetProperties ()) {
                            if (!property.IsPublic)
                                continue;
                            contextList.AddMember (property);
                        }
                        foreach (var field in initalizerResult.Item1.Type.GetFields ()) {
                            if (!field.IsPublic)
                                continue;
                            contextList.AddMember (field);
                        }
                        return contextList.Result;
                    }
                    Console.WriteLine ("blub");
                    return DefaultControlSpaceItems ();
                }
                if (n != null/* && !(identifierStart.Item2 is TypeDeclaration)*/) {
                    csResolver = new CSharpResolver (ctx);
                    var nodes = new List<AstNode> ();
                    nodes.Add (n);
                    if (n.Parent is ICSharpCode.NRefactory.CSharp.Attribute)
                        nodes.Add (n.Parent);
                    var navigator = new NodeListResolveVisitorNavigator (nodes);
                    var visitor = new ResolveVisitor (csResolver, identifierStart.Item1, navigator);
                    visitor.Scan (identifierStart.Item3);
                    try {
                        csResolver = visitor.GetResolverStateBefore (n);
                    } catch (Exception) {
                        csResolver = GetState ();
                    }
                    // add attribute properties.
                    if (n.Parent is ICSharpCode.NRefactory.CSharp.Attribute) {
                        var resolved = visitor.GetResolveResult (n.Parent);
                        if (resolved != null && resolved.Type != null) {
                            foreach (var property in resolved.Type.GetProperties (p => p.Accessibility == Accessibility.Public)) {
                                contextList.AddMember (property);
                            }
                            foreach (var field in resolved.Type.GetFields (p => p.Accessibility == Accessibility.Public)) {
                                contextList.AddMember (field);
                            }
                        }
                    }
                } else {
                    csResolver = GetState ();
                }

                // identifier has already started with the first letter
                offset--;

                AddContextCompletion (contextList, csResolver, identifierStart.Item2);
                return contextList.Result;
            //				if (stub.Parent is BlockStatement)

            //				result = FindExpression (dom, completionContext, -1);
            //				if (result == null)
            //					return null;
            //				 else if (result.ExpressionContext != ExpressionContext.IdentifierExpected) {
            //					triggerWordLength = 1;
            //					bool autoSelect = true;
            //					IType returnType = null;
            //					if ((prevCh == ',' || prevCh == '(') && GetParameterCompletionCommandOffset (out cpos)) {
            //						ctx = CompletionWidget.CreateCodeCompletionContext (cpos);
            //						NRefactoryParameterDataProvider dataProvider = ParameterCompletionCommand (ctx) as NRefactoryParameterDataProvider;
            //						if (dataProvider != null) {
            //							int i = dataProvider.GetCurrentParameterIndex (CompletionWidget, ctx) - 1;
            //							foreach (var method in dataProvider.Methods) {
            //								if (i < method.Parameters.Count) {
            //									returnType = dom.GetType (method.Parameters [i].ReturnType);
            //									autoSelect = returnType == null || returnType.ClassType != ClassType.Delegate;
            //									break;
            //								}
            //							}
            //						}
            //					}
            //					// Bug 677531 - Auto-complete doesn't always highlight generic parameter in method signature
            //					//if (result.ExpressionContext == ExpressionContext.TypeName)
            //					//	autoSelect = false;
            //					CompletionDataList dataList = CreateCtrlSpaceCompletionData (completionContext, result);
            //					AddEnumMembers (dataList, returnType);
            //					dataList.AutoSelect = autoSelect;
            //					return dataList;
            //				} else {
            //					result = FindExpression (dom, completionContext, 0);
            //					tokenIndex = offset;
            //
            //					// 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 != null && possibleForeachToken != "(") {
            //							possibleForeachToken = GetPreviousToken (ref tokenIndex, false);
            //						}
            //					} else {
            //						possibleForeachToken = GetPreviousToken (ref tokenIndex, false); // (
            //						if (possibleForeachToken == ".")
            //							while (possibleForeachToken != null && 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;
            //
            //					return CreateCtrlSpaceCompletionData (completionContext, result);
            //				}
            //				break;
            }
            return null;
        }
        protected Tuple<ResolveResult, CSharpResolver> ResolveExpression(CSharpParsedFile file, AstNode expr, CompilationUnit unit)
        {
            if (expr == null)
                return null;
            AstNode resolveNode;
            if (expr is Expression || expr is AstType) {
                resolveNode = expr;
            } else if (expr is VariableDeclarationStatement) {
                resolveNode = ((VariableDeclarationStatement)expr).Type;
            } else {
                resolveNode = expr;
            }

            //			var newContent = ProjectContent.UpdateProjectContent (CSharpParsedFile, file);

            var csResolver = new CSharpResolver (ctx);

            var navigator = new NodeListResolveVisitorNavigator (new[] { resolveNode });
            var visitor = new ResolveVisitor (csResolver, CSharpParsedFile, navigator);

            visitor.Scan (unit);
            var state = visitor.GetResolverStateBefore (resolveNode);
            var result = visitor.GetResolveResult (resolveNode);
            return Tuple.Create (result, state);
        }