示例#1
0
        public static ResolveResult Resolve(Lazy<ICompilation> compilation, CSharpUnresolvedFile unresolvedFile, SyntaxTree syntaxTree, TextLocation location, out AstNode node,
		                                    CancellationToken cancellationToken = default(CancellationToken))
        {
            node = syntaxTree.GetNodeAt(location);
            if (node == null || node is ArrayInitializerExpression)
                return null;
            if (node.Parent is UsingAliasDeclaration && node.Role == UsingAliasDeclaration.AliasRole) {
                var r = new CSharpAstResolver(compilation.Value, syntaxTree, unresolvedFile);
                return r.Resolve(((UsingAliasDeclaration)node.Parent).Import, cancellationToken);
            }
            if (CSharpAstResolver.IsUnresolvableNode(node)) {
                if (node is Identifier) {
                    node = node.Parent;
                } else if (node.NodeType == NodeType.Token) {
                    if (node.Parent is IndexerExpression || node.Parent is ConstructorInitializer) {
                        // There's no other place where one could hover to see the indexer's tooltip,
                        // so we need to resolve it when hovering over the '[' or ']'.
                        // For constructor initializer, the same applies to the 'base'/'this' token.
                        node = node.Parent;
                    } else {
                        return null;
                    }
                } else {
                    // don't resolve arbitrary nodes - we don't want to show tooltips for everything
                    return null;
                }
            } else {
                // It's a resolvable node.
                // However, we usually don't want to show the tooltip everywhere
                // For example, hovering with the mouse over an empty line between two methods causes
                // node==TypeDeclaration, but we don't want to show any tooltip.

                if (!node.GetChildByRole(Roles.Identifier).IsNull) {
                    // We'll suppress the tooltip for resolvable nodes if there is an identifier that
                    // could be hovered over instead:
                    return null;
                }
            }

            if (node == null)
                return null;

            if (node.Parent is ObjectCreateExpression && node.Role == Roles.Type) {
                node = node.Parent;
            }

            InvocationExpression parentInvocation = null;
            if ((node is IdentifierExpression || node is MemberReferenceExpression || node is PointerReferenceExpression) && node.Role != Roles.Argument) {
                // we also need to resolve the invocation
                parentInvocation = node.Parent as InvocationExpression;
            }

            // TODO: I think we should provide an overload so that an existing CSharpAstResolver can be reused
            CSharpAstResolver resolver = new CSharpAstResolver(compilation.Value, syntaxTree, unresolvedFile);
            ResolveResult rr = resolver.Resolve(node, cancellationToken);
            if (rr is MethodGroupResolveResult && parentInvocation != null)
                return resolver.Resolve(parentInvocation);
            else
                return rr;
        }
示例#2
0
		static IEnumerable<IType> GetAllValidTypesFromInvocation(CSharpAstResolver resolver, InvocationExpression invoke, AstNode parameter)
		{
			int index = GetArgumentIndex(invoke.Arguments, parameter);
			if (index < 0)
				yield break;

			var targetResult = resolver.Resolve(invoke.Target) as MethodGroupResolveResult;
			if (targetResult != null) {
				foreach (var method in targetResult.Methods) {
					if (index < method.Parameters.Count) {
						if (method.Parameters [index].IsParams) {
							var arrayType = method.Parameters [index].Type as ArrayType;
							if (arrayType != null)
								yield return arrayType.ElementType;
						}

						yield return method.Parameters [index].Type;
					}
				}
				foreach (var extMethods in targetResult.GetExtensionMethods ()) {
					foreach (var extMethod in extMethods) {
						if (index + 1 < extMethod.Parameters.Count) {
							if (extMethod.Parameters [index + 1].IsParams) {
								var arrayType = extMethod.Parameters [index + 1].Type as ArrayType;
								if (arrayType != null)
									yield return arrayType.ElementType;
							}

							yield return extMethod.Parameters [index + 1].Type;
						}
					}
				}
			}
		}
		public override IEntity ResolveCref(string cref)
		{
			if (cref.Length > 2 && cref[1] == ':') {
				// resolve ID string
				return base.ResolveCref(cref);
			}
			var documentationReference = new CSharpParser().ParseDocumentationReference(cref);
			var csharpContext = context as CSharpTypeResolveContext;
			CSharpResolver resolver;
			if (csharpContext != null) {
				resolver = new CSharpResolver(csharpContext);
			} else {
				resolver = new CSharpResolver(context.Compilation);
			}
			var astResolver = new CSharpAstResolver(resolver, documentationReference);
			var rr = astResolver.Resolve(documentationReference);
			
			MemberResolveResult mrr = rr as MemberResolveResult;
			if (mrr != null)
				return mrr.Member;
			TypeResolveResult trr = rr as TypeResolveResult;
			if (trr != null)
				return trr.Type.GetDefinition();
			return null;
		}
示例#4
0
 internal override void NavigatorDone(CSharpAstResolver resolver, CancellationToken cancellationToken)
 {
     foreach (var expr in potentialMethodGroupConversions)
     {
         var conversion = resolver.GetConversion(expr, cancellationToken);
         if (conversion.IsMethodGroupConversion && conversion.Method.MemberDefinition == method)
         {
             IType         targetType = resolver.GetExpectedType(expr, cancellationToken);
             ResolveResult result     = resolver.Resolve(expr, cancellationToken);
             ReportMatch(expr, new ConversionResolveResult(targetType, result, conversion));
         }
     }
     base.NavigatorDone(resolver, cancellationToken);
 }
示例#5
0
        public static void RunTestWithoutUnresolvedFile(CSharpFile file)
        {
            CSharpAstResolver resolver = new CSharpAstResolver(file.Project.Compilation, file.SyntaxTree);
            var navigator = new ValidatingResolveAllNavigator(file.FileName);
            resolver.ApplyNavigator(navigator, CancellationToken.None);
            navigator.Validate(resolver, file.SyntaxTree);

            CSharpAstResolver originalResolver = new CSharpAstResolver(file.Project.Compilation, file.SyntaxTree, file.UnresolvedTypeSystemForFile);
            foreach (var node in file.SyntaxTree.DescendantsAndSelf) {
                var originalResult = originalResolver.Resolve(node);
                var result = resolver.Resolve(node);
                if (!RandomizedOrderResolverTest.IsEqualResolveResult(result, originalResult)) {
                    Console.WriteLine("Got different without IUnresolvedFile at " + file.FileName + ":" + node.StartLocation);
                }
            }
        }
示例#6
0
		static IEnumerable<IType> GetAllValidTypesFromObjectCreation(CSharpAstResolver resolver, ObjectCreateExpression invoke, AstNode parameter)
		{
			int index = GetArgumentIndex(invoke.Arguments, parameter);
			if (index < 0)
				yield break;

			var targetResult = resolver.Resolve(invoke.Type);
			if (targetResult is TypeResolveResult) {
				var type = ((TypeResolveResult)targetResult).Type;
				if (type.Kind == TypeKind.Delegate && index == 0) {
					yield return type;
					yield break;
				}
				foreach (var constructor in type.GetConstructors ()) {
					if (index < constructor.Parameters.Count)
						yield return constructor.Parameters [index].Type;
				}
			}
		}
示例#7
0
		static IEnumerable<IType> GetAllValidTypesFromInvocation(CSharpAstResolver resolver, InvocationExpression invoke, AstNode parameter)
		{
			int index = GetArgumentIndex(invoke.Arguments, parameter);
			if (index < 0)
				yield break;

			var targetResult = resolver.Resolve(invoke.Target) as MethodGroupResolveResult;
			if (targetResult != null) {
				foreach (var method in targetResult.Methods) {
					if (index < method.Parameters.Count) {
						if (method.Parameters [index].IsParams) {
							var arrayType = method.Parameters [index].Type as ArrayType;
							if (arrayType != null)
								yield return arrayType.ElementType;
						}

						yield return method.Parameters [index].Type;
					}
				}
				foreach (var extMethods in targetResult.GetExtensionMethods ()) {
					foreach (var extMethod in extMethods) {
						IType[] inferredTypes;
						var m = extMethod;
						if (CSharpResolver.IsEligibleExtensionMethod(targetResult.TargetType, extMethod, true, out inferredTypes)) {
							if (inferredTypes != null)
								m = extMethod.Specialize(new TypeParameterSubstitution(null, inferredTypes));
						}

						int correctedIndex = index + 1;
						if (correctedIndex < m.Parameters.Count) {
							if (m.Parameters [correctedIndex].IsParams) {
								var arrayType = m.Parameters [correctedIndex].Type as ArrayType;
								if (arrayType != null)
									yield return arrayType.ElementType;
							}
							yield return m.Parameters [correctedIndex].Type;
						}
					}
				}
			}
		}
示例#8
0
        public static ResolveResult Resolve(ICompilation compilation, CSharpParsedFile parsedFile, CompilationUnit cu, TextLocation location, out AstNode node,
                                            CancellationToken cancellationToken = default(CancellationToken))
        {
            node = cu.GetNodeAt(location);
            if (node == null)
            {
                return(null);
            }
            if (CSharpAstResolver.IsUnresolvableNode(node))
            {
                if (node is Identifier)
                {
                    node = node.Parent;
                }
                else if (node.NodeType == NodeType.Token)
                {
                    if (node.Parent is IndexerExpression || node.Parent is ConstructorInitializer)
                    {
                        // There's no other place where one could hover to see the indexer's tooltip,
                        // so we need to resolve it when hovering over the '[' or ']'.
                        // For constructor initializer, the same applies to the 'base'/'this' token.
                        node = node.Parent;
                    }
                    else
                    {
                        return(null);
                    }
                }
                else
                {
                    // don't resolve arbitrary nodes - we don't want to show tooltips for everything
                    return(null);
                }
            }
            else
            {
                // It's a resolvable node.
                // However, we usually don't want to show the tooltip everywhere
                // For example, hovering with the mouse over an empty line between two methods causes
                // node==TypeDeclaration, but we don't want to show any tooltip.

                if (!node.GetChildByRole(AstNode.Roles.Identifier).IsNull)
                {
                    // We'll suppress the tooltip for resolvable nodes if there is an identifier that
                    // could be hovered over instead:
                    return(null);
                }
            }
            if (node == null)
            {
                return(null);
            }

            if (node.Parent is ObjectCreateExpression && node.Role == ObjectCreateExpression.Roles.Type)
            {
                node = node.Parent;
            }

            InvocationExpression parentInvocation = null;

            if (node is IdentifierExpression || node is MemberReferenceExpression || node is PointerReferenceExpression)
            {
                // we also need to resolve the invocation
                parentInvocation = node.Parent as InvocationExpression;
            }

            CSharpAstResolver resolver = new CSharpAstResolver(compilation, cu, parsedFile);
            ResolveResult     rr       = resolver.Resolve(node, cancellationToken);

            if (rr is MethodGroupResolveResult && parentInvocation != null)
            {
                return(resolver.Resolve(parentInvocation));
            }
            else
            {
                return(rr);
            }
        }
示例#9
0
		public void AddChildren (AstNode node, CSharpAstResolver visitor, TreeIter iter)
		{
			if (node == null)
				return;
			iterDict [node] = iter;
			foreach (var child in node.Children) {
				ResolveResult result = null;
				try {
					if (child is Expression)
						result = visitor.Resolve (child, CancellationToken.None);
				} catch (Exception){
					result = null;
				}
				
				var childIter = store.AppendValues (iter, GetNodeTitle (child), result != null ? result.ToString () : "", child, GetIcon (child));
				AddChildren (child, visitor, childIter);
			}
		}
示例#10
0
 static IEnumerable<NodeResolved> GetResolvedNodes(AstNode tree, AstNode after, CSharpAstResolver resolver)
 {
     return tree.Descendants.Distinct().SkipWhile(n => n != after).Skip(1).OrderBy(n => n.StartLocation).Select(n => new NodeResolved
         {
             Node = n,
             ResolveResult = resolver.Resolve(n)
         });
 }
		IEnumerable<ICompletionData> MagicKeyCompletion(char completionChar, bool controlSpace)
		{
			Tuple<ResolveResult, CSharpResolver> resolveResult;
			switch (completionChar) {
			// Magic key completion
				case ':':
				case '.':
					if (IsInsideCommentStringOrDirective()) {
						return Enumerable.Empty<ICompletionData>();
					}
					return HandleMemberReferenceCompletion(GetExpressionBeforeCursor());
				case '#':
					if (!IsInPreprocessorDirective())
						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 (IsInsideCommentStringOrDirective()) {
						return null;
					}
					var invoke = GetInvocationBeforeCursor(true);
					if (invoke == null) {
						if (controlSpace)
							return DefaultControlSpaceItems(invoke);
						return null;
					}
					if (invoke.Node is TypeOfExpression) {
						return CreateTypeList();
					}
					var invocationResult = ResolveExpression(invoke);
					if (invocationResult == null) {
						return null;
					}
					var methodGroup = invocationResult.Item1 as MethodGroupResolveResult;
					if (methodGroup != null) {
						return CreateParameterCompletion(
							methodGroup,
							invocationResult.Item2,
							invoke.Node,
							invoke.Unit,
							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 ' ':
					int tokenIndex = offset;
					string token = GetPreviousToken(ref tokenIndex, false);
					if (IsInsideCommentStringOrDirective()) {
						if (IsInPreprocessorDirective())
							return HandleKeywordCompletion(tokenIndex, token);
						return null;
					}
				// 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.Node is VariableDeclarationStatement && token != "new") {
						var parent = isAsExpression.Node as VariableDeclarationStatement;
						var proposeNameList = new CompletionDataWrapper(this);
						if (parent.Variables.Count != 1)
							return DefaultControlSpaceItems(isAsExpression, controlSpace);

						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 - 1, this.offset) - 1;
							if (currentParameter < 0) {
								return null;
							}
							invoke = GetInvocationBeforeCursor(token == "(");
							if (invoke == null) {
								return null;
							}
							invocationResult = ResolveExpression(invoke);
							if (invocationResult == null) {
								return null;
							}
							methodGroup = invocationResult.Item1 as MethodGroupResolveResult;
							if (methodGroup != null) {
								return CreateParameterCompletion(
									methodGroup,
									invocationResult.Item2,
									invoke.Node,
									invoke.Unit,
									currentParameter,
									controlSpace);
							}
							return null;
						case "=":
						case "==":
							GetPreviousToken(ref tokenIndex, false);
							var expressionOrVariableDeclaration = GetExpressionAt(tokenIndex);
							if (expressionOrVariableDeclaration == null) {
								return null;
							}
					
							resolveResult = ResolveExpression(expressionOrVariableDeclaration);
					
							if (resolveResult == null) {
								return null;
							}
							if (resolveResult.Item1.Type.Kind == TypeKind.Enum) {
								var wrapper = new CompletionDataWrapper(this);
								AddContextCompletion(
									wrapper,
									resolveResult.Item2,
									expressionOrVariableDeclaration.Node,
									expressionOrVariableDeclaration.Unit);
								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);
							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) {
								token = GetPreviousToken(ref tokenIndex, false);
								token = GetPreviousToken(ref tokenIndex, false);
								if (token == "enum")
									return HandleEnumContext();
								var wrapper = new CompletionDataWrapper(this);

								AddTypesAndNamespaces(
									wrapper,
									GetState(),
									null,
									t => currentType != null && !currentType.ReflectionName.Equals(t.ReflectionName) ? t : null
								);
								return wrapper.Result;
							}
							return null;
					}
				
					var keywordCompletion = HandleKeywordCompletion(tokenIndex, token);
					if (keywordCompletion == null && controlSpace) {
						goto default;
					}
					return keywordCompletion;
			// Automatic completion
				default:
					if (IsInsideCommentStringOrDirective()) {
						return null;
					}
					if (IsInLinqContext(offset)) {
						if (!controlSpace && !(char.IsLetter(completionChar) || completionChar == '_')) {
							return null;
						}
						tokenIndex = offset;
						token = GetPreviousToken(ref tokenIndex, false);
						// token last typed
						if (!char.IsWhiteSpace(completionChar) && !linqKeywords.Contains(token)) {
							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) {
						if (identifierStart.Node is TypeParameterDeclaration) {
							return null;
						}

						if (identifierStart.Node is MemberReferenceExpression) {
							return HandleMemberReferenceCompletion(
								new ExpressionResult(
								((MemberReferenceExpression)identifierStart.Node).Target,
								identifierStart.Unit
							)
							);
						}

						if (identifierStart.Node is Identifier) {
							// May happen in variable names
							return controlSpace ? DefaultControlSpaceItems(identifierStart) : null;
						}
						if (identifierStart.Node is VariableInitializer && location <= ((VariableInitializer)identifierStart.Node).NameToken.EndLocation) {
							return controlSpace ? HandleAccessorContext() ?? DefaultControlSpaceItems(identifierStart) : null;
						}
	
						if (identifierStart.Node is CatchClause) {
							if (((CatchClause)identifierStart.Node).VariableNameToken.Contains(location)) {
								return null;
							}
							return HandleCatchClauseType(identifierStart);
						}
					}
					if (!(char.IsLetter(completionChar) || completionChar == '_') && (!controlSpace || identifierStart == null || !(identifierStart.Node.Parent 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);
					if (token == "class" || token == "interface" || token == "struct" || token == "enum" || token == "namespace") {
						// after these always follows a name
						return null;
					}
					var keywordresult = HandleKeywordCompletion(tokenIndex, token);
					if (keywordresult != null) {
						return keywordresult;
					}
					
					int prevTokenIndex = tokenIndex;
					var prevToken2 = GetPreviousToken(ref prevTokenIndex, false);
					if (prevToken2 == "delegate") {
						// after these always follows a name
						return null;
					}
					
					if (identifierStart == null && !string.IsNullOrEmpty(token) && !IsInsideCommentStringOrDirective() && (prevToken2 == ";" || prevToken2 == "{" || prevToken2 == "}")) {
						char last = token [token.Length - 1];
						if (char.IsLetterOrDigit(last) || last == '_' || token == ">") {
							return HandleKeywordCompletion(tokenIndex, token);
						}
					}

					if (identifierStart == null) {
						var accCtx = HandleAccessorContext();
						if (accCtx != null) {
							return accCtx;
						}
						return DefaultControlSpaceItems(null, controlSpace);
					}
					CSharpResolver csResolver;
					AstNode n = identifierStart.Node;
					if (n != null && n.Parent is AnonymousTypeCreateExpression) {
						AutoSelect = false;
					}

					// 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;
						}

//						var astResolver = new CSharpAstResolver(
//							GetState(),
//							identifierStart.Unit,
//							CSharpParsedFile
//						);
//
//						foreach (var type in CreateFieldAction.GetValidTypes(astResolver, (Expression)n)) {
//							if (type.Kind == TypeKind.Delegate) {
//								AddDelegateHandlers(contextList, type, false, false);
//								AutoSelect = false;
//								AutoCompleteEmptyMatch = false;
//							}
//						}
					}
					
					// Handle object/enumerable initialzer expressions: "new O () { P$"
					if (n is IdentifierExpression && n.Parent is ArrayInitializerExpression) {
						var result = HandleObjectInitializer(identifierStart.Unit, n);
						if (result != null)
							return result;
					}

					if (n != null && n.Parent is InvocationExpression) {
						var invokeParent = (InvocationExpression)n.Parent;
						var invokeResult = ResolveExpression(
							invokeParent.Target,
							identifierStart.Unit
						);
						var mgr = invokeResult != null ? invokeResult.Item1 as MethodGroupResolveResult : null;
						if (mgr != null) {
							int idx = 0;
							foreach (var arg in invokeParent.Arguments) {
								if (arg == n) {
									break;
								}
								idx++;
							}
						
							foreach (var method in mgr.Methods) {
								if (idx < method.Parameters.Count && method.Parameters [idx].Type.Kind == TypeKind.Delegate) {
									AutoSelect = false;
									AutoCompleteEmptyMatch = false;
								}
								foreach (var p in method.Parameters) {
									contextList.AddNamedParameterVariable(p);
								}
							}
							idx++;
							foreach (var list in mgr.GetExtensionMethods ()) {
								foreach (var method in list) {
									if (idx < method.Parameters.Count && method.Parameters [idx].Type.Kind == TypeKind.Delegate) {
										AutoSelect = false;
										AutoCompleteEmptyMatch = false;
									}
								}
							}
						}
					}

					if (n != null && n.Parent is ObjectCreateExpression) {
						var invokeResult = ResolveExpression(n.Parent, identifierStart.Unit);
						var mgr = invokeResult != null ? invokeResult.Item1 as ResolveResult : null;
						if (mgr != null) {
							foreach (var constructor in mgr.Type.GetConstructors ()) {
								foreach (var p in constructor.Parameters) {
									contextList.AddVariable(p);
								}
							}
						}
					}
					
					if (n is IdentifierExpression) {
						var bop = n.Parent as BinaryOperatorExpression;
						Expression evaluationExpr = null;

						if (bop != null && bop.Right == n && (bop.Operator == BinaryOperatorType.Equality || bop.Operator == BinaryOperatorType.InEquality)) {
							evaluationExpr = bop.Left;
						}
						// check for compare to enum case 
						if (evaluationExpr != null) {
							resolveResult = ResolveExpression(evaluationExpr, identifierStart.Unit);
							if (resolveResult != null && resolveResult.Item1.Type.Kind == TypeKind.Enum) {
								var wrapper = new CompletionDataWrapper(this);
								AddContextCompletion(
									wrapper,
									resolveResult.Item2,
									evaluationExpr,
									identifierStart.Unit
								);
								AddEnumMembers(wrapper, resolveResult.Item1.Type, resolveResult.Item2);
								AutoCompleteEmptyMatch = false;
								return wrapper.Result;
							}
						}
					}
				
					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(n.Parent, identifierStart.Unit);
					
						var concreteNode = identifierStart.Unit.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;
						}
						return DefaultControlSpaceItems();
					}
					if (IsAttributeContext(n)) {
						// add attribute targets
						if (currentType == null) {
							contextList.AddCustom("assembly");
							contextList.AddCustom("module");
							contextList.AddCustom("type");
						} else {
							contextList.AddCustom("param");
							contextList.AddCustom("field");
							contextList.AddCustom("property");
							contextList.AddCustom("method");
							contextList.AddCustom("event");
						}
						contextList.AddCustom("return");
					}
					if (n is MemberType) {
						resolveResult = ResolveExpression(
							((MemberType)n).Target,
							identifierStart.Unit
						);
						return CreateTypeAndNamespaceCompletionData(
							location,
							resolveResult.Item1,
							((MemberType)n).Target,
							resolveResult.Item2
						);
					}
					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 astResolver = new CSharpAstResolver(
							csResolver,
							identifierStart.Unit,
							CSharpParsedFile
						);
						astResolver.ApplyNavigator(new NodeListResolveVisitorNavigator(nodes));
						try {
							csResolver = astResolver.GetResolverStateBefore(n);
						} catch (Exception) {
							csResolver = GetState();
						}
						// add attribute properties.
						if (n.Parent is ICSharpCode.NRefactory.CSharp.Attribute) {
							var resolved = astResolver.Resolve(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.Node,
						identifierStart.Unit
					);
					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;
		}
示例#12
0
 static IEnumerable<IType> GuessFromConstructorInitializer(CSharpAstResolver resolver, AstNode expr)
 {
     var init = expr.Parent as ConstructorInitializer;
     var rr = resolver.Resolve(expr.Parent);
     int index = GetArgumentIndex(init.Arguments, expr);
     if (index >= 0) {
         foreach (var constructor in rr.Type.GetConstructors()) {
             if (index < constructor.Parameters.Count) {
                 yield return constructor.Parameters[index].Type;
             }
         }
     }
 }
		public CodeGenerationOptions ()
		{
			currentState = new Lazy<CSharpResolver> (() => {
				var parsedDocument = Document.ParsedDocument;
				if (parsedDocument == null)
					return null;
				var unit = parsedDocument.GetAst<SyntaxTree> ().Clone ();
				var file = parsedDocument.ParsedFile as CSharpUnresolvedFile;
				
				var resolvedNode = unit.GetNodeAt<BlockStatement> (Document.Editor.Caret.Location);
				if (resolvedNode == null)
					return null;
				
				var expr = new IdentifierExpression ("foo");
				resolvedNode.Add (expr);
				
				var ctx = file.GetTypeResolveContext (Document.Compilation, Document.Editor.Caret.Location);
				
				var resolver = new CSharpResolver (ctx);
				
				var astResolver = new CSharpAstResolver (resolver, unit, file);
				astResolver.ApplyNavigator (new NodeListResolveVisitorNavigator (expr), CancellationToken.None);
				astResolver.Resolve (expr);
				return astResolver.GetResolverStateBefore (expr);
			});
		}
示例#14
0
		public static ResolveResult Resolve(ICompilation compilation, CSharpParsedFile parsedFile, CompilationUnit cu, TextLocation location, out AstNode node,
		                                    CancellationToken cancellationToken = default(CancellationToken))
		{
			node = cu.GetNodeAt(location);
			if (node == null)
				return null;
			if (CSharpAstResolver.IsUnresolvableNode(node)) {
				if (node is Identifier) {
					node = node.Parent;
				} else if (node.NodeType == NodeType.Token) {
					if (node.Parent is IndexerExpression || node.Parent is ConstructorInitializer) {
						// There's no other place where one could hover to see the indexer's tooltip,
						// so we need to resolve it when hovering over the '[' or ']'.
						// For constructor initializer, the same applies to the 'base'/'this' token.
						node = node.Parent;
					} else {
						return null;
					}
				} else {
					// don't resolve arbitrary nodes - we don't want to show tooltips for everything
					return null;
				}
			} else {
				// It's a resolvable node.
				// However, we usually don't want to show the tooltip everywhere
				// For example, hovering with the mouse over an empty line between two methods causes
				// node==TypeDeclaration, but we don't want to show any tooltip.
				
				if (!node.GetChildByRole(AstNode.Roles.Identifier).IsNull) {
					// We'll suppress the tooltip for resolvable nodes if there is an identifier that
					// could be hovered over instead:
					return null;
				}
			}
			if (node == null)
				return null;
			
			if (node.Parent is ObjectCreateExpression && node.Role == ObjectCreateExpression.Roles.Type) {
				node = node.Parent;
			}
			
			InvocationExpression parentInvocation = null;
			if (node is IdentifierExpression || node is MemberReferenceExpression || node is PointerReferenceExpression) {
				// we also need to resolve the invocation
				parentInvocation = node.Parent as InvocationExpression;
			}
			
			CSharpAstResolver resolver = new CSharpAstResolver(compilation, cu, parsedFile);
			ResolveResult rr = resolver.Resolve(node, cancellationToken);
			if (rr is MethodGroupResolveResult && parentInvocation != null)
				return resolver.Resolve(parentInvocation);
			else
				return rr;
		}
		void VisitVisibleNodes(AstNode node, IResolveVisitorNavigator currentNavigator, CSharpAstResolver resolver, int start, int end)
		{
			if (!CSharpAstResolver.IsUnresolvableNode(node))
				currentNavigator.Resolved(node, resolver.Resolve(node, caretMovementTokenSource.Token));
			for (var child = node.FirstChild; child != null; child = child.NextSibling) {
				if (child.StartLocation.Line <= end && child.EndLocation.Line >= start)
					VisitVisibleNodes(child, currentNavigator, resolver, start, end);
			}
		}
示例#16
0
        public static ResolveResult Resolve(Lazy <ICompilation> compilation, CSharpUnresolvedFile unresolvedFile, SyntaxTree syntaxTree, TextLocation location, out AstNode node,
                                            CancellationToken cancellationToken = default(CancellationToken))
        {
            node = syntaxTree.GetNodeAt(location);
            if (node == null || node is ArrayInitializerExpression)
            {
                return(null);
            }
            if (node.Parent is UsingAliasDeclaration && node.Role == UsingAliasDeclaration.AliasRole)
            {
                var r = new CSharpAstResolver(compilation.Value, syntaxTree, unresolvedFile);
                return(r.Resolve(((UsingAliasDeclaration)node.Parent).Import, cancellationToken));
            }
            if (CSharpAstResolver.IsUnresolvableNode(node))
            {
                if (node is Identifier)
                {
                    node = node.Parent;
                }
                else if (node.NodeType == NodeType.Token)
                {
                    if (node.Parent is IndexerExpression || node.Parent is ConstructorInitializer || node.Role == IndexerDeclaration.ThisKeywordRole)
                    {
                        // There's no other place where one could hover to see the indexer's tooltip,
                        // so we need to resolve it when hovering over the '[' or ']'.
                        // For constructor initializer, the same applies to the 'base'/'this' token.
                        node = node.Parent;
                    }
                    else if (node.Parent is BinaryOperatorExpression || node.Parent is UnaryOperatorExpression)
                    {
                        // Resolve user-defined operator
                        node = node.Parent;
                    }
                    else
                    {
                        return(null);
                    }
                }
                else
                {
                    // don't resolve arbitrary nodes - we don't want to show tooltips for everything
                    return(null);
                }
            }
            else
            {
                // It's a resolvable node.
                // However, we usually don't want to show the tooltip everywhere
                // For example, hovering with the mouse over an empty line between two methods causes
                // node==TypeDeclaration, but we don't want to show any tooltip.

                if (!node.GetChildByRole(Roles.Identifier).IsNull)
                {
                    // We'll suppress the tooltip for resolvable nodes if there is an identifier that
                    // could be hovered over instead:
                    return(null);
                }
            }

            if (node == null)
            {
                return(null);
            }
            if (node.Parent is ObjectCreateExpression && node.Role == Roles.Type)
            {
                node = node.Parent;
            }

            InvocationExpression parentInvocation = null;

            if ((node is IdentifierExpression || node is MemberReferenceExpression || node is PointerReferenceExpression) && node.Role != Roles.Argument)
            {
                // we also need to resolve the invocation
                parentInvocation = node.Parent as InvocationExpression;
            }

            // TODO: I think we should provide an overload so that an existing CSharpAstResolver can be reused
            CSharpAstResolver        resolver = new CSharpAstResolver(compilation.Value, syntaxTree, unresolvedFile);
            ResolveResult            rr       = resolver.Resolve(node, cancellationToken);
            MethodGroupResolveResult mgrr     = rr as MethodGroupResolveResult;

            if (mgrr != null)
            {
                // For method groups, resolve the parent invocation instead.
                if (parentInvocation != null)
                {
                    return(resolver.Resolve(parentInvocation));
                }
                if (node is Expression)
                {
                    // If it's not an invocation, try if it's a conversion to a delegate type:
                    Conversion c = resolver.GetConversion((Expression)node, cancellationToken);
                    if (c.IsMethodGroupConversion)
                    {
                        return(new MemberResolveResult(mgrr.TargetResult, c.Method));
                    }
                }
            }
            return(rr);
        }
示例#17
0
        private void ParseTargetExpression(Expression expression)
        {
            if (_file != null)
            {
                var resolver = new CSharpAstResolver(_file.Project.Compilation, _file.SyntaxTree, _file.UnresolvedTypeSystemForFile);
                var resolveResult = resolver.Resolve(expression);

                if (resolveResult is CSharpInvocationResolveResult)
                {
                    var member = ((CSharpInvocationResolveResult)resolveResult).Member;
                    var method = member as IMethod;

                    if (method != null)
                    {
                        var callerType = _type;
                        var callerMethod = _method;

                        SDType calledType = null;
                        var sdType = _repository.GetTypeByIdentifier(member.DeclaringType.GetIdentifier());
                        if (sdType == null)
                        {
                            var sdNamespace = _repository.GetNamespaceByIdentifier(member.DeclaringType.Namespace);
                            sdNamespace = sdNamespace == null ? new SDNamespace(member.DeclaringType.Namespace) { IsProjectStranger = true } : sdNamespace;
                            calledType = new SDType(member.DeclaringType.GetIdentifier(), member.DeclaringType.Name, sdNamespace) { IsProjectStranger = true };
                        }
                        else
                        {
                            calledType = sdType;
                        }

                        SDMethod calledMethod = null;
                        if (calledType.IsProjectStranger)
                        {
                            calledMethod = new SDMethod(method.GetIdentifier(), method.Name);
                        }
                        else
                        {
                            SDMethod sdMethod = sdType.Methods.Concat(sdType.Constructors).SingleOrDefault(m => m.Identifier == method.GetIdentifier());
                            if(sdMethod != null)
                            {
                                calledMethod = sdMethod;
                            }
                        }

                        // Only add method, if it is project stranger, public or private (if not only public members option on)
                        if (calledMethod != null)
                        {
                            var token = new SDTargetNode
                                            {
                                                    CalledType = calledType,
                                                    CallerType = callerType,
                                                    CalledMethod = calledMethod,
                                                    CallerMethod = callerMethod
                                            };

                            _tokenList.Add(token);
                        }
                    }
                }
            }
        }
示例#18
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 CSharpAstResolver(new CSharpResolver (ctx), unit, CSharpParsedFile);
			
			var result = csResolver.Resolve (resolveNode);
			var state = csResolver.GetResolverStateBefore (resolveNode);
			return Tuple.Create (result, state);
		}
示例#19
0
			public virtual void Validate(CSharpAstResolver resolver, CompilationUnit cu)
			{
				foreach (AstNode node in cu.DescendantsAndSelf.Except(resolvedNodes.Keys)) {
					if (!CSharpAstResolver.IsUnresolvableNode(node)) {
						Console.WriteLine("Forgot to resolve " + node);
					}
				}
				foreach (var pair in resolvedNodes) {
					if (resolver.Resolve(pair.Key) != pair.Value)
						throw new InvalidOperationException("Inconsistent result");
				}
			}
示例#20
0
		void ResolveButtonClick(object sender, EventArgs e)
		{
			IProjectContent project = new CSharpProjectContent();
			var unresolvedFile = syntaxTree.ToTypeSystem();
			project = project.AddOrUpdateFiles(unresolvedFile);
			project = project.AddAssemblyReferences(builtInLibs.Value);
			
			ICompilation compilation = project.CreateCompilation();
			
			ResolveResult result;
			if (csharpTreeView.SelectedNode != null) {
				var selectedNode = (AstNode)csharpTreeView.SelectedNode.Tag;
				CSharpAstResolver resolver = new CSharpAstResolver(compilation, syntaxTree, unresolvedFile);
				result = resolver.Resolve(selectedNode);
				// CSharpAstResolver.Resolve() never returns null
			} else {
				TextLocation location = GetTextLocation(csharpCodeTextBox, csharpCodeTextBox.SelectionStart);
				result = ResolveAtLocation.Resolve(compilation, unresolvedFile, syntaxTree, location);
				if (result == null) {
					MessageBox.Show("Could not find a resolvable node at the caret location.");
					return;
				}
			}
			using (var dlg = new SemanticTreeDialog(result))
				dlg.ShowDialog();
		}
示例#21
0
		void FindReferencesButtonClick(object sender, EventArgs e)
		{
			if (csharpTreeView.SelectedNode == null)
				return;
			
			IProjectContent project = new CSharpProjectContent();
			var unresolvedFile = syntaxTree.ToTypeSystem();
			project = project.AddOrUpdateFiles(unresolvedFile);
			project = project.AddAssemblyReferences(builtInLibs.Value);
			
			ICompilation compilation = project.CreateCompilation();
			CSharpAstResolver resolver = new CSharpAstResolver(compilation, syntaxTree, unresolvedFile);
			
			AstNode node = (AstNode)csharpTreeView.SelectedNode.Tag;
			IEntity entity;
			MemberResolveResult mrr = resolver.Resolve(node) as MemberResolveResult;
			TypeResolveResult trr = resolver.Resolve(node) as TypeResolveResult;
			if (mrr != null) {
				entity = mrr.Member;
			} else if (trr != null) {
				entity = trr.Type.GetDefinition();
			} else {
				return;
			}
			
			FindReferences fr = new FindReferences();
			int referenceCount = 0;
			FoundReferenceCallback callback = delegate(AstNode matchNode, ResolveResult result) {
				Debug.WriteLine(matchNode.StartLocation + " - " + matchNode + " - " + result);
				referenceCount++;
			};
			
			var searchScopes = fr.GetSearchScopes(entity);
			Debug.WriteLine("Find references to " + entity.ReflectionName);
			fr.FindReferencesInFile(searchScopes, unresolvedFile, syntaxTree, compilation, callback, CancellationToken.None);
			
			MessageBox.Show("Found " + referenceCount + " references to " + entity.FullName);
		}
		protected Tuple<ResolveResult, CSharpResolver> ResolveExpression(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;
			}
			try {
				var ctx = CSharpParsedFile.GetResolver(Compilation, location);
				var root = expr.AncestorsAndSelf.FirstOrDefault(n => n is EntityDeclaration || n is CompilationUnit);
				if (root == null) {
					return null;
				}
				var csResolver = new CSharpAstResolver (ctx, root, CSharpParsedFile);
				var result = csResolver.Resolve(resolveNode);
				var state = csResolver.GetResolverStateBefore(resolveNode);
				return Tuple.Create(result, state);
			} catch (Exception e) {
				Console.WriteLine(e);
				return null;
			}
		}
示例#23
0
		public ResolveResult ResolveSnippet(ParseInformation parseInfo, TextLocation location, string codeSnippet, ICompilation compilation, CancellationToken cancellationToken)
		{
			var csParseInfo = parseInfo as CSharpFullParseInformation;
			if (csParseInfo == null)
				throw new ArgumentException("Parse info does not have SyntaxTree");
			CSharpAstResolver contextResolver = new CSharpAstResolver(compilation, csParseInfo.SyntaxTree, csParseInfo.UnresolvedFile);
			var node = csParseInfo.SyntaxTree.GetNodeAt(location);
			CSharpResolver context;
			if (node != null)
				context = contextResolver.GetResolverStateAfter(node, cancellationToken);
			else
				context = new CSharpResolver(compilation);
			CSharpParser parser = new CSharpParser();
			var expr = parser.ParseExpression(codeSnippet);
			if (parser.HasErrors)
				return new ErrorResolveResult(SpecialType.UnknownType, PrintErrorsAsString(parser.Errors), TextLocation.Empty);
			CSharpAstResolver snippetResolver = new CSharpAstResolver(context, expr);
			return snippetResolver.Resolve(expr, cancellationToken);
		}
示例#24
0
			public virtual void Validate(CSharpAstResolver resolver, SyntaxTree syntaxTree)
			{
				foreach (AstNode node in syntaxTree.DescendantsAndSelf.Except(resolvedNodes.Keys)) {
					if (!CSharpAstResolver.IsUnresolvableNode(node)) {
						if (!node.Ancestors.Any(a => a is PreProcessorDirective)) {
							Console.WriteLine("Forgot to resolve " + node);
						}
					}
				}
				foreach (var pair in resolvedNodes) {
					if (resolver.Resolve(pair.Key) != pair.Value)
						throw new InvalidOperationException("Inconsistent result");
				}
			}
示例#25
0
 internal override void NavigatorDone(CSharpAstResolver resolver, CancellationToken cancellationToken)
 {
     foreach (var expr in potentialMethodGroupConversions) {
         var conversion = resolver.GetConversion(expr, cancellationToken);
         if (conversion.IsMethodGroupConversion && findReferences.IsMemberMatch(method, conversion.Method, conversion.IsVirtualMethodLookup)) {
             IType targetType = resolver.GetExpectedType(expr, cancellationToken);
             ResolveResult result = resolver.Resolve(expr, cancellationToken);
             ReportMatch(expr, new ConversionResolveResult(targetType, result, conversion));
         }
     }
     base.NavigatorDone(resolver, cancellationToken);
 }
		static IEnumerable<IType> GetAllValidTypesFromInvokation(CSharpAstResolver resolver, InvocationExpression invoke, AstNode parameter)
		{
			int index = GetArgumentIndex(invoke.Arguments, parameter);
			if (index < 0)
				yield break;
					
			var targetResult = resolver.Resolve(invoke.Target);
			if (targetResult is MethodGroupResolveResult) {
				foreach (var method in ((MethodGroupResolveResult)targetResult).Methods) {
					if (index < method.Parameters.Count) {
						yield return method.Parameters [index].Type;
					}
				}
			}
		}
示例#27
0
        public static IEnumerable<IType> GetValidTypes(CSharpAstResolver resolver, AstNode expr)
        {
            if (expr.Role == Roles.Condition) {
                return new [] { resolver.Compilation.FindType (KnownTypeCode.Boolean) };
            }

            var mref = expr as MemberReferenceExpression;
            if (mref != null) {
                // case: guess enum when trying to access not existent enum member
                var rr = resolver.Resolve(mref.Target);
                if (!rr.IsError && rr.Type.Kind == TypeKind.Enum)
                    return new [] { rr.Type };
            }

            if (expr.Parent is ParenthesizedExpression || expr.Parent is NamedArgumentExpression) {
                return GetValidTypes(resolver, expr.Parent);
            }
            if (expr.Parent is DirectionExpression) {
                var parent = expr.Parent.Parent;
                if (parent is InvocationExpression) {
                    var invoke = (InvocationExpression)parent;
                    return GetAllValidTypesFromInvocation(resolver, invoke, expr.Parent);
                }
            }

            if (expr.Parent is ArrayInitializerExpression) {
                if (expr is NamedExpression)
                    return new [] { resolver.Resolve(((NamedExpression)expr).Expression).Type };

                var aex = expr.Parent as ArrayInitializerExpression;
                if (aex.IsSingleElement)
                    aex = aex.Parent as ArrayInitializerExpression;
                var type = GetElementType(resolver, resolver.Resolve(aex.Parent).Type);
                if (type.Kind != TypeKind.Unknown)
                    return new [] { type };
            }

            if (expr.Parent is ObjectCreateExpression) {
                var invoke = (ObjectCreateExpression)expr.Parent;
                return GetAllValidTypesFromObjectCreation(resolver, invoke, expr);
            }

            if (expr.Parent is ArrayCreateExpression) {
                var ace = (ArrayCreateExpression)expr.Parent;
                if (!ace.Type.IsNull) {
                    return new [] { resolver.Resolve(ace.Type).Type };
                }
            }

            if (expr.Parent is InvocationExpression) {
                var parent = expr.Parent;
                if (parent is InvocationExpression) {
                    var invoke = (InvocationExpression)parent;
                    return GetAllValidTypesFromInvocation(resolver, invoke, expr);
                }
            }

            if (expr.Parent is VariableInitializer) {
                var initializer = (VariableInitializer)expr.Parent;
                var field = initializer.GetParent<FieldDeclaration>();
                if (field != null) {
                    var rr = resolver.Resolve(field.ReturnType);
                    if (!rr.IsError)
                        return new [] { rr.Type };
                }
                var varStmt = initializer.GetParent<VariableDeclarationStatement>();
                if (varStmt != null) {
                    var rr = resolver.Resolve(varStmt.Type);
                    if (!rr.IsError)
                        return new [] { rr.Type };
                }
                return new [] { resolver.Resolve(initializer).Type };
            }

            if (expr.Parent is CastExpression) {
                var cast = (CastExpression)expr.Parent;
                return new [] { resolver.Resolve(cast.Type).Type };
            }

            if (expr.Parent is AsExpression) {
                var cast = (AsExpression)expr.Parent;
                return new [] { resolver.Resolve(cast.Type).Type };
            }

            if (expr.Parent is AssignmentExpression) {
                var assign = (AssignmentExpression)expr.Parent;
                var other = assign.Left == expr ? assign.Right : assign.Left;
                return new [] { resolver.Resolve(other).Type };
            }

            if (expr.Parent is BinaryOperatorExpression) {
                var assign = (BinaryOperatorExpression)expr.Parent;
                var other = assign.Left == expr ? assign.Right : assign.Left;
                return new [] { resolver.Resolve(other).Type };
            }

            if (expr.Parent is ReturnStatement) {
                var parent = expr.Ancestors.FirstOrDefault(n => n is EntityDeclaration || n is AnonymousMethodExpression|| n is LambdaExpression);
                if (parent != null) {
                    var rr = resolver.Resolve(parent);
                    if (!rr.IsError)
                        return new [] { rr.Type };
                }
                var e = parent as EntityDeclaration;
                if (e != null) {
                    var rt = resolver.Resolve(e.ReturnType);
                    if (!rt.IsError)
                        return new [] { rt.Type };
                }
            }

            if (expr.Parent is YieldReturnStatement) {
                var state = resolver.GetResolverStateBefore(expr);
                if (state != null && (state.CurrentMember.ReturnType is ParameterizedType)) {
                    var pt = (ParameterizedType)state.CurrentMember.ReturnType;
                    if (pt.FullName == "System.Collections.Generic.IEnumerable") {
                        return new [] { pt.TypeArguments.First() };
                    }
                }
            }

            if (expr.Parent is UnaryOperatorExpression) {
                var uop = (UnaryOperatorExpression)expr.Parent;
                switch (uop.Operator) {
                    case UnaryOperatorType.Not:
                        return new [] { resolver.Compilation.FindType(KnownTypeCode.Boolean) };
                        case UnaryOperatorType.Minus:
                        case UnaryOperatorType.Plus:
                        case UnaryOperatorType.Increment:
                        case UnaryOperatorType.Decrement:
                        case UnaryOperatorType.PostIncrement:
                        case UnaryOperatorType.PostDecrement:
                        return new [] { resolver.Compilation.FindType(KnownTypeCode.Int32) };
                }
            }

            if (expr.Parent is ConstructorInitializer)
                return GuessFromConstructorInitializer(resolver, expr);

            if (expr.Parent is NamedExpression) {
                var rr = resolver.Resolve(expr.Parent);
                if (!rr.IsError) {
                    return new [] { rr.Type };
                }
            }

            return Enumerable.Empty<IType>();
        }
		internal static IEnumerable<IType> GetValidTypes(CSharpAstResolver resolver, Expression expr)
		{
			if (expr.Parent is DirectionExpression) {
				var parent = expr.Parent.Parent;
				if (parent is InvocationExpression) {
					var invoke = (InvocationExpression)parent;
					return GetAllValidTypesFromInvokation(resolver, invoke, expr.Parent);
				}
			}

			if (expr.Parent is ArrayInitializerExpression) {
				if (expr is NamedExpression)
					return new [] { resolver.Resolve(((NamedExpression)expr).Expression).Type };

				var aex = expr.Parent as ArrayInitializerExpression;
				if (aex.IsSingleElement)
					aex = aex.Parent as ArrayInitializerExpression;
				var type = GetElementType(resolver, resolver.Resolve(aex.Parent).Type);
				if (type.Kind != TypeKind.Unknown)
					return new [] { type };
			}

			if (expr.Parent is ObjectCreateExpression) {
				var invoke = (ObjectCreateExpression)expr.Parent;
				return GetAllValidTypesFromObjectCreation(resolver, invoke, expr);
			}

			if (expr.Parent is ArrayCreateExpression) {
				var ace = (ArrayCreateExpression)expr.Parent;
				if (!ace.Type.IsNull) {
					return new [] { resolver.Resolve(ace.Type).Type };
				}
			}

			if (expr.Parent is InvocationExpression) {
				var parent = expr.Parent;
				if (parent is InvocationExpression) {
					var invoke = (InvocationExpression)parent;
					return GetAllValidTypesFromInvokation(resolver, invoke, expr);
				}
			}
			
			if (expr.Parent is VariableInitializer) {
				var initializer = (VariableInitializer)expr.Parent;
				var field = initializer.GetParent<FieldDeclaration>();
				if (field != null)
					return new [] { resolver.Resolve(field.ReturnType).Type };
				return new [] { resolver.Resolve(initializer).Type };
			}
			
			if (expr.Parent is CastExpression) {
				var cast = (CastExpression)expr.Parent;
				return new [] { resolver.Resolve(cast.Type).Type };
			}
			
			if (expr.Parent is AsExpression) {
				var cast = (AsExpression)expr.Parent;
				return new [] { resolver.Resolve(cast.Type).Type };
			}

			if (expr.Parent is AssignmentExpression) {
				var assign = (AssignmentExpression)expr.Parent;
				var other = assign.Left == expr ? assign.Right : assign.Left;
				return new [] { resolver.Resolve(other).Type };
			}

			if (expr.Parent is BinaryOperatorExpression) {
				var assign = (BinaryOperatorExpression)expr.Parent;
				var other = assign.Left == expr ? assign.Right : assign.Left;
				return new [] { resolver.Resolve(other).Type };
			}
			
			if (expr.Parent is ReturnStatement) {
				var state = resolver.GetResolverStateBefore(expr.Parent);
				if (state != null  && state.CurrentMember != null)
					return new [] { state.CurrentMember.ReturnType };
			}

			if (expr.Parent is YieldReturnStatement) {
				var state = resolver.GetResolverStateBefore(expr);
				if (state != null && (state.CurrentMember.ReturnType is ParameterizedType)) {
					var pt = (ParameterizedType)state.CurrentMember.ReturnType;
					if (pt.FullName == "System.Collections.Generic.IEnumerable") {
						return new [] { pt.TypeArguments.First() };
					}
				}
			}

			if (expr.Parent is UnaryOperatorExpression) {
				var uop = (UnaryOperatorExpression)expr.Parent;
				switch (uop.Operator) {
					case UnaryOperatorType.Not:
						return new [] { resolver.Compilation.FindType(KnownTypeCode.Boolean) };
					case UnaryOperatorType.Minus:
					case UnaryOperatorType.Plus:
					case UnaryOperatorType.Increment:
					case UnaryOperatorType.Decrement:
					case UnaryOperatorType.PostIncrement:
					case UnaryOperatorType.PostDecrement:
						return new [] { resolver.Compilation.FindType(KnownTypeCode.Int32) };
				}
			}
			return Enumerable.Empty<IType>();
		}
示例#29
0
        public static void Main(string[] args)
        {
            if (args.Length == 0) {
                Console.WriteLine("Please specify the path to a .sln file on the command line");

                Console.Write("Press any key to continue . . . ");
                Console.ReadKey(true);
                return;
            }

            Solution solution = new Solution(args[0]);
            foreach (var file in solution.AllFiles) {
                var astResolver = new CSharpAstResolver(file.Project.Compilation, file.SyntaxTree, file.UnresolvedTypeSystemForFile);
                foreach (var invocation in file.SyntaxTree.Descendants.OfType<InvocationExpression>()) {
                    // Retrieve semantics for the invocation
                    var rr = astResolver.Resolve(invocation) as InvocationResolveResult;
                    if (rr == null) {
                        // Not an invocation resolve result - e.g. could be a UnknownMemberResolveResult instead
                        continue;
                    }
                    if (rr.Member.FullName != "System.String.IndexOf") {
                        // Invocation isn't a string.IndexOf call
                        continue;
                    }
                    if (rr.Member.Parameters.First().Type.FullName != "System.String") {
                        // Ignore the overload that accepts a char, as that doesn't take a StringComparison.
                        // (looking for a char always performs the expected ordinal comparison)
                        continue;
                    }
                    if (rr.Member.Parameters.Last().Type.FullName == "System.StringComparison") {
                        // Already using the overload that specifies a StringComparison
                        continue;
                    }
                    Console.WriteLine(invocation.GetRegion() + ": " + invocation.GetText());
                    file.IndexOfInvocations.Add(invocation);
                }
            }
            Console.WriteLine("Found {0} places to refactor in {1} files.",
                              solution.AllFiles.Sum(f => f.IndexOfInvocations.Count),
                              solution.AllFiles.Count(f => f.IndexOfInvocations.Count > 0));
            Console.Write("Apply refactorings? ");
            string answer = Console.ReadLine();
            if ("yes".Equals(answer, StringComparison.OrdinalIgnoreCase) || "y".Equals(answer, StringComparison.OrdinalIgnoreCase)) {
                foreach (var file in solution.AllFiles) {
                    if (file.IndexOfInvocations.Count == 0)
                        continue;
                    // DocumentScript expects the the AST to stay unmodified (so that it fits
                    // to the document state at the time of the DocumentScript constructor call),
                    // so we call Freeze() to prevent accidental modifications (e.g. forgetting a Clone() call).
                    file.SyntaxTree.Freeze();
                    // AST resolver used to find context for System.StringComparison generation
                    var compilation = file.Project.Compilation;
                    var astResolver = new CSharpAstResolver(compilation, file.SyntaxTree, file.UnresolvedTypeSystemForFile);

                    // Create a document containing the file content:
                    var document = new StringBuilderDocument(file.OriginalText);
                    var formattingOptions = FormattingOptionsFactory.CreateAllman();
                    var options = new TextEditorOptions();
                    using (var script = new DocumentScript(document, formattingOptions, options)) {
                        foreach (InvocationExpression expr in file.IndexOfInvocations) {
                            // Generate a reference to System.StringComparison in this context:
                            var astBuilder = new TypeSystemAstBuilder(astResolver.GetResolverStateBefore(expr));
                            IType stringComparison = compilation.FindType(typeof(StringComparison));
                            AstType stringComparisonAst = astBuilder.ConvertType(stringComparison);

                            // Alternative 1: clone a portion of the AST and modify it
                            var copy = (InvocationExpression)expr.Clone();
                            copy.Arguments.Add(stringComparisonAst.Member("Ordinal"));
                            script.Replace(expr, copy);

            //							// Alternative 2: perform direct text insertion
            //							int offset = script.GetCurrentOffset(expr.RParToken.StartLocation);
            //							script.InsertText(offset, ", " + stringComparisonAst.GetText() +  ".Ordinal");
                        }
                    }
                    File.WriteAllText(Path.ChangeExtension(file.FileName, ".output.cs"), document.Text);
                }
            }
        }
示例#30
0
        static IEnumerable<NodeResolved> GetAllUnresolvedNodes(AstNode tree, CSharpAstResolver resolver)
        {
            var nodes = tree.Descendants.OrderBy(n => n.StartLocation).Select(n => new NodeResolved
                {
                    Node = n,
                    ResolveResult = resolver.Resolve(n)
                });

            return nodes.Where(n => n.ResolveResult is UnknownIdentifierResolveResult ||
                n.ResolveResult is UnknownMemberResolveResult);
        }