提交 811ddd1a 编写于 作者: C CyrusNajmabadi 提交者: GitHub

Merge pull request #12902 from Hosch250/master

A code fix for a set of Documentation Comment diagnostics returned by the compiler
......@@ -204,6 +204,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\RemoveDocCommentNodeCodeFixProviderTests.cs" />
<Compile Include="GoToAdjacentMember\CSharpGoToAdjacentMemberTests.cs" />
<Compile Include="Diagnostics\AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest.cs" />
<Compile Include="Diagnostics\AddUsing\AddUsingTests.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.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.DiagnosticComments.CodeFixes;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics;
using Roslyn.Test.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.DocumentationComments.CodeFixes
{
public class RemoveDocCommentNodeCodeFixProviderTests : AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest
{
internal override Tuple<DiagnosticAnalyzer, CodeFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace)
{
return new Tuple<DiagnosticAnalyzer, CodeFixProvider>(null, new CSharpRemoveDocCommentNodeCodeFixProvider());
}
private async Task TestAsync(string initial, string expected)
{
var parseOptions = Options.Regular.WithDocumentationMode(DocumentationMode.Diagnose);
await TestAsync(initial, expected, parseOptions: parseOptions, compareTokens: false);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveDocCommentNode)]
public async Task RemovesDuplicateParamTag()
{
var initial =
@"class Program
{
/// <summary>
///
/// </summary>
/// <param name=""value""></param>
/// <param [|name=""value""|]></param>
public void Fizz(int value) {}
}
";
var expected =
@"class Program
{
/// <summary>
///
/// </summary>
/// <param name=""value""></param>
public void Fizz(int value) {}
}
";
await TestAsync(initial, expected);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveDocCommentNode)]
public async Task RemovesDuplicateParamTag_OnlyParamTags()
{
var initial =
@"class Program
{
/// <param name=""value""></param>
/// <param [|name=""value""|]></param>
public void Fizz(int value) {}
}
";
var expected =
@"class Program
{
/// <param name=""value""></param>
public void Fizz(int value) {}
}
";
await TestAsync(initial, expected);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveDocCommentNode)]
public async Task RemovesDuplicateParamTag_TagBelowOffendingParamTag()
{
var initial =
@"class Program
{
/// <param name=""value""></param>
/// <param [|name=""value""|]></param>
/// <returns></returns>
public int Fizz(int value) { return 0; }
}
";
var expected =
@"class Program
{
/// <param name=""value""></param>
/// <returns></returns>
public int Fizz(int value) { return 0; }
}
";
await TestAsync(initial, expected);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveDocCommentNode)]
public async Task RemovesDuplicateParamTag_BothParamTagsOnSameLine_DocCommentTagBetweenThem()
{
var initial =
@"class Program
{
/// <summary>
///
/// </summary>
/// <param name=""value""></param> /// <param [|name=""value""|]></param>
public void Fizz(int value) {}
}
";
var expected =
@"class Program
{
/// <summary>
///
/// </summary>
/// <param name=""value""></param>
public void Fizz(int value) {}
}
";
await TestAsync(initial, expected);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveDocCommentNode)]
public async Task RemovesDuplicateParamTag_BothParamTagsOnSameLine_WhitespaceBetweenThem()
{
var initial =
@"class Program
{
/// <summary>
///
/// </summary>
/// <param name=""value""></param> <param [|name=""value""|]></param>
public void Fizz(int value) {}
}
";
var expected =
@"class Program
{
/// <summary>
///
/// </summary>
/// <param name=""value""></param>
public void Fizz(int value) {}
}
";
await TestAsync(initial, expected);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveDocCommentNode)]
public async Task RemovesDuplicateParamTag_BothParamTagsOnSameLine_NothingBetweenThem()
{
var initial =
@"class Program
{
/// <summary>
///
/// </summary>
/// <param name=""value""></param><param [|name=""value""|]></param>
public void Fizz(int value) {}
}
";
var expected =
@"class Program
{
/// <summary>
///
/// </summary>
/// <param name=""value""></param>
public void Fizz(int value) {}
}
";
await TestAsync(initial, expected);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveDocCommentNode)]
public async Task RemovesDuplicateParamTag_RawTextBeforeAndAfterNode()
{
var initial =
@"class Program
{
/// <summary>
///
/// </summary>
/// <param name=""value""></param>
/// some comment<param [|name=""value""|]></param>out of the XML nodes
public void Fizz(int value) {}
}
";
var expected =
@"class Program
{
/// <summary>
///
/// </summary>
/// <param name=""value""></param>
/// some commentout of the XML nodes
public void Fizz(int value) {}
}
";
await TestAsync(initial, expected);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveDocCommentNode)]
public async Task RemovesDuplicateTypeparamTag()
{
var initial =
@"class Program
{
/// <summary>
///
/// </summary>
/// <typeparam name=""T""></typeparam>
/// <typeparam [|name=""T""|]></typeparam>
public void Fizz<T>() { }
}
";
var expected =
@"class Program
{
/// <summary>
///
/// </summary>
/// <typeparam name=""T""></typeparam>
public void Fizz<T>() { }
}
";
await TestAsync(initial, expected);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveDocCommentNode)]
public async Task RemovesParamTagWithNoMatchingParameter()
{
var initial =
@"class Program
{
/// <summary>
///
/// </summary>
/// <param name=""[|val|]""></param>
public void Fizz(int value) {}
}
";
var expected =
@"class Program
{
/// <summary>
///
/// </summary>
public void Fizz(int value) {}
}
";
await TestAsync(initial, expected);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveDocCommentNode)]
public async Task RemovesParamTag_NestedInSummaryTag()
{
var initial =
@"class Program
{
/// <summary>
/// <param name=""value""></param>
/// <param [|name=""value""|]></param>
/// </summary>
public void Fizz(int value) {}
}
";
var expected =
@"class Program
{
/// <summary>
/// <param name=""value""></param>
/// </summary>
public void Fizz(int value) {}
}
";
await TestAsync(initial, expected);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveDocCommentNode)]
public async Task RemovesParamTag_NestedInSummaryTag_WithChildren()
{
var initial =
@"class Program
{
/// <summary>
/// <param name=""value""></param>
/// <param [|name=""value""|]>
/// <xmlnode></xmlnode>
/// </param>
/// </summary>
public void Fizz(int value) {}
}
";
var expected =
@"class Program
{
/// <summary>
/// <param name=""value""></param>
/// </summary>
public void Fizz(int value) {}
}
";
await TestAsync(initial, expected);
}
[Fact]
[Trait(Traits.Feature, Traits.Features.CodeActionsRemoveDocCommentNode)]
[Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)]
public async Task TestFixAllTypeparamInDocument_DoesNotFixDuplicateParamTags()
{
var initial = @"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"" DocumentationMode=""Diagnose"">
<Document>
<![CDATA[
class Program1
{
/// <summary>
///
/// </summary>
/// <param name=""value""></param>
/// <param name=""value""></param>
/// <typeparam name=""T""></typeparam>
/// <typeparam {|FixAllInDocument:name=""T""|}></typeparam>
/// <typeparam name=""U""></typeparam>
public void Fizz<T, U>(int value) {}
/// <summary>
///
/// </summary>
/// <param name=""value""></param>
/// <param name=""value""></param>
/// <typeparam name=""T""></typeparam>
/// <typeparam name=""T""></typeparam>
/// <typeparam name=""U""></typeparam>
/// <returns></returns>
public int Buzz<T, U>(int value) { returns 0; }
}]]>
</Document>
<Document>
<![CDATA[
class Program2
{
/// <summary>
///
/// </summary>
/// <param name=""value""></param>
/// <param name=""value""></param>
public void Fizz(int value) {}
}]]>
</Document>
</Project>
<Project Language=""C#"" AssemblyName=""Assembly2"" CommonReferences=""true"" DocumentationMode=""Diagnose"">
<Document>
<![CDATA[
class Program3
{
/// <summary>
///
/// </summary>
/// <param name=""value""></param>
/// <param name=""value""></param>
public void Fizz(int value) {}
}]]>
</Document>
</Project>
</Workspace>";
var expected = @"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"" DocumentationMode=""Diagnose"">
<Document>
<![CDATA[
class Program1
{
/// <summary>
///
/// </summary>
/// <param name=""value""></param>
/// <param name=""value""></param>
/// <typeparam name=""T""></typeparam>
/// <typeparam name=""U""></typeparam>
public void Fizz<T, U>(int value) {}
/// <summary>
///
/// </summary>
/// <param name=""value""></param>
/// <param name=""value""></param>
/// <typeparam name=""T""></typeparam>
/// <typeparam name=""U""></typeparam>
/// <returns></returns>
public int Buzz<T, U>(int value) { returns 0; }
}]]>
</Document>
<Document>
<![CDATA[
class Program2
{
/// <summary>
///
/// </summary>
/// <param name=""value""></param>
/// <param name=""value""></param>
public void Fizz(int value) {}
}]]>
</Document>
</Project>
<Project Language=""C#"" AssemblyName=""Assembly2"" CommonReferences=""true"" DocumentationMode=""Diagnose"">
<Document>
<![CDATA[
class Program3
{
/// <summary>
///
/// </summary>
/// <param name=""value""></param>
/// <param name=""value""></param>
public void Fizz(int value) {}
}]]>
</Document>
</Project>
</Workspace>";
await TestAsync(initial, expected);
}
[Fact]
[Trait(Traits.Feature, Traits.Features.CodeActionsRemoveDocCommentNode)]
[Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)]
public async Task TestFixAllInDocument()
{
var initial = @"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"" DocumentationMode=""Diagnose"">
<Document>
<![CDATA[
class Program1
{
/// <summary>
///
/// </summary>
/// <param name=""value""></param>
/// <param {|FixAllInDocument:name=""value""|}></param>
public void Fizz(int value) {}
/// <summary>
///
/// </summary>
/// <param name=""value""></param>
/// <param name=""value""></param>
/// <returns></returns>
public int Buzz(int value) { returns 0; }
}]]>
</Document>
<Document>
<![CDATA[
class Program2
{
/// <summary>
///
/// </summary>
/// <param name=""value""></param>
/// <param name=""value""></param>
public void Fizz(int value) {}
}]]>
</Document>
</Project>
<Project Language=""C#"" AssemblyName=""Assembly2"" CommonReferences=""true"" DocumentationMode=""Diagnose"">
<Document>
<![CDATA[
class Program3
{
/// <summary>
///
/// </summary>
/// <param name=""value""></param>
/// <param name=""value""></param>
public void Fizz(int value) {}
}]]>
</Document>
</Project>
</Workspace>";
var expected = @"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"" DocumentationMode=""Diagnose"">
<Document>
<![CDATA[
class Program1
{
/// <summary>
///
/// </summary>
/// <param name=""value""></param>
public void Fizz(int value) {}
/// <summary>
///
/// </summary>
/// <param name=""value""></param>
/// <returns></returns>
public int Buzz(int value) { returns 0; }
}]]>
</Document>
<Document>
<![CDATA[
class Program2
{
/// <summary>
///
/// </summary>
/// <param name=""value""></param>
/// <param name=""value""></param>
public void Fizz(int value) {}
}]]>
</Document>
</Project>
<Project Language=""C#"" AssemblyName=""Assembly2"" CommonReferences=""true"" DocumentationMode=""Diagnose"">
<Document>
<![CDATA[
class Program3
{
/// <summary>
///
/// </summary>
/// <param name=""value""></param>
/// <param name=""value""></param>
public void Fizz(int value) {}
}]]>
</Document>
</Project>
</Workspace>";
await TestAsync(initial, expected);
}
[Fact]
[Trait(Traits.Feature, Traits.Features.CodeActionsRemoveDocCommentNode)]
[Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)]
public async Task TestFixAllInProject()
{
var initial = @"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"" DocumentationMode=""Diagnose"">
<Document>
<![CDATA[
class Program1
{
/// <summary>
///
/// </summary>
/// <param name=""value""></param>
/// <param {|FixAllInProject:name=""value""|}></param>
public void Fizz(int value) {}
}]]>
</Document>
<Document>
<![CDATA[
class Program2
{
/// <summary>
///
/// </summary>
/// <param name=""value""></param>
/// <param name=""value""></param>
public void Fizz(int value) {}
}]]>
</Document>
</Project>
<Project Language=""C#"" AssemblyName=""Assembly2"" CommonReferences=""true"" DocumentationMode=""Diagnose"">
<Document>
<![CDATA[
class Program3
{
/// <summary>
///
/// </summary>
/// <param name=""value""></param>
/// <param name=""value""></param>
public void Fizz(int value) {}
}]]>
</Document>
</Project>
</Workspace>";
var expected = @"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"">
<Document>
<![CDATA[
class Program1
{
/// <summary>
///
/// </summary>
/// <param name=""value""></param>
public void Fizz(int value) {}
}]]>
</Document>
<Document>
<![CDATA[
class Program2
{
/// <summary>
///
/// </summary>
/// <param name=""value""></param>
public void Fizz(int value) {}
}]]>
</Document>
</Project>
<Project Language=""C#"" AssemblyName=""Assembly2"" CommonReferences=""true"">
<Document>
<![CDATA[
class Program3
{
/// <summary>
///
/// </summary>
/// <param name=""value""></param>
/// <param name=""value""></param>
public void Fizz(int value) {}
}]]>
</Document>
</Project>
</Workspace>";
await TestAsync(initial, expected);
}
[Fact]
[Trait(Traits.Feature, Traits.Features.CodeActionsRemoveDocCommentNode)]
[Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)]
public async Task TestFixAllInSolution()
{
var initial = @"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"" DocumentationMode=""Diagnose"">
<Document>
<![CDATA[
class Program1
{
/// <summary>
///
/// </summary>
/// <param name=""value""></param>
/// <param {|FixAllInSolution:name=""value""|}></param>
public void Fizz(int value) {}
}]]>
</Document>
<Document>
<![CDATA[
class Program2
{
/// <summary>
///
/// </summary>
/// <param name=""value""></param>
/// <param name=""value""></param>
public void Fizz(int value) {}
}]]>
</Document>
</Project>
<Project Language=""C#"" AssemblyName=""Assembly2"" CommonReferences=""true"" DocumentationMode=""Diagnose"">
<Document>
<![CDATA[
class Program3
{
/// <summary>
///
/// </summary>
/// <param name=""value""></param>
/// <param name=""value""></param>
public void Fizz(int value) {}
}]]>
</Document>
</Project>
</Workspace>";
var expected = @"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"" DocumentationMode=""Diagnose"">
<Document>
<![CDATA[
class Program1
{
/// <summary>
///
/// </summary>
/// <param name=""value""></param>
public void Fizz(int value) {}
}]]>
</Document>
<Document>
<![CDATA[
class Program2
{
/// <summary>
///
/// </summary>
/// <param name=""value""></param>
public void Fizz(int value) {}
}]]>
</Document>
</Project>
<Project Language=""C#"" AssemblyName=""Assembly2"" CommonReferences=""true"" DocumentationMode=""Diagnose"">
<Document>
<![CDATA[
class Program3
{
/// <summary>
///
/// </summary>
/// <param name=""value""></param>
public void Fizz(int value) {}
}]]>
</Document>
</Project>
</Workspace>";
await TestAsync(initial, expected);
}
}
}
......@@ -74,6 +74,7 @@ public static class Features
public const string CodeActionsReplaceMethodWithProperty = "CodeActions.ReplaceMethodWithProperty";
public const string CodeActionsReplacePropertyWithMethods = "CodeActions.ReplacePropertyWithMethods";
public const string CodeActionsRemoveByVal = "CodeActions.RemoveByVal";
public const string CodeActionsRemoveDocCommentNode = "CodeActions.RemoveDocCommentNode";
public const string CodeActionsRemoveUnnecessaryCast = "CodeActions.RemoveUnnecessaryCast";
public const string CodeActionsRemoveUnnecessaryImports = "CodeActions.RemoveUnnecessaryImports";
public const string CodeActionsSimplifyTypeNames = "CodeActions.SimplifyTypeNames";
......
......@@ -201,6 +201,7 @@
<Compile Include="Diagnostics\Suppression\SuppressionAllCodeTests.vb" />
<Compile Include="Diagnostics\Suppression\SuppressionTests.vb" />
<Compile Include="Diagnostics\UseAutoProperty\UseAutoPropertyTests.vb" />
<Compile Include="DocumentationComments\CodeFixes\RemoveDocCommentNodeCodeFixProviderTests.vb" />
<Compile Include="DocumentationComments\DocumentationCommentTests.vb" />
<Compile Include="DocumentationComments\XmlTagCompletionTests.vb" />
<Compile Include="EditAndContinue\ActiveStatementTests.vb" />
......
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports Microsoft.CodeAnalysis.CodeFixes
Imports Microsoft.CodeAnalysis.DiagnosticComments.CodeFixes
Imports Microsoft.CodeAnalysis.Diagnostics
Imports Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Diagnostics
Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.DocumentationComments.CodeFixes
Public Class RemoveDocCommentNodeCodeFixProviderTests
Inherits AbstractVisualBasicDiagnosticProviderBasedUserDiagnosticTest
Friend Overrides Function CreateDiagnosticProviderAndFixer(workspace As Workspace) As Tuple(Of DiagnosticAnalyzer, CodeFixProvider)
Return Tuple.Create(Of DiagnosticAnalyzer, CodeFixProvider)(
Nothing,
New VisualBasicRemoveDocCommentNodeCodeFixProvider())
End Function
Private Overloads Async Function TestAsync(ByVal initial As String, ByVal expected As String) As Task
Dim parseOptions = TestOptions.Regular.WithDocumentationMode(DocumentationMode.Diagnose)
Await TestAsync(initial, expected, parseOptions:=parseOptions, compareTokens:=False)
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveDocCommentNode)>
Public Async Function RemovesDuplicateParamTag() As Task
Dim initial =
"Class Program
''' <summary>
'''
''' </summary>
''' <param name=""value""></param>
''' [|<param name=""value""></param>|]
Sub Fizz(ByVal value As Integer)
End Sub
End Class"
Dim expected =
"Class Program
''' <summary>
'''
''' </summary>
''' <param name=""value""></param>
Sub Fizz(ByVal value As Integer)
End Sub
End Class"
Await TestAsync(initial, expected)
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveDocCommentNode)>
Public Async Function RemovesDuplicateParamTag_OnlyParamTags() As Task
Dim initial =
"Class Program
''' <param name=""value""></param>
''' [|<param name=""value""></param>|]
Sub Fizz(ByVal value As Integer)
End Sub
End Class"
Dim expected =
"Class Program
''' <param name=""value""></param>
Sub Fizz(ByVal value As Integer)
End Sub
End Class"
Await TestAsync(initial, expected)
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveDocCommentNode)>
Public Async Function RemovesDuplicateParamTag_TagBelowOffendingParamTag() As Task
Dim initial =
"Class Program
''' <param name=""value""></param>
''' [|<param name=""value""></param>|]
''' <returns></returns>
Public Function Fizz(ByVal value As Integer) As Integer
Return 0
End Function
End Class"
Dim expected =
"Class Program
''' <param name=""value""></param>
''' <returns></returns>
Public Function Fizz(ByVal value As Integer) As Integer
Return 0
End Function
End Class"
Await TestAsync(initial, expected)
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveDocCommentNode)>
Public Async Function RemovesDuplicateParamTag_BothParamTagsOnSameLine_DocCommentTagBetweenThem() As Task
Dim initial =
"Class Program
''' <summary>
'''
''' </summary>
''' <param name=""value""></param> ''' [|<param name=""value""></param>|]
Sub Fizz(ByVal value As Integer)
End Sub
End Class"
Dim expected =
"Class Program
''' <summary>
'''
''' </summary>
''' <param name=""value""></param>
Sub Fizz(ByVal value As Integer)
End Sub
End Class"
Await TestAsync(initial, expected)
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveDocCommentNode)>
Public Async Function RemovesDuplicateParamTag_BothParamTagsOnSameLine_WhitespaceBetweenThem() As Task
Dim initial =
"Class Program
''' <summary>
'''
''' </summary>
''' <param name=""value""></param> [|<param name=""value""></param>|]
Sub Fizz(ByVal value As Integer)
End Sub
End Class"
Dim expected =
"Class Program
''' <summary>
'''
''' </summary>
''' <param name=""value""></param>
Sub Fizz(ByVal value As Integer)
End Sub
End Class"
Await TestAsync(initial, expected)
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveDocCommentNode)>
Public Async Function RemovesDuplicateParamTag_BothParamTagsOnSameLine_NothingBetweenThem() As Task
Dim initial =
"Class Program
''' <summary>
'''
''' </summary>
''' <param name=""value""></param>[|<param name=""value""></param>|]
Sub Fizz(ByVal value As Integer)
End Sub
End Class"
Dim expected =
"Class Program
''' <summary>
'''
''' </summary>
''' <param name=""value""></param>
Sub Fizz(ByVal value As Integer)
End Sub
End Class"
Await TestAsync(initial, expected)
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveDocCommentNode)>
Public Async Function RemovesParamTagWithNoMatchingParam() As Task
Dim initial =
"Class Program
''' <summary>
'''
''' </summary>
''' <param name=""value""></param>
''' [|<param name=""buzz""></param>|]
Sub Fizz(ByVal value As Integer)
End Sub
End Class"
Dim expected =
"Class Program
''' <summary>
'''
''' </summary>
''' <param name=""value""></param>
Sub Fizz(ByVal value As Integer)
End Sub
End Class"
Await TestAsync(initial, expected)
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveDocCommentNode)>
Public Async Function RemovesDuplicateParamTag_RawTextBeforeAndAfterNode() As Task
Dim initial =
"Class Program
''' <summary>
'''
''' </summary>
''' <param name=""value""></param>
''' some comment[|<param name=""value""></param>|]out of the XML nodes
Sub Fizz(ByVal value As Integer)
End Sub
End Class"
Dim expected =
"Class Program
''' <summary>
'''
''' </summary>
''' <param name=""value""></param>
''' some commentout of the XML nodes
Sub Fizz(ByVal value As Integer)
End Sub
End Class"
Await TestAsync(initial, expected)
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveDocCommentNode)>
Public Async Function RemovesDuplicateTypeparamTag() As Task
Dim initial =
"Class Program
''' <summary>
'''
''' </summary>
''' <typeparam name=""T""></typeparam>
''' [|<typeparam name=""T""></typeparam>|]
''' <typeparam name=""U""></typeparam>
''' <param name=""value""></param>
Sub Fizz(Of T, U)(ByVal value As Integer)
End Sub
End Class"
Dim expected =
"Class Program
''' <summary>
'''
''' </summary>
''' <typeparam name=""T""></typeparam>
''' <typeparam name=""U""></typeparam>
''' <param name=""value""></param>
Sub Fizz(Of T, U)(ByVal value As Integer)
End Sub
End Class"
Await TestAsync(initial, expected)
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveDocCommentNode)>
Public Async Function RemovesTypeparamTagWithNoMatchingType() As Task
Dim initial =
"Class Program
''' <summary>
'''
''' </summary>
''' <typeparam name=""T""></typeparam>
''' <typeparam name=""U""></typeparam>
''' [|<typeparam name=""A""></typeparam>|]
''' <param name=""value""></param>
Sub Fizz(Of T, U)(ByVal value As Integer)
End Sub
End Class"
Dim expected =
"Class Program
''' <summary>
'''
''' </summary>
''' <typeparam name=""T""></typeparam>
''' <typeparam name=""U""></typeparam>
''' <param name=""value""></param>
Sub Fizz(Of T, U)(ByVal value As Integer)
End Sub
End Class"
Await TestAsync(initial, expected)
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveDocCommentNode)>
Public Async Function RemovesReturnsTagOnSub() As Task
Dim initial =
"Class Program
''' <summary>
'''
''' </summary>
''' <param name=""value""></param>
''' [|<returns></returns>|]
Public Sub Fizz(ByVal value As Integer)
End Sub
End Class"
Dim expected =
"Class Program
''' <summary>
'''
''' </summary>
''' <param name=""value""></param>
Public Sub Fizz(ByVal value As Integer)
End Sub
End Class"
Await TestAsync(initial, expected)
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveDocCommentNode)>
Public Async Function RemovesDuplicateReturnsTag() As Task
Dim initial =
"Class Program
''' <param name=""value""></param>
''' <param name=""value""></param>
''' <returns></returns>
''' [|<returns></returns>|]
Public Function Fizz(ByVal value As Integer) As Integer
Return 0
End Function
End Class"
Dim expected =
"Class Program
''' <param name=""value""></param>
''' <param name=""value""></param>
''' <returns></returns>
Public Function Fizz(ByVal value As Integer) As Integer
Return 0
End Function
End Class"
Await TestAsync(initial, expected)
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveDocCommentNode)>
Public Async Function RemovesIllegalReturnsTagOnWriteOnlyProperty() As Task
Dim initial =
"Class Program
''' <summary>
'''
''' </summary>
''' [|<returns></returns>|]
WriteOnly Property P As Integer
Set(value As Integer)
End Set
End Property
End Class"
Dim expected =
"Class Program
''' <summary>
'''
''' </summary>
WriteOnly Property P As Integer
Set(value As Integer)
End Set
End Property
End Class"
Await TestAsync(initial, expected)
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveDocCommentNode)>
Public Async Function RemovesIllegalReturnsTagOnDeclareSub() As Task
Dim initial =
"Class Program
''' <summary>
'''
''' </summary>
''' [|<returns></returns>|]
Declare Sub Foo Lib ""User"" ()
End Class"
Dim expected =
"Class Program
''' <summary>
'''
''' </summary>
Declare Sub Foo Lib ""User"" ()
End Class"
Await TestAsync(initial, expected)
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveDocCommentNode)>
Public Async Function RemovesParamTag_NestedInSummaryTag() As Task
Dim initial =
"Class Program
''' <summary>
''' <param name=""value""></param>
''' [|<param name=""value""></param>|]
''' </summary>
Sub Fizz(ByVal value As Integer)
End Sub
End Class"
Dim expected =
"Class Program
''' <summary>
''' <param name=""value""></param>
''' </summary>
Sub Fizz(ByVal value As Integer)
End Sub
End Class"
Await TestAsync(initial, expected)
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveDocCommentNode)>
Public Async Function RemovesParamTag_NestedInSummaryTag_WithChildren() As Task
Dim initial =
"Class Program
''' <summary>
''' <param name=""value""></param>
''' [|<param name=""value"">
''' <xmlnode></xmlnode>
''' </param>|]
''' </summary>
Sub Fizz(ByVal value As Integer)
End Sub
End Class"
Dim expected =
"Class Program
''' <summary>
''' <param name=""value""></param>
''' </summary>
Sub Fizz(ByVal value As Integer)
End Sub
End Class"
Await TestAsync(initial, expected)
End Function
<Fact>
<Trait(Traits.Feature, Traits.Features.CodeActionsRemoveDocCommentNode)>
<Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)>
Public Async Function TestFixAllTypeparamInDocument_FixesDuplicateParamTags() As Task
' This fixes both because VB.NET has one diagnostic for all doc comment nodes with the same attributes
Dim initial =
"<Workspace>
<Project Language=""Visual Basic"" AssemblyName=""Assembly1"" CommonReferences=""true"" DocumentationMode=""Diagnose"">
<Document><![CDATA[
Class Program
''' <summary>
'''
''' </summary>
''' <param name=""value""></param>
''' <param name=""value""></param>
''' <typeparam name=""T""></typeparam>
''' {|FixAllInDocument:<typeparam name=""T""></typeparam>|}
''' <typeparam name=""U""></typeparam>
Sub Fizz(Of T, U)(ByVal value As Integer)
End Sub
''' <summary>
'''
''' </summary>
''' <param name=""value""></param>
''' <param name=""value""></param>
''' <typeparam name=""T""></typeparam>
''' <typeparam name=""U""></typeparam>
''' <typeparam name=""U""></typeparam>
''' <returns></returns>
Function Buzz(Of T, U)(value As Integer) As Integer
Return 0
End Function
End Class]]>
</Document>
<Document><![CDATA[
Class Program
''' <summary>
'''
''' </summary>
''' <param name=""value""></param>
''' <param name=""value""></param>
Sub Fizz(ByVal value As Integer)
End Sub
End Class]]>
</Document>
</Project>
<Project Language=""Visual Basic"" AssemblyName=""Assembly2"" CommonReferences=""true"" DocumentationMode=""Diagnose"">
<ProjectReference>Assembly1</ProjectReference>
<Document><![CDATA[
Class Program
''' <summary>
'''
''' </summary>
''' <param name=""value""></param>
''' <param name=""value""></param>
Sub Fizz(ByVal value As Integer)
End Sub
End Class]]>
</Document>
</Project>
</Workspace>"
Dim expected =
"<Workspace>
<Project Language=""Visual Basic"" AssemblyName=""Assembly1"" CommonReferences=""true"" DocumentationMode=""Diagnose"">
<Document><![CDATA[
Class Program
''' <summary>
'''
''' </summary>
''' <param name=""value""></param>
''' <typeparam name=""T""></typeparam>
''' <typeparam name=""U""></typeparam>
Sub Fizz(Of T, U)(ByVal value As Integer)
End Sub
''' <summary>
'''
''' </summary>
''' <param name=""value""></param>
''' <typeparam name=""T""></typeparam>
''' <typeparam name=""U""></typeparam>
''' <returns></returns>
Function Buzz(Of T, U)(value As Integer) As Integer
Return 0
End Function
End Class]]>
</Document>
<Document><![CDATA[
Class Program
''' <summary>
'''
''' </summary>
''' <param name=""value""></param>
''' <param name=""value""></param>
Sub Fizz(ByVal value As Integer)
End Sub
End Class]]>
</Document>
</Project>
<Project Language=""Visual Basic"" AssemblyName=""Assembly2"" CommonReferences=""true"" DocumentationMode=""Diagnose"">
<ProjectReference>Assembly1</ProjectReference>
<Document><![CDATA[
Class Program
''' <summary>
'''
''' </summary>
''' <param name=""value""></param>
''' <param name=""value""></param>
Sub Fizz(ByVal value As Integer)
End Sub
End Class]]>
</Document>
</Project>
</Workspace>"
Await TestAsync(initial, expected)
End Function
<Fact>
<Trait(Traits.Feature, Traits.Features.CodeActionsRemoveDocCommentNode)>
<Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)>
Public Async Function TestFixAllTypeparamInDocument_DoesNotFixIllegalReturnsOnSub() As Task
' This fixes both because VB.NET has one diagnostic for all doc comment nodes with the same attributes
Dim initial =
"<Workspace>
<Project Language=""Visual Basic"" AssemblyName=""Assembly1"" CommonReferences=""true"" DocumentationMode=""Diagnose"">
<Document><![CDATA[
Class Program
''' <summary>
'''
''' </summary>
''' <param name=""value""></param>
''' <param name=""value""></param>
''' <typeparam name=""T""></typeparam>
''' {|FixAllInDocument:<typeparam name=""T""></typeparam>|}
''' <typeparam name=""U""></typeparam>
''' <returns></returns>
Sub Fizz(Of T, U)(ByVal value As Integer)
End Sub
''' <summary>
'''
''' </summary>
''' <param name=""value""></param>
''' <param name=""value""></param>
''' <typeparam name=""T""></typeparam>
''' <typeparam name=""U""></typeparam>
''' <typeparam name=""U""></typeparam>
''' <returns></returns>
Function Buzz(Of T, U)(value As Integer) As Integer
Return 0
End Function
End Class]]>
</Document>
<Document><![CDATA[
Class Program
''' <summary>
'''
''' </summary>
''' <param name=""value""></param>
''' <param name=""value""></param>
Sub Fizz(ByVal value As Integer)
End Sub
End Class]]>
</Document>
</Project>
<Project Language=""Visual Basic"" AssemblyName=""Assembly2"" CommonReferences=""true"" DocumentationMode=""Diagnose"">
<ProjectReference>Assembly1</ProjectReference>
<Document><![CDATA[
Class Program
''' <summary>
'''
''' </summary>
''' <param name=""value""></param>
''' <param name=""value""></param>
Sub Fizz(ByVal value As Integer)
End Sub
End Class]]>
</Document>
</Project>
</Workspace>"
Dim expected =
"<Workspace>
<Project Language=""Visual Basic"" AssemblyName=""Assembly1"" CommonReferences=""true"" DocumentationMode=""Diagnose"">
<Document><![CDATA[
Class Program
''' <summary>
'''
''' </summary>
''' <param name=""value""></param>
''' <typeparam name=""T""></typeparam>
''' <typeparam name=""U""></typeparam>
''' <returns></returns>
Sub Fizz(Of T, U)(ByVal value As Integer)
End Sub
''' <summary>
'''
''' </summary>
''' <param name=""value""></param>
''' <typeparam name=""T""></typeparam>
''' <typeparam name=""U""></typeparam>
''' <returns></returns>
Function Buzz(Of T, U)(value As Integer) As Integer
Return 0
End Function
End Class]]>
</Document>
<Document><![CDATA[
Class Program
''' <summary>
'''
''' </summary>
''' <param name=""value""></param>
''' <param name=""value""></param>
Sub Fizz(ByVal value As Integer)
End Sub
End Class]]>
</Document>
</Project>
<Project Language=""Visual Basic"" AssemblyName=""Assembly2"" CommonReferences=""true"" DocumentationMode=""Diagnose"">
<ProjectReference>Assembly1</ProjectReference>
<Document><![CDATA[
Class Program
''' <summary>
'''
''' </summary>
''' <param name=""value""></param>
''' <param name=""value""></param>
Sub Fizz(ByVal value As Integer)
End Sub
End Class]]>
</Document>
</Project>
</Workspace>"
Await TestAsync(initial, expected)
End Function
<Fact>
<Trait(Traits.Feature, Traits.Features.CodeActionsRemoveDocCommentNode)>
<Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)>
Public Async Function TestFixAllInDocument() As Task
Dim initial =
"<Workspace>
<Project Language=""Visual Basic"" AssemblyName=""Assembly1"" CommonReferences=""true"" DocumentationMode=""Diagnose"">
<Document><![CDATA[
Class Program
''' <summary>
'''
''' </summary>
''' <param name=""value""></param>
''' {|FixAllInDocument:<param name=""value""></param>|}
Sub Fizz(ByVal value As Integer)
End Sub
''' <summary>
'''
''' </summary>
''' <param name=""value""></param>
''' <param name=""value""></param>
''' <returns></returns>
Function Buzz(value As Integer) As Integer
Return 0
End Function
End Class]]>
</Document>
<Document><![CDATA[
Class Program
''' <summary>
'''
''' </summary>
''' <param name=""value""></param>
''' <param name=""value""></param>
Sub Fizz(ByVal value As Integer)
End Sub
End Class]]>
</Document>
</Project>
<Project Language=""Visual Basic"" AssemblyName=""Assembly2"" CommonReferences=""true"" DocumentationMode=""Diagnose"">
<ProjectReference>Assembly1</ProjectReference>
<Document><![CDATA[
Class Program
''' <summary>
'''
''' </summary>
''' <param name=""value""></param>
''' <param name=""value""></param>
Sub Fizz(ByVal value As Integer)
End Sub
End Class]]>
</Document>
</Project>
</Workspace>"
Dim expected =
"<Workspace>
<Project Language=""Visual Basic"" AssemblyName=""Assembly1"" CommonReferences=""true"" DocumentationMode=""Diagnose"">
<Document><![CDATA[
Class Program
''' <summary>
'''
''' </summary>
''' <param name=""value""></param>
Sub Fizz(ByVal value As Integer)
End Sub
''' <summary>
'''
''' </summary>
''' <param name=""value""></param>
''' <returns></returns>
Function Buzz(value As Integer) As Integer
Return 0
End Function
End Class]]>
</Document>
<Document><![CDATA[
Class Program
''' <summary>
'''
''' </summary>
''' <param name=""value""></param>
''' <param name=""value""></param>
Sub Fizz(ByVal value As Integer)
End Sub
End Class]]>
</Document>
</Project>
<Project Language=""Visual Basic"" AssemblyName=""Assembly2"" CommonReferences=""true"" DocumentationMode=""Diagnose"">
<ProjectReference>Assembly1</ProjectReference>
<Document><![CDATA[
Class Program
''' <summary>
'''
''' </summary>
''' <param name=""value""></param>
''' <param name=""value""></param>
Sub Fizz(ByVal value As Integer)
End Sub
End Class]]>
</Document>
</Project>
</Workspace>"
Await TestAsync(initial, expected)
End Function
<Fact>
<Trait(Traits.Feature, Traits.Features.CodeActionsRemoveDocCommentNode)>
<Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)>
Public Async Function TestFixAllInProject() As Task
Dim initial =
"<Workspace>
<Project Language=""Visual Basic"" AssemblyName=""Assembly1"" CommonReferences=""true"" DocumentationMode=""Diagnose"">
<Document><![CDATA[
Class Program
''' <summary>
'''
''' </summary>
''' <param name=""value""></param>
''' {|FixAllInProject:<param name=""value""></param>|}
Sub Fizz(ByVal value As Integer)
End Sub
End Class]]>
</Document>
<Document><![CDATA[
Class Program
''' <summary>
'''
''' </summary>
''' <param name=""value""></param>
''' <param name=""value""></param>
Sub Fizz(ByVal value As Integer)
End Sub
End Class]]>
</Document>
</Project>
<Project Language=""Visual Basic"" AssemblyName=""Assembly2"" CommonReferences=""true"" DocumentationMode=""Diagnose"">
<ProjectReference>Assembly1</ProjectReference>
<Document><![CDATA[
Class Program
''' <summary>
'''
''' </summary>
''' <param name=""value""></param>
''' <param name=""value""></param>
Sub Fizz(ByVal value As Integer)
End Sub
End Class]]>
</Document>
</Project>
</Workspace>"
Dim expected =
"<Workspace>
<Project Language=""Visual Basic"" AssemblyName=""Assembly1"" CommonReferences=""true"" DocumentationMode=""Diagnose"">
<Document><![CDATA[
Class Program
''' <summary>
'''
''' </summary>
''' <param name=""value""></param>
Sub Fizz(ByVal value As Integer)
End Sub
End Class]]>
</Document>
<Document><![CDATA[
Class Program
''' <summary>
'''
''' </summary>
''' <param name=""value""></param>
Sub Fizz(ByVal value As Integer)
End Sub
End Class]]>
</Document>
</Project>
<Project Language=""Visual Basic"" AssemblyName=""Assembly2"" CommonReferences=""true"" DocumentationMode=""Diagnose"">
<ProjectReference>Assembly1</ProjectReference>
<Document><![CDATA[
Class Program
''' <summary>
'''
''' </summary>
''' <param name=""value""></param>
''' <param name=""value""></param>
Sub Fizz(ByVal value As Integer)
End Sub
End Class]]>
</Document>
</Project>
</Workspace>"
Await TestAsync(initial, expected)
End Function
<Fact>
<Trait(Traits.Feature, Traits.Features.CodeActionsRemoveDocCommentNode)>
<Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)>
Public Async Function TestFixAllInSolution() As Task
Dim initial =
"<Workspace>
<Project Language=""Visual Basic"" AssemblyName=""Assembly1"" CommonReferences=""true"" DocumentationMode=""Diagnose"">
<Document>
<![CDATA[Class Program
''' <summary>
'''
''' </summary>
''' <param name=""value""></param>
''' {|FixAllInSolution:<param name=""value""></param>|}
Sub Fizz(ByVal value As Integer)
End Sub
End Class]]>
</Document>
<Document>
<![CDATA[Class Program
''' <summary>
'''
''' </summary>
''' <param name=""value""></param>
''' <param name=""value""></param>
Sub Fizz(ByVal value As Integer)
End Sub
End Class]]>
</Document>
</Project>
<Project Language=""Visual Basic"" AssemblyName=""Assembly2"" CommonReferences=""true"" DocumentationMode=""Diagnose"">
<ProjectReference>Assembly1</ProjectReference>
<Document>
<![CDATA[Class Program
''' <summary>
'''
''' </summary>
''' <param name=""value""></param>
''' <param name=""value""></param>
Sub Fizz(ByVal value As Integer)
End Sub
End Class]]>
</Document>
</Project>
</Workspace>"
Dim expected =
"<Workspace>
<Project Language=""Visual Basic"" AssemblyName=""Assembly1"" CommonReferences=""true"" DocumentationMode=""Diagnose"">
<Document>
<![CDATA[Class Program
''' <summary>
'''
''' </summary>
''' <param name=""value""></param>
Sub Fizz(ByVal value As Integer)
End Sub
End Class]]>
</Document>
<Document>
<![CDATA[Class Program
''' <summary>
'''
''' </summary>
''' <param name=""value""></param>
Sub Fizz(ByVal value As Integer)
End Sub
End Class]]>
</Document>
</Project>
<Project Language=""Visual Basic"" AssemblyName=""Assembly2"" CommonReferences=""true"" DocumentationMode=""Diagnose"">
<ProjectReference>Assembly1</ProjectReference>
<Document>
<![CDATA[Class Program
''' <summary>
'''
''' </summary>
''' <param name=""value""></param>
Sub Fizz(ByVal value As Integer)
End Sub
End Class]]>
</Document>
</Project>
</Workspace>"
Await TestAsync(initial, expected)
End Function
End Class
End Namespace
......@@ -271,6 +271,7 @@
<Compile Include="Diagnostics\Analyzers\CSharpUseExplicitTypeDiagnosticAnalyzer.cs" />
<Compile Include="Diagnostics\Analyzers\CSharpUseImplicitTypeDiagnosticAnalyzer.cs" />
<Compile Include="Diagnostics\CSharpAnalyzerDriverService.cs" />
<Compile Include="DocumentationComments\CodeFixes\CSharpRemoveDocCommentNodeCodeFixProvider.cs" />
<Compile Include="DocumentationComments\CSharpDocumentationCommentFormattingService.cs" />
<Compile Include="DocumentationComments\DocumentationCommentUtilities.cs" />
<Compile Include="EditAndContinue\BreakpointSpans.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.Collections.Immutable;
using System.Composition;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace Microsoft.CodeAnalysis.DiagnosticComments.CodeFixes
{
[ExportCodeFixProvider(LanguageNames.CSharp, Name = PredefinedCodeFixProviderNames.RemoveDocCommentNode), Shared]
[ExtensionOrder(After = PredefinedCodeFixProviderNames.ImplementInterface)]
internal class CSharpRemoveDocCommentNodeCodeFixProvider : AbstractRemoveDocCommentNodeCodeFixProvider<XmlElementSyntax>
{
/// <summary>
/// Duplicate param tag
/// </summary>
private const string CS1571 = nameof(CS1571);
/// <summary>
/// Param tag with no matching parameter
/// </summary>
private const string CS1572 = nameof(CS1572);
/// <summary>
/// Duplicate typeparam tag
/// </summary>
private const string CS1710 = nameof(CS1710);
public override ImmutableArray<string> FixableDiagnosticIds { get; } = ImmutableArray.Create(CS1571, CS1572, CS1710);
protected override string DocCommentSignifierToken { get; } = "///";
protected override SyntaxTriviaList GetRevisedDocCommentTrivia(string docCommentText)
=> SyntaxFactory.ParseLeadingTrivia(docCommentText);
}
}
\ No newline at end of file
......@@ -13,6 +13,7 @@ internal static class PredefinedCodeFixProviderNames
public const string ConvertToAsync = "Convert To Async";
public const string ConvertToIterator = "Convert To Iterator";
public const string CorrectNextControlVariable = "Correct Next Control Variable";
public const string RemoveDocCommentNode = "Remove Doc Comment Node";
public const string AddMissingReference = "Add Missing Reference";
public const string AddUsingOrImport = "Add Using or Import";
public const string FullyQualify = "Fully Qualify";
......
// 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.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<TXMLElement> : CodeFixProvider
{
public override FixAllProvider GetFixAllProvider() => WellKnownFixAllProviders.BatchFixer;
public abstract override ImmutableArray<string> FixableDiagnosticIds { get; }
protected abstract string DocCommentSignifierToken { get; }
protected abstract SyntaxTriviaList GetRevisedDocCommentTrivia(string docCommentText);
public async sealed override Task RegisterCodeFixesAsync(CodeFixContext context)
{
var root = await context.Document.GetSyntaxRootAsync().ConfigureAwait(false);
if (GetParamNode(root, context.Span) != null)
{
context.RegisterCodeFix(
new MyCodeAction(
c => RemoveDuplicateParamTag(context.Document, context.Span, c)),
context.Diagnostics);
}
return;
}
private SyntaxNode 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;
}
private async Task<Document> RemoveDuplicateParamTag(Document document, TextSpan span, CancellationToken cancellationToken)
{
var root = await document.GetSyntaxRootAsync().ConfigureAwait(false);
var paramNode = GetParamNode(root, span, cancellationToken);
var removedNodes = new List<SyntaxNode> { paramNode };
var paramNodeSiblings = paramNode.Parent.ChildNodes().ToList();
// This should not cause a crash because the diagnostics are only thrown in
// doc comment XML nodes, which, by definition, start with `///` (C#) or `'''` (VB.NET)
// If, perhaps, this specific node is not directly preceded by the comment marker node,
// it will be preceded by another XML node
var paramNodeIndex = paramNodeSiblings.IndexOf(paramNode);
var previousNodeTextTrimmed = paramNodeSiblings[paramNodeIndex - 1].ToFullString().Trim();
if (previousNodeTextTrimmed == string.Empty || previousNodeTextTrimmed == DocCommentSignifierToken)
{
removedNodes.Add(paramNodeSiblings[paramNodeIndex - 1]);
}
// Remove all trivia attached to the nodes I am removing.
// Really, any option should work here because the leading/trailing text
// around these nodes are not attached to them as trivia.
var newRoot = root.RemoveNodes(removedNodes, SyntaxRemoveOptions.KeepNoTrivia);
return document.WithSyntaxRoot(newRoot);
}
private class MyCodeAction : CodeAction.DocumentChangeAction
{
public MyCodeAction(Func<CancellationToken, Task<Document>> createChangedDocument) :
base(FeaturesResources.Remove_tag, createChangedDocument)
{
}
}
}
}
\ No newline at end of file
......@@ -224,6 +224,7 @@
<Compile Include="Diagnostics\AbstractHostDiagnosticUpdateSource.cs" />
<Compile Include="Diagnostics\Analyzers\QualifyMemberAccessDiagnosticAnalyzerBase.cs" />
<Compile Include="Diagnostics\Analyzers\NamingStyles\Capitalization.cs" />
<Compile Include="DocumentationComments\CodeFixes\AbstractRemoveDocCommentNodeCodeFixProvider.cs" />
<Compile Include="FindReferences\DefinitionItem.cs" />
<Compile Include="FindReferences\DefinitionItem.DocumentLocationDefinitionItem.cs" />
<Compile Include="FindReferences\DefinitionItem.NonNavigatingDefinitionItem.cs" />
......
......@@ -2085,6 +2085,15 @@ internal class FeaturesResources {
}
}
/// <summary>
/// Looks up a localized string similar to Remove tag.
/// </summary>
internal static string Remove_tag {
get {
return ResourceManager.GetString("Remove_tag", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Remove Unnecessary Cast.
/// </summary>
......
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
......@@ -1044,4 +1043,7 @@ This version used in: {2}</value>
<data name="Rename_type_to_0" xml:space="preserve">
<value>Rename type to {0}</value>
</data>
<data name="Remove_tag" xml:space="preserve">
<value>Remove tag</value>
</data>
</root>
\ No newline at end of file
......@@ -302,6 +302,7 @@
<Compile Include="Diagnostics\VisualBasicAnalyzerDriverService.vb" />
<Compile Include="DocumentationComments\DocumentationCommentUtilities.vb" />
<Compile Include="DocumentationComments\VisualBasicDocumentationCommentFormattingService.vb" />
<Compile Include="DocumentationComments\CodeFixes\VisualBasicRemoveDocCommentNodeCodeFixProvider.vb" />
<Compile Include="EditAndContinue\BreakpointSpans.vb" />
<Compile Include="EditAndContinue\StatementSyntaxComparer.vb" />
<Compile Include="EditAndContinue\SyntaxComparer.vb" />
......
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports System.Collections.Immutable
Imports System.Composition
Imports Microsoft.CodeAnalysis.CodeFixes
Imports Microsoft.CodeAnalysis.VisualBasic
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Namespace Microsoft.CodeAnalysis.DiagnosticComments.CodeFixes
<ExportCodeFixProvider(LanguageNames.VisualBasic, Name:=PredefinedCodeFixProviderNames.RemoveDocCommentNode), [Shared]>
Friend Class VisualBasicRemoveDocCommentNodeCodeFixProvider
Inherits AbstractRemoveDocCommentNodeCodeFixProvider(Of XmlElementSyntax)
''' <summary>
''' XML comment tag with identical attributes
''' </summary>
Private Const BC42305 As String = NameOf(BC42305)
''' <summary>
''' XML comment tag is not permitted on a 'sub' language element
''' </summary>
Private Const BC42306 As String = NameOf(BC42306)
''' <summary>
''' XML comment type parameter does not match a type parameter
''' </summary>
Private Const BC42307 As String = NameOf(BC42307)
''' <summary>
''' XML comment tag 'returns' is not permitted on a 'WriteOnly' property
''' </summary>
Private Const BC42313 As String = NameOf(BC42313)
''' <summary>
''' XML comment tag 'returns' is not permitted on a 'declare sub' language element
''' </summary>
Private Const BC42315 As String = NameOf(BC42315)
''' <summary>
''' XML comment type parameter does not match a type parameter
''' </summary>
Private Const BC42317 As String = NameOf(BC42317)
Friend ReadOnly Id As ImmutableArray(Of String) = ImmutableArray.Create(BC42305, BC42306, BC42307, BC42313, BC42315, BC42317)
Public Overrides ReadOnly Property FixableDiagnosticIds As ImmutableArray(Of String)
Get
Return Id
End Get
End Property
Protected Overrides ReadOnly Property DocCommentSignifierToken As String
Get
Return "'''"
End Get
End Property
Protected Overrides Function GetRevisedDocCommentTrivia(docCommentText As String) As SyntaxTriviaList
Return SyntaxFactory.ParseLeadingTrivia(docCommentText)
End Function
End Class
End Namespace
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册