Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ability to treat rule violations as errors #523

Merged
merged 2 commits into from
Feb 29, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -542,15 +542,17 @@ Static code analysis can be enabled by adding the following to the project file:
<Project Sdk="MSBuild.Sdk.SqlProj/2.7.0">
<PropertyGroup>
<RunSqlCodeAnalysis>True</RunSqlCodeAnalysis>
<CodeAnalysisRules>-SqlServer.Rules.SRD0006;-Smells.*</CodeAnalysisRules>
<CodeAnalysisRules>-SqlServer.Rules.SRD0006;-Smells.*;+!SqlServer.Rules.SRN0005</CodeAnalysisRules>
ErikEJ marked this conversation as resolved.
Show resolved Hide resolved
</PropertyGroup>
</Project>
```
The optional `CodeAnalysisRules` property allows you to disable individual rules or groups of rules.

A xml file with the analysis results is created in the output folder, and any problems found during analysis are reported as build warnings.
Any rule violations found during analysis are reported as build warnings.

`TreatWarningsAsErrors` does not affect found problems.
This syntax in the `CodeAnalysisRules` property: `+!SqlServer.Rules.SRN0005` forces a rule violation to be treated as a build error.

A xml file with the analysis results is created in the output folder,

## Workaround for parser errors (SQL46010)
This project relies on the publicly available T-SQL parser which may not support all T-SQL syntax constructions. Therefore you might encounter a SQL46010 error if you have a script file that contains unsupported syntax. If that happens, there's a couple of workarounds you can try:
Expand Down
13 changes: 11 additions & 2 deletions src/DacpacTool/PackageAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public sealed class PackageAnalyzer
private readonly IConsole _console;
private readonly HashSet<string> _ignoredRules = new();
private readonly HashSet<string> _ignoredRuleSets = new();
private readonly HashSet<string> _errorRuleSets = new();

public PackageAnalyzer(IConsole console, string rulesExpression)
{
Expand Down Expand Up @@ -49,7 +50,7 @@ public void Analyze(TSqlModel model, FileInfo outputFile)
{
foreach (var err in result.Problems)
{
_console.WriteLine(err.GetOutputMessage());
_console.WriteLine(err.GetOutputMessage(_errorRuleSets));
}

result.SerializeResultsToXml(GetOutputFileName(outputFile));
Expand All @@ -72,7 +73,7 @@ private void BuildRuleLists(string rulesExpression)
.StartsWith("-", StringComparison.OrdinalIgnoreCase)
&& rule.Length > 1))
{
if (rule.EndsWith("*", StringComparison.OrdinalIgnoreCase))
if (rule.Length > 2 && rule.EndsWith("*", StringComparison.OrdinalIgnoreCase))
{
_ignoredRuleSets.Add(rule[1..^1]);
}
Expand All @@ -81,6 +82,14 @@ private void BuildRuleLists(string rulesExpression)
_ignoredRules.Add(rule[1..]);
}
}
foreach (var rule in rulesExpression.Split(new[] { ';' },
StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
.Where(rule => rule
.StartsWith("+!", StringComparison.OrdinalIgnoreCase)
&& rule.Length > 2))
{
_errorRuleSets.Add(rule[2..]);
}
}
}

Expand Down
12 changes: 10 additions & 2 deletions src/DacpacTool/SqlRuleProblemExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.SqlServer.Dac.CodeAnalysis;

Expand All @@ -9,9 +10,16 @@ namespace MSBuild.Sdk.SqlProj.DacpacTool
/// </summary>
public static class SqlRuleProblemExtensions
{
public static string GetOutputMessage(this SqlRuleProblem sqlRuleProblem)
public static string GetOutputMessage(this SqlRuleProblem sqlRuleProblem, HashSet<string> errorRules)
{
ArgumentNullException.ThrowIfNull(sqlRuleProblem);

SqlRuleProblemSeverity sqlRuleProblemSeverity = sqlRuleProblem.Severity;

if (errorRules.Contains(sqlRuleProblem.RuleId))
{
sqlRuleProblemSeverity = SqlRuleProblemSeverity.Error;
}

var stringBuilder = new StringBuilder();
stringBuilder.Append(sqlRuleProblem.SourceName);
Expand All @@ -21,7 +29,7 @@ public static string GetOutputMessage(this SqlRuleProblem sqlRuleProblem)
stringBuilder.Append(sqlRuleProblem.StartColumn);
stringBuilder.Append("):");
stringBuilder.Append(' ');
stringBuilder.Append(sqlRuleProblem.Severity);
stringBuilder.Append(sqlRuleProblemSeverity);
stringBuilder.Append(' ');
stringBuilder.Append(sqlRuleProblem.ErrorMessageString);

Expand Down
10 changes: 6 additions & 4 deletions test/DacpacTool.Tests/PackageAnalyzerTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.IO;
using System.Linq;
using Microsoft.SqlServer.Dac.Model;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Shouldly;
Expand Down Expand Up @@ -38,7 +39,7 @@ public void RunsAnalyzerWithSupressions()
var testConsole = (TestConsole)_console;
testConsole.Lines.Clear();
var result = BuildSimpleModel();
var packageAnalyzer = new PackageAnalyzer(_console, "-SqlServer.Rules.SRD0006;-Smells.SML005;-SqlServer.Rules.SRD999;;");
var packageAnalyzer = new PackageAnalyzer(_console, "-SqlServer.Rules.SRD0006;-Smells.SML005;-SqlServer.Rules.SRD999;+!SqlServer.Rules.SRN0002;");

// Act
packageAnalyzer.Analyze(result.model, result.fileInfo);
Expand All @@ -47,8 +48,9 @@ public void RunsAnalyzerWithSupressions()
testConsole.Lines.Count.ShouldBe(13);

testConsole.Lines.ShouldContain($"Analyzing package '{result.fileInfo.FullName}'");
testConsole.Lines.ShouldNotContain($"SRD0006");
testConsole.Lines.ShouldNotContain($"SML005");
testConsole.Lines.Any(l => l.Contains("SRD0006")).ShouldBeFalse();
testConsole.Lines.Any(l => l.Contains("SML0005")).ShouldBeFalse();
testConsole.Lines.Any(l => l.Contains("Error SRN0002")).ShouldBeTrue();
testConsole.Lines.ShouldContain($"Successfully analyzed package '{result.fileInfo.FullName}'");
}

Expand All @@ -68,7 +70,7 @@ public void RunsAnalyzerWithWildcardSupressions()
testConsole.Lines.Count.ShouldBe(13);

testConsole.Lines.ShouldContain($"Analyzing package '{result.fileInfo.FullName}'");
testConsole.Lines.ShouldNotContain($"SRD");
testConsole.Lines.Any(l => l.Contains("SRD")).ShouldBeFalse();
testConsole.Lines.ShouldContain($"Successfully analyzed package '{result.fileInfo.FullName}'");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<TargetFramework>netstandard2.0</TargetFramework>
<SqlServerVersion>Sql150</SqlServerVersion>
<RunSqlCodeAnalysis>True</RunSqlCodeAnalysis>
<CodeAnalysisRules>-SqlServer.Rules.SRD0006;-Smells.*</CodeAnalysisRules>
<CodeAnalysisRules>-SqlServer.Rules.SRD0006;-Smells.*;+!SqlServer.Rules.SRN0002</CodeAnalysisRules>
</PropertyGroup>

<Import Project="$(MSBuildThisFileDirectory)..\..\src\MSBuild.Sdk.SqlProj\Sdk\Sdk.targets" />
Expand Down