diff --git a/src/Analyzers/CSharp/Analyzers/CSharpAnalyzers.projitems b/src/Analyzers/CSharp/Analyzers/CSharpAnalyzers.projitems index 0aade4854f24e..0efeba0ffee6c 100644 --- a/src/Analyzers/CSharp/Analyzers/CSharpAnalyzers.projitems +++ b/src/Analyzers/CSharp/Analyzers/CSharpAnalyzers.projitems @@ -96,6 +96,7 @@ + @@ -103,4 +104,4 @@ - + \ No newline at end of file diff --git a/src/Analyzers/CSharp/Analyzers/UsePatternMatching/CSharpUseNotPatternDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/UsePatternMatching/CSharpUseNotPatternDiagnosticAnalyzer.cs new file mode 100644 index 0000000000000..7a87419a24f2f --- /dev/null +++ b/src/Analyzers/CSharp/Analyzers/UsePatternMatching/CSharpUseNotPatternDiagnosticAnalyzer.cs @@ -0,0 +1,91 @@ +// 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.Collections.Immutable; +using Microsoft.CodeAnalysis.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.Shared.Extensions; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Diagnostics; + +namespace Microsoft.CodeAnalysis.CSharp.UsePatternMatching +{ + /// + /// Looks for code of the forms: + /// + /// var x = o as Type; + /// if (!(x is Y y)) ... + /// + /// and converts it to: + /// + /// if (x is not Y y) ... + /// + /// + [DiagnosticAnalyzer(LanguageNames.CSharp)] + internal partial class CSharpUseNotPatternDiagnosticAnalyzer : AbstractBuiltInCodeStyleDiagnosticAnalyzer + { + public CSharpUseNotPatternDiagnosticAnalyzer() + : base(IDEDiagnosticIds.UseNotPatternDiagnosticId, + CSharpCodeStyleOptions.PreferNotPattern, + LanguageNames.CSharp, + new LocalizableResourceString( + nameof(CSharpAnalyzersResources.Use_pattern_matching), CSharpAnalyzersResources.ResourceManager, typeof(CSharpAnalyzersResources))) + { + } + + public override DiagnosticAnalyzerCategory GetAnalyzerCategory() + => DiagnosticAnalyzerCategory.SemanticSpanAnalysis; + + protected override void InitializeWorker(AnalysisContext context) + { +#if !CODE_STYLE // CODE_STYLE layer doesn't currently support generating 'not patterns'. Do not bother analyzing. + context.RegisterSyntaxNodeAction(SyntaxNodeAction, SyntaxKind.LogicalNotExpression); +#endif + } + + private void SyntaxNodeAction(SyntaxNodeAnalysisContext syntaxContext) + { + var node = syntaxContext.Node; + var syntaxTree = node.SyntaxTree; + + // "x is not Type y" is only available in C# 9.0 and above. Don't offer this refactoring + // in projects targeting a lesser version. + if (!((CSharpParseOptions)syntaxTree.Options).LanguageVersion.IsCSharp9OrAbove()) + return; + + var options = syntaxContext.Options; + var cancellationToken = syntaxContext.CancellationToken; + + // Bail immediately if the user has disabled this feature. + var styleOption = options.GetOption(CSharpCodeStyleOptions.PreferNotPattern, syntaxTree, cancellationToken); + if (!styleOption.Value) + return; + + // Look for the form: !(x is Y y) + if (!(node is PrefixUnaryExpressionSyntax + { + Operand: ParenthesizedExpressionSyntax + { + Expression: IsPatternExpressionSyntax + { + Pattern: DeclarationPatternSyntax, + } isPattern, + }, + } notExpression)) + { + return; + } + + // Put a diagnostic with the appropriate severity on `is` keyword. + syntaxContext.ReportDiagnostic(DiagnosticHelper.Create( + Descriptor, + isPattern.IsKeyword.GetLocation(), + styleOption.Notification.Severity, + ImmutableArray.Create(notExpression.GetLocation()), + properties: null)); + } + } +} diff --git a/src/Analyzers/CSharp/CodeFixes/CSharpCodeFixes.projitems b/src/Analyzers/CSharp/CodeFixes/CSharpCodeFixes.projitems index 4c7912b80a93f..8ba1d0e8aec03 100644 --- a/src/Analyzers/CSharp/CodeFixes/CSharpCodeFixes.projitems +++ b/src/Analyzers/CSharp/CodeFixes/CSharpCodeFixes.projitems @@ -59,6 +59,7 @@ + diff --git a/src/Analyzers/CSharp/CodeFixes/UsePatternMatching/CSharpUseNotPatternCodeFixProvider.cs b/src/Analyzers/CSharp/CodeFixes/UsePatternMatching/CSharpUseNotPatternCodeFixProvider.cs new file mode 100644 index 0000000000000..e89a4c0745ebb --- /dev/null +++ b/src/Analyzers/CSharp/CodeFixes/UsePatternMatching/CSharpUseNotPatternCodeFixProvider.cs @@ -0,0 +1,94 @@ +// 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.Composition; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeActions; +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Editing; +using Microsoft.CodeAnalysis.Shared.Extensions; +using Roslyn.Utilities; + +namespace Microsoft.CodeAnalysis.CSharp.UsePatternMatching +{ + using static SyntaxFactory; + + [ExportCodeFixProvider(LanguageNames.CSharp), Shared] + internal partial class CSharpUseNotPatternCodeFixProvider : SyntaxEditorBasedCodeFixProvider + { + [ImportingConstructor] + [SuppressMessage("RoslynDiagnosticsReliability", "RS0033:Importing constructor should be [Obsolete]", Justification = "Used in test code: https://github.com/dotnet/roslyn/issues/42814")] + public CSharpUseNotPatternCodeFixProvider() + { + } + + public override ImmutableArray FixableDiagnosticIds + => ImmutableArray.Create(IDEDiagnosticIds.UseNotPatternDiagnosticId); + + internal sealed override CodeFixCategory CodeFixCategory => CodeFixCategory.CodeStyle; + + public override Task RegisterCodeFixesAsync(CodeFixContext context) + { + context.RegisterCodeFix(new MyCodeAction( + c => FixAsync(context.Document, context.Diagnostics.First(), c)), + context.Diagnostics); + return Task.CompletedTask; + } + + protected override Task FixAllAsync( + Document document, ImmutableArray diagnostics, + SyntaxEditor editor, CancellationToken cancellationToken) + { + foreach (var diagnostic in diagnostics) + { + cancellationToken.ThrowIfCancellationRequested(); + ProcessDiagnostic(editor, diagnostic, cancellationToken); + } + + return Task.CompletedTask; + } + + private static void ProcessDiagnostic( + SyntaxEditor editor, + Diagnostic diagnostic, + CancellationToken cancellationToken) + { +#if CODE_STYLE + Contract.Fail("We should have never gotten here as CODE_STYLE doesn't support C# 9 yet."); +#else + + var notExpressionLocation = diagnostic.AdditionalLocations[0]; + + var notExpression = (PrefixUnaryExpressionSyntax)notExpressionLocation.FindNode(getInnermostNodeForTie: true, cancellationToken); + var parenthesizedExpression = (ParenthesizedExpressionSyntax)notExpression.Operand; + var isPattern = (IsPatternExpressionSyntax)parenthesizedExpression.Expression; + + var updatedPattern = isPattern.WithPattern(UnaryPattern(Token(SyntaxKind.NotKeyword), isPattern.Pattern)); + editor.ReplaceNode( + notExpression, + updatedPattern.WithPrependedLeadingTrivia(notExpression.GetLeadingTrivia()) + .WithAppendedTrailingTrivia(notExpression.GetTrailingTrivia())); + +#endif + + } + + private class MyCodeAction : CustomCodeActions.DocumentChangeAction + { + public MyCodeAction(Func> createChangedDocument) + : base(CSharpAnalyzersResources.Use_pattern_matching, createChangedDocument, CSharpAnalyzersResources.Use_pattern_matching) + { + } + } + } +} diff --git a/src/Analyzers/CSharp/Tests/CSharpAnalyzers.UnitTests.projitems b/src/Analyzers/CSharp/Tests/CSharpAnalyzers.UnitTests.projitems index 8c7403ae72cf6..22a2b50061755 100644 --- a/src/Analyzers/CSharp/Tests/CSharpAnalyzers.UnitTests.projitems +++ b/src/Analyzers/CSharp/Tests/CSharpAnalyzers.UnitTests.projitems @@ -87,6 +87,7 @@ + diff --git a/src/Analyzers/CSharp/Tests/UsePatternMatching/CSharpUseNotPatternTests.cs b/src/Analyzers/CSharp/Tests/UsePatternMatching/CSharpUseNotPatternTests.cs new file mode 100644 index 0000000000000..cee824be3c437 --- /dev/null +++ b/src/Analyzers/CSharp/Tests/UsePatternMatching/CSharpUseNotPatternTests.cs @@ -0,0 +1,74 @@ +// 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 System.Threading.Tasks; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.UsePatternMatching; +using Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions; +using Microsoft.CodeAnalysis.Test.Utilities; +using Roslyn.Test.Utilities; +using Xunit; + +namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.UsePatternMatching +{ + using VerifyCS = CSharpCodeFixVerifier< + CSharpUseNotPatternDiagnosticAnalyzer, + CSharpUseNotPatternCodeFixProvider>; + + public partial class CSharpUseNotPatternTests + { +#if !CODE_STYLE + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseNotPattern)] + [WorkItem(46699, "https://github.com/dotnet/roslyn/issues/46699")] + public async Task UseNotPattern() + { + await new VerifyCS.Test + { + TestCode = +@"class C +{ + void M(object x) + { + if (!(x [|is|] string s)) + { + } + } +}", + FixedCode = +@"class C +{ + void M(object x) + { + if (x is not string s) + { + } + } +}", + LanguageVersion = LanguageVersion.CSharp9, + }.RunAsync(); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseNotPattern)] + public async Task UnavailableInCSharp8() + { + await new VerifyCS.Test + { + TestCode = +@"class C +{ + void M(object x) + { + if (!(x is string s)) + { + } + } +}", + LanguageVersion = LanguageVersion.CSharp8, + }.RunAsync(); + } + +#endif + } +} diff --git a/src/Analyzers/Core/Analyzers/IDEDiagnosticIds.cs b/src/Analyzers/Core/Analyzers/IDEDiagnosticIds.cs index 66387e5a2ffa3..d278de0d9c790 100644 --- a/src/Analyzers/Core/Analyzers/IDEDiagnosticIds.cs +++ b/src/Analyzers/Core/Analyzers/IDEDiagnosticIds.cs @@ -142,6 +142,9 @@ internal static class IDEDiagnosticIds public const string ConvertTypeOfToNameOfDiagnosticId = "IDE0082"; + public const string UseNotPatternDiagnosticId = "IDE0083"; + public const string UseIsNotExpressionDiagnosticId = "IDE0084"; + // Analyzer error Ids public const string AnalyzerChangedId = "IDE1001"; public const string AnalyzerDependencyConflictId = "IDE1002"; diff --git a/src/Analyzers/VisualBasic/Analyzers/UseIsNotExpression/VisualBasicUseIsNotDiagnosticAnalyzer.vb b/src/Analyzers/VisualBasic/Analyzers/UseIsNotExpression/VisualBasicUseIsNotDiagnosticAnalyzer.vb new file mode 100644 index 0000000000000..ad3c106ae7d52 --- /dev/null +++ b/src/Analyzers/VisualBasic/Analyzers/UseIsNotExpression/VisualBasicUseIsNotDiagnosticAnalyzer.vb @@ -0,0 +1,82 @@ +' 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. + +Imports System.Collections.Immutable +Imports Microsoft.CodeAnalysis.CodeStyle +Imports Microsoft.CodeAnalysis.Diagnostics +Imports Microsoft.CodeAnalysis.VisualBasic.CodeStyle +Imports Microsoft.CodeAnalysis.VisualBasic.Syntax + +Namespace Microsoft.CodeAnalysis.VisualBasic.UseIsNotExpression + ''' + ''' Looks for code of the forms: + ''' + ''' if not x is ... + ''' + ''' and converts it to: + ''' + ''' if x isnot ... + ''' + ''' + + Partial Friend Class VisualBasicUseIsNotExpressionDiagnosticAnalyzer + Inherits AbstractBuiltInCodeStyleDiagnosticAnalyzer + + Public Sub New() + MyBase.New(IDEDiagnosticIds.UseIsNotExpressionDiagnosticId, + VisualBasicCodeStyleOptions.PreferIsNotExpression, + LanguageNames.VisualBasic, + New LocalizableResourceString( + NameOf(VisualBasicAnalyzersResources.Use_IsNot_expression), VisualBasicAnalyzersResources.ResourceManager, GetType(VisualBasicAnalyzersResources))) + End Sub + + Public Overrides Function GetAnalyzerCategory() As DiagnosticAnalyzerCategory + Return DiagnosticAnalyzerCategory.SemanticSpanAnalysis + End Function + + Protected Overrides Sub InitializeWorker(context As AnalysisContext) + context.RegisterSyntaxNodeAction(AddressOf SyntaxNodeAction, SyntaxKind.NotExpression) + End Sub + + Private Sub SyntaxNodeAction(syntaxContext As SyntaxNodeAnalysisContext) + Dim node = syntaxContext.Node + Dim syntaxTree = node.SyntaxTree + + ' "x is not Type y" is only available in C# 9.0 and above. Don't offer this refactoring + ' in projects targeting a lesser version. + If DirectCast(syntaxTree.Options, VisualBasicParseOptions).LanguageVersion < LanguageVersion.VisualBasic14 Then + Return + End If + + Dim options = syntaxContext.Options + Dim cancellationToken = syntaxContext.CancellationToken + + ' Bail immediately if the user has disabled this feature. + Dim styleOption = options.GetOption(VisualBasicCodeStyleOptions.PreferIsNotExpression, syntaxTree, cancellationToken) + If Not styleOption.Value Then + Return + End If + + Dim notExpression = DirectCast(node, UnaryExpressionSyntax) + Dim operand = notExpression.Operand + + ' Look for the form: not x is y, or not typeof x is y + If Not operand.IsKind(SyntaxKind.IsExpression) AndAlso Not operand.IsKind(SyntaxKind.TypeOfIsExpression) Then + Return + End If + + Dim isKeyword = If(operand.IsKind(SyntaxKind.IsExpression), + DirectCast(operand, BinaryExpressionSyntax).OperatorToken, + DirectCast(operand, TypeOfExpressionSyntax).OperatorToken) + + ' Put a diagnostic with the appropriate severity on `is` keyword. + syntaxContext.ReportDiagnostic(DiagnosticHelper.Create( + Descriptor, + isKeyword.GetLocation(), + styleOption.Notification.Severity, + ImmutableArray.Create(notExpression.GetLocation()), + properties:=Nothing)) + End Sub + End Class +End Namespace diff --git a/src/Analyzers/VisualBasic/Analyzers/VisualBasicAnalyzers.projitems b/src/Analyzers/VisualBasic/Analyzers/VisualBasicAnalyzers.projitems index 9cef6706dece8..f06aba5084ed2 100644 --- a/src/Analyzers/VisualBasic/Analyzers/VisualBasicAnalyzers.projitems +++ b/src/Analyzers/VisualBasic/Analyzers/VisualBasicAnalyzers.projitems @@ -44,6 +44,7 @@ + @@ -52,4 +53,4 @@ - + \ No newline at end of file diff --git a/src/Analyzers/VisualBasic/Analyzers/VisualBasicAnalyzersResources.resx b/src/Analyzers/VisualBasic/Analyzers/VisualBasicAnalyzersResources.resx index 577f20f1f9c0e..a171b866ea844 100644 --- a/src/Analyzers/VisualBasic/Analyzers/VisualBasicAnalyzersResources.resx +++ b/src/Analyzers/VisualBasic/Analyzers/VisualBasicAnalyzersResources.resx @@ -136,4 +136,8 @@ 'GetType' can be converted to 'NameOf' + + Use 'IsNot' expression + {locked: IsNot}This is a Visual Basic keyword and should not be localized or have its casing changed + \ No newline at end of file diff --git a/src/Analyzers/VisualBasic/Analyzers/xlf/VisualBasicAnalyzersResources.cs.xlf b/src/Analyzers/VisualBasic/Analyzers/xlf/VisualBasicAnalyzersResources.cs.xlf index b6140dda45bbb..ae43249b5004a 100644 --- a/src/Analyzers/VisualBasic/Analyzers/xlf/VisualBasicAnalyzersResources.cs.xlf +++ b/src/Analyzers/VisualBasic/Analyzers/xlf/VisualBasicAnalyzersResources.cs.xlf @@ -27,6 +27,11 @@ Použít kontrolu „IsNot Nothing“ + + Use 'IsNot' expression + Use 'IsNot' expression + {locked: IsNot}This is a Visual Basic keyword and should not be localized or have its casing changed + Use 'Is Nothing' check Použít kontrolu „Is Nothing“ diff --git a/src/Analyzers/VisualBasic/Analyzers/xlf/VisualBasicAnalyzersResources.de.xlf b/src/Analyzers/VisualBasic/Analyzers/xlf/VisualBasicAnalyzersResources.de.xlf index 5d5f3d4259880..72423c50e92df 100644 --- a/src/Analyzers/VisualBasic/Analyzers/xlf/VisualBasicAnalyzersResources.de.xlf +++ b/src/Analyzers/VisualBasic/Analyzers/xlf/VisualBasicAnalyzersResources.de.xlf @@ -27,6 +27,11 @@ Prüfung "IsNot Nothing" verwenden + + Use 'IsNot' expression + Use 'IsNot' expression + {locked: IsNot}This is a Visual Basic keyword and should not be localized or have its casing changed + Use 'Is Nothing' check Prüfung "Is Nothing" verwenden diff --git a/src/Analyzers/VisualBasic/Analyzers/xlf/VisualBasicAnalyzersResources.es.xlf b/src/Analyzers/VisualBasic/Analyzers/xlf/VisualBasicAnalyzersResources.es.xlf index 71ade7791b7a8..feb7e5f67ddbb 100644 --- a/src/Analyzers/VisualBasic/Analyzers/xlf/VisualBasicAnalyzersResources.es.xlf +++ b/src/Analyzers/VisualBasic/Analyzers/xlf/VisualBasicAnalyzersResources.es.xlf @@ -27,6 +27,11 @@ Usar comprobación "IsNot Nothing" + + Use 'IsNot' expression + Use 'IsNot' expression + {locked: IsNot}This is a Visual Basic keyword and should not be localized or have its casing changed + Use 'Is Nothing' check Usar comprobación "Is Nothing" diff --git a/src/Analyzers/VisualBasic/Analyzers/xlf/VisualBasicAnalyzersResources.fr.xlf b/src/Analyzers/VisualBasic/Analyzers/xlf/VisualBasicAnalyzersResources.fr.xlf index 410a897af43ee..03c96c0d21b3b 100644 --- a/src/Analyzers/VisualBasic/Analyzers/xlf/VisualBasicAnalyzersResources.fr.xlf +++ b/src/Analyzers/VisualBasic/Analyzers/xlf/VisualBasicAnalyzersResources.fr.xlf @@ -27,6 +27,11 @@ Utiliser la vérification 'IsNot Nothing' + + Use 'IsNot' expression + Use 'IsNot' expression + {locked: IsNot}This is a Visual Basic keyword and should not be localized or have its casing changed + Use 'Is Nothing' check Utiliser la vérification 'Is Nothing' diff --git a/src/Analyzers/VisualBasic/Analyzers/xlf/VisualBasicAnalyzersResources.it.xlf b/src/Analyzers/VisualBasic/Analyzers/xlf/VisualBasicAnalyzersResources.it.xlf index b8e63c68853fa..faf223c24e4a3 100644 --- a/src/Analyzers/VisualBasic/Analyzers/xlf/VisualBasicAnalyzersResources.it.xlf +++ b/src/Analyzers/VisualBasic/Analyzers/xlf/VisualBasicAnalyzersResources.it.xlf @@ -27,6 +27,11 @@ Usa controllo 'IsNot Nothing' + + Use 'IsNot' expression + Use 'IsNot' expression + {locked: IsNot}This is a Visual Basic keyword and should not be localized or have its casing changed + Use 'Is Nothing' check Usa controllo 'Is Nothing' diff --git a/src/Analyzers/VisualBasic/Analyzers/xlf/VisualBasicAnalyzersResources.ja.xlf b/src/Analyzers/VisualBasic/Analyzers/xlf/VisualBasicAnalyzersResources.ja.xlf index 252fb40300914..936968aea0bf4 100644 --- a/src/Analyzers/VisualBasic/Analyzers/xlf/VisualBasicAnalyzersResources.ja.xlf +++ b/src/Analyzers/VisualBasic/Analyzers/xlf/VisualBasicAnalyzersResources.ja.xlf @@ -27,6 +27,11 @@ IsNot Nothing' チェックを使用します + + Use 'IsNot' expression + Use 'IsNot' expression + {locked: IsNot}This is a Visual Basic keyword and should not be localized or have its casing changed + Use 'Is Nothing' check Is Nothing' チェックを使用します diff --git a/src/Analyzers/VisualBasic/Analyzers/xlf/VisualBasicAnalyzersResources.ko.xlf b/src/Analyzers/VisualBasic/Analyzers/xlf/VisualBasicAnalyzersResources.ko.xlf index b15684a4db1d1..d41fe4bdd9886 100644 --- a/src/Analyzers/VisualBasic/Analyzers/xlf/VisualBasicAnalyzersResources.ko.xlf +++ b/src/Analyzers/VisualBasic/Analyzers/xlf/VisualBasicAnalyzersResources.ko.xlf @@ -27,6 +27,11 @@ IsNot Nothing' 검사 사용 + + Use 'IsNot' expression + Use 'IsNot' expression + {locked: IsNot}This is a Visual Basic keyword and should not be localized or have its casing changed + Use 'Is Nothing' check Is Nothing' 검사 사용 diff --git a/src/Analyzers/VisualBasic/Analyzers/xlf/VisualBasicAnalyzersResources.pl.xlf b/src/Analyzers/VisualBasic/Analyzers/xlf/VisualBasicAnalyzersResources.pl.xlf index a80f2d66b4ba8..4e66c11497cc7 100644 --- a/src/Analyzers/VisualBasic/Analyzers/xlf/VisualBasicAnalyzersResources.pl.xlf +++ b/src/Analyzers/VisualBasic/Analyzers/xlf/VisualBasicAnalyzersResources.pl.xlf @@ -27,6 +27,11 @@ Użyj sprawdzania „IsNot Nothing” + + Use 'IsNot' expression + Use 'IsNot' expression + {locked: IsNot}This is a Visual Basic keyword and should not be localized or have its casing changed + Use 'Is Nothing' check Użyj sprawdzania „Is Nothing” diff --git a/src/Analyzers/VisualBasic/Analyzers/xlf/VisualBasicAnalyzersResources.pt-BR.xlf b/src/Analyzers/VisualBasic/Analyzers/xlf/VisualBasicAnalyzersResources.pt-BR.xlf index 9c60dabda871c..c988addaa7311 100644 --- a/src/Analyzers/VisualBasic/Analyzers/xlf/VisualBasicAnalyzersResources.pt-BR.xlf +++ b/src/Analyzers/VisualBasic/Analyzers/xlf/VisualBasicAnalyzersResources.pt-BR.xlf @@ -27,6 +27,11 @@ Usar a verificação 'IsNot Nothing' + + Use 'IsNot' expression + Use 'IsNot' expression + {locked: IsNot}This is a Visual Basic keyword and should not be localized or have its casing changed + Use 'Is Nothing' check Usar a verificação 'Is Nothing' diff --git a/src/Analyzers/VisualBasic/Analyzers/xlf/VisualBasicAnalyzersResources.ru.xlf b/src/Analyzers/VisualBasic/Analyzers/xlf/VisualBasicAnalyzersResources.ru.xlf index c95dc451756b9..f87f106cbe3d7 100644 --- a/src/Analyzers/VisualBasic/Analyzers/xlf/VisualBasicAnalyzersResources.ru.xlf +++ b/src/Analyzers/VisualBasic/Analyzers/xlf/VisualBasicAnalyzersResources.ru.xlf @@ -27,6 +27,11 @@ Использовать флажок "IsNot Nothing" + + Use 'IsNot' expression + Use 'IsNot' expression + {locked: IsNot}This is a Visual Basic keyword and should not be localized or have its casing changed + Use 'Is Nothing' check Использовать флажок "Is Nothing" diff --git a/src/Analyzers/VisualBasic/Analyzers/xlf/VisualBasicAnalyzersResources.tr.xlf b/src/Analyzers/VisualBasic/Analyzers/xlf/VisualBasicAnalyzersResources.tr.xlf index 98ba3fae2b053..48f847b5f0a06 100644 --- a/src/Analyzers/VisualBasic/Analyzers/xlf/VisualBasicAnalyzersResources.tr.xlf +++ b/src/Analyzers/VisualBasic/Analyzers/xlf/VisualBasicAnalyzersResources.tr.xlf @@ -27,6 +27,11 @@ IsNot Nothing' denetimi kullan + + Use 'IsNot' expression + Use 'IsNot' expression + {locked: IsNot}This is a Visual Basic keyword and should not be localized or have its casing changed + Use 'Is Nothing' check Is Nothing' denetimi kullan diff --git a/src/Analyzers/VisualBasic/Analyzers/xlf/VisualBasicAnalyzersResources.zh-Hans.xlf b/src/Analyzers/VisualBasic/Analyzers/xlf/VisualBasicAnalyzersResources.zh-Hans.xlf index ddbdcbd5c036e..c8922b280c56a 100644 --- a/src/Analyzers/VisualBasic/Analyzers/xlf/VisualBasicAnalyzersResources.zh-Hans.xlf +++ b/src/Analyzers/VisualBasic/Analyzers/xlf/VisualBasicAnalyzersResources.zh-Hans.xlf @@ -27,6 +27,11 @@ 使用 "IsNot Nothing" 检查 + + Use 'IsNot' expression + Use 'IsNot' expression + {locked: IsNot}This is a Visual Basic keyword and should not be localized or have its casing changed + Use 'Is Nothing' check 使用 "Is Nothing" 检查 diff --git a/src/Analyzers/VisualBasic/Analyzers/xlf/VisualBasicAnalyzersResources.zh-Hant.xlf b/src/Analyzers/VisualBasic/Analyzers/xlf/VisualBasicAnalyzersResources.zh-Hant.xlf index 6acc7b2551ed0..97d79958c5d19 100644 --- a/src/Analyzers/VisualBasic/Analyzers/xlf/VisualBasicAnalyzersResources.zh-Hant.xlf +++ b/src/Analyzers/VisualBasic/Analyzers/xlf/VisualBasicAnalyzersResources.zh-Hant.xlf @@ -27,6 +27,11 @@ 使用 'IsNot Nothing' 檢查 + + Use 'IsNot' expression + Use 'IsNot' expression + {locked: IsNot}This is a Visual Basic keyword and should not be localized or have its casing changed + Use 'Is Nothing' check 使用 'Is Nothing' 檢查 diff --git a/src/Analyzers/VisualBasic/CodeFixes/UseIsNotExpression/VisualBasicUseIsNotExpressionCodeFixProvider.vb b/src/Analyzers/VisualBasic/CodeFixes/UseIsNotExpression/VisualBasicUseIsNotExpressionCodeFixProvider.vb new file mode 100644 index 0000000000000..d621742e9980c --- /dev/null +++ b/src/Analyzers/VisualBasic/CodeFixes/UseIsNotExpression/VisualBasicUseIsNotExpressionCodeFixProvider.vb @@ -0,0 +1,90 @@ +' 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. + +Imports System.Collections.Immutable +Imports System.Composition +Imports System.Diagnostics.CodeAnalysis +Imports System.Threading +Imports Microsoft.CodeAnalysis.CodeActions +Imports Microsoft.CodeAnalysis.CodeFixes +Imports Microsoft.CodeAnalysis.Diagnostics +Imports Microsoft.CodeAnalysis.Editing +Imports Microsoft.CodeAnalysis.UseIsNullCheck +Imports Microsoft.CodeAnalysis.VisualBasic.Syntax + +Namespace Microsoft.CodeAnalysis.VisualBasic.UseIsNotExpression + + Friend Class VisualBasicUseIsNotExpressionCodeFixProvider + Inherits SyntaxEditorBasedCodeFixProvider + + + + Public Sub New() + End Sub + + Public Overrides ReadOnly Property FixableDiagnosticIds As ImmutableArray(Of String) = ImmutableArray.Create(IDEDiagnosticIds.UseIsNotExpressionDiagnosticId) + + Friend Overrides ReadOnly Property CodeFixCategory As CodeFixCategory = CodeFixCategory.CodeStyle + + Public Overrides Function RegisterCodeFixesAsync(context As CodeFixContext) As Task + context.RegisterCodeFix(New MyCodeAction( + Function(c) FixAsync(context.Document, context.Diagnostics.First(), c)), + context.Diagnostics) + Return Task.CompletedTask + End Function + + Protected Overrides Function FixAllAsync( + document As Document, + diagnostics As ImmutableArray(Of Diagnostic), + editor As SyntaxEditor, + cancellationToken As CancellationToken) As Task + + For Each diagnostic In diagnostics + cancellationToken.ThrowIfCancellationRequested() + ProcessDiagnostic(editor, diagnostic, cancellationToken) + Next + + Return Task.CompletedTask + End Function + + Private Shared Sub ProcessDiagnostic( + editor As SyntaxEditor, + diagnostic As Diagnostic, + cancellationToken As CancellationToken) + Dim notExpressionLocation = diagnostic.AdditionalLocations(0) + + Dim notExpression = DirectCast(notExpressionLocation.FindNode(getInnermostNodeForTie:=True, cancellationToken), UnaryExpressionSyntax) + Dim operand = notExpression.Operand + + Dim replacement As ExpressionSyntax + If operand.IsKind(SyntaxKind.IsExpression) Then + Dim isExpression = DirectCast(operand, BinaryExpressionSyntax) + replacement = SyntaxFactory.IsNotExpression( + isExpression.Left, + SyntaxFactory.Token(SyntaxKind.IsNotKeyword).WithTriviaFrom(isExpression.OperatorToken), + isExpression.Right) + Else + Contract.ThrowIfFalse(operand.IsKind(SyntaxKind.TypeOfIsExpression)) + Dim typeOfIsExpression = DirectCast(operand, TypeOfExpressionSyntax) + replacement = SyntaxFactory.TypeOfIsNotExpression( + typeOfIsExpression.TypeOfKeyword, + typeOfIsExpression.Expression, + SyntaxFactory.Token(SyntaxKind.IsNotKeyword).WithTriviaFrom(typeOfIsExpression.OperatorToken), + typeOfIsExpression.Type) + End If + + editor.ReplaceNode( + notExpression, + replacement.WithPrependedLeadingTrivia(notExpression.GetLeadingTrivia())) + End Sub + + Private Class MyCodeAction + Inherits CustomCodeActions.DocumentChangeAction + + Public Sub New(createChangedDocument As Func(Of CancellationToken, Task(Of Document))) + MyBase.New(VisualBasicAnalyzersResources.Use_IsNot_expression, createChangedDocument, VisualBasicAnalyzersResources.Use_IsNot_expression) + End Sub + End Class + End Class +End Namespace diff --git a/src/Analyzers/VisualBasic/CodeFixes/VisualBasicCodeFixes.projitems b/src/Analyzers/VisualBasic/CodeFixes/VisualBasicCodeFixes.projitems index 2e606b36c06fe..0c1cc8c7e560d 100644 --- a/src/Analyzers/VisualBasic/CodeFixes/VisualBasicCodeFixes.projitems +++ b/src/Analyzers/VisualBasic/CodeFixes/VisualBasicCodeFixes.projitems @@ -34,6 +34,7 @@ + diff --git a/src/Analyzers/VisualBasic/Tests/UseIsNotExpression/UseIsNotExpressionTests.vb b/src/Analyzers/VisualBasic/Tests/UseIsNotExpression/UseIsNotExpressionTests.vb new file mode 100644 index 0000000000000..775076e84f7ff --- /dev/null +++ b/src/Analyzers/VisualBasic/Tests/UseIsNotExpression/UseIsNotExpressionTests.vb @@ -0,0 +1,66 @@ +' 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. + +Imports VerifyVB = Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions.VisualBasicCodeFixVerifier(Of + Microsoft.CodeAnalysis.VisualBasic.UseIsNotExpression.VisualBasicUseIsNotExpressionDiagnosticAnalyzer, + Microsoft.CodeAnalysis.VisualBasic.UseIsNotExpression.VisualBasicUseIsNotExpressionCodeFixProvider) + +Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.UseIsNotExpression + Partial Public Class UseIsNotExpressionTests + + + Public Async Function TestIsExpression() As Task + Await New VerifyVB.Test With { + .TestCode = " +class C + sub M(o as object) + if not o [|is|] nothing + end if + end sub +end class", + .FixedCode = " +class C + sub M(o as object) + if o IsNot nothing + end if + end sub +end class" + }.RunAsync() + End Function + + + Public Async Function TestTypeOfIsExpression() As Task + Await New VerifyVB.Test With { + .TestCode = " +class C + sub M(o as object) + if not typeof o [|is|] string + end if + end sub +end class", + .FixedCode = " +class C + sub M(o as object) + if typeof o IsNot string + end if + end sub +end class" + }.RunAsync() + End Function + + + Public Async Function TestVB12() As Task + Await New VerifyVB.Test With { + .TestCode = " +class C + sub M(o as object) + if not o is nothing + end if + end sub +end class", + .LanguageVersion = LanguageVersion.VisualBasic12 + }.RunAsync() + End Function + End Class +End Namespace diff --git a/src/Analyzers/VisualBasic/Tests/VisualBasicAnalyzers.UnitTests.projitems b/src/Analyzers/VisualBasic/Tests/VisualBasicAnalyzers.UnitTests.projitems index a0f61fcf3853f..d4deea6bed69f 100644 --- a/src/Analyzers/VisualBasic/Tests/VisualBasicAnalyzers.UnitTests.projitems +++ b/src/Analyzers/VisualBasic/Tests/VisualBasicAnalyzers.UnitTests.projitems @@ -44,6 +44,7 @@ + diff --git a/src/EditorFeatures/Test/Diagnostics/IDEDiagnosticIDConfigurationTests.cs b/src/EditorFeatures/Test/Diagnostics/IDEDiagnosticIDConfigurationTests.cs index 17476b38ee1c5..8195046306ba5 100644 --- a/src/EditorFeatures/Test/Diagnostics/IDEDiagnosticIDConfigurationTests.cs +++ b/src/EditorFeatures/Test/Diagnostics/IDEDiagnosticIDConfigurationTests.cs @@ -394,6 +394,9 @@ public void CSharp_VerifyIDEDiagnosticSeveritiesAreConfigurable() # IDE0082 dotnet_diagnostic.IDE0082.severity = %value% +# IDE0083 +csharp_style_prefer_not_pattern = true:suggestion + # IDE1005 csharp_style_conditional_delegate_call = true:suggestion @@ -549,6 +552,9 @@ public void VisualBasic_VerifyIDEDiagnosticSeveritiesAreConfigurable() # IDE0082 dotnet_diagnostic.IDE0082.severity = %value% +# IDE0084 +visual_basic_style_prefer_isnot_expression = true:suggestion + # IDE1006 dotnet_diagnostic.IDE1006.severity = %value% @@ -933,6 +939,9 @@ No editorconfig based code style option # IDE0082 No editorconfig based code style option +# IDE0083, PreferNotPattern +csharp_style_prefer_not_pattern = true:suggestion + # IDE1005, PreferConditionalDelegateCall csharp_style_conditional_delegate_call = true:suggestion @@ -1121,6 +1130,9 @@ No editorconfig based code style option # IDE0082 No editorconfig based code style option +# IDE0084, PreferIsNotExpression +visual_basic_style_prefer_isnot_expression = true:suggestion + # IDE1006 No editorconfig based code style option diff --git a/src/Test/Utilities/Portable/Traits/Traits.cs b/src/Test/Utilities/Portable/Traits/Traits.cs index cd2088df63f7f..6ce3dd5398692 100644 --- a/src/Test/Utilities/Portable/Traits/Traits.cs +++ b/src/Test/Utilities/Portable/Traits/Traits.cs @@ -181,9 +181,11 @@ public static class Features public const string CodeActionsUseIndexOperator = "CodeActions.UseIndexOperator"; public const string CodeActionsUseInferredMemberName = "CodeActions.UseInferredMemberName"; public const string CodeActionsUseInterpolatedVerbatimString = "CodeActions.UseInterpolatedVerbatimString"; + public const string CodeActionsUseIsNotExpression = "CodeActions.UseIsNotExpression"; public const string CodeActionsUseIsNullCheck = "CodeActions.UseIsNullCheck"; public const string CodeActionsUseLocalFunction = "CodeActions.UseLocalFunction"; public const string CodeActionsUseNamedArguments = "CodeActions.UseNamedArguments"; + public const string CodeActionsUseNotPattern = "CodeActions.UseNotPattern"; public const string CodeActionsUsePatternCombinators = "CodeActions.UsePatternCombinators"; public const string CodeActionsUseNullPropagation = "CodeActions.UseNullPropagation"; public const string CodeActionsUseObjectInitializer = "CodeActions.UseObjectInitializer"; diff --git a/src/VisualStudio/CSharp/Impl/CSharpVSResources.resx b/src/VisualStudio/CSharp/Impl/CSharpVSResources.resx index 5fab8a226ac68..d0a690cf19b18 100644 --- a/src/VisualStudio/CSharp/Impl/CSharpVSResources.resx +++ b/src/VisualStudio/CSharp/Impl/CSharpVSResources.resx @@ -611,4 +611,10 @@ Format document + + Pattern matching preferences: + + + Prefer pattern matching over mixed type check + \ No newline at end of file diff --git a/src/VisualStudio/CSharp/Impl/Options/Formatting/StyleViewModel.cs b/src/VisualStudio/CSharp/Impl/Options/Formatting/StyleViewModel.cs index 245c8e320faa2..e3126ad83364f 100644 --- a/src/VisualStudio/CSharp/Impl/Options/Formatting/StyleViewModel.cs +++ b/src/VisualStudio/CSharp/Impl/Options/Formatting/StyleViewModel.cs @@ -405,6 +405,30 @@ void M2() //] }} }} +"; + + private static readonly string s_preferPatternMatchingOverMixedTypeCheck = $@" +class C +{{ + void M1() + {{ +//[ + // {ServicesVSResources.Prefer_colon} + if (o is not string s) + {{ + }} +//] + }} + void M2() + {{ +//[ + // {ServicesVSResources.Over_colon} + if (!(o is string s)) + {{ + }} +//] + }} +}} "; private static readonly string s_preferConditionalExpressionOverIfWithAssignments = $@" @@ -1652,6 +1676,7 @@ internal StyleViewModel(OptionStore optionStore, IServiceProvider serviceProvide var modifierGroupTitle = ServicesVSResources.Modifier_preferences_colon; var codeBlockPreferencesGroupTitle = ServicesVSResources.Code_block_preferences_colon; var expressionPreferencesGroupTitle = ServicesVSResources.Expression_preferences_colon; + var patternMatchingPreferencesGroupTitle = CSharpVSResources.Pattern_matching_preferences_colon; var variablePreferencesGroupTitle = ServicesVSResources.Variable_preferences_colon; var parameterPreferencesGroupTitle = ServicesVSResources.Parameter_preferences_colon; @@ -1705,9 +1730,6 @@ internal StyleViewModel(OptionStore optionStore, IServiceProvider serviceProvide CodeStyleItems.Add(new BooleanCodeStyleOptionViewModel(CodeStyleOptions2.PreferCollectionInitializer, ServicesVSResources.Prefer_collection_initializer, s_preferCollectionInitializer, s_preferCollectionInitializer, this, optionStore, expressionPreferencesGroupTitle)); CodeStyleItems.Add(new BooleanCodeStyleOptionViewModel(CodeStyleOptions2.PreferSimplifiedBooleanExpressions, ServicesVSResources.Prefer_simplified_boolean_expressions, s_preferSimplifiedConditionalExpression, s_preferSimplifiedConditionalExpression, this, optionStore, expressionPreferencesGroupTitle)); CodeStyleItems.Add(new BooleanCodeStyleOptionViewModel(CSharpCodeStyleOptions.PreferSwitchExpression, CSharpVSResources.Prefer_switch_expression, s_preferSwitchExpression, s_preferSwitchExpression, this, optionStore, expressionPreferencesGroupTitle)); - CodeStyleItems.Add(new BooleanCodeStyleOptionViewModel(CSharpCodeStyleOptions.PreferPatternMatching, CSharpVSResources.Prefer_pattern_matching, s_preferPatternMatching, s_preferPatternMatching, this, optionStore, expressionPreferencesGroupTitle)); - CodeStyleItems.Add(new BooleanCodeStyleOptionViewModel(CSharpCodeStyleOptions.PreferPatternMatchingOverIsWithCastCheck, CSharpVSResources.Prefer_pattern_matching_over_is_with_cast_check, s_preferPatternMatchingOverIsWithCastCheck, s_preferPatternMatchingOverIsWithCastCheck, this, optionStore, expressionPreferencesGroupTitle)); - CodeStyleItems.Add(new BooleanCodeStyleOptionViewModel(CSharpCodeStyleOptions.PreferPatternMatchingOverAsWithNullCheck, CSharpVSResources.Prefer_pattern_matching_over_as_with_null_check, s_preferPatternMatchingOverAsWithNullCheck, s_preferPatternMatchingOverAsWithNullCheck, this, optionStore, expressionPreferencesGroupTitle)); CodeStyleItems.Add(new BooleanCodeStyleOptionViewModel(CodeStyleOptions2.PreferConditionalExpressionOverAssignment, ServicesVSResources.Prefer_conditional_expression_over_if_with_assignments, s_preferConditionalExpressionOverIfWithAssignments, s_preferConditionalExpressionOverIfWithAssignments, this, optionStore, expressionPreferencesGroupTitle)); CodeStyleItems.Add(new BooleanCodeStyleOptionViewModel(CodeStyleOptions2.PreferConditionalExpressionOverReturn, ServicesVSResources.Prefer_conditional_expression_over_if_with_returns, s_preferConditionalExpressionOverIfWithReturns, s_preferConditionalExpressionOverIfWithReturns, this, optionStore, expressionPreferencesGroupTitle)); CodeStyleItems.Add(new BooleanCodeStyleOptionViewModel(CodeStyleOptions2.PreferExplicitTupleNames, ServicesVSResources.Prefer_explicit_tuple_name, s_preferExplicitTupleName, s_preferExplicitTupleName, this, optionStore, expressionPreferencesGroupTitle)); @@ -1720,6 +1742,12 @@ internal StyleViewModel(OptionStore optionStore, IServiceProvider serviceProvide CodeStyleItems.Add(new BooleanCodeStyleOptionViewModel(CSharpCodeStyleOptions.PreferIndexOperator, ServicesVSResources.Prefer_index_operator, s_preferIndexOperator, s_preferIndexOperator, this, optionStore, expressionPreferencesGroupTitle)); CodeStyleItems.Add(new BooleanCodeStyleOptionViewModel(CSharpCodeStyleOptions.PreferRangeOperator, ServicesVSResources.Prefer_range_operator, s_preferRangeOperator, s_preferRangeOperator, this, optionStore, expressionPreferencesGroupTitle)); + // Pattern matching + CodeStyleItems.Add(new BooleanCodeStyleOptionViewModel(CSharpCodeStyleOptions.PreferPatternMatching, CSharpVSResources.Prefer_pattern_matching, s_preferPatternMatching, s_preferPatternMatching, this, optionStore, patternMatchingPreferencesGroupTitle)); + CodeStyleItems.Add(new BooleanCodeStyleOptionViewModel(CSharpCodeStyleOptions.PreferPatternMatchingOverIsWithCastCheck, CSharpVSResources.Prefer_pattern_matching_over_is_with_cast_check, s_preferPatternMatchingOverIsWithCastCheck, s_preferPatternMatchingOverIsWithCastCheck, this, optionStore, patternMatchingPreferencesGroupTitle)); + CodeStyleItems.Add(new BooleanCodeStyleOptionViewModel(CSharpCodeStyleOptions.PreferPatternMatchingOverAsWithNullCheck, CSharpVSResources.Prefer_pattern_matching_over_as_with_null_check, s_preferPatternMatchingOverAsWithNullCheck, s_preferPatternMatchingOverAsWithNullCheck, this, optionStore, patternMatchingPreferencesGroupTitle)); + CodeStyleItems.Add(new BooleanCodeStyleOptionViewModel(CSharpCodeStyleOptions.PreferNotPattern, CSharpVSResources.Prefer_pattern_matching_over_mixed_type_check, s_preferPatternMatchingOverMixedTypeCheck, s_preferPatternMatchingOverMixedTypeCheck, this, optionStore, patternMatchingPreferencesGroupTitle)); + AddExpressionBodyOptions(optionStore, expressionPreferencesGroupTitle); AddUnusedValueOptions(optionStore, expressionPreferencesGroupTitle); diff --git a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.cs.xlf b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.cs.xlf index 67e69898e107f..00869bf2c806c 100644 --- a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.cs.xlf +++ b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.cs.xlf @@ -67,6 +67,11 @@ Vně namespace 'namespace' is a C# keyword and should not be localized + + Pattern matching preferences: + Pattern matching preferences: + + Perform additional code cleanup during formatting Při formátování provést dodatečné vyčištění kódu @@ -82,6 +87,11 @@ Prefer pattern matching + + Prefer pattern matching over mixed type check + Prefer pattern matching over mixed type check + + Prefer switch expression Preferovat výraz switch diff --git a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.de.xlf b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.de.xlf index 89d2842546e57..f9d2eedd8e959 100644 --- a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.de.xlf +++ b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.de.xlf @@ -67,6 +67,11 @@ Außerhalb des Namespaces 'namespace' is a C# keyword and should not be localized + + Pattern matching preferences: + Pattern matching preferences: + + Perform additional code cleanup during formatting Zusätzliche Codebereinigung während der Formatierung durchführen @@ -82,6 +87,11 @@ Prefer pattern matching + + Prefer pattern matching over mixed type check + Prefer pattern matching over mixed type check + + Prefer switch expression Switch-Ausdruck bevorzugen diff --git a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.es.xlf b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.es.xlf index 109aea406bfbc..516bf813b6312 100644 --- a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.es.xlf +++ b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.es.xlf @@ -67,6 +67,11 @@ namespace exterior 'namespace' is a C# keyword and should not be localized + + Pattern matching preferences: + Pattern matching preferences: + + Perform additional code cleanup during formatting Realizar limpieza de código adicional durante la aplicación de formato @@ -82,6 +87,11 @@ Prefer pattern matching + + Prefer pattern matching over mixed type check + Prefer pattern matching over mixed type check + + Prefer switch expression Preferir expresión switch diff --git a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.fr.xlf b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.fr.xlf index c2d6e48733a43..128730d4fbf0e 100644 --- a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.fr.xlf +++ b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.fr.xlf @@ -67,6 +67,11 @@ Hors du namespace 'namespace' is a C# keyword and should not be localized + + Pattern matching preferences: + Pattern matching preferences: + + Perform additional code cleanup during formatting Effectuer un nettoyage supplémentaire du code pendant la mise en forme @@ -82,6 +87,11 @@ Prefer pattern matching + + Prefer pattern matching over mixed type check + Prefer pattern matching over mixed type check + + Prefer switch expression Préférer l'expression switch diff --git a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.it.xlf b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.it.xlf index d32e913edcc55..6eb1e5312b801 100644 --- a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.it.xlf +++ b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.it.xlf @@ -67,6 +67,11 @@ All'esterno di namespace 'namespace' is a C# keyword and should not be localized + + Pattern matching preferences: + Pattern matching preferences: + + Perform additional code cleanup during formatting Esegui la pulizia del codice aggiuntiva durante la formattazione @@ -82,6 +87,11 @@ Prefer pattern matching + + Prefer pattern matching over mixed type check + Prefer pattern matching over mixed type check + + Prefer switch expression Preferisci espressione switch diff --git a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.ja.xlf b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.ja.xlf index 4e4c2cd9d881a..da38407f821ae 100644 --- a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.ja.xlf +++ b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.ja.xlf @@ -67,6 +67,11 @@ namespace 外 'namespace' is a C# keyword and should not be localized + + Pattern matching preferences: + Pattern matching preferences: + + Perform additional code cleanup during formatting 書式設定中に追加のコード クリーンアップを実行 @@ -82,6 +87,11 @@ Prefer pattern matching + + Prefer pattern matching over mixed type check + Prefer pattern matching over mixed type check + + Prefer switch expression switch 式を優先する diff --git a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.ko.xlf b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.ko.xlf index e3ff00ac0e26d..0a77342902c10 100644 --- a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.ko.xlf +++ b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.ko.xlf @@ -67,6 +67,11 @@ 외부 namespace 'namespace' is a C# keyword and should not be localized + + Pattern matching preferences: + Pattern matching preferences: + + Perform additional code cleanup during formatting 서식을 지정하는 동안 추가 코드 정리 수행 @@ -82,6 +87,11 @@ Prefer pattern matching + + Prefer pattern matching over mixed type check + Prefer pattern matching over mixed type check + + Prefer switch expression switch 식 선호 diff --git a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.pl.xlf b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.pl.xlf index ff45f53f26303..faaa21ec1ab8d 100644 --- a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.pl.xlf +++ b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.pl.xlf @@ -67,6 +67,11 @@ Poza elementem namespace 'namespace' is a C# keyword and should not be localized + + Pattern matching preferences: + Pattern matching preferences: + + Perform additional code cleanup during formatting Wykonaj dodatkowe oczyszczanie kodu podczas formatowania @@ -82,6 +87,11 @@ Prefer pattern matching + + Prefer pattern matching over mixed type check + Prefer pattern matching over mixed type check + + Prefer switch expression Preferuj wyrażenie switch diff --git a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.pt-BR.xlf b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.pt-BR.xlf index eeabbfb189f8e..df1cda090490c 100644 --- a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.pt-BR.xlf +++ b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.pt-BR.xlf @@ -67,6 +67,11 @@ Namespace externo 'namespace' is a C# keyword and should not be localized + + Pattern matching preferences: + Pattern matching preferences: + + Perform additional code cleanup during formatting Executar limpeza de código adicional durante a formatação @@ -82,6 +87,11 @@ Prefer pattern matching + + Prefer pattern matching over mixed type check + Prefer pattern matching over mixed type check + + Prefer switch expression Preferir a expressão switch diff --git a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.ru.xlf b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.ru.xlf index 6dd7b0cbb55bb..eda9c922b4837 100644 --- a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.ru.xlf +++ b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.ru.xlf @@ -67,6 +67,11 @@ Вне пространства имен 'namespace' is a C# keyword and should not be localized + + Pattern matching preferences: + Pattern matching preferences: + + Perform additional code cleanup during formatting Выполнять при форматировании дополнительную очистку кода @@ -82,6 +87,11 @@ Prefer pattern matching + + Prefer pattern matching over mixed type check + Prefer pattern matching over mixed type check + + Prefer switch expression Предпочитать выражение switch diff --git a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.tr.xlf b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.tr.xlf index 4b9a7f7432db6..3f8184931c9e4 100644 --- a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.tr.xlf +++ b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.tr.xlf @@ -67,6 +67,11 @@ namespace dışında 'namespace' is a C# keyword and should not be localized + + Pattern matching preferences: + Pattern matching preferences: + + Perform additional code cleanup during formatting Biçimlendirme sırasında ek kod temizleme gerçekleştir @@ -82,6 +87,11 @@ Prefer pattern matching + + Prefer pattern matching over mixed type check + Prefer pattern matching over mixed type check + + Prefer switch expression Switch ifadesini tercih et diff --git a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.zh-Hans.xlf b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.zh-Hans.xlf index 1a7b61cf94032..e1914abdfabba 100644 --- a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.zh-Hans.xlf +++ b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.zh-Hans.xlf @@ -67,6 +67,11 @@ 命名空间外 'namespace' is a C# keyword and should not be localized + + Pattern matching preferences: + Pattern matching preferences: + + Perform additional code cleanup during formatting 在格式设置期间执行其他代码清理 @@ -82,6 +87,11 @@ Prefer pattern matching + + Prefer pattern matching over mixed type check + Prefer pattern matching over mixed type check + + Prefer switch expression 首选 switch 表达式 diff --git a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.zh-Hant.xlf b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.zh-Hant.xlf index ac864b60a162b..ab2adf61e322b 100644 --- a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.zh-Hant.xlf +++ b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.zh-Hant.xlf @@ -67,6 +67,11 @@ 位於 namespace 外 'namespace' is a C# keyword and should not be localized + + Pattern matching preferences: + Pattern matching preferences: + + Perform additional code cleanup during formatting 在格式化期間執行額外程式碼清除 @@ -82,6 +87,11 @@ Prefer pattern matching + + Prefer pattern matching over mixed type check + Prefer pattern matching over mixed type check + + Prefer switch expression 建議使用 switch 運算式 diff --git a/src/VisualStudio/Core/Test/Options/BasicEditorConfigGeneratorTests.vb b/src/VisualStudio/Core/Test/Options/BasicEditorConfigGeneratorTests.vb index 6405bb1c8daaa..5092677243188 100644 --- a/src/VisualStudio/Core/Test/Options/BasicEditorConfigGeneratorTests.vb +++ b/src/VisualStudio/Core/Test/Options/BasicEditorConfigGeneratorTests.vb @@ -93,6 +93,7 @@ dotnet_remove_unnecessary_suppression_exclusions = none visual_basic_preferred_modifier_order = partial,default,private,protected,public,friend,notoverridable,overridable,mustoverride,overloads,overrides,mustinherit,notinheritable,static,shared,shadows,readonly,writeonly,dim,const,withevents,widening,narrowing,custom,async,iterator:silent # Expression-level preferences +visual_basic_style_prefer_isnot_expression = true:suggestion visual_basic_style_unused_value_assignment_preference = unused_local_variable:suggestion visual_basic_style_unused_value_expression_statement_preference = unused_local_variable:silent @@ -224,6 +225,7 @@ dotnet_remove_unnecessary_suppression_exclusions = none visual_basic_preferred_modifier_order = partial,default,private,protected,public,friend,notoverridable,overridable,mustoverride,overloads,overrides,mustinherit,notinheritable,static,shared,shadows,readonly,writeonly,dim,const,withevents,widening,narrowing,custom,async,iterator:silent # Expression-level preferences +visual_basic_style_prefer_isnot_expression = true:suggestion visual_basic_style_unused_value_assignment_preference = unused_local_variable:suggestion visual_basic_style_unused_value_expression_statement_preference = unused_local_variable:silent diff --git a/src/VisualStudio/Core/Test/Options/CSharpEditorConfigGeneratorTests.vb b/src/VisualStudio/Core/Test/Options/CSharpEditorConfigGeneratorTests.vb index 6f2458d0ddd3a..c380fc6f31c8d 100644 --- a/src/VisualStudio/Core/Test/Options/CSharpEditorConfigGeneratorTests.vb +++ b/src/VisualStudio/Core/Test/Options/CSharpEditorConfigGeneratorTests.vb @@ -106,6 +106,7 @@ csharp_style_expression_bodied_properties = true:silent # Pattern matching preferences csharp_style_pattern_matching_over_as_with_null_check = true:suggestion csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion +csharp_style_prefer_not_pattern = true:suggestion csharp_style_prefer_pattern_matching = true:silent csharp_style_prefer_switch_expression = true:suggestion @@ -323,6 +324,7 @@ csharp_style_expression_bodied_properties = true:silent # Pattern matching preferences csharp_style_pattern_matching_over_as_with_null_check = true:suggestion csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion +csharp_style_prefer_not_pattern = true:suggestion csharp_style_prefer_pattern_matching = true:silent csharp_style_prefer_switch_expression = true:suggestion diff --git a/src/VisualStudio/VisualBasic/Impl/BasicVSResources.resx b/src/VisualStudio/VisualBasic/Impl/BasicVSResources.resx index ba8cfa476c5cd..07c4b5f860abd 100644 --- a/src/VisualStudio/VisualBasic/Impl/BasicVSResources.resx +++ b/src/VisualStudio/VisualBasic/Impl/BasicVSResources.resx @@ -301,4 +301,7 @@ Show remarks in Quick Info + + Prefer 'IsNot' expression + \ No newline at end of file diff --git a/src/VisualStudio/VisualBasic/Impl/Options/StyleViewModel.vb b/src/VisualStudio/VisualBasic/Impl/Options/StyleViewModel.vb index 68f51019db9c3..f0330f5db9f90 100644 --- a/src/VisualStudio/VisualBasic/Impl/Options/StyleViewModel.vb +++ b/src/VisualStudio/VisualBasic/Impl/Options/StyleViewModel.vb @@ -447,6 +447,24 @@ Class Customer End Sub End Class" + Private Shared ReadOnly s_preferIsNotExpression As String = $" +Imports System + +Class Customer + Sub M1(value as object) +//[ + ' {ServicesVSResources.Prefer_colon} + Dim isSomething = value IsNot Nothing +//] + End Sub + Sub M2(value as object) +//[ + ' {ServicesVSResources.Over_colon} + Dim isSomething = Not value Is Nothing +//] + End Sub +End Class" + #Region "arithmetic binary parentheses" Private Shared ReadOnly s_arithmeticBinaryAlwaysForClarity As String = $" @@ -725,6 +743,7 @@ End Class Me.CodeStyleItems.Add(New BooleanCodeStyleOptionViewModel(CodeStyleOptions2.PreferConditionalExpressionOverAssignment, ServicesVSResources.Prefer_conditional_expression_over_if_with_assignments, s_preferConditionalExpressionOverIfWithAssignments, s_preferConditionalExpressionOverIfWithAssignments, Me, optionStore, expressionPreferencesGroupTitle)) Me.CodeStyleItems.Add(New BooleanCodeStyleOptionViewModel(CodeStyleOptions2.PreferConditionalExpressionOverReturn, ServicesVSResources.Prefer_conditional_expression_over_if_with_returns, s_preferConditionalExpressionOverIfWithReturns, s_preferConditionalExpressionOverIfWithReturns, Me, optionStore, expressionPreferencesGroupTitle)) Me.CodeStyleItems.Add(New BooleanCodeStyleOptionViewModel(CodeStyleOptions2.PreferCompoundAssignment, ServicesVSResources.Prefer_compound_assignments, s_preferCompoundAssignments, s_preferCompoundAssignments, Me, optionStore, expressionPreferencesGroupTitle)) + Me.CodeStyleItems.Add(New BooleanCodeStyleOptionViewModel(VisualBasicCodeStyleOptions.PreferIsNotExpression, BasicVSResources.Prefer_IsNot_expression, s_preferIsNotExpression, s_preferIsNotExpression, Me, optionStore, expressionPreferencesGroupTitle)) AddUnusedValueOptions(optionStore, expressionPreferencesGroupTitle) diff --git a/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.cs.xlf b/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.cs.xlf index daf8239984e94..1f6129aed751e 100644 --- a/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.cs.xlf +++ b/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.cs.xlf @@ -32,6 +32,11 @@ Nikdy + + Prefer 'IsNot' expression + Prefer 'IsNot' expression + + Prefer 'Is Nothing' for reference equality checks U kontrol rovnosti odkazů dávat přednost možnosti Is Nothing diff --git a/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.de.xlf b/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.de.xlf index 26f76ff16b43c..667690d4a645b 100644 --- a/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.de.xlf +++ b/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.de.xlf @@ -32,6 +32,11 @@ Nie + + Prefer 'IsNot' expression + Prefer 'IsNot' expression + + Prefer 'Is Nothing' for reference equality checks "Is Nothing" für Verweisübereinstimmungsprüfungen vorziehen diff --git a/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.es.xlf b/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.es.xlf index 1b91c2cdd600e..acc14b99f1c4d 100644 --- a/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.es.xlf +++ b/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.es.xlf @@ -32,6 +32,11 @@ Nunca + + Prefer 'IsNot' expression + Prefer 'IsNot' expression + + Prefer 'Is Nothing' for reference equality checks Preferir “Is Nothing” para comprobaciones de igualdad de referencias diff --git a/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.fr.xlf b/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.fr.xlf index ab10dfffc9652..ed7fab4c4784d 100644 --- a/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.fr.xlf +++ b/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.fr.xlf @@ -32,6 +32,11 @@ Jamais + + Prefer 'IsNot' expression + Prefer 'IsNot' expression + + Prefer 'Is Nothing' for reference equality checks Préférer 'Is Nothing' pour les vérifications d'égalité de référence diff --git a/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.it.xlf b/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.it.xlf index 4f29a7cee36e5..21d0ba8162f50 100644 --- a/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.it.xlf +++ b/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.it.xlf @@ -32,6 +32,11 @@ Mai + + Prefer 'IsNot' expression + Prefer 'IsNot' expression + + Prefer 'Is Nothing' for reference equality checks Preferisci 'Is Nothing' per i controlli di uguaglianza dei riferimenti diff --git a/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.ja.xlf b/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.ja.xlf index bddb8cb962660..108ec1506bf87 100644 --- a/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.ja.xlf +++ b/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.ja.xlf @@ -32,6 +32,11 @@ 行わない + + Prefer 'IsNot' expression + Prefer 'IsNot' expression + + Prefer 'Is Nothing' for reference equality checks 参照の等値性のチェックには 'Is Nothing' を優先する diff --git a/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.ko.xlf b/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.ko.xlf index 9652fac5fbbe3..020cc0f50348a 100644 --- a/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.ko.xlf +++ b/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.ko.xlf @@ -32,6 +32,11 @@ 안 함 + + Prefer 'IsNot' expression + Prefer 'IsNot' expression + + Prefer 'Is Nothing' for reference equality checks 참조 같음 검사에 대해 'Is Nothing' 선호 diff --git a/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.pl.xlf b/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.pl.xlf index 803792414aa31..d88f61cc0c3e4 100644 --- a/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.pl.xlf +++ b/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.pl.xlf @@ -32,6 +32,11 @@ Nigdy + + Prefer 'IsNot' expression + Prefer 'IsNot' expression + + Prefer 'Is Nothing' for reference equality checks Preferuj wyrażenie „Is Nothing” w przypadku sprawdzeń odwołań pod kątem równości diff --git a/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.pt-BR.xlf b/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.pt-BR.xlf index b2eb675afbc82..5f9c9ab3d508c 100644 --- a/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.pt-BR.xlf +++ b/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.pt-BR.xlf @@ -32,6 +32,11 @@ Nunca + + Prefer 'IsNot' expression + Prefer 'IsNot' expression + + Prefer 'Is Nothing' for reference equality checks Prefira 'Is Nothing' para as verificações de igualdade de referência diff --git a/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.ru.xlf b/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.ru.xlf index 61d699e2a81e4..264023ff3473b 100644 --- a/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.ru.xlf +++ b/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.ru.xlf @@ -32,6 +32,11 @@ Никогда + + Prefer 'IsNot' expression + Prefer 'IsNot' expression + + Prefer 'Is Nothing' for reference equality checks Предпочитать Is Nothing для проверок равенства ссылок diff --git a/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.tr.xlf b/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.tr.xlf index 963492a89fd37..d7f131009ac4f 100644 --- a/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.tr.xlf +++ b/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.tr.xlf @@ -32,6 +32,11 @@ Hiçbir zaman + + Prefer 'IsNot' expression + Prefer 'IsNot' expression + + Prefer 'Is Nothing' for reference equality checks Başvuru eşitliği denetimleri için 'Is Nothing'i tercih et diff --git a/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.zh-Hans.xlf b/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.zh-Hans.xlf index 0451f70700648..046409923d277 100644 --- a/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.zh-Hans.xlf +++ b/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.zh-Hans.xlf @@ -32,6 +32,11 @@ 从不 + + Prefer 'IsNot' expression + Prefer 'IsNot' expression + + Prefer 'Is Nothing' for reference equality checks 引用相等检查偏好 “Is Nothing” diff --git a/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.zh-Hant.xlf b/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.zh-Hant.xlf index 4521fe8af1113..af4d772b74dc1 100644 --- a/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.zh-Hant.xlf +++ b/src/VisualStudio/VisualBasic/Impl/xlf/BasicVSResources.zh-Hant.xlf @@ -32,6 +32,11 @@ 永不 + + Prefer 'IsNot' expression + Prefer 'IsNot' expression + + Prefer 'Is Nothing' for reference equality checks 參考相等檢查最好使用 'Is Nothing' diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/CodeStyle/CSharpCodeStyleOptions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/CodeStyle/CSharpCodeStyleOptions.cs index c6f8b0b3da3e2..7737be5daf0a3 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/CodeStyle/CSharpCodeStyleOptions.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/CodeStyle/CSharpCodeStyleOptions.cs @@ -79,6 +79,13 @@ private static Option2 CreateOption(OptionGroup group, string name, T defa EditorConfigStorageLocation.ForBoolCodeStyleOption("csharp_style_pattern_matching_over_is_with_cast_check"), new RoamingProfileStorageLocation($"TextEditor.CSharp.Specific.{nameof(PreferPatternMatchingOverIsWithCastCheck)}")}); + public static readonly Option2> PreferNotPattern = CreateOption( + CSharpCodeStyleOptionGroups.PatternMatching, nameof(PreferNotPattern), + defaultValue: s_trueWithSuggestionEnforcement, + storageLocations: new OptionStorageLocation2[] { + EditorConfigStorageLocation.ForBoolCodeStyleOption("csharp_style_prefer_not_pattern"), + new RoamingProfileStorageLocation($"TextEditor.CSharp.Specific.{nameof(PreferNotPattern)}")}); + public static readonly Option2> PreferThrowExpression = CreateOption( CSharpCodeStyleOptionGroups.ExpressionLevelPreferences, nameof(PreferThrowExpression), defaultValue: s_trueWithSuggestionEnforcement, diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/CodeStyle/VisualBasicCodeStyleOptions.vb b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/CodeStyle/VisualBasicCodeStyleOptions.vb index add5c7294b714..f39146343614c 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/CodeStyle/VisualBasicCodeStyleOptions.vb +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/CodeStyle/VisualBasicCodeStyleOptions.vb @@ -30,12 +30,18 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeStyle SyntaxKind.WithEventsKeyword, SyntaxKind.WideningKeyword, SyntaxKind.NarrowingKeyword, SyntaxKind.CustomKeyword, SyntaxKind.AsyncKeyword, SyntaxKind.IteratorKeyword) - Public Shared ReadOnly PreferredModifierOrder As [Option2](Of CodeStyleOption2(Of String)) = CreateOption( + Public Shared ReadOnly PreferredModifierOrder As Option2(Of CodeStyleOption2(Of String)) = CreateOption( VisualBasicCodeStyleOptionGroups.Modifier, NameOf(PreferredModifierOrder), defaultValue:=New CodeStyleOption2(Of String)(String.Join(",", PreferredModifierOrderDefault.Select(AddressOf SyntaxFacts.GetText)), NotificationOption2.Silent), EditorConfigStorageLocation.ForStringCodeStyleOption("visual_basic_preferred_modifier_order"), New RoamingProfileStorageLocation($"TextEditor.%LANGUAGE%.Specific.{NameOf(PreferredModifierOrder)}")) + Public Shared ReadOnly PreferIsNotExpression As Option2(Of CodeStyleOption2(Of Boolean)) = CreateOption( + VisualBasicCodeStyleOptionGroups.ExpressionLevelPreferences, NameOf(PreferIsNotExpression), + defaultValue:=New CodeStyleOption2(Of Boolean)(True, NotificationOption2.Suggestion), + EditorConfigStorageLocation.ForBoolCodeStyleOption("visual_basic_style_prefer_isnot_expression"), + New RoamingProfileStorageLocation($"TextEditor.%LANGUAGE%.Specific.{NameOf(PreferIsNotExpression)}")) + Public Shared ReadOnly UnusedValueExpressionStatement As [Option2](Of CodeStyleOption2(Of UnusedValuePreference)) = CodeStyleHelpers.CreateUnusedExpressionAssignmentOption( group:=VisualBasicCodeStyleOptionGroups.ExpressionLevelPreferences,