File: ProjectSystemShim\LegacyProject\AnalyzersTests.cs
Web Access
Project: src\src\VisualStudio\CSharp\Test\Microsoft.VisualStudio.LanguageServices.CSharp.UnitTests.csproj (Microsoft.VisualStudio.LanguageServices.CSharp.UnitTests)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
#nullable disable
 
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Shared.TestHooks;
using Microsoft.CodeAnalysis.Test.Utilities;
using Microsoft.VisualStudio.LanguageServices.CSharp.ProjectSystemShim.Interop;
using Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem.Interop;
using Microsoft.VisualStudio.LanguageServices.UnitTests.ProjectSystemShim.Framework;
using Roslyn.Test.Utilities;
using Xunit;
 
namespace Roslyn.VisualStudio.CSharp.UnitTests.ProjectSystemShim.LegacyProject;
 
[UseExportProvider]
[Trait(Traits.Feature, Traits.Features.ProjectSystemShims)]
public sealed class AnalyzersTests : TestBase
{
    [WpfFact]
    public void RuleSet_GeneralOption()
    {
        var ruleSetFile = Temp.CreateFile().WriteAllText(
@"<?xml version=""1.0"" encoding=""utf-8""?>
<RuleSet Name=""Ruleset1"" Description=""Test""  ToolsVersion=""12.0"">
  <IncludeAll Action=""Error"" />
</RuleSet>
");
        using var environment = new TestEnvironment();
        var project = CSharpHelpers.CreateCSharpProject(environment, "Test");
 
        var options = (CSharpCompilationOptions)environment.GetUpdatedCompilationOptionOfSingleProject();
 
        Assert.Equal(expected: ReportDiagnostic.Default, actual: options.GeneralDiagnosticOption);
 
        ((IAnalyzerHost)project).SetRuleSetFile(ruleSetFile.Path);
 
        options = (CSharpCompilationOptions)environment.GetUpdatedCompilationOptionOfSingleProject();
 
        Assert.Equal(expected: ReportDiagnostic.Error, actual: options.GeneralDiagnosticOption);
    }
 
    [WpfFact]
    public void RuleSet_CanBeFetchedFromWorkspace()
    {
        var ruleSetFile = Temp.CreateFile();
 
        using var environment = new TestEnvironment();
        var project = CSharpHelpers.CreateCSharpProject(environment, "Test");
 
        ((IAnalyzerHost)project).SetRuleSetFile(ruleSetFile.Path);
 
        var projectId = environment.Workspace.CurrentSolution.ProjectIds.Single();
        Assert.Equal(ruleSetFile.Path, environment.Workspace.TryGetRuleSetPathForProject(projectId));
    }
 
    [WpfFact]
    public void RuleSet_ProjectSettingOverridesGeneralOption()
    {
        var ruleSetFile = Temp.CreateFile().WriteAllText(
@"<?xml version=""1.0"" encoding=""utf-8""?>
<RuleSet Name=""Ruleset1"" Description=""Test""  ToolsVersion=""12.0"">
  <IncludeAll Action=""Warning"" />
</RuleSet>
");
 
        using var environment = new TestEnvironment();
        var project = CSharpHelpers.CreateCSharpProject(environment, "Test");
 
        ((IAnalyzerHost)project).SetRuleSetFile(ruleSetFile.Path);
 
        var workspaceProject = environment.Workspace.CurrentSolution.Projects.Single();
        var options = (CSharpCompilationOptions)workspaceProject.CompilationOptions;
 
        Assert.Equal(expected: ReportDiagnostic.Warn, actual: options.GeneralDiagnosticOption);
 
        project.SetOption(CompilerOptions.OPTID_WARNINGSAREERRORS, true);
 
        workspaceProject = environment.Workspace.CurrentSolution.Projects.Single();
        options = (CSharpCompilationOptions)workspaceProject.CompilationOptions;
 
        Assert.Equal(expected: ReportDiagnostic.Error, actual: options.GeneralDiagnosticOption);
    }
 
    [WpfFact]
    public void RuleSet_SpecificOptions()
    {
        var ruleSetFile = Temp.CreateFile().WriteAllText(
@"<?xml version=""1.0"" encoding=""utf-8""?>
<RuleSet Name=""Ruleset1"" Description=""Test""  ToolsVersion=""12.0"">
  <IncludeAll Action=""Warning"" />
  <Rules AnalyzerId=""Microsoft.Analyzers.ManagedCodeAnalysis"" RuleNamespace=""Microsoft.Rules.Managed"">
    <Rule Id=""CA1012"" Action=""Error"" />
  </Rules>
</RuleSet>
");
 
        using var environment = new TestEnvironment();
        var project = CSharpHelpers.CreateCSharpProject(environment, "Test");
 
        ((IAnalyzerHost)project).SetRuleSetFile(ruleSetFile.Path);
 
        var options = (CSharpCompilationOptions)environment.GetUpdatedCompilationOptionOfSingleProject();
 
        var ca1012DiagnosticOption = options.SpecificDiagnosticOptions["CA1012"];
        Assert.Equal(expected: ReportDiagnostic.Error, actual: ca1012DiagnosticOption);
    }
 
    [WpfFact]
    public void RuleSet_ProjectSettingsOverrideSpecificOptions()
    {
        var ruleSetFile = Temp.CreateFile().WriteAllText(
@"<?xml version=""1.0"" encoding=""utf-8""?>
<RuleSet Name=""Ruleset1"" Description=""Test""  ToolsVersion=""12.0"">
  <IncludeAll Action=""Warning"" />
  <Rules AnalyzerId=""Microsoft.Analyzers.ManagedCodeAnalysis"" RuleNamespace=""Microsoft.Rules.Managed"">
    <Rule Id=""CS1014"" Action=""None"" />
  </Rules>
</RuleSet>
");
        using var environment = new TestEnvironment();
        var project = CSharpHelpers.CreateCSharpProject(environment, "Test");
 
        ((IAnalyzerHost)project).SetRuleSetFile(ruleSetFile.Path);
        project.SetOption(CompilerOptions.OPTID_WARNASERRORLIST, "1014");
 
        var options = (CSharpCompilationOptions)environment.GetUpdatedCompilationOptionOfSingleProject();
 
        var ca1014DiagnosticOption = options.SpecificDiagnosticOptions["CS1014"];
        Assert.Equal(expected: ReportDiagnostic.Error, actual: ca1014DiagnosticOption);
    }
 
    [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1087250")]
    public void SetRuleSetFile_RemoveExtraBackslashes()
    {
        var ruleSetFile = Temp.CreateFile();
        using var environment = new TestEnvironment();
        var project = CSharpHelpers.CreateCSharpProject(environment, "Test");
        var pathWithExtraBackslashes = ruleSetFile.Path.Replace(@"\", @"\\");
 
        ((IAnalyzerHost)project).SetRuleSetFile(pathWithExtraBackslashes);
 
        var projectRuleSetFile = project.ProjectSystemProjectOptionsProcessor.ExplicitRuleSetFilePath;
 
        Assert.Equal(expected: ruleSetFile.Path, actual: projectRuleSetFile);
    }
 
    [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1092636")]
    [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1040247")]
    [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1048368")]
    [WorkItem("https://github.com/dotnet/roslyn/issues/468")]
    public void RuleSet_ProjectSettingsOverrideSpecificOptionsAndRestore()
    {
        var ruleSetFile = Temp.CreateFile().WriteAllText(
@"<?xml version=""1.0"" encoding=""utf-8""?>
<RuleSet Name=""Ruleset1"" Description=""Test""  ToolsVersion=""12.0"">
  <IncludeAll Action=""Warning"" />
  <Rules AnalyzerId=""Microsoft.Analyzers.ManagedCodeAnalysis"" RuleNamespace=""Microsoft.Rules.Managed"">
    <Rule Id=""CS1014"" Action=""None"" />
  </Rules>
</RuleSet>
");
 
        using var environment = new TestEnvironment();
        var project = CSharpHelpers.CreateCSharpProject(environment, "Test");
 
        ((IAnalyzerHost)project).SetRuleSetFile(ruleSetFile.Path);
 
        project.SetOption(CompilerOptions.OPTID_WARNASERRORLIST, "1014");
        var options = environment.GetUpdatedCompilationOptionOfSingleProject();
        Assert.Equal(expected: ReportDiagnostic.Error, actual: options.SpecificDiagnosticOptions["CS1014"]);
 
        project.SetOption(CompilerOptions.OPTID_WARNNOTASERRORLIST, "1014");
        options = environment.GetUpdatedCompilationOptionOfSingleProject();
        Assert.Equal(expected: ReportDiagnostic.Suppress, actual: options.SpecificDiagnosticOptions["CS1014"]);
 
        project.SetOption(CompilerOptions.OPTID_WARNNOTASERRORLIST, null);
        options = environment.GetUpdatedCompilationOptionOfSingleProject();
        Assert.Equal(expected: ReportDiagnostic.Error, actual: options.SpecificDiagnosticOptions["CS1014"]);
 
        project.SetOption(CompilerOptions.OPTID_WARNASERRORLIST, null);
        options = environment.GetUpdatedCompilationOptionOfSingleProject();
        Assert.Equal(expected: ReportDiagnostic.Suppress, actual: options.SpecificDiagnosticOptions["CS1014"]);
    }
 
    [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/468")]
    public void RuleSet_ProjectNoWarnOverridesOtherSettings()
    {
        var ruleSetFile = Temp.CreateFile().WriteAllText(
@"<?xml version=""1.0"" encoding=""utf-8""?>
<RuleSet Name=""Ruleset1"" Description=""Test""  ToolsVersion=""12.0"">
  <IncludeAll Action=""Warning"" />
  <Rules AnalyzerId=""Microsoft.Analyzers.ManagedCodeAnalysis"" RuleNamespace=""Microsoft.Rules.Managed"">
    <Rule Id=""CS1014"" Action=""Info"" />
  </Rules>
</RuleSet>
");
 
        using var environment = new TestEnvironment();
        var project = CSharpHelpers.CreateCSharpProject(environment, "Test");
 
        ((IAnalyzerHost)project).SetRuleSetFile(ruleSetFile.Path);
        project.SetOption(CompilerOptions.OPTID_NOWARNLIST, "1014");
        project.SetOption(CompilerOptions.OPTID_WARNASERRORLIST, "1014");
 
        var workspaceProject = environment.Workspace.CurrentSolution.Projects.Single();
        var options = (CSharpCompilationOptions)workspaceProject.CompilationOptions;
 
        var ca1014DiagnosticOption = options.SpecificDiagnosticOptions["CS1014"];
        Assert.Equal(expected: ReportDiagnostic.Suppress, actual: ca1014DiagnosticOption);
    }
 
    [WpfTheory]
    [CombinatorialData]
    [WorkItem("https://github.com/dotnet/roslyn/pull/33505")]
    public async Task RuleSet_FileChangingOnDiskRefreshes(bool useCpsProject)
    {
        var ruleSetSource =
@"<?xml version=""1.0"" encoding=""utf-8""?>
<RuleSet Name=""Ruleset1"" Description=""Test""  ToolsVersion=""12.0"">
  <IncludeAll Action=""Error"" />
</RuleSet>
";
 
        var ruleSetFile = Temp.CreateFile().WriteAllText(ruleSetSource);
        using var environment = new TestEnvironment();
        if (useCpsProject)
        {
            await CSharpHelpers.CreateCSharpCPSProjectAsync(environment, "Test", binOutputPath: @"C:\test.dll", $"/ruleset:\"{ruleSetFile.Path}\"");
        }
        else
        {
            // Test legacy project handling
            var project = CSharpHelpers.CreateCSharpProject(environment, "Test");
            ((IAnalyzerHost)project).SetRuleSetFile(ruleSetFile.Path);
        }
 
        var options = (CSharpCompilationOptions)environment.GetUpdatedCompilationOptionOfSingleProject();
 
        // Assert the value exists now
        Assert.Equal(expected: ReportDiagnostic.Error, actual: options.GeneralDiagnosticOption);
 
        // Modify the file and raise a mock file change
        File.WriteAllText(ruleSetFile.Path, ruleSetSource.Replace("Error", "Warning"));
        await environment.RaiseFileChangeAsync(ruleSetFile.Path);
 
        var listenerProvider = environment.ExportProvider.GetExportedValue<AsynchronousOperationListenerProvider>();
        var waiter = listenerProvider.GetWaiter(FeatureAttribute.RuleSetEditor);
        waiter.ExpeditedWaitAsync().JoinUsingDispatcher(CancellationToken.None);
 
        options = (CSharpCompilationOptions)environment.GetUpdatedCompilationOptionOfSingleProject();
        Assert.Equal(expected: ReportDiagnostic.Warn, actual: options.GeneralDiagnosticOption);
    }
}