internal ReferencedSymbol( SymbolAndProjectId definitionAndProjectId, IEnumerable<ReferenceLocation> locations) { this.DefinitionAndProjectId = definitionAndProjectId; this.Locations = (locations ?? SpecializedCollections.EmptyEnumerable<ReferenceLocation>()).ToReadOnlyCollection(); }
private static Task<ImmutableArray<SymbolAndProjectId<INamedTypeSymbol>>> FindDerivedClassesAsync( SymbolAndProjectId<INamedTypeSymbol> type, Solution solution, IImmutableSet<Project> projects, bool transitive, CancellationToken cancellationToken) { if (s_isNonSealedClass(type.Symbol)) { Func<SymbolAndProjectIdSet, INamedTypeSymbol, bool> metadataTypeMatches = (set, metadataType) => TypeDerivesFrom(set, metadataType, transitive); Func<SymbolAndProjectIdSet, INamedTypeSymbol, bool> sourceTypeImmediatelyMatches = (set, metadataType) => set.Contains(SymbolAndProjectId.Create(metadataType.BaseType?.OriginalDefinition, projectId: null)); return FindTypesAsync(type, solution, projects, metadataTypeMatches: metadataTypeMatches, sourceTypeImmediatelyMatches: sourceTypeImmediatelyMatches, shouldContinueSearching: s_isNonSealedClass, transitive: transitive, cancellationToken: cancellationToken); } return SpecializedTasks.EmptyImmutableArray<SymbolAndProjectId<INamedTypeSymbol>>(); }
public Task OnReferenceFoundAsync( SymbolAndProjectId definition, ReferenceLocation reference) { return _service.Rpc.InvokeAsync(nameof(OnReferenceFoundAsync), SerializableSymbolAndProjectId.Dehydrate(definition), SerializableReferenceLocation.Dehydrate(reference)); }
private static async Task FindReferencesInServiceProcessAsync( SymbolAndProjectId symbolAndProjectId, Solution solution, IStreamingFindReferencesProgress progress, IImmutableSet<Document> documents, CancellationToken cancellationToken) { var client = await solution.Workspace.GetRemoteHostClientAsync(cancellationToken).ConfigureAwait(false); if (client == null) { await FindReferencesInCurrentProcessAsync( symbolAndProjectId, solution, progress, documents, cancellationToken).ConfigureAwait(false); return; } // 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 upate the UI. var serverCallback = new ServerCallback(solution, progress, cancellationToken); using (var session = await client.CreateCodeAnalysisServiceSessionAsync( solution, serverCallback, cancellationToken).ConfigureAwait(false)) { await session.InvokeAsync( nameof(IRemoteSymbolFinder.FindReferencesAsync), SerializableSymbolAndProjectId.Dehydrate(symbolAndProjectId), documents?.Select(SerializableDocumentId.Dehydrate).ToArray()).ConfigureAwait(false); } }
public Task OnReferenceFoundAsync(SymbolAndProjectId definition, ReferenceLocation location) { lock (_gate) { _symbolToLocations[definition].Add(location); } return _underlyingProgress.OnReferenceFoundAsync(definition, location); }
public Task OnDefinitionFoundAsync(SymbolAndProjectId definition) { lock (_gate) { _symbolToLocations[definition] = new List<ReferenceLocation>(); } return _underlyingProgress.OnDefinitionFoundAsync(definition); }
internal static Task FindReferencesAsync( SymbolAndProjectId symbolAndProjectId, Solution solution, IStreamingFindReferencesProgress progress, IImmutableSet<Document> documents, CancellationToken cancellationToken = default(CancellationToken)) { var engineService = solution.Workspace.Services.GetService<ISymbolFinderEngineService>(); return engineService.FindReferencesAsync(symbolAndProjectId, solution, progress, documents, cancellationToken); }
internal static Task FindReferencesInCurrentProcessAsync( SymbolAndProjectId symbolAndProjectId, Solution solution, IStreamingFindReferencesProgress progress, IImmutableSet<Document> documents, CancellationToken cancellationToken) { var finders = ReferenceFinders.DefaultReferenceFinders; progress = progress ?? StreamingFindReferencesProgress.Instance; var engine = new FindReferencesSearchEngine( solution, documents, finders, progress, cancellationToken); return engine.FindReferencesAsync(symbolAndProjectId); }
public async Task FindReferencesAsync( SymbolAndProjectId symbolAndProjectId, Solution solution, IStreamingFindReferencesProgress progress, IImmutableSet<Document> documents, CancellationToken cancellationToken) { using (Logger.LogBlock(FunctionId.FindReference, cancellationToken)) { await FindReferencesInCurrentProcessAsync( symbolAndProjectId, solution, progress, documents, cancellationToken).ConfigureAwait(false); } }
internal RenameLocations( ISet<RenameLocation> locations, SymbolAndProjectId symbolAndProjectId, Solution solution, IEnumerable<SymbolAndProjectId> referencedSymbols, IEnumerable<ReferenceLocation> implicitLocations, OptionSet options) { _symbolAndProjectId = symbolAndProjectId; _solution = solution; _mergedResult = new SearchResult(locations, implicitLocations, referencedSymbols); Options = options; }
public async Task<ImmutableArray<SymbolAndProjectId>> DetermineCascadedSymbolsAsync( SymbolAndProjectId symbolAndProjectId, Solution solution, IImmutableSet<Project> projects = null, CancellationToken cancellationToken = default(CancellationToken)) { var linkedSymbols = new HashSet<SymbolAndProjectId>(); var symbol = symbolAndProjectId.Symbol; foreach (var location in symbol.DeclaringSyntaxReferences) { var originalDocument = solution.GetDocument(location.SyntaxTree); // GetDocument will return null for locations in #load'ed trees. // TODO: Remove this check and add logic to fetch the #load'ed tree's // Document once https://github.com/dotnet/roslyn/issues/5260 is fixed. if (originalDocument == null) { Debug.Assert(solution.Workspace.Kind == "Interactive"); continue; } foreach (var linkedDocumentId in originalDocument.GetLinkedDocumentIds()) { var linkedDocument = solution.GetDocument(linkedDocumentId); var linkedSyntaxRoot = await linkedDocument.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); // Defend against constructed solutions with inconsistent linked documents if (!linkedSyntaxRoot.FullSpan.Contains(location.Span)) { continue; } var linkedNode = linkedSyntaxRoot.FindNode(location.Span, getInnermostNodeForTie: true); var semanticModel = await linkedDocument.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); var linkedSymbol = semanticModel.GetDeclaredSymbol(linkedNode, cancellationToken); if (linkedSymbol != null && linkedSymbol.Kind == symbol.Kind && linkedSymbol.Name == symbol.Name) { var linkedSymbolAndProjectId = SymbolAndProjectId.Create(linkedSymbol, linkedDocument.Project.Id); if (!linkedSymbols.Contains(linkedSymbolAndProjectId)) { linkedSymbols.Add(linkedSymbolAndProjectId); } } } } return linkedSymbols.ToImmutableArray(); }
public async Task OnReferenceFoundAsync(SymbolAndProjectId definition, ReferenceLocation location) { // Ignore duplicate locations. We don't want to clutter the UI with them. if (location.IsDuplicateReferenceLocation) { return; } var referenceItem = location.TryCreateSourceReferenceItem( GetDefinitionItem(definition), includeHiddenLocations: false); if (referenceItem != null) { await _context.OnReferenceFoundAsync(referenceItem).ConfigureAwait(false); } }
private RenameLocations( SymbolAndProjectId symbolAndProjectId, Solution solution, OptionSet options, SearchResult originalSymbolResult, List<SearchResult> overloadsResult, IEnumerable<RenameLocation> stringsResult, IEnumerable<RenameLocation> commentsResult) { _symbolAndProjectId = symbolAndProjectId; _solution = solution; Options = options; _originalSymbolResult = originalSymbolResult; _overloadsResult = overloadsResult; _stringsResult = stringsResult; _commentsResult = commentsResult; var mergedLocations = new HashSet<RenameLocation>(); var mergedReferencedSymbols = new List<SymbolAndProjectId>(); var mergedImplicitLocations = new List<ReferenceLocation>(); if (options.GetOption(RenameOptions.RenameInStrings)) { mergedLocations.AddRange(stringsResult); } if (options.GetOption(RenameOptions.RenameInComments)) { mergedLocations.AddRange(commentsResult); } var renameMethodGroupReferences = options.GetOption(RenameOptions.RenameOverloads) || !GetOverloadedSymbols(symbolAndProjectId).Any(); var overloadsToMerge = (options.GetOption(RenameOptions.RenameOverloads) ? overloadsResult : null) ?? SpecializedCollections.EmptyEnumerable<SearchResult>(); foreach (var result in overloadsToMerge.Concat(originalSymbolResult)) { mergedLocations.AddRange(renameMethodGroupReferences ? result.Locations : result.Locations.Where(x => !x.IsMethodGroupReference)); mergedImplicitLocations.AddRange(result.ImplicitLocations); mergedReferencedSymbols.AddRange(result.ReferencedSymbols); } _mergedResult = new SearchResult(mergedLocations, mergedImplicitLocations, mergedReferencedSymbols); }
public async Task FindReferencesAsync(SymbolAndProjectId symbolAndProjectId) { await _progress.OnStartedAsync().ConfigureAwait(false); await _progressTracker.AddItemsAsync(1).ConfigureAwait(false); try { var symbols = await DetermineAllSymbolsAsync(symbolAndProjectId).ConfigureAwait(false); var projectMap = await CreateProjectMapAsync(symbols).ConfigureAwait(false); var documentMap = await CreateDocumentMapAsync(projectMap).ConfigureAwait(false); await ProcessAsync(documentMap).ConfigureAwait(false); } finally { await _progressTracker.ItemCompletedAsync().ConfigureAwait(false); await _progress.OnCompletedAsync().ConfigureAwait(false); } }
internal static async Task<IEnumerable<SymbolAndProjectId>> FindOverridesAsync( SymbolAndProjectId symbolAndProjectId, Solution solution, IImmutableSet<Project> projects = null, CancellationToken cancellationToken = default(CancellationToken)) { // Method can only have overrides if its a virtual, abstract or override and is not // sealed. var symbol = symbolAndProjectId.Symbol; if (symbol.IsOverridable()) { // To find the overrides, we need to walk down the type hierarchy and check all // derived types. TODO(cyrusn): This seems extremely costly. Is there any way to // speed this up? var containingType = symbol.ContainingType.OriginalDefinition; var derivedTypes = await FindDerivedClassesAsync( symbolAndProjectId.WithSymbol(containingType), solution, projects, cancellationToken).ConfigureAwait(false); List<SymbolAndProjectId> results = null; foreach (var type in derivedTypes) { foreach (var m in GetMembers(type, symbol.Name)) { var sourceMember = await FindSourceDefinitionAsync(m, solution, cancellationToken).ConfigureAwait(false); var bestMember = sourceMember.Symbol != null ? sourceMember : m; var member = bestMember.Symbol; if (member != null && member.IsOverride && member.OverriddenMember() != null && OriginalSymbolsMatch(member.OverriddenMember().OriginalDefinition, symbol.OriginalDefinition, solution, cancellationToken)) { results = results ?? new List<SymbolAndProjectId>(); results.Add(bestMember); } } } if (results != null) { return results; } } return SpecializedCollections.EmptyEnumerable<SymbolAndProjectId>(); }
public async Task FindReferencesAsync( SymbolAndProjectId symbolAndProjectId, Solution solution, IStreamingFindReferencesProgress progress, IImmutableSet<Document> documents, CancellationToken cancellationToken) { using (Logger.LogBlock(FunctionId.FindReference, cancellationToken)) { if (symbolAndProjectId.ProjectId == null) { // This is a call through our old public API. We don't have the necessary // data to effectively run the call out of proc. await DefaultSymbolFinderEngineService.FindReferencesInCurrentProcessAsync( symbolAndProjectId, solution, progress, documents, cancellationToken).ConfigureAwait(false); } else { await FindReferencesInServiceProcessAsync( symbolAndProjectId, solution, progress, documents, cancellationToken).ConfigureAwait(false); } } }
private async Task ProcessDocumentAsync( Document document, SymbolAndProjectId symbolAndProjectId, IReferenceFinder finder) { using (Logger.LogBlock(FunctionId.FindReference_ProcessDocumentAsync, s_logDocument, document, symbolAndProjectId.Symbol, _cancellationToken)) { try { var references = await finder.FindReferencesInDocumentAsync(symbolAndProjectId, document, _cancellationToken).ConfigureAwait(false); foreach (var location in references) { await HandleLocationAsync(symbolAndProjectId, location).ConfigureAwait(false); } } finally { await _progressTracker.ItemCompletedAsync().ConfigureAwait(false); } } }
public SymbolInlineRenameInfo( IEnumerable<IRefactorNotifyService> refactorNotifyServices, Document document, TextSpan triggerSpan, SymbolAndProjectId renameSymbolAndProjectId, bool forceRenameOverloads, CancellationToken cancellationToken) { this.CanRename = true; _refactorNotifyServices = refactorNotifyServices; _document = document; this.RenameSymbolAndProjectId = renameSymbolAndProjectId; this.HasOverloads = RenameLocations.GetOverloadedSymbols(this.RenameSymbolAndProjectId).Any(); this.ForceRenameOverloads = forceRenameOverloads; _isRenamingAttributePrefix = CanRenameAttributePrefix(document, triggerSpan, cancellationToken); this.TriggerSpan = GetReferenceEditSpan(new InlineRenameLocation(document, triggerSpan), cancellationToken); _shortenedTriggerSpan = this.TriggerSpan != triggerSpan; }
internal static async Task<ImmutableArray<ReferencedSymbol>> FindRenamableReferencesAsync( SymbolAndProjectId symbolAndProjectId, Solution solution, CancellationToken cancellationToken) { using (Logger.LogBlock(FunctionId.FindReference_Rename, cancellationToken)) { var streamingProgress = new StreamingProgressCollector( StreamingFindReferencesProgress.Instance); IImmutableSet<Document> documents = null; var engine = new FindReferencesSearchEngine( solution, documents, ReferenceFinders.DefaultRenameReferenceFinders, streamingProgress, cancellationToken); await engine.FindReferencesAsync(symbolAndProjectId).ConfigureAwait(false); return streamingProgress.GetReferencedSymbols(); } }
private async Task<ImmutableArray<DocumentHighlights>> GetTagsForReferencedSymbolAsync( SymbolAndProjectId symbolAndProjectId, IImmutableSet<Document> documentsToSearch, Solution solution, CancellationToken cancellationToken) { var symbol = symbolAndProjectId.Symbol; Contract.ThrowIfNull(symbol); if (ShouldConsiderSymbol(symbol)) { var progress = new StreamingProgressCollector( StreamingFindReferencesProgress.Instance); await SymbolFinder.FindReferencesAsync( symbolAndProjectId, solution, progress, documentsToSearch, cancellationToken).ConfigureAwait(false); return await FilterAndCreateSpansAsync( progress.GetReferencedSymbols(), solution, documentsToSearch, symbol, cancellationToken).ConfigureAwait(false); } return ImmutableArray<DocumentHighlights>.Empty; }
private Task HandleLocationAsync(SymbolAndProjectId symbolAndProjectId, ReferenceLocation location) { return _progress.OnReferenceFoundAsync(symbolAndProjectId, location); }
private async Task <Solution> ProcessResultAsync(CodeFixContext context, Diagnostic diagnostic, CancellationToken cancellationToken) { var locations = diagnostic.AdditionalLocations; var propertyLocation = locations[0]; var declaratorLocation = locations[1]; var declarator = declaratorLocation.FindToken(cancellationToken).Parent.FirstAncestorOrSelf <TVariableDeclarator>(); var fieldDocument = context.Document.Project.GetDocument(declarator.SyntaxTree); var fieldSemanticModel = await fieldDocument.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); var fieldSymbol = (IFieldSymbol)fieldSemanticModel.GetDeclaredSymbol(declarator); var property = propertyLocation.FindToken(cancellationToken).Parent.FirstAncestorOrSelf <TPropertyDeclaration>(); var propertyDocument = context.Document.Project.GetDocument(property.SyntaxTree); var propertySemanticModel = await propertyDocument.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); var propertySymbol = (IPropertySymbol)propertySemanticModel.GetDeclaredSymbol(property); Debug.Assert(fieldDocument.Project == propertyDocument.Project); var project = fieldDocument.Project; var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false); var solution = context.Document.Project.Solution; var fieldLocations = await Renamer.GetRenameLocationsAsync( solution, SymbolAndProjectId.Create(fieldSymbol, fieldDocument.Project.Id), solution.Options, cancellationToken).ConfigureAwait(false); // First, create the updated property we want to replace the old property with var isWrittenToOutsideOfConstructor = IsWrittenToOutsideOfConstructorOrProperty(fieldSymbol, fieldLocations, property, cancellationToken); var updatedProperty = await UpdatePropertyAsync( propertyDocument, compilation, fieldSymbol, propertySymbol, property, isWrittenToOutsideOfConstructor, cancellationToken).ConfigureAwait(false); // Note: rename will try to update all the references in linked files as well. However, // this can lead to some very bad behavior as we will change the references in linked files // but only remove the field and update the property in a single document. So, you can // end in the state where you do this in one of the linked file: // // int Prop { get { return this.field; } } => int Prop { get { return this.Prop } } // // But in the main file we'll replace: // // int Prop { get { return this.field; } } => int Prop { get; } // // The workspace will see these as two irreconcilable edits. To avoid this, we disallow // any edits to the other links for the files containing the field and property. i.e. // rename will only be allowed to edit the exact same doc we're removing the field from // and the exact doc we're updating the property in. It can't touch the other linked // files for those docs. (It can of course touch any other documents unrelated to the // docs that the field and prop are declared in). var linkedFiles = new HashSet <DocumentId>(); linkedFiles.AddRange(fieldDocument.GetLinkedDocumentIds()); linkedFiles.AddRange(propertyDocument.GetLinkedDocumentIds()); var canEdit = new Dictionary <SyntaxTree, bool>(); // Now, rename all usages of the field to point at the property. Except don't actually // rename the field itself. We want to be able to find it again post rename. var updatedSolution = await Renamer.RenameAsync(fieldLocations, propertySymbol.Name, location => !location.SourceSpan.IntersectsWith(declaratorLocation.SourceSpan) && CanEditDocument(solution, location.SourceTree, linkedFiles, canEdit), symbols => HasConflict(symbols, propertySymbol, compilation, cancellationToken), cancellationToken).ConfigureAwait(false); solution = updatedSolution; // Now find the field and property again post rename. fieldDocument = solution.GetDocument(fieldDocument.Id); propertyDocument = solution.GetDocument(propertyDocument.Id); Debug.Assert(fieldDocument.Project == propertyDocument.Project); compilation = await fieldDocument.Project.GetCompilationAsync(cancellationToken).ConfigureAwait(false); fieldSymbol = (IFieldSymbol)fieldSymbol.GetSymbolKey().Resolve(compilation, cancellationToken: cancellationToken).Symbol; propertySymbol = (IPropertySymbol)propertySymbol.GetSymbolKey().Resolve(compilation, cancellationToken: cancellationToken).Symbol; Debug.Assert(fieldSymbol != null && propertySymbol != null); declarator = (TVariableDeclarator)await fieldSymbol.DeclaringSyntaxReferences[0].GetSyntaxAsync(cancellationToken).ConfigureAwait(false); var temp = await propertySymbol.DeclaringSyntaxReferences[0].GetSyntaxAsync(cancellationToken).ConfigureAwait(false); property = temp.FirstAncestorOrSelf <TPropertyDeclaration>(); var nodeToRemove = GetNodeToRemove(declarator); // If we have a situation where the property is the second member in a type, and it // would become the first, then remove any leading blank lines from it so we don't have // random blanks above it that used to space it from the field that was there. // // The reason we do this special processing is that the first member of a type tends to // be special wrt leading trivia. i.e. users do not normally put blank lines before the // first member. And so, when a type now becomes the first member, we want to follow the // user's common pattern here. // // In all other code cases, i.e.when there are multiple fields above, or the field is // below the property, then the property isn't now becoming "the first member", and as // such, it doesn't want this special behavior about it's leading blank lines. i.e. if // the user has: // // class C // { // int i; // int j; // // int Prop => j; // } // // Then if we remove 'j' (or even 'i'), then 'Prop' would stay the non-first member, and // would definitely want to keep that blank line above it. // // In essence, the blank line above the property exists for separation from what's above // it. As long as something is above it, we keep the separation. However, if the // property becomes the first member in the type, the separation is now inappropriate // because there's nothing to actually separate it from. if (fieldDocument == propertyDocument) { var syntaxFacts = fieldDocument.GetLanguageService <ISyntaxFactsService>(); if (WillRemoveFirstFieldInTypeDirectlyAboveProperty(syntaxFacts, property, nodeToRemove) && syntaxFacts.GetLeadingBlankLines(nodeToRemove).Length == 0) { updatedProperty = syntaxFacts.GetNodeWithoutLeadingBlankLines(updatedProperty); } } var syntaxRemoveOptions = CreateSyntaxRemoveOptions(nodeToRemove); if (fieldDocument == propertyDocument) { // Same file. Have to do this in a slightly complicated fashion. var declaratorTreeRoot = await fieldDocument.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var editor = new SyntaxEditor(declaratorTreeRoot, fieldDocument.Project.Solution.Workspace); editor.ReplaceNode(property, updatedProperty); editor.RemoveNode(nodeToRemove, syntaxRemoveOptions); var newRoot = editor.GetChangedRoot(); newRoot = Format(newRoot, fieldDocument, cancellationToken); return(solution.WithDocumentSyntaxRoot(fieldDocument.Id, newRoot)); } else { // In different files. Just update both files. var fieldTreeRoot = await fieldDocument.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var propertyTreeRoot = await propertyDocument.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var newFieldTreeRoot = fieldTreeRoot.RemoveNode(nodeToRemove, syntaxRemoveOptions); var newPropertyTreeRoot = propertyTreeRoot.ReplaceNode(property, updatedProperty); newFieldTreeRoot = Format(newFieldTreeRoot, fieldDocument, cancellationToken); newPropertyTreeRoot = Format(newPropertyTreeRoot, propertyDocument, cancellationToken); updatedSolution = solution.WithDocumentSyntaxRoot(fieldDocument.Id, newFieldTreeRoot); updatedSolution = updatedSolution.WithDocumentSyntaxRoot(propertyDocument.Id, newPropertyTreeRoot); return(updatedSolution); } }
private async Task DetermineAllSymbolsCoreAsync( SymbolAndProjectId symbolAndProjectId, ConcurrentSet<SymbolAndProjectId> result) { _cancellationToken.ThrowIfCancellationRequested(); var searchSymbolAndProjectId = MapToAppropriateSymbol(symbolAndProjectId); // 2) Try to map this back to source symbol if this was a metadata symbol. var sourceSymbolAndProjectId = await SymbolFinder.FindSourceDefinitionAsync(searchSymbolAndProjectId, _solution, _cancellationToken).ConfigureAwait(false); if (sourceSymbolAndProjectId.Symbol != null) { searchSymbolAndProjectId = sourceSymbolAndProjectId; } var searchSymbol = searchSymbolAndProjectId.Symbol; if (searchSymbol != null && result.Add(searchSymbolAndProjectId)) { await _progress.OnDefinitionFoundAsync(searchSymbolAndProjectId).ConfigureAwait(false); // get project to search var projects = GetProjectScope(); _cancellationToken.ThrowIfCancellationRequested(); List<Task> finderTasks = new List<Task>(); foreach (var f in _finders) { finderTasks.Add(Task.Run(async () => { var symbolTasks = new List<Task>(); var symbols = await f.DetermineCascadedSymbolsAsync( searchSymbolAndProjectId, _solution, projects, _cancellationToken).ConfigureAwait(false); AddSymbolTasks(result, symbols, symbolTasks); // Defer to the language to see if it wants to cascade here in some special way. var symbolProject = _solution.GetProject(searchSymbol.ContainingAssembly); var service = symbolProject?.LanguageServices.GetService<ILanguageServiceReferenceFinder>(); if (service != null) { symbols = await service.DetermineCascadedSymbolsAsync( searchSymbolAndProjectId, symbolProject, _cancellationToken).ConfigureAwait(false); AddSymbolTasks(result, symbols, symbolTasks); } _cancellationToken.ThrowIfCancellationRequested(); await Task.WhenAll(symbolTasks).ConfigureAwait(false); }, _cancellationToken)); } await Task.WhenAll(finderTasks).ConfigureAwait(false); } }
// More complicated forwarding functions. These need to map from the symbols // used by the FAR engine to the INavigableItems used by the streaming FAR // feature. private DefinitionItem GetDefinitionItem(SymbolAndProjectId definition) { return(_definitionToItem.GetOrAdd(definition.Symbol, _definitionFactory)); }
/// <summary> /// Given a symbol, finds the symbol that actually defines the name that we're using. /// </summary> public static async Task<SymbolAndProjectId> FindDefinitionSymbolAsync( SymbolAndProjectId symbolAndProjectId, Solution solution, CancellationToken cancellationToken) { var symbol = symbolAndProjectId.Symbol; Contract.ThrowIfNull(symbol); Contract.ThrowIfNull(solution); // Make sure we're on the original source definition if we can be var foundSymbolAndProjectId = await SymbolFinder.FindSourceDefinitionAsync( symbolAndProjectId, solution, cancellationToken).ConfigureAwait(false); var bestSymbolAndProjectId = foundSymbolAndProjectId.Symbol != null ? foundSymbolAndProjectId : symbolAndProjectId; symbol = bestSymbolAndProjectId.Symbol; // If we're renaming a property, it might be a synthesized property for a method // backing field. if (symbol.Kind == SymbolKind.Parameter) { if (symbol.ContainingSymbol.Kind == SymbolKind.Method) { var containingMethod = (IMethodSymbol)symbol.ContainingSymbol; if (containingMethod.AssociatedSymbol is IPropertySymbol) { var associatedPropertyOrEvent = (IPropertySymbol)containingMethod.AssociatedSymbol; var ordinal = containingMethod.Parameters.IndexOf((IParameterSymbol)symbol); if (ordinal < associatedPropertyOrEvent.Parameters.Length) { return bestSymbolAndProjectId.WithSymbol( associatedPropertyOrEvent.Parameters[ordinal]); } } } } // if we are renaming a compiler generated delegate for an event, cascade to the event if (symbol.Kind == SymbolKind.NamedType) { var typeSymbol = (INamedTypeSymbol)symbol; if (typeSymbol.IsImplicitlyDeclared && typeSymbol.IsDelegateType() && typeSymbol.AssociatedSymbol != null) { return bestSymbolAndProjectId.WithSymbol( typeSymbol.AssociatedSymbol); } } // If we are renaming a constructor or destructor, we wish to rename the whole type if (symbol.Kind == SymbolKind.Method) { var methodSymbol = (IMethodSymbol)symbol; if (methodSymbol.MethodKind == MethodKind.Constructor || methodSymbol.MethodKind == MethodKind.StaticConstructor || methodSymbol.MethodKind == MethodKind.Destructor) { return bestSymbolAndProjectId.WithSymbol( methodSymbol.ContainingType); } } // If we are renaming a backing field for a property, cascade to the property if (symbol.Kind == SymbolKind.Field) { var fieldSymbol = (IFieldSymbol)symbol; if (fieldSymbol.IsImplicitlyDeclared && fieldSymbol.AssociatedSymbol.IsKind(SymbolKind.Property)) { return bestSymbolAndProjectId.WithSymbol( fieldSymbol.AssociatedSymbol); } } // in case this is e.g. an overridden property accessor, we'll treat the property itself as the definition symbol var propertyAndProjectId = await GetPropertyFromAccessorOrAnOverride(bestSymbolAndProjectId, solution, cancellationToken).ConfigureAwait(false); return propertyAndProjectId.Symbol != null ? propertyAndProjectId : bestSymbolAndProjectId; }
public Task OnDefinitionFoundAsync(SymbolAndProjectId definition) => _service.Rpc.InvokeAsync(nameof(OnDefinitionFoundAsync), SerializableSymbolAndProjectId.Dehydrate(definition));
public async Task OnDefinitionFoundAsync(SymbolAndProjectId definition) { var definitionItem = await GetDefinitionItemAsync(definition).ConfigureAwait(false); await _context.OnDefinitionFoundAsync(definitionItem).ConfigureAwait(false); }
public async Task FindBasesAsync(Document document, int position, IFindUsagesContext context) { var cancellationToken = context.CancellationToken; var symbolAndProject = await FindUsagesHelpers.GetRelevantSymbolAndProjectAtPositionAsync( document, position, cancellationToken).ConfigureAwait(false); if (symbolAndProject == null) { await context.ReportMessageAsync( EditorFeaturesResources.Cannot_navigate_to_the_symbol_under_the_caret).ConfigureAwait(false); return; } var symbol = symbolAndProject.Value.symbol; var bases = FindBaseHelpers.FindBases( symbol, symbolAndProject.Value.project, cancellationToken); await context.SetSearchTitleAsync( string.Format(EditorFeaturesResources._0_bases, FindUsagesHelpers.GetDisplayName(symbol))).ConfigureAwait(false); var project = document.Project; var solution = project.Solution; var projectId = project.Id; var found = false; // For each potential base, try to find its definition in sources. // If found, add it's definitionItem to the context. // If not found but the symbol is from metadata, create it's definition item from metadata and add to the context. foreach (var baseSymbol in bases) { var sourceDefinition = await SymbolFinder.FindSourceDefinitionAsync( SymbolAndProjectId.Create(baseSymbol, projectId), solution, cancellationToken).ConfigureAwait(false); if (sourceDefinition.Symbol != null) { var definitionItem = await sourceDefinition.Symbol.ToClassifiedDefinitionItemAsync( solution.GetProject(sourceDefinition.ProjectId), includeHiddenLocations : false, FindReferencesSearchOptions.Default, cancellationToken : cancellationToken) .ConfigureAwait(false); await context.OnDefinitionFoundAsync(definitionItem).ConfigureAwait(false); found = true; } else if (baseSymbol.Locations.Any(l => l.IsInMetadata)) { var definitionItem = baseSymbol.ToNonClassifiedDefinitionItem( project, includeHiddenLocations: true); await context.OnDefinitionFoundAsync(definitionItem).ConfigureAwait(false); found = true; } } if (!found) { await context.ReportMessageAsync(EditorFeaturesResources.The_symbol_has_no_base) .ConfigureAwait(false); } }
public Task OnDefinitionFoundAsync(SymbolAndProjectId definition) => _endPoint.InvokeAsync(nameof(SymbolFinder.FindReferencesServerCallback.OnDefinitionFoundAsync), new object[] { SerializableSymbolAndProjectId.Dehydrate(definition) }, _cancellationToken);
private bool TryCreateUpdatedSolution( ChangeSignatureAnalyzedContext context, ChangeSignatureOptionsResult options, CancellationToken cancellationToken, out Solution updatedSolution) { updatedSolution = context.Solution; var declaredSymbol = context.Symbol; var nodesToUpdate = new Dictionary <DocumentId, List <SyntaxNode> >(); var definitionToUse = new Dictionary <SyntaxNode, ISymbol>(); bool hasLocationsInMetadata = false; var symbols = FindChangeSignatureReferencesAsync( SymbolAndProjectId.Create(declaredSymbol, context.Project.Id), context.Solution, cancellationToken).WaitAndGetResult(cancellationToken); foreach (var symbol in symbols) { if (symbol.Definition.Kind == SymbolKind.Method && ((symbol.Definition as IMethodSymbol).MethodKind == MethodKind.PropertyGet || (symbol.Definition as IMethodSymbol).MethodKind == MethodKind.PropertySet)) { continue; } if (symbol.Definition.Kind == SymbolKind.NamedType) { continue; } if (symbol.Definition.Locations.Any(loc => loc.IsInMetadata)) { hasLocationsInMetadata = true; continue; } var symbolWithSyntacticParameters = symbol.Definition; var symbolWithSemanticParameters = symbol.Definition; var includeDefinitionLocations = true; if (symbol.Definition.Kind == SymbolKind.Field) { includeDefinitionLocations = false; } if (symbolWithSyntacticParameters.Kind == SymbolKind.Event) { var eventSymbol = symbolWithSyntacticParameters as IEventSymbol; var type = eventSymbol.Type as INamedTypeSymbol; if (type != null && type.DelegateInvokeMethod != null) { symbolWithSemanticParameters = type.DelegateInvokeMethod; } else { continue; } } if (symbolWithSyntacticParameters.Kind == SymbolKind.Method) { var methodSymbol = symbolWithSyntacticParameters as IMethodSymbol; if (methodSymbol.MethodKind == MethodKind.DelegateInvoke) { symbolWithSyntacticParameters = methodSymbol.ContainingType; } if (methodSymbol.Name == WellKnownMemberNames.DelegateBeginInvokeName && methodSymbol.ContainingType != null && methodSymbol.ContainingType.IsDelegateType()) { includeDefinitionLocations = false; } } // Find and annotate all the relevant definitions if (includeDefinitionLocations) { foreach (var def in symbolWithSyntacticParameters.Locations) { if (!TryGetNodeWithEditableSignatureOrAttributes(def, updatedSolution, out var nodeToUpdate, out var documentId)) { continue; } if (!nodesToUpdate.ContainsKey(documentId)) { nodesToUpdate.Add(documentId, new List <SyntaxNode>()); } AddUpdatableNodeToDictionaries(nodesToUpdate, documentId, nodeToUpdate, definitionToUse, symbolWithSemanticParameters); } } // Find and annotate all the relevant references foreach (var location in symbol.Locations) { if (location.Location.IsInMetadata) { hasLocationsInMetadata = true; continue; } if (!TryGetNodeWithEditableSignatureOrAttributes(location.Location, updatedSolution, out var nodeToUpdate2, out var documentId2)) { continue; } if (!nodesToUpdate.ContainsKey(documentId2)) { nodesToUpdate.Add(documentId2, new List <SyntaxNode>()); } AddUpdatableNodeToDictionaries(nodesToUpdate, documentId2, nodeToUpdate2, definitionToUse, symbolWithSemanticParameters); } } if (hasLocationsInMetadata) { var notificationService = context.Solution.Workspace.Services.GetService <INotificationService>(); if (!notificationService.ConfirmMessageBox(FeaturesResources.This_symbol_has_related_definitions_or_references_in_metadata_Changing_its_signature_may_result_in_build_errors_Do_you_want_to_continue, severity: NotificationSeverity.Warning)) { return(false); } } // Construct all the relevant syntax trees from the base solution var updatedRoots = new Dictionary <DocumentId, SyntaxNode>(); foreach (var docId in nodesToUpdate.Keys) { var doc = updatedSolution.GetDocument(docId); var updater = doc.Project.LanguageServices.GetService <AbstractChangeSignatureService>(); var root = doc.GetSyntaxRootSynchronously(CancellationToken.None); var nodes = nodesToUpdate[docId]; var newRoot = root.ReplaceNodes(nodes, (originalNode, potentiallyUpdatedNode) => { return(updater.ChangeSignature(doc, definitionToUse[originalNode], potentiallyUpdatedNode, originalNode, CreateCompensatingSignatureChange(definitionToUse[originalNode], options.UpdatedSignature), cancellationToken)); }); var annotatedNodes = newRoot.GetAnnotatedNodes <SyntaxNode>(syntaxAnnotation: changeSignatureFormattingAnnotation); var formattedRoot = Formatter.FormatAsync( newRoot, changeSignatureFormattingAnnotation, doc.Project.Solution.Workspace, options: null, rules: GetFormattingRules(doc), cancellationToken: CancellationToken.None).WaitAndGetResult(CancellationToken.None); updatedRoots[docId] = formattedRoot; } // Update the documents using the updated syntax trees foreach (var docId in nodesToUpdate.Keys) { updatedSolution = updatedSolution.WithDocumentSyntaxRoot(docId, updatedRoots[docId]); } return(true); }
protected virtual Task <ImmutableArray <SymbolAndProjectId> > DetermineCascadedSymbolsAsync( SymbolAndProjectId <TSymbol> symbolAndProject, Solution solution, IImmutableSet <Project> projects, FindReferencesSearchOptions options, CancellationToken cancellationToken) { return(SpecializedTasks.EmptyImmutableArray <SymbolAndProjectId>()); }
public abstract Task <ImmutableArray <FinderLocation> > FindReferencesInDocumentAsync( SymbolAndProjectId symbolAndProjectId, Document document, SemanticModel semanticModel, FindReferencesSearchOptions options, CancellationToken cancellationToken);
public abstract Task <ImmutableArray <SymbolAndProjectId> > DetermineCascadedSymbolsAsync( SymbolAndProjectId symbolAndProject, Solution solution, IImmutableSet <Project> projects, FindReferencesSearchOptions options, CancellationToken cancellationToken);
private static async Task<SearchResult> AddLocationsReferenceSymbolsAsync( SymbolAndProjectId symbolAndProjectId, Solution solution, CancellationToken cancellationToken) { var symbol = symbolAndProjectId.Symbol; var locations = new HashSet<RenameLocation>(); var referenceSymbols = await SymbolFinder.FindRenamableReferencesAsync( symbolAndProjectId, solution, cancellationToken).ConfigureAwait(false); foreach (var referencedSymbol in referenceSymbols) { locations.AddAll( await ReferenceProcessing.GetRenamableDefinitionLocationsAsync(referencedSymbol.Definition, symbol, solution, cancellationToken).ConfigureAwait(false)); locations.AddAll( await referencedSymbol.Locations.SelectManyAsync<ReferenceLocation, RenameLocation>( (l, c) => ReferenceProcessing.GetRenamableReferenceLocationsAsync(referencedSymbol.Definition, symbol, l, solution, c), cancellationToken).ConfigureAwait(false)); } var implicitLocations = referenceSymbols.SelectMany(refSym => refSym.Locations).Where(loc => loc.IsImplicit).ToList(); var referencedSymbols = referenceSymbols.Select(r => r.DefinitionAndProjectId).Where(r => !r.Symbol.Equals(symbol)).ToList(); return new SearchResult(locations, implicitLocations, referencedSymbols); }
protected override async Task UpdateAsync(CommandArrayInfo ainfo, CancellationToken cancelToken) { var doc = IdeApp.Workbench.ActiveDocument; if (doc == null || doc.FileName == FilePath.Null || doc.AnalysisDocument == null) { return; } var semanticModel = await doc.AnalysisDocument.GetSemanticModelAsync(cancelToken); if (semanticModel == null) { return; } var info = await RefactoringSymbolInfo.GetSymbolInfoAsync(doc, doc.Editor); bool added = false; var ext = doc.GetContent <CodeActionEditorExtension> (); var ciset = new CommandInfoSet(); ciset.Text = GettextCatalog.GetString("Refactor"); bool canRename = RenameHandler.CanRename(info.Symbol ?? info.DeclaredSymbol); if (canRename) { ciset.CommandInfos.Add(IdeApp.CommandService.GetCommandInfo(MonoDevelop.Ide.Commands.EditCommands.Rename), new Action(async delegate { await new MonoDevelop.Refactoring.Rename.RenameRefactoring().Rename(info.Symbol ?? info.DeclaredSymbol); })); added = true; } bool first = true; if (ciset.CommandInfos.Count > 0) { ainfo.Add(ciset, null); added = true; } var gotoDeclarationSymbol = info.Symbol; if (gotoDeclarationSymbol == null && info.DeclaredSymbol != null && info.DeclaredSymbol.Locations.Length > 1) { gotoDeclarationSymbol = info.DeclaredSymbol; } if (IdeApp.ProjectOperations.CanJumpToDeclaration(gotoDeclarationSymbol) || gotoDeclarationSymbol == null && IdeApp.ProjectOperations.CanJumpToDeclaration(info.CandidateSymbols.FirstOrDefault())) { var type = (gotoDeclarationSymbol ?? info.CandidateSymbols.FirstOrDefault()) as INamedTypeSymbol; if (type != null && type.Locations.Length > 1) { var declSet = new CommandInfoSet(); declSet.Text = GettextCatalog.GetString("_Go to Declaration"); foreach (var part in type.Locations) { var loc = part.GetLineSpan(); declSet.CommandInfos.Add(string.Format(GettextCatalog.GetString("{0}, Line {1}"), FormatFileName(part.SourceTree.FilePath), loc.StartLinePosition.Line + 1), new Action(() => IdeApp.ProjectOperations.JumpTo(type, part, doc.Project))); } ainfo.Add(declSet); } else { ainfo.Add(IdeApp.CommandService.GetCommandInfo(RefactoryCommands.GotoDeclaration), new Action(() => GotoDeclarationHandler.Run(doc))); } added = true; } if (info.DeclaredSymbol != null && GotoBaseDeclarationHandler.CanGotoBase(info.DeclaredSymbol)) { ainfo.Add(GotoBaseDeclarationHandler.GetDescription(info.DeclaredSymbol), new Action(() => GotoBaseDeclarationHandler.GotoBase(doc, info.DeclaredSymbol).Ignore())); added = true; } var sym = info.Symbol ?? info.DeclaredSymbol; if (doc.HasProject && sym != null) { ainfo.Add(IdeApp.CommandService.GetCommandInfo(RefactoryCommands.FindReferences), new System.Action(() => { if (sym.Kind == SymbolKind.Local || sym.Kind == SymbolKind.Parameter || sym.Kind == SymbolKind.TypeParameter) { FindReferencesHandler.FindRefs(new [] { SymbolAndProjectId.Create(sym, doc.AnalysisDocument.Project.Id) }, doc.AnalysisDocument.Project.Solution).Ignore(); } else { RefactoringService.FindReferencesAsync(FindReferencesHandler.FilterSymbolForFindReferences(sym).GetDocumentationCommentId()).Ignore(); } })); try { if (Microsoft.CodeAnalysis.FindSymbols.SymbolFinder.FindSimilarSymbols(sym, semanticModel.Compilation).Count() > 1) { ainfo.Add(IdeApp.CommandService.GetCommandInfo(RefactoryCommands.FindAllReferences), new System.Action(() => RefactoringService.FindAllReferencesAsync(FindReferencesHandler.FilterSymbolForFindReferences(sym).GetDocumentationCommentId()))); } } catch (Exception) { // silently ignore roslyn bug. } } added = true; }
private async Task <Solution> ProcessResult(CodeFixContext context, Diagnostic diagnostic, CancellationToken cancellationToken) { var locations = diagnostic.AdditionalLocations; var propertyLocation = locations[0]; var declaratorLocation = locations[1]; var declarator = declaratorLocation.FindToken(cancellationToken).Parent.FirstAncestorOrSelf <TVariableDeclarator>(); var fieldDocument = context.Document.Project.GetDocument(declarator.SyntaxTree); var fieldSemanticModel = await fieldDocument.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); var fieldSymbol = (IFieldSymbol)fieldSemanticModel.GetDeclaredSymbol(declarator); var property = propertyLocation.FindToken(cancellationToken).Parent.FirstAncestorOrSelf <TPropertyDeclaration>(); var propertyDocument = context.Document.Project.GetDocument(property.SyntaxTree); var propertySemanticModel = await propertyDocument.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); var propertySymbol = (IPropertySymbol)propertySemanticModel.GetDeclaredSymbol(property); Debug.Assert(fieldDocument.Project == propertyDocument.Project); var project = fieldDocument.Project; var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false); var solution = context.Document.Project.Solution; var fieldLocations = await Renamer.GetRenameLocationsAsync( solution, SymbolAndProjectId.Create(fieldSymbol, fieldDocument.Project.Id), solution.Options, cancellationToken).ConfigureAwait(false); // First, create the updated property we want to replace the old property with var isWrittenToOutsideOfConstructor = IsWrittenToOutsideOfConstructorOrProperty(fieldSymbol, fieldLocations, property, cancellationToken); var updatedProperty = await UpdatePropertyAsync(propertyDocument, compilation, fieldSymbol, propertySymbol, property, isWrittenToOutsideOfConstructor, cancellationToken).ConfigureAwait(false); // Now, rename all usages of the field to point at the property. Except don't actually // rename the field itself. We want to be able to find it again post rename. var updatedSolution = await Renamer.RenameAsync(fieldLocations, propertySymbol.Name, location => !location.SourceSpan.IntersectsWith(declaratorLocation.SourceSpan), symbols => HasConflict(symbols, propertySymbol, compilation, cancellationToken), cancellationToken).ConfigureAwait(false); solution = updatedSolution; // Now find the field and property again post rename. fieldDocument = solution.GetDocument(fieldDocument.Id); propertyDocument = solution.GetDocument(propertyDocument.Id); Debug.Assert(fieldDocument.Project == propertyDocument.Project); compilation = await fieldDocument.Project.GetCompilationAsync(cancellationToken).ConfigureAwait(false); fieldSymbol = (IFieldSymbol)fieldSymbol.GetSymbolKey().Resolve(compilation, cancellationToken: cancellationToken).Symbol; propertySymbol = (IPropertySymbol)propertySymbol.GetSymbolKey().Resolve(compilation, cancellationToken: cancellationToken).Symbol; Debug.Assert(fieldSymbol != null && propertySymbol != null); declarator = (TVariableDeclarator)await fieldSymbol.DeclaringSyntaxReferences[0].GetSyntaxAsync(cancellationToken).ConfigureAwait(false); var temp = await propertySymbol.DeclaringSyntaxReferences[0].GetSyntaxAsync(cancellationToken).ConfigureAwait(false); property = temp.FirstAncestorOrSelf <TPropertyDeclaration>(); var nodeToRemove = GetNodeToRemove(declarator); const SyntaxRemoveOptions options = SyntaxRemoveOptions.KeepUnbalancedDirectives | SyntaxRemoveOptions.AddElasticMarker; if (fieldDocument == propertyDocument) { // Same file. Have to do this in a slightly complicated fashion. var declaratorTreeRoot = await fieldDocument.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var editor = new SyntaxEditor(declaratorTreeRoot, fieldDocument.Project.Solution.Workspace); editor.RemoveNode(nodeToRemove, options); editor.ReplaceNode(property, updatedProperty); var newRoot = editor.GetChangedRoot(); newRoot = await FormatAsync(newRoot, fieldDocument, cancellationToken).ConfigureAwait(false); return(solution.WithDocumentSyntaxRoot( fieldDocument.Id, newRoot)); } else { // In different files. Just update both files. var fieldTreeRoot = await fieldDocument.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var propertyTreeRoot = await propertyDocument.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var newFieldTreeRoot = fieldTreeRoot.RemoveNode(nodeToRemove, options); var newPropertyTreeRoot = propertyTreeRoot.ReplaceNode(property, updatedProperty); newFieldTreeRoot = await FormatAsync(newFieldTreeRoot, fieldDocument, cancellationToken).ConfigureAwait(false); newPropertyTreeRoot = await FormatAsync(newPropertyTreeRoot, propertyDocument, cancellationToken).ConfigureAwait(false); updatedSolution = solution.WithDocumentSyntaxRoot(fieldDocument.Id, newFieldTreeRoot); updatedSolution = updatedSolution.WithDocumentSyntaxRoot(propertyDocument.Id, newPropertyTreeRoot); return(updatedSolution); } }
public abstract Task <ImmutableArray <ReferenceLocation> > FindReferencesInDocumentAsync(SymbolAndProjectId symbolAndProjectId, Document document, CancellationToken cancellationToken);
internal static async Task<SymbolAndProjectId> GetPropertyFromAccessorOrAnOverride( SymbolAndProjectId symbolAndProjectId, Solution solution, CancellationToken cancellationToken) { var symbol = symbolAndProjectId.Symbol; if (symbol.IsPropertyAccessor()) { return symbolAndProjectId.WithSymbol( ((IMethodSymbol)symbol).AssociatedSymbol); } if (symbol.IsOverride && symbol.OverriddenMember() != null) { var originalSourceSymbol = await SymbolFinder.FindSourceDefinitionAsync( symbolAndProjectId.WithSymbol(symbol.OverriddenMember()), solution, cancellationToken).ConfigureAwait(false); if (originalSourceSymbol.Symbol != null) { return await GetPropertyFromAccessorOrAnOverride(originalSourceSymbol, solution, cancellationToken).ConfigureAwait(false); } } if (symbol.Kind == SymbolKind.Method && symbol.ContainingType.TypeKind == TypeKind.Interface) { var methodImplementors = await SymbolFinder.FindImplementationsAsync( symbolAndProjectId, solution, cancellationToken: cancellationToken).ConfigureAwait(false); foreach (var methodImplementor in methodImplementors) { var propertyAccessorOrAnOverride = await GetPropertyFromAccessorOrAnOverride(methodImplementor, solution, cancellationToken).ConfigureAwait(false); if (propertyAccessorOrAnOverride.Symbol != null) { return propertyAccessorOrAnOverride; } } } return default(SymbolAndProjectId); }
public Task OnDefinitionFoundAsync(SymbolAndProjectId definition) => _service.InvokeAsync(nameof(OnDefinitionFoundAsync), new object[] { SerializableSymbolAndProjectId.Dehydrate(definition) }, _cancellationToken);
/// <summary> /// Given a symbol, finds the symbol that actually defines the name that we're using. /// </summary> public static async Task <SymbolAndProjectId> FindDefinitionSymbolAsync( SymbolAndProjectId symbolAndProjectId, Solution solution, CancellationToken cancellationToken) { var symbol = symbolAndProjectId.Symbol; Contract.ThrowIfNull(symbol); Contract.ThrowIfNull(solution); // Make sure we're on the original source definition if we can be var foundSymbolAndProjectId = await SymbolFinder.FindSourceDefinitionAsync( symbolAndProjectId, solution, cancellationToken).ConfigureAwait(false); var bestSymbolAndProjectId = foundSymbolAndProjectId.Symbol != null ? foundSymbolAndProjectId : symbolAndProjectId; symbol = bestSymbolAndProjectId.Symbol; // If we're renaming a property, it might be a synthesized property for a method // backing field. if (symbol.Kind == SymbolKind.Parameter) { if (symbol.ContainingSymbol.Kind == SymbolKind.Method) { var containingMethod = (IMethodSymbol)symbol.ContainingSymbol; if (containingMethod.AssociatedSymbol is IPropertySymbol) { var associatedPropertyOrEvent = (IPropertySymbol)containingMethod.AssociatedSymbol; var ordinal = containingMethod.Parameters.IndexOf((IParameterSymbol)symbol); if (ordinal < associatedPropertyOrEvent.Parameters.Length) { return(bestSymbolAndProjectId.WithSymbol( associatedPropertyOrEvent.Parameters[ordinal])); } } } } // if we are renaming a compiler generated delegate for an event, cascade to the event if (symbol.Kind == SymbolKind.NamedType) { var typeSymbol = (INamedTypeSymbol)symbol; if (typeSymbol.IsImplicitlyDeclared && typeSymbol.IsDelegateType() && typeSymbol.AssociatedSymbol != null) { return(bestSymbolAndProjectId.WithSymbol( typeSymbol.AssociatedSymbol)); } } // If we are renaming a constructor or destructor, we wish to rename the whole type if (symbol.Kind == SymbolKind.Method) { var methodSymbol = (IMethodSymbol)symbol; if (methodSymbol.MethodKind == MethodKind.Constructor || methodSymbol.MethodKind == MethodKind.StaticConstructor || methodSymbol.MethodKind == MethodKind.Destructor) { return(bestSymbolAndProjectId.WithSymbol( methodSymbol.ContainingType)); } } // If we are renaming a backing field for a property, cascade to the property if (symbol.Kind == SymbolKind.Field) { var fieldSymbol = (IFieldSymbol)symbol; if (fieldSymbol.IsImplicitlyDeclared && fieldSymbol.AssociatedSymbol.IsKind(SymbolKind.Property)) { return(bestSymbolAndProjectId.WithSymbol( fieldSymbol.AssociatedSymbol)); } } // in case this is e.g. an overridden property accessor, we'll treat the property itself as the definition symbol var propertyAndProjectId = await GetPropertyFromAccessorOrAnOverride(bestSymbolAndProjectId, solution, cancellationToken).ConfigureAwait(false); return(propertyAndProjectId.Symbol != null ? propertyAndProjectId : bestSymbolAndProjectId); }
private async Task<ConcurrentSet<SymbolAndProjectId>> DetermineAllSymbolsAsync( SymbolAndProjectId symbolAndProjectId) { using (Logger.LogBlock(FunctionId.FindReference_DetermineAllSymbolsAsync, _cancellationToken)) { var result = new ConcurrentSet<SymbolAndProjectId>( new SymbolAndProjectIdComparer(MetadataUnifyingEquivalenceComparer.Instance)); await DetermineAllSymbolsCoreAsync(symbolAndProjectId, result).ConfigureAwait(false); return result; } }
public Task OnDefinitionFoundAsync(SymbolAndProjectId definition) { return(_context.OnDefinitionFoundAsync(GetDefinitionItem(definition))); }
private static SymbolAndProjectId MapToAppropriateSymbol( SymbolAndProjectId symbolAndProjectId) { // Never search for an alias. Always search for it's target. Note: if the caller was // actually searching for an alias, they can always get that information out in the end // by checking the ReferenceLocations that are returned. var symbol = symbolAndProjectId.Symbol; var searchSymbol = symbol; if (searchSymbol is IAliasSymbol) { searchSymbol = ((IAliasSymbol)searchSymbol).Target; } searchSymbol = searchSymbol.GetOriginalUnreducedDefinition(); // If they're searching for a delegate constructor, then just search for the delegate // itself. They're practically interchangeable for consumers. if (searchSymbol.IsConstructor() && searchSymbol.ContainingType.TypeKind == TypeKind.Delegate) { searchSymbol = symbol.ContainingType; } return symbolAndProjectId.WithSymbol(searchSymbol); }
/// <summary> /// Returns the corresponding symbol in this type or a base type that implements /// interfaceMember (either implicitly or explicitly), or null if no such symbol exists /// (which might be either because this type doesn't implement the container of /// interfaceMember, or this type doesn't supply a member that successfully implements /// interfaceMember). /// </summary> public static IEnumerable <SymbolAndProjectId> FindImplementationsForInterfaceMember( this SymbolAndProjectId <ITypeSymbol> typeSymbolAndProjectId, ISymbol interfaceMember, Workspace workspace, CancellationToken cancellationToken) { // This method can return multiple results. Consider the case of: // // interface IFoo<X> { void Foo(X x); } // // class C : IFoo<int>, IFoo<string> { void Foo(int x); void Foo(string x); } // // If you're looking for the implementations of IFoo<X>.Foo then you want to find both // results in C. // TODO(cyrusn): Implement this using the actual code for // TypeSymbol.FindImplementationForInterfaceMember var typeSymbol = typeSymbolAndProjectId.Symbol; if (typeSymbol == null || interfaceMember == null) { yield break; } if (interfaceMember.Kind != SymbolKind.Event && interfaceMember.Kind != SymbolKind.Method && interfaceMember.Kind != SymbolKind.Property) { yield break; } // WorkItem(4843) // // 'typeSymbol' has to at least implement the interface containing the member. note: // this just means that the interface shows up *somewhere* in the inheritance chain of // this type. However, this type may not actually say that it implements it. For // example: // // interface I { void Foo(); } // // class B { } // // class C : B, I { } // // class D : C { } // // D does implement I transitively through C. However, even if D has a "Foo" method, it // won't be an implementation of I.Foo. The implementation of I.Foo must be from a type // that actually has I in it's direct interface chain, or a type that's a base type of // that. in this case, that means only classes C or B. var interfaceType = interfaceMember.ContainingType; if (!typeSymbol.ImplementsIgnoringConstruction(interfaceType)) { yield break; } // We've ascertained that the type T implements some constructed type of the form I<X>. // However, we're not precisely sure which constructions of I<X> are being used. For // example, a type C might implement I<int> and I<string>. If we're searching for a // method from I<X> we might need to find several methods that implement different // instantiations of that method. var originalInterfaceType = interfaceMember.ContainingType.OriginalDefinition; var originalInterfaceMember = interfaceMember.OriginalDefinition; var constructedInterfaces = typeSymbol.AllInterfaces.Where(i => SymbolEquivalenceComparer.Instance.Equals(i.OriginalDefinition, originalInterfaceType)); foreach (var constructedInterface in constructedInterfaces) { cancellationToken.ThrowIfCancellationRequested(); var constructedInterfaceMember = constructedInterface.GetMembers().FirstOrDefault(m => SymbolEquivalenceComparer.Instance.Equals(m.OriginalDefinition, originalInterfaceMember)); if (constructedInterfaceMember == null) { continue; } // Now we need to walk the base type chain, but we start at the first type that actually // has the interface directly in its interface hierarchy. var seenTypeDeclaringInterface = false; for (var currentType = typeSymbol; currentType != null; currentType = currentType.BaseType) { seenTypeDeclaringInterface = seenTypeDeclaringInterface || currentType.GetOriginalInterfacesAndTheirBaseInterfaces().Contains(interfaceType.OriginalDefinition); if (seenTypeDeclaringInterface) { var result = constructedInterfaceMember.TypeSwitch( (IEventSymbol eventSymbol) => FindImplementations(currentType, eventSymbol, workspace, e => e.ExplicitInterfaceImplementations), (IMethodSymbol methodSymbol) => FindImplementations(currentType, methodSymbol, workspace, m => m.ExplicitInterfaceImplementations), (IPropertySymbol propertySymbol) => FindImplementations(currentType, propertySymbol, workspace, p => p.ExplicitInterfaceImplementations)); if (result != null) { yield return(typeSymbolAndProjectId.WithSymbol(result)); break; } } } } }
public static async Task <ImmutableArray <SymbolAndProjectId> > FindImplementationsForInterfaceMemberAsync( this SymbolAndProjectId <ITypeSymbol> typeSymbolAndProjectId, SymbolAndProjectId interfaceMemberAndProjectId, Solution solution, CancellationToken cancellationToken) { // This method can return multiple results. Consider the case of: // // interface IGoo<X> { void Goo(X x); } // // class C : IGoo<int>, IGoo<string> { void Goo(int x); void Goo(string x); } // // If you're looking for the implementations of IGoo<X>.Goo then you want to find both // results in C. var arrBuilder = ArrayBuilder <SymbolAndProjectId> .GetInstance(); var interfaceMember = interfaceMemberAndProjectId.Symbol; // TODO(cyrusn): Implement this using the actual code for // TypeSymbol.FindImplementationForInterfaceMember var typeSymbol = typeSymbolAndProjectId.Symbol; if (typeSymbol == null || interfaceMember == null) { return(arrBuilder.ToImmutableAndFree()); } if (interfaceMember.Kind != SymbolKind.Event && interfaceMember.Kind != SymbolKind.Method && interfaceMember.Kind != SymbolKind.Property) { return(arrBuilder.ToImmutableAndFree()); } // WorkItem(4843) // // 'typeSymbol' has to at least implement the interface containing the member. note: // this just means that the interface shows up *somewhere* in the inheritance chain of // this type. However, this type may not actually say that it implements it. For // example: // // interface I { void Goo(); } // // class B { } // // class C : B, I { } // // class D : C { } // // D does implement I transitively through C. However, even if D has a "Goo" method, it // won't be an implementation of I.Goo. The implementation of I.Goo must be from a type // that actually has I in it's direct interface chain, or a type that's a base type of // that. in this case, that means only classes C or B. var interfaceType = interfaceMember.ContainingType; if (!typeSymbol.ImplementsIgnoringConstruction(interfaceType)) { return(arrBuilder.ToImmutableAndFree()); } // We've ascertained that the type T implements some constructed type of the form I<X>. // However, we're not precisely sure which constructions of I<X> are being used. For // example, a type C might implement I<int> and I<string>. If we're searching for a // method from I<X> we might need to find several methods that implement different // instantiations of that method. var originalInterfaceType = interfaceMember.ContainingType.OriginalDefinition; var originalInterfaceMember = interfaceMember.OriginalDefinition; var constructedInterfaces = typeSymbol.AllInterfaces.Where(i => SymbolEquivalenceComparer.Instance.Equals(i.OriginalDefinition, originalInterfaceType)); // Try to get the compilation for the symbol we're searching for, // which can help identify matches with the call to SymbolFinder.OriginalSymbolsMatch. // OriginalSymbolMatch allows types to be matched across different assemblies // if they are considered to be the same type, which provides a more accurate // implementations list for interfaces. var typeSymbolProject = solution.GetProject(typeSymbolAndProjectId.ProjectId); var interfaceMemberProject = solution.GetProject(interfaceMemberAndProjectId.ProjectId); var typeSymbolCompilation = await GetCompilationOrNullAsync(typeSymbolProject, cancellationToken).ConfigureAwait(false); var interfaceMemberCompilation = await GetCompilationOrNullAsync(interfaceMemberProject, cancellationToken).ConfigureAwait(false); foreach (var constructedInterface in constructedInterfaces) { cancellationToken.ThrowIfCancellationRequested(); var constructedInterfaceMember = constructedInterface.GetMembers().FirstOrDefault(typeSymbol => SymbolFinder.OriginalSymbolsMatch( typeSymbol, interfaceMember, solution, typeSymbolCompilation, interfaceMemberCompilation, cancellationToken)); if (constructedInterfaceMember == null) { continue; } // Now we need to walk the base type chain, but we start at the first type that actually // has the interface directly in its interface hierarchy. var seenTypeDeclaringInterface = false; for (ITypeSymbol?currentType = typeSymbol; currentType != null; currentType = currentType.BaseType) { seenTypeDeclaringInterface = seenTypeDeclaringInterface || currentType.GetOriginalInterfacesAndTheirBaseInterfaces().Contains(interfaceType.OriginalDefinition); if (seenTypeDeclaringInterface) { var result = currentType.FindImplementations(constructedInterfaceMember, solution.Workspace); if (result != null) { arrBuilder.Add(typeSymbolAndProjectId.WithSymbol(result)); break; } } } } return(arrBuilder.ToImmutableAndFree());
internal static IEnumerable<SymbolAndProjectId> GetOverloadedSymbols( SymbolAndProjectId symbolAndProjectId) { var symbol = symbolAndProjectId.Symbol; if (symbol is IMethodSymbol) { var containingType = symbol.ContainingType; if (containingType.Kind == SymbolKind.NamedType) { foreach (var member in containingType.GetMembers()) { if (string.Equals(member.MetadataName, symbol.MetadataName, StringComparison.Ordinal) && member is IMethodSymbol && !member.Equals(symbol)) { yield return symbolAndProjectId.WithSymbol(member); } } } } }
public abstract Task <ImmutableArray <SymbolAndProjectId> > DetermineCascadedSymbolsFromDelegateInvoke( SymbolAndProjectId <IMethodSymbol> symbolAndProjectId, Document document, CancellationToken cancellationToken);
internal static Task <Solution> RenameSymbolAsync( Solution solution, SymbolAndProjectId symbolAndProjectId, string newName, OptionSet optionSet, CancellationToken cancellationToken = default) { return(RenameSymbolAsync(solution, symbolAndProjectId, newName, optionSet, nonConflictSymbols: null, cancellationToken)); }
public Task<ImmutableArray<ReferenceLocation>> FindReferencesInDocumentAsync( SymbolAndProjectId symbolAndProjectId, Document document, CancellationToken cancellationToken = default(CancellationToken)) { return SpecializedTasks.EmptyImmutableArray<ReferenceLocation>(); }
private Task HandleLocationAsync(SymbolAndProjectId symbolAndProjectId, ReferenceLocation location) { return(_progress.OnReferenceFoundAsync(symbolAndProjectId, location)); }