diff --git a/src/Features/Core/Portable/DocumentationComments/CodeFixes/AbstractRemoveDocCommentNodeCodeFixProvider.cs b/src/Features/Core/Portable/DocumentationComments/CodeFixes/AbstractRemoveDocCommentNodeCodeFixProvider.cs index 715413ba05dd6abf3227b135ffafe0ead363ed09..fd0b850515730b8e8031c16aedfc6e4113e6ad64 100644 --- a/src/Features/Core/Portable/DocumentationComments/CodeFixes/AbstractRemoveDocCommentNodeCodeFixProvider.cs +++ b/src/Features/Core/Portable/DocumentationComments/CodeFixes/AbstractRemoveDocCommentNodeCodeFixProvider.cs @@ -1,22 +1,24 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.CodeFixes; -using System.Collections.Generic; using Microsoft.CodeAnalysis.Text; namespace Microsoft.CodeAnalysis.DiagnosticComments.CodeFixes { - internal abstract class AbstractRemoveDocCommentNodeCodeFixProvider : CodeFixProvider + internal abstract class AbstractRemoveDocCommentNodeCodeFixProvider : CodeFixProvider + where TXmlElementSyntax : SyntaxNode { public override FixAllProvider GetFixAllProvider() => WellKnownFixAllProviders.BatchFixer; public abstract override ImmutableArray FixableDiagnosticIds { get; } + protected abstract string DocCommentSignifierToken { get; } protected abstract SyntaxTriviaList GetRevisedDocCommentTrivia(string docCommentText); @@ -29,31 +31,25 @@ public async sealed override Task RegisterCodeFixesAsync(CodeFixContext context) { context.RegisterCodeFix( new MyCodeAction( - c => RemoveDuplicateParamTag(context.Document, context.Span, c)), + c => RemoveDuplicateParamTagAsync(context.Document, context.Span, c)), context.Diagnostics); } - - return; } - private SyntaxNode GetParamNode(SyntaxNode root, TextSpan span, CancellationToken cancellationToken = default(CancellationToken)) + private TXmlElementSyntax GetParamNode(SyntaxNode root, TextSpan span, CancellationToken cancellationToken = default(CancellationToken)) { // First, we get the node the diagnostic fired on // Then, we climb the tree to the first parent that is of the type XMLElement // This is to correctly handle XML nodes that are nested in other XML nodes, so we only // remove the node the diagnostic fired on and its children, but no parent nodes var paramNode = root.FindNode(span, findInsideTrivia: true); - while (paramNode != null && !(paramNode is TXMLElement)) - { - paramNode = paramNode.Parent; - } - - return paramNode is TXMLElement ? paramNode : null; + return paramNode.FirstAncestorOrSelf(); } - private async Task RemoveDuplicateParamTag(Document document, TextSpan span, CancellationToken cancellationToken) + private async Task RemoveDuplicateParamTagAsync( + Document document, TextSpan span, CancellationToken cancellationToken) { - var root = await document.GetSyntaxRootAsync().ConfigureAwait(false); + var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var paramNode = GetParamNode(root, span, cancellationToken); var removedNodes = new List { paramNode }; @@ -80,8 +76,8 @@ private async Task RemoveDuplicateParamTag(Document document, TextSpan private class MyCodeAction : CodeAction.DocumentChangeAction { - public MyCodeAction(Func> createChangedDocument) : - base(FeaturesResources.Remove_tag, createChangedDocument) + public MyCodeAction(Func> createChangedDocument) + : base(FeaturesResources.Remove_tag, createChangedDocument) { } }