diff --git a/src/EditorFeatures/Core/InlineRename/AbstractEditorInlineRenameService.InlineRenameLocationSet.cs b/src/EditorFeatures/Core/InlineRename/AbstractEditorInlineRenameService.InlineRenameLocationSet.cs index 45b1faf47c43f..099b006d36cb0 100644 --- a/src/EditorFeatures/Core/InlineRename/AbstractEditorInlineRenameService.InlineRenameLocationSet.cs +++ b/src/EditorFeatures/Core/InlineRename/AbstractEditorInlineRenameService.InlineRenameLocationSet.cs @@ -42,8 +42,6 @@ public async Task GetReplacementsAsync(string repl var conflicts = await _renameLocationSet.ResolveConflictsAsync( _renameInfo.GetFinalSymbolName(replacementText), nonConflictSymbols: null, cancellationToken: cancellationToken).ConfigureAwait(false); - Contract.ThrowIfTrue(conflicts.ErrorMessage != null); - return new InlineRenameReplacementInfo(conflicts); } } diff --git a/src/EditorFeatures/Core/InlineRename/AbstractEditorInlineRenameService.InlineRenameReplacementInfo.cs b/src/EditorFeatures/Core/InlineRename/AbstractEditorInlineRenameService.InlineRenameReplacementInfo.cs index 5a1a07a7d7b72..75c806681a643 100644 --- a/src/EditorFeatures/Core/InlineRename/AbstractEditorInlineRenameService.InlineRenameReplacementInfo.cs +++ b/src/EditorFeatures/Core/InlineRename/AbstractEditorInlineRenameService.InlineRenameReplacementInfo.cs @@ -16,13 +16,16 @@ private class InlineRenameReplacementInfo : IInlineRenameReplacementInfo private readonly ConflictResolution _conflicts; public InlineRenameReplacementInfo(ConflictResolution conflicts) - => _conflicts = conflicts; + { + Contract.ThrowIfFalse(conflicts.IsSuccessful); + _conflicts = conflicts; + } public IEnumerable DocumentIds => _conflicts.DocumentIds; - public Solution NewSolution => _conflicts.NewSolution; + public Solution NewSolution => _conflicts.NewSolution!; - public bool ReplacementTextValid => _conflicts.ReplacementTextValid; + public bool ReplacementTextValid => _conflicts.ReplacementTextValid!.Value; public IEnumerable GetReplacements(DocumentId documentId) { diff --git a/src/EditorFeatures/Core/InlineRename/AbstractEditorInlineRenameService.cs b/src/EditorFeatures/Core/InlineRename/AbstractEditorInlineRenameService.cs index a89dc3270fcf8..7b1849adfda66 100644 --- a/src/EditorFeatures/Core/InlineRename/AbstractEditorInlineRenameService.cs +++ b/src/EditorFeatures/Core/InlineRename/AbstractEditorInlineRenameService.cs @@ -55,7 +55,7 @@ public async Task GetRenameInfoAsync(Document document, int p return new FailureInlineRenameInfo(EditorFeaturesResources.You_must_rename_an_identifier); var semanticModel = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false); - var semanticFacts = document.GetLanguageService(); + var semanticFacts = document.GetRequiredLanguageService(); var tokenRenameInfo = RenameUtilities.GetTokenRenameInfo(semanticFacts, semanticModel, triggerToken, cancellationToken); diff --git a/src/EditorFeatures/Test2/Rename/RenameEngineResult.vb b/src/EditorFeatures/Test2/Rename/RenameEngineResult.vb index 204737337cf56..66e737ce21463 100644 --- a/src/EditorFeatures/Test2/Rename/RenameEngineResult.vb +++ b/src/EditorFeatures/Test2/Rename/RenameEngineResult.vb @@ -89,6 +89,7 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.Rename Dim result = GetConflictResolution(renameTo, workspace.CurrentSolution, symbol, renameOptions, host) If expectFailure Then + Assert.False(result.IsSuccessful) Assert.NotNull(result.ErrorMessage) Return engineResult Else diff --git a/src/Features/Core/Portable/EncapsulateField/AbstractEncapsulateFieldService.cs b/src/Features/Core/Portable/EncapsulateField/AbstractEncapsulateFieldService.cs index eb9f6c39f1fc7..937cbcac29ec1 100644 --- a/src/Features/Core/Portable/EncapsulateField/AbstractEncapsulateFieldService.cs +++ b/src/Features/Core/Portable/EncapsulateField/AbstractEncapsulateFieldService.cs @@ -316,7 +316,7 @@ private async Task EncapsulateFieldsInCurrentProcessAsync(Document doc var resolution = await initialLocations.Filter(filter).ResolveConflictsAsync( finalName, nonConflictSymbols: null, cancellationToken).ConfigureAwait(false); - Contract.ThrowIfTrue(resolution.ErrorMessage != null); + Contract.ThrowIfFalse(resolution.IsSuccessful); return resolution.NewSolution; } diff --git a/src/Features/Core/Portable/UseAutoProperty/AbstractUseAutoPropertyCodeFixProvider.cs b/src/Features/Core/Portable/UseAutoProperty/AbstractUseAutoPropertyCodeFixProvider.cs index ef47debfc221f..612e88308ad40 100644 --- a/src/Features/Core/Portable/UseAutoProperty/AbstractUseAutoPropertyCodeFixProvider.cs +++ b/src/Features/Core/Portable/UseAutoProperty/AbstractUseAutoPropertyCodeFixProvider.cs @@ -140,7 +140,7 @@ private async Task ProcessResultAsync(CodeFixContext context, Diagnost nonConflictSymbols: ImmutableHashSet.Create(propertySymbol), cancellationToken).ConfigureAwait(false); - Contract.ThrowIfTrue(resolution.ErrorMessage != null); + Contract.ThrowIfFalse(resolution.IsSuccessful); solution = resolution.NewSolution; diff --git a/src/Tools/ExternalAccess/OmniSharp/Rename/OmniSharpRenamer.cs b/src/Tools/ExternalAccess/OmniSharp/Rename/OmniSharpRenamer.cs index 0dfe4d8ed0082..58c047aff45a6 100644 --- a/src/Tools/ExternalAccess/OmniSharp/Rename/OmniSharpRenamer.cs +++ b/src/Tools/ExternalAccess/OmniSharp/Rename/OmniSharpRenamer.cs @@ -14,7 +14,7 @@ namespace Microsoft.CodeAnalysis.ExternalAccess.OmniSharp { internal static class OmniSharpRenamer { - public readonly record struct RenameResult(Solution Solution, string? ErrorMessage); + public readonly record struct RenameResult(Solution? Solution, string? ErrorMessage); public static async Task RenameSymbolAsync( Solution solution, diff --git a/src/Workspaces/Core/Portable/Rename/ConflictEngine/ComplexifiedSpan.cs b/src/Workspaces/Core/Portable/Rename/ConflictEngine/ComplexifiedSpan.cs index b3b8cbe53a691..a807d161e7a35 100644 --- a/src/Workspaces/Core/Portable/Rename/ConflictEngine/ComplexifiedSpan.cs +++ b/src/Workspaces/Core/Portable/Rename/ConflictEngine/ComplexifiedSpan.cs @@ -2,8 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#nullable disable - using System.Collections.Immutable; using System.Runtime.Serialization; using Microsoft.CodeAnalysis.Text; diff --git a/src/Workspaces/Core/Portable/Rename/ConflictEngine/ConflictResolver.Session.cs b/src/Workspaces/Core/Portable/Rename/ConflictEngine/ConflictResolver.Session.cs index ec011c8e044dc..ce56254502ea0 100644 --- a/src/Workspaces/Core/Portable/Rename/ConflictEngine/ConflictResolver.Session.cs +++ b/src/Workspaces/Core/Portable/Rename/ConflictEngine/ConflictResolver.Session.cs @@ -238,7 +238,7 @@ public async Task ResolveConflictsAsync() { var definitionLocations = _renameLocationSet.Symbol.Locations; var definitionDocuments = definitionLocations - .Select(l => conflictResolution.OldSolution.GetDocument(l.SourceTree)) + .Select(l => conflictResolution.OldSolution.GetRequiredDocument(l.SourceTree)) .Distinct(); if (definitionDocuments.Count() == 1 && _replacementTextValid) diff --git a/src/Workspaces/Core/Portable/Rename/ConflictEngine/ConflictResolver.cs b/src/Workspaces/Core/Portable/Rename/ConflictEngine/ConflictResolver.cs index 6a10d88080809..3f1da65195396 100644 --- a/src/Workspaces/Core/Portable/Rename/ConflictEngine/ConflictResolver.cs +++ b/src/Workspaces/Core/Portable/Rename/ConflictEngine/ConflictResolver.cs @@ -77,27 +77,28 @@ internal static partial class ConflictResolver ImmutableHashSet? nonConflictSymbols, CancellationToken cancellationToken) { + // when someone e.g. renames a symbol from metadata through the API (IDE blocks this), we need to return + var renameSymbolDeclarationLocation = renameLocationSet.Symbol.Locations.Where(loc => loc.IsInSource).FirstOrDefault(); + if (renameSymbolDeclarationLocation == null) + { + // Symbol "{0}" is not from source. + return new ConflictResolution(string.Format(WorkspacesResources.Symbol_0_is_not_from_source, renameLocationSet.Symbol.Name)); + } + var resolution = await ResolveMutableConflictsAsync( - renameLocationSet, replacementText, nonConflictSymbols, cancellationToken).ConfigureAwait(false); + renameLocationSet, renameSymbolDeclarationLocation, replacementText, nonConflictSymbols, cancellationToken).ConfigureAwait(false); + return resolution.ToConflictResolution(); } private static Task ResolveMutableConflictsAsync( RenameLocations renameLocationSet, + Location renameSymbolDeclarationLocation, string replacementText, ImmutableHashSet? nonConflictSymbols, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); - - // when someone e.g. renames a symbol from metadata through the API (IDE blocks this), we need to return - var renameSymbolDeclarationLocation = renameLocationSet.Symbol.Locations.Where(loc => loc.IsInSource).FirstOrDefault(); - if (renameSymbolDeclarationLocation == null) - { - // Symbol "{0}" is not from source. - return Task.FromResult(new MutableConflictResolution(string.Format(WorkspacesResources.Symbol_0_is_not_from_source, renameLocationSet.Symbol.Name))); - } - var session = new Session( renameLocationSet, renameSymbolDeclarationLocation, replacementText, nonConflictSymbols, cancellationToken); diff --git a/src/Workspaces/Core/Portable/Rename/ConflictEngine/ConflictingIdentifierTracker.cs b/src/Workspaces/Core/Portable/Rename/ConflictEngine/ConflictingIdentifierTracker.cs index 4e3a316228ecf..432875ac8efe4 100644 --- a/src/Workspaces/Core/Portable/Rename/ConflictEngine/ConflictingIdentifierTracker.cs +++ b/src/Workspaces/Core/Portable/Rename/ConflictEngine/ConflictingIdentifierTracker.cs @@ -2,8 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#nullable disable - using System.Collections.Generic; namespace Microsoft.CodeAnalysis.Rename.ConflictEngine diff --git a/src/Workspaces/Core/Portable/Rename/ConflictEngine/DeclarationConflictHelpers.cs b/src/Workspaces/Core/Portable/Rename/ConflictEngine/DeclarationConflictHelpers.cs index 9409df55f3253..c0e9b2675b732 100644 --- a/src/Workspaces/Core/Portable/Rename/ConflictEngine/DeclarationConflictHelpers.cs +++ b/src/Workspaces/Core/Portable/Rename/ConflictEngine/DeclarationConflictHelpers.cs @@ -2,8 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#nullable disable - using System; using System.Collections.Generic; using System.Collections.Immutable; @@ -22,7 +20,7 @@ public static ImmutableArray GetMembersWithConflictingSignatures(IMeth .Where(m => !m.Equals(renamedMethod) && m.Arity == renamedMethod.Arity); return GetConflictLocations(renamedMethod, potentiallyConflictingMethods, isMethod: true, - (method) => GetAllSignatures((method as IMethodSymbol).Parameters, trimOptionalParameters)); + method => GetAllSignatures(((IMethodSymbol)method).Parameters, trimOptionalParameters)); } public static ImmutableArray GetMembersWithConflictingSignatures(IPropertySymbol renamedProperty, bool trimOptionalParameters) @@ -33,7 +31,7 @@ public static ImmutableArray GetMembersWithConflictingSignatures(IProp .Where(m => !m.Equals(renamedProperty) && m.Parameters.Length == renamedProperty.Parameters.Length); return GetConflictLocations(renamedProperty, potentiallyConflictingProperties, isMethod: false, - (property) => GetAllSignatures((property as IPropertySymbol).Parameters, trimOptionalParameters)); + property => GetAllSignatures(((IPropertySymbol)property).Parameters, trimOptionalParameters)); } private static ImmutableArray GetConflictLocations(ISymbol renamedMember, @@ -57,10 +55,8 @@ public static ImmutableArray GetMembersWithConflictingSignatures(IProp { if (signatureToConflictingMember.TryGetValue(signature, out var conflictingSymbol)) { - if (isMethod) + if (isMethod && conflictingSymbol is IMethodSymbol conflictingMethod && renamedMember is IMethodSymbol renamedMethod) { - var conflictingMethod = conflictingSymbol as IMethodSymbol; - var renamedMethod = renamedMember as IMethodSymbol; if (!(conflictingMethod.PartialDefinitionPart != null && Equals(conflictingMethod.PartialDefinitionPart, renamedMethod)) && !(conflictingMethod.PartialImplementationPart != null && Equals(conflictingMethod.PartialImplementationPart, renamedMethod))) { diff --git a/src/Workspaces/Core/Portable/Rename/ConflictEngine/MutableConflictResolution.cs b/src/Workspaces/Core/Portable/Rename/ConflictEngine/MutableConflictResolution.cs index c48fd56f7560b..b0a7646855fba 100644 --- a/src/Workspaces/Core/Portable/Rename/ConflictEngine/MutableConflictResolution.cs +++ b/src/Workspaces/Core/Portable/Rename/ConflictEngine/MutableConflictResolution.cs @@ -2,8 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#nullable disable - using System; using System.Collections.Generic; using System.Collections.Immutable; @@ -22,8 +20,6 @@ namespace Microsoft.CodeAnalysis.Rename.ConflictEngine /// internal sealed class MutableConflictResolution { - public readonly string ErrorMessage; - // Used to map spans from oldSolution to the newSolution private readonly RenamedSpansTracker _renamedSpansTracker; @@ -53,9 +49,6 @@ internal sealed class MutableConflictResolution private (DocumentId documentId, string newName) _renamedDocument; - public MutableConflictResolution(string errorMessage) - => ErrorMessage = errorMessage; - public MutableConflictResolution( Solution oldSolution, RenamedSpansTracker renamedSpansTracker, @@ -89,8 +82,8 @@ internal void UpdateCurrentSolution(Solution solution) { if (_renamedSpansTracker.IsDocumentChanged(documentId)) { - var document = CurrentSolution.GetDocument(documentId); - var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); + var document = CurrentSolution.GetRequiredDocument(documentId); + var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); // For the computeReplacementToken and computeReplacementNode functions, use // the "updated" node to maintain any annotation removals from descendants. @@ -161,9 +154,6 @@ internal void AddOrReplaceRelatedLocation(RelatedLocation location) public ConflictResolution ToConflictResolution() { - if (ErrorMessage != null) - return new ConflictResolution(ErrorMessage); - var documentIds = _renamedSpansTracker.DocumentIds.Concat( this.RelatedLocations.Select(l => l.DocumentId)).Distinct().ToImmutableArray(); diff --git a/src/Workspaces/Core/Portable/Rename/ConflictEngine/RelatedLocation.cs b/src/Workspaces/Core/Portable/Rename/ConflictEngine/RelatedLocation.cs index a2b3e17395a87..d86b0ef99ff78 100644 --- a/src/Workspaces/Core/Portable/Rename/ConflictEngine/RelatedLocation.cs +++ b/src/Workspaces/Core/Portable/Rename/ConflictEngine/RelatedLocation.cs @@ -2,8 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#nullable disable - using System; using System.Collections.Generic; using System.Runtime.Serialization; @@ -52,7 +50,7 @@ public RelatedLocation(TextSpan conflictCheckSpan, DocumentId documentId, Relate public RelatedLocation WithType(RelatedLocationType type) => new(ConflictCheckSpan, DocumentId, type, IsReference, ComplexifiedTargetSpan); - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj is RelatedLocation location && Equals(location); public bool Equals(RelatedLocation other) diff --git a/src/Workspaces/Core/Portable/Rename/ConflictEngine/RelatedLocationType.cs b/src/Workspaces/Core/Portable/Rename/ConflictEngine/RelatedLocationType.cs index 01ea10fa939d2..53c9577b5ddb9 100644 --- a/src/Workspaces/Core/Portable/Rename/ConflictEngine/RelatedLocationType.cs +++ b/src/Workspaces/Core/Portable/Rename/ConflictEngine/RelatedLocationType.cs @@ -2,8 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#nullable disable - using System; namespace Microsoft.CodeAnalysis.Rename.ConflictEngine diff --git a/src/Workspaces/Core/Portable/Rename/ConflictEngine/RenamedSpansTracker.cs b/src/Workspaces/Core/Portable/Rename/ConflictEngine/RenamedSpansTracker.cs index 749b8e9f048ee..bf0f680d53c00 100644 --- a/src/Workspaces/Core/Portable/Rename/ConflictEngine/RenamedSpansTracker.cs +++ b/src/Workspaces/Core/Portable/Rename/ConflictEngine/RenamedSpansTracker.cs @@ -2,8 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#nullable disable - using System; using System.Collections.Generic; using System.Collections.Immutable; @@ -12,6 +10,7 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeCleanup; using Microsoft.CodeAnalysis.Formatting; +using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Simplification; using Microsoft.CodeAnalysis.Text; using Roslyn.Utilities; @@ -48,7 +47,7 @@ internal void AddComplexifiedSpan(DocumentId documentId, TextSpan oldSpan, TextS _documentToComplexifiedSpansMap[documentId] = spans; } - spans.Add(new MutableComplexifiedSpan() { OriginalSpan = oldSpan, NewSpan = newSpan, ModifiedSubSpans = modifiedSubSpans }); + spans.Add(new MutableComplexifiedSpan(originalSpan: oldSpan, newSpan: newSpan, modifiedSubSpans: modifiedSubSpans)); } // Given a position in the old solution, we get back the new adjusted position @@ -124,6 +123,14 @@ private class MutableComplexifiedSpan public TextSpan OriginalSpan; public TextSpan NewSpan; public List<(TextSpan oldSpan, TextSpan newSpan)> ModifiedSubSpans; + + public MutableComplexifiedSpan( + TextSpan originalSpan, TextSpan newSpan, List<(TextSpan oldSpan, TextSpan newSpan)> modifiedSubSpans) + { + OriginalSpan = originalSpan; + NewSpan = newSpan; + ModifiedSubSpans = modifiedSubSpans; + } } internal void ClearDocuments(IEnumerable conflictLocationDocumentIds) @@ -149,7 +156,7 @@ internal async Task SimplifyAsync(Solution solution, IEnumerable SimplifyAsync(Solution solution, IEnumerable(root) - .Select(x => Tuple.Create(renameAnnotations.GetAnnotations(x).First(), (SyntaxNode)x)); + .Select(x => Tuple.Create(renameAnnotations.GetAnnotations(x).First(), (SyntaxNode)x!)); var modifiedTokensInComplexifiedStatements = new HashSet(); foreach (var annotationAndNode in nodeAnnotations) diff --git a/src/Workspaces/Core/Portable/Rename/ConflictResolution.cs b/src/Workspaces/Core/Portable/Rename/ConflictResolution.cs index 43d1cc00d6a5e..15ebca24d0bf0 100644 --- a/src/Workspaces/Core/Portable/Rename/ConflictResolution.cs +++ b/src/Workspaces/Core/Portable/Rename/ConflictResolution.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System.Collections.Immutable; +using System.Diagnostics.CodeAnalysis; using Microsoft.CodeAnalysis.Rename.ConflictEngine; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Text; @@ -12,19 +13,32 @@ namespace Microsoft.CodeAnalysis.Rename { internal readonly partial struct ConflictResolution { + /// + /// A flag indicate if the rename operation is successful or not. + /// If this is false, the would be with this resolution. All the other field or property would be or empty. + /// If this is true, the would be null. All the other fields or properties would be valid. + /// + [MemberNotNullWhen(false, nameof(ErrorMessage))] + [MemberNotNullWhen(true, nameof(_newSolutionWithoutRenamedDocument))] + [MemberNotNullWhen(true, nameof(_renamedDocument))] + [MemberNotNullWhen(true, nameof(OldSolution))] + [MemberNotNullWhen(true, nameof(NewSolution))] + [MemberNotNullWhen(true, nameof(ReplacementTextValid))] + public bool IsSuccessful { get; } + public readonly string? ErrorMessage; - private readonly Solution _newSolutionWithoutRenamedDocument; - private readonly (DocumentId documentId, string newName) _renamedDocument; + private readonly Solution? _newSolutionWithoutRenamedDocument; + private readonly (DocumentId documentId, string newName)? _renamedDocument; - public readonly Solution OldSolution; + public readonly Solution? OldSolution; /// /// The final solution snapshot. Including any renamed documents. /// - public readonly Solution NewSolution; + public readonly Solution? NewSolution; - public readonly bool ReplacementTextValid; + public readonly bool? ReplacementTextValid; /// /// The list of all document ids of documents that have been touched for this rename operation. @@ -37,10 +51,22 @@ namespace Microsoft.CodeAnalysis.Rename private readonly ImmutableDictionary> _documentToComplexifiedSpansMap; private readonly ImmutableDictionary> _documentToRelatedLocationsMap; -#nullable disable warnings - public ConflictResolution(string errorMessage) : this() - => ErrorMessage = errorMessage; -#nullable enable warnings + public ConflictResolution(string errorMessage) + { + IsSuccessful = false; + ErrorMessage = errorMessage; + + _newSolutionWithoutRenamedDocument = null; + _renamedDocument = null; + OldSolution = null; + NewSolution = null; + ReplacementTextValid = null; + DocumentIds = ImmutableArray.Empty; + RelatedLocations = ImmutableArray.Empty; + _documentToModifiedSpansMap = ImmutableDictionary>.Empty; + _documentToComplexifiedSpansMap = ImmutableDictionary>.Empty; + _documentToRelatedLocationsMap = ImmutableDictionary>.Empty; + } public ConflictResolution( Solution oldSolution, @@ -52,7 +78,9 @@ public ConflictResolution(string errorMessage) : this() ImmutableDictionary> documentToComplexifiedSpansMap, ImmutableDictionary> documentToRelatedLocationsMap) { + IsSuccessful = true; ErrorMessage = null; + OldSolution = oldSolution; _newSolutionWithoutRenamedDocument = newSolutionWithoutRenamedDocument; ReplacementTextValid = replacementTextValid; @@ -63,9 +91,9 @@ public ConflictResolution(string errorMessage) : this() _documentToComplexifiedSpansMap = documentToComplexifiedSpansMap; _documentToRelatedLocationsMap = documentToRelatedLocationsMap; - NewSolution = _renamedDocument.documentId == null + NewSolution = _renamedDocument.Value.documentId == null ? _newSolutionWithoutRenamedDocument - : _newSolutionWithoutRenamedDocument.WithDocumentName(_renamedDocument.documentId, _renamedDocument.newName); + : _newSolutionWithoutRenamedDocument.WithDocumentName(_renamedDocument.Value.documentId, _renamedDocument.Value.newName); } public ImmutableArray<(TextSpan oldSpan, TextSpan newSpan)> GetComplexifiedSpans(DocumentId documentId) diff --git a/src/Workspaces/Core/Portable/Rename/IRemoteRenamerService.cs b/src/Workspaces/Core/Portable/Rename/IRemoteRenamerService.cs index 733ca2754367f..755c613890c60 100644 --- a/src/Workspaces/Core/Portable/Rename/IRemoteRenamerService.cs +++ b/src/Workspaces/Core/Portable/Rename/IRemoteRenamerService.cs @@ -340,15 +340,15 @@ internal partial struct ConflictResolution { public async Task DehydrateAsync(CancellationToken cancellationToken) { - if (ErrorMessage != null) + if (!IsSuccessful) return new SerializableConflictResolution(ErrorMessage, resolution: null); var documentTextChanges = await RemoteUtilities.GetDocumentTextChangesAsync(OldSolution, _newSolutionWithoutRenamedDocument, cancellationToken).ConfigureAwait(false); return new SerializableConflictResolution( errorMessage: null, new SuccessfulConflictResolution( - ReplacementTextValid, - _renamedDocument, + ReplacementTextValid.Value, + _renamedDocument.Value, DocumentIds, RelatedLocations, documentTextChanges, diff --git a/src/Workspaces/Core/Portable/Rename/RenameEntityKind.cs b/src/Workspaces/Core/Portable/Rename/RenameEntityKind.cs index 50fb4d2496ced..f6bdceb7beeeb 100644 --- a/src/Workspaces/Core/Portable/Rename/RenameEntityKind.cs +++ b/src/Workspaces/Core/Portable/Rename/RenameEntityKind.cs @@ -2,8 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#nullable disable - namespace Microsoft.CodeAnalysis.Rename { public enum RenameEntityKind diff --git a/src/Workspaces/Core/Portable/Rename/RenameUtilities.cs b/src/Workspaces/Core/Portable/Rename/RenameUtilities.cs index 8230296a8d705..8b0b87b19eec6 100644 --- a/src/Workspaces/Core/Portable/Rename/RenameUtilities.cs +++ b/src/Workspaces/Core/Portable/Rename/RenameUtilities.cs @@ -2,8 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#nullable disable - using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; @@ -79,11 +77,11 @@ internal static IEnumerable GetDocumentsAffectedByRename(ISymbol symbo if (IsSymbolDefinedInsideMethod(symbol)) { // if the symbol was declared inside of a method, don't check for conflicts in non-renamed documents. - return renameLocations.Select(l => solution.GetDocument(l.DocumentId)); + return renameLocations.Select(l => solution.GetRequiredDocument(l.DocumentId)); } else { - var documentsOfRenameSymbolDeclaration = symbol.Locations.Where(l => l.IsInSource).Select(l => solution.GetDocument(l.SourceTree)); + var documentsOfRenameSymbolDeclaration = symbol.Locations.Where(l => l.IsInSource).Select(l => solution.GetRequiredDocument(l.SourceTree!)); var projectIdsOfRenameSymbolDeclaration = documentsOfRenameSymbolDeclaration.SelectMany(d => d.GetLinkedDocumentIds()) .Concat(documentsOfRenameSymbolDeclaration.First().Id) @@ -94,7 +92,7 @@ internal static IEnumerable GetDocumentsAffectedByRename(ISymbol symbo { var isSubset = renameLocations.Select(l => l.DocumentId.ProjectId).Distinct().Except(projectIdsOfRenameSymbolDeclaration).IsEmpty(); Contract.ThrowIfFalse(isSubset); - return projectIdsOfRenameSymbolDeclaration.SelectMany(p => solution.GetProject(p).Documents); + return projectIdsOfRenameSymbolDeclaration.SelectMany(p => solution.GetRequiredProject(p).Documents); } else { @@ -102,7 +100,7 @@ internal static IEnumerable GetDocumentsAffectedByRename(ISymbol symbo // the rename symbol. Other projects should not be affected by the rename. var relevantProjects = projectIdsOfRenameSymbolDeclaration.Concat(projectIdsOfRenameSymbolDeclaration.SelectMany(p => solution.GetProjectDependencyGraph().GetProjectsThatDirectlyDependOnThisProject(p))).Distinct(); - return relevantProjects.SelectMany(p => solution.GetProject(p).Documents); + return relevantProjects.SelectMany(p => solution.GetRequiredProject(p).Documents); } } } diff --git a/src/Workspaces/Core/Portable/Rename/Renamer.cs b/src/Workspaces/Core/Portable/Rename/Renamer.cs index 40bc229c1e70a..ca4f72bce5c47 100644 --- a/src/Workspaces/Core/Portable/Rename/Renamer.cs +++ b/src/Workspaces/Core/Portable/Rename/Renamer.cs @@ -54,12 +54,16 @@ public static Task RenameSymbolAsync(Solution solution, ISymbol symbol var resolution = await RenameSymbolAsync(solution, symbol, newName, options, CodeActionOptions.DefaultProvider, nonConflictSymbols: null, cancellationToken).ConfigureAwait(false); - // This is a public entry-point. So if rename failed to resolve conflicts, we report that back to caller as - // an exception. - if (resolution.ErrorMessage != null) + if (resolution.IsSuccessful) + { + return resolution.NewSolution; + } + else + { + // This is a public entry-point. So if rename failed to resolve conflicts, we report that back to caller as + // an exception. throw new ArgumentException(resolution.ErrorMessage); - - return resolution.NewSolution; + } } [Obsolete("Use overload taking RenameOptions")] diff --git a/src/Workspaces/Core/Portable/Rename/TokenRenameInfo.cs b/src/Workspaces/Core/Portable/Rename/TokenRenameInfo.cs index 528086b125e3f..f8ca1c5c9f08e 100644 --- a/src/Workspaces/Core/Portable/Rename/TokenRenameInfo.cs +++ b/src/Workspaces/Core/Portable/Rename/TokenRenameInfo.cs @@ -2,8 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#nullable disable - using System.Collections.Generic; using Roslyn.Utilities; @@ -15,31 +13,38 @@ internal sealed class TokenRenameInfo public IEnumerable Symbols { get; private set; } public bool IsMemberGroup { get; private set; } + public TokenRenameInfo(bool hasSymbols, IEnumerable symbols, bool isMemberGroup) + { + HasSymbols = hasSymbols; + Symbols = symbols; + IsMemberGroup = isMemberGroup; + } + public static TokenRenameInfo CreateMemberGroupTokenInfo(IEnumerable symbols) { return new TokenRenameInfo - { - HasSymbols = true, - IsMemberGroup = true, - Symbols = symbols - }; + ( + hasSymbols: true, + isMemberGroup: true, + symbols: symbols + ); } public static TokenRenameInfo CreateSingleSymbolTokenInfo(ISymbol symbol) { return new TokenRenameInfo - { - HasSymbols = true, - IsMemberGroup = false, - Symbols = SpecializedCollections.SingletonEnumerable(symbol) - }; + ( + hasSymbols: true, + isMemberGroup: false, + symbols: SpecializedCollections.SingletonEnumerable(symbol) + ); } - public static TokenRenameInfo NoSymbolsTokenInfo = new() - { - HasSymbols = false, - IsMemberGroup = false, - Symbols = SpecializedCollections.EmptyEnumerable() - }; + public static TokenRenameInfo NoSymbolsTokenInfo = new + ( + hasSymbols: false, + isMemberGroup: false, + symbols: SpecializedCollections.EmptyEnumerable() + ); } }