From fc24f81dc0601fb2f43ae4485a93f2ff3cfb5069 Mon Sep 17 00:00:00 2001 From: Corniel Nobel Date: Wed, 7 Jun 2023 08:49:49 +0200 Subject: [PATCH 1/8] Implement S6326 for both C# and VB.NET. --- .../RegexShouldNotContainMultipleSpaces.cs | 27 ++++ .../Facade/ILanguageFacade.cs | 20 +++ .../RegularExpressions/RegexContext.cs | 3 +- ...RegexShouldNotContainMultipleSpacesBase.cs | 66 ++++++++++ .../RegexShouldNotContainMultipleSpaces.cs | 27 ++++ .../RegexMustHaveValidSyntaxTest.cs | 57 ++++++++ ...RegexShouldNotContainMultipleSpacesTest.cs | 46 +++++++ .../RegexShouldNotContainMultipleSpaces.cs | 124 ++++++++++++++++++ .../RegexShouldNotContainMultipleSpaces.vb | 34 +++++ 9 files changed, 403 insertions(+), 1 deletion(-) create mode 100644 analyzers/src/SonarAnalyzer.CSharp/Rules/RegularExpressions/RegexShouldNotContainMultipleSpaces.cs create mode 100644 analyzers/src/SonarAnalyzer.Common/Rules/RegularExpressions/RegexShouldNotContainMultipleSpacesBase.cs create mode 100644 analyzers/src/SonarAnalyzer.VisualBasic/Rules/RegularExpressions/RegexShouldNotContainMultipleSpaces.cs create mode 100644 analyzers/tests/SonarAnalyzer.UnitTest/Rules/RegularExpressions/RegexMustHaveValidSyntaxTest.cs create mode 100644 analyzers/tests/SonarAnalyzer.UnitTest/Rules/RegularExpressions/RegexShouldNotContainMultipleSpacesTest.cs create mode 100644 analyzers/tests/SonarAnalyzer.UnitTest/TestCases/RegularExpressions/RegexShouldNotContainMultipleSpaces.cs create mode 100644 analyzers/tests/SonarAnalyzer.UnitTest/TestCases/RegularExpressions/RegexShouldNotContainMultipleSpaces.vb diff --git a/analyzers/src/SonarAnalyzer.CSharp/Rules/RegularExpressions/RegexShouldNotContainMultipleSpaces.cs b/analyzers/src/SonarAnalyzer.CSharp/Rules/RegularExpressions/RegexShouldNotContainMultipleSpaces.cs new file mode 100644 index 00000000000..472b2a317d8 --- /dev/null +++ b/analyzers/src/SonarAnalyzer.CSharp/Rules/RegularExpressions/RegexShouldNotContainMultipleSpaces.cs @@ -0,0 +1,27 @@ +/* + * SonarAnalyzer for .NET + * Copyright (C) 2015-2023 SonarSource SA + * mailto: contact AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +namespace SonarAnalyzer.Rules.CSharp; + +[DiagnosticAnalyzer(LanguageNames.CSharp)] +public sealed class RegexShouldNotContainMultipleSpaces : RegexShouldNotContainMultipleSpacesBase +{ + protected override ILanguageFacade Language => CSharpFacade.Instance; +} diff --git a/analyzers/src/SonarAnalyzer.Common/Facade/ILanguageFacade.cs b/analyzers/src/SonarAnalyzer.Common/Facade/ILanguageFacade.cs index e196f6f12ed..70bc6c2b1c1 100644 --- a/analyzers/src/SonarAnalyzer.Common/Facade/ILanguageFacade.cs +++ b/analyzers/src/SonarAnalyzer.Common/Facade/ILanguageFacade.cs @@ -44,3 +44,23 @@ public interface ILanguageFacade : ILanguageFacade ISyntaxKindFacade SyntaxKind { get; } ITrackerFacade Tracker { get; } } + +public static class LanguageFacadeExtensions +{ + public static TEnum? FindConstantEnum(this ILanguageFacade facade, SemanticModel model, SyntaxNode node) where TEnum : struct + { + var value = facade.FindConstantValue(model, node); + if (value is TEnum @enum) + { + return @enum; + } + else if (value is int || value is long) + { + return (TEnum)value; + } + else + { + return null; + } + } +} diff --git a/analyzers/src/SonarAnalyzer.Common/RegularExpressions/RegexContext.cs b/analyzers/src/SonarAnalyzer.Common/RegularExpressions/RegexContext.cs index 6bbb84be2a9..3a8cf4506c8 100644 --- a/analyzers/src/SonarAnalyzer.Common/RegularExpressions/RegexContext.cs +++ b/analyzers/src/SonarAnalyzer.Common/RegularExpressions/RegexContext.cs @@ -22,6 +22,7 @@ namespace SonarAnalyzer.RegularExpressions; +[DebuggerDisplay("Pattern = {Pattern}, Options = {Options}")] internal sealed class RegexContext { private static readonly RegexOptions ValidationMask = (RegexOptions)int.MaxValue ^ RegexOptions.Compiled; @@ -102,7 +103,7 @@ private static RegexContext FromMethod(ILanguageFacade pattern, language.FindConstantValue(model, pattern) as string, options, - language.FindConstantValue(model, options) is RegexOptions value ? value : null); + language.FindConstantEnum(model, options)); } private static SyntaxNode TryGetNonParamsSyntax(IMethodSymbol method, IMethodParameterLookup parameters, string paramName) => diff --git a/analyzers/src/SonarAnalyzer.Common/Rules/RegularExpressions/RegexShouldNotContainMultipleSpacesBase.cs b/analyzers/src/SonarAnalyzer.Common/Rules/RegularExpressions/RegexShouldNotContainMultipleSpacesBase.cs new file mode 100644 index 00000000000..6e81bc77f60 --- /dev/null +++ b/analyzers/src/SonarAnalyzer.Common/Rules/RegularExpressions/RegexShouldNotContainMultipleSpacesBase.cs @@ -0,0 +1,66 @@ +/* + * SonarAnalyzer for .NET + * Copyright (C) 2015-2023 SonarSource SA + * mailto: contact AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +using System.Text.RegularExpressions; +using SonarAnalyzer.RegularExpressions; + +namespace SonarAnalyzer.Rules; + +public abstract class RegexShouldNotContainMultipleSpacesBase : SonarDiagnosticAnalyzer + where TSyntaxKind : struct +{ + private const string DiagnosticId = "S6326"; + + protected sealed override string MessageFormat => "Regular expressions should not contain multiple spaces."; + + protected RegexShouldNotContainMultipleSpacesBase() : base(DiagnosticId) { } + + protected override void Initialize(SonarAnalysisContext context) + { + context.RegisterNodeAction( + Language.GeneratedCodeRecognizer, + c => Analyze(c, RegexContext.FromCtor(Language, c.SemanticModel, c.Node)), + Language.SyntaxKind.ObjectCreationExpressions); + + context.RegisterNodeAction( + Language.GeneratedCodeRecognizer, + c => Analyze(c, RegexContext.FromMethod(Language, c.SemanticModel, c.Node)), + Language.SyntaxKind.InvocationExpression); + + context.RegisterNodeAction( + Language.GeneratedCodeRecognizer, + c => Analyze(c, RegexContext.FromAttribute(Language, c.SemanticModel, c.Node)), + Language.SyntaxKind.Attribute); + } + + private void Analyze(SonarSyntaxNodeReportingContext c, RegexContext context) + { + if (context?.Regex is { } + && !IgnoresPatternWhitespace(context) + && context.Pattern.Contains(" ")) + { + c.ReportIssue(Diagnostic.Create(Rule, context.PatternNode.GetLocation())); + } + } + + private bool IgnoresPatternWhitespace(RegexContext context) => + context.Options is { } options + && options.HasFlag(RegexOptions.IgnorePatternWhitespace); +} diff --git a/analyzers/src/SonarAnalyzer.VisualBasic/Rules/RegularExpressions/RegexShouldNotContainMultipleSpaces.cs b/analyzers/src/SonarAnalyzer.VisualBasic/Rules/RegularExpressions/RegexShouldNotContainMultipleSpaces.cs new file mode 100644 index 00000000000..82fafb23c78 --- /dev/null +++ b/analyzers/src/SonarAnalyzer.VisualBasic/Rules/RegularExpressions/RegexShouldNotContainMultipleSpaces.cs @@ -0,0 +1,27 @@ +/* + * SonarAnalyzer for .NET + * Copyright (C) 2015-2023 SonarSource SA + * mailto: contact AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +namespace SonarAnalyzer.Rules.VisualBasic; + +[DiagnosticAnalyzer(LanguageNames.VisualBasic)] +public sealed class RegexShouldNotContainMultipleSpaces : RegexShouldNotContainMultipleSpacesBase +{ + protected override ILanguageFacade Language => VisualBasicFacade.Instance; +} diff --git a/analyzers/tests/SonarAnalyzer.UnitTest/Rules/RegularExpressions/RegexMustHaveValidSyntaxTest.cs b/analyzers/tests/SonarAnalyzer.UnitTest/Rules/RegularExpressions/RegexMustHaveValidSyntaxTest.cs new file mode 100644 index 00000000000..56499a1d266 --- /dev/null +++ b/analyzers/tests/SonarAnalyzer.UnitTest/Rules/RegularExpressions/RegexMustHaveValidSyntaxTest.cs @@ -0,0 +1,57 @@ +/* + * SonarAnalyzer for .NET + * Copyright (C) 2015-2023 SonarSource SA + * mailto: contact AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +using CS = SonarAnalyzer.Rules.CSharp; +using VB = SonarAnalyzer.Rules.VisualBasic; + +namespace SonarAnalyzer.UnitTest.Rules; + +[TestClass] +public class RegexMustHaveValidSyntaxTest +{ + private readonly VerifierBuilder builderCS = new VerifierBuilder() + .WithBasePath("RegularExpressions") + .AddReferences(MetadataReferenceFacade.RegularExpressions) + .AddReferences(NuGetMetadataReference.SystemComponentModelAnnotations()); + + private readonly VerifierBuilder builderVB = new VerifierBuilder() + .WithBasePath("RegularExpressions") + .AddReferences(MetadataReferenceFacade.RegularExpressions) + .AddReferences(NuGetMetadataReference.SystemComponentModelAnnotations()); + + [TestMethod] + public void RegexMustHaveValidSyntax_CS() => + builderCS.AddPaths("RegexMustHaveValidSyntax.cs").Verify(); + +#if NET + + [TestMethod] + public void RegexMustHaveValidSyntax_CSharp9() => + builderCS.AddPaths("RegexMustHaveValidSyntax.CSharp9.cs").WithOptions(ParseOptionsHelper.FromCSharp9).Verify(); + + [TestMethod] + public void RegexMustHaveValidSyntax_CSharp11() => + builderCS.AddPaths("RegexMustHaveValidSyntax.CSharp11.cs").WithOptions(ParseOptionsHelper.FromCSharp11).Verify(); +#endif + + [TestMethod] + public void RegexMustHaveValidSyntax_VB() => + builderVB.AddPaths("RegexMustHaveValidSyntax.vb").Verify(); +} diff --git a/analyzers/tests/SonarAnalyzer.UnitTest/Rules/RegularExpressions/RegexShouldNotContainMultipleSpacesTest.cs b/analyzers/tests/SonarAnalyzer.UnitTest/Rules/RegularExpressions/RegexShouldNotContainMultipleSpacesTest.cs new file mode 100644 index 00000000000..f8377d0d7a7 --- /dev/null +++ b/analyzers/tests/SonarAnalyzer.UnitTest/Rules/RegularExpressions/RegexShouldNotContainMultipleSpacesTest.cs @@ -0,0 +1,46 @@ +/* + * SonarAnalyzer for .NET + * Copyright (C) 2015-2023 SonarSource SA + * mailto: contact AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +using CS = SonarAnalyzer.Rules.CSharp; +using VB = SonarAnalyzer.Rules.VisualBasic; + +namespace SonarAnalyzer.UnitTest.Rules; + +[TestClass] +public class RegexShouldNotContainMultipleSpacesTest +{ + private readonly VerifierBuilder builderCS = new VerifierBuilder() + .WithBasePath("RegularExpressions") + .AddReferences(MetadataReferenceFacade.RegularExpressions) + .AddReferences(NuGetMetadataReference.SystemComponentModelAnnotations()); + + private readonly VerifierBuilder builderVB = new VerifierBuilder() + .WithBasePath("RegularExpressions") + .AddReferences(MetadataReferenceFacade.RegularExpressions) + .AddReferences(NuGetMetadataReference.SystemComponentModelAnnotations()); + + [TestMethod] + public void RegexShouldNotContainMultipleSpaces_CS() => + builderCS.AddPaths("RegexShouldNotContainMultipleSpaces.cs").Verify(); + + [TestMethod] + public void RegexShouldNotContainMultipleSpaces_VB() => + builderVB.AddPaths("RegexShouldNotContainMultipleSpaces.vb").Verify(); +} diff --git a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/RegularExpressions/RegexShouldNotContainMultipleSpaces.cs b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/RegularExpressions/RegexShouldNotContainMultipleSpaces.cs new file mode 100644 index 00000000000..3cbfbe2ca5a --- /dev/null +++ b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/RegularExpressions/RegexShouldNotContainMultipleSpaces.cs @@ -0,0 +1,124 @@ +using System; +using System.ComponentModel.DataAnnotations; +using System.Text.RegularExpressions; + +class Compliant +{ + void Ctor() + { + var defaultOrder = new Regex("single space"); // Compliant + + var namedArgs = new Regex( + pattern: "single space"); + + var noRegex = new NoRegex("single space"); // Compliant + + var singleOption = new Regex("ignore pattern white space", RegexOptions.IgnorePatternWhitespace); // Compliant + var mixedOptions = new Regex("ignore pattern white space", RegexOptions.IgnorePatternWhitespace | RegexOptions.Compiled); // Compliant + } + + void Static() + { + var isMatch = Regex.IsMatch("some input", "single space"); // Compliant + var noRegex = NoRegex.IsMatch("some input", "multiple white spaces"); // Compliant + } + + void Unknown(string unknown) + { + var regex = new NoRegex(unknown + "multiple white spaces"); // Compliant + } + + bool ConcatanationMultiline(string input) + { + return Regex.IsMatch(input, "single space" + + "|b" + + "|c" + + "|d]"); // Compliant + } + + bool ConcatanationSingleIne(string input) + { + return Regex.IsMatch(input, "a" + "|b" + "|c" + "|single white space"); // Compliant + } + + [RegularExpression("single space")] // Compliant + public string Attribute { get; set; } + + bool WhiteSpaceVariations(string input) + { + return Regex.IsMatch(input, " with multple single spaces ") + || Regex.IsMatch(input, "without_spaces") + || Regex.IsMatch(input, "with\ttab") + || Regex.IsMatch(input, "") + || Regex.IsMatch(input, "ignore pattern white space", RegexOptions.IgnorePatternWhitespace); + } +} + +class Noncompliant +{ + private const string Prefix = ".*"; + + void Ctor() + { + var patternOnly = new Regex("multiple white spaces"); // Noncompliant {{Regular expressions should not contain multiple spaces.}} + // ^^^^^^^^^^^^^^^^^^^^^^^^^ + + var withConst = new Regex(Prefix + "multiple white spaces"); // Noncompliant + } + + void Static() + { + var isMatch = Regex.IsMatch("some input", "multiple white spaces"); // Noncompliant + // ^^^^^^^^^^^^^^^^^^^^^^^^^ + var match = Regex.Match("some input", "multiple white spaces"); // Noncompliant + var matches = Regex.Matches("some input", "multiple white spaces"); // Noncompliant + var split = Regex.Split("some input", "multiple white spaces"); // Noncompliant + + var replace = Regex.Replace("some input", "multiple white spaces", "some replacement"); // Noncompliant + } + + bool Multiline(string input) + { + return Regex.IsMatch(input, + @"|b + |c + |multiple white spaces"); // Noncompliant @-2 + } + + bool ConcatanationMultiline(string input) + { + return Regex.IsMatch(input, "a" // Noncompliant + + "|b" + + "|c" + + "|multiple white spaces"); + } + + bool ConcatanationSingleIne(string input) + { + return Regex.IsMatch(input, "a" + "|b" + "|c" + "|multiple white spaces"); // Noncompliant + } + + [RegularExpression("multiple white spaces")] // Noncompliant + public string Attribute { get; set; } + + [System.ComponentModel.DataAnnotations.RegularExpression("multiple white spaces")] // Noncompliant + public string AttributeFullySpecified { get; set; } + + [global::System.ComponentModel.DataAnnotations.RegularExpression("multiple white spaces")] // Noncompliant + public string AttributeGloballySpecified { get; set; } +} + +class DoesNotCrash +{ + bool UnknownVariable(string input) + { + return Regex.IsMatch(input, "a" + undefined); // Error CS0103 The name 'undefined' does not exist in the current context + } +} + +public class NoRegex +{ + public NoRegex(string pattern) { } + + public static bool IsMatch(string input, string pattern) { return true; } +} diff --git a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/RegularExpressions/RegexShouldNotContainMultipleSpaces.vb b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/RegularExpressions/RegexShouldNotContainMultipleSpaces.vb new file mode 100644 index 00000000000..130521f5057 --- /dev/null +++ b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/RegularExpressions/RegexShouldNotContainMultipleSpaces.vb @@ -0,0 +1,34 @@ +Imports System.ComponentModel.DataAnnotations +Imports System.Text.RegularExpressions + +Class Compliant + Private Sub Ctor() + Dim defaultOrder = New Regex("single space") + Dim namedArgs = New Regex(options:=RegexOptions.IgnorePatternWhitespace, pattern:="ignore pattern white space") + End Sub + + Private Sub [Static]() + Dim isMatch = Regex.IsMatch("some input", "single space") + End Sub + + + Public Property Attribute As String +End Class + +Class Noncompliant + Private Sub Ctor() + Dim patternOnly = New Regex("multiple white spaces") ' Noncompliant {{Regular expressions should not contain multiple spaces.}} + ' ^^^^^^^^^^^^^^^^^^^^^^^^^ + End Sub + + Private Sub [Static]() + Dim isMatch = Regex.IsMatch("some input", "multiple white spaces") ' Noncompliant + Dim match = Regex.Match("some input", "multiple white spaces") ' Noncompliant + Dim matches = Regex.Matches("some input", "multiple white spaces") ' Noncompliant + Dim split = Regex.Split("some input", "multiple white spaces") ' Noncompliant + Dim replace = Regex.Replace("some input", "multiple white spaces", "some replacement") ' Noncompliant + End Sub + + ' Noncompliant + Public Property Attribute As String +End Class From 180201f9b4df1119eb06f3b8dce568590b174ede Mon Sep 17 00:00:00 2001 From: Corniel Nobel Date: Thu, 20 Jul 2023 22:49:03 +0200 Subject: [PATCH 2/8] Update analyzers/tests/SonarAnalyzer.UnitTest/TestCases/RegularExpressions/RegexShouldNotContainMultipleSpaces.cs Co-authored-by: Pavel Mikula <57188685+pavel-mikula-sonarsource@users.noreply.github.com> --- .../RegularExpressions/RegexShouldNotContainMultipleSpaces.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/RegularExpressions/RegexShouldNotContainMultipleSpaces.cs b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/RegularExpressions/RegexShouldNotContainMultipleSpaces.cs index 3cbfbe2ca5a..1260c179411 100644 --- a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/RegularExpressions/RegexShouldNotContainMultipleSpaces.cs +++ b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/RegularExpressions/RegexShouldNotContainMultipleSpaces.cs @@ -60,7 +60,7 @@ class Noncompliant void Ctor() { - var patternOnly = new Regex("multiple white spaces"); // Noncompliant {{Regular expressions should not contain multiple spaces.}} + var patternOnly = new Regex("multiple white spaces"); // Noncompliant {{Regular expressions should not contain multiple spaces.}} // ^^^^^^^^^^^^^^^^^^^^^^^^^ var withConst = new Regex(Prefix + "multiple white spaces"); // Noncompliant From 2c3ad46cb0f176156064e2d9eb62e660d056e28b Mon Sep 17 00:00:00 2001 From: Corniel Nobel Date: Thu, 20 Jul 2023 23:00:25 +0200 Subject: [PATCH 3/8] Introduction of a base class. --- analyzers/NuGet.Config | 43 ---------------- .../RegularExpressions/RegexContext.cs | 2 +- .../RegularExpressions/RegexAnalyzerBase.cs | 49 +++++++++++++++++++ .../RegexMustHaveValidSyntaxBase.cs | 24 ++------- ...RegexShouldNotContainMultipleSpacesBase.cs | 30 +++--------- 5 files changed, 59 insertions(+), 89 deletions(-) delete mode 100644 analyzers/NuGet.Config create mode 100644 analyzers/src/SonarAnalyzer.Common/Rules/RegularExpressions/RegexAnalyzerBase.cs diff --git a/analyzers/NuGet.Config b/analyzers/NuGet.Config deleted file mode 100644 index 0118683ee77..00000000000 --- a/analyzers/NuGet.Config +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - protobuf-packages;Microsoft;sharwell;meirb;dotnetfoundation;castleproject;jonorossi;onovotny;fluentassertions;SteveGilham;jamesnk;commandlineparser;grpc-packages;Fody;NSubstitute - - - - - - - diff --git a/analyzers/src/SonarAnalyzer.Common/RegularExpressions/RegexContext.cs b/analyzers/src/SonarAnalyzer.Common/RegularExpressions/RegexContext.cs index 3a8cf4506c8..e8e5ac9f2ed 100644 --- a/analyzers/src/SonarAnalyzer.Common/RegularExpressions/RegexContext.cs +++ b/analyzers/src/SonarAnalyzer.Common/RegularExpressions/RegexContext.cs @@ -23,7 +23,7 @@ namespace SonarAnalyzer.RegularExpressions; [DebuggerDisplay("Pattern = {Pattern}, Options = {Options}")] -internal sealed class RegexContext +public sealed class RegexContext { private static readonly RegexOptions ValidationMask = (RegexOptions)int.MaxValue ^ RegexOptions.Compiled; diff --git a/analyzers/src/SonarAnalyzer.Common/Rules/RegularExpressions/RegexAnalyzerBase.cs b/analyzers/src/SonarAnalyzer.Common/Rules/RegularExpressions/RegexAnalyzerBase.cs new file mode 100644 index 00000000000..e9245352f01 --- /dev/null +++ b/analyzers/src/SonarAnalyzer.Common/Rules/RegularExpressions/RegexAnalyzerBase.cs @@ -0,0 +1,49 @@ +/* + * SonarAnalyzer for .NET + * Copyright (C) 2015-2023 SonarSource SA + * mailto: contact AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +using SonarAnalyzer.RegularExpressions; + +namespace SonarAnalyzer.Rules; + +public abstract class RegexAnalyzerBase : SonarDiagnosticAnalyzer + where TSyntaxKind : struct +{ + protected RegexAnalyzerBase(string diagnosticId) : base(diagnosticId) { } + + protected abstract void Analyze(SonarSyntaxNodeReportingContext context, RegexContext regexContext); + + protected sealed override void Initialize(SonarAnalysisContext context) + { + context.RegisterNodeAction( + Language.GeneratedCodeRecognizer, + c => Analyze(c, RegexContext.FromCtor(Language, c.SemanticModel, c.Node)), + Language.SyntaxKind.ObjectCreationExpressions); + + context.RegisterNodeAction( + Language.GeneratedCodeRecognizer, + c => Analyze(c, RegexContext.FromMethod(Language, c.SemanticModel, c.Node)), + Language.SyntaxKind.InvocationExpression); + + context.RegisterNodeAction( + Language.GeneratedCodeRecognizer, + c => Analyze(c, RegexContext.FromAttribute(Language, c.SemanticModel, c.Node)), + Language.SyntaxKind.Attribute); + } +} diff --git a/analyzers/src/SonarAnalyzer.Common/Rules/RegularExpressions/RegexMustHaveValidSyntaxBase.cs b/analyzers/src/SonarAnalyzer.Common/Rules/RegularExpressions/RegexMustHaveValidSyntaxBase.cs index 1f44b0ce84d..2498d339b16 100644 --- a/analyzers/src/SonarAnalyzer.Common/Rules/RegularExpressions/RegexMustHaveValidSyntaxBase.cs +++ b/analyzers/src/SonarAnalyzer.Common/Rules/RegularExpressions/RegexMustHaveValidSyntaxBase.cs @@ -22,7 +22,7 @@ namespace SonarAnalyzer.Rules; -public abstract class RegexMustHaveValidSyntaxBase : SonarDiagnosticAnalyzer +public abstract class RegexMustHaveValidSyntaxBase : RegexAnalyzerBase where TSyntaxKind : struct { private const string DiagnosticId = "S5856"; @@ -31,27 +31,9 @@ public abstract class RegexMustHaveValidSyntaxBase : SonarDiagnosti protected RegexMustHaveValidSyntaxBase() : base(DiagnosticId) { } - protected override void Initialize(SonarAnalysisContext context) + protected sealed override void Analyze(SonarSyntaxNodeReportingContext context, RegexContext regexContext) { - context.RegisterNodeAction( - Language.GeneratedCodeRecognizer, - c => Analyze(c, RegexContext.FromCtor(Language, c.SemanticModel, c.Node)), - Language.SyntaxKind.ObjectCreationExpressions); - - context.RegisterNodeAction( - Language.GeneratedCodeRecognizer, - c => Analyze(c, RegexContext.FromMethod(Language, c.SemanticModel, c.Node)), - Language.SyntaxKind.InvocationExpression); - - context.RegisterNodeAction( - Language.GeneratedCodeRecognizer, - c => Analyze(c, RegexContext.FromAttribute(Language, c.SemanticModel, c.Node)), - Language.SyntaxKind.Attribute); - } - - private void Analyze(SonarSyntaxNodeReportingContext c, RegexContext context) - { - if (context?.ParseError is { } error) + if (regexContext?.ParseError is { } error) { c.ReportIssue(Rule, context.PatternNode, error.Message); } diff --git a/analyzers/src/SonarAnalyzer.Common/Rules/RegularExpressions/RegexShouldNotContainMultipleSpacesBase.cs b/analyzers/src/SonarAnalyzer.Common/Rules/RegularExpressions/RegexShouldNotContainMultipleSpacesBase.cs index 6e81bc77f60..2849e5ba60b 100644 --- a/analyzers/src/SonarAnalyzer.Common/Rules/RegularExpressions/RegexShouldNotContainMultipleSpacesBase.cs +++ b/analyzers/src/SonarAnalyzer.Common/Rules/RegularExpressions/RegexShouldNotContainMultipleSpacesBase.cs @@ -23,7 +23,7 @@ namespace SonarAnalyzer.Rules; -public abstract class RegexShouldNotContainMultipleSpacesBase : SonarDiagnosticAnalyzer +public abstract class RegexShouldNotContainMultipleSpacesBase : RegexAnalyzerBase where TSyntaxKind : struct { private const string DiagnosticId = "S6326"; @@ -32,31 +32,13 @@ public abstract class RegexShouldNotContainMultipleSpacesBase : Son protected RegexShouldNotContainMultipleSpacesBase() : base(DiagnosticId) { } - protected override void Initialize(SonarAnalysisContext context) + protected sealed override void Analyze(SonarSyntaxNodeReportingContext context, RegexContext regexContext) { - context.RegisterNodeAction( - Language.GeneratedCodeRecognizer, - c => Analyze(c, RegexContext.FromCtor(Language, c.SemanticModel, c.Node)), - Language.SyntaxKind.ObjectCreationExpressions); - - context.RegisterNodeAction( - Language.GeneratedCodeRecognizer, - c => Analyze(c, RegexContext.FromMethod(Language, c.SemanticModel, c.Node)), - Language.SyntaxKind.InvocationExpression); - - context.RegisterNodeAction( - Language.GeneratedCodeRecognizer, - c => Analyze(c, RegexContext.FromAttribute(Language, c.SemanticModel, c.Node)), - Language.SyntaxKind.Attribute); - } - - private void Analyze(SonarSyntaxNodeReportingContext c, RegexContext context) - { - if (context?.Regex is { } - && !IgnoresPatternWhitespace(context) - && context.Pattern.Contains(" ")) + if (regexContext?.Regex is { } + && !IgnoresPatternWhitespace(regexContext) + && regexContext.Pattern.Contains(" ")) { - c.ReportIssue(Diagnostic.Create(Rule, context.PatternNode.GetLocation())); + context.ReportIssue(Diagnostic.Create(Rule, regexContext.PatternNode.GetLocation())); } } From 4d6e8645883ef50005f6d5997c388fd52eff1c0d Mon Sep 17 00:00:00 2001 From: Corniel Nobel Date: Thu, 20 Jul 2023 23:19:41 +0200 Subject: [PATCH 4/8] Applied suggestions. --- .../Facade/ILanguageFacade.cs | 20 ------------------- .../RegularExpressions/RegexContext.cs | 7 ++++++- ...RegexShouldNotContainMultipleSpacesBase.cs | 4 ++-- .../RegexShouldNotContainMultipleSpaces.cs | 20 +++++++++++++------ .../RegexShouldNotContainMultipleSpaces.vb | 4 ++-- 5 files changed, 24 insertions(+), 31 deletions(-) diff --git a/analyzers/src/SonarAnalyzer.Common/Facade/ILanguageFacade.cs b/analyzers/src/SonarAnalyzer.Common/Facade/ILanguageFacade.cs index 70bc6c2b1c1..e196f6f12ed 100644 --- a/analyzers/src/SonarAnalyzer.Common/Facade/ILanguageFacade.cs +++ b/analyzers/src/SonarAnalyzer.Common/Facade/ILanguageFacade.cs @@ -44,23 +44,3 @@ public interface ILanguageFacade : ILanguageFacade ISyntaxKindFacade SyntaxKind { get; } ITrackerFacade Tracker { get; } } - -public static class LanguageFacadeExtensions -{ - public static TEnum? FindConstantEnum(this ILanguageFacade facade, SemanticModel model, SyntaxNode node) where TEnum : struct - { - var value = facade.FindConstantValue(model, node); - if (value is TEnum @enum) - { - return @enum; - } - else if (value is int || value is long) - { - return (TEnum)value; - } - else - { - return null; - } - } -} diff --git a/analyzers/src/SonarAnalyzer.Common/RegularExpressions/RegexContext.cs b/analyzers/src/SonarAnalyzer.Common/RegularExpressions/RegexContext.cs index e8e5ac9f2ed..8aaaa73666a 100644 --- a/analyzers/src/SonarAnalyzer.Common/RegularExpressions/RegexContext.cs +++ b/analyzers/src/SonarAnalyzer.Common/RegularExpressions/RegexContext.cs @@ -103,9 +103,14 @@ private static RegexContext FromMethod(ILanguageFacade pattern, language.FindConstantValue(model, pattern) as string, options, - language.FindConstantEnum(model, options)); + FindRegexOptions(language, model, options)); } + private static RegexOptions? FindRegexOptions(ILanguageFacade language, SemanticModel model, SyntaxNode options) where TSyntaxKind : struct => + language.FindConstantValue(model, options) is int constant + ? (RegexOptions)constant + : null; + private static SyntaxNode TryGetNonParamsSyntax(IMethodSymbol method, IMethodParameterLookup parameters, string paramName) => method.Parameters.SingleOrDefault(x => x.Name == paramName) is { } param && parameters.TryGetNonParamsSyntax(param, out var node) diff --git a/analyzers/src/SonarAnalyzer.Common/Rules/RegularExpressions/RegexShouldNotContainMultipleSpacesBase.cs b/analyzers/src/SonarAnalyzer.Common/Rules/RegularExpressions/RegexShouldNotContainMultipleSpacesBase.cs index 2849e5ba60b..21fb9e914c4 100644 --- a/analyzers/src/SonarAnalyzer.Common/Rules/RegularExpressions/RegexShouldNotContainMultipleSpacesBase.cs +++ b/analyzers/src/SonarAnalyzer.Common/Rules/RegularExpressions/RegexShouldNotContainMultipleSpacesBase.cs @@ -26,7 +26,7 @@ namespace SonarAnalyzer.Rules; public abstract class RegexShouldNotContainMultipleSpacesBase : RegexAnalyzerBase where TSyntaxKind : struct { - private const string DiagnosticId = "S6326"; + private const string DiagnosticId = "S101"; protected sealed override string MessageFormat => "Regular expressions should not contain multiple spaces."; @@ -34,7 +34,7 @@ protected RegexShouldNotContainMultipleSpacesBase() : base(DiagnosticId) { } protected sealed override void Analyze(SonarSyntaxNodeReportingContext context, RegexContext regexContext) { - if (regexContext?.Regex is { } + if (regexContext?.Regex is not null && !IgnoresPatternWhitespace(regexContext) && regexContext.Pattern.Contains(" ")) { diff --git a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/RegularExpressions/RegexShouldNotContainMultipleSpaces.cs b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/RegularExpressions/RegexShouldNotContainMultipleSpaces.cs index 1260c179411..9c192d67892 100644 --- a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/RegularExpressions/RegexShouldNotContainMultipleSpaces.cs +++ b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/RegularExpressions/RegexShouldNotContainMultipleSpaces.cs @@ -23,11 +23,6 @@ void Static() var noRegex = NoRegex.IsMatch("some input", "multiple white spaces"); // Compliant } - void Unknown(string unknown) - { - var regex = new NoRegex(unknown + "multiple white spaces"); // Compliant - } - bool ConcatanationMultiline(string input) { return Regex.IsMatch(input, "single space" @@ -61,7 +56,7 @@ class Noncompliant void Ctor() { var patternOnly = new Regex("multiple white spaces"); // Noncompliant {{Regular expressions should not contain multiple spaces.}} - // ^^^^^^^^^^^^^^^^^^^^^^^^^ + // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ var withConst = new Regex(Prefix + "multiple white spaces"); // Noncompliant } @@ -108,6 +103,19 @@ bool ConcatanationSingleIne(string input) public string AttributeGloballySpecified { get; set; } } +class Invalid +{ + void FalseNegative(string unknown) + { + var regex = new NoRegex(unknown + "multiple white spaces"); // FN + } + + void FalsePositive() + { + var withComment = new Regex("(?# comment with spaces)"); // Noncompliant, FP + } +} + class DoesNotCrash { bool UnknownVariable(string input) diff --git a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/RegularExpressions/RegexShouldNotContainMultipleSpaces.vb b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/RegularExpressions/RegexShouldNotContainMultipleSpaces.vb index 130521f5057..06c9a59c770 100644 --- a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/RegularExpressions/RegexShouldNotContainMultipleSpaces.vb +++ b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/RegularExpressions/RegexShouldNotContainMultipleSpaces.vb @@ -17,8 +17,8 @@ End Class Class Noncompliant Private Sub Ctor() - Dim patternOnly = New Regex("multiple white spaces") ' Noncompliant {{Regular expressions should not contain multiple spaces.}} - ' ^^^^^^^^^^^^^^^^^^^^^^^^^ + Dim patternOnly = New Regex("multiple white spaces") ' Noncompliant {{Regular expressions should not contain multiple spaces.}} + ' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ End Sub Private Sub [Static]() From 97a07ded65e91ba710f9277b2d318b8ecd6d311b Mon Sep 17 00:00:00 2001 From: Corniel Nobel Date: Tue, 19 Mar 2024 13:13:45 +0100 Subject: [PATCH 5/8] Clean-up. --- .../Rules/RegularExpressions/RegexMustHaveValidSyntaxTest.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/analyzers/tests/SonarAnalyzer.Test/Rules/RegularExpressions/RegexMustHaveValidSyntaxTest.cs b/analyzers/tests/SonarAnalyzer.Test/Rules/RegularExpressions/RegexMustHaveValidSyntaxTest.cs index 60642591652..496a9420915 100644 --- a/analyzers/tests/SonarAnalyzer.Test/Rules/RegularExpressions/RegexMustHaveValidSyntaxTest.cs +++ b/analyzers/tests/SonarAnalyzer.Test/Rules/RegularExpressions/RegexMustHaveValidSyntaxTest.cs @@ -18,8 +18,6 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -using System.Text.RegularExpressions; -using SonarAnalyzer.RegularExpressions; using CS = SonarAnalyzer.Rules.CSharp; using VB = SonarAnalyzer.Rules.VisualBasic; From 91d247e083a0b7a53fcc223b3afa91469e907645 Mon Sep 17 00:00:00 2001 From: Corniel Nobel Date: Tue, 19 Mar 2024 13:53:15 +0100 Subject: [PATCH 6/8] Add whitespace examples. --- .../RegularExpressions/RegexContext.cs | 6 +- ...RegexShouldNotContainMultipleSpacesTest.cs | 4 +- .../RegexShouldNotContainMultipleSpaces.cs | 7 +++ .../RegexShouldNotContainMultipleSpaces.vb | 0 .../RegexMustHaveValidSyntaxTest.cs | 57 ------------------- 5 files changed, 12 insertions(+), 62 deletions(-) rename analyzers/tests/{SonarAnalyzer.UnitTest => SonarAnalyzer.Test}/Rules/RegularExpressions/RegexShouldNotContainMultipleSpacesTest.cs (95%) rename analyzers/tests/{SonarAnalyzer.UnitTest => SonarAnalyzer.Test}/TestCases/RegularExpressions/RegexShouldNotContainMultipleSpaces.cs (91%) rename analyzers/tests/{SonarAnalyzer.UnitTest => SonarAnalyzer.Test}/TestCases/RegularExpressions/RegexShouldNotContainMultipleSpaces.vb (100%) delete mode 100644 analyzers/tests/SonarAnalyzer.UnitTest/Rules/RegularExpressions/RegexMustHaveValidSyntaxTest.cs diff --git a/analyzers/src/SonarAnalyzer.Common/RegularExpressions/RegexContext.cs b/analyzers/src/SonarAnalyzer.Common/RegularExpressions/RegexContext.cs index 8aaaa73666a..6863b275afd 100644 --- a/analyzers/src/SonarAnalyzer.Common/RegularExpressions/RegexContext.cs +++ b/analyzers/src/SonarAnalyzer.Common/RegularExpressions/RegexContext.cs @@ -27,14 +27,14 @@ public sealed class RegexContext { private static readonly RegexOptions ValidationMask = (RegexOptions)int.MaxValue ^ RegexOptions.Compiled; - private static readonly string[] MatchMethods = new[] - { + private static readonly string[] MatchMethods = + [ nameof(Regex.IsMatch), nameof(Regex.Match), nameof(Regex.Matches), nameof(Regex.Replace), nameof(Regex.Split), - }; + ]; public SyntaxNode PatternNode { get; } public string Pattern { get; } diff --git a/analyzers/tests/SonarAnalyzer.UnitTest/Rules/RegularExpressions/RegexShouldNotContainMultipleSpacesTest.cs b/analyzers/tests/SonarAnalyzer.Test/Rules/RegularExpressions/RegexShouldNotContainMultipleSpacesTest.cs similarity index 95% rename from analyzers/tests/SonarAnalyzer.UnitTest/Rules/RegularExpressions/RegexShouldNotContainMultipleSpacesTest.cs rename to analyzers/tests/SonarAnalyzer.Test/Rules/RegularExpressions/RegexShouldNotContainMultipleSpacesTest.cs index f8377d0d7a7..d7feedf3c37 100644 --- a/analyzers/tests/SonarAnalyzer.UnitTest/Rules/RegularExpressions/RegexShouldNotContainMultipleSpacesTest.cs +++ b/analyzers/tests/SonarAnalyzer.Test/Rules/RegularExpressions/RegexShouldNotContainMultipleSpacesTest.cs @@ -1,6 +1,6 @@ /* * SonarAnalyzer for .NET - * Copyright (C) 2015-2023 SonarSource SA + * Copyright (C) 2015-2024 SonarSource SA * mailto: contact AT sonarsource DOT com * * This program is free software; you can redistribute it and/or @@ -21,7 +21,7 @@ using CS = SonarAnalyzer.Rules.CSharp; using VB = SonarAnalyzer.Rules.VisualBasic; -namespace SonarAnalyzer.UnitTest.Rules; +namespace SonarAnalyzer.Test.Rules; [TestClass] public class RegexShouldNotContainMultipleSpacesTest diff --git a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/RegularExpressions/RegexShouldNotContainMultipleSpaces.cs b/analyzers/tests/SonarAnalyzer.Test/TestCases/RegularExpressions/RegexShouldNotContainMultipleSpaces.cs similarity index 91% rename from analyzers/tests/SonarAnalyzer.UnitTest/TestCases/RegularExpressions/RegexShouldNotContainMultipleSpaces.cs rename to analyzers/tests/SonarAnalyzer.Test/TestCases/RegularExpressions/RegexShouldNotContainMultipleSpaces.cs index 9c192d67892..28c99723e3d 100644 --- a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/RegularExpressions/RegexShouldNotContainMultipleSpaces.cs +++ b/analyzers/tests/SonarAnalyzer.Test/TestCases/RegularExpressions/RegexShouldNotContainMultipleSpaces.cs @@ -45,6 +45,13 @@ bool WhiteSpaceVariations(string input) || Regex.IsMatch(input, "without_spaces") || Regex.IsMatch(input, "with\ttab") || Regex.IsMatch(input, "") + || Regex.IsMatch(input, "\x09 character tabulation") + || Regex.IsMatch(input, "\x0A line feed") + || Regex.IsMatch(input, "\x0B line tabulation") + || Regex.IsMatch(input, "\x0C form feed") + || Regex.IsMatch(input, "\x0D carriage feed") + || Regex.IsMatch(input, "\x85 next line") + || Regex.IsMatch(input, "\xA0 non-break space") || Regex.IsMatch(input, "ignore pattern white space", RegexOptions.IgnorePatternWhitespace); } } diff --git a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/RegularExpressions/RegexShouldNotContainMultipleSpaces.vb b/analyzers/tests/SonarAnalyzer.Test/TestCases/RegularExpressions/RegexShouldNotContainMultipleSpaces.vb similarity index 100% rename from analyzers/tests/SonarAnalyzer.UnitTest/TestCases/RegularExpressions/RegexShouldNotContainMultipleSpaces.vb rename to analyzers/tests/SonarAnalyzer.Test/TestCases/RegularExpressions/RegexShouldNotContainMultipleSpaces.vb diff --git a/analyzers/tests/SonarAnalyzer.UnitTest/Rules/RegularExpressions/RegexMustHaveValidSyntaxTest.cs b/analyzers/tests/SonarAnalyzer.UnitTest/Rules/RegularExpressions/RegexMustHaveValidSyntaxTest.cs deleted file mode 100644 index 56499a1d266..00000000000 --- a/analyzers/tests/SonarAnalyzer.UnitTest/Rules/RegularExpressions/RegexMustHaveValidSyntaxTest.cs +++ /dev/null @@ -1,57 +0,0 @@ -/* - * SonarAnalyzer for .NET - * Copyright (C) 2015-2023 SonarSource SA - * mailto: contact AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -using CS = SonarAnalyzer.Rules.CSharp; -using VB = SonarAnalyzer.Rules.VisualBasic; - -namespace SonarAnalyzer.UnitTest.Rules; - -[TestClass] -public class RegexMustHaveValidSyntaxTest -{ - private readonly VerifierBuilder builderCS = new VerifierBuilder() - .WithBasePath("RegularExpressions") - .AddReferences(MetadataReferenceFacade.RegularExpressions) - .AddReferences(NuGetMetadataReference.SystemComponentModelAnnotations()); - - private readonly VerifierBuilder builderVB = new VerifierBuilder() - .WithBasePath("RegularExpressions") - .AddReferences(MetadataReferenceFacade.RegularExpressions) - .AddReferences(NuGetMetadataReference.SystemComponentModelAnnotations()); - - [TestMethod] - public void RegexMustHaveValidSyntax_CS() => - builderCS.AddPaths("RegexMustHaveValidSyntax.cs").Verify(); - -#if NET - - [TestMethod] - public void RegexMustHaveValidSyntax_CSharp9() => - builderCS.AddPaths("RegexMustHaveValidSyntax.CSharp9.cs").WithOptions(ParseOptionsHelper.FromCSharp9).Verify(); - - [TestMethod] - public void RegexMustHaveValidSyntax_CSharp11() => - builderCS.AddPaths("RegexMustHaveValidSyntax.CSharp11.cs").WithOptions(ParseOptionsHelper.FromCSharp11).Verify(); -#endif - - [TestMethod] - public void RegexMustHaveValidSyntax_VB() => - builderVB.AddPaths("RegexMustHaveValidSyntax.vb").Verify(); -} From 0b040a9cedda33259de264abc6fe0d074e7ce230 Mon Sep 17 00:00:00 2001 From: Corniel Nobel Date: Wed, 20 Mar 2024 09:58:49 +0100 Subject: [PATCH 7/8] Error syntax. --- .../RegularExpressions/RegexShouldNotContainMultipleSpaces.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/analyzers/tests/SonarAnalyzer.Test/TestCases/RegularExpressions/RegexShouldNotContainMultipleSpaces.cs b/analyzers/tests/SonarAnalyzer.Test/TestCases/RegularExpressions/RegexShouldNotContainMultipleSpaces.cs index 28c99723e3d..7ad84d16f0c 100644 --- a/analyzers/tests/SonarAnalyzer.Test/TestCases/RegularExpressions/RegexShouldNotContainMultipleSpaces.cs +++ b/analyzers/tests/SonarAnalyzer.Test/TestCases/RegularExpressions/RegexShouldNotContainMultipleSpaces.cs @@ -127,7 +127,7 @@ class DoesNotCrash { bool UnknownVariable(string input) { - return Regex.IsMatch(input, "a" + undefined); // Error CS0103 The name 'undefined' does not exist in the current context + return Regex.IsMatch(input, "a" + undefined); // Error [CS0103] The name 'undefined' does not exist in the current context } } From 6600459edbdd7acff5f825e67e95b5d641b7831d Mon Sep 17 00:00:00 2001 From: Corniel Nobel Date: Wed, 31 Jul 2024 09:55:21 +0200 Subject: [PATCH 8/8] fix rebase --- analyzers/NuGet.Config | 40 +++++++++++++++++++ .../RegexMustHaveValidSyntaxBase.cs | 2 +- 2 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 analyzers/NuGet.Config diff --git a/analyzers/NuGet.Config b/analyzers/NuGet.Config new file mode 100644 index 00000000000..2b0930d2017 --- /dev/null +++ b/analyzers/NuGet.Config @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + protobuf-packages;Microsoft;sharwell;meirb;kzu;dotnetfoundation;castleproject;jonorossi;onovotny;fluentassertions;SteveGilham;jamesnk;commandlineparser;grpc-packages + + + + + + diff --git a/analyzers/src/SonarAnalyzer.Common/Rules/RegularExpressions/RegexMustHaveValidSyntaxBase.cs b/analyzers/src/SonarAnalyzer.Common/Rules/RegularExpressions/RegexMustHaveValidSyntaxBase.cs index 2498d339b16..b0d562f992e 100644 --- a/analyzers/src/SonarAnalyzer.Common/Rules/RegularExpressions/RegexMustHaveValidSyntaxBase.cs +++ b/analyzers/src/SonarAnalyzer.Common/Rules/RegularExpressions/RegexMustHaveValidSyntaxBase.cs @@ -35,7 +35,7 @@ protected sealed override void Analyze(SonarSyntaxNodeReportingContext context, { if (regexContext?.ParseError is { } error) { - c.ReportIssue(Rule, context.PatternNode, error.Message); + context.ReportIssue(Rule, regexContext.PatternNode, error.Message); } } }