Skip to content

Commit

Permalink
Merge pull request #1739 from OmniSharp/feature/runanalyzers
Browse files Browse the repository at this point in the history
Support for `<RunAnalyzers />` and `<RunAnalyzersDuringLiveAnalysis />`
  • Loading branch information
filipw authored Mar 26, 2020
2 parents 40156eb + 15d536a commit 3163c23
Show file tree
Hide file tree
Showing 12 changed files with 101 additions and 5 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# Changelog
All changes to the project will be documented in this file.

## [1.34.16] - not yet released
* Support for `<RunAnalyzers />` and `<RunAnalyzersDuringLiveAnalysis />` (PR: [#1739](https://github.com/OmniSharp/omnisharp-roslyn/pull/1739))

## [1.34.15] - 2020-03-25
* Support for .NET Core 3.1 in csx files (PR: [#1731](https://github.com/OmniSharp/omnisharp-roslyn/pull/1731))
* Update the minimal MSBuild to better support .NET 5 Previews ([omnisharp-vscode#3653](https://github.com/OmniSharp/omnisharp-vscode/issues/3653), PR: [#1746](https://github.com/OmniSharp/omnisharp-roslyn/pull/1746))
Expand Down
5 changes: 4 additions & 1 deletion build.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@
"ProjectWithMultiTFMLib",
"ExternAlias",
"ProjectWithComplexAnalyzers",
"ProjectWithDisabledAnalyzers",
"ProjectWithDisabledAnalyzers2",
"ProjectWithAnalyzers",
"NetCore30Project",
"Net50Project"
],
Expand All @@ -50,4 +53,4 @@
"RestoreOnlyTestAssets": [
"ProjectWithMissingType"
]
}
}
19 changes: 16 additions & 3 deletions src/OmniSharp.MSBuild/ProjectFile/ProjectFileInfo.ProjectData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ private class ProjectData
public ImmutableDictionary<string, string> ReferenceAliases { get; }
public ImmutableDictionary<string, string> ProjectReferenceAliases { get; }
public bool TreatWarningsAsErrors { get; }
public bool RunAnalyzers { get; }
public bool RunAnalyzersDuringLiveAnalysis { get; }
public string DefaultNamespace { get; }

private ProjectData()
Expand Down Expand Up @@ -91,6 +93,8 @@ private ProjectData(
string assemblyOriginatorKeyFile,
bool treatWarningsAsErrors,
string defaultNamespace,
bool runAnalyzers,
bool runAnalyzersDuringLiveAnalysis,
RuleSet ruleset)
: this()
{
Expand Down Expand Up @@ -122,6 +126,9 @@ private ProjectData(
TreatWarningsAsErrors = treatWarningsAsErrors;
RuleSet = ruleset;
DefaultNamespace = defaultNamespace;

RunAnalyzers = runAnalyzers;
RunAnalyzersDuringLiveAnalysis = runAnalyzersDuringLiveAnalysis;
}

private ProjectData(
Expand Down Expand Up @@ -149,12 +156,14 @@ private ProjectData(
ImmutableArray<string> additionalFiles,
bool treatWarningsAsErrors,
string defaultNamespace,
bool runAnalyzers,
bool runAnalyzersDuringLiveAnalysis,
RuleSet ruleset,
ImmutableDictionary<string, string> referenceAliases,
ImmutableDictionary<string, string> projectReferenceAliases)
: this(guid, name, assemblyName, targetPath, outputPath, intermediateOutputPath, projectAssetsFile,
configuration, platform, targetFramework, targetFrameworks, outputKind, languageVersion, nullableContextOptions, allowUnsafeCode, checkForOverflowUnderflow,
documentationFile, preprocessorSymbolNames, suppressedDiagnosticIds, signAssembly, assemblyOriginatorKeyFile, treatWarningsAsErrors, defaultNamespace, ruleset)
documentationFile, preprocessorSymbolNames, suppressedDiagnosticIds, signAssembly, assemblyOriginatorKeyFile, treatWarningsAsErrors, defaultNamespace, runAnalyzers, runAnalyzersDuringLiveAnalysis, ruleset)
{
SourceFiles = sourceFiles.EmptyIfDefault();
ProjectReferences = projectReferences.EmptyIfDefault();
Expand Down Expand Up @@ -200,11 +209,13 @@ public static ProjectData Create(MSB.Evaluation.Project project)
var signAssembly = PropertyConverter.ToBoolean(project.GetPropertyValue(PropertyNames.SignAssembly), defaultValue: false);
var assemblyOriginatorKeyFile = project.GetPropertyValue(PropertyNames.AssemblyOriginatorKeyFile);
var treatWarningsAsErrors = PropertyConverter.ToBoolean(project.GetPropertyValue(PropertyNames.TreatWarningsAsErrors), defaultValue: false);
var runAnalyzers = PropertyConverter.ToBoolean(project.GetPropertyValue(PropertyNames.RunAnalyzers), defaultValue: true);
var runAnalyzersDuringLiveAnalysis = PropertyConverter.ToBoolean(project.GetPropertyValue(PropertyNames.RunAnalyzersDuringLiveAnalysis), defaultValue: true);

return new ProjectData(
guid, name, assemblyName, targetPath, outputPath, intermediateOutputPath, projectAssetsFile,
configuration, platform, targetFramework, targetFrameworks, outputKind, languageVersion, nullableContextOptions, allowUnsafeCode, checkForOverflowUnderflow,
documentationFile, preprocessorSymbolNames, suppressedDiagnosticIds, signAssembly, assemblyOriginatorKeyFile, treatWarningsAsErrors, defaultNamespace, ruleset: null);
documentationFile, preprocessorSymbolNames, suppressedDiagnosticIds, signAssembly, assemblyOriginatorKeyFile, treatWarningsAsErrors, defaultNamespace, runAnalyzers, runAnalyzersDuringLiveAnalysis, ruleset: null);
}

public static ProjectData Create(MSB.Execution.ProjectInstance projectInstance)
Expand Down Expand Up @@ -240,6 +251,8 @@ public static ProjectData Create(MSB.Execution.ProjectInstance projectInstance)
var suppressedDiagnosticIds = PropertyConverter.ToSuppressedDiagnosticIds(projectInstance.GetPropertyValue(PropertyNames.NoWarn));
var signAssembly = PropertyConverter.ToBoolean(projectInstance.GetPropertyValue(PropertyNames.SignAssembly), defaultValue: false);
var treatWarningsAsErrors = PropertyConverter.ToBoolean(projectInstance.GetPropertyValue(PropertyNames.TreatWarningsAsErrors), defaultValue: false);
var runAnalyzers = PropertyConverter.ToBoolean(projectInstance.GetPropertyValue(PropertyNames.RunAnalyzers), defaultValue: true);
var runAnalyzersDuringLiveAnalysis = PropertyConverter.ToBoolean(projectInstance.GetPropertyValue(PropertyNames.RunAnalyzersDuringLiveAnalysis), defaultValue: true);
var assemblyOriginatorKeyFile = projectInstance.GetPropertyValue(PropertyNames.AssemblyOriginatorKeyFile);

var ruleset = ResolveRulesetIfAny(projectInstance);
Expand Down Expand Up @@ -310,7 +323,7 @@ public static ProjectData Create(MSB.Execution.ProjectInstance projectInstance)
configuration, platform, targetFramework, targetFrameworks,
outputKind, languageVersion, nullableContextOptions, allowUnsafeCode, checkForOverflowUnderflow, documentationFile, preprocessorSymbolNames, suppressedDiagnosticIds,
signAssembly, assemblyOriginatorKeyFile,
sourceFiles, projectReferences.ToImmutable(), references.ToImmutable(), packageReferences, analyzers, additionalFiles, treatWarningsAsErrors, defaultNamespace, ruleset,
sourceFiles, projectReferences.ToImmutable(), references.ToImmutable(), packageReferences, analyzers, additionalFiles, treatWarningsAsErrors, defaultNamespace, runAnalyzers, runAnalyzersDuringLiveAnalysis, ruleset,
referenceAliases.ToImmutableDictionary(), projectReferenceAliases.ToImmutable());
}

Expand Down
2 changes: 2 additions & 0 deletions src/OmniSharp.MSBuild/ProjectFile/ProjectFileInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ internal partial class ProjectFileInfo
public ImmutableDictionary<string, string> ReferenceAliases => _data.ReferenceAliases;
public ImmutableDictionary<string, string> ProjectReferenceAliases => _data.ProjectReferenceAliases;
public bool TreatWarningsAsErrors => _data.TreatWarningsAsErrors;
public bool RunAnalyzers => _data.RunAnalyzers;
public bool RunAnalyzersDuringLiveAnalysis => _data.RunAnalyzersDuringLiveAnalysis;
public string DefaultNamespace => _data.DefaultNamespace;

public ProjectIdInfo ProjectIdInfo { get; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,11 @@ public static ProjectInfo CreateProjectInfo(this ProjectFileInfo projectFileInfo

private static IEnumerable<AnalyzerReference> ResolveAnalyzerReferencesForProject(ProjectFileInfo projectFileInfo, IAnalyzerAssemblyLoader analyzerAssemblyLoader)
{
if (!projectFileInfo.RunAnalyzers || !projectFileInfo.RunAnalyzersDuringLiveAnalysis)
{
return Enumerable.Empty<AnalyzerReference>();
}

foreach(var analyzerAssemblyPath in projectFileInfo.Analyzers.Distinct())
{
analyzerAssemblyLoader.AddDependencyLocation(analyzerAssemblyPath);
Expand Down
2 changes: 2 additions & 0 deletions src/OmniSharp.MSBuild/ProjectFile/PropertyNames.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ internal static class PropertyNames
public const string _ResolveReferenceDependencies = nameof(_ResolveReferenceDependencies);
public const string RootNamespace = nameof(RootNamespace);
public const string RoslynTargetsPath = nameof(RoslynTargetsPath);
public const string RunAnalyzers = nameof(RunAnalyzers);
public const string RunAnalyzersDuringLiveAnalysis = nameof(RunAnalyzersDuringLiveAnalysis);
public const string SignAssembly = nameof(SignAssembly);
public const string SkipCompilerExecution = nameof(SkipCompilerExecution);
public const string SolutionDir = nameof(SolutionDir);
Expand Down
6 changes: 6 additions & 0 deletions src/OmniSharp.MSBuild/ProjectManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,12 @@ private void UpdateProject(string projectFilePath)

private void UpdateAnalyzerReferences(Project project, ProjectFileInfo projectFileInfo)
{
if (!projectFileInfo.RunAnalyzers || !projectFileInfo.RunAnalyzersDuringLiveAnalysis)
{
_workspace.SetAnalyzerReferences(project.Id, ImmutableArray<AnalyzerFileReference>.Empty);
return;
}

var analyzerFileReferences = projectFileInfo.Analyzers
.Select(analyzerReferencePath => new AnalyzerFileReference(analyzerReferencePath, _analyzerAssemblyLoader))
.ToImmutableArray();
Expand Down
12 changes: 12 additions & 0 deletions test-assets/test-projects/ProjectWithDisabledAnalyzers/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using System;

namespace HelloWorld
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.1</TargetFramework>
<RestorePackagesPath>./nugets/</RestorePackagesPath>
<RunAnalyzers>false</RunAnalyzers>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118" />
</ItemGroup>
</Project>
12 changes: 12 additions & 0 deletions test-assets/test-projects/ProjectWithDisabledAnalyzers2/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using System;

namespace HelloWorld
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.1</TargetFramework>
<RestorePackagesPath>./nugets/</RestorePackagesPath>
<RunAnalyzersDuringLiveAnalysis>false</RunAnalyzersDuringLiveAnalysis>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118" />
</ItemGroup>
</Project>
16 changes: 15 additions & 1 deletion tests/OmniSharp.MSBuild.Tests/ProjectWithAnalyzersTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,28 @@ public async Task WhenProjectHasAnalyzersItDoesntLockAnalyzerDlls()
public async Task WhenProjectIsLoadedThenItContainsCustomRulesetsFromCsproj()
{
using (var testProject = await TestAssets.Instance.GetTestProjectAsync("ProjectWithAnalyzers"))
using (var host = CreateMSBuildTestHost(testProject.Directory))
using (var host = CreateMSBuildTestHost(testProject.Directory, configurationData: TestHelpers.GetConfigurationDataWithAnalyzerConfig(roslynAnalyzersEnabled: true)))
{
var project = host.Workspace.CurrentSolution.Projects.Single();

Assert.Contains(project.CompilationOptions.SpecificDiagnosticOptions, x => x.Key == "CA1021" && x.Value == ReportDiagnostic.Warn);
}
}

[Theory]
[InlineData("ProjectWithDisabledAnalyzers")]
[InlineData("ProjectWithDisabledAnalyzers2")]
public async Task WhenProjectWithRunAnalyzersDisabledIsLoadedThenAnalyzersAreIgnored(string projectName)
{
using var testProject = await TestAssets.Instance.GetTestProjectAsync(projectName);
await RestoreProject(testProject);

using var host = CreateMSBuildTestHost(testProject.Directory, configurationData: TestHelpers.GetConfigurationDataWithAnalyzerConfig(roslynAnalyzersEnabled: true));
var analyzerReferences = host.Workspace.CurrentSolution.Projects.Single().AnalyzerReferences.ToList();

Assert.Empty(analyzerReferences);
}

[Fact]
public async Task WhenProjectRulesetFileIsChangedThenUpdateRulesAccordingly()
{
Expand Down

0 comments on commit 3163c23

Please sign in to comment.