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)); } } }
private async Task <bool> CheckForConflictAsync( ConflictResolution conflictResolution, ISymbol renamedSymbolInNewSolution, Document newDocument, RenameActionAnnotation conflictAnnotation, IEnumerable <ISymbol> newReferencedSymbols) { try { bool hasConflict; var solution = conflictResolution.NewSolution; if (conflictAnnotation.IsNamespaceDeclarationReference) { hasConflict = false; } else if (conflictAnnotation.IsMemberGroupReference) { if (!conflictAnnotation.RenameDeclarationLocationReferences.Any()) { hasConflict = false; } else { // Ensure newReferencedSymbols contains at least one of the original referenced // symbols, and allow any new symbols to be added to the set of references. hasConflict = true; var newLocationTasks = newReferencedSymbols.Select(async symbol => await GetSymbolLocationAsync(solution, symbol, _cancellationToken).ConfigureAwait(false)); var newLocations = (await Task.WhenAll(newLocationTasks).ConfigureAwait(false)).Where(loc => loc != null && loc.IsInSource); foreach (var originalReference in conflictAnnotation.RenameDeclarationLocationReferences.Where(loc => loc.IsSourceLocation)) { var adjustedStartPosition = conflictResolution.GetAdjustedTokenStartingPosition(originalReference.TextSpan.Start, originalReference.DocumentId); if (newLocations.Any(loc => loc.SourceSpan.Start == adjustedStartPosition)) { hasConflict = false; break; } } } } else if (!conflictAnnotation.IsRenameLocation && conflictAnnotation.IsOriginalTextLocation && conflictAnnotation.RenameDeclarationLocationReferences.Length > 1 && newReferencedSymbols.Count() == 1) { // an ambiguous situation was resolved through rename in non reference locations hasConflict = false; } else if (newReferencedSymbols.Count() != conflictAnnotation.RenameDeclarationLocationReferences.Length) { // Don't show conflicts for errors in the old solution that now bind in the new solution. if (newReferencedSymbols.Count() != 0 && conflictAnnotation.RenameDeclarationLocationReferences.Length == 0) { hasConflict = false; } else { hasConflict = true; } } else { hasConflict = false; int symbolIndex = 0; foreach (var symbol in newReferencedSymbols) { if (conflictAnnotation.RenameDeclarationLocationReferences[symbolIndex].SymbolLocationsCount != symbol.Locations.Length) { hasConflict = true; break; } var newLocation = await GetSymbolLocationAsync(solution, symbol, _cancellationToken).ConfigureAwait(false); if (newLocation != null && conflictAnnotation.RenameDeclarationLocationReferences[symbolIndex].IsSourceLocation) { // location was in source before, but not after rename if (!newLocation.IsInSource) { hasConflict = true; break; } var renameDeclarationLocationReference = conflictAnnotation.RenameDeclarationLocationReferences[symbolIndex]; var newAdjustedStartPosition = conflictResolution.GetAdjustedTokenStartingPosition(renameDeclarationLocationReference.TextSpan.Start, renameDeclarationLocationReference.DocumentId); if (newAdjustedStartPosition != newLocation.SourceSpan.Start) { hasConflict = true; break; } if (conflictAnnotation.RenameDeclarationLocationReferences[symbolIndex].IsOverriddenFromMetadata) { var overridingSymbol = await SymbolFinder.FindSymbolAtPositionAsync(solution.GetDocument(newLocation.SourceTree), newLocation.SourceSpan.Start, cancellationToken : _cancellationToken).ConfigureAwait(false); if (overridingSymbol != null && renamedSymbolInNewSolution != overridingSymbol) { if (!overridingSymbol.IsOverride) { hasConflict = true; break; } else { var overriddenSymbol = overridingSymbol.OverriddenMember(); if (overriddenSymbol == null || !overriddenSymbol.Locations.All(loc => loc.IsInMetadata)) { hasConflict = true; break; } } } } } else { var newMetadataName = symbol.ToDisplayString(s_metadataSymbolDisplayFormat); var oldMetadataName = conflictAnnotation.RenameDeclarationLocationReferences[symbolIndex].Name; if (newLocation == null || newLocation.IsInSource || !HeuristicMetadataNameEquivalenceCheck( oldMetadataName, newMetadataName, _originalText, _replacementText)) { hasConflict = true; break; } } symbolIndex++; } } return(hasConflict); } catch (Exception e) when(FatalError.ReportUnlessCanceled(e)) { throw ExceptionUtilities.Unreachable; } }
/// <summary> /// Find conflicts in the new solution /// </summary> private async Task <bool> IdentifyConflictsAsync( HashSet <DocumentId> documentIdsForConflictResolution, IEnumerable <DocumentId> allDocumentIdsInProject, ProjectId projectId, ConflictResolution conflictResolution) { try { _documentOfRenameSymbolHasBeenRenamed |= documentIdsForConflictResolution.Contains(_documentIdOfRenameSymbolDeclaration); // Get the renamed symbol in complexified new solution ISymbol renamedSymbolInNewSolution = await GetRenamedSymbolInCurrentSolutionAsync(conflictResolution).ConfigureAwait(false); // if the text replacement is invalid, we just did a simple token replacement. // Therefore we don't need more mapping information and can skip the rest of // the loop body. if (!IsRenameValid(conflictResolution, renamedSymbolInNewSolution)) { foreach (var documentId in documentIdsForConflictResolution) { var newDocument = conflictResolution.NewSolution.GetDocument(documentId); var syntaxRoot = await newDocument.GetSyntaxRootAsync(_cancellationToken).ConfigureAwait(false); var nodesOrTokensWithConflictCheckAnnotations = GetNodesOrTokensToCheckForConflicts(documentId, syntaxRoot); foreach (var nodeOrToken in nodesOrTokensWithConflictCheckAnnotations) { if (nodeOrToken.annotation.IsRenameLocation) { conflictResolution.AddRelatedLocation(new RelatedLocation( nodeOrToken.annotation.OriginalSpan, documentId, RelatedLocationType.UnresolvedConflict)); } } } return(false); } Dictionary <Location, Location> reverseMappedLocations = new Dictionary <Location, Location>(); foreach (var documentId in documentIdsForConflictResolution) { var newDocument = conflictResolution.NewSolution.GetDocument(documentId); var syntaxRoot = await newDocument.GetSyntaxRootAsync(_cancellationToken).ConfigureAwait(false); var baseDocument = conflictResolution.OldSolution.GetDocument(documentId); var baseSyntaxTree = await baseDocument.GetSyntaxTreeAsync(_cancellationToken).ConfigureAwait(false); var baseRoot = await baseDocument.GetSyntaxRootAsync(_cancellationToken).ConfigureAwait(false); SemanticModel newDocumentSemanticModel = null; var syntaxFactsService = newDocument.Project.LanguageServices.GetService <ISyntaxFactsService>(); // Get all tokens that need conflict check var nodesOrTokensWithConflictCheckAnnotations = GetNodesOrTokensToCheckForConflicts(documentId, syntaxRoot); var complexifiedLocationSpanForThisDocument = _conflictLocations .Where(t => t.DocumentId == documentId) .Select(t => t.OriginalIdentifierSpan).ToSet(); foreach (var nodeAndAnnotation in nodesOrTokensWithConflictCheckAnnotations) { var tokenOrNode = nodeAndAnnotation.syntax; var conflictAnnotation = nodeAndAnnotation.annotation; reverseMappedLocations[tokenOrNode.GetLocation()] = baseSyntaxTree.GetLocation(conflictAnnotation.OriginalSpan); var originalLocation = conflictAnnotation.OriginalSpan; IEnumerable <ISymbol> newReferencedSymbols = null; var hasConflict = _renameAnnotations.HasAnnotation(tokenOrNode, RenameInvalidIdentifierAnnotation.Instance); if (!hasConflict) { newDocumentSemanticModel = newDocumentSemanticModel ?? await newDocument.GetSemanticModelAsync(_cancellationToken).ConfigureAwait(false); newReferencedSymbols = GetSymbolsInNewSolution(newDocument, newDocumentSemanticModel, conflictAnnotation, tokenOrNode); // The semantic correctness, after rename, for each token of interest in the // rename context is performed by getting the symbol pointed by each token // and obtain the Symbol's First Ordered Location's Span-Start and check to // see if it is the same as before from the base solution. During rename, // the spans would have been modified and so we need to adjust the old position // to the new position for which we use the renameSpanTracker, which was tracking // & mapping the old span -> new span during rename hasConflict = _hasConflictCallback?.Invoke(newReferencedSymbols) ?? await CheckForConflictAsync(conflictResolution, renamedSymbolInNewSolution, newDocument, conflictAnnotation, newReferencedSymbols).ConfigureAwait(false); } if (!hasConflict && !conflictAnnotation.IsInvocationExpression) { hasConflict = LocalVariableConflictPerLanguage((SyntaxToken)tokenOrNode, newDocument, newReferencedSymbols); } if (!hasConflict) { if (conflictAnnotation.IsRenameLocation) { conflictResolution.AddRelatedLocation( new RelatedLocation(originalLocation, documentId, complexifiedLocationSpanForThisDocument.Contains(originalLocation) ? RelatedLocationType.ResolvedReferenceConflict : RelatedLocationType.NoConflict, isReference: true)); } else { // if a complexified location was not a reference location, then it was a resolved conflict of a non reference location if (!conflictAnnotation.IsOriginalTextLocation && complexifiedLocationSpanForThisDocument.Contains(originalLocation)) { conflictResolution.AddRelatedLocation( new RelatedLocation(originalLocation, documentId, RelatedLocationType.ResolvedNonReferenceConflict, isReference: false)); } } } else { var baseToken = baseRoot.FindToken(conflictAnnotation.OriginalSpan.Start, true); var complexifiedTarget = GetExpansionTargetForLocationPerLanguage(baseToken, baseDocument); conflictResolution.AddRelatedLocation(new RelatedLocation( originalLocation, documentId, complexifiedTarget != null ? RelatedLocationType.PossiblyResolvableConflict : RelatedLocationType.UnresolvableConflict, isReference: conflictAnnotation.IsRenameLocation, complexifiedTargetSpan: complexifiedTarget != null ? complexifiedTarget.Span : default)); } } } // there are more conflicts that cannot be identified by checking if the tokens still reference the same // symbol. These conflicts are mostly language specific. A good example is a member with the same name // as the parent (yes I know, this is a simplification). if (_documentIdOfRenameSymbolDeclaration.ProjectId == projectId) { // Calculating declaration conflicts may require location mapping in documents // that were not otherwise being processed in the current rename phase, so add // the annotated spans in these documents to reverseMappedLocations. foreach (var unprocessedDocumentIdWithPotentialDeclarationConflicts in allDocumentIdsInProject.Where(d => !documentIdsForConflictResolution.Contains(d))) { var newDocument = conflictResolution.NewSolution.GetDocument(unprocessedDocumentIdWithPotentialDeclarationConflicts); var syntaxRoot = await newDocument.GetSyntaxRootAsync(_cancellationToken).ConfigureAwait(false); var baseDocument = conflictResolution.OldSolution.GetDocument(unprocessedDocumentIdWithPotentialDeclarationConflicts); var baseSyntaxTree = await baseDocument.GetSyntaxTreeAsync(_cancellationToken).ConfigureAwait(false); var nodesOrTokensWithConflictCheckAnnotations = GetNodesOrTokensToCheckForConflicts(unprocessedDocumentIdWithPotentialDeclarationConflicts, syntaxRoot); foreach (var nodeAndAnnotation in nodesOrTokensWithConflictCheckAnnotations) { var tokenOrNode = nodeAndAnnotation.syntax; var conflictAnnotation = nodeAndAnnotation.annotation; reverseMappedLocations[tokenOrNode.GetLocation()] = baseSyntaxTree.GetLocation(conflictAnnotation.OriginalSpan); } } var referencedSymbols = _renameLocationSet.ReferencedSymbols; var renameSymbol = _renameLocationSet.Symbol; await AddDeclarationConflictsAsync( renamedSymbolInNewSolution, renameSymbol, referencedSymbols, conflictResolution, reverseMappedLocations, _cancellationToken).ConfigureAwait(false); } return(conflictResolution.RelatedLocations.Any(r => r.Type == RelatedLocationType.PossiblyResolvableConflict)); } catch (Exception e) when(FatalError.ReportUnlessCanceled(e)) { throw ExceptionUtilities.Unreachable; } }
// The method which performs rename, resolves the conflict locations and returns the result of the rename operation public async Task <ConflictResolution> ResolveConflictsAsync() { try { await FindDocumentsAndPossibleNameConflicts().ConfigureAwait(false); var baseSolution = _renameLocationSet.Solution; // Process rename one project at a time to improve caching and reduce syntax tree serialization. var documentsGroupedByTopologicallySortedProjectId = _documentsIdsToBeCheckedForConflict .GroupBy(d => d.ProjectId) .OrderBy(g => _topologicallySortedProjects.IndexOf(g.Key)); _replacementTextValid = IsIdentifierValid_Worker(baseSolution, _replacementText, documentsGroupedByTopologicallySortedProjectId.Select(g => g.Key), _cancellationToken); var renamedSpansTracker = new RenamedSpansTracker(); var conflictResolution = new ConflictResolution(baseSolution, renamedSpansTracker, _replacementText, _replacementTextValid); foreach (var documentsByProject in documentsGroupedByTopologicallySortedProjectId) { var documentIdsThatGetsAnnotatedAndRenamed = new HashSet <DocumentId>(documentsByProject); using (baseSolution.Services.CacheService?.EnableCaching(documentsByProject.Key)) { // Rename is going to be in 4 phases. // 1st phase - Does a simple token replacement // If the 1st phase results in conflict then we perform then: // 2nd phase is to expand and simplify only the reference locations with conflicts // 3rd phase is to expand and simplify all the conflict locations (both reference and non-reference) // If there are unresolved Conflicts after the 3rd phase then in 4th phase, // We complexify and resolve locations that were resolvable and for the other locations we perform the normal token replacement like the first the phase. for (int phase = 0; phase < 4; phase++) { // Step 1: // The rename process and annotation for the bookkeeping is performed in one-step // The Process in short is, // 1. If renaming a token which is no conflict then replace the token and make a map of the oldspan to the newspan // 2. If we encounter a node that has to be expanded( because there was a conflict in previous phase), we expand it. // If the node happens to contain a token that needs to be renamed then we annotate it and rename it after expansion else just expand and proceed // 3. Through the whole process we maintain a map of the oldspan to newspan. In case of expansion & rename, we map the expanded node and the renamed token conflictResolution.UpdateCurrentSolution(await AnnotateAndRename_WorkerAsync( baseSolution, conflictResolution.NewSolution, documentIdsThatGetsAnnotatedAndRenamed, _renameLocationSet.Locations, renamedSpansTracker, _replacementTextValid).ConfigureAwait(false)); // Step 2: Check for conflicts in the renamed solution bool foundResolvableConflicts = await IdentifyConflictsAsync( documentIdsForConflictResolution : documentIdsThatGetsAnnotatedAndRenamed, allDocumentIdsInProject : documentsByProject, projectId : documentsByProject.Key, conflictResolution : conflictResolution).ConfigureAwait(false); if (!foundResolvableConflicts || phase == 3) { break; } if (phase == 0) { _conflictLocations = conflictResolution.RelatedLocations .Where(loc => (documentIdsThatGetsAnnotatedAndRenamed.Contains(loc.DocumentId) && loc.Type == RelatedLocationType.PossiblyResolvableConflict && loc.IsReference)) .Select(loc => new ConflictLocationInfo(loc)) .ToSet(); // If there were no conflicting locations in references, then the first conflict phase has to be skipped. if (_conflictLocations.Count == 0) { phase++; } } if (phase == 1) { _conflictLocations = _conflictLocations.Concat(conflictResolution.RelatedLocations .Where(loc => documentIdsThatGetsAnnotatedAndRenamed.Contains(loc.DocumentId) && loc.Type == RelatedLocationType.PossiblyResolvableConflict) .Select(loc => new ConflictLocationInfo(loc))) .ToSet(); } // Set the documents with conflicts that need to be processed in the next phase. // Note that we need to get the conflictLocations here since we're going to remove some locations below if phase == 2 documentIdsThatGetsAnnotatedAndRenamed = new HashSet <DocumentId>(_conflictLocations.Select(l => l.DocumentId)); if (phase == 2) { // After phase 2, if there are still conflicts then remove the conflict locations from being expanded var unresolvedLocations = conflictResolution.RelatedLocations .Where(l => (l.Type & RelatedLocationType.UnresolvedConflict) != 0) .Select(l => Tuple.Create(l.ComplexifiedTargetSpan, l.DocumentId)).Distinct(); _conflictLocations = _conflictLocations.Where(l => !unresolvedLocations.Any(c => c.Item2 == l.DocumentId && c.Item1.Contains(l.OriginalIdentifierSpan))).ToSet(); } // Clean up side effects from rename before entering the next phase conflictResolution.ClearDocuments(documentIdsThatGetsAnnotatedAndRenamed); } // Step 3: Simplify the project conflictResolution.UpdateCurrentSolution(await renamedSpansTracker.SimplifyAsync(conflictResolution.NewSolution, documentsByProject, _replacementTextValid, _renameAnnotations, _cancellationToken).ConfigureAwait(false)); await conflictResolution.RemoveAllRenameAnnotationsAsync(documentsByProject, _renameAnnotations, _cancellationToken).ConfigureAwait(false); } } // This rename could break implicit references of this symbol (e.g. rename MoveNext on a collection like type in a // foreach/for each statement ISymbol renamedSymbolInNewSolution = await GetRenamedSymbolInCurrentSolutionAsync(conflictResolution).ConfigureAwait(false); if (IsRenameValid(conflictResolution, renamedSymbolInNewSolution)) { await AddImplicitConflictsAsync( renamedSymbolInNewSolution, _renameLocationSet.Symbol, _renameLocationSet.ImplicitLocations, await conflictResolution.NewSolution.GetDocument(_documentIdOfRenameSymbolDeclaration).GetSemanticModelAsync(_cancellationToken).ConfigureAwait(false), _renameSymbolDeclarationLocation, renamedSpansTracker.GetAdjustedPosition(_renameSymbolDeclarationLocation.SourceSpan.Start, _documentIdOfRenameSymbolDeclaration), conflictResolution, _cancellationToken).ConfigureAwait(false); } foreach (var relatedLocation in conflictResolution.RelatedLocations) { if (relatedLocation.Type == RelatedLocationType.PossiblyResolvableConflict) { relatedLocation.Type = RelatedLocationType.UnresolvedConflict; } } #if DEBUG await DebugVerifyNoErrorsAsync(conflictResolution, _documentsIdsToBeCheckedForConflict).ConfigureAwait(false); #endif return(conflictResolution); } catch (Exception e) when(FatalError.ReportUnlessCanceled(e)) { throw ExceptionUtilities.Unreachable; } }
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)); } } } } }
/// <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; } }
private static bool IsRenameValid(ConflictResolution conflictResolution, ISymbol renamedSymbol) { // if we rename an identifier and it now binds to a symbol from metadata this should be treated as // an invalid rename. return(conflictResolution.ReplacementTextValid && renamedSymbol != null && renamedSymbol.Locations.Any(loc => loc.IsInSource)); }