/// <summary> /// Attempts to find all the locations to rename. Will not cross any process boundaries to do this. /// </summary> public static async Task <HeavyweightRenameLocations> FindLocationsInCurrentProcessAsync( ISymbol symbol, Solution solution, SymbolRenameOptions options, CodeCleanupOptionsProvider cleanupOptions, CancellationToken cancellationToken) { Contract.ThrowIfNull(symbol); using (Logger.LogBlock(FunctionId.Rename_AllRenameLocations, cancellationToken)) { symbol = await RenameUtilities.FindDefinitionSymbolAsync(symbol, solution, cancellationToken).ConfigureAwait(false); // First, find the direct references just to the symbol being renamed. var originalSymbolResult = await AddLocationsReferenceSymbolsAsync(symbol, solution, cancellationToken).ConfigureAwait(false); // Next, find references to overloads, if the user has asked to rename those as well. var overloadsResult = options.RenameOverloads ? await GetOverloadsAsync(symbol, solution, cancellationToken).ConfigureAwait(false) : ImmutableArray <SearchResult> .Empty; // Finally, include strings/comments if that's what the user wants. var(strings, comments) = await ReferenceProcessing.GetRenamableLocationsInStringsAndCommentsAsync( symbol, solution, originalSymbolResult.Locations, options.RenameInStrings, options.RenameInComments, cancellationToken).ConfigureAwait(false); var mergedLocations = ImmutableHashSet.CreateBuilder <RenameLocation>(); using var _1 = ArrayBuilder <ISymbol> .GetInstance(out var mergedReferencedSymbols); using var _2 = ArrayBuilder <ReferenceLocation> .GetInstance(out var mergedImplicitLocations); var renameMethodGroupReferences = options.RenameOverloads || !RenameUtilities.GetOverloadedSymbols(symbol).Any(); foreach (var result in overloadsResult.Concat(originalSymbolResult)) { mergedLocations.AddRange(renameMethodGroupReferences ? result.Locations : result.Locations.Where(x => x.CandidateReason != CandidateReason.MemberGroup)); mergedImplicitLocations.AddRange(result.ImplicitLocations); mergedReferencedSymbols.AddRange(result.ReferencedSymbols); } // Add string and comment locations to the merged hashset // after adding in reference symbols. This allows any references // in comments to be resolved as proper references rather than // comment resolutions. See https://github.com/dotnet/roslyn/issues/54294 mergedLocations.AddRange(strings.NullToEmpty()); mergedLocations.AddRange(comments.NullToEmpty()); return(new HeavyweightRenameLocations( symbol, solution, options, cleanupOptions, mergedLocations.ToImmutable(), mergedImplicitLocations.ToImmutable(), mergedReferencedSymbols.ToImmutable())); } }
private static async Task <ImmutableArray <SearchResult> > GetOverloadsAsync( ISymbol symbol, Solution solution, CancellationToken cancellationToken) { using var _ = ArrayBuilder <SearchResult> .GetInstance(out var overloadsResult); foreach (var overloadedSymbol in RenameUtilities.GetOverloadedSymbols(symbol)) { overloadsResult.Add(await AddLocationsReferenceSymbolsAsync(overloadedSymbol, solution, cancellationToken).ConfigureAwait(false)); } return(overloadsResult.ToImmutable()); }
internal static async Task<(ImmutableArray<RenameLocation>, ImmutableArray<RenameLocation>)> GetRenamableLocationsInStringsAndCommentsAsync( ISymbol originalSymbol, Solution solution, ISet<RenameLocation> renameLocations, bool renameInStrings, bool renameInComments, CancellationToken cancellationToken) { if (!renameInStrings && !renameInComments) return default; var renameText = originalSymbol.Name; using var _1 = ArrayBuilder<RenameLocation>.GetInstance(out var stringLocations); using var _2 = ArrayBuilder<RenameLocation>.GetInstance(out var commentLocations); foreach (var documentsGroupedByLanguage in RenameUtilities.GetDocumentsAffectedByRename(originalSymbol, solution, renameLocations).GroupBy(d => d.Project.Language)) { var syntaxFactsLanguageService = solution.Workspace.Services.GetLanguageServices(documentsGroupedByLanguage.Key).GetService<ISyntaxFactsService>(); if (syntaxFactsLanguageService != null) { foreach (var document in documentsGroupedByLanguage) { if (renameInStrings) { await AddLocationsToRenameInStringsAsync( document, renameText, syntaxFactsLanguageService, stringLocations, cancellationToken).ConfigureAwait(false); } if (renameInComments) { await AddLocationsToRenameInCommentsAsync(document, renameText, commentLocations, cancellationToken).ConfigureAwait(false); } } } } return (renameInStrings ? stringLocations.ToImmutable() : default,
internal static async Task <Tuple <IEnumerable <RenameLocation>, IEnumerable <RenameLocation> > > GetRenamableLocationsInStringsAndCommentsAsync( ISymbol originalSymbol, Solution solution, ISet <RenameLocation> renameLocations, bool renameInStrings, bool renameInComments, CancellationToken cancellationToken) { if (!renameInStrings && !renameInComments) { return(new Tuple <IEnumerable <RenameLocation>, IEnumerable <RenameLocation> >(null, null)); } var renameText = originalSymbol.Name; List <RenameLocation> stringLocations = renameInStrings ? new List <RenameLocation>() : null; List <RenameLocation> commentLocations = renameInComments ? new List <RenameLocation>() : null; foreach (var documentsGroupedByLanguage in RenameUtilities.GetDocumentsAffectedByRename(originalSymbol, solution, renameLocations).GroupBy(d => d.Project.Language)) { var syntaxFactsLanguageService = solution.Workspace.Services.GetLanguageServices(documentsGroupedByLanguage.Key).GetService <ISyntaxFactsService>(); foreach (var document in documentsGroupedByLanguage) { if (renameInStrings) { await AddLocationsToRenameInStringsAsync(document, renameText, syntaxFactsLanguageService, stringLocations, cancellationToken).ConfigureAwait(false); } if (renameInComments) { await AddLocationsToRenameInCommentsAsync(document, renameText, commentLocations, cancellationToken).ConfigureAwait(false); } } } return(new Tuple <IEnumerable <RenameLocation>, IEnumerable <RenameLocation> >(stringLocations, commentLocations)); }
/// <summary> /// Given a symbol, finds the symbol that actually defines the name that we're using. /// </summary> public static async Task <ISymbol> FindDefinitionSymbolAsync( ISymbol symbol, Solution solution, CancellationToken cancellationToken) { Contract.ThrowIfNull(symbol); Contract.ThrowIfNull(solution); // Make sure we're on the original source definition if we can be var foundSymbol = await SymbolFinder.FindSourceDefinitionAsync( symbol, solution, cancellationToken).ConfigureAwait(false); var bestSymbol = foundSymbol ?? symbol; symbol = bestSymbol; // 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(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(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 is MethodKind.Constructor or MethodKind.StaticConstructor or MethodKind.Destructor) { return(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(fieldSymbol.AssociatedSymbol); } } // in case this is e.g. an overridden property accessor, we'll treat the property itself as the definition symbol var property = await RenameUtilities.TryGetPropertyFromAccessorOrAnOverrideAsync(bestSymbol, solution, cancellationToken).ConfigureAwait(false); return(property ?? bestSymbol); }