diff --git a/CHANGELOG.md b/CHANGELOG.md index 31082aa6fb..ed4d1db3ee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Changelog All changes to the project will be documented in this file. +## [1.34.16] - not yet released +* Support for `` and `` (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)) diff --git a/build.json b/build.json index 7301822d3e..8c09180fe8 100644 --- a/build.json +++ b/build.json @@ -38,6 +38,9 @@ "ProjectWithMultiTFMLib", "ExternAlias", "ProjectWithComplexAnalyzers", + "ProjectWithDisabledAnalyzers", + "ProjectWithDisabledAnalyzers2", + "ProjectWithAnalyzers", "NetCore30Project", "Net50Project" ], @@ -50,4 +53,4 @@ "RestoreOnlyTestAssets": [ "ProjectWithMissingType" ] -} \ No newline at end of file +} diff --git a/src/OmniSharp.MSBuild/ProjectFile/ProjectFileInfo.ProjectData.cs b/src/OmniSharp.MSBuild/ProjectFile/ProjectFileInfo.ProjectData.cs index 1e6aa214ee..6602d98f64 100644 --- a/src/OmniSharp.MSBuild/ProjectFile/ProjectFileInfo.ProjectData.cs +++ b/src/OmniSharp.MSBuild/ProjectFile/ProjectFileInfo.ProjectData.cs @@ -53,6 +53,8 @@ private class ProjectData public ImmutableDictionary ReferenceAliases { get; } public ImmutableDictionary ProjectReferenceAliases { get; } public bool TreatWarningsAsErrors { get; } + public bool RunAnalyzers { get; } + public bool RunAnalyzersDuringLiveAnalysis { get; } public string DefaultNamespace { get; } private ProjectData() @@ -91,6 +93,8 @@ private ProjectData( string assemblyOriginatorKeyFile, bool treatWarningsAsErrors, string defaultNamespace, + bool runAnalyzers, + bool runAnalyzersDuringLiveAnalysis, RuleSet ruleset) : this() { @@ -122,6 +126,9 @@ private ProjectData( TreatWarningsAsErrors = treatWarningsAsErrors; RuleSet = ruleset; DefaultNamespace = defaultNamespace; + + RunAnalyzers = runAnalyzers; + RunAnalyzersDuringLiveAnalysis = runAnalyzersDuringLiveAnalysis; } private ProjectData( @@ -149,12 +156,14 @@ private ProjectData( ImmutableArray additionalFiles, bool treatWarningsAsErrors, string defaultNamespace, + bool runAnalyzers, + bool runAnalyzersDuringLiveAnalysis, RuleSet ruleset, ImmutableDictionary referenceAliases, ImmutableDictionary 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(); @@ -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) @@ -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); @@ -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()); } diff --git a/src/OmniSharp.MSBuild/ProjectFile/ProjectFileInfo.cs b/src/OmniSharp.MSBuild/ProjectFile/ProjectFileInfo.cs index 1d7177847b..2d9651af76 100644 --- a/src/OmniSharp.MSBuild/ProjectFile/ProjectFileInfo.cs +++ b/src/OmniSharp.MSBuild/ProjectFile/ProjectFileInfo.cs @@ -55,6 +55,8 @@ internal partial class ProjectFileInfo public ImmutableDictionary ReferenceAliases => _data.ReferenceAliases; public ImmutableDictionary 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; } diff --git a/src/OmniSharp.MSBuild/ProjectFile/ProjectFileInfoExtensions.cs b/src/OmniSharp.MSBuild/ProjectFile/ProjectFileInfoExtensions.cs index ada58e331a..d983e7655e 100644 --- a/src/OmniSharp.MSBuild/ProjectFile/ProjectFileInfoExtensions.cs +++ b/src/OmniSharp.MSBuild/ProjectFile/ProjectFileInfoExtensions.cs @@ -76,6 +76,11 @@ public static ProjectInfo CreateProjectInfo(this ProjectFileInfo projectFileInfo private static IEnumerable ResolveAnalyzerReferencesForProject(ProjectFileInfo projectFileInfo, IAnalyzerAssemblyLoader analyzerAssemblyLoader) { + if (!projectFileInfo.RunAnalyzers || !projectFileInfo.RunAnalyzersDuringLiveAnalysis) + { + return Enumerable.Empty(); + } + foreach(var analyzerAssemblyPath in projectFileInfo.Analyzers.Distinct()) { analyzerAssemblyLoader.AddDependencyLocation(analyzerAssemblyPath); diff --git a/src/OmniSharp.MSBuild/ProjectFile/PropertyNames.cs b/src/OmniSharp.MSBuild/ProjectFile/PropertyNames.cs index d28f8e1a49..2b1f0806f5 100644 --- a/src/OmniSharp.MSBuild/ProjectFile/PropertyNames.cs +++ b/src/OmniSharp.MSBuild/ProjectFile/PropertyNames.cs @@ -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); diff --git a/src/OmniSharp.MSBuild/ProjectManager.cs b/src/OmniSharp.MSBuild/ProjectManager.cs index 6be793bfec..d14b8bd723 100644 --- a/src/OmniSharp.MSBuild/ProjectManager.cs +++ b/src/OmniSharp.MSBuild/ProjectManager.cs @@ -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.Empty); + return; + } + var analyzerFileReferences = projectFileInfo.Analyzers .Select(analyzerReferencePath => new AnalyzerFileReference(analyzerReferencePath, _analyzerAssemblyLoader)) .ToImmutableArray(); diff --git a/test-assets/test-projects/ProjectWithDisabledAnalyzers/Program.cs b/test-assets/test-projects/ProjectWithDisabledAnalyzers/Program.cs new file mode 100644 index 0000000000..8168c80511 --- /dev/null +++ b/test-assets/test-projects/ProjectWithDisabledAnalyzers/Program.cs @@ -0,0 +1,12 @@ +using System; + +namespace HelloWorld +{ + class Program + { + static void Main(string[] args) + { + Console.WriteLine("Hello World!"); + } + } +} diff --git a/test-assets/test-projects/ProjectWithDisabledAnalyzers/ProjectWithDisabledAnalyzers.csproj b/test-assets/test-projects/ProjectWithDisabledAnalyzers/ProjectWithDisabledAnalyzers.csproj new file mode 100644 index 0000000000..a769c05836 --- /dev/null +++ b/test-assets/test-projects/ProjectWithDisabledAnalyzers/ProjectWithDisabledAnalyzers.csproj @@ -0,0 +1,12 @@ + + + + Exe + netcoreapp2.1 + ./nugets/ + false + + + + + diff --git a/test-assets/test-projects/ProjectWithDisabledAnalyzers2/Program.cs b/test-assets/test-projects/ProjectWithDisabledAnalyzers2/Program.cs new file mode 100644 index 0000000000..8168c80511 --- /dev/null +++ b/test-assets/test-projects/ProjectWithDisabledAnalyzers2/Program.cs @@ -0,0 +1,12 @@ +using System; + +namespace HelloWorld +{ + class Program + { + static void Main(string[] args) + { + Console.WriteLine("Hello World!"); + } + } +} diff --git a/test-assets/test-projects/ProjectWithDisabledAnalyzers2/ProjectWithDisabledAnalyzers2.csproj b/test-assets/test-projects/ProjectWithDisabledAnalyzers2/ProjectWithDisabledAnalyzers2.csproj new file mode 100644 index 0000000000..bfa10df6be --- /dev/null +++ b/test-assets/test-projects/ProjectWithDisabledAnalyzers2/ProjectWithDisabledAnalyzers2.csproj @@ -0,0 +1,12 @@ + + + + Exe + netcoreapp2.1 + ./nugets/ + false + + + + + diff --git a/tests/OmniSharp.MSBuild.Tests/ProjectWithAnalyzersTests.cs b/tests/OmniSharp.MSBuild.Tests/ProjectWithAnalyzersTests.cs index b219ead2e8..9b1d9219f3 100644 --- a/tests/OmniSharp.MSBuild.Tests/ProjectWithAnalyzersTests.cs +++ b/tests/OmniSharp.MSBuild.Tests/ProjectWithAnalyzersTests.cs @@ -67,7 +67,7 @@ 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(); @@ -75,6 +75,20 @@ public async Task WhenProjectIsLoadedThenItContainsCustomRulesetsFromCsproj() } } + [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() {