未验证 提交 ff431c22 编写于 作者: M Manish Vasani 提交者: GitHub

Merge pull request #37615 from jnm2/existing_globalsuppressions

 Recognize existing GlobalSuppressions.cs when it has a using directive 
......@@ -1539,6 +1539,39 @@ class Class { }
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage(""InfoDiagnostic"", ""InfoDiagnostic:InfoDiagnostic"", Justification = ""<Pending>"", Scope = ""type"", Target = ""Class"")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage(""InfoDiagnostic"", ""InfoDiagnostic:InfoDiagnostic"", Justification = ""{FeaturesResources.Pending}"", Scope = ""type"", Target = ""~T:Class2"")]
";
await TestAsync(initialMarkup, expectedText);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsSuppression)]
public async Task TestSuppressionWithUsingDirectiveInExistingGlobalSuppressionsDocument()
{
var initialMarkup = @"<Workspace>
<Project Language=""C#"" CommonReferences=""true"" AssemblyName=""Proj1"">
<Document FilePath=""CurrentDocument.cs""><![CDATA[
using System;
class Class { }
[|class Class2|] { }
]]>
</Document>
<Document FilePath=""GlobalSuppressions.cs""><![CDATA[
using System.Diagnostics.CodeAnalysis;
[assembly: SuppressMessage(""InfoDiagnostic"", ""InfoDiagnostic:InfoDiagnostic"", Justification = ""<Pending>"", Scope = ""type"", Target = ""Class"")]
]]>
</Document>
</Project>
</Workspace>";
var expectedText =
$@"
using System.Diagnostics.CodeAnalysis;
[assembly: SuppressMessage(""InfoDiagnostic"", ""InfoDiagnostic:InfoDiagnostic"", Justification = ""<Pending>"", Scope = ""type"", Target = ""Class"")]
[assembly: SuppressMessage(""InfoDiagnostic"", ""InfoDiagnostic:InfoDiagnostic"", Justification = ""{FeaturesResources.Pending}"", Scope = ""type"", Target = ""~T:Class2"")]
";
await TestAsync(initialMarkup, expectedText);
......
......@@ -1475,7 +1475,7 @@ End Class]]>
' a specific target and scoped to a namespace, type, member, etc.
<Assembly: Diagnostics.CodeAnalysis.SuppressMessage(""InfoDiagnostic"", ""InfoDiagnostic:InfoDiagnostic"", Justification:=""<Pending>"", Scope:=""type"", Target:=""Class1"")>
<Assembly: System.Diagnostics.CodeAnalysis.SuppressMessage(""InfoDiagnostic"", ""InfoDiagnostic:InfoDiagnostic"", Justification:=""{FeaturesResources.Pending}"", Scope:=""type"", Target:=""~T:Class2"")>
<Assembly: Diagnostics.CodeAnalysis.SuppressMessage(""InfoDiagnostic"", ""InfoDiagnostic:InfoDiagnostic"", Justification:=""{FeaturesResources.Pending}"", Scope:=""type"", Target:=""~T:Class2"")>
"
Await TestAsync(source.ToString(), expected)
......@@ -1511,7 +1511,7 @@ End Class
' Project-level suppressions either have no target or are given
' a specific target and scoped to a namespace, type, member, etc.
<Assembly: System.Diagnostics.CodeAnalysis.SuppressMessage(""InfoDiagnostic"", ""InfoDiagnostic:InfoDiagnostic"", Justification:=""{FeaturesResources.Pending}"", Scope:=""type"", Target:=""~T:Class2"")>
<Assembly: Diagnostics.CodeAnalysis.SuppressMessage(""InfoDiagnostic"", ""InfoDiagnostic:InfoDiagnostic"", Justification:=""{FeaturesResources.Pending}"", Scope:=""type"", Target:=""~T:Class2"")>
"
Await TestAsync(source.ToString(), expected)
......@@ -1557,7 +1557,40 @@ End Class
' a specific target and scoped to a namespace, type, member, etc.
<Assembly: Diagnostics.CodeAnalysis.SuppressMessage(""InfoDiagnostic"", ""InfoDiagnostic:InfoDiagnostic"", Justification:=""<Pending>"", Scope:=""type"", Target:=""Class1"")>
<Assembly: System.Diagnostics.CodeAnalysis.SuppressMessage(""InfoDiagnostic"", ""InfoDiagnostic:InfoDiagnostic"", Justification:=""{FeaturesResources.Pending}"", Scope:=""type"", Target:=""~T:Class2"")>
<Assembly: Diagnostics.CodeAnalysis.SuppressMessage(""InfoDiagnostic"", ""InfoDiagnostic:InfoDiagnostic"", Justification:=""{FeaturesResources.Pending}"", Scope:=""type"", Target:=""~T:Class2"")>
"
Await TestAsync(source.ToString(), expected)
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsSuppression)>
Public Async Function TestSuppressionWithUsingDirectiveInExistingGlobalSuppressionsDocument() As Task
Dim source =
<Workspace>
<Project Language="Visual Basic" CommonReferences="true">
<Document FilePath="CurrentDocument.vb"><![CDATA[
Imports System
Class Class1
End Class
[|Class Class2|]
End Class]]>
</Document>
<Document FilePath="GlobalSuppressions.vb"><![CDATA[
Imports System.Diagnostics.CodeAnalysis
<Assembly: SuppressMessage("InfoDiagnostic", "InfoDiagnostic:InfoDiagnostic", Justification:="<Pending>", Scope:="type", Target:="Class1")>
]]>
</Document>
</Project>
</Workspace>
Dim expected = $"
Imports System.Diagnostics.CodeAnalysis
<Assembly: SuppressMessage(""InfoDiagnostic"", ""InfoDiagnostic:InfoDiagnostic"", Justification:=""<Pending>"", Scope:=""type"", Target:=""Class1"")>
<Assembly: SuppressMessage(""InfoDiagnostic"", ""InfoDiagnostic:InfoDiagnostic"", Justification:=""{FeaturesResources.Pending}"", Scope:=""type"", Target:=""~T:Class2"")>
"
Await TestAsync(source.ToString(), expected)
......@@ -1645,7 +1678,7 @@ End Class
Imports System
' Some Trivia
<System.Diagnostics.CodeAnalysis.SuppressMessage(""InfoDiagnostic"", ""InfoDiagnostic:InfoDiagnostic"", Justification:=""{FeaturesResources.Pending}"")>
<Diagnostics.CodeAnalysis.SuppressMessage(""InfoDiagnostic"", ""InfoDiagnostic:InfoDiagnostic"", Justification:=""{FeaturesResources.Pending}"")>
Class C
Sub Method()
Dim x
......@@ -1668,7 +1701,7 @@ End Class
Imports System
' Some Trivia
<System.Diagnostics.CodeAnalysis.SuppressMessage("SomeOtherDiagnostic", "SomeOtherDiagnostic:Title", Justification:="<Pending>")>
<Diagnostics.CodeAnalysis.SuppressMessage("SomeOtherDiagnostic", "SomeOtherDiagnostic:Title", Justification:="<Pending>")>
[|Class C|]
Sub Method()
Dim x
......@@ -1679,8 +1712,8 @@ End Class
Imports System
' Some Trivia
<System.Diagnostics.CodeAnalysis.SuppressMessage(""SomeOtherDiagnostic"", ""SomeOtherDiagnostic:Title"", Justification:=""<Pending>"")>
<System.Diagnostics.CodeAnalysis.SuppressMessage(""InfoDiagnostic"", ""InfoDiagnostic:InfoDiagnostic"", Justification:=""{FeaturesResources.Pending}"")>
<Diagnostics.CodeAnalysis.SuppressMessage(""SomeOtherDiagnostic"", ""SomeOtherDiagnostic:Title"", Justification:=""<Pending>"")>
<Diagnostics.CodeAnalysis.SuppressMessage(""InfoDiagnostic"", ""InfoDiagnostic:InfoDiagnostic"", Justification:=""{FeaturesResources.Pending}"")>
Class C
Sub Method()
Dim x
......@@ -1719,7 +1752,7 @@ Imports System
''' <summary>
''' My custom type
''' </summary>
<System.Diagnostics.CodeAnalysis.SuppressMessage(""InfoDiagnostic"", ""InfoDiagnostic:InfoDiagnostic"", Justification:=""{FeaturesResources.Pending}"")>
<Diagnostics.CodeAnalysis.SuppressMessage(""InfoDiagnostic"", ""InfoDiagnostic:InfoDiagnostic"", Justification:=""{FeaturesResources.Pending}"")>
Class C
Sub Method()
Dim x
......@@ -1760,7 +1793,7 @@ Imports System
''' My custom type
''' </summary>
<Diagnostics.CodeAnalysis.SuppressMessage(""SomeOtherDiagnostic"", ""SomeOtherDiagnostic:Title"", Justification:=""<Pending>"")>
<System.Diagnostics.CodeAnalysis.SuppressMessage(""InfoDiagnostic"", ""InfoDiagnostic:InfoDiagnostic"", Justification:=""{FeaturesResources.Pending}"")>
<Diagnostics.CodeAnalysis.SuppressMessage(""InfoDiagnostic"", ""InfoDiagnostic:InfoDiagnostic"", Justification:=""{FeaturesResources.Pending}"")>
Class C
Sub Method()
Dim x
......@@ -1794,7 +1827,7 @@ Imports System
Namespace N
' Some Trivia
<System.Diagnostics.CodeAnalysis.SuppressMessage(""InfoDiagnostic"", ""InfoDiagnostic:InfoDiagnostic"", Justification:=""{FeaturesResources.Pending}"")>
<Diagnostics.CodeAnalysis.SuppressMessage(""InfoDiagnostic"", ""InfoDiagnostic:InfoDiagnostic"", Justification:=""{FeaturesResources.Pending}"")>
Class C
Sub Method()
Dim x
......@@ -1828,7 +1861,7 @@ Imports System
Class Generic(Of T)
' Some Trivia
<System.Diagnostics.CodeAnalysis.SuppressMessage(""InfoDiagnostic"", ""InfoDiagnostic:InfoDiagnostic"", Justification:=""{FeaturesResources.Pending}"")>
<Diagnostics.CodeAnalysis.SuppressMessage(""InfoDiagnostic"", ""InfoDiagnostic:InfoDiagnostic"", Justification:=""{FeaturesResources.Pending}"")>
Class C
Sub Method()
Dim x
......@@ -1863,7 +1896,7 @@ Imports System
Class Generic(Of T)
Class C
' Some Trivia
<System.Diagnostics.CodeAnalysis.SuppressMessage(""InfoDiagnostic"", ""InfoDiagnostic:InfoDiagnostic"", Justification:=""{FeaturesResources.Pending}"")>
<Diagnostics.CodeAnalysis.SuppressMessage(""InfoDiagnostic"", ""InfoDiagnostic:InfoDiagnostic"", Justification:=""{FeaturesResources.Pending}"")>
Sub Method()
Dim x
End Sub
......
......@@ -10,6 +10,7 @@
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Formatting;
using Microsoft.CodeAnalysis.Simplification;
using Microsoft.CodeAnalysis.Text;
namespace Microsoft.CodeAnalysis.CSharp.CodeFixes.Suppression
......@@ -124,9 +125,11 @@ protected override SyntaxNode AddLocalSuppressMessageAttribute(SyntaxNode target
SyntaxTriviaList leadingTrivia,
bool needsLeadingEndOfLine)
{
var attributeName = SyntaxFactory.ParseName(SuppressMessageAttributeName).WithAdditionalAnnotations(Simplifier.Annotation);
var attributeArguments = CreateAttributeArguments(targetSymbol, diagnostic, isAssemblyAttribute);
var attribute = SyntaxFactory.Attribute(SyntaxFactory.ParseName(SuppressMessageAttributeName), attributeArguments);
var attributes = new SeparatedSyntaxList<AttributeSyntax>().Add(attribute);
var attributes = new SeparatedSyntaxList<AttributeSyntax>()
.Add(SyntaxFactory.Attribute(attributeName, attributeArguments));
AttributeListSyntax attributeList;
if (isAssemblyAttribute)
......
......@@ -6,6 +6,7 @@
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.LanguageServices;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CodeFixes.Suppression
......@@ -70,12 +71,15 @@ protected async Task<Document> GetOrCreateSuppressionsDocumentAsync(Cancellation
var fullPath = !string.IsNullOrEmpty(filePath) ? Path.GetFullPath(filePath) : filePath;
if (fullPath == suppressionsFilePath)
{
// Existing global suppressions file, see if this file only has global assembly attributes.
// Existing global suppressions file. See if this file only has imports and global assembly
// attributes.
hasDocWithSuppressionsName = true;
var t = await document.GetSyntaxTreeAsync(c).ConfigureAwait(false);
var r = await t.GetRootAsync(c).ConfigureAwait(false);
if (r.ChildNodes().All(n => Fixer.IsAttributeListWithAssemblyAttributes(n)))
var syntaxFacts = _project.LanguageServices.GetRequiredService<ISyntaxFactsService>();
if (r.ChildNodes().All(n => syntaxFacts.IsUsingOrExternOrImport(n) || Fixer.IsAttributeListWithAssemblyAttributes(n)))
{
suppressionsDoc = document;
break;
......
......@@ -6,6 +6,7 @@ Imports System.Threading
Imports Microsoft.CodeAnalysis.CodeFixes
Imports Microsoft.CodeAnalysis.CodeFixes.Suppression
Imports Microsoft.CodeAnalysis.Formatting
Imports Microsoft.CodeAnalysis.Simplification
Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
......@@ -158,7 +159,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeFixes.Suppression
Private Function CreateAttributeList(targetSymbol As ISymbol, diagnostic As Diagnostic, isAssemblyAttribute As Boolean) As AttributeListSyntax
Dim attributeTarget = If(isAssemblyAttribute, SyntaxFactory.AttributeTarget(SyntaxFactory.Token(SyntaxKind.AssemblyKeyword)), Nothing)
Dim attributeName = SyntaxFactory.ParseName(SuppressMessageAttributeName)
Dim attributeName = SyntaxFactory.ParseName(SuppressMessageAttributeName).WithAdditionalAnnotations(Simplifier.Annotation)
Dim attributeArguments = CreateAttributeArguments(targetSymbol, diagnostic, isAssemblyAttribute)
Dim attribute As AttributeSyntax = SyntaxFactory.Attribute(attributeTarget, attributeName, attributeArguments)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册