protected override ValueTask <ImmutableArray <FinderLocation> > FindReferencesInDocumentAsync( IEventSymbol symbol, Document document, SemanticModel semanticModel, FindReferencesSearchOptions options, CancellationToken cancellationToken ) { return(FindReferencesInDocumentUsingSymbolNameAsync( symbol, document, semanticModel, cancellationToken )); }
protected override async Task <ImmutableArray <FinderLocation> > FindReferencesInDocumentAsync( INamedTypeSymbol namedType, Document document, SemanticModel semanticModel, FindReferencesSearchOptions options, CancellationToken cancellationToken) { var namedTypeReferences = await FindReferencesInDocumentWorker( namedType, document, semanticModel, cancellationToken).ConfigureAwait(false); // Mark any references that are also Constructor references. Some callers // will want to know about these so they won't display duplicates. return(await MarkConstructorReferences( namedType, document, semanticModel, namedTypeReferences, cancellationToken).ConfigureAwait(false)); }
protected sealed override async Task <ImmutableArray <Document> > DetermineDocumentsToSearchAsync( IMethodSymbol symbol, HashSet <string>?globalAliases, Project project, IImmutableSet <Document>?documents, FindReferencesSearchOptions options, CancellationToken cancellationToken) { var op = symbol.GetPredefinedOperator(); var documentsWithOp = await FindDocumentsAsync(project, documents, op, cancellationToken).ConfigureAwait(false); var documentsWithGlobalAttributes = await FindDocumentsWithGlobalSuppressMessageAttributeAsync(project, documents, cancellationToken).ConfigureAwait(false); return(documentsWithOp.Concat(documentsWithGlobalAttributes)); }
public override Task <ImmutableArray <SymbolAndProjectId> > DetermineCascadedSymbolsAsync( SymbolAndProjectId symbolAndProjectId, Solution solution, IImmutableSet <Project> projects, FindReferencesSearchOptions options, CancellationToken cancellationToken) { var symbol = symbolAndProjectId.Symbol; if (symbol is TSymbol && CanFind((TSymbol)symbol)) { return(DetermineCascadedSymbolsAsync( symbolAndProjectId.WithSymbol((TSymbol)symbol), solution, projects, options, cancellationToken)); } return(SpecializedTasks.EmptyImmutableArray <SymbolAndProjectId>()); }
protected override Task <ImmutableArray <Document> > DetermineDocumentsToSearchAsync( IParameterSymbol symbol, HashSet <string>?globalAliases, Project project, IImmutableSet <Document>?documents, FindReferencesSearchOptions options, CancellationToken cancellationToken) { // TODO(cyrusn): We can be smarter with parameters. They will either be found // within the method that they were declared on, or they will referenced // elsewhere as "paramName:" or "paramName:=". We can narrow the search by // filtering down to matches of that form. For now we just return any document // that references something with this name. return(FindDocumentsAsync(project, documents, cancellationToken, symbol.Name)); }
public override Task <ImmutableArray <ISymbol> > DetermineCascadedSymbolsAsync( ISymbol symbol, Solution solution, IImmutableSet <Project> projects, FindReferencesSearchOptions options, CancellationToken cancellationToken) { if (options.Cascade && symbol is TSymbol typedSymbol && CanFind(typedSymbol)) { return(DetermineCascadedSymbolsAsync( typedSymbol, solution, projects, options, cancellationToken)); } return(SpecializedTasks.EmptyImmutableArray <ISymbol>()); }
public static async Task FindReferencesAsync( IFindUsagesContext context, ISymbol symbol, Project project, FindReferencesSearchOptions options ) { var cancellationToken = context.CancellationToken; var solution = project.Solution; var client = await RemoteHostClient .TryGetClientAsync(solution.Workspace, cancellationToken) .ConfigureAwait(false); if (client != null) { // Create a callback that we can pass to the server process to hear about the // results as it finds them. When we hear about results we'll forward them to // the 'progress' parameter which will then update the UI. var serverCallback = new FindUsagesServerCallback(solution, context); var symbolAndProjectId = SerializableSymbolAndProjectId.Create( symbol, project, cancellationToken ); _ = await client .TryInvokeAsync <IRemoteFindUsagesService>( solution, (service, solutionInfo, callbackId, cancellationToken) => service.FindReferencesAsync( solutionInfo, callbackId, symbolAndProjectId, options, cancellationToken ), serverCallback, cancellationToken ) .ConfigureAwait(false); } else { // Couldn't effectively search in OOP. Perform the search in-process. await FindReferencesInCurrentProcessAsync(context, symbol, project, options) .ConfigureAwait(false); } }
protected override Task <ImmutableArray <ISymbol> > DetermineCascadedSymbolsAsync( IFieldSymbol symbol, Solution solution, IImmutableSet <Project> projects, FindReferencesSearchOptions options, CancellationToken cancellationToken) { if (symbol.AssociatedSymbol != null) { return(Task.FromResult(ImmutableArray.Create(symbol.AssociatedSymbol))); } else { return(SpecializedTasks.EmptyImmutableArray <ISymbol>()); } }
protected override Task <ImmutableArray <Document> > DetermineDocumentsToSearchAsync( ITypeParameterSymbol symbol, Project project, IImmutableSet <Document>?documents, FindReferencesSearchOptions options, CancellationToken cancellationToken) { // Type parameters are only found in documents that have both their name, and the // name of its owning type. NOTE(cyrusn): We have to check in multiple files because // of partial types. A type parameter can be referenced across all the parts. // NOTE(cyrusn): We look for type parameters by name. This means if the same type // parameter has a different name in different parts that we won't find it. However, // this only happens in error situations. It is not legal in C# to use a different // name for a type parameter in different parts. return(FindDocumentsAsync(project, documents, findInGlobalSuppressions: false, cancellationToken, symbol.Name, symbol.ContainingType.Name)); }
/// <summary> /// Public helper that we use from features like ObjectBrowser which start with a symbol /// and want to push all the references to it into the Streaming-Find-References window. /// </summary> public static async Task FindSymbolReferencesAsync( IFindUsagesContext context, ISymbol symbol, Project project, CancellationToken cancellationToken) { await context.SetSearchTitleAsync( string.Format(FeaturesResources._0_references, FindUsagesHelpers.GetDisplayName(symbol)), cancellationToken).ConfigureAwait(false); var options = FindReferencesSearchOptions.GetFeatureOptionsForStartingSymbol(symbol); // Now call into the underlying FAR engine to find reference. The FAR // engine will push results into the 'progress' instance passed into it. // We'll take those results, massage them, and forward them along to the // FindReferencesContext instance we were given. await FindReferencesAsync(context, symbol, project, options, cancellationToken).ConfigureAwait(false); }
protected override async ValueTask <ImmutableArray <FinderLocation> > FindReferencesInDocumentAsync( INamedTypeSymbol namedType, Document document, SemanticModel semanticModel, FindReferencesSearchOptions options, CancellationToken cancellationToken) { var nonAliasReferences = await FindNonAliasReferencesAsync(namedType, document, semanticModel, cancellationToken).ConfigureAwait(false); var symbolsMatch = GetStandardSymbolsMatchFunction(namedType, findParentNode: null, document.Project.Solution, cancellationToken); var aliasReferences = await FindAliasReferencesAsync(nonAliasReferences, document, semanticModel, symbolsMatch, cancellationToken).ConfigureAwait(false); var suppressionReferences = await FindReferencesInDocumentInsideGlobalSuppressionsAsync(document, semanticModel, namedType, cancellationToken).ConfigureAwait(false); return(nonAliasReferences.Concat(aliasReferences, suppressionReferences)); }
protected override Task <ImmutableArray <Document> > DetermineDocumentsToSearchAsync( IFieldSymbol symbol, Project project, IImmutableSet <Document>?documents, FindReferencesSearchOptions options, CancellationToken cancellationToken ) { return(FindDocumentsAsync( project, documents, findInGlobalSuppressions: true, cancellationToken, symbol.Name )); }
public static bool ShouldShow( this ReferencedSymbol referencedSymbol, FindReferencesSearchOptions options ) { // If the reference has any locations then we will present it. if (referencedSymbol.Locations.Any()) { return(true); } return(referencedSymbol.Definition.ShouldShowWithNoReferenceLocations( options, showMetadataSymbolsWithoutReferences: true )); }
> DetermineCascadedSymbolsAsync( ITypeParameterSymbol symbol, Solution solution, IImmutableSet <Project>?projects, FindReferencesSearchOptions options, FindReferencesCascadeDirection cascadeDirection, CancellationToken cancellationToken ) { var method = (IMethodSymbol)symbol.ContainingSymbol; var ordinal = method.TypeParameters.IndexOf(symbol); if (ordinal >= 0) { if ( method.PartialDefinitionPart != null && ordinal < method.PartialDefinitionPart.TypeParameters.Length ) { return(Task.FromResult( ImmutableArray.Create( ( (ISymbol)method.PartialDefinitionPart.TypeParameters[ordinal], cascadeDirection ) ) )); } if ( method.PartialImplementationPart != null && ordinal < method.PartialImplementationPart.TypeParameters.Length ) { return(Task.FromResult( ImmutableArray.Create( ( (ISymbol)method.PartialImplementationPart.TypeParameters[ordinal], cascadeDirection ) ) )); } } return(SpecializedTasks.EmptyImmutableArray <(ISymbol symbol, FindReferencesCascadeDirection cascadeDirection)>()); }
protected override async ValueTask <ImmutableArray <FinderLocation> > FindReferencesInDocumentAsync( IMethodSymbol methodSymbol, Document document, SemanticModel semanticModel, FindReferencesSearchOptions options, CancellationToken cancellationToken) { var syntaxFactsService = document.GetRequiredLanguageService <ISyntaxFactsService>(); var typeName = methodSymbol.ContainingType.Name; var tokens = await document.GetConstructorInitializerTokensAsync(semanticModel, cancellationToken).ConfigureAwait(false); if (semanticModel.Language == LanguageNames.VisualBasic) { tokens = tokens.Concat(await GetIdentifierOrGlobalNamespaceTokensWithTextAsync( document, semanticModel, "New", cancellationToken).ConfigureAwait(false)).Distinct(); } return(await FindReferencesInTokensAsync( methodSymbol, document, semanticModel, tokens, TokensMatch, cancellationToken).ConfigureAwait(false)); // local functions bool TokensMatch(SyntaxToken t) { if (syntaxFactsService.IsBaseConstructorInitializer(t)) { var containingType = semanticModel.GetEnclosingNamedType(t.SpanStart, cancellationToken); return(containingType != null && containingType.BaseType != null && containingType.BaseType.Name == typeName); } else if (syntaxFactsService.IsThisConstructorInitializer(t)) { var containingType = semanticModel.GetEnclosingNamedType(t.SpanStart, cancellationToken); return(containingType != null && containingType.Name == typeName); } else if (semanticModel.Language == LanguageNames.VisualBasic && t.IsPartOfStructuredTrivia()) { return(true); } return(false); } }
private async Task <ImmutableArray <FinderLocation> > FindElementAccessReferencesAsync( IPropertySymbol symbol, Document document, SemanticModel semanticModel, FindReferencesSearchOptions options, CancellationToken cancellationToken) { if (options.AssociatePropertyReferencesWithSpecificAccessor) { // Looking for individual get/set references. Don't find anything here. // these results will be provided by the PropertyAccessorSymbolReferenceFinder return(ImmutableArray <FinderLocation> .Empty); } var symbolsMatch = GetStandardSymbolsNodeMatchFunction(symbol, document.Project.Solution, cancellationToken); var syntaxRoot = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var syntaxFacts = document.GetLanguageService <ISyntaxFactsService>(); var semanticFacts = document.GetLanguageService <ISemanticFactsService>(); var elementAccessExpressions = syntaxRoot.DescendantNodes().Where(syntaxFacts.IsElementAccessExpression); var locations = ArrayBuilder <FinderLocation> .GetInstance(); foreach (var node in elementAccessExpressions) { cancellationToken.ThrowIfCancellationRequested(); var(matched, reason) = symbolsMatch(node, semanticModel); if (matched) { syntaxFacts.GetPartsOfElementAccessExpression(node, out var expression, out var argumentList); if (symbolsMatch(expression, semanticModel).matched) { // Element access with explicit member name (allowed in VB). // We have already added a reference location for the member name identifier, so skip this one. continue; } var location = argumentList.SyntaxTree.GetLocation(new TextSpan(argumentList.SpanStart, 0)); var symbolUsageInfo = GetSymbolUsageInfo(node, semanticModel, syntaxFacts, semanticFacts, cancellationToken); locations.Add(new FinderLocation( node, new ReferenceLocation(document, null, location, isImplicit: false, symbolUsageInfo, GetAdditionalFindUsagesProperties(node, semanticModel, syntaxFacts), candidateReason: reason))); } } return(locations.ToImmutableAndFree()); }
protected override Task <ImmutableArray <(ISymbol symbol, FindReferencesCascadeDirection cascadeDirection)> > DetermineCascadedSymbolsAsync( IMethodSymbol symbol, Solution solution, IImmutableSet <Project>?projects, FindReferencesSearchOptions options, FindReferencesCascadeDirection cascadeDirection, CancellationToken cancellationToken) { if (!cascadeDirection.HasFlag(FindReferencesCascadeDirection.Up)) { return(SpecializedTasks.EmptyImmutableArray <(ISymbol symbol, FindReferencesCascadeDirection cascadeDirection)>()); } // An explicit interface method will cascade to all the methods that it implements in the up direction. return(Task.FromResult( symbol.ExplicitInterfaceImplementations.SelectAsArray(m => ((ISymbol)m, FindReferencesCascadeDirection.Up)))); }
protected override async Task <ImmutableArray <(ISymbol symbol, FindReferencesCascadeDirection cascadeDirection)> > DetermineCascadedSymbolsAsync( TSymbol symbol, Solution solution, IImmutableSet <Project>?projects, FindReferencesSearchOptions options, FindReferencesCascadeDirection cascadeDirection, CancellationToken cancellationToken) { if (symbol.IsImplementableMember()) { // We have an interface method. Walk down the inheritance hierarchy and find all implementations of // that method and cascade to them. var result = cascadeDirection.HasFlag(FindReferencesCascadeDirection.Down) ? await SymbolFinder.FindMemberImplementationsArrayAsync(symbol, solution, projects, cancellationToken).ConfigureAwait(false) : ImmutableArray <ISymbol> .Empty; return(result.SelectAsArray(s => (s, FindReferencesCascadeDirection.Down))); } else { // We have a normal method. Find any interface methods up the inheritance hierarchy that it implicitly // or explicitly implements and cascade to those. var interfaceMembersImplemented = cascadeDirection.HasFlag(FindReferencesCascadeDirection.Up) ? await SymbolFinder.FindImplementedInterfaceMembersArrayAsync(symbol, solution, projects, cancellationToken).ConfigureAwait(false) : ImmutableArray <ISymbol> .Empty; // Finally, methods can cascade through virtual/override inheritance. NOTE(cyrusn): // We only need to go up or down one level. Then, when we're finding references on // those members, we'll end up traversing the entire hierarchy. var overrides = cascadeDirection.HasFlag(FindReferencesCascadeDirection.Down) ? await SymbolFinder.FindOverridesArrayAsync(symbol, solution, projects, cancellationToken).ConfigureAwait(false) : ImmutableArray <ISymbol> .Empty; var overriddenMember = cascadeDirection.HasFlag(FindReferencesCascadeDirection.Up) ? symbol.GetOverriddenMember() : null; var interfaceMembersImplementedWithDirection = interfaceMembersImplemented.SelectAsArray(s => (s, FindReferencesCascadeDirection.Up)); var overridesWithDirection = overrides.SelectAsArray(s => (s, FindReferencesCascadeDirection.Down)); var overriddenMemberWithDirection = (overriddenMember !, FindReferencesCascadeDirection.Up); return(overriddenMember == null ? interfaceMembersImplementedWithDirection.Concat(overridesWithDirection) : interfaceMembersImplementedWithDirection.Concat(overridesWithDirection).Concat(overriddenMemberWithDirection)); } }
protected sealed override Task <ImmutableArray <ISymbol> > DetermineCascadedSymbolsAsync( IEventSymbol symbol, Solution solution, FindReferencesSearchOptions options, CancellationToken cancellationToken) { var backingFields = symbol.ContainingType.GetMembers() .OfType <IFieldSymbol>() .Where(f => symbol.Equals(f.AssociatedSymbol)) .ToImmutableArray <ISymbol>(); var associatedNamedTypes = symbol.ContainingType.GetTypeMembers() .WhereAsArray(n => symbol.Equals(n.AssociatedSymbol)) .CastArray <ISymbol>(); return(Task.FromResult(backingFields.Concat(associatedNamedTypes))); }
public FindReferencesSearchEngine( Solution solution, IImmutableSet <Document> documents, ImmutableArray <IReferenceFinder> finders, IStreamingFindReferencesProgress progress, FindReferencesSearchOptions options, CancellationToken cancellationToken) { _documents = documents; _solution = solution; _finders = finders; _progress = progress; _cancellationToken = cancellationToken; _options = options; _progressTracker = progress.ProgressTracker; }
protected override Task <ImmutableArray <ISymbol> > DetermineCascadedSymbolsAsync( IMethodSymbol symbol, Solution solution, FindReferencesSearchOptions options, CancellationToken cancellationToken) { // If it's a delegate method, then cascade to the type as well. These guys are // practically equivalent for users. if (symbol.ContainingType.TypeKind == TypeKind.Delegate) { return(Task.FromResult(ImmutableArray.Create <ISymbol>(symbol.ContainingType))); } else { return(Task.FromResult(GetOtherPartsOfPartial(symbol))); } }
> FindReferencesInDocumentAsync( TSymbol symbol, Document document, SemanticModel semanticModel, FindReferencesSearchOptions options, CancellationToken cancellationToken ) { var container = GetContainer(symbol); if (container != null) { return(await FindReferencesInContainerAsync( symbol, container, document, semanticModel, cancellationToken ) .ConfigureAwait(false)); } if (symbol.ContainingType != null && symbol.ContainingType.IsScriptClass) { var syntaxTree = await document .GetRequiredSyntaxTreeAsync(cancellationToken) .ConfigureAwait(false); var syntaxFactsService = document.GetLanguageService <ISyntaxFactsService>(); var root = await syntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false); var tokens = root.DescendantTokens(); return(await FindReferencesInTokensWithSymbolNameAsync( symbol, document, semanticModel, tokens, cancellationToken ) .ConfigureAwait(false)); } return(ImmutableArray <FinderLocation> .Empty); }
protected override async Task <ImmutableArray <Document> > DetermineDocumentsToSearchAsync( IPropertySymbol symbol, Project project, IImmutableSet <Document>?documents, FindReferencesSearchOptions options, CancellationToken cancellationToken ) { var ordinaryDocuments = await FindDocumentsAsync( project, documents, findInGlobalSuppressions : true, cancellationToken, symbol.Name ) .ConfigureAwait(false); var forEachDocuments = IsForEachProperty(symbol) ? await FindDocumentsWithForEachStatementsAsync(project, documents, cancellationToken) .ConfigureAwait(false) : ImmutableArray <Document> .Empty; var elementAccessDocument = symbol.IsIndexer ? await FindDocumentWithElementAccessExpressionsAsync( project, documents, cancellationToken ) .ConfigureAwait(false) : ImmutableArray <Document> .Empty; var indexerMemberCrefDocument = symbol.IsIndexer ? await FindDocumentWithIndexerMemberCrefAsync( project, documents, cancellationToken ) .ConfigureAwait(false) : ImmutableArray <Document> .Empty; return(ordinaryDocuments .Concat(forEachDocuments) .Concat(elementAccessDocument) .Concat(indexerMemberCrefDocument)); }
protected override async Task <ImmutableArray <Document> > DetermineDocumentsToSearchAsync( INamedTypeSymbol symbol, Project project, IImmutableSet <Document> documents, FindReferencesSearchOptions options, CancellationToken cancellationToken) { var documentsWithName = await FindDocumentsAsync(project, documents, cancellationToken, symbol.Name).ConfigureAwait(false); var documentsWithType = await FindDocumentsAsync(project, documents, symbol.SpecialType.ToPredefinedType(), cancellationToken).ConfigureAwait(false); var documentsWithAttribute = TryGetNameWithoutAttributeSuffix(symbol.Name, project.LanguageServices.GetService <ISyntaxFactsService>(), out var simpleName) ? await FindDocumentsAsync(project, documents, cancellationToken, simpleName).ConfigureAwait(false) : ImmutableArray <Document> .Empty; return(documentsWithName.Concat(documentsWithType) .Concat(documentsWithAttribute)); }
private static Task FindReferencesInCurrentProcessAsync( IFindUsagesContext context, ISymbol symbol, Project project, FindReferencesSearchOptions options ) { var progress = new FindReferencesProgressAdapter(project.Solution, context, options); return(SymbolFinder.FindReferencesAsync( symbol, project.Solution, progress, documents: null, options, context.CancellationToken )); }
protected override async ValueTask <ImmutableArray <FinderLocation> > FindReferencesInDocumentAsync( IMethodSymbol symbol, Document document, SemanticModel semanticModel, FindReferencesSearchOptions options, CancellationToken cancellationToken) { var syntaxFacts = document.GetRequiredLanguageService <ISyntaxFactsService>(); var op = symbol.GetPredefinedOperator(); var opReferences = await FindReferencesInDocumentAsync(symbol, document, semanticModel, t => IsPotentialReference(syntaxFacts, op, t), cancellationToken).ConfigureAwait(false); var suppressionReferences = await FindReferencesInDocumentInsideGlobalSuppressionsAsync(document, semanticModel, symbol, cancellationToken).ConfigureAwait(false); return(opReferences.Concat(suppressionReferences)); }
public FindReferencesSearchEngine( Solution solution, IImmutableSet <Document> documents, ImmutableArray <IReferenceFinder> finders, IStreamingFindReferencesProgress progress, FindReferencesSearchOptions options, CancellationToken cancellationToken) { _documents = documents; _solution = solution; _finders = finders; _progress = progress; _cancellationToken = cancellationToken; _dependencyGraph = solution.GetProjectDependencyGraph(); _options = options; _progressTracker = new StreamingProgressTracker(progress.ReportProgressAsync); }
protected override ValueTask <ImmutableArray <FinderLocation> > FindReferencesInDocumentAsync( ITypeParameterSymbol symbol, Document document, SemanticModel semanticModel, FindReferencesSearchOptions options, CancellationToken cancellationToken ) { // TODO(cyrusn): Method type parameters are like locals. They are only in scope in // the bounds of the method they're declared within. We could improve perf by // limiting our search by only looking within the method body's span. return(FindReferencesInDocumentUsingSymbolNameAsync( symbol, document, semanticModel, cancellationToken )); }
public static bool ShouldShowWithNoReferenceLocations( this ISymbol definition, FindReferencesSearchOptions options, bool showMetadataSymbolsWithoutReferences) { // If the definition is implicit and we have no references, then we don't want to // clutter the UI with it. if (definition.IsImplicitlyDeclared) { return(false); } // If we're associating property references with an accessor, then we don't want to show // a property if it is has no references. Similarly, if we're associated associating // everything with the property, then we don't want to include accessors if there are no // references to them. if (options.AssociatePropertyReferencesWithSpecificAccessor) { if (definition.Kind == SymbolKind.Property) { return(false); } } else { if (definition.IsPropertyAccessor()) { return(false); } } // Otherwise we still show the item even if there are no references to it. // And it's at least a source definition. if (definition.Locations.Any(loc => loc.IsInSource)) { return(true); } if (showMetadataSymbolsWithoutReferences && definition.Locations.Any(loc => loc.IsInMetadata)) { return(true); } return(false); }
> DetermineCascadedSymbolsAsync( IMethodSymbol symbol, Solution solution, IImmutableSet <Project> projects, FindReferencesSearchOptions options, FindReferencesCascadeDirection cascadeDirection, CancellationToken cancellationToken ) { using var _ = ArrayBuilder <(ISymbol symbol, FindReferencesCascadeDirection cascadeDirection)> .GetInstance( out var result ); var beginInvoke = symbol.ContainingType .GetMembers(WellKnownMemberNames.DelegateBeginInvokeName) .FirstOrDefault(); if (beginInvoke != null) { result.Add((beginInvoke, cascadeDirection)); } // All method group references foreach (var project in solution.Projects) { foreach (var document in project.Documents) { var changeSignatureService = document.GetLanguageService <AbstractChangeSignatureService>(); var cascaded = await changeSignatureService .DetermineCascadedSymbolsFromDelegateInvokeAsync( symbol, document, cancellationToken ) .ConfigureAwait(false); result.AddRange(cascaded.SelectAsArray(s => (s, cascadeDirection))); } } return(result.ToImmutable()); }