Skip to content

Commit

Permalink
Introduction of a base class.
Browse files Browse the repository at this point in the history
  • Loading branch information
Corniel committed Jul 20, 2023
1 parent 990ac77 commit 63af105
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 47 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
Original file line number Diff line number Diff line change
@@ -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<TSyntaxKind> : SonarDiagnosticAnalyzer<TSyntaxKind>
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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

namespace SonarAnalyzer.Rules;

public abstract class RegexMustHaveValidSyntaxBase<TSyntaxKind> : SonarDiagnosticAnalyzer<TSyntaxKind>
public abstract class RegexMustHaveValidSyntaxBase<TSyntaxKind> : RegexAnalyzerBase<TSyntaxKind>
where TSyntaxKind : struct
{
private const string DiagnosticId = "S5856";
Expand All @@ -31,29 +31,11 @@ public abstract class RegexMustHaveValidSyntaxBase<TSyntaxKind> : 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(Diagnostic.Create(Rule, context.PatternNode.GetLocation(), error.Message));
context.ReportIssue(Diagnostic.Create(Rule, regexContext.PatternNode.GetLocation(), error.Message));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

namespace SonarAnalyzer.Rules;

public abstract class RegexShouldNotContainMultipleSpacesBase<TSyntaxKind> : SonarDiagnosticAnalyzer<TSyntaxKind>
public abstract class RegexShouldNotContainMultipleSpacesBase<TSyntaxKind> : RegexAnalyzerBase<TSyntaxKind>
where TSyntaxKind : struct
{
private const string DiagnosticId = "S6326";
Expand All @@ -32,31 +32,13 @@ public abstract class RegexShouldNotContainMultipleSpacesBase<TSyntaxKind> : 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()));
}
}

Expand Down

0 comments on commit 63af105

Please sign in to comment.