提交 b20e7817 编写于 作者: A Abraham Hosch

Respond to comments

上级 7e4275cb
......@@ -205,7 +205,7 @@
<Compile Include="Diagnostics\UseImplicitOrExplicitType\UseExplicitTypeTests_FixAllTests.cs" />
<Compile Include="Diagnostics\UseImplicitOrExplicitType\UseImplicitTypeTests_FixAllTests.cs" />
<Compile Include="Diagnostics\UseImplicitOrExplicitType\UseImplicitTypeTests.cs" />
<Compile Include="DocumentationComments\CodeFixes\AddDocCommentParamNodeCodeFixProviderTests.cs" />
<Compile Include="DocumentationComments\CodeFixes\AddDocCommentNodesCodeFixProviderTests.cs" />
<Compile Include="DocumentationComments\CodeFixes\RemoveDocCommentNodeCodeFixProviderTests.cs" />
<Compile Include="GoToAdjacentMember\CSharpGoToAdjacentMemberTests.cs" />
<Compile Include="Diagnostics\AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest.cs" />
......
......@@ -11,11 +11,11 @@
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.DocumentationComments.CodeFixes
{
public class AddDocCommentParamNodeCodeFixProviderTests : AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest
public class AddDocCommentNodesCodesFixProviderTests : AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest
{
internal override Tuple<DiagnosticAnalyzer, CodeFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace)
{
return new Tuple<DiagnosticAnalyzer, CodeFixProvider>(null, new CSharpAddDocCommentParamNodeCodeFixProvider());
return new Tuple<DiagnosticAnalyzer, CodeFixProvider>(null, new CSharpAddDocCommentNodesCodeFixProvider());
}
private async Task TestAsync(string initial, string expected)
......@@ -24,7 +24,7 @@ private async Task TestAsync(string initial, string expected)
await TestAsync(initial, expected, parseOptions: parseOptions, compareTokens: false);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddDocCommentParamNode)]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddDocCommentNodes)]
public async Task AddsParamTag_NoNodesBefore()
{
var initial =
......@@ -53,7 +53,7 @@ public async Task AddsParamTag_NoNodesBefore()
await TestAsync(initial, expected);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddDocCommentParamNode)]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddDocCommentNodes)]
public async Task AddsParamTag_NoNodesAfter()
{
var initial =
......@@ -82,7 +82,7 @@ public async Task AddsParamTag_NoNodesAfter()
await TestAsync(initial, expected);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddDocCommentParamNode)]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddDocCommentNodes)]
public async Task AddsParamTag_NodesBeforeAndAfter()
{
var initial =
......@@ -112,7 +112,7 @@ public async Task AddsParamTag_NodesBeforeAndAfter()
await TestAsync(initial, expected);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddDocCommentParamNode)]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddDocCommentNodes)]
public async Task AddsParamTag_NodesBeforeAndAfter_RawTextInComment()
{
var initial =
......@@ -144,7 +144,7 @@ public async Task AddsParamTag_NodesBeforeAndAfter_RawTextInComment()
await TestAsync(initial, expected);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddDocCommentParamNode)]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddDocCommentNodes)]
public async Task AddsParamTag_NodesBeforeAndAfter_WithContent()
{
var initial =
......@@ -174,7 +174,7 @@ public async Task AddsParamTag_NodesBeforeAndAfter_WithContent()
await TestAsync(initial, expected);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddDocCommentParamNode)]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddDocCommentNodes)]
public async Task AddsParamTag_NestedInSummaryTag()
{
var initial =
......@@ -201,7 +201,7 @@ public async Task AddsParamTag_NestedInSummaryTag()
await TestAsync(initial, expected);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddDocCommentParamNode)]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddDocCommentNodes)]
public async Task AddsParamTag_InsertsAfterTypeparamTag()
{
var initial =
......@@ -230,7 +230,7 @@ public async Task AddsParamTag_InsertsAfterTypeparamTag()
await TestAsync(initial, expected);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddDocCommentParamNode)]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddDocCommentNodes)]
public async Task AddsParamTag_BeforeNode_EverythingOnOneLine()
{
var initial =
......@@ -253,7 +253,7 @@ public async Task AddsParamTag_BeforeNode_EverythingOnOneLine()
await TestAsync(initial, expected);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddDocCommentParamNode)]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddDocCommentNodes)]
public async Task AddsParamTag_AfterNode_EverythingOnOneLine()
{
var initial =
......@@ -276,7 +276,7 @@ public async Task AddsParamTag_AfterNode_EverythingOnOneLine()
await TestAsync(initial, expected);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddDocCommentParamNode)]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddDocCommentNodes)]
public async Task AddsParamTag_BeforeNode_JustParamNode()
{
var initial =
......@@ -299,7 +299,7 @@ public async Task AddsParamTag_BeforeNode_JustParamNode()
await TestAsync(initial, expected);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddDocCommentParamNode)]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddDocCommentNodes)]
public async Task AddsParamTag_AfterNode_JustParamNode()
{
var initial =
......@@ -322,7 +322,7 @@ public async Task AddsParamTag_AfterNode_JustParamNode()
await TestAsync(initial, expected);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddDocCommentParamNode)]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddDocCommentNodes)]
public async Task AddsParamTag_Ctor()
{
var initial =
......@@ -351,7 +351,7 @@ public async Task AddsParamTag_Ctor()
await TestAsync(initial, expected);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddDocCommentParamNode)]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddDocCommentNodes)]
public async Task AddsParamTag_Delegate()
{
var initial =
......@@ -380,7 +380,7 @@ public async Task AddsParamTag_Delegate()
await TestAsync(initial, expected);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddDocCommentParamNode)]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddDocCommentNodes)]
public async Task AddsParamTag_Operator()
{
var initial =
......@@ -431,7 +431,7 @@ public MyStruct(int val)
}
[Fact]
[Trait(Traits.Feature, Traits.Features.CodeActionsAddDocCommentParamNode)]
[Trait(Traits.Feature, Traits.Features.CodeActionsAddDocCommentNodes)]
[Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)]
public async Task TestFixAllInDocument_MultipleParamNodesInVariousPlaces()
{
......@@ -462,7 +462,7 @@ public async Task TestFixAllInDocument_MultipleParamNodesInVariousPlaces()
}
[Fact]
[Trait(Traits.Feature, Traits.Features.CodeActionsAddDocCommentParamNode)]
[Trait(Traits.Feature, Traits.Features.CodeActionsAddDocCommentNodes)]
[Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)]
public async Task TestFixAllInDocument()
{
......@@ -576,7 +576,7 @@ class Program3
}
[Fact]
[Trait(Traits.Feature, Traits.Features.CodeActionsAddDocCommentParamNode)]
[Trait(Traits.Feature, Traits.Features.CodeActionsAddDocCommentNodes)]
[Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)]
public async Task TestFixAllInProject()
{
......@@ -678,7 +678,7 @@ class Program3
}
[Fact]
[Trait(Traits.Feature, Traits.Features.CodeActionsAddDocCommentParamNode)]
[Trait(Traits.Feature, Traits.Features.CodeActionsAddDocCommentNodes)]
[Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)]
public async Task TestFixAllInSolution()
{
......
......@@ -28,7 +28,7 @@ public static class Features
public const string Classification = nameof(Classification);
public const string ClassView = nameof(ClassView);
public const string CodeActionsAddConstructorParameters = "CodeActions.AddConstructorParameters";
public const string CodeActionsAddDocCommentParamNode = "CodeActions.AddDocCommentParamNode";
public const string CodeActionsAddDocCommentNodes = "CodeActions.AddDocCommentParamNode";
public const string CodeActionsAddAsync = "CodeActions.AddAsync";
public const string CodeActionsAddAwait = "CodeActions.AddAwait";
public const string CodeActionsAddBraces = "CodeActions.AddBraces";
......
......@@ -272,7 +272,7 @@
<Compile Include="Diagnostics\Analyzers\CSharpUseExplicitTypeDiagnosticAnalyzer.cs" />
<Compile Include="Diagnostics\Analyzers\CSharpUseImplicitTypeDiagnosticAnalyzer.cs" />
<Compile Include="Diagnostics\CSharpAnalyzerDriverService.cs" />
<Compile Include="DocumentationComments\CodeFixes\CSharpAddDocCommentParamNodeCodeFixProvider.cs" />
<Compile Include="DocumentationComments\CodeFixes\CSharpAddDocCommentNodesCodeFixProvider.cs" />
<Compile Include="DocumentationComments\CodeFixes\CSharpRemoveDocCommentNodeCodeFixProvider.cs" />
<Compile Include="DocumentationComments\CSharpDocumentationCommentFormattingService.cs" />
<Compile Include="DocumentationComments\DocumentationCommentUtilities.cs" />
......
// 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.Composition;
......@@ -7,14 +8,13 @@
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System;
namespace Microsoft.CodeAnalysis.DiagnosticComments.CodeFixes
{
[ExportCodeFixProvider(LanguageNames.CSharp, Name = PredefinedCodeFixProviderNames.AddAttribute), Shared]
[ExportCodeFixProvider(LanguageNames.CSharp, Name = PredefinedCodeFixProviderNames.AddDocCommentNodes), Shared]
[ExtensionOrder(After = PredefinedCodeFixProviderNames.ImplementInterface)]
internal class CSharpAddDocCommentParamNodeCodeFixProvider
: AbstractAddDocCommentParamNodeCodeFixProvider<XmlElementSyntax, XmlNameAttributeSyntax, XmlTextSyntax, MemberDeclarationSyntax, ParameterSyntax>
internal class CSharpAddDocCommentNodesCodeFixProvider
: AbstractAddDocCommentNodesCodeFixProvider<XmlElementSyntax, XmlNameAttributeSyntax, XmlTextSyntax, MemberDeclarationSyntax>
{
/// <summary>
/// Parameter has no matching param tag in XML comment
......@@ -23,6 +23,8 @@ internal class CSharpAddDocCommentParamNodeCodeFixProvider
public override ImmutableArray<string> FixableDiagnosticIds { get; } = ImmutableArray.Create(CS1573);
protected override string NodeName { get; } = "param";
protected override List<XmlNameAttributeSyntax> GetNameAttributes(XmlElementSyntax node)
=> node.StartTag.Attributes.OfType<XmlNameAttributeSyntax>().ToList();
......@@ -37,11 +39,6 @@ protected override string GetXmlElementLocalName(XmlElementSyntax element)
protected override List<string> GetParameterNames(MemberDeclarationSyntax member)
{
if (member is BaseMethodDeclarationSyntax)
{
return ((BaseMethodDeclarationSyntax)member).ParameterList.Parameters.Select(s => s.Identifier.ValueText).ToList();
}
var parameterList = (ParameterListSyntax)member.DescendantNodes(descendIntoChildren: _ => true, descendIntoTrivia: false)
.FirstOrDefault(f => f is ParameterListSyntax);
......@@ -50,9 +47,6 @@ protected override List<string> GetParameterNames(MemberDeclarationSyntax member
: new List<string>();
}
protected override string GetParameterName(ParameterSyntax parameter)
=> parameter.Identifier.ValueText;
protected override XmlElementSyntax GetNewNode(string parameterName, bool isFirstNodeInComment)
{
var newDocCommentNode = SyntaxFactory.DocumentationComment(SyntaxFactory.XmlParamElement(parameterName));
......@@ -62,7 +56,7 @@ protected override XmlElementSyntax GetNewNode(string parameterName, bool isFirs
return !isFirstNodeInComment
? elementNode.WithLeadingTrivia(
SyntaxFactory.ParseLeadingTrivia(Environment.NewLine)
.AddRange(elementNode.GetLeadingTrivia().Select(s => s)))
.AddRange(elementNode.GetLeadingTrivia()))
: elementNode.WithTrailingTrivia(SyntaxFactory.ParseTrailingTrivia(Environment.NewLine));
}
}
......
......@@ -4,7 +4,7 @@ namespace Microsoft.CodeAnalysis.CodeFixes
{
internal static class PredefinedCodeFixProviderNames
{
public const string AddAttribute = "Add Attribute";
public const string AddDocCommentNodes = "Add Attribute";
public const string AddAwait = "Add Await For Expression";
public const string AddAsync = "Add Async To Member";
public const string ApplyNamingStyle = "Apply Naming Style";
......
......@@ -13,37 +13,36 @@
namespace Microsoft.CodeAnalysis.DiagnosticComments.CodeFixes
{
internal abstract class AbstractAddDocCommentParamNodeCodeFixProvider
<TXmlElementSyntax, TXmlNameAttributeSyntax, TXmlTextSyntax, TMemberDeclarationSyntax, TParameterSyntax> : CodeFixProvider
internal abstract class AbstractAddDocCommentNodesCodeFixProvider
<TXmlElementSyntax, TXmlNameAttributeSyntax, TXmlTextSyntax, TMemberDeclarationSyntax> : CodeFixProvider
where TXmlElementSyntax : SyntaxNode
where TXmlNameAttributeSyntax : SyntaxNode
where TXmlTextSyntax : SyntaxNode
where TMemberDeclarationSyntax : SyntaxNode
where TParameterSyntax : SyntaxNode
{
public override FixAllProvider GetFixAllProvider() => WellKnownFixAllProviders.BatchFixer;
public async sealed override Task RegisterCodeFixesAsync(CodeFixContext context)
{
var root = await context.Document.GetSyntaxRootAsync().ConfigureAwait(false);
var parameter = root.FindNode(context.Span) as TParameterSyntax;
var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);
var parentMethod = root.FindNode(context.Span)?.FirstAncestorOrSelf<TMemberDeclarationSyntax>();
var parentMethod = parameter?.FirstAncestorOrSelf<TMemberDeclarationSyntax>();
if (parentMethod != null)
{
context.RegisterCodeFix(
new MyCodeAction(
c => AddParamTagAsync(context.Document, context.Span, c), GetParameterName(parameter)),
c => AddParamTagAsync(context.Document, context.Span, c)),
context.Diagnostics);
}
}
protected abstract string NodeName { get; }
protected abstract List<TXmlNameAttributeSyntax> GetNameAttributes(TXmlElementSyntax node);
protected abstract string GetValueFromNameAttribute(TXmlNameAttributeSyntax attribute);
protected abstract SyntaxNode GetDocCommentNode(SyntaxTriviaList parameter);
protected abstract string GetXmlElementLocalName(TXmlElementSyntax element);
protected abstract List<string> GetParameterNames(TMemberDeclarationSyntax method);
protected abstract string GetParameterName(TParameterSyntax parameter);
protected abstract TXmlElementSyntax GetNewNode(string parameterName, bool isFirstNodeInComment);
protected async Task<Document> AddParamTagAsync(
......@@ -54,24 +53,30 @@ public async sealed override Task RegisterCodeFixesAsync(CodeFixContext context)
var docCommentNode = GetDocCommentNode(parentMethod.GetLeadingTrivia());
var newDocComment = docCommentNode;
var methodParamNames = GetParameterNames(parentMethod);
var parameterNames = GetParameterNames(parentMethod);
foreach (var name in methodParamNames)
foreach (var parameterName in parameterNames)
{
var paramNodes = GetParamNodes(newDocComment);
if (NodeExists(paramNodes, name)) { continue; }
var paramNodes = GetNodes(newDocComment);
if (NodeExists(paramNodes, parameterName))
{
continue;
}
var paramsBeforeCurrentParam = methodParamNames.TakeWhile(t => t != name).ToList();
var paramsAfterCurrentParam = methodParamNames.Except(paramsBeforeCurrentParam).ToList();
paramsAfterCurrentParam.Remove(name);
var paramsBeforeCurrentParam = parameterNames.TakeWhile(t => t != parameterName).ToList();
var paramsAfterCurrentParam = parameterNames.Except(paramsBeforeCurrentParam).ToList();
paramsAfterCurrentParam.Remove(parameterName);
// First, try to get the node before the param node so we know where to insert the new node
SyntaxNode nodeBeforeNewParamNode = null;
SyntaxNode nodeAfterNewParamNode = null;
if (paramsBeforeCurrentParam.Any())
{
nodeBeforeNewParamNode = GetLastParamNodeCorrespondingToParamInList(paramNodes, paramsBeforeCurrentParam);
}
// This value is only useful if there are no nodes before the new node
// I placed it here to keep related code together
SyntaxNode nodeAfterNewParamNode = null;
if (paramsAfterCurrentParam.Any())
{
nodeAfterNewParamNode = GetLastParamNodeCorrespondingToParamInList(paramNodes.Reverse(), paramsAfterCurrentParam);
......@@ -92,7 +97,7 @@ public async sealed override Task RegisterCodeFixesAsync(CodeFixContext context)
var newNodeList = new SyntaxNode[]
{
GetNewNode(name, isFirstNodeInComment: newDocComment.ChildNodes().First() == nodeAfterNewParamNode)
GetNewNode(parameterName, isFirstNodeInComment: newDocComment.ChildNodes().First() == nodeAfterNewParamNode)
};
newDocComment = nodeBeforeNewParamNode != null
......@@ -104,17 +109,17 @@ public async sealed override Task RegisterCodeFixesAsync(CodeFixContext context)
return document.WithSyntaxRoot(newRoot);
}
private IEnumerable<TXmlElementSyntax> GetParamNodes(SyntaxNode docComment)
private IEnumerable<TXmlElementSyntax> GetNodes(SyntaxNode docComment)
{
var paramNodes = docComment.ChildNodes().OfType<TXmlElementSyntax>()
.Where(w => GetXmlElementLocalName(w) == "param");
.Where(w => GetXmlElementLocalName(w) == NodeName);
// Prefer to place the doc comment in the outer level, as in auto-created comments
if (!paramNodes.Any())
{
paramNodes = docComment.DescendantNodes(descendIntoChildren: _ => true)
.OfType<TXmlElementSyntax>()
.Where(w => GetXmlElementLocalName(w) == "param");
.Where(w => GetXmlElementLocalName(w) == NodeName);
}
return paramNodes;
......@@ -152,8 +157,8 @@ protected TXmlElementSyntax GetLastParamNodeCorrespondingToParamInList(IEnumerab
private class MyCodeAction : CodeAction.DocumentChangeAction
{
public MyCodeAction(Func<CancellationToken, Task<Document>> createChangedDocument, string parameterName)
: base(string.Format(FeaturesResources.Add_missing_param_nodes, parameterName), createChangedDocument)
public MyCodeAction(Func<CancellationToken, Task<Document>> createChangedDocument)
: base(FeaturesResources.Add_missing_param_nodes, createChangedDocument)
{
}
}
......
......@@ -231,7 +231,7 @@
<Compile Include="Diagnostics\AbstractHostDiagnosticUpdateSource.cs" />
<Compile Include="Diagnostics\Analyzers\QualifyMemberAccessDiagnosticAnalyzerBase.cs" />
<Compile Include="Diagnostics\Analyzers\NamingStyles\Capitalization.cs" />
<Compile Include="DocumentationComments\CodeFixes\AbstractAddDocCommentParamNodeCodeFixProvider.cs" />
<Compile Include="DocumentationComments\CodeFixes\AbstractAddDocCommentNodesCodeFixProvider.cs" />
<Compile Include="DocumentationComments\CodeFixes\AbstractRemoveDocCommentNodeCodeFixProvider.cs" />
<Compile Include="DocumentSpan.cs" />
<Compile Include="FindReferences\DefinitionItem.cs" />
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册