-
Notifications
You must be signed in to change notification settings - Fork 20
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add SQL code analysis from PackageReference or ProjectReference (#479)
* Add test for project reference * Fix test * Add PackageReference test * Add missing TestData * Merge from main * Update DacFx version * Remove extra line
- Loading branch information
Showing
8 changed files
with
181 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
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
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,78 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
using System.Collections.Generic; | ||
using System.IO; | ||
using NUnit.Framework; | ||
|
||
namespace Microsoft.Build.Sql.Tests | ||
{ | ||
[TestFixture] | ||
public class CodeAnalysisTests : DotnetTestBase | ||
{ | ||
[Test] | ||
public void VerifyCodeAnalyzerFromProjectReference() | ||
{ | ||
// Copy the analyzer project to a temp folder | ||
string tempFolder = TestUtils.CreateTempDirectory(); | ||
TestUtils.CopyDirectoryRecursive(Path.Combine(this.CommonTestDataDirectory, "CodeAnalyzerSample"), tempFolder); | ||
|
||
// Add the analyzer csproj as a ProjectReference to the test sqlproj | ||
ProjectUtils.AddItemGroup(this.GetProjectFilePath(), "ProjectReference", | ||
new string[] { Path.Combine(tempFolder, "CodeAnalyzerSample.csproj") }, | ||
item => | ||
{ | ||
item.AddMetadata("PrivateAssets", "All"); | ||
item.AddMetadata("ReferenceOutputAssembly", "False"); | ||
item.AddMetadata("OutputItemType", "Analyzer"); | ||
item.AddMetadata("SetTargetFramework", "TargetFramework=netstandard2.1"); | ||
}); | ||
|
||
// Set up code analysis properties | ||
ProjectUtils.AddProperties(this.GetProjectFilePath(), new Dictionary<string, string>() | ||
{ | ||
{ "RunSqlCodeAnalysis", "true" }, | ||
{ "SqlCodeAnalysisRules", "+!CodeAnalyzerSample.TableNameRule001" } // Should fail build on this rule | ||
}); | ||
|
||
int exitCode = this.RunDotnetCommandOnProject("build", out string stdOutput, out string stdError); | ||
|
||
Assert.AreNotEqual(0, exitCode, "Build should have failed"); | ||
Assert.IsTrue(stdOutput.Contains("Table name [dbo].[NotAView] ends in View. This can cause confusion and should be avoided"), "Unexpected stderr"); | ||
} | ||
|
||
[Test] | ||
public void VerifyCodeAnalyzerFromPackageReference() | ||
{ | ||
// Set up and create the analyzer package | ||
string tempFolder = TestUtils.CreateTempDirectory(); | ||
TestUtils.CopyDirectoryRecursive(Path.Combine(CommonTestDataDirectory, "CodeAnalyzerSample"), tempFolder); | ||
RunGenericDotnetCommand($"pack {Path.Combine(tempFolder, "CodeAnalyzerSample.csproj")} -o {tempFolder}", out _, out _); | ||
|
||
// Copy analyzer package to local Nuget source | ||
string analyzerPackagePath = Path.Combine(tempFolder, "CodeAnalyzerSample.1.0.0.nupkg"); | ||
FileAssert.Exists(analyzerPackagePath); | ||
File.Copy(analyzerPackagePath, Path.Combine(WorkingDirectory, "pkg", "CodeAnalyzerSample.1.0.0.nupkg")); | ||
|
||
// Add the analyzer package as a PackageReference to the test sqlproj | ||
ProjectUtils.AddItemGroup(this.GetProjectFilePath(), "PackageReference", | ||
new string[] { "CodeAnalyzerSample" }, | ||
item => | ||
{ | ||
item.AddMetadata("Version", "1.0.0"); | ||
}); | ||
|
||
// Set up code analysis properties | ||
ProjectUtils.AddProperties(this.GetProjectFilePath(), new Dictionary<string, string>() | ||
{ | ||
{ "RunSqlCodeAnalysis", "true" }, | ||
{ "SqlCodeAnalysisRules", "+!CodeAnalyzerSample.TableNameRule001" } // Should fail build on this rule | ||
}); | ||
|
||
int exitCode = this.RunDotnetCommandOnProject("build", out string stdOutput, out string stdError); | ||
|
||
Assert.AreNotEqual(0, exitCode, "Build should have failed"); | ||
Assert.IsTrue(stdOutput.Contains("Table name [dbo].[NotAView] ends in View. This can cause confusion and should be avoided"), "Unexpected stderr"); | ||
} | ||
} | ||
} |
16 changes: 16 additions & 0 deletions
16
test/Microsoft.Build.Sql.Tests/TestData/CodeAnalyzerSample/CodeAnalyzerSample.csproj
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,16 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
<PropertyGroup> | ||
<OutputType>Library</OutputType> | ||
<TargetFrameworks>netstandard2.1</TargetFrameworks> | ||
<TargetsForTfmSpecificContentInPackage>$(TargetsForTfmSpecificContentInPackage);_AddAnalyzersToOutput</TargetsForTfmSpecificContentInPackage> | ||
</PropertyGroup> | ||
<ItemGroup> | ||
<PackageReference Include="Microsoft.SqlServer.DacFx" Version="162.3.566" PrivateAssets="all" /> | ||
</ItemGroup> | ||
<Target Name="GetTargetPath" /> | ||
<Target Name="_AddAnalyzersToOutput"> | ||
<ItemGroup> | ||
<TfmSpecificPackageFile Include="$(OutputPath)\CodeAnalyzerSample.dll" PackagePath="analyzers/dotnet/cs" /> | ||
</ItemGroup> | ||
</Target> | ||
</Project> |
73 changes: 73 additions & 0 deletions
73
test/Microsoft.Build.Sql.Tests/TestData/CodeAnalyzerSample/TableNameEndingInViewRule.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,73 @@ | ||
//------------------------------------------------------------------------------ | ||
// <copyright> | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// </copyright> | ||
//---------------------------------------------------------------------------- | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using Microsoft.SqlServer.Dac.Extensibility; | ||
using Microsoft.SqlServer.Dac.CodeAnalysis; | ||
using Microsoft.SqlServer.Dac.Model; | ||
|
||
namespace CodeAnalyzerSample | ||
{ | ||
|
||
/// <summary> | ||
/// Simple test class - note it doesn't use resources since these aren't handled by the test harness | ||
/// that builds dll files | ||
/// </summary> | ||
[ExportCodeAnalysisRule("CodeAnalyzerSample.TableNameRule001", | ||
"SampleRule", | ||
Description = "Table names should not end in 'View'", | ||
Category = "Naming", | ||
PlatformCompatibility = TSqlPlatformCompatibility.OnPremises)] | ||
class TableNameEndingInViewRule : SqlCodeAnalysisRule | ||
{ | ||
private static readonly ModelTypeClass[] _supportedElementTypes = new[] { ModelSchema.Table }; | ||
|
||
public TableNameEndingInViewRule() | ||
{ | ||
SupportedElementTypes = new[] { Table.TypeClass }; | ||
} | ||
|
||
public override IList<SqlRuleProblem> Analyze(SqlRuleExecutionContext ruleExecutionContext) | ||
{ | ||
List<SqlRuleProblem> problems = new List<SqlRuleProblem>(); | ||
|
||
TSqlObject table = ruleExecutionContext.ModelElement; | ||
if (table != null) | ||
{ | ||
if (NameEndsInView(table.Name)) | ||
{ | ||
string problemDescription = string.Format("Table name {0} ends in View. This can cause confusion and should be avoided", | ||
GetQualifiedTableName(table.Name)); | ||
SqlRuleProblem problem = new SqlRuleProblem(problemDescription, table); | ||
problems.Add(problem); | ||
} | ||
} | ||
|
||
return problems; | ||
} | ||
|
||
private bool NameEndsInView(ObjectIdentifier id) | ||
{ | ||
return id.HasName && id.Parts.Last().EndsWith("View", StringComparison.OrdinalIgnoreCase); | ||
} | ||
|
||
private string GetQualifiedTableName(ObjectIdentifier id) | ||
{ | ||
StringBuilder buf = new StringBuilder(); | ||
foreach (string part in id.Parts) | ||
{ | ||
if (buf.Length > 0) | ||
{ | ||
buf.Append('.'); | ||
} | ||
buf.Append('[').Append(part).Append(']'); | ||
} | ||
return buf.ToString(); | ||
} | ||
} | ||
} |
3 changes: 3 additions & 0 deletions
3
test/Microsoft.Build.Sql.Tests/TestData/VerifyCodeAnalyzerFromPackageReference/NotAView.sql
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,3 @@ | ||
CREATE TABLE NotAView ( | ||
Col VARCHAR(255) | ||
) |
3 changes: 3 additions & 0 deletions
3
test/Microsoft.Build.Sql.Tests/TestData/VerifyCodeAnalyzerFromProjectReference/NotAView.sql
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,3 @@ | ||
CREATE TABLE NotAView ( | ||
Col VARCHAR(255) | ||
) |