/// <summary> /// Enables editing all the symbol's declarations. /// Partial types and methods may have more than one declaration. /// </summary> /// <param name="symbol">The symbol to be edited.</param> /// <param name="editAction">The action that makes edits to the declaration.</param> /// <param name="cancellationToken">An optional <see cref="CancellationToken"/>.</param> /// <returns>The new symbol including the changes.</returns> public async Task<ISymbol> EditAllDeclarationsAsync( ISymbol symbol, AsyncDeclarationEditAction editAction, CancellationToken cancellationToken = default(CancellationToken)) { var currentSymbol = await this.GetCurrentSymbolAsync(symbol, cancellationToken).ConfigureAwait(false); CheckSymbolArgument(currentSymbol, symbol); var declsByDocId = this.GetDeclarations(currentSymbol).ToLookup(d => _currentSolution.GetDocument(d.SyntaxTree).Id); var solutionEditor = new SolutionEditor(_currentSolution); foreach (var declGroup in declsByDocId) { var docId = declGroup.Key; var editor = await solutionEditor.GetDocumentEditorAsync(docId, cancellationToken).ConfigureAwait(false); foreach (var decl in declGroup) { editor.TrackNode(decl); // ensure the declaration gets tracked await editAction(editor, decl, cancellationToken).ConfigureAwait(false); } } _currentSolution = solutionEditor.GetChangedSolution(); // try to find new symbol by looking up via original declarations foreach (var declGroup in declsByDocId) { var doc = _currentSolution.GetDocument(declGroup.Key); var model = await doc.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); foreach (var decl in declGroup) { var newDeclaration = model.SyntaxTree.GetRoot(cancellationToken).GetCurrentNode(decl); if (newDeclaration != null) { var newSymbol = model.GetDeclaredSymbol(newDeclaration); if (newSymbol != null) { return newSymbol; } } } } // otherwise fallback to rebinding with original symbol return await GetCurrentSymbolAsync(symbol, cancellationToken).ConfigureAwait(false); }