public override async Task RenameAsync(IProjectTreeActionHandlerContext context, IProjectTree node, string value) { Requires.NotNull(context, nameof(Context)); Requires.NotNull(node, nameof(node)); Requires.NotNullOrEmpty(value, nameof(value)); string?oldFilePath = node.FilePath; string oldName = Path.GetFileNameWithoutExtension(oldFilePath); string newFileWithExtension = value; CodeAnalysis.Project?project = GetCurrentProject(); // Rename the file await CPSRenameAsync(context, node, value); if (await IsAutomationFunctionAsync() || node.IsFolder || _vsOnlineServices.ConnectedToVSOnline) { // Do not display rename Prompt return; } if (project is null) { return; } string newName = Path.GetFileNameWithoutExtension(newFileWithExtension); if (!await CanRenameType(project, oldName, newName)) { return; } (bool result, Renamer.RenameDocumentActionSet? documentRenameResult) = await GetRenameSymbolsActions(project, oldFilePath, newFileWithExtension); if (result == false || documentRenameResult == null) { return; } // Ask if the user wants to rename the symbol bool userWantsToRenameSymbol = await CheckUserConfirmation(oldName); if (!userWantsToRenameSymbol) { return; } _threadingService.RunAndForget(async() => { // TODO - implement PublishAsync() to sync with LanguageService // https://github.com/dotnet/project-system/issues/3425) // await _languageService.PublishAsync(treeVersion); IVsOperationProgressStageStatus stageStatus = (await _operationProgressService.GetValueAsync()).GetStageStatus(CommonOperationProgressStageIds.Intellisense); await stageStatus.WaitForCompletionAsync(); // Apply actions and notify other VS features CodeAnalysis.Solution?currentSolution = GetCurrentProject()?.Solution; if (currentSolution == null) { return; } string renameOperationName = string.Format(CultureInfo.CurrentCulture, VSResources.Renaming_Type_from_0_to_1, oldName, value); (WaitIndicatorResult result, CodeAnalysis.Solution renamedSolution) = _waitService.WaitForAsyncFunctionWithResult( title: VSResources.Renaming_Type, message: renameOperationName, allowCancel: true, token => documentRenameResult.UpdateSolutionAsync(currentSolution, token)); // Do not warn the user if the rename was cancelled by the user if (result.WasCanceled()) { return; } await _projectVsServices.ThreadingService.SwitchToUIThread(); if (!_roslynServices.ApplyChangesToSolution(currentSolution.Workspace, renamedSolution)) { string failureMessage = string.Format(CultureInfo.CurrentCulture, VSResources.RenameSymbolFailed, oldName); _userNotificationServices.ShowWarning(failureMessage); } return; }, _unconfiguredProject); }
internal async Task HandleRenameAsync(string oldFilePath, string newFilePath) { // Do not offer to rename the file in VS Online scenarios. if (_vsOnlineServices.ConnectedToVSOnline) { return; } // Do not offer to rename types if the user changes the file extensions if (!oldFilePath.EndsWith(Path.GetExtension(newFilePath), StringComparisons.Paths)) { return; } if (GetCurrentProject() is null) { return; } // see if the current project contains a compilation (bool success, bool isCaseSensitive) = await TryDetermineIfCompilationIsCaseSensitiveAsync(GetCurrentProject()); if (!success) { return; } // Check that the new name is a valid identifier in the current programming language string oldName = Path.GetFileNameWithoutExtension(oldFilePath); string newName = Path.GetFileNameWithoutExtension(newFilePath); if (!CanHandleRename(oldName, newName, isCaseSensitive)) { return; } // Check if there are any symbols that need to be renamed ISymbol?symbol = await TryGetSymbolToRename(oldName, oldFilePath, newFilePath, isCaseSensitive, GetCurrentProject); if (symbol is null) { return; } // Ask if the user wants to rename the symbol bool userWantsToRenameSymbol = await CheckUserConfirmation(oldName); if (!userWantsToRenameSymbol) { return; } // Try and apply the changes to the current solution await _projectVsServices.ThreadingService.SwitchToUIThread(); string renameOperationName = string.Format(CultureInfo.CurrentCulture, VSResources.Renaming_Type_from_0_to_1, oldName, newName); (WaitIndicatorResult result, bool renamed) = _waitService.WaitForAsyncFunctionWithResult( title: VSResources.Renaming_Type, message: renameOperationName, allowCancel: true, token => RenameAsync(oldFilePath, newFilePath, isCaseSensitive, oldName, newName, symbol, renameOperationName, token)); // Do not warn the user if the rename was cancelled by the user if (result.WasCanceled()) { return; } // Notify the user if the rename could not be performed if (!renamed) { string failureMessage = string.Format(CultureInfo.CurrentCulture, VSResources.RenameSymbolFailed, oldName); _userNotificationServices.ShowWarning(failureMessage); } }