-
Notifications
You must be signed in to change notification settings - Fork 229
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement S6326 for both C# and VB.NET.
- Loading branch information
Corniel Nobel
committed
Jun 7, 2023
1 parent
a720d7f
commit b1d2709
Showing
10 changed files
with
347 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
27 changes: 27 additions & 0 deletions
27
.../src/SonarAnalyzer.CSharp/Rules/RegularExpressions/RegexShouldNotContainMultipleSpaces.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<SyntaxKind> | ||
{ | ||
protected override ILanguageFacade<SyntaxKind> Language => CSharpFacade.Instance; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
66 changes: 66 additions & 0 deletions
66
.../SonarAnalyzer.Common/Rules/RegularExpressions/RegexShouldNotContainMultipleSpacesBase.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<TSyntaxKind> : SonarDiagnosticAnalyzer<TSyntaxKind> | ||
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); | ||
} |
27 changes: 27 additions & 0 deletions
27
...SonarAnalyzer.VisualBasic/Rules/RegularExpressions/RegexShouldNotContainMultipleSpaces.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<SyntaxKind> | ||
{ | ||
protected override ILanguageFacade<SyntaxKind> Language => VisualBasicFacade.Instance; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
46 changes: 46 additions & 0 deletions
46
...onarAnalyzer.UnitTest/Rules/RegularExpressions/RegexShouldNotContainMultipleSpacesTest.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<CS.RegexShouldNotContainMultipleSpaces>() | ||
.WithBasePath("RegularExpressions") | ||
.AddReferences(MetadataReferenceFacade.RegularExpressions) | ||
.AddReferences(NuGetMetadataReference.SystemComponentModelAnnotations()); | ||
|
||
private readonly VerifierBuilder builderVB = new VerifierBuilder<VB.RegexShouldNotContainMultipleSpaces>() | ||
.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(); | ||
} |
124 changes: 124 additions & 0 deletions
124
...onarAnalyzer.UnitTest/TestCases/RegularExpressions/RegexShouldNotContainMultipleSpaces.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; } | ||
} |
34 changes: 34 additions & 0 deletions
34
...onarAnalyzer.UnitTest/TestCases/RegularExpressions/RegexShouldNotContainMultipleSpaces.vb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
|
||
<RegularExpression("single space")> | ||
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 | ||
|
||
<RegularExpression("multiple white spaces")> ' Noncompliant | ||
Public Property Attribute As String | ||
End Class |