protected ResolveResult Resolve(string code) { CompilationUnit cu = new CSharpParser().Parse(new StringReader(code.Replace("$", ""))); TextLocation[] dollars = FindDollarSigns(code).ToArray(); Assert.AreEqual(2, dollars.Length, "Expected 2 dollar signs marking start+end of desired node"); SetUp(); CSharpParsedFile parsedFile = new CSharpParsedFile("test.cs", resolver.CurrentUsingScope); TypeSystemConvertVisitor convertVisitor = new TypeSystemConvertVisitor(parsedFile, resolver.CurrentUsingScope, null); cu.AcceptVisitor(convertVisitor, null); project.UpdateProjectContent(null, convertVisitor.ParsedFile); FindNodeVisitor fnv = new FindNodeVisitor(dollars[0], dollars[1]); cu.AcceptVisitor(fnv, null); Assert.IsNotNull(fnv.ResultNode, "Did not find DOM node at the specified location"); Debug.WriteLine(new string('=', 70)); Debug.WriteLine("Starting new resolver for " + fnv.ResultNode); var navigator = new NodeListResolveVisitorNavigator(new[] { fnv.ResultNode }); ResolveResult rr; using (var context = this.context.Synchronize()) { ResolveVisitor rv = new ResolveVisitor(new CSharpResolver(context), convertVisitor.ParsedFile, navigator); rv.Scan(cu); rr = rv.GetResolveResult(fnv.ResultNode); } Assert.IsNotNull(rr, "ResolveResult is null - did something go wrong while navigating to the target node?"); Debug.WriteLine("ResolveResult is " + rr); return(rr); }
void InitResolver(AstNode firstNodeToResolve) { if (resolveVisitor == null) { resolveVisitor = new ResolveVisitor(initialResolverState, parsedFile, new NodeListResolveVisitorNavigator(firstNodeToResolve)); resolveVisitor.Scan(rootNode); } }
/// <summary> /// Applies a resolver navigator. This will resolve the nodes requested by the navigator, and will inform the /// navigator of the results. /// This method must be called as the first operation on the CSharpAstResolver, it is invalid to apply a navigator /// after a portion of the file was already resolved. /// </summary> public void ApplyNavigator(IResolveVisitorNavigator navigator, CancellationToken cancellationToken = default(CancellationToken)) { if (navigator == null) { throw new ArgumentNullException("navigator"); } if (resolveVisitor != null) { throw new InvalidOperationException("Applying a navigator is only valid as the first operation on the CSharpAstResolver."); } resolveVisitor = new ResolveVisitor(initialResolverState, parsedFile, navigator); lock (resolveVisitor) resolveVisitor.Scan(rootNode); }
/// <summary> /// Creates a new C# AST resolver. /// Use this overload if you are resolving code snippets (not necessarily complete files). /// </summary> /// <param name="resolver">The resolver state at the root node (to be more precise: outside the root node).</param> /// <param name="rootNode">The root node of the resolved tree.</param> /// <param name="parsedFile"> /// Optional: Result of the <see cref="TypeSystemConvertVisitor"/> for the file being resolved. /// <para> /// This is used for setting up the context on the resolver. The parsed file must be registered in the compilation. /// </para> /// <para> /// When a parsedFile is specified, the resolver will use the member's StartLocation/EndLocation to identify /// member declarations in the AST with members in the type system. /// When no parsedFile is specified (<c>null</c> value for this parameter), the resolver will instead compare the /// member's signature in the AST with the signature in the type system. /// </para> /// </param> public CSharpAstResolver(CSharpResolver resolver, AstNode rootNode, CSharpParsedFile parsedFile = null) { if (resolver == null) { throw new ArgumentNullException("resolver"); } if (rootNode == null) { throw new ArgumentNullException("rootNode"); } this.initialResolverState = resolver; this.rootNode = rootNode; this.parsedFile = parsedFile; this.resolveVisitor = new ResolveVisitor(initialResolverState, parsedFile); }
/// <summary> /// Creates a new C# AST resolver. /// Use this overload if you are resolving within a complete C# file. /// </summary> /// <param name="compilation">The current compilation.</param> /// <param name="compilationUnit">The compilation unit corresponding to the specified parsed file.</param> /// <param name="parsedFile"> /// Optional: Result of the <see cref="TypeSystemConvertVisitor"/> for the file being resolved. /// <para> /// This is used for setting up the context on the resolver. The parsed file must be registered in the compilation. /// </para> /// <para> /// When a parsedFile is specified, the resolver will use the member's StartLocation/EndLocation to identify /// member declarations in the AST with members in the type system. /// When no parsedFile is specified (<c>null</c> value for this parameter), the resolver will instead compare the /// member's signature in the AST with the signature in the type system. /// </para> /// </param> public CSharpAstResolver(ICompilation compilation, CompilationUnit compilationUnit, CSharpParsedFile parsedFile = null) { if (compilation == null) { throw new ArgumentNullException("compilation"); } if (compilationUnit == null) { throw new ArgumentNullException("compilationUnit"); } this.initialResolverState = new CSharpResolver(compilation); this.rootNode = compilationUnit; this.parsedFile = parsedFile; this.resolveVisitor = new ResolveVisitor(initialResolverState, parsedFile); }
/// <summary> /// Creates a new C# AST resolver. /// Use this overload if you are resolving within a complete C# file. /// </summary> /// <param name="compilation">The current compilation.</param> /// <param name="syntaxTree">The syntax tree to be resolved.</param> /// <param name="unresolvedFile"> /// Optional: Result of <see cref="SyntaxTree.ToTypeSystem()"/> for the file being resolved. /// <para> /// This is used for setting up the context on the resolver. The unresolved file must be registered in the compilation. /// </para> /// <para> /// When a unresolvedFile is specified, the resolver will use the member's StartLocation/EndLocation to identify /// member declarations in the AST with members in the type system. /// When no unresolvedFile is specified (<c>null</c> value for this parameter), the resolver will instead compare the /// member's signature in the AST with the signature in the type system. /// </para> /// </param> public CSharpAstResolver(ICompilation compilation, SyntaxTree syntaxTree, CSharpUnresolvedFile unresolvedFile = null) { if (compilation == null) { throw new ArgumentNullException("compilation"); } if (syntaxTree == null) { throw new ArgumentNullException("syntaxTree"); } this.initialResolverState = new CSharpResolver(compilation); this.rootNode = syntaxTree; this.unresolvedFile = unresolvedFile; this.resolveVisitor = new ResolveVisitor(initialResolverState, unresolvedFile); }
/// <summary> /// Finds all references in the given file. /// </summary> /// <param name="searchScopes">The search scopes for which to look.</param> /// <param name="parsedFile">The type system representation of the file being searched.</param> /// <param name="compilationUnit">The compilation unit of the file being searched.</param> /// <param name="context">The type resolve context to use for resolving the file.</param> /// <param name="callback">Callback used to report the references that were found.</param> public void FindReferencesInFile(IList <IFindReferenceSearchScope> searchScopes, CSharpParsedFile parsedFile, CompilationUnit compilationUnit, ITypeResolveContext context, FoundReferenceCallback callback) { if (searchScopes == null) { throw new ArgumentNullException("searchScopes"); } if (parsedFile == null) { throw new ArgumentNullException("parsedFile"); } if (compilationUnit == null) { throw new ArgumentNullException("compilationUnit"); } if (context == null) { throw new ArgumentNullException("context"); } this.CancellationToken.ThrowIfCancellationRequested(); if (searchScopes.Count == 0) { return; } using (var ctx = context.Synchronize()) { IResolveVisitorNavigator navigator; if (searchScopes.Count == 1) { navigator = searchScopes[0].GetNavigator(callback); } else { navigator = new CompositeResolveVisitorNavigator(searchScopes.Select(s => s.GetNavigator(callback)).ToArray()); } navigator = new DetectSkippableNodesNavigator(navigator, compilationUnit); CSharpResolver resolver = new CSharpResolver(ctx, this.CancellationToken); ResolveVisitor v = new ResolveVisitor(resolver, parsedFile, navigator); v.Scan(compilationUnit); } }
internal override bool CanMatch(AstNode node) { InvocationExpression ie = node as InvocationExpression; if (ie != null) { Expression target = ResolveVisitor.UnpackParenthesizedExpression(ie.Target); IdentifierExpression ident = target as IdentifierExpression; if (ident != null) { return(ident.Identifier == method.Name); } MemberReferenceExpression mre = target as MemberReferenceExpression; if (mre != null) { return(mre.MemberName == method.Name); } PointerReferenceExpression pre = target as PointerReferenceExpression; if (pre != null) { return(pre.MemberName == method.Name); } } if (node is MethodDeclaration) { return(true); } if (specialNodeType != null) { return(specialNodeType.IsInstanceOfType(node)); } else { return(false); } }
public void Resolved(AstNode node, ResolveResult result) { if (ResolveVisitor.ActsAsParenthesizedExpression(node)) { return; } MemberResolveResult mrr = result as MemberResolveResult; if (mrr != null) { referenceFound(node, mrr.Member.MemberDefinition); } TypeResolveResult trr = result as TypeResolveResult; if (trr != null) { ITypeDefinition typeDef = trr.Type.GetDefinition(); if (typeDef != null) { referenceFound(node, typeDef); } } }
public static ResolveResult Resolve(ITypeResolveContext context, CSharpParsedFile parsedFile, CompilationUnit cu, TextLocation location, CancellationToken cancellationToken = default(CancellationToken)) { AstNode node = cu.GetNodeAt(location); if (node == null) { return(null); } AstNode resolvableNode; if (node is AstType) { resolvableNode = node; if (resolvableNode.Parent is ComposedType) { while (resolvableNode.Parent is ComposedType) { resolvableNode = resolvableNode.Parent; } //node is preffered over the resolvable node. Which shouldn't be done in the case of nullables, arrays etc. node = resolvableNode; } } else if (node is Identifier) { resolvableNode = node.Parent; } else if (node.NodeType == NodeType.Token) { if (node.Parent is ConstructorInitializer) { resolvableNode = node.Parent; } else { return(null); } } else { // don't resolve arbitrary nodes - we don't want to show tooltips for everything return(null); } InvocationExpression parentInvocation = null; if ((resolvableNode is IdentifierExpression || resolvableNode is MemberReferenceExpression || resolvableNode is PointerReferenceExpression)) { // we also need to resolve the invocation parentInvocation = resolvableNode.Parent as InvocationExpression; } IResolveVisitorNavigator navigator; if (parentInvocation != null) { navigator = new NodeListResolveVisitorNavigator(new[] { resolvableNode, parentInvocation }); } else { navigator = new NodeListResolveVisitorNavigator(new[] { resolvableNode }); } using (var ctx = context.Synchronize()) { CSharpResolver resolver = new CSharpResolver(ctx, cancellationToken); ResolveVisitor v = new ResolveVisitor(resolver, parsedFile, navigator); v.Scan(cu); // Prefer the RR from the token itself, if it was assigned a ResolveResult // (this can happen with the identifiers in various nodes such as catch clauses or foreach statements) ResolveResult rr = v.GetResolveResult(node) ?? v.GetResolveResult(resolvableNode); if (rr is MethodGroupResolveResult && parentInvocation != null) { return(v.GetResolveResult(parentInvocation)); } else { return(rr); } } }
public override IEnumerable<ICSharpCode.NRefactory.TypeSystem.IMember> ResolveMember (Expression expression) { var pf = ParsedFile; var csResolver = new CSharpResolver (TypeResolveContext, System.Threading.CancellationToken.None); var navigator = new NodeListResolveVisitorNavigator (new[] { expression }); var visitor = new ICSharpCode.NRefactory.CSharp.Resolver.ResolveVisitor (csResolver, pf, navigator); visitor.VisitCompilationUnit (Unit, null); var resolveResult = visitor.Resolve (expression); if (resolveResult == null) yield break; if (resolveResult is MemberResolveResult) { yield return ((MemberResolveResult)resolveResult).Member; } else if (resolveResult is MethodGroupResolveResult) { var mgg = (MethodGroupResolveResult)resolveResult; foreach (var m in mgg.Methods) yield return m; } }