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
+ {locked: IsNot}This is a Visual Basic keyword and should not be localized or have its casing changed
+
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
+ {locked: IsNot}This is a Visual Basic keyword and should not be localized or have its casing changed
+
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
+ {locked: IsNot}This is a Visual Basic keyword and should not be localized or have its casing changed
+
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
+ {locked: IsNot}This is a Visual Basic keyword and should not be localized or have its casing changed
+
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
+ {locked: IsNot}This is a Visual Basic keyword and should not be localized or have its casing changed
+
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
+ {locked: IsNot}This is a Visual Basic keyword and should not be localized or have its casing changed
+
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
+ {locked: IsNot}This is a Visual Basic keyword and should not be localized or have its casing changed
+
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
+ {locked: IsNot}This is a Visual Basic keyword and should not be localized or have its casing changed
+
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
+ {locked: IsNot}This is a Visual Basic keyword and should not be localized or have its casing changed
+
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
+ {locked: IsNot}This is a Visual Basic keyword and should not be localized or have its casing changed
+
Использовать флажок "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
+ {locked: IsNot}This is a Visual Basic keyword and should not be localized or have its casing changed
+
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
+ {locked: IsNot}This is a Visual Basic keyword and should not be localized or have its casing changed
+
使用 "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
+ {locked: IsNot}This is a Visual Basic keyword and should not be localized or have its casing changed
+
使用 '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:
+
+
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
+
+
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:
+
+
Zusätzliche Codebereinigung während der Formatierung durchführen
@@ -82,6 +87,11 @@
Prefer pattern matching
+
+
+ Prefer pattern matching over mixed type check
+
+
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:
+
+
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
+
+
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:
+
+
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
+
+
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:
+
+
Esegui la pulizia del codice aggiuntiva durante la formattazione
@@ -82,6 +87,11 @@
Prefer pattern matching
+
+
+ Prefer pattern matching over mixed type check
+
+
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:
+
+
書式設定中に追加のコード クリーンアップを実行
@@ -82,6 +87,11 @@
Prefer pattern matching
+
+
+ Prefer pattern matching over mixed type check
+
+
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:
+
+
서식을 지정하는 동안 추가 코드 정리 수행
@@ -82,6 +87,11 @@
Prefer pattern matching
+
+
+ Prefer pattern matching over mixed type check
+
+
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:
+
+
Wykonaj dodatkowe oczyszczanie kodu podczas formatowania
@@ -82,6 +87,11 @@
Prefer pattern matching
+
+
+ Prefer pattern matching over mixed type check
+
+
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:
+
+
Executar limpeza de código adicional durante a formatação
@@ -82,6 +87,11 @@
Prefer pattern matching
+
+
+ Prefer pattern matching over mixed type check
+
+
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:
+
+
Выполнять при форматировании дополнительную очистку кода
@@ -82,6 +87,11 @@
Prefer pattern matching
+
+
+ Prefer pattern matching over mixed type check
+
+
Предпочитать выражение 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:
+
+
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
+
+
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:
+
+
在格式设置期间执行其他代码清理
@@ -82,6 +87,11 @@
Prefer pattern matching
+
+
+ Prefer pattern matching over mixed type check
+
+
首选 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:
+
+
在格式化期間執行額外程式碼清除
@@ -82,6 +87,11 @@
Prefer pattern matching
+
+
+ Prefer pattern matching over mixed type check
+
+
建議使用 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
+
+
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
+
+
"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
+
+
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
+
+
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
+
+
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
+
+
参照の等値性のチェックには '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
+
+
참조 같음 검사에 대해 '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
+
+
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
+
+
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
+
+
Предпочитать 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
+
+
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
+
+
引用相等检查偏好 “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
+
+
參考相等檢查最好使用 '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,