Skip to content

Commit

Permalink
Merge pull request #44357 from dotnet/merges/master-to-master-vs-deps
Browse files Browse the repository at this point in the history
Merge master to master-vs-deps
  • Loading branch information
msftbot[bot] authored May 19, 2020
2 parents 6057e3c + 14a785e commit c8d525c
Show file tree
Hide file tree
Showing 71 changed files with 2,061 additions and 94 deletions.
2 changes: 1 addition & 1 deletion eng/Versions.props
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<MajorVersion>3</MajorVersion>
<MinorVersion>7</MinorVersion>
<PatchVersion>0</PatchVersion>
<PreReleaseVersionLabel>2</PreReleaseVersionLabel>
<PreReleaseVersionLabel>3</PreReleaseVersionLabel>
<VersionPrefix>$(MajorVersion).$(MinorVersion).$(PatchVersion)</VersionPrefix>
<!--
By default the assembly version in official builds is "$(MajorVersion).$(MinorVersion).0.0".
Expand Down
8 changes: 4 additions & 4 deletions eng/config/PublishData.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,21 +72,21 @@
"vsBranch": "rel/d16.6",
"vsMajorVersion": 16
},
"release/dev16.7-preview1-vs-deps": {
"release/dev16.7-preview2-vs-deps": {
"nugetKind": ["Shipping", "NonShipping"],
"version": "3.7.*",
"nuget": [ "https://dotnet.myget.org/F/roslyn/api/v2/package" ],
"vsix": [ "https://dotnet.myget.org/F/roslyn/vsix/upload" ],
"channels": [ "dev16.7", "dev16.7p1" ],
"vsBranch": "rel/d16.7",
"channels": [ "dev16.7", "dev16.7p2" ],
"vsBranch": "master",
"vsMajorVersion": 16
},
"master-vs-deps": {
"nugetKind": ["Shipping", "NonShipping"],
"version": "3.7.*",
"nuget": [ "https://dotnet.myget.org/F/roslyn/api/v2/package" ],
"vsix": [ "https://dotnet.myget.org/F/roslyn/vsix/upload" ],
"channels": [ "dev16.7", "dev16.7p2" ],
"channels": [ "dev16.7", "dev16.7p3" ],
"vsBranch": "master",
"vsMajorVersion": 16
},
Expand Down
1 change: 1 addition & 0 deletions src/Analyzers/CSharp/Analyzers/CSharpAnalyzers.projitems
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
<Compile Include="$(MSBuildThisFileDirectory)AddAccessibilityModifiers\CSharpAddAccessibilityModifiersDiagnosticAnalyzer.cs" />
<Compile Include="$(MSBuildThisFileDirectory)AddBraces\CSharpAddBracesDiagnosticAnalyzer.cs" />
<Compile Include="$(MSBuildThisFileDirectory)AddRequiredParentheses\CSharpAddRequiredPatternParenthesesDiagnosticAnalyzer.cs" />
<Compile Include="$(MSBuildThisFileDirectory)RemoveUnnecessarySuppressions\CSharpRemoveUnnecessarySuppressionsDiagnosticAnalyzer.cs" />
<Compile Include="$(MSBuildThisFileDirectory)RemoveUnnecessaryParentheses\CSharpRemoveUnnecessaryPatternParenthesesDiagnosticAnalyzer.cs" />
<Compile Include="..\..\..\Analyzers\CSharp\Analyzers\AddRequiredParentheses\CSharpAddRequiredExpressionParenthesesDiagnosticAnalyzer.cs" />
<Compile Include="$(MSBuildThisFileDirectory)ConvertAnonymousTypeToTuple\CSharpConvertAnonymousTypeToTupleDiagnosticAnalyzer.cs" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.RemoveUnnecessarySuppressions;

#nullable enable

namespace Microsoft.CodeAnalysis.CSharp.RemoveUnnecessarySuppressions
{
[DiagnosticAnalyzer(LanguageNames.CSharp)]
internal sealed class CSharpRemoveUnnecessarySuppressionsDiagnosticAnalyzer
: AbstractRemoveUnnecessarySuppressionsDiagnosticAnalyzer
{
protected override void RegisterAttributeSyntaxAction(CompilationStartAnalysisContext context, CompilationAnalyzer compilationAnalyzer)
{
context.RegisterSyntaxNodeAction(context =>
{
var attributeList = (AttributeListSyntax)context.Node;
switch (attributeList.Target?.Identifier.Kind())
{
case SyntaxKind.AssemblyKeyword:
case SyntaxKind.ModuleKeyword:
foreach (var attribute in attributeList.Attributes)
{
compilationAnalyzer.AnalyzeAssemblyOrModuleAttribute(attribute, context.SemanticModel, context.ReportDiagnostic, context.CancellationToken);
}
break;
}
}, SyntaxKind.AttributeList);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
<Compile Include="$(MSBuildThisFileDirectory)MisplacedUsingDirectives\MisplacedUsingDirectivesCodeFixProviderTests.cs" />
<Compile Include="$(MSBuildThisFileDirectory)OrderModifiers\OrderModifiersCompilerErrorTests.cs" />
<Compile Include="$(MSBuildThisFileDirectory)OrderModifiers\OrderModifiersTests.cs" />
<Compile Include="$(MSBuildThisFileDirectory)RemoveUnnecessarySuppressions\RemoveUnnecessarySuppressionsTests.cs" />
<Compile Include="$(MSBuildThisFileDirectory)RemoveUnnecessaryParentheses\RemoveUnnecessaryPatternParenthesesTests.cs" />
<Compile Include="$(MSBuildThisFileDirectory)RemoveUnreachableCode\RemoveUnreachableCodeTests.cs" />
<Compile Include="$(MSBuildThisFileDirectory)SimplifyBooleanExpression\SimplifyConditionalTests.cs" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#nullable enable

using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;
using VerifyCS = Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions.CSharpCodeFixVerifier<
Microsoft.CodeAnalysis.CSharp.RemoveUnnecessarySuppressions.CSharpRemoveUnnecessarySuppressionsDiagnosticAnalyzer,
Microsoft.CodeAnalysis.RemoveUnnecessarySuppressions.RemoveUnnecessarySuppressionsCodeFixProvider>;

namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.RemoveUnnecessarySuppressions
{
[Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnnecessarySuppressions)]
[WorkItem(44176, "https://github.com/dotnet/roslyn/issues/44176")]
public class RemoveUnnecessarySuppressionsTests
{
[Fact]
public void TestStandardProperties()
=> VerifyCS.VerifyStandardProperties();

[Theory]
// Field
[InlineData(@"Scope = ""member""", @"Target = ""~F:N.C.F""", "assembly")]
// Property
[InlineData(@"Scope = ""member""", @"Target = ""~P:N.C.P""", "assembly")]
// Method
[InlineData(@"Scope = ""member""", @"Target = ""~M:N.C.M()""", "assembly")]
// Type
[InlineData(@"Scope = ""member""", @"Target = ""~T:N.C""", "assembly")]
// Namespace
[InlineData(@"Scope = ""namespace""", @"Target = ""~N:N""", "assembly")]
// NamespaceAndDescendants
[InlineData(@"Scope = ""namespaceanddescendants""", @"Target = ""~N:N""", "assembly")]
// Module - no scope, no target
[InlineData(null, null, "assembly")]
// Module - no target
[InlineData(@"Scope = ""module""", null, "assembly")]
// Module - null target
[InlineData(@"Scope = ""module""", @"Target = null", "assembly")]
// Resource - not handled
[InlineData(@"Scope = ""resource""", @"Target = """"", "assembly")]
// 'module' attribute target
[InlineData(@"Scope = ""member""", @"Target = ""~M:N.C.M()""", "module")]
// Member with non-matching scope (seems to be respected by suppression decoder)
[InlineData(@"Scope = ""type""", @"Target = ""~M:N.C.M()""", "assembly")]
[InlineData(@"Scope = ""namespace""", @"Target = ""~F:N.C.F""", "assembly")]
// Case insensitive scope
[InlineData(@"Scope = ""Member""", @"Target = ""~F:N.C.F""", "assembly")]
[InlineData(@"Scope = ""MEMBER""", @"Target = ""~F:N.C.F""", "assembly")]
public async Task ValidSuppressions(string? scope, string? target, string attributeTarget)
{
var scopeString = scope != null ? $@", {scope}" : string.Empty;
var targetString = target != null ? $@", {target}" : string.Empty;

var input = $@"
[{attributeTarget}: System.Diagnostics.CodeAnalysis.SuppressMessage(""Category"", ""Id: Title"", Justification = ""Pending""{scopeString}{targetString})]
namespace N
{{
class C
{{
public int F;
public int P {{ get; }}
public void M() {{ }}
}}
}}";
await VerifyCS.VerifyCodeFixAsync(input, input);
}

[Theory]
// Field - no matching symbol
[InlineData(@"Scope = ""member""", @"Target = ""~F:N.C.F2""", "assembly")]
// Field - no matching symbol (case insensitive)
[InlineData(@"Scope = ""Member""", @"Target = ""~F:N.C.F2""", "assembly")]
[InlineData(@"Scope = ""MEMBER""", @"Target = ""~F:N.C.F2""", "assembly")]
// Property - invalid scope
[InlineData(@"Scope = ""invalid""", @"Target = ""~P:N.C.P""", "assembly")]
// Method - wrong signature
[InlineData(@"Scope = ""member""", @"Target = ""~M:N.C.M(System.Int32)""", "assembly")]
// Method - module scope
[InlineData(@"Scope = ""module""", @"Target = ""~M:N.C.M()""", "assembly")]
// Method - null scope
[InlineData(@"Scope = null", @"Target = ""~M:N.C.M()""", "assembly")]
// Method - no scope
[InlineData(null, @"Target = ""~M:N.C.M()""", "assembly")]
// Member scope - null target
[InlineData(@"Scope = ""member""", @"Target = null", "assembly")]
// Member scope - no target
[InlineData(@"Scope = ""member""", null, "assembly")]
// Type - no matching namespace
[InlineData(@"Scope = ""type""", @"Target = ""~T:N2.C""", "assembly")]
// Namespace - extra namespace qualification
[InlineData(@"Scope = ""namespace""", @"Target = ""~N:N.N2""", "assembly")]
// NamespaceAndDescendants - empty target
[InlineData(@"Scope = ""namespaceanddescendants""", @"Target = """"", "assembly")]
// Module - no scope, empty target
[InlineData(null, @"Target = """"", "assembly")]
// Module - no scope, non-empty target
[InlineData(null, @"Target = ""~T:N.C""", "assembly")]
// Module scope, empty target
[InlineData(@"Scope = ""module""", @"Target = """"", "assembly")]
// Module no scope, non-empty target
[InlineData(@"Scope = ""module""", @"Target = ""~T:N.C""", "assembly")]
public async Task InvalidSuppressions(string? scope, string? target, string attributeTarget)
{
var scopeString = scope != null ? $@", {scope}" : string.Empty;
var targetString = target != null ? $@", {target}" : string.Empty;

var input = $@"
[{attributeTarget}: [|System.Diagnostics.CodeAnalysis.SuppressMessage(""Category"", ""Id: Title"", Justification = ""Pending""{scopeString}{targetString})|]]
namespace N
{{
class C
{{
public int F;
public int P {{ get; }}
public void M() {{ }}
}}
}}";

var fixedCode = $@"
namespace N
{{
class C
{{
public int F;
public int P {{ get; }}
public void M() {{ }}
}}
}}";
await VerifyCS.VerifyCodeFixAsync(input, fixedCode);
}

[Fact]
public async Task ValidAndInvalidSuppressions()
{
var attributePrefix = @"System.Diagnostics.CodeAnalysis.SuppressMessage(""Category"", ""Id: Title"", Justification = ""Pending""";
var validSuppression = $@"{attributePrefix}, Scope = ""member"", Target = ""~T:C"")";
var invalidSuppression = $@"[|{attributePrefix}, Scope = ""member"", Target = """")|]";

var input = $@"
[assembly: {validSuppression}]
[assembly: {invalidSuppression}]
[assembly: {validSuppression}, {validSuppression}]
[assembly: {invalidSuppression}, {invalidSuppression}]
[assembly: {validSuppression}, {invalidSuppression}]
[assembly: {invalidSuppression}, {validSuppression}]
[assembly: {invalidSuppression}, {validSuppression}, {invalidSuppression}, {validSuppression}]
class C {{ }}
";

var fixedCode = $@"
[assembly: {validSuppression}]
[assembly: {validSuppression}, {validSuppression}]
[assembly: {validSuppression}]
[assembly: {validSuppression}]
[assembly: {validSuppression}, {validSuppression}]
class C {{ }}
";
await VerifyCS.VerifyCodeFixAsync(input, fixedCode);
}

[Theory]
[InlineData("")]
[InlineData(@", Scope = ""member"", Target = ""~M:C.M()""")]
[InlineData(@", Scope = ""invalid"", Target = ""invalid""")]
public async Task LocalSuppressions(string scopeAndTarget)
{
var input = $@"
[System.Diagnostics.CodeAnalysis.SuppressMessage(""Category"", ""Id: Title"", Justification = ""Pending""{scopeAndTarget})]
class C
{{
public void M() {{ }}
}}";
await VerifyCS.VerifyCodeFixAsync(input, input);
}
}
}
4 changes: 4 additions & 0 deletions src/Analyzers/Core/Analyzers/Analyzers.projitems
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@
<Compile Include="$(MSBuildThisFileDirectory)Helpers\DiagnosticHelper.cs" />
<Compile Include="$(MSBuildThisFileDirectory)IDEDiagnosticIds.cs" />
<Compile Include="$(MSBuildThisFileDirectory)IDEDiagnosticIdToOptionMappingHelper.cs" />
<Compile Include="$(MSBuildThisFileDirectory)RemoveUnnecessarySuppressions\SuppressMessageAttributeState.cs" />
<Compile Include="$(MSBuildThisFileDirectory)RemoveUnnecessarySuppressions\AbstractRemoveUnnecessarySuppressionsDiagnosticAnalyzer.cs" />
<Compile Include="$(MSBuildThisFileDirectory)..\..\..\Compilers\Core\Portable\DiagnosticAnalyzer\SuppressMessageAttributeState.TargetScope.cs" Link="RemoveUnnecessarySuppressions\SuppressMessageAttributeState.TargetScope.cs" />
<Compile Include="$(MSBuildThisFileDirectory)..\..\..\Compilers\Core\Portable\DiagnosticAnalyzer\SuppressMessageAttributeState.TargetSymbolResolver.cs" Link="RemoveUnnecessarySuppressions\SuppressMessageAttributeState.TargetSymbolResolver.cs" />
<Compile Include="$(MSBuildThisFileDirectory)MakeFieldReadonly\MakeFieldReadonlyDiagnosticAnalyzer.cs" />
<Compile Include="$(MSBuildThisFileDirectory)NamingStyle\NamingStyleDiagnosticAnalyzerBase.cs" />
<Compile Include="$(MSBuildThisFileDirectory)OrderModifiers\AbstractOrderModifiersDiagnosticAnalyzer.cs" />
Expand Down
9 changes: 9 additions & 0 deletions src/Analyzers/Core/Analyzers/AnalyzersResources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -307,4 +307,13 @@
<data name="Conditional_expression_can_be_simplified" xml:space="preserve">
<value>Conditional expression can be simplified</value>
</data>
<data name="Invalid_global_SuppressMessageAttribute" xml:space="preserve">
<value>Invalid global 'SuppressMessageAttribute'</value>
</data>
<data name="Invalid_scope_for_SuppressMessageAttribute" xml:space="preserve">
<value>Invalid scope for 'SuppressMessageAttribute'</value>
</data>
<data name="Invalid_or_missing_target_for_SuppressMessageAttribute" xml:space="preserve">
<value>Invalid or missing target for 'SuppressMessageAttribute'</value>
</data>
</root>
2 changes: 2 additions & 0 deletions src/Analyzers/Core/Analyzers/IDEDiagnosticIds.cs
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,8 @@ internal static class IDEDiagnosticIds

public const string SimplifyConditionalExpressionDiagnosticId = "IDE0075";

public const string InvalidSuppressMessageAttributeDiagnosticId = "IDE0076";

// Analyzer error Ids
public const string AnalyzerChangedId = "IDE1001";
public const string AnalyzerDependencyConflictId = "IDE1002";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#nullable enable

using System;
using System.Collections.Immutable;
using System.Threading;
using Microsoft.CodeAnalysis.CodeQuality;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Shared.Extensions;

namespace Microsoft.CodeAnalysis.RemoveUnnecessarySuppressions
{
internal abstract class AbstractRemoveUnnecessarySuppressionsDiagnosticAnalyzer
: AbstractCodeQualityDiagnosticAnalyzer
{
private static readonly LocalizableResourceString s_localizableTitle = new LocalizableResourceString(
nameof(AnalyzersResources.Invalid_global_SuppressMessageAttribute), AnalyzersResources.ResourceManager, typeof(AnalyzersResources));
private static readonly LocalizableResourceString s_localizableInvalidScopeMessage = new LocalizableResourceString(
nameof(AnalyzersResources.Invalid_scope_for_SuppressMessageAttribute), AnalyzersResources.ResourceManager, typeof(AnalyzersResources));
private static readonly LocalizableResourceString s_localizableInvalidOrMissingTargetMessage = new LocalizableResourceString(
nameof(AnalyzersResources.Invalid_or_missing_target_for_SuppressMessageAttribute), AnalyzersResources.ResourceManager, typeof(AnalyzersResources));

private static readonly DiagnosticDescriptor s_invalidScopeDescriptor = CreateDescriptor(
IDEDiagnosticIds.InvalidSuppressMessageAttributeDiagnosticId, s_localizableTitle, s_localizableInvalidScopeMessage, isUnnecessary: true);
private static readonly DiagnosticDescriptor s_invalidOrMissingTargetDescriptor = CreateDescriptor(
IDEDiagnosticIds.InvalidSuppressMessageAttributeDiagnosticId, s_localizableTitle, s_localizableInvalidOrMissingTargetMessage, isUnnecessary: true);

public AbstractRemoveUnnecessarySuppressionsDiagnosticAnalyzer()
: base(ImmutableArray.Create(s_invalidScopeDescriptor, s_invalidOrMissingTargetDescriptor), GeneratedCodeAnalysisFlags.None)
{
}

protected abstract void RegisterAttributeSyntaxAction(CompilationStartAnalysisContext context, CompilationAnalyzer compilationAnalyzer);
public sealed override DiagnosticAnalyzerCategory GetAnalyzerCategory() => DiagnosticAnalyzerCategory.SemanticDocumentAnalysis;

protected sealed override void InitializeWorker(AnalysisContext context)
{
context.RegisterCompilationStartAction(context =>
{
var suppressMessageAttributeType = context.Compilation.SuppressMessageAttributeType();
if (suppressMessageAttributeType == null)
{
return;
}
RegisterAttributeSyntaxAction(context, new CompilationAnalyzer(context.Compilation, suppressMessageAttributeType));
});
}

protected sealed class CompilationAnalyzer
{
private readonly SuppressMessageAttributeState _state;

public CompilationAnalyzer(Compilation compilation, INamedTypeSymbol suppressMessageAttributeType)
{
_state = new SuppressMessageAttributeState(compilation, suppressMessageAttributeType);
}

public void AnalyzeAssemblyOrModuleAttribute(SyntaxNode attributeSyntax, SemanticModel model, Action<Diagnostic> reportDiagnostic, CancellationToken cancellationToken)
{
if (!_state.IsSuppressMessageAttributeWithNamedArguments(attributeSyntax, model, cancellationToken, out var namedAttributeArguments))
{
return;
}

DiagnosticDescriptor rule;
if (_state.HasInvalidScope(namedAttributeArguments, out var targetScope))
{
rule = s_invalidScopeDescriptor;
}
else if (_state.HasInvalidOrMissingTarget(namedAttributeArguments, targetScope))
{
rule = s_invalidOrMissingTargetDescriptor;
}
else
{
return;
}

reportDiagnostic(Diagnostic.Create(rule, attributeSyntax.GetLocation()));
}
}
}
}
Loading

0 comments on commit c8d525c

Please sign in to comment.