private static void AddConflictingSymbolLocations(IEnumerable <ISymbol> conflictingSymbols, ConflictResolution conflictResolution, IDictionary <Location, Location> reverseMappedLocations) { foreach (var newSymbol in conflictingSymbols) { foreach (var newLocation in newSymbol.Locations) { if (newLocation.IsInSource) { if (reverseMappedLocations.TryGetValue(newLocation, out var oldLocation)) { conflictResolution.AddOrReplaceRelatedLocation(new RelatedLocation(oldLocation.SourceSpan, conflictResolution.OldSolution.GetDocument(oldLocation.SourceTree).Id, RelatedLocationType.UnresolvableConflict)); } } } } }
private static async Task AddImplicitConflictsAsync( ISymbol renamedSymbol, ISymbol originalSymbol, IEnumerable <ReferenceLocation> implicitReferenceLocations, SemanticModel semanticModel, Location originalDeclarationLocation, int newDeclarationLocationStartingPosition, ConflictResolution conflictResolution, CancellationToken cancellationToken) { { var renameRewriterService = conflictResolution.NewSolution.Workspace.Services.GetLanguageServices(renamedSymbol.Language).GetService <IRenameRewriterLanguageService>(); var implicitUsageConflicts = renameRewriterService.ComputePossibleImplicitUsageConflicts(renamedSymbol, semanticModel, originalDeclarationLocation, newDeclarationLocationStartingPosition, cancellationToken); foreach (var implicitUsageConflict in implicitUsageConflicts) { conflictResolution.AddOrReplaceRelatedLocation(new RelatedLocation(implicitUsageConflict.SourceSpan, conflictResolution.OldSolution.GetDocument(implicitUsageConflict.SourceTree).Id, RelatedLocationType.UnresolvableConflict)); } } if (implicitReferenceLocations.IsEmpty()) { return; } foreach (var implicitReferenceLocationsPerLanguage in implicitReferenceLocations.GroupBy(loc => loc.Document.Project.Language)) { // the location of the implicit reference defines the language rules to check. // E.g. foreach in C# using a MoveNext in VB that is renamed to MOVENEXT (within VB) var renameRewriterService = implicitReferenceLocationsPerLanguage.First().Document.Project.LanguageServices.GetService <IRenameRewriterLanguageService>(); var implicitConflicts = await renameRewriterService.ComputeImplicitReferenceConflictsAsync( originalSymbol, renamedSymbol, implicitReferenceLocationsPerLanguage, cancellationToken).ConfigureAwait(false); foreach (var implicitConflict in implicitConflicts) { conflictResolution.AddRelatedLocation(new RelatedLocation(implicitConflict.SourceSpan, conflictResolution.OldSolution.GetDocument(implicitConflict.SourceTree).Id, RelatedLocationType.UnresolvableConflict)); } } }
/// <summary> /// Computes an adds conflicts relating to declarations, which are independent of /// location-based checks. Examples of these types of conflicts include renaming a member to /// the same name as another member of a type: binding doesn't change (at least from the /// perspective of find all references), but we still need to track it. /// </summary> internal static async Task AddDeclarationConflictsAsync( ISymbol renamedSymbol, ISymbol renameSymbol, IEnumerable <SymbolAndProjectId> referencedSymbols, ConflictResolution conflictResolution, IDictionary <Location, Location> reverseMappedLocations, CancellationToken cancellationToken) { try { if (renamedSymbol.ContainingSymbol.IsKind(SymbolKind.NamedType)) { var otherThingsNamedTheSame = renamedSymbol.ContainingType.GetMembers(renamedSymbol.Name) .Where(s => !s.Equals(renamedSymbol) && string.Equals(s.MetadataName, renamedSymbol.MetadataName, StringComparison.Ordinal) && (s.Kind != SymbolKind.Method || renamedSymbol.Kind != SymbolKind.Method)); AddConflictingSymbolLocations(otherThingsNamedTheSame, conflictResolution, reverseMappedLocations); } if (renamedSymbol.IsKind(SymbolKind.Namespace) && renamedSymbol.ContainingSymbol.IsKind(SymbolKind.Namespace)) { var otherThingsNamedTheSame = ((INamespaceSymbol)renamedSymbol.ContainingSymbol).GetMembers(renamedSymbol.Name) .Where(s => !s.Equals(renamedSymbol) && !s.IsKind(SymbolKind.Namespace) && string.Equals(s.MetadataName, renamedSymbol.MetadataName, StringComparison.Ordinal)); AddConflictingSymbolLocations(otherThingsNamedTheSame, conflictResolution, reverseMappedLocations); } if (renamedSymbol.IsKind(SymbolKind.NamedType) && renamedSymbol.ContainingSymbol is INamespaceOrTypeSymbol) { var otherThingsNamedTheSame = ((INamespaceOrTypeSymbol)renamedSymbol.ContainingSymbol).GetMembers(renamedSymbol.Name) .Where(s => !s.Equals(renamedSymbol) && string.Equals(s.MetadataName, renamedSymbol.MetadataName, StringComparison.Ordinal)); var conflictingSymbolLocations = otherThingsNamedTheSame.Where(s => !s.IsKind(SymbolKind.Namespace)); if (otherThingsNamedTheSame.Any(s => s.IsKind(SymbolKind.Namespace))) { conflictingSymbolLocations = conflictingSymbolLocations.Concat(renamedSymbol); } AddConflictingSymbolLocations(conflictingSymbolLocations, conflictResolution, reverseMappedLocations); } // Some types of symbols (namespaces, cref stuff, etc) might not have ContainingAssemblies if (renamedSymbol.ContainingAssembly != null) { var project = conflictResolution.NewSolution.GetProject(renamedSymbol.ContainingAssembly, cancellationToken); // There also might be language specific rules we need to include var languageRenameService = project.LanguageServices.GetService <IRenameRewriterLanguageService>(); var languageConflicts = await languageRenameService.ComputeDeclarationConflictsAsync( conflictResolution.ReplacementText, renamedSymbol, renameSymbol, referencedSymbols, conflictResolution.OldSolution, conflictResolution.NewSolution, reverseMappedLocations, cancellationToken).ConfigureAwait(false); foreach (var languageConflict in languageConflicts) { conflictResolution.AddOrReplaceRelatedLocation(new RelatedLocation(languageConflict.SourceSpan, conflictResolution.OldSolution.GetDocument(languageConflict.SourceTree).Id, RelatedLocationType.UnresolvableConflict)); } } } catch (Exception e) when(FatalError.ReportUnlessCanceled(e)) { // A NullReferenceException is happening in this method, but the dumps do not // contain information about this stack frame because this method is async and // therefore the exception filter in IdentifyConflictsAsync is insufficient. // See https://devdiv.visualstudio.com/DevDiv/_workitems?_a=edit&id=378642 throw ExceptionUtilities.Unreachable; } }