public ToolTipData (ICSharpCode.NRefactory.PlayScript.SyntaxTree unit, ICSharpCode.NRefactory.Semantics.ResolveResult result, ICSharpCode.NRefactory.PlayScript.AstNode node, CSharpAstResolver file)
			{
				this.Unit = unit;
				this.Result = result;
				this.Node = node;
				this.Resolver = file;
			}
		public override IEntity ResolveCref(string cref)
		{
			if (cref.Length > 2 && cref[1] == ':') {
				// resolve ID string
				return base.ResolveCref(cref);
			}
			var documentationReference = new PlayScriptParser().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;
		}
		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);
			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;
		}
		public override TooltipItem GetItem (Mono.TextEditor.TextEditor editor, int offset)
		{
			var doc = IdeApp.Workbench.ActiveDocument;
			if (doc == null || doc.ParsedDocument == null)
				return null;
			var unit = doc.ParsedDocument.GetAst<SyntaxTree> ();
			if (unit == null)
				return null;

			var file = doc.ParsedDocument.ParsedFile as CSharpUnresolvedFile;
			if (file == null)
				return null;
			
			ResolveResult result;
			AstNode node;
			var loc = editor.OffsetToLocation (offset);
			if (!doc.TryResolveAt (loc, out result, out node)) {
				if (node is CSharpTokenNode) {
					int startOffset2 = editor.LocationToOffset (node.StartLocation);
					int endOffset2 = editor.LocationToOffset (node.EndLocation);

					return new TooltipItem (new ToolTipData (unit, result, node, null), startOffset2, endOffset2 - startOffset2);
				}
				return null;
			}
			if (node == lastNode)
				return lastResult;
			var resolver = new CSharpAstResolver (doc.Compilation, unit, file);
			resolver.ApplyNavigator (new NodeListResolveVisitorNavigator (node), CancellationToken.None);

			var hoverNode = node.GetNodeAt (loc) ?? node;

			int startOffset = editor.LocationToOffset (hoverNode.StartLocation);
			int endOffset = editor.LocationToOffset (hoverNode.EndLocation);
			return lastResult = new TooltipItem (new ToolTipData (unit, result, node, resolver), startOffset, endOffset - startOffset);
		}
			public ErrorVisitor (CSharpAstResolver resolver, CancellationToken cancellationToken = default(CancellationToken))
			{
				this.resolver = resolver;
				this.cancellationToken = cancellationToken;
			}
			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);
			}
		/// <summary>
		/// Finds all references in the given file.
		/// </summary>
		/// <param name="searchScopes">The search scopes for which to look.</param>
		/// <param name="unresolvedFile">The type system representation of the file being searched.</param>
		/// <param name="syntaxTree">The syntax tree of the file being searched.</param>
		/// <param name="compilation">The compilation for the project that contains the file.</param>
		/// <param name="callback">Callback used to report the references that were found.</param>
		/// <param name="cancellationToken">CancellationToken that may be used to cancel the operation.</param>
		public void FindReferencesInFile(IList<IFindReferenceSearchScope> searchScopes, CSharpUnresolvedFile unresolvedFile, SyntaxTree syntaxTree,
		                                 ICompilation compilation, FoundReferenceCallback callback, CancellationToken cancellationToken)
		{
			if (searchScopes == null)
				throw new ArgumentNullException("searchScopes");
			if (syntaxTree == null)
				throw new ArgumentNullException("syntaxTree");
			if (compilation == null)
				throw new ArgumentNullException("compilation");
			if (callback == null)
				throw new ArgumentNullException("callback");
			
			if (searchScopes.Count == 0)
				return;
			var navigators = new IResolveVisitorNavigator[searchScopes.Count];
			for (int i = 0; i < navigators.Length; i++) {
				navigators[i] = searchScopes[i].GetNavigator(compilation, callback);
			}
			IResolveVisitorNavigator combinedNavigator;
			if (searchScopes.Count == 1) {
				combinedNavigator = navigators[0];
			} else {
				combinedNavigator = new CompositeResolveVisitorNavigator(navigators);
			}
			
			cancellationToken.ThrowIfCancellationRequested();
			combinedNavigator = new DetectSkippableNodesNavigator(combinedNavigator, syntaxTree);
			cancellationToken.ThrowIfCancellationRequested();
			CSharpAstResolver resolver = new CSharpAstResolver(compilation, syntaxTree, unresolvedFile);
			resolver.ApplyNavigator(combinedNavigator, cancellationToken);
			foreach (var n in navigators) {
				var frn = n as FindReferenceNavigator;
				if (frn != null)
					frn.NavigatorDone(resolver, cancellationToken);
			}
		}
			bool TypeChangeResolvesCorrectly(ParameterDeclaration parameter, AstNode rootNode, IType type)
			{
				MethodResolveCount++;
				var resolver = ctx.GetResolverStateBefore(rootNode);
				resolver = resolver.AddVariable(new DefaultParameter(type, parameter.Name));
				var astResolver = new CSharpAstResolver(resolver, rootNode, ctx.UnresolvedFile);
				var validator = new TypeChangeValidationNavigator();
				astResolver.ApplyNavigator(validator, ctx.CancellationToken);
				return !validator.FoundErrors;
			}
		internal static IEnumerable<IType> GetValidTypes(CSharpAstResolver resolver, AstNode 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>();
		}
		static IType GetElementType(CSharpAstResolver resolver, IType type)
		{
			// TODO: A better get element type method.
			if (type.Kind == TypeKind.Array || type.Kind == TypeKind.Dynamic) {
				if (type.Kind == TypeKind.Array)
					return ((ArrayType)type).ElementType;
				return resolver.Compilation.FindType(KnownTypeCode.Object);
			}


			foreach (var method in type.GetMethods (m => m.Name == "GetEnumerator")) {
				IType returnType = null;
				foreach (var prop in method.ReturnType.GetProperties(p => p.Name == "Current")) {
					if (returnType != null && prop.ReturnType.IsKnownType (KnownTypeCode.Object))
						continue;
					returnType = prop.ReturnType;
				}
				if (returnType != null)
					return returnType;
			}

			return resolver.Compilation.FindType(KnownTypeCode.Object);
		}
		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;
				}
			}
		}
		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) as MethodGroupResolveResult;
			if (targetResult != null) {
				foreach (var method in targetResult.Methods) {
					if (index < method.Parameters.Count) {
						yield return method.Parameters [index].Type;
					}
				}
				foreach (var extMethods in targetResult.GetExtensionMethods ()) {
					foreach (var extMethod in extMethods) {
						if (index + 1 < extMethod.Parameters.Count) {
							yield return extMethod.Parameters [index + 1].Type;
						}
					}
				}
			}
		}
Exemplo n.º 13
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);
            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);
        }
 public BaseRefactoringContext(ICSharpCode.NRefactory.PlayScript.Resolver.CSharpAstResolver resolver, System.Threading.CancellationToken cancellationToken)
 {
     this.resolver          = resolver;
     this.cancellationToken = cancellationToken;
     this.referenceFinder   = new LocalReferenceFinder(resolver);
 }
		public ResolveResult GetLanguageItem (MonoDevelop.Ide.Gui.Document doc, int offset, string expression)
		{
			if (offset < 0) {
				return null;
			}

			var parsedDocument = doc.ParsedDocument;
			if (parsedDocument == null)
				return null;
			var data = doc.Editor;
			var loc = data.OffsetToLocation (offset);

			var unit = parsedDocument.GetAst<SyntaxTree> ();
			var parsedFile = parsedDocument.ParsedFile as CSharpUnresolvedFile;
			
			if (unit == null || parsedFile == null) {
				return null;
			}
			var node = unit.GetNodeAt (loc);
			if (node == null) {
				return null;
			}
			
			var resolver = new CSharpAstResolver (doc.Compilation, unit, parsedFile);
			resolver.ApplyNavigator (new NodeListResolveVisitorNavigator (node), CancellationToken.None);
			var state = resolver.GetResolverStateBefore (node, CancellationToken.None);
			return state.LookupSimpleNameOrTypeName (expression, new List<IType> (), NameLookupMode.Expression);
		}
			internal virtual void NavigatorDone(CSharpAstResolver resolver, CancellationToken cancellationToken)
			{
			}
		public BaseRefactoringContext (ICSharpCode.NRefactory.PlayScript.Resolver.CSharpAstResolver resolver, System.Threading.CancellationToken cancellationToken)
		{
			this.resolver = resolver;
			this.cancellationToken = cancellationToken;
			this.referenceFinder = new LocalReferenceFinder(resolver);
		}
		public static ReachabilityAnalysis Create(Statement statement, CSharpAstResolver resolver = null, CancellationToken cancellationToken = default(CancellationToken))
		{
			var cfgBuilder = new ControlFlowGraphBuilder();
			var cfg = cfgBuilder.BuildControlFlowGraph(statement, resolver, cancellationToken);
			return Create(cfg, cancellationToken);
		}