提交 b9a3e825 编写于 作者: C CyrusNajmabadi

Fix crash in AddUsing when changing casing of a typename.

上级 ca1b475e
......@@ -4554,5 +4554,54 @@ void M()
}
}");
}
[WorkItem(19218, "https://github.com/dotnet/roslyn/issues/19218")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddImport)]
public async Task TestChangeCaseWithUsingsInNestedNamespace()
{
await TestInRegularAndScriptAsync(
@"namespace VS
{
interface IVsStatusbar
{
}
}
namespace Outer
{
using System;
class C
{
void M()
{
// Note: IVsStatusBar is cased incorrectly.
[|IVsStatusBar|] b;
}
}
}
",
@"namespace VS
{
interface IVsStatusbar
{
}
}
namespace Outer
{
using System;
using VS;
class C
{
void M()
{
IVsStatusbar b;
}
}
}
");
}
}
}
\ No newline at end of file
......@@ -107,7 +107,8 @@ private class ParentCodeAction : CodeAction.CodeActionWithNestedActions
CancellationToken cancellationToken)
{
var oldDocument = document;
reference.ReplaceNameNode(ref node, ref document, cancellationToken);
(node, document) = await reference.ReplaceNameNodeAsync(
node, document, cancellationToken).ConfigureAwait(false);
var newDocument = await reference.provider.AddImportAsync(
node, reference.SearchResult.NameParts, document, placeSystemNamespaceFirst, cancellationToken).ConfigureAwait(false);
......
......@@ -105,9 +105,8 @@ protected override async Task<IEnumerable<CodeActionOperation>> ComputeOperation
var reference = service.GetReference(resolvedPath, MetadataReferenceProperties.Assembly);
// First add the "using/import" directive in the code.
var node = _node;
var document = _document;
_reference.ReplaceNameNode(ref node, ref document, cancellationToken);
(SyntaxNode node, Document document) = await _reference.ReplaceNameNodeAsync(
_node, _document, cancellationToken).ConfigureAwait(false);
var newDocument = await _reference.provider.AddImportAsync(
node, _reference.SearchResult.NameParts, document, _placeSystemNamespaceFirst, cancellationToken).ConfigureAwait(false);
......
......@@ -92,26 +92,28 @@ public override int GetHashCode()
return Hash.CombineValues(this.SearchResult.NameParts);
}
protected void ReplaceNameNode(
ref SyntaxNode contextNode, ref Document document, CancellationToken cancellationToken)
protected async Task<(SyntaxNode, Document)> ReplaceNameNodeAsync(
SyntaxNode contextNode, Document document, CancellationToken cancellationToken)
{
if (!this.SearchResult.DesiredNameDiffersFromSourceName())
if (this.SearchResult.DesiredNameDiffersFromSourceName())
{
return;
}
var identifier = SearchResult.NameNode.GetFirstToken();
var generator = SyntaxGenerator.GetGenerator(document);
var newIdentifier = generator.IdentifierName(SearchResult.DesiredName).GetFirstToken().WithTriviaFrom(identifier);
var annotation = new SyntaxAnnotation();
var root = contextNode.SyntaxTree.GetRoot(cancellationToken);
root = root.ReplaceToken(identifier, newIdentifier.WithAdditionalAnnotations(annotation));
document = document.WithSyntaxRoot(root);
var identifier = SearchResult.NameNode.GetFirstToken();
var generator = SyntaxGenerator.GetGenerator(document);
var newIdentifier = generator.IdentifierName(SearchResult.DesiredName).GetFirstToken().WithTriviaFrom(identifier);
var annotation = new SyntaxAnnotation();
var currentRoot = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
contextNode = currentRoot.GetAnnotatedTokens(annotation).First().Parent;
}
var root = contextNode.SyntaxTree.GetRoot(cancellationToken);
root = root.ReplaceToken(identifier, newIdentifier.WithAdditionalAnnotations(annotation));
document = document.WithSyntaxRoot(root);
contextNode = root.GetAnnotatedTokens(annotation).First().Parent;
return (contextNode, document);
}
public abstract Task<CodeAction> CreateCodeActionAsync(Document document, SyntaxNode node, bool placeSystemNamespaceFirst, CancellationToken cancellationToken);
}
}
}
}
\ No newline at end of file
......@@ -2,9 +2,11 @@
using System;
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.FindSymbols;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CodeFixes.AddImport
......@@ -61,22 +63,23 @@ public override int GetHashCode()
protected virtual Solution GetUpdatedSolution(Document newDocument)
=> newDocument.Project.Solution;
private Task<Document> UpdateDocumentAsync(
private async Task<Document> UpdateDocumentAsync(
Document document, SyntaxNode contextNode,
bool placeSystemNamespaceFirst, bool hasExistingImport,
CancellationToken cancellationToken)
{
ReplaceNameNode(ref contextNode, ref document, cancellationToken);
// Defer to the language to add the actual import/using.
if (hasExistingImport)
{
return Task.FromResult(document);
return document;
}
return provider.AddImportAsync(contextNode,
this.SymbolResult.Symbol, document,
placeSystemNamespaceFirst, cancellationToken);
(var newContextNode, var newDocument) = await ReplaceNameNodeAsync(
contextNode, document, cancellationToken).ConfigureAwait(false);
return await provider.AddImportAsync(
newContextNode, this.SymbolResult.Symbol, newDocument,
placeSystemNamespaceFirst, cancellationToken).ConfigureAwait(false);
}
public override async Task<CodeAction> CreateCodeActionAsync(
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册