diff --git a/build/tools/ExtractRuleDescFromJson/RuleDescExtractor.cs b/build/tools/ExtractRuleDescFromJson/RuleDescExtractor.cs index b49c73fc9..9c43f9dc6 100644 --- a/build/tools/ExtractRuleDescFromJson/RuleDescExtractor.cs +++ b/build/tools/ExtractRuleDescFromJson/RuleDescExtractor.cs @@ -103,36 +103,38 @@ private static IEnumerable LoadRules(string file) private void ProcessRule(PluginRule pluginRule) { - try - { - var descAsxml = HtmlXmlCompatibilityHelper.EnsureHtmlIsXml(pluginRule.Description); - - var slvsRule = new RuleInfo( - pluginRule.Language?.ToLower() ?? throw new ArgumentNullException("language"), - pluginRule.Key ?? throw new ArgumentNullException("key"), - descAsxml, - pluginRule.Name ?? throw new ArgumentNullException("name"), - ConvertPluginSeverity(pluginRule.DefaultSeverity), - ConvertPluginIssueType(pluginRule.Type), - Convert.ToBoolean(pluginRule.IsActiveByDefault), - pluginRule.Tags ?? Array.Empty(), - pluginRule.DescriptionSections?.Select(x => new SonarLint.VisualStudio.Rules.DescriptionSection(x.Key, - HtmlXmlCompatibilityHelper.EnsureHtmlIsXml(x.HtmlContent), - x.Context != null - ? new SonarLint.VisualStudio.Rules.Context(x.Context.Key, x.Context.DisplayName) - : null)).ToList(), - pluginRule.EducationPrinciples, - null, - pluginRule.CleanCodeAttribute, - pluginRule.DefaultImpacts - ); - - SaveRuleFile(slvsRule); - } - catch (Exception ex) - { - Logger.LogError($"Error processing rule. Rule key: {pluginRule.Key}, file: {context.RuleJsonFilePath}, {ex.Message}"); - } + return; // this will be deleted later + + // try + // { + // var descAsxml = HtmlXmlCompatibilityHelper.EnsureHtmlIsXml(pluginRule.Description); + // + // var slvsRule = new RuleInfo( + // pluginRule.Language?.ToLower() ?? throw new ArgumentNullException("language"), + // pluginRule.Key ?? throw new ArgumentNullException("key"), + // descAsxml, + // pluginRule.Name ?? throw new ArgumentNullException("name"), + // ConvertPluginSeverity(pluginRule.DefaultSeverity), + // ConvertPluginIssueType(pluginRule.Type), + // Convert.ToBoolean(pluginRule.IsActiveByDefault), + // pluginRule.Tags ?? Array.Empty(), + // pluginRule.DescriptionSections?.Select(x => new SonarLint.VisualStudio.Rules.DescriptionSection(x.Key, + // HtmlXmlCompatibilityHelper.EnsureHtmlIsXml(x.HtmlContent), + // x.Context != null + // ? new SonarLint.VisualStudio.Rules.Context(x.Context.Key, x.Context.DisplayName) + // : null)).ToList(), + // pluginRule.EducationPrinciples, + // null, + // pluginRule.CleanCodeAttribute, + // pluginRule.DefaultImpacts + // ); + // + // SaveRuleFile(slvsRule); + // } + // catch (Exception ex) + // { + // Logger.LogError($"Error processing rule. Rule key: {pluginRule.Key}, file: {context.RuleJsonFilePath}, {ex.Message}"); + // } } private static RuleIssueSeverity ConvertPluginSeverity(string? pluginSeverity) diff --git a/src/Education.UnitTests/Layout/Logical/AssesTheProblemSectionTests.cs b/src/Education.UnitTests/Layout/Logical/AssesTheProblemSectionTests.cs deleted file mode 100644 index cd1495a4f..000000000 --- a/src/Education.UnitTests/Layout/Logical/AssesTheProblemSectionTests.cs +++ /dev/null @@ -1,50 +0,0 @@ -/* - * SonarLint for Visual Studio - * Copyright (C) 2016-2024 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -using FluentAssertions; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using SonarLint.VisualStudio.Education.Layout.Logical; -using SonarLint.VisualStudio.Education.Layout.Visual; - -namespace SonarLint.VisualStudio.Education.UnitTests.Layout.Logical; - -[TestClass] -public class AssesTheProblemSectionTests -{ - [TestMethod] - public void KeyAndTitle_AreCorrect() - { - var testSubject = new AssesTheProblemSection(""); - - testSubject.Key.Should().BeSameAs(AssesTheProblemSection.RuleInfoKey).And.Be("assess_the_problem"); - testSubject.Title.Should().Be("Assess the risk"); - } - - [TestMethod] - public void GetVisualizationTreeNode_ProducesOneContentSection() - { - var partialXaml = "Think about the problem more"; - var testSubject = new AssesTheProblemSection(partialXaml); - - var visualizationTreeNode = testSubject.GetVisualizationTreeNode(null); - - visualizationTreeNode.Should().BeOfType().Which.xamlContent.Should().Be(partialXaml); - } -} diff --git a/src/Education.UnitTests/Layout/Logical/HowToFixSectionTests.cs b/src/Education.UnitTests/Layout/Logical/HowToFixSectionTests.cs deleted file mode 100644 index e399d7e10..000000000 --- a/src/Education.UnitTests/Layout/Logical/HowToFixSectionTests.cs +++ /dev/null @@ -1,111 +0,0 @@ -/* - * SonarLint for Visual Studio - * Copyright (C) 2016-2024 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -using System.Collections.Generic; -using System.Linq; -using FluentAssertions; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using SonarLint.VisualStudio.Education.Layout.Logical; -using SonarLint.VisualStudio.Education.Layout.Visual; -using SonarLint.VisualStudio.Education.Layout.Visual.Tabs; -using SonarLint.VisualStudio.Education.XamlGenerator; - -namespace SonarLint.VisualStudio.Education.UnitTests.Layout.Logical; - -[TestClass] -public class HowToFixSectionTests -{ - [TestMethod] - public void KeyAndTitle_AreCorrect() - { - var testSubject = new HowToFixItSection(""); - - testSubject.Key.Should().BeSameAs(HowToFixItSection.RuleInfoKey).And.Be("how_to_fix"); - testSubject.Title.Should().Be("How can I fix it?"); - } - - [TestMethod] - public void GetVisualizationTreeNode_Contextless_ProducesOneContentSection() - { - var partialXaml = "Just fix it"; - var testSubject = new HowToFixItSection(partialXaml); - - var visualizationTreeNode = testSubject.GetVisualizationTreeNode(null); - - visualizationTreeNode.Should().BeOfType().Which.xamlContent.Should().Be(partialXaml); - } - - [TestMethod] - public void GetVisualizationTreeNode_ContextAware_ProducesCorrectMultiBlockSection() - { - var contexts = new List - { - new HowToFixItSectionContext("aspnetmvc", "asp net mvc", "rewrite to asp net core"), - new HowToFixItSectionContext("aspnetcore","asp net core", "nothing to worry about, unless..."), - }; - var testSubject = new HowToFixItSection(contexts, null); - var staticXamlStorage = new StaticXamlStorage(new RuleHelpXamlTranslatorFactory(new XamlWriterFactory(), new DiffTranslator(new XamlWriterFactory()))); - - var visualizationTreeNode = testSubject.GetVisualizationTreeNode(staticXamlStorage); - - var multiBlockSection = visualizationTreeNode.Should().BeOfType().Subject; - multiBlockSection.blocks.Should().HaveCount(2); - - multiBlockSection.blocks[0].Should().BeOfType() - .Which.xamlContent.Should().Be(staticXamlStorage.HowToFixItHeader); - - var tabGroup = multiBlockSection.blocks[1].Should().BeOfType().Subject; - tabGroup.tabs.Should().HaveCount(contexts.Count + 1); - - tabGroup.selectedTabIndex.Should().Be(0); - - for (var i = 0; i < contexts.Count; i++) - { - ((TabItem)tabGroup.tabs[i]).content.Should().BeOfType().Which.xamlContent.Should().Be(contexts[i].PartialXamlContent); - } - - ((TabItem)tabGroup.tabs.Last()).content.Should().BeOfType().Which.xamlContent.Should().Be(staticXamlStorage.HowToFixItFallbackContext); - } - - [DataTestMethod] - [DataRow("notinthelist", 2)] // 2 - the fallback tab - [DataRow(null, 0)] - [DataRow("aspnetmvc", 0)] - [DataRow("aspnetcore", 1)] - public void GetVisualizationTreeNode_ContextAware_SelectsCorrectContext(string selectedContext, int expectedSelectedTabIndex) - { - var contexts = new List - { - new HowToFixItSectionContext("aspnetmvc", "asp net mvc", "rewrite to asp net core"), - new HowToFixItSectionContext("aspnetcore","asp net core", "nothing to worry about, unless..."), - }; - var testSubject = new HowToFixItSection(contexts, selectedContext); - var staticXamlStorage = new StaticXamlStorage(new RuleHelpXamlTranslatorFactory(new XamlWriterFactory(), new DiffTranslator(new XamlWriterFactory()))); - - var visualizationTreeNode = testSubject.GetVisualizationTreeNode(staticXamlStorage); - - visualizationTreeNode - .Should().BeOfType() - .Which.blocks.Last() - .Should().BeOfType() - .Which.selectedTabIndex - .Should().Be(expectedSelectedTabIndex); - } -} diff --git a/src/Education.UnitTests/Layout/Logical/ResourcesSectionTests.cs b/src/Education.UnitTests/Layout/Logical/ResourcesSectionTests.cs deleted file mode 100644 index 094b43e07..000000000 --- a/src/Education.UnitTests/Layout/Logical/ResourcesSectionTests.cs +++ /dev/null @@ -1,89 +0,0 @@ -/* - * SonarLint for Visual Studio - * Copyright (C) 2016-2024 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -using System.Collections.Generic; -using FluentAssertions; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using SonarLint.VisualStudio.Education.Layout.Logical; -using SonarLint.VisualStudio.Education.Layout.Visual; -using SonarLint.VisualStudio.Education.XamlGenerator; - -namespace SonarLint.VisualStudio.Education.UnitTests.Layout.Logical -{ - [TestClass] - public class ResourcesSectionTests - { - [TestMethod] - public void KeyAndTitle_AreCorrect() - { - var testSubject = new ResourcesSection("", null); - - testSubject.Key.Should().BeSameAs(ResourcesSection.RuleInfoKey).And.Be("resources"); - testSubject.Title.Should().Be("More info"); - } - - [DataTestMethod] - [DataRow(true)] - [DataRow(false)] - public void GetVisualizationTreeNode_NoEducation_ProducesCorrectMultiBlockSection(bool emptyOrNull) - { - var partialXaml = "please read coding 101"; - var testSubject = new ResourcesSection(partialXaml, - emptyOrNull ? new List() : null); - var staticXamlStorage = CreateStaticXamlStorage(); - - var visualizationTreeNode = testSubject.GetVisualizationTreeNode(staticXamlStorage); - - var multiBlockSection = visualizationTreeNode.Should().BeOfType().Subject; - multiBlockSection.blocks.Should().HaveCount(2); - multiBlockSection.blocks[0].Should().BeOfType() - .Which.xamlContent.Should().Be(staticXamlStorage.ResourcesHeader); - multiBlockSection.blocks[1].Should().BeOfType() - .Which.xamlContent.Should().Be(partialXaml); - } - - [TestMethod] - public void GetVisualizationTreeNode_WithEducation_ProducesCorrectMultiBlockSection() - { - var partialXaml = "please read coding 101"; - var testSubject = new ResourcesSection(partialXaml, - new List { "defense_in_depth", "unknown_section_to_be_ignored", "never_trust_user_input" }); - var staticXamlStorage = CreateStaticXamlStorage(); - - var visualizationTreeNode = testSubject.GetVisualizationTreeNode(staticXamlStorage); - - var multiBlockSection = visualizationTreeNode.Should().BeOfType().Subject; - multiBlockSection.blocks.Should().HaveCount(5); - multiBlockSection.blocks[2].Should().BeOfType() - .Which.xamlContent.Should().Be(staticXamlStorage.EducationPrinciplesHeader); - multiBlockSection.blocks[3].Should().BeOfType() - .Which.content.Should().BeOfType() - .Which.xamlContent.Should().Be(staticXamlStorage.EducationPrinciplesDefenseInDepth); - multiBlockSection.blocks[4].Should().BeOfType() - .Which.content.Should().BeOfType() - .Which.xamlContent.Should().Be(staticXamlStorage.EducationPrinciplesNeverTrustUserInput); - } - - private static StaticXamlStorage CreateStaticXamlStorage() - { - return new StaticXamlStorage(new RuleHelpXamlTranslatorFactory(new XamlWriterFactory(), new DiffTranslator(new XamlWriterFactory()))); - } - } -} diff --git a/src/Education.UnitTests/Layout/Logical/RootCauseSectionTests.cs b/src/Education.UnitTests/Layout/Logical/RootCauseSectionTests.cs deleted file mode 100644 index fd3150e75..000000000 --- a/src/Education.UnitTests/Layout/Logical/RootCauseSectionTests.cs +++ /dev/null @@ -1,53 +0,0 @@ -/* - * SonarLint for Visual Studio - * Copyright (C) 2016-2024 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -using FluentAssertions; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using SonarLint.VisualStudio.Education.Layout.Logical; -using SonarLint.VisualStudio.Education.Layout.Visual; - -namespace SonarLint.VisualStudio.Education.UnitTests.Layout.Logical; - -[TestClass] -public class RootCauseSectionTests -{ - [TestMethod] - public void KeyAndTitle_AreCorrect() - { - var testSubject = new RootCauseSection("", false); - var testSubjectHotspot = new RootCauseSection("", true); - - testSubject.Key.Should().BeSameAs(RootCauseSection.RuleInfoKey).And.Be("root_cause"); - testSubject.Title.Should().Be("Why is this an issue?"); - testSubjectHotspot.Key.Should().BeSameAs(RootCauseSection.RuleInfoKey).And.Be("root_cause"); - testSubjectHotspot.Title.Should().Be("What's the risk?"); - } - - [TestMethod] - public void GetVisualizationTreeNode_ProducesOneContentSection() - { - var partialXaml = "Your code is bad"; - var testSubject = new RootCauseSection(partialXaml, false); - - var visualizationTreeNode = testSubject.GetVisualizationTreeNode(null); - - visualizationTreeNode.Should().BeOfType().Which.xamlContent.Should().Be(partialXaml); - } -} diff --git a/src/Education.UnitTests/Layout/Logical/RuleInfoTranslatorTests.cs b/src/Education.UnitTests/Layout/Logical/RuleInfoTranslatorTests.cs deleted file mode 100644 index 62b5294b5..000000000 --- a/src/Education.UnitTests/Layout/Logical/RuleInfoTranslatorTests.cs +++ /dev/null @@ -1,248 +0,0 @@ -/* - * SonarLint for Visual Studio - * Copyright (C) 2016-2024 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -using System; -using System.Collections.Generic; -using System.Linq; -using FluentAssertions; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using Moq; -using SonarLint.VisualStudio.Core; -using SonarLint.VisualStudio.Education.Layout.Logical; -using SonarLint.VisualStudio.Education.XamlGenerator; -using SonarLint.VisualStudio.Rules; -using SonarLint.VisualStudio.TestInfrastructure; - -namespace SonarLint.VisualStudio.Education.UnitTests.Layout.Logical -{ - [TestClass] - public class RuleInfoTranslatorTests - { - [TestMethod] - public void MefCtor_CheckExports() - { - MefTestHelpers.CheckTypeCanBeImported( - MefTestHelpers.CreateExport(), - MefTestHelpers.CreateExport()); - } - - [TestMethod] - public void GetRuleDescriptionSections_IgnoresUnknownSection() - { - var ruleInfo = GetRuleInfo(new[] { new DescriptionSection(Guid.NewGuid().ToString(), "hello") }); - var ruleHelpXamlTranslatorFactoryMock = new Mock(); - var ruleHelpXamlTranslatorMock = new Mock(); - ruleHelpXamlTranslatorFactoryMock.Setup(x => x.Create()).Returns(ruleHelpXamlTranslatorMock.Object); - var testSubject = new RuleInfoTranslator(ruleHelpXamlTranslatorFactoryMock.Object, new TestLogger()); - - var ruleDescriptionSections = testSubject.GetRuleDescriptionSections(ruleInfo, null).ToList(); - - ruleDescriptionSections.Should().HaveCount(0); - ruleHelpXamlTranslatorMock.Invocations.Should().HaveCount(0); - } - - [TestMethod] - public void GetRuleDescriptionSections_CorrectlyFormsRootCauseSection() - { - GetRuleDescriptionSections_CorrectlyFormsSimpleContentSection("root_cause", - (section, xamlContent) => section.partialXamlContent.Should().Be(xamlContent)); - } - - [DataRow(RuleIssueType.Hotspot, "What's the risk?")] - [DataRow(RuleIssueType.Vulnerability, "Why is this an issue?")] - [DataRow(RuleIssueType.CodeSmell, "Why is this an issue?")] - [DataRow(RuleIssueType.Bug, "Why is this an issue?")] - [DataTestMethod] - public void GetRuleDescriptionSections_RootCauseSectionSetsCorrectTitle(RuleIssueType issueType, string expectedTitle) - { - var ruleHelpXamlTranslatorFactoryMock = new Mock(); - var ruleHelpXamlTranslatorMock = new Mock(); - ruleHelpXamlTranslatorFactoryMock.Setup(x => x.Create()).Returns(ruleHelpXamlTranslatorMock.Object); - var ruleInfoTranslator = new RuleInfoTranslator(ruleHelpXamlTranslatorFactoryMock.Object, new TestLogger()); - - var descriptionSections = - ruleInfoTranslator - .GetRuleDescriptionSections( - GetRuleInfo(new[] { new DescriptionSection("root_cause", null) }, issueType), null) - .ToList(); - - descriptionSections.Should().ContainSingle(); - descriptionSections.Single().Should().BeOfType().Which.Title.Should().Be(expectedTitle); - } - - [TestMethod] - public void GetRuleDescriptionSections_CorrectlyFormsAssesTheProblemSection() - { - GetRuleDescriptionSections_CorrectlyFormsSimpleContentSection("assess_the_problem", - (section, xamlContent) => section.partialXamlContent.Should().Be(xamlContent)); - } - - [TestMethod] - public void GetRuleDescriptionSections_CorrectlyFormsNoContextHowToFixItSection() - { - GetRuleDescriptionSections_CorrectlyFormsSimpleContentSection("how_to_fix", - (section, xamlContent) => - { - section.contexts.Should().BeNull(); - section.partialXamlContent.Should().Be(xamlContent); - }); - } - - [TestMethod] - public void GetRuleDescriptionSections_CorrectlyFormsMultiContextHowToFixItSection() - { - var selectedIssueContext = "abrakadabra"; - var content1 = "hello"; - var content2 = "hello2"; - var content3 = "hello3"; - var ruleInfo = GetRuleInfo(new[] - { - new DescriptionSection("how_to_fix", content1, new Context("asp", "ASP")), - new DescriptionSection("how_to_fix", content2, new Context("console", "CLI")), - new DescriptionSection("how_to_fix", content3, new Context("xamarin", "Xamarin")), - }); - var ruleHelpXamlTranslatorFactoryMock = new Mock(); - var ruleHelpXamlTranslatorMock = new Mock(); - ruleHelpXamlTranslatorFactoryMock.Setup(x => x.Create()).Returns(ruleHelpXamlTranslatorMock.Object); - ruleHelpXamlTranslatorMock.Setup(x => x.TranslateHtmlToXaml(content1)).Returns(content1); - ruleHelpXamlTranslatorMock.Setup(x => x.TranslateHtmlToXaml(content2)).Returns(content2); - ruleHelpXamlTranslatorMock.Setup(x => x.TranslateHtmlToXaml(content3)).Returns(content3); - var testSubject = new RuleInfoTranslator(ruleHelpXamlTranslatorFactoryMock.Object, new TestLogger()); - - var ruleDescriptionSections = testSubject.GetRuleDescriptionSections(ruleInfo, selectedIssueContext).ToList(); - - ruleDescriptionSections.Should().HaveCount(1); - ruleDescriptionSections[0].Should().BeOfType(); - var howToFixItSection = (HowToFixItSection)ruleDescriptionSections[0]; - howToFixItSection.selectedIssueContext.Should().Be(selectedIssueContext); - howToFixItSection.partialXamlContent.Should().BeNull(); - howToFixItSection.contexts.Count.Should().Be(3); - howToFixItSection.contexts.Select(x => x.Key).Should().BeEquivalentTo(ruleInfo.DescriptionSections.Select(x => x.Context.Key)); - howToFixItSection.contexts.Select(x => x.Title).Should().BeEquivalentTo(ruleInfo.DescriptionSections.Select(x => x.Context.DisplayName)); - howToFixItSection.contexts.Select(x => x.PartialXamlContent).Should().BeEquivalentTo(content1, content2, content3); - ruleHelpXamlTranslatorMock.Verify(x => x.TranslateHtmlToXaml(It.IsAny()), Times.Exactly(3)); - } - - [TestMethod] - public void GetRuleDescriptionSections_CorrectlyFormsResourcesSection() - { - GetRuleDescriptionSections_CorrectlyFormsSimpleContentSection("resources", - (section, xamlContent) => - { - section.partialXamlContent.Should().Be(xamlContent); - section.educationPrinciples.Should().HaveCount(2); - }); - } - - [DataTestMethod] - [DataRow(RootCauseSection.RuleInfoKey)] - [DataRow(AssesTheProblemSection.RuleInfoKey)] - [DataRow(ResourcesSection.RuleInfoKey)] - public void GetRuleDescriptionSections_RuleInfoHasDuplicateSections_LogsWarning(string key) - { - var ruleInfo = GetRuleInfo(new[] - { - new DescriptionSection(key, ""), - new DescriptionSection(key, ""), - new DescriptionSection(key, "") - }); - var ruleHelpXamlTranslatorFactoryMock = new Mock(); - ruleHelpXamlTranslatorFactoryMock.Setup(x => x.Create()).Returns(Mock.Of()); - var testLogger = new TestLogger(); - - var testSubject = new RuleInfoTranslator(ruleHelpXamlTranslatorFactoryMock.Object, testLogger); - - var sections = testSubject.GetRuleDescriptionSections(ruleInfo, null).ToList(); - - sections.Should().HaveCount(1); - testLogger.OutputStrings.Single() - .Should().Contain(key) - .And.Contain(ruleInfo.FullRuleKey) - .And.Contain("unexpected number of section items"); - } - - [TestMethod] - public void GetRuleDescriptionSections_OrdersSectionsCorrectly() - { - var ruleInfo = GetRuleInfo(new IDescriptionSection[] - { - new DescriptionSection("assess_the_problem", "2"), - new DescriptionSection("resources", "4"), - new DescriptionSection("how_to_fix", "3", new Context("1", "1")), - new DescriptionSection("root_cause", "1"), - new DescriptionSection("how_to_fix", "3", new Context("2", "2")), - }); - var ruleHelpXamlTranslatorFactoryMock = new Mock(); - ruleHelpXamlTranslatorFactoryMock.Setup(x => x.Create()).Returns(Mock.Of()); - - var testSubject = new RuleInfoTranslator(ruleHelpXamlTranslatorFactoryMock.Object, new TestLogger()); - - var sections = testSubject.GetRuleDescriptionSections(ruleInfo, null).ToList(); - - sections.Should().HaveCount(4); - sections[0].Should().BeOfType(); - sections[1].Should().BeOfType(); - sections[2].Should().BeOfType(); - var contexts = ((HowToFixItSection)sections[2]).contexts; - contexts.Should().HaveCount(2); - contexts[0].Key.Should().Be("1"); - contexts[1].Key.Should().Be("2"); - sections[3].Should().BeOfType(); - } - - private void GetRuleDescriptionSections_CorrectlyFormsSimpleContentSection(string key, Action verifyXamlContent) - { - var htmlContent = "

hello

"; - var xamlContent = "hello"; - var ruleInfo = GetRuleInfo(new[] { new DescriptionSection(key, htmlContent) }); - var ruleHelpXamlTranslatorFactoryMock = new Mock(); - var ruleHelpXamlTranslatorMock = new Mock(); - ruleHelpXamlTranslatorFactoryMock.Setup(x => x.Create()).Returns(ruleHelpXamlTranslatorMock.Object); - ruleHelpXamlTranslatorMock.Setup(x => x.TranslateHtmlToXaml(htmlContent)).Returns(xamlContent); - - var testSubject = new RuleInfoTranslator(ruleHelpXamlTranslatorFactoryMock.Object, new TestLogger()); - - var ruleDescriptionSections = testSubject.GetRuleDescriptionSections(ruleInfo, null).ToList(); - - ruleDescriptionSections.Should().HaveCount(1); - ruleDescriptionSections[0].Should().BeOfType(); - verifyXamlContent((T)ruleDescriptionSections[0], xamlContent); - ruleHelpXamlTranslatorMock.Verify(x => x.TranslateHtmlToXaml(htmlContent), Times.Once); - } - - private IRuleInfo GetRuleInfo(IReadOnlyList sections, RuleIssueType issueType = RuleIssueType.Vulnerability) - { - return new RuleInfo( - Language.CSharp.ServerLanguage.Key, - "xxx:S123", - "a description", - "the rule name", - RuleIssueSeverity.Blocker, - issueType, - isActiveByDefault: true, - new List { "veryimportantissue" }, - sections, - new List { "think before you do something", "think again" }, - null, - null, - null); - } - } -} diff --git a/src/Education.UnitTests/XamlGenerator/RichRuleHelpXamlBuilderTests.cs b/src/Education.UnitTests/XamlGenerator/RichRuleHelpXamlBuilderTests.cs index 2df981f9d..eb50e749a 100644 --- a/src/Education.UnitTests/XamlGenerator/RichRuleHelpXamlBuilderTests.cs +++ b/src/Education.UnitTests/XamlGenerator/RichRuleHelpXamlBuilderTests.cs @@ -1,109 +1,108 @@ -using System.Linq; -using System.Text; -using System.Windows.Controls; -using FluentAssertions; -using System.Windows.Documents; -using System.Xml; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using Moq; -using SonarLint.VisualStudio.Education.Layout.Logical; -using SonarLint.VisualStudio.Education.Layout.Visual; -using SonarLint.VisualStudio.Education.XamlGenerator; -using SonarLint.VisualStudio.Rules; -using SonarLint.VisualStudio.TestInfrastructure; - -namespace SonarLint.VisualStudio.Education.UnitTests.XamlGenerator -{ - [TestClass] - public class RichRuleHelpXamlBuilderTests - { - [TestMethod] - public void MefCtor_CheckExports() - { - MefTestHelpers.CheckTypeCanBeImported( - MefTestHelpers.CreateExport(), - MefTestHelpers.CreateExport(), - MefTestHelpers.CreateExport(), - MefTestHelpers.CreateExport()); - } - - [TestMethod] - public void Create_GeneratesCorrectStructure() - { - var selectedIssueContext = "abrakadabra"; - var callSequence = new MockSequence(); - var ruleInfoTranslatorMock = new Mock(MockBehavior.Strict); - var xamlGeneratorHelperFactoryMock = new Mock(MockBehavior.Strict); - var xamlGeneratorHelperMock = new Mock(MockBehavior.Strict); - var xamlWriterFactoryMock = new Mock(MockBehavior.Strict); - var ruleInfo = Mock.Of(); - XmlWriter writer = null; - ruleInfoTranslatorMock - .InSequence(callSequence) - .Setup(x => x.GetRuleDescriptionSections(ruleInfo, selectedIssueContext)) - .Returns(Enumerable - .Range(0, 3) - .Select(x => - { - var mock = new Mock(MockBehavior.Strict); - mock - .SetupGet(y => y.Title) - .Returns(x.ToString()); - mock - .Setup(y => y.GetVisualizationTreeNode(It.IsAny())) - .Returns(new ContentSection($"{x}")); - return mock.Object; - })); - xamlWriterFactoryMock - .InSequence(callSequence) - .Setup(x => x.Create(It.IsAny())) - .Returns((StringBuilder sb) => - { - writer = new XamlWriterFactory().Create(sb); - return writer; - }); - xamlGeneratorHelperFactoryMock - .InSequence(callSequence) - .Setup(x => x.Create(It.IsAny())) - .Returns(xamlGeneratorHelperMock.Object); - xamlGeneratorHelperMock - .InSequence(callSequence) - .Setup(x => x.WriteDocumentHeader(ruleInfo)) - .Callback(() => { writer.WriteStartElement("FlowDocument", "http://schemas.microsoft.com/winfx/2006/xaml/presentation"); }); - xamlGeneratorHelperMock - .InSequence(callSequence) - .Setup(x => x.EndDocument()) - .Callback(() => - { - writer.WriteFullEndElement(); - writer.Close(); - }); - - var testSubject = new RichRuleHelpXamlBuilder(ruleInfoTranslatorMock.Object, xamlGeneratorHelperFactoryMock.Object, Mock.Of(), xamlWriterFactoryMock.Object); - - var flowDocument = testSubject.Create(ruleInfo, selectedIssueContext); - - var blockUiContainer = flowDocument.Blocks.Single().Should().BeOfType().Subject; - var tabControl = blockUiContainer.Child.Should().BeOfType().Subject; - tabControl.SelectedIndex.Should().Be(0); - tabControl.Items.Should().HaveCount(3); - for (var index = 0; index < tabControl.Items.Count; index++) - { - ((TabItem)tabControl.Items[index]) - .Content - .Should().BeOfType() - .Which - .Document - .Blocks - .Single() - .Should().BeOfType() - .Which - .Inlines - .Single() - .Should().BeOfType() - .Which - .Text.Should().BeEquivalentTo(index.ToString()); - } - } - } -} +// using System.Linq; +// using System.Text; +// using System.Windows.Controls; +// using FluentAssertions; +// using System.Windows.Documents; +// using System.Xml; +// using Microsoft.VisualStudio.TestTools.UnitTesting; +// using Moq; +// using SonarLint.VisualStudio.Education.Layout.Logical; +// using SonarLint.VisualStudio.Education.Layout.Visual; +// using SonarLint.VisualStudio.Education.XamlGenerator; +// using SonarLint.VisualStudio.Rules; +// using SonarLint.VisualStudio.TestInfrastructure; +// +// namespace SonarLint.VisualStudio.Education.UnitTests.XamlGenerator +// { +// [TestClass] +// public class RichRuleHelpXamlBuilderTests +// { +// [TestMethod] +// public void MefCtor_CheckExports() +// { +// MefTestHelpers.CheckTypeCanBeImported( +// MefTestHelpers.CreateExport(), +// MefTestHelpers.CreateExport(), +// MefTestHelpers.CreateExport()); +// } +// +// [TestMethod] +// public void Create_GeneratesCorrectStructure() +// { +// var selectedIssueContext = "abrakadabra"; +// var callSequence = new MockSequence(); +// var ruleInfoTranslatorMock = new Mock(MockBehavior.Strict); +// var xamlGeneratorHelperFactoryMock = new Mock(MockBehavior.Strict); +// var xamlGeneratorHelperMock = new Mock(MockBehavior.Strict); +// var xamlWriterFactoryMock = new Mock(MockBehavior.Strict); +// var ruleInfo = Mock.Of(); +// XmlWriter writer = null; +// ruleInfoTranslatorMock +// .InSequence(callSequence) +// .Setup(x => x.GetRuleDescriptionSections(ruleInfo, selectedIssueContext)) +// .Returns(Enumerable +// .Range(0, 3) +// .Select(x => +// { +// var mock = new Mock(MockBehavior.Strict); +// mock +// .SetupGet(y => y.Title) +// .Returns(x.ToString()); +// mock +// .Setup(y => y.GetVisualizationTreeNode(It.IsAny())) +// .Returns(new ContentSection($"{x}")); +// return mock.Object; +// })); +// xamlWriterFactoryMock +// .InSequence(callSequence) +// .Setup(x => x.Create(It.IsAny())) +// .Returns((StringBuilder sb) => +// { +// writer = new XamlWriterFactory().Create(sb); +// return writer; +// }); +// xamlGeneratorHelperFactoryMock +// .InSequence(callSequence) +// .Setup(x => x.Create(It.IsAny())) +// .Returns(xamlGeneratorHelperMock.Object); +// xamlGeneratorHelperMock +// .InSequence(callSequence) +// .Setup(x => x.WriteDocumentHeader(ruleInfo)) +// .Callback(() => { writer.WriteStartElement("FlowDocument", "http://schemas.microsoft.com/winfx/2006/xaml/presentation"); }); +// xamlGeneratorHelperMock +// .InSequence(callSequence) +// .Setup(x => x.EndDocument()) +// .Callback(() => +// { +// writer.WriteFullEndElement(); +// writer.Close(); +// }); +// +// var testSubject = new RichRuleHelpXamlBuilder(ruleInfoTranslatorMock.Object, xamlGeneratorHelperFactoryMock.Object, Mock.Of(), xamlWriterFactoryMock.Object); +// +// var flowDocument = testSubject.Create(ruleInfo, selectedIssueContext); +// +// var blockUiContainer = flowDocument.Blocks.Single().Should().BeOfType().Subject; +// var tabControl = blockUiContainer.Child.Should().BeOfType().Subject; +// tabControl.SelectedIndex.Should().Be(0); +// tabControl.Items.Should().HaveCount(3); +// for (var index = 0; index < tabControl.Items.Count; index++) +// { +// ((TabItem)tabControl.Items[index]) +// .Content +// .Should().BeOfType() +// .Which +// .Document +// .Blocks +// .Single() +// .Should().BeOfType() +// .Which +// .Inlines +// .Single() +// .Should().BeOfType() +// .Which +// .Text.Should().BeEquivalentTo(index.ToString()); +// } +// } +// } +// } diff --git a/src/Education.UnitTests/XamlGenerator/RuleHelpXamlBuilderTests.cs b/src/Education.UnitTests/XamlGenerator/RuleHelpXamlBuilderTests.cs index bb754b153..f8a77ee8e 100644 --- a/src/Education.UnitTests/XamlGenerator/RuleHelpXamlBuilderTests.cs +++ b/src/Education.UnitTests/XamlGenerator/RuleHelpXamlBuilderTests.cs @@ -1,60 +1,60 @@ -/* - * SonarLint for Visual Studio - * Copyright (C) 2016-2024 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -using System.Collections.Generic; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using Moq; -using SonarLint.VisualStudio.Education.XamlGenerator; -using SonarLint.VisualStudio.Rules; -using SonarLint.VisualStudio.TestInfrastructure; - -namespace SonarLint.VisualStudio.Education.UnitTests.XamlGenerator; - -[TestClass] -public class RuleHelpXamlBuilderTests -{ - [TestMethod] - public void MefCtor_CheckExports() - { - MefTestHelpers.CheckTypeCanBeImported( - MefTestHelpers.CreateExport(), - MefTestHelpers.CreateExport()); - } - - [DataTestMethod] - [DataRow(true)] - [DataRow(false)] - public void Create_ChoosesCorrectLayoutBuilder(bool isExtendedRule) - { - var selectedIssueContext = "abrakadabra"; - var ruleInfoMock = new Mock(); - ruleInfoMock.SetupGet(x => x.DescriptionSections).Returns(isExtendedRule - ? new List { new DescriptionSection(null, null), new DescriptionSection(null, null) } - : null); - var simpleRuleHelpXamlBuilderMock = new Mock(); - var richRuleHelpXamlBuilderMock = new Mock(); - var testSubject = new RuleHelpXamlBuilder(simpleRuleHelpXamlBuilderMock.Object, richRuleHelpXamlBuilderMock.Object); - - testSubject.Create(ruleInfoMock.Object, selectedIssueContext); - - simpleRuleHelpXamlBuilderMock.Verify(x => x.Create(ruleInfoMock.Object), isExtendedRule ? Times.Never : Times.Once); - richRuleHelpXamlBuilderMock.Verify(x => x.Create(ruleInfoMock.Object, selectedIssueContext), isExtendedRule ? Times.Once : Times.Never); - } -} +// /* +// * SonarLint for Visual Studio +// * Copyright (C) 2016-2024 SonarSource SA +// * mailto:info AT sonarsource DOT com +// * +// * This program is free software; you can redistribute it and/or +// * modify it under the terms of the GNU Lesser General Public +// * License as published by the Free Software Foundation; either +// * version 3 of the License, or (at your option) any later version. +// * +// * This program is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// * Lesser General Public License for more details. +// * +// * You should have received a copy of the GNU Lesser General Public License +// * along with this program; if not, write to the Free Software Foundation, +// * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// */ +// +// using System.Collections.Generic; +// using Microsoft.VisualStudio.TestTools.UnitTesting; +// using Moq; +// using SonarLint.VisualStudio.Education.XamlGenerator; +// using SonarLint.VisualStudio.Rules; +// using SonarLint.VisualStudio.TestInfrastructure; +// +// namespace SonarLint.VisualStudio.Education.UnitTests.XamlGenerator; +// +// [TestClass] +// public class RuleHelpXamlBuilderTests +// { +// [TestMethod] +// public void MefCtor_CheckExports() +// { +// MefTestHelpers.CheckTypeCanBeImported( +// MefTestHelpers.CreateExport(), +// MefTestHelpers.CreateExport()); +// } +// +// [DataTestMethod] +// [DataRow(true)] +// [DataRow(false)] +// public void Create_ChoosesCorrectLayoutBuilder(bool isExtendedRule) +// { +// var selectedIssueContext = "abrakadabra"; +// var ruleInfoMock = new Mock(); +// ruleInfoMock.SetupGet(x => x.DescriptionSections).Returns(isExtendedRule +// ? new List { new DescriptionSection(null, null), new DescriptionSection(null, null) } +// : null); +// var simpleRuleHelpXamlBuilderMock = new Mock(); +// var richRuleHelpXamlBuilderMock = new Mock(); +// var testSubject = new RuleHelpXamlBuilder(simpleRuleHelpXamlBuilderMock.Object, richRuleHelpXamlBuilderMock.Object); +// +// testSubject.Create(ruleInfoMock.Object, selectedIssueContext); +// +// simpleRuleHelpXamlBuilderMock.Verify(x => x.Create(ruleInfoMock.Object), isExtendedRule ? Times.Never : Times.Once); +// richRuleHelpXamlBuilderMock.Verify(x => x.Create(ruleInfoMock.Object, selectedIssueContext), isExtendedRule ? Times.Once : Times.Never); +// } +// } diff --git a/src/Education.UnitTests/XamlGenerator/RuleXamlBuilderSmokeTest.cs b/src/Education.UnitTests/XamlGenerator/RuleXamlBuilderSmokeTest.cs index 43ade8e91..53a537fd9 100644 --- a/src/Education.UnitTests/XamlGenerator/RuleXamlBuilderSmokeTest.cs +++ b/src/Education.UnitTests/XamlGenerator/RuleXamlBuilderSmokeTest.cs @@ -35,90 +35,90 @@ namespace SonarLint.VisualStudio.Education.UnitTests.XamlGenerator; [TestClass] public class RuleXamlBuilderSmokeTest { - private static readonly Assembly ResourceAssembly = typeof(LocalRuleMetadataProvider).Assembly; - - [TestMethod] - public void Create_CheckAllEmbedded() - { - // Performance: this test is loading nearly 2000 files and creating - // XAML document for them, but it still only takes a around 3 seconds - // to run. - var resourceNames = ResourceAssembly.GetManifestResourceNames() - .Where(x => x.EndsWith(".json")); - - // Sanity check - should have checked at least 1500 rules - resourceNames.Count().Should().BeGreaterThan(1500); - - Console.WriteLine("Checking xaml creation. Count = " + resourceNames.Count()); - - string[] failures; - using (new AssertIgnoreScope()) // the product code can assert if it encounters an unrecognised tag - { - failures = resourceNames.Where(x => !ProcessResource(x)) - .ToArray(); - } - - failures.Should().BeEquivalentTo(new[] - { - // introduced in sonar-cpp 6.48 - "SonarLint.VisualStudio.Rules.Embedded.cpp.S1232.json", - // some issue with diff highlighting - "SonarLint.VisualStudio.Rules.Embedded.csharpsquid.S6640.json", - }); - } - - private static bool ProcessResource(string fullResourceName) - { - var xamlWriterFactory = new XamlWriterFactory(); - var ruleHelpXamlTranslatorFactory = new RuleHelpXamlTranslatorFactory(xamlWriterFactory, new DiffTranslator(xamlWriterFactory)); - var xamlGeneratorHelperFactory = new XamlGeneratorHelperFactory(ruleHelpXamlTranslatorFactory); - var ruleInfoTranslator = new RuleInfoTranslator(ruleHelpXamlTranslatorFactory, new TestLogger()); - var staticXamlStorage = new StaticXamlStorage(ruleHelpXamlTranslatorFactory); - - var simpleXamlBuilder = new SimpleRuleHelpXamlBuilder(ruleHelpXamlTranslatorFactory, xamlGeneratorHelperFactory, xamlWriterFactory); - var richXamlBuilder = new RichRuleHelpXamlBuilder(ruleInfoTranslator, xamlGeneratorHelperFactory, staticXamlStorage, xamlWriterFactory); - - try - { - bool res = false; - - var data = ReadResource(fullResourceName); - var jsonRuleInfo = LocalRuleMetadataProvider.RuleInfoJsonDeserializer.Deserialize(data); - - if (!string.IsNullOrWhiteSpace(jsonRuleInfo.Description)) - { - Res(simpleXamlBuilder.Create(jsonRuleInfo)); - res = true; - } - - if (jsonRuleInfo.DescriptionSections.Any()) - { - Res(richXamlBuilder.Create(jsonRuleInfo, null)); - res = true; - } - - return res; // simple || rich should be true - } - catch (Exception ex) - { - Console.WriteLine("Failed: " + fullResourceName); - Console.WriteLine(" " + ex.Message); - return false; - } - } - - private static void Res(FlowDocument doc) - { - // Quick sanity check that something was produced - // Note: this is a quick way of getting the size of the document. Serializing the doc to a string - // and checking the length takes much longer (around 25 seconds) - var docLength = doc.ContentStart.DocumentStart.GetOffsetToPosition(doc.ContentEnd.DocumentEnd); - docLength.Should().BeGreaterThan(30); - } - - private static string ReadResource(string fullResourceName) - { - using var stream = new StreamReader(ResourceAssembly.GetManifestResourceStream(fullResourceName)); - return stream.ReadToEnd(); - } + // private static readonly Assembly ResourceAssembly = typeof(LocalRuleMetadataProvider).Assembly; + // + // [TestMethod] + // public void Create_CheckAllEmbedded() + // { + // // Performance: this test is loading nearly 2000 files and creating + // // XAML document for them, but it still only takes a around 3 seconds + // // to run. + // var resourceNames = ResourceAssembly.GetManifestResourceNames() + // .Where(x => x.EndsWith(".json")); + // + // // Sanity check - should have checked at least 1500 rules + // resourceNames.Count().Should().BeGreaterThan(1500); + // + // Console.WriteLine("Checking xaml creation. Count = " + resourceNames.Count()); + // + // string[] failures; + // using (new AssertIgnoreScope()) // the product code can assert if it encounters an unrecognised tag + // { + // failures = resourceNames.Where(x => !ProcessResource(x)) + // .ToArray(); + // } + // + // failures.Should().BeEquivalentTo(new[] + // { + // // introduced in sonar-cpp 6.48 + // "SonarLint.VisualStudio.Rules.Embedded.cpp.S1232.json", + // // some issue with diff highlighting + // "SonarLint.VisualStudio.Rules.Embedded.csharpsquid.S6640.json", + // }); + // } + // + // private static bool ProcessResource(string fullResourceName) + // { + // var xamlWriterFactory = new XamlWriterFactory(); + // var ruleHelpXamlTranslatorFactory = new RuleHelpXamlTranslatorFactory(xamlWriterFactory, new DiffTranslator(xamlWriterFactory)); + // var xamlGeneratorHelperFactory = new XamlGeneratorHelperFactory(ruleHelpXamlTranslatorFactory); + // var ruleInfoTranslator = new RuleInfoTranslator(ruleHelpXamlTranslatorFactory, new TestLogger()); + // var staticXamlStorage = new StaticXamlStorage(ruleHelpXamlTranslatorFactory); + // + // var simpleXamlBuilder = new SimpleRuleHelpXamlBuilder(ruleHelpXamlTranslatorFactory, xamlGeneratorHelperFactory, xamlWriterFactory); + // var richXamlBuilder = new RichRuleHelpXamlBuilder(ruleInfoTranslator, xamlGeneratorHelperFactory, staticXamlStorage, xamlWriterFactory); + // + // try + // { + // bool res = false; + // + // var data = ReadResource(fullResourceName); + // var jsonRuleInfo = LocalRuleMetadataProvider.RuleInfoJsonDeserializer.Deserialize(data); + // + // if (!string.IsNullOrWhiteSpace(jsonRuleInfo.Description)) + // { + // Res(simpleXamlBuilder.Create(jsonRuleInfo)); + // res = true; + // } + // + // if (jsonRuleInfo.DescriptionSections.Any()) + // { + // Res(richXamlBuilder.Create(jsonRuleInfo, null)); + // res = true; + // } + // + // return res; // simple || rich should be true + // } + // catch (Exception ex) + // { + // Console.WriteLine("Failed: " + fullResourceName); + // Console.WriteLine(" " + ex.Message); + // return false; + // } + // } + // + // private static void Res(FlowDocument doc) + // { + // // Quick sanity check that something was produced + // // Note: this is a quick way of getting the size of the document. Serializing the doc to a string + // // and checking the length takes much longer (around 25 seconds) + // var docLength = doc.ContentStart.DocumentStart.GetOffsetToPosition(doc.ContentEnd.DocumentEnd); + // docLength.Should().BeGreaterThan(30); + // } + // + // private static string ReadResource(string fullResourceName) + // { + // using var stream = new StreamReader(ResourceAssembly.GetManifestResourceStream(fullResourceName)); + // return stream.ReadToEnd(); + // } } diff --git a/src/Education.UnitTests/XamlGenerator/SimpleRuleHelpXamlBuilderTests.cs b/src/Education.UnitTests/XamlGenerator/SimpleRuleHelpXamlBuilderTests.cs index 8d08e9daf..2b0bb73d0 100644 --- a/src/Education.UnitTests/XamlGenerator/SimpleRuleHelpXamlBuilderTests.cs +++ b/src/Education.UnitTests/XamlGenerator/SimpleRuleHelpXamlBuilderTests.cs @@ -35,8 +35,6 @@ namespace SonarLint.VisualStudio.Education.UnitTests.XamlGenerator [TestClass] public class SimpleRuleHelpXamlBuilderTests { - private static readonly Assembly ResourceAssembly = typeof(LocalRuleMetadataProvider).Assembly; - [TestMethod] public void MefCtor_CheckExports() { diff --git a/src/Education.UnitTests/XamlGenerator/StaticXamlStorageTests.cs b/src/Education.UnitTests/XamlGenerator/StaticXamlStorageTests.cs deleted file mode 100644 index cb68f3bd3..000000000 --- a/src/Education.UnitTests/XamlGenerator/StaticXamlStorageTests.cs +++ /dev/null @@ -1,153 +0,0 @@ -/* - * SonarLint for Visual Studio - * Copyright (C) 2016-2024 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -using System; -using FluentAssertions; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using Moq; -using SonarLint.VisualStudio.Education.XamlGenerator; -using SonarLint.VisualStudio.TestInfrastructure; - -namespace SonarLint.VisualStudio.Education.UnitTests.XamlGenerator -{ - [TestClass] - public class StaticXamlStorageTests - { - [TestMethod] - public void MefCtor_CheckExports() - { - MefTestHelpers.CheckTypeCanBeImported( - MefTestHelpers.CreateExport()); - } - - [TestMethod] - public void EducationPrinciplesHeader_IsLazy() - { - var translatorFactoryMock = new Mock(); - var translatorMock = new Mock(); - translatorFactoryMock.Setup(x => x.Create()).Returns(translatorMock.Object); - var testSubject = new StaticXamlStorage(translatorFactoryMock.Object); - - _ = testSubject.EducationPrinciplesHeader; - _ = testSubject.EducationPrinciplesHeader; - - translatorMock.Verify(x => x.TranslateHtmlToXaml(StaticHtmlSnippets.EducationPrinciplesHeader), Times.Once); - } - - [TestMethod] - public void EducationPrinciplesHeader_DoesNotThrow() - { - var testSubject = CreateTestSubject(); - - Action act = () => - { - _ = testSubject.EducationPrinciplesHeader; - }; - - act.Should().NotThrow(); - } - - [TestMethod] - public void EducationPrinciplesDefenseInDepth_IsLazy() - { - var translatorFactoryMock = new Mock(); - var translatorMock = new Mock(); - translatorFactoryMock.Setup(x => x.Create()).Returns(translatorMock.Object); - var testSubject = new StaticXamlStorage(translatorFactoryMock.Object); - - _ = testSubject.EducationPrinciplesDefenseInDepth; - _ = testSubject.EducationPrinciplesDefenseInDepth; - - translatorMock.Verify(x => x.TranslateHtmlToXaml(StaticHtmlSnippets.EducationPrinciplesDefenseInDepth), Times.Once); - } - - [TestMethod] - public void EducationPrinciplesDefenseInDepth_DoesNotThrow() - { - var testSubject = CreateTestSubject(); - - Action act = () => - { - _ = testSubject.EducationPrinciplesDefenseInDepth; - }; - - act.Should().NotThrow(); - } - - [TestMethod] - public void EducationPrinciplesNeverTrustUserInput_IsLazy() - { - var translatorFactoryMock = new Mock(); - var translatorMock = new Mock(); - translatorFactoryMock.Setup(x => x.Create()).Returns(translatorMock.Object); - var testSubject = new StaticXamlStorage(translatorFactoryMock.Object); - - _ = testSubject.EducationPrinciplesNeverTrustUserInput; - _ = testSubject.EducationPrinciplesNeverTrustUserInput; - - translatorMock.Verify(x => x.TranslateHtmlToXaml(StaticHtmlSnippets.EducationPrinciplesNeverTrustUserInput), Times.Once); - } - - [TestMethod] - public void EducationPrinciplesNeverTrustUserInput_DoesNotThrow() - { - var testSubject = CreateTestSubject(); - - Action act = () => - { - _ = testSubject.EducationPrinciplesNeverTrustUserInput; - }; - - act.Should().NotThrow(); - } - - [TestMethod] - public void HowToFixItFallbackContext_IsLazy() - { - var translatorFactoryMock = new Mock(); - var translatorMock = new Mock(); - translatorFactoryMock.Setup(x => x.Create()).Returns(translatorMock.Object); - var testSubject = new StaticXamlStorage(translatorFactoryMock.Object); - - _ = testSubject.HowToFixItFallbackContext; - _ = testSubject.HowToFixItFallbackContext; - - translatorMock.Verify(x => x.TranslateHtmlToXaml(StaticHtmlSnippets.HowToFixItFallbackContext), Times.Once); - } - - [TestMethod] - public void HowToFixItFallbackContext_DoesNotThrow() - { - var testSubject = CreateTestSubject(); - - Action act = () => - { - _ = testSubject.HowToFixItFallbackContext; - }; - - act.Should().NotThrow(); - } - - private StaticXamlStorage CreateTestSubject() - { - return new StaticXamlStorage(new RuleHelpXamlTranslatorFactory(new XamlWriterFactory(), new DiffTranslator(new XamlWriterFactory()))); - } - } -} diff --git a/src/Education.UnitTests/XamlGenerator/XamlGeneratorHelperTests.cs b/src/Education.UnitTests/XamlGenerator/XamlGeneratorHelperTests.cs index 4d4500380..1c578682b 100644 --- a/src/Education.UnitTests/XamlGenerator/XamlGeneratorHelperTests.cs +++ b/src/Education.UnitTests/XamlGenerator/XamlGeneratorHelperTests.cs @@ -45,143 +45,143 @@ public void Factory_Create_ReturnsNonNull() ruleHelpXamlTranslatorFactoryMock.Verify(x => x.Create()); } - [TestMethod] - public void WriteDocumentHeaderAndEndDocument_ExtendedDescription_ProduceCorrectStructure() - { - var sb = new StringBuilder(); - var xmlWriter = new XamlWriterFactory().Create(sb); - var ruleInfo = new RuleInfo("cs", "cs:123", "

Hi

", "Hi", RuleIssueSeverity.Critical, - RuleIssueType.Vulnerability, true, new List(), new List(), - new List(), "

fix this pls

", null, null); - - var testSubject = CreateTestSubject(xmlWriter); - - testSubject.WriteDocumentHeader(ruleInfo); - xmlWriter.WriteStartElement("LineBreak"); - xmlWriter.WriteEndElement(); - testSubject.EndDocument(); - - sb.ToString().Should().BeEquivalentTo( -@" - Hi - - - - - Vulnerability - - - - Critical - cs:123 - fix this pls".Replace("\r\n", "\n").Replace("\n", "\r\n")); - } - - [TestMethod] - public void WriteDocumentHeaderAndEndDocument_ProduceCorrectStructure() - { - var sb = new StringBuilder(); - var xmlWriter = new XamlWriterFactory().Create(sb); - var ruleInfo = new RuleInfo("cs", "cs:123", "

Hi

", "Hi", RuleIssueSeverity.Critical, - RuleIssueType.Vulnerability, true, new List(), new List(), - new List(), null, null, null); - IXamlGeneratorHelper testSubject = CreateTestSubject(xmlWriter); - - testSubject.WriteDocumentHeader(ruleInfo); - xmlWriter.WriteStartElement("Section"); - xmlWriter.WriteEndElement(); - testSubject.EndDocument(); - - sb.ToString().Should().BeEquivalentTo( -@" - Hi - - - - - Vulnerability - - - - Critical - cs:123 - -
-".Replace("\r\n", "\n").Replace("\n", "\r\n")); - } - - [TestMethod] - public void WriteDocumentHeaderAndEndDocument_ProduceCorrectStructure_NewCCT() - { - var sb = new StringBuilder(); - var xmlWriter = new XamlWriterFactory().Create(sb); - var ruleInfo = new RuleInfo("cs", "cs:123", "

Hi

", "Hi", RuleIssueSeverity.Critical, - RuleIssueType.Vulnerability, true, new List(), new List(), - new List(), null, CleanCodeAttribute.Formatted, new Dictionary - { - { SoftwareQuality.Maintainability, SoftwareQualitySeverity.High}, - { SoftwareQuality.Security, SoftwareQualitySeverity.Low}, - { SoftwareQuality.Reliability, SoftwareQualitySeverity.Medium}, - }); - IXamlGeneratorHelper testSubject = CreateTestSubject(xmlWriter); - - testSubject.WriteDocumentHeader(ruleInfo); - xmlWriter.WriteStartElement("Section"); - xmlWriter.WriteEndElement(); - testSubject.EndDocument(); - - sb.ToString().Should().BeEquivalentTo(@" - Hi - - - - - - Consistency issue | Not Formatted - - - - - Maintainability - - - - - - - - - Security - - - - - - - - - Reliability - - - - - - - - Learn more about Clean Code - - - - - cs:123 - -
-".Replace("\r\n", "\n").Replace("\n", "\r\n")); - } - - private static IXamlGeneratorHelper CreateTestSubject(XmlWriter xmlWriter) - { - return (new XamlGeneratorHelperFactory(new RuleHelpXamlTranslatorFactory(new XamlWriterFactory(), new DiffTranslator(new XamlWriterFactory())))).Create(xmlWriter); - } +// [TestMethod] +// public void WriteDocumentHeaderAndEndDocument_ExtendedDescription_ProduceCorrectStructure() +// { +// var sb = new StringBuilder(); +// var xmlWriter = new XamlWriterFactory().Create(sb); +// var ruleInfo = new RuleInfo("cs", "cs:123", "

Hi

", "Hi", RuleIssueSeverity.Critical, +// RuleIssueType.Vulnerability, true, new List(), new List(), +// new List(), "

fix this pls

", null, null); +// +// var testSubject = CreateTestSubject(xmlWriter); +// +// testSubject.WriteDocumentHeader(ruleInfo); +// xmlWriter.WriteStartElement("LineBreak"); +// xmlWriter.WriteEndElement(); +// testSubject.EndDocument(); +// +// sb.ToString().Should().BeEquivalentTo( +// @" +// Hi +// +// +// +// +// Vulnerability +// +// +// +// Critical +// cs:123 +// fix this pls".Replace("\r\n", "\n").Replace("\n", "\r\n")); +// } +// +// [TestMethod] +// public void WriteDocumentHeaderAndEndDocument_ProduceCorrectStructure() +// { +// var sb = new StringBuilder(); +// var xmlWriter = new XamlWriterFactory().Create(sb); +// var ruleInfo = new RuleInfo("cs", "cs:123", "

Hi

", "Hi", RuleIssueSeverity.Critical, +// RuleIssueType.Vulnerability, true, new List(), new List(), +// new List(), null, null, null); +// IXamlGeneratorHelper testSubject = CreateTestSubject(xmlWriter); +// +// testSubject.WriteDocumentHeader(ruleInfo); +// xmlWriter.WriteStartElement("Section"); +// xmlWriter.WriteEndElement(); +// testSubject.EndDocument(); +// +// sb.ToString().Should().BeEquivalentTo( +// @" +// Hi +// +// +// +// +// Vulnerability +// +// +// +// Critical +// cs:123 +// +//
+// ".Replace("\r\n", "\n").Replace("\n", "\r\n")); +// } +// +// [TestMethod] +// public void WriteDocumentHeaderAndEndDocument_ProduceCorrectStructure_NewCCT() +// { +// var sb = new StringBuilder(); +// var xmlWriter = new XamlWriterFactory().Create(sb); +// var ruleInfo = new RuleInfo("cs", "cs:123", "

Hi

", "Hi", RuleIssueSeverity.Critical, +// RuleIssueType.Vulnerability, true, new List(), new List(), +// new List(), null, CleanCodeAttribute.Formatted, new Dictionary +// { +// { SoftwareQuality.Maintainability, SoftwareQualitySeverity.High}, +// { SoftwareQuality.Security, SoftwareQualitySeverity.Low}, +// { SoftwareQuality.Reliability, SoftwareQualitySeverity.Medium}, +// }); +// IXamlGeneratorHelper testSubject = CreateTestSubject(xmlWriter); +// +// testSubject.WriteDocumentHeader(ruleInfo); +// xmlWriter.WriteStartElement("Section"); +// xmlWriter.WriteEndElement(); +// testSubject.EndDocument(); +// +// sb.ToString().Should().BeEquivalentTo(@" +// Hi +// +// +// +// +// +// Consistency issue | Not Formatted +// +// +// +// +// Maintainability +// +// +// +// +// +// +// +// +// Security +// +// +// +// +// +// +// +// +// Reliability +// +// +// +// +// +// +// +// Learn more about Clean Code +// +// +// +// +// cs:123 +// +//
+// ".Replace("\r\n", "\n").Replace("\n", "\r\n")); +// } +// +// private static IXamlGeneratorHelper CreateTestSubject(XmlWriter xmlWriter) +// { +// return (new XamlGeneratorHelperFactory(new RuleHelpXamlTranslatorFactory(new XamlWriterFactory(), new DiffTranslator(new XamlWriterFactory())))).Create(xmlWriter); +// } } } diff --git a/src/Education/Education.csproj b/src/Education/Education.csproj index 0baddb059..dd5cf446d 100644 --- a/src/Education/Education.csproj +++ b/src/Education/Education.csproj @@ -68,11 +68,6 @@ True True - - True - True - StaticHtmlSnippets.resx - @@ -80,10 +75,6 @@ Resources.Designer.cs ResXFileCodeGenerator - - ResXFileCodeGenerator - StaticHtmlSnippets.Designer.cs - diff --git a/src/Education/Layout/Logical/AssesTheProblemSection.cs b/src/Education/Layout/Logical/AssesTheProblemSection.cs deleted file mode 100644 index dd677bfdb..000000000 --- a/src/Education/Layout/Logical/AssesTheProblemSection.cs +++ /dev/null @@ -1,45 +0,0 @@ -/* - * SonarLint for Visual Studio - * Copyright (C) 2016-2024 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -using SonarLint.VisualStudio.Education.Layout.Visual; -using SonarLint.VisualStudio.Education.XamlGenerator; - -namespace SonarLint.VisualStudio.Education.Layout.Logical -{ - internal class AssesTheProblemSection : IRichRuleDescriptionSection - { - public const string RuleInfoKey = "assess_the_problem"; - internal /* for testing */ readonly string partialXamlContent; - - public AssesTheProblemSection(string partialXaml) - { - partialXamlContent = partialXaml; - } - - public string Key => RuleInfoKey; - - public string Title => "Assess the risk"; - - public IAbstractVisualizationTreeNode GetVisualizationTreeNode(IStaticXamlStorage staticXamlStorage) - { - return new ContentSection(partialXamlContent); - } - } -} diff --git a/src/Education/Layout/Logical/HowToFixItSection.cs b/src/Education/Layout/Logical/HowToFixItSection.cs deleted file mode 100644 index 1d8ebaf1d..000000000 --- a/src/Education/Layout/Logical/HowToFixItSection.cs +++ /dev/null @@ -1,99 +0,0 @@ -/* - * SonarLint for Visual Studio - * Copyright (C) 2016-2024 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -using System.Collections.Generic; -using System.Linq; -using SonarLint.VisualStudio.Education.Layout.Visual; -using SonarLint.VisualStudio.Education.Layout.Visual.Tabs; -using SonarLint.VisualStudio.Education.XamlGenerator; - -namespace SonarLint.VisualStudio.Education.Layout.Logical -{ - internal class HowToFixItSection : IRichRuleDescriptionSection - { - public const string RuleInfoKey = "how_to_fix"; - internal /* for testing */ readonly List contexts; - internal /* for testing */ readonly string selectedIssueContext; - internal /* for testing */ readonly string partialXamlContent; - - public HowToFixItSection(string partialXaml) - { - partialXamlContent = partialXaml; - } - - public HowToFixItSection(List contexts, string selectedIssueContext) - { - this.contexts = contexts; - this.selectedIssueContext = selectedIssueContext; - } - - public string Key => RuleInfoKey; - - public string Title => "How can I fix it?"; - - public IAbstractVisualizationTreeNode GetVisualizationTreeNode(IStaticXamlStorage staticXamlStorage) - { - if (partialXamlContent != null) - { - return new ContentSection(partialXamlContent); - } - - var contextTabs = contexts - .Select(x => new TabItem(x.Title, new ContentSection(x.PartialXamlContent))) - .ToList(); - contextTabs.Add(new TabItem("Other", new ContentSection(staticXamlStorage.HowToFixItFallbackContext))); - - return new MultiBlockSection( - new ContentSection(staticXamlStorage.HowToFixItHeader), - new TabGroup(contextTabs, GetSelectedTabIndex(contextTabs))); - } - - private int GetSelectedTabIndex(List contextTabs) - { - if (selectedIssueContext == null) - { - return 0; - } - - var selectedIndex = contexts.FindIndex(x => x.Key.Equals(selectedIssueContext)); - - if (selectedIndex > -1) - { - return selectedIndex; - } - - return contextTabs.Count - 1; - } - } - - internal class HowToFixItSectionContext - { - public HowToFixItSectionContext(string key, string title, string partialXaml) - { - Key = key; - Title = title; - PartialXamlContent = partialXaml; - } - - public string Key { get; } - public string Title { get; } - public string PartialXamlContent { get; } - } -} diff --git a/src/Education/Layout/Logical/IRichRuleDescriptionSection.cs b/src/Education/Layout/Logical/IRichRuleDescriptionSection.cs deleted file mode 100644 index 87079a168..000000000 --- a/src/Education/Layout/Logical/IRichRuleDescriptionSection.cs +++ /dev/null @@ -1,32 +0,0 @@ -/* - * SonarLint for Visual Studio - * Copyright (C) 2016-2024 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -using SonarLint.VisualStudio.Education.Layout.Visual; -using SonarLint.VisualStudio.Education.XamlGenerator; - -namespace SonarLint.VisualStudio.Education.Layout.Logical -{ - internal interface IRichRuleDescriptionSection - { - string Key { get; } - string Title { get; } - IAbstractVisualizationTreeNode GetVisualizationTreeNode(IStaticXamlStorage staticXamlStorage); - } -} diff --git a/src/Education/Layout/Logical/ResourcesSection.cs b/src/Education/Layout/Logical/ResourcesSection.cs deleted file mode 100644 index 863634c0f..000000000 --- a/src/Education/Layout/Logical/ResourcesSection.cs +++ /dev/null @@ -1,77 +0,0 @@ -/* - * SonarLint for Visual Studio - * Copyright (C) 2016-2024 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -using System.Collections.Generic; -using SonarLint.VisualStudio.Education.Layout.Visual; -using SonarLint.VisualStudio.Education.XamlGenerator; - -namespace SonarLint.VisualStudio.Education.Layout.Logical -{ - internal class ResourcesSection : IRichRuleDescriptionSection - { - public const string RuleInfoKey = "resources"; - internal /* for testing */ readonly string partialXamlContent; - internal /* for testing */ readonly IReadOnlyList educationPrinciples; - - public ResourcesSection(string partialXaml, IReadOnlyList educationPrinciples) - { - partialXamlContent = partialXaml; - this.educationPrinciples = educationPrinciples; - } - - public string Key => RuleInfoKey; - public string Title => "More info"; - - public IAbstractVisualizationTreeNode GetVisualizationTreeNode(IStaticXamlStorage staticXamlStorage) - { - var sections = new List - { - new ContentSection(staticXamlStorage.ResourcesHeader), - new ContentSection(partialXamlContent) - }; - - if (educationPrinciples != null && educationPrinciples.Count != 0) - { - sections.Add(new ContentSection(staticXamlStorage.EducationPrinciplesHeader)); - foreach (var educationPrinciple in educationPrinciples) - { - string educationPrincipleXamlContent = null; - switch (educationPrinciple) - { - case "defense_in_depth": - educationPrincipleXamlContent = staticXamlStorage.EducationPrinciplesDefenseInDepth; - break; - case "never_trust_user_input": - educationPrincipleXamlContent = staticXamlStorage.EducationPrinciplesNeverTrustUserInput; - break; - } - - if (educationPrincipleXamlContent != null) - { - - sections.Add(new BorderedSection(new ContentSection(educationPrincipleXamlContent))); - } - } - } - - return new MultiBlockSection(sections); - } - } -} diff --git a/src/Education/Layout/Logical/RootCauseSection.cs b/src/Education/Layout/Logical/RootCauseSection.cs deleted file mode 100644 index 96e6be5f8..000000000 --- a/src/Education/Layout/Logical/RootCauseSection.cs +++ /dev/null @@ -1,46 +0,0 @@ -/* - * SonarLint for Visual Studio - * Copyright (C) 2016-2024 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -using SonarLint.VisualStudio.Education.Layout.Visual; -using SonarLint.VisualStudio.Education.XamlGenerator; - -namespace SonarLint.VisualStudio.Education.Layout.Logical -{ - internal class RootCauseSection : IRichRuleDescriptionSection - { - public const string RuleInfoKey = "root_cause"; - internal /* for testing */ readonly string partialXamlContent; - - public RootCauseSection(string partialXaml, bool isHotspot) - { - partialXamlContent = partialXaml; - Title = isHotspot ? "What's the risk?" : "Why is this an issue?"; - } - - public string Key => RuleInfoKey; - - public string Title { get; } - - public IAbstractVisualizationTreeNode GetVisualizationTreeNode(IStaticXamlStorage staticXamlStorage) - { - return new ContentSection(partialXamlContent); - } - } -} diff --git a/src/Education/Layout/Logical/RuleInfoTranslator.cs b/src/Education/Layout/Logical/RuleInfoTranslator.cs deleted file mode 100644 index 4cc350ab4..000000000 --- a/src/Education/Layout/Logical/RuleInfoTranslator.cs +++ /dev/null @@ -1,107 +0,0 @@ -/* - * SonarLint for Visual Studio - * Copyright (C) 2016-2024 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -using System.Collections.Generic; -using System.ComponentModel.Composition; -using SonarLint.VisualStudio.Education.XamlGenerator; -using System.Linq; -using SonarLint.VisualStudio.Core; -using SonarLint.VisualStudio.Rules; - -namespace SonarLint.VisualStudio.Education.Layout.Logical -{ - internal interface IRuleInfoTranslator - { - IEnumerable GetRuleDescriptionSections(IRuleInfo ruleInfo, string issueContext); - } - - [Export(typeof(IRuleInfoTranslator))] - [PartCreationPolicy(CreationPolicy.Shared)] - internal class RuleInfoTranslator : IRuleInfoTranslator - { - private readonly IRuleHelpXamlTranslator xamlTranslator; - private readonly ILogger logger; - - [ImportingConstructor] - public RuleInfoTranslator(IRuleHelpXamlTranslatorFactory xamlTranslatorFactory, ILogger logger) - { - this.logger = logger; - xamlTranslator = xamlTranslatorFactory.Create(); - } - - public IEnumerable GetRuleDescriptionSections(IRuleInfo ruleInfo, string issueContext) - { - var sectionsByKey = ruleInfo.DescriptionSections - .GroupBy(x => x.Key) - .ToDictionary(x => x.Key, x => x.ToList()); - - if (sectionsByKey.TryGetValue(RootCauseSection.RuleInfoKey, out var rootCauseSectionContent)) - { - AssertExpectedNumberOfDescriptionSections(ruleInfo.FullRuleKey, RootCauseSection.RuleInfoKey, rootCauseSectionContent.Count); - yield return new RootCauseSection(GeneratePartialXaml(rootCauseSectionContent[0].HtmlContent), ruleInfo.IssueType == RuleIssueType.Hotspot); - } - - if (sectionsByKey.TryGetValue(AssesTheProblemSection.RuleInfoKey, out var assessTheProblemContent)) - { - AssertExpectedNumberOfDescriptionSections(ruleInfo.FullRuleKey, AssesTheProblemSection.RuleInfoKey, assessTheProblemContent.Count); - yield return new AssesTheProblemSection(GeneratePartialXaml(assessTheProblemContent[0].HtmlContent)); - } - - if (sectionsByKey.TryGetValue(HowToFixItSection.RuleInfoKey, out var howToFixItContents)) - { - if (howToFixItContents.Count == 1 && howToFixItContents[0].Context == null) - { - yield return new HowToFixItSection(GeneratePartialXaml(howToFixItContents[0].HtmlContent)); - } - else - { - yield return new HowToFixItSection(howToFixItContents - .Select(x => new HowToFixItSectionContext(x.Context.Key, - x.Context.DisplayName, - GeneratePartialXaml(x.HtmlContent))) - .ToList(), - issueContext); - } - } - - if (sectionsByKey.TryGetValue(ResourcesSection.RuleInfoKey, out var resourcesSectionContent)) - { - AssertExpectedNumberOfDescriptionSections(ruleInfo.FullRuleKey, ResourcesSection.RuleInfoKey, resourcesSectionContent.Count); - yield return new ResourcesSection(GeneratePartialXaml(resourcesSectionContent[0].HtmlContent), ruleInfo.EducationPrinciples); - } - } - - private void AssertExpectedNumberOfDescriptionSections(string ruleKey, string descriptionSection, int sectionsCount, int expectedCount = 1) - { - if (sectionsCount == expectedCount) - { - return; - } - - var message = $"[{nameof(RuleInfoTranslator)}] Encountered rule description {ruleKey} with unexpected number of section items for {descriptionSection}: expected {expectedCount}, got {sectionsCount}"; - logger.WriteLine(message); - } - - private string GeneratePartialXaml(string htmlContent) - { - return xamlTranslator.TranslateHtmlToXaml(htmlContent); - } - } -} diff --git a/src/Education/XamlGenerator/RichRuleHelpXamlBuilder.cs b/src/Education/XamlGenerator/RichRuleHelpXamlBuilder.cs index e216df1fe..edbbebb2d 100644 --- a/src/Education/XamlGenerator/RichRuleHelpXamlBuilder.cs +++ b/src/Education/XamlGenerator/RichRuleHelpXamlBuilder.cs @@ -18,6 +18,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +using System; using System.ComponentModel.Composition; using System.Linq; using System.Text; @@ -47,39 +48,37 @@ internal interface IRichRuleHelpXamlBuilder [PartCreationPolicy(CreationPolicy.Shared)] internal class RichRuleHelpXamlBuilder : IRichRuleHelpXamlBuilder { - private readonly IRuleInfoTranslator ruleInfoTranslator; private readonly IXamlGeneratorHelperFactory xamlGeneratorHelperFactory; - private readonly IStaticXamlStorage staticXamlStorage; private readonly IXamlWriterFactory xamlWriterFactory; [ImportingConstructor] - public RichRuleHelpXamlBuilder(IRuleInfoTranslator ruleInfoTranslator, IXamlGeneratorHelperFactory xamlGeneratorHelperFactory, IStaticXamlStorage staticXamlStorage, IXamlWriterFactory xamlWriterFactory) + public RichRuleHelpXamlBuilder(IXamlGeneratorHelperFactory xamlGeneratorHelperFactory, IXamlWriterFactory xamlWriterFactory) { - this.ruleInfoTranslator = ruleInfoTranslator; this.xamlGeneratorHelperFactory = xamlGeneratorHelperFactory; - this.staticXamlStorage = staticXamlStorage; this.xamlWriterFactory = xamlWriterFactory; } public FlowDocument Create(IRuleInfo ruleInfo, string issueContext) { - var richRuleDescriptionSections = ruleInfoTranslator.GetRuleDescriptionSections(ruleInfo, issueContext).ToList(); - var mainTabGroup = new TabGroup(richRuleDescriptionSections - .Select(richRuleDescriptionSection => - new TabItem(richRuleDescriptionSection.Title, - richRuleDescriptionSection.GetVisualizationTreeNode(staticXamlStorage))) - .ToList(), - 0); - - var sb = new StringBuilder(); - var writer = xamlWriterFactory.Create(sb); - var helper = xamlGeneratorHelperFactory.Create(writer); - - helper.WriteDocumentHeader(ruleInfo); - mainTabGroup.ProduceXaml(writer); - helper.EndDocument(); - - return (FlowDocument)XamlReader.Parse(sb.ToString()); + throw new NotImplementedException(); // will be re-implemented later + + // var richRuleDescriptionSections = ruleInfoTranslator.GetRuleDescriptionSections(ruleInfo, issueContext).ToList(); + // var mainTabGroup = new TabGroup(richRuleDescriptionSections + // .Select(richRuleDescriptionSection => + // new TabItem(richRuleDescriptionSection.Title, + // richRuleDescriptionSection.GetVisualizationTreeNode(staticXamlStorage))) + // .ToList(), + // 0); + // + // var sb = new StringBuilder(); + // var writer = xamlWriterFactory.Create(sb); + // var helper = xamlGeneratorHelperFactory.Create(writer); + // + // helper.WriteDocumentHeader(ruleInfo); + // mainTabGroup.ProduceXaml(writer); + // helper.EndDocument(); + // + // return (FlowDocument)XamlReader.Parse(sb.ToString()); } } } diff --git a/src/Education/XamlGenerator/StaticHtmlSnippets.Designer.cs b/src/Education/XamlGenerator/StaticHtmlSnippets.Designer.cs deleted file mode 100644 index d6c295751..000000000 --- a/src/Education/XamlGenerator/StaticHtmlSnippets.Designer.cs +++ /dev/null @@ -1,149 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace SonarLint.VisualStudio.Education.XamlGenerator { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class StaticHtmlSnippets { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal StaticHtmlSnippets() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SonarLint.VisualStudio.Education.XamlGenerator.StaticHtmlSnippets", typeof(StaticHtmlSnippets).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// - /// Looks up a localized string similar to <h3>Defense-In-Depth</h3> - ///<p> - /// Applications and infrastructure benefit greatly from relying on multiple security mechanisms - /// layered on top of each other. If one security mechanism fails, there is a high probability - /// that the subsequent layers of security will successfully defend against the attack. - ///</p> - ///<p>A non-exhaustive list of these code protection ramparts includes the following:</p> - ///<ul> - /// <li>Minimizing the attack surface of the code</li> - /// <li>Application of the principle of l [rest of string was truncated]";. - /// - internal static string EducationPrinciplesDefenseInDepth { - get { - return ResourceManager.GetString("EducationPrinciplesDefenseInDepth", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to <h2>Clean Code principles</h2>. - /// - internal static string EducationPrinciplesHeader { - get { - return ResourceManager.GetString("EducationPrinciplesHeader", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to <h3>Never Trust User Input</h3> - ///<p> - /// Applications must treat all user input and, more generally, all third-party data as - /// attacker-controlled data. - ///</p> - ///<p> - /// The application must determine where the third-party data comes from and treat that data - /// source as an attack vector. Two rules apply: - ///</p> - /// - ///<p> - /// First, before using it in the application&apos;s business logic, the application must - /// validate the attacker-controlled data against predefined formats, such as: - ///</p> - ///<ul> - /// [rest of string was truncated]";. - /// - internal static string EducationPrinciplesNeverTrustUserInput { - get { - return ResourceManager.GetString("EducationPrinciplesNeverTrustUserInput", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to <h3>How can I fix it in another component or framework?</h3> - ///<p>Although the main framework or component you use in your project is not listed, you may find helpful content in the instructions we provide.</p> - ///<p>Caution: The libraries mentioned in these instructions may not be appropriate for your code.</p> - ///<ul> - /// <li>Do use libraries that are compatible with the frameworks you are using.</li> - /// <li>Don't blindly copy and paste the fix-ups into your code.</li> - ///</ul> - ///<h3>Help us improve</h3> - ///<p>L [rest of string was truncated]";. - /// - internal static string HowToFixItFallbackContext { - get { - return ResourceManager.GetString("HowToFixItFallbackContext", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to <h2>Which component or framework contains the issue?</h2>. - /// - internal static string HowToFixItHeader { - get { - return ResourceManager.GetString("HowToFixItHeader", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to <h2>Resources</h2>. - /// - internal static string ResourcesHeader { - get { - return ResourceManager.GetString("ResourcesHeader", resourceCulture); - } - } - } -} diff --git a/src/Education/XamlGenerator/StaticHtmlSnippets.resx b/src/Education/XamlGenerator/StaticHtmlSnippets.resx deleted file mode 100644 index c330ac3e2..000000000 --- a/src/Education/XamlGenerator/StaticHtmlSnippets.resx +++ /dev/null @@ -1,193 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - <h3>Defense-In-Depth</h3> -<p> - Applications and infrastructure benefit greatly from relying on multiple security mechanisms - layered on top of each other. If one security mechanism fails, there is a high probability - that the subsequent layers of security will successfully defend against the attack. -</p> -<p>A non-exhaustive list of these code protection ramparts includes the following:</p> -<ul> - <li>Minimizing the attack surface of the code</li> - <li>Application of the principle of least privilege</li> - <li>Validation and sanitization of data</li> - <li>Encrypting incoming, outgoing, or stored data with secure cryptography</li> - <li>Ensuring that internal errors cannot disrupt the overall runtime</li> - <li>Separation of tasks and access to information</li> -</ul> - -<p> - Note that these layers must be simple enough to use in an everyday workflow. Security - measures should not break usability. -</p> - - - <h2>Clean Code principles</h2> - - - <h3>Never Trust User Input</h3> -<p> - Applications must treat all user input and, more generally, all third-party data as - attacker-controlled data. -</p> -<p> - The application must determine where the third-party data comes from and treat that data - source as an attack vector. Two rules apply: -</p> - -<p> - First, before using it in the application&apos;s business logic, the application must - validate the attacker-controlled data against predefined formats, such as: -</p> -<ul> - <li>Character sets</li> - <li>Sizes</li> - <li>Types</li> - <li>Or any strict schema</li> -</ul> - -<p> - Second, the application must sanitize string data before inserting it into interpreted - contexts (client-side code, file paths, SQL queries). Unsanitized code can corrupt the - application&apos;s logic. -</p> - - - <h3>How can I fix it in another component or framework?</h3> -<p>Although the main framework or component you use in your project is not listed, you may find helpful content in the instructions we provide.</p> -<p>Caution: The libraries mentioned in these instructions may not be appropriate for your code.</p> -<ul> - <li>Do use libraries that are compatible with the frameworks you are using.</li> - <li>Don't blindly copy and paste the fix-ups into your code.</li> -</ul> -<h3>Help us improve</h3> -<p>Let us know if the instructions we provide do not work for you. - Tell us which framework you use and why our solution does not work by submitting an idea on the SonarLint product-board.</p> -<a href="https://portal.productboard.com/sonarsource/4-sonarlint/submit-idea">Submit an idea</a> -<p>We will do our best to provide you with more relevant instructions in the future.</p> - - - <h2>Which component or framework contains the issue?</h2> - - - <h2>Resources</h2> - - \ No newline at end of file diff --git a/src/Education/XamlGenerator/StaticXamlStorage.cs b/src/Education/XamlGenerator/StaticXamlStorage.cs deleted file mode 100644 index 1d66a0012..000000000 --- a/src/Education/XamlGenerator/StaticXamlStorage.cs +++ /dev/null @@ -1,67 +0,0 @@ -/* - * SonarLint for Visual Studio - * Copyright (C) 2016-2024 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -using System; -using System.ComponentModel.Composition; -using System.Threading; - -namespace SonarLint.VisualStudio.Education.XamlGenerator -{ - internal interface IStaticXamlStorage - { - string EducationPrinciplesHeader { get; } - string EducationPrinciplesDefenseInDepth { get; } - string EducationPrinciplesNeverTrustUserInput { get; } - string HowToFixItFallbackContext { get; } - string HowToFixItHeader { get; } - string ResourcesHeader { get; } - } - - [Export(typeof(IStaticXamlStorage))] - [PartCreationPolicy(CreationPolicy.Shared)] - internal class StaticXamlStorage : IStaticXamlStorage - { - private readonly Lazy educationPrinciplesHeader; - private readonly Lazy educationPrinciplesDefenseInDepth; - private readonly Lazy educationPrinciplesNeverTrustUserInput; - private readonly Lazy howToFixItFallbackContext; - private readonly Lazy howToFixItHeader; - private readonly Lazy resourcesHeader; - - [ImportingConstructor] - public StaticXamlStorage(IRuleHelpXamlTranslatorFactory ruleHelpXamlTranslatorFactory) - { - var ruleHelpXamlTranslator = ruleHelpXamlTranslatorFactory.Create(); - educationPrinciplesHeader = new Lazy(() => ruleHelpXamlTranslator.TranslateHtmlToXaml(StaticHtmlSnippets.EducationPrinciplesHeader), LazyThreadSafetyMode.None); - educationPrinciplesDefenseInDepth = new Lazy(() => ruleHelpXamlTranslator.TranslateHtmlToXaml(StaticHtmlSnippets.EducationPrinciplesDefenseInDepth), LazyThreadSafetyMode.None); - educationPrinciplesNeverTrustUserInput = new Lazy(() => ruleHelpXamlTranslator.TranslateHtmlToXaml(StaticHtmlSnippets.EducationPrinciplesNeverTrustUserInput), LazyThreadSafetyMode.None); - howToFixItFallbackContext = new Lazy(() => ruleHelpXamlTranslator.TranslateHtmlToXaml(StaticHtmlSnippets.HowToFixItFallbackContext), LazyThreadSafetyMode.None); - howToFixItHeader = new Lazy(() => ruleHelpXamlTranslator.TranslateHtmlToXaml(StaticHtmlSnippets.HowToFixItHeader), LazyThreadSafetyMode.None); - resourcesHeader = new Lazy(() => ruleHelpXamlTranslator.TranslateHtmlToXaml(StaticHtmlSnippets.ResourcesHeader), LazyThreadSafetyMode.None); - } - - public string EducationPrinciplesHeader => educationPrinciplesHeader.Value; - public string EducationPrinciplesDefenseInDepth => educationPrinciplesDefenseInDepth.Value; - public string EducationPrinciplesNeverTrustUserInput => educationPrinciplesNeverTrustUserInput.Value; - public string HowToFixItFallbackContext => howToFixItFallbackContext.Value; - public string HowToFixItHeader => howToFixItHeader.Value; - public string ResourcesHeader => resourcesHeader.Value; - } -} diff --git a/src/Integration.Vsix/AsmRef_Integration.Vsix_Baseline_WithStrongNames.txt b/src/Integration.Vsix/AsmRef_Integration.Vsix_Baseline_WithStrongNames.txt index f07c377d5..d4ffa33f9 100644 --- a/src/Integration.Vsix/AsmRef_Integration.Vsix_Baseline_WithStrongNames.txt +++ b/src/Integration.Vsix/AsmRef_Integration.Vsix_Baseline_WithStrongNames.txt @@ -1,7 +1,7 @@ --- ################################ # Assembly references report -# Report date/time: 2024-02-07T13:54:19.6745665Z +# Report date/time: 2024-02-12T09:18:56.2978143Z ################################ # # Generated by Devtility CheckAsmRefs v0.11.0.223 @@ -223,11 +223,10 @@ Referenced assemblies: - 'SonarLint.VisualStudio.Rules, Version=7.7.0.0, Culture=neutral, PublicKeyToken=c5b62af9de6d7244' - 'System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' - 'System.ComponentModel.Composition, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' -- 'System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' - 'System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' - 'System.Xaml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' - 'System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' -# Number of references: 19 +# Number of references: 18 --- Assembly: 'SonarLint.VisualStudio.Infrastructure.VS, Version=7.7.0.0, Culture=neutral, PublicKeyToken=c5b62af9de6d7244' @@ -435,9 +434,8 @@ Referenced assemblies: - 'SonarLint.VisualStudio.Core, Version=7.7.0.0, Culture=neutral, PublicKeyToken=c5b62af9de6d7244' - 'SonarQube.Client, Version=7.7.0.0, Culture=neutral, PublicKeyToken=c5b62af9de6d7244' - 'System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' -- 'System.ComponentModel.Composition, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' - 'System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' -# Number of references: 7 +# Number of references: 6 --- Assembly: 'SonarLint.VisualStudio.SLCore, Version=7.7.0.0, Culture=neutral, PublicKeyToken=c5b62af9de6d7244' diff --git a/src/Integration.Vsix/AsmRef_Integration.Vsix_Baseline_WithoutStrongNames.txt b/src/Integration.Vsix/AsmRef_Integration.Vsix_Baseline_WithoutStrongNames.txt index d52045d9e..db0e833ed 100644 --- a/src/Integration.Vsix/AsmRef_Integration.Vsix_Baseline_WithoutStrongNames.txt +++ b/src/Integration.Vsix/AsmRef_Integration.Vsix_Baseline_WithoutStrongNames.txt @@ -1,7 +1,7 @@ --- ################################ # Assembly references report -# Report date/time: 2024-02-07T13:54:19.6745665Z +# Report date/time: 2024-02-12T09:18:56.2978143Z ################################ # # Generated by Devtility CheckAsmRefs v0.11.0.223 @@ -223,11 +223,10 @@ Referenced assemblies: - 'SonarLint.VisualStudio.Rules, Version=7.7.0.0, Culture=neutral, PublicKeyToken=null' - 'System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' - 'System.ComponentModel.Composition, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' -- 'System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' - 'System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' - 'System.Xaml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' - 'System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' -# Number of references: 19 +# Number of references: 18 --- Assembly: 'SonarLint.VisualStudio.Infrastructure.VS, Version=7.7.0.0, Culture=neutral, PublicKeyToken=null' @@ -435,9 +434,8 @@ Referenced assemblies: - 'SonarLint.VisualStudio.Core, Version=7.7.0.0, Culture=neutral, PublicKeyToken=null' - 'SonarQube.Client, Version=7.7.0.0, Culture=neutral, PublicKeyToken=null' - 'System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' -- 'System.ComponentModel.Composition, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' - 'System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' -# Number of references: 7 +# Number of references: 6 --- Assembly: 'SonarLint.VisualStudio.SLCore, Version=7.7.0.0, Culture=neutral, PublicKeyToken=null' diff --git a/src/Rules.UnitTests/EmbeddedResourceTests.cs b/src/Rules.UnitTests/EmbeddedResourceTests.cs deleted file mode 100644 index d93329a6d..000000000 --- a/src/Rules.UnitTests/EmbeddedResourceTests.cs +++ /dev/null @@ -1,120 +0,0 @@ -/* - * SonarLint for Visual Studio - * Copyright (C) 2016-2024 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -using System; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Xml; -using FluentAssertions; -using Microsoft.VisualStudio.TestTools.UnitTesting; - -namespace SonarLint.VisualStudio.Rules.UnitTests -{ - /// - /// Tests that the assembly contains the expected embedded resources - /// - [TestClass] - public class EmbeddedResourceTests - { - private const string BaseResourcePath = "SonarLint.VisualStudio.Rules.Embedded."; - - [TestMethod] - [DataRow("c", 1200)] - [DataRow("cpp", 500)] - [DataRow("javascript", 200)] - [DataRow("typescript", 200)] - [DataRow("csharpsquid", 350)] - [DataRow("vbnet", 140)] - public void CheckEmbeddedDescriptionFiles_ByLanguage(string repoKey, int atLeastXRules) - { - // Sanity check that the number of rules for each language is at least in the right ballpark. - - // We don't check an exact number as we don't want to have to update this test every time - // we update the analyzers. - - // TODO: embed the rule json file, and use that to check for the expected rules - var resourceNames = typeof(LocalRuleMetadataProvider).Assembly.GetManifestResourceNames() - .Where(x => x.StartsWith($"{BaseResourcePath}{repoKey}") && x.EndsWith(".json")); - - Console.WriteLine($"{repoKey}: number of rules = {resourceNames.Count()}"); - foreach (var resourceName in resourceNames) - { - Console.WriteLine(resourceName); - } - - resourceNames.Should().HaveCountGreaterThan(atLeastXRules); - } - - [TestMethod] - public void CheckEmbeddedDescriptionFiles_AreParseableAsXml() - { - // Performance: this test is loading and parsing nearly 2000 files, - // but is still only takes a few hundred milliseconds. - var asm = typeof(LocalRuleMetadataProvider).Assembly; - var resourceNames = asm.GetManifestResourceNames() - .Where(x => x.EndsWith(".desc")); - - Console.WriteLine("Checking embedded files. Count = " + resourceNames.Count()); - var failures = resourceNames.Where(x => !ReadResourceAsXml(asm, x)) - .ToArray(); - - failures.Should().HaveCount(0); - } - - private static bool ReadResourceAsXml(Assembly asm, string fullResourceName) - { - try - { - var readerSettings = new XmlReaderSettings - { - ConformanceLevel = ConformanceLevel.Fragment - }; - using var stream = new StreamReader(asm.GetManifestResourceStream(fullResourceName)); - using var reader = XmlReader.Create(stream, readerSettings); - - while (reader.Read()) { } - } - catch (Exception ex) - { - Console.WriteLine("Failed: " + fullResourceName); - Console.WriteLine(" " + ex.Message); - return false; - } - return true; - } - - [Ignore] // not yet implemented - [TestMethod] - [DataRow("c")] - [DataRow("cpp")] - [DataRow("js")] - [DataRow("ts")] - [DataRow("cs")] - [DataRow("vbnet")] - public void CheckEmbeddedJson_ByLanguage(string languageKey) - { - using var jsonStream = typeof(LocalRuleMetadataProvider).Assembly - .GetManifestResourceStream($"{BaseResourcePath}{languageKey}.rules.json"); - - jsonStream.Should().NotBeNull(); - } - } -} diff --git a/src/Rules.UnitTests/LocalRuleMetadataProvider.RuleInfoDeserializerTests.cs b/src/Rules.UnitTests/LocalRuleMetadataProvider.RuleInfoDeserializerTests.cs deleted file mode 100644 index 130e00a63..000000000 --- a/src/Rules.UnitTests/LocalRuleMetadataProvider.RuleInfoDeserializerTests.cs +++ /dev/null @@ -1,80 +0,0 @@ -/* - * SonarLint for Visual Studio - * Copyright (C) 2016-2024 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -using FluentAssertions; -using Microsoft.VisualStudio.TestTools.UnitTesting; - -namespace SonarLint.VisualStudio.Rules.UnitTests -{ - [TestClass] - public class RuleInfoJsonDeserializerTests - { - [TestMethod] - public void Deserialize() - { - const string data = @"{ - 'FullRuleKey': 'javascript:S6509', - 'Name': 'Extra boolean casts should be removed', - 'Severity': 3, - 'IssueType': 0, - 'IsActiveByDefault': true, - 'LanguageKey': 'js', - 'Description': 'description', - 'Tags': [], - 'DescriptionSections': [ - { - 'Key': 'introduction', - 'HtmlContent': 'content1', - 'Context': null - }, - { - 'Key': 'root_cause', - 'HtmlContent': 'content2', - 'Context': - { - 'Key': 'context key', - 'DisplayName': 'context display name' - } - } - ], - 'EducationPrinciples': [ 'aaa', 'bbb' ], - 'HtmlNote': null -}"; - - var actual = LocalRuleMetadataProvider.RuleInfoJsonDeserializer.Deserialize(data); - - actual.Should().NotBeNull(); - actual.DescriptionSections.Should().HaveCount(2); - actual.DescriptionSections[0].Key.Should().Be("introduction"); - actual.DescriptionSections[0].HtmlContent.Should().Be("content1"); - actual.DescriptionSections[0].Context.Should().BeNull(); - - actual.DescriptionSections[1].Key.Should().Be("root_cause"); - actual.DescriptionSections[1].HtmlContent.Should().Be("content2"); - actual.DescriptionSections[1].Context.Should().NotBeNull(); - actual.DescriptionSections[1].Context.Key.Should().Be("context key"); - actual.DescriptionSections[1].Context.DisplayName.Should().Be("context display name"); - - actual.EducationPrinciples.Should().HaveCount(2); - actual.EducationPrinciples[0].Should().Be("aaa"); - actual.EducationPrinciples[1].Should().Be("bbb"); - } - } -} diff --git a/src/Rules.UnitTests/LocalRuleMetadataProviderTests.cs b/src/Rules.UnitTests/LocalRuleMetadataProviderTests.cs deleted file mode 100644 index 863588cc0..000000000 --- a/src/Rules.UnitTests/LocalRuleMetadataProviderTests.cs +++ /dev/null @@ -1,127 +0,0 @@ -/* - * SonarLint for Visual Studio - * Copyright (C) 2016-2024 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -using System; -using System.IO; -using System.Linq; -using FluentAssertions; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using SonarLint.VisualStudio.Core; -using SonarLint.VisualStudio.TestInfrastructure; - -namespace SonarLint.VisualStudio.Rules.UnitTests -{ - [TestClass] - public class LocalRuleMetadataProviderTests - { - [TestMethod] - public void MefCtor_CheckIsExported() - { - MefTestHelpers.CheckTypeCanBeImported( - MefTestHelpers.CreateExport()); - } - - [TestMethod] - public void GetRuleHelp_UnknownRepo_ReturnsNullp() - { - var ruleId = new SonarCompositeRuleId("unknown repo key", "S100"); - - var testSubject = CreateTestSubject(); - - var actual = testSubject.GetRuleInfo(ruleId); - - actual.Should().BeNull(); - } - - [TestMethod] - public void GetRuleHelp_UnknownRuleKey_ReturnsMissingHelp() - { - var ruleId = new SonarCompositeRuleId("cpp", "unknown rule key"); - - var testSubject = CreateTestSubject(); - - var actual = testSubject.GetRuleInfo(ruleId); - - actual.Should().BeNull(); - } - - [TestMethod] - public void GetRuleHelp_CheckAllRules() - { - // Perf: this checks around 2000 embedded resources currently, but only - // takes < 0.5 seconds to run locally. - - // Note: this test isn't checking that the correct resources are embedded. - // That is done by the EmbeddedResourceTests class. - - var testSubject = CreateTestSubject(); - var resourceNames = testSubject.GetType().Assembly.GetManifestResourceNames() - .Where(x => x.EndsWith(".json")); - - Console.WriteLine("Number of embedded rule descriptions: " + resourceNames.Count()); - - foreach (var name in resourceNames) - { - CheckRule(name); - } - - void CheckRule(string fullResourceName) - { - Console.WriteLine("Checking " + fullResourceName); - - SonarCompositeRuleId ruleId = GetCompositeRuleIdFromResourceName(fullResourceName); - var expectedRuleInfo = GetEmbeddedRuleInfo(fullResourceName); - - var actual = testSubject.GetRuleInfo(ruleId); - - actual.FullRuleKey.Should().Be(ruleId.ToString()); - actual.Description.Should().Be(expectedRuleInfo.Description); - actual.DescriptionSections.Should().BeEquivalentTo(expectedRuleInfo.DescriptionSections); - actual.DescriptionSections.All(section => !string.IsNullOrWhiteSpace(section.HtmlContent)).Should().BeTrue(); - - (!string.IsNullOrWhiteSpace(actual.Description) || actual.DescriptionSections.Count > 0) - .Should() - .BeTrue(); - } - } - - private static LocalRuleMetadataProvider CreateTestSubject() - => new LocalRuleMetadataProvider(new TestLogger(logToConsole: true)); - - private static SonarCompositeRuleId GetCompositeRuleIdFromResourceName(string fullResourceName) - { - // Names are expected to be in the format: - // SonarLint.VisualStudio.Rules.Embedded.{repo key}.{rule key} - // e.g. SonarLint.VisualStudio.Rules.Embedded.cpp.S101.json - var parts = fullResourceName.Split('.'); - var repoKey = parts[parts.Length - 3]; - var ruleKey = parts[parts.Length - 2]; - - return new SonarCompositeRuleId(repoKey, ruleKey); - } - - private static IRuleInfo GetEmbeddedRuleInfo(string fullResourceName) - { - using var reader = new StreamReader(typeof(LocalRuleMetadataProvider).Assembly.GetManifestResourceStream(fullResourceName)); - var data = reader.ReadToEnd(); - return LocalRuleMetadataProvider.RuleInfoJsonDeserializer.Deserialize(data); - } - } -} diff --git a/src/Rules.UnitTests/RuleExtensionTests.cs b/src/Rules.UnitTests/RuleExtensionTests.cs index c6fe72cfd..25fd9ba11 100644 --- a/src/Rules.UnitTests/RuleExtensionTests.cs +++ b/src/Rules.UnitTests/RuleExtensionTests.cs @@ -109,33 +109,5 @@ public void ToRuleIssueType_Converts(SonarQubeIssueType input, RuleIssueType exp actualResult.Should().Be(expectedResult); } - - [TestMethod] - public void ToDescriptionSection_HasContext_Converts() - { - var testSubject = new SonarQubeDescriptionSection("Key", "htmlContent", new SonarQubeContext("DisplayName", "ContextKey")); - - var result = testSubject.ToDescriptionSection(); - - result.Key.Should().Be("Key"); - result.HtmlContent.Should().Be("htmlContent"); - - result.Context.Should().NotBeNull(); - result.Context.Key.Should().Be("ContextKey"); - result.Context.DisplayName.Should().Be("DisplayName"); - } - - [TestMethod] - public void ToDescriptionSection_HasNotContext_ConvertsWithNullContext() - { - var testSubject = new SonarQubeDescriptionSection("Key", "htmlContent", null); - - var result = testSubject.ToDescriptionSection(); - - result.Key.Should().Be("Key"); - result.HtmlContent.Should().Be("htmlContent"); - - result.Context.Should().BeNull(); - } } } diff --git a/src/Rules.UnitTests/RuleHelpTests.cs b/src/Rules.UnitTests/RuleHelpTests.cs index 9e9794ee3..df4cf4707 100644 --- a/src/Rules.UnitTests/RuleHelpTests.cs +++ b/src/Rules.UnitTests/RuleHelpTests.cs @@ -29,103 +29,50 @@ namespace SonarLint.VisualStudio.Rules.UnitTests [TestClass] public class RuleHelpTests { - [TestMethod] - public void Context_Ctor_SetsProperties() - { - var testSubject = new Context("some key", "some display name"); - testSubject.Key.Should().Be("some key"); - testSubject.DisplayName.Should().Be("some display name"); - } - - [TestMethod] - public void DescriptionSection_Ctor_SetsProperties() - { - var context = new Context("some context key", "some display name"); - var testSubject = new DescriptionSection("some descriptionSection key", "some htmlcontent", context); - testSubject.Key.Should().Be("some descriptionSection key"); - testSubject.HtmlContent.Should().Be("some htmlcontent"); - testSubject.Context.Should().Be(context); - } - - [TestMethod] - public void DescriptionSection_NoContext_Ctor_SetsProperties() - { - var testSubject = new DescriptionSection("some descriptionSection key", "some htmlcontent"); - testSubject.Key.Should().Be("some descriptionSection key"); - testSubject.HtmlContent.Should().Be("some htmlcontent"); - testSubject.Context.Should().BeNull(); - } - - [TestMethod] - public void Ctor_SetsProperties() - { - var context = new Context("some context key", "some display name"); - var descriptionSection1 = new DescriptionSection("some descriptionSection key 1", "some htmlcontent 1", context); - var descriptionSection2 = new DescriptionSection("some descriptionSection key 2", "some htmlcontent 2"); - var descriptionSections = new[] { descriptionSection1, descriptionSection2 }; - - var educationPrinciples = new[] { "defense_in_depth", "never_trust_user_input" }; - var defaultImpacts = new Dictionary(); - defaultImpacts.Add(SoftwareQuality.Maintainability, SoftwareQualitySeverity.Medium); - defaultImpacts.Add(SoftwareQuality.Reliability, SoftwareQualitySeverity.Low); - - var tags = new string[] { "convention", "bad-practice" }; - - var testSubject = new RuleInfo( - Language.CSharp.ServerLanguage.Key, - "xxx:S123", - "a description", - "the rule name", - RuleIssueSeverity.Blocker, - RuleIssueType.Vulnerability, - isActiveByDefault: true, - tags, - descriptionSections, - educationPrinciples, - "some user note", - CleanCodeAttribute.Respectful, - defaultImpacts); - - testSubject.LanguageKey.Should().Be(Language.CSharp.ServerLanguage.Key); - testSubject.FullRuleKey.Should().Be("xxx:S123"); - testSubject.Description.Should().Be("a description"); - testSubject.Name.Should().Be("the rule name"); - testSubject.Severity.Should().Be(RuleIssueSeverity.Blocker); - testSubject.IssueType.Should().Be(RuleIssueType.Vulnerability); - testSubject.IsActiveByDefault.Should().BeTrue(); - testSubject.Tags.Should().BeEquivalentTo(tags); - testSubject.DescriptionSections.Should().BeEquivalentTo(descriptionSections); - testSubject.EducationPrinciples.Should().BeEquivalentTo(educationPrinciples); - testSubject.HtmlNote.Should().Be("some user note"); - testSubject.CleanCodeAttribute.Should().Be(CleanCodeAttribute.Respectful); - testSubject.DefaultImpacts.Should().BeEquivalentTo(defaultImpacts); - } - - [TestMethod] - public void WithOverridenHtmlNote_CreatesNewCopy() - { - var testSubject = new RuleInfo( - Language.CSharp.ServerLanguage.Key, - "xxx:S123", - null, - null, - RuleIssueSeverity.Blocker, - RuleIssueType.Unknown, - true, - null, - null, - null, - "some user note", - null, - null); - - var result = testSubject.WithServerOverride(RuleIssueSeverity.Major, "new Note"); - - result.Should().NotBe(testSubject); - result.LanguageKey.Should().Be(Language.CSharp.ServerLanguage.Key); - result.FullRuleKey.Should().Be("xxx:S123"); - result.Severity.Should().Be(RuleIssueSeverity.Major); - result.HtmlNote.Should().Be("new Note"); - } + + // [TestMethod] + // public void Ctor_SetsProperties() + // { + // var context = new Context("some context key", "some display name"); + // var descriptionSection1 = new DescriptionSection("some descriptionSection key 1", "some htmlcontent 1", context); + // var descriptionSection2 = new DescriptionSection("some descriptionSection key 2", "some htmlcontent 2"); + // var descriptionSections = new[] { descriptionSection1, descriptionSection2 }; + // + // var educationPrinciples = new[] { "defense_in_depth", "never_trust_user_input" }; + // var defaultImpacts = new Dictionary(); + // defaultImpacts.Add(SoftwareQuality.Maintainability, SoftwareQualitySeverity.Medium); + // defaultImpacts.Add(SoftwareQuality.Reliability, SoftwareQualitySeverity.Low); + // + // var tags = new string[] { "convention", "bad-practice" }; + // + // var testSubject = new RuleInfo( + // Language.CSharp.ServerLanguage.Key, + // "xxx:S123", + // "a description", + // "the rule name", + // RuleIssueSeverity.Blocker, + // RuleIssueType.Vulnerability, + // isActiveByDefault: true, + // tags, + // descriptionSections, + // educationPrinciples, + // "some user note", + // CleanCodeAttribute.Respectful, + // defaultImpacts); + // + // testSubject.LanguageKey.Should().Be(Language.CSharp.ServerLanguage.Key); + // testSubject.FullRuleKey.Should().Be("xxx:S123"); + // testSubject.Description.Should().Be("a description"); + // testSubject.Name.Should().Be("the rule name"); + // testSubject.Severity.Should().Be(RuleIssueSeverity.Blocker); + // testSubject.IssueType.Should().Be(RuleIssueType.Vulnerability); + // testSubject.IsActiveByDefault.Should().BeTrue(); + // testSubject.Tags.Should().BeEquivalentTo(tags); + // testSubject.DescriptionSections.Should().BeEquivalentTo(descriptionSections); + // testSubject.EducationPrinciples.Should().BeEquivalentTo(educationPrinciples); + // testSubject.HtmlNote.Should().Be("some user note"); + // testSubject.CleanCodeAttribute.Should().Be(CleanCodeAttribute.Respectful); + // testSubject.DefaultImpacts.Should().BeEquivalentTo(defaultImpacts); + // } } } diff --git a/src/Rules.UnitTests/RuleInfoExtensionsTests.cs b/src/Rules.UnitTests/RuleInfoExtensionsTests.cs deleted file mode 100644 index 39f3ef6d8..000000000 --- a/src/Rules.UnitTests/RuleInfoExtensionsTests.cs +++ /dev/null @@ -1,66 +0,0 @@ -/* - * SonarLint for Visual Studio - * Copyright (C) 2016-2024 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -using System.Collections.Generic; -using FluentAssertions; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using Moq; - -namespace SonarLint.VisualStudio.Rules.UnitTests; - -[TestClass] -public class RuleInfoExtensionsTests -{ - [TestMethod] - public void IsRich_DescriptionSectionsNull_False() - { - var testSubject = new Mock(); - testSubject.SetupGet(x => x.DescriptionSections).Returns((IReadOnlyList)null); - - testSubject.Object.IsRichRuleDescription().Should().BeFalse(); - } - - [TestMethod] - public void IsRich_DescriptionSectionsEmpty_False() - { - var testSubject = new Mock(); - testSubject.SetupGet(x => x.DescriptionSections).Returns(new List()); - - testSubject.Object.IsRichRuleDescription().Should().BeFalse(); - } - - [TestMethod] - public void IsRich_DescriptionSectionsHasOneMember_False() - { - var testSubject = new Mock(); - testSubject.SetupGet(x => x.DescriptionSections).Returns(new List { new DescriptionSection(null, null) }); - - testSubject.Object.IsRichRuleDescription().Should().BeFalse(); - } - - [TestMethod] - public void IsRich_DescriptionSectionsHasMoreThanOneMember_True() - { - var testSubject = new Mock(); - testSubject.SetupGet(x => x.DescriptionSections).Returns(new List { new DescriptionSection(null, null), new DescriptionSection(null, null) }); - - testSubject.Object.IsRichRuleDescription().Should().BeTrue(); - } -} diff --git a/src/Rules.UnitTests/RuleInfoTests.cs b/src/Rules.UnitTests/RuleInfoTests.cs index 679cf8e66..fc71f9f52 100644 --- a/src/Rules.UnitTests/RuleInfoTests.cs +++ b/src/Rules.UnitTests/RuleInfoTests.cs @@ -29,81 +29,81 @@ namespace SonarLint.VisualStudio.Rules.UnitTests [TestClass] public class RuleInfoTests { - [TestMethod] - public void Ctor_NullCollectionsAreAllowed_SetToEmptyCollections() - { - var testSubject = new RuleInfo( - languageKey: null, - fullRuleKey: null, - description: null, - name: null, - RuleIssueSeverity.Unknown, - RuleIssueType.Unknown, - isActiveByDefault: false, - tags: null, - descriptionSections: null, - educationPrinciples: null, - htmlNote: null, - cleanCodeAttribute: null, - defaultImpacts: null); - - testSubject.Tags.Should().NotBeNull(); - testSubject.DescriptionSections.Should().NotBeNull(); - testSubject.EducationPrinciples.Should().NotBeNull(); - - testSubject.Tags.Should().HaveCount(0); - testSubject.DescriptionSections.Should().HaveCount(0); - testSubject.EducationPrinciples.Should().HaveCount(0); - } - - [TestMethod] - public void WithCleanCodeTaxonomyDisabled_SetsCctPropertiesToNull() - { - var languageKey = "any"; - var fullRuleKey = "any"; - var description = "any"; - var name = "any"; - var ruleIssueSeverity = RuleIssueSeverity.Critical; - var ruleIssueType = RuleIssueType.Bug; - var isActiveByDefault = true; - IReadOnlyList tags = new []{ "any"}; - IReadOnlyList descriptionSections = Array.Empty(); - IReadOnlyList educationPrinciples = Array.Empty(); - var htmlNote = "any"; - CleanCodeAttribute? cleanCodeAttribute = CleanCodeAttribute.Focused; - Dictionary defaultImpacts = new Dictionary(); - - var testSubject = new RuleInfo( - languageKey, - fullRuleKey, - description, - name, - ruleIssueSeverity, - ruleIssueType, - isActiveByDefault, - tags, - descriptionSections, - educationPrinciples, - htmlNote, - cleanCodeAttribute, - defaultImpacts); - - var expected = new RuleInfo( - languageKey, - fullRuleKey, - description, - name, - ruleIssueSeverity, - ruleIssueType, - isActiveByDefault, - tags, - descriptionSections, - educationPrinciples, - htmlNote, - null, - null); - - testSubject.WithCleanCodeTaxonomyDisabled().Should().BeEquivalentTo(expected); - } + // [TestMethod] + // public void Ctor_NullCollectionsAreAllowed_SetToEmptyCollections() + // { + // var testSubject = new RuleInfo( + // languageKey: null, + // fullRuleKey: null, + // description: null, + // name: null, + // RuleIssueSeverity.Unknown, + // RuleIssueType.Unknown, + // isActiveByDefault: false, + // tags: null, + // descriptionSections: null, + // educationPrinciples: null, + // htmlNote: null, + // cleanCodeAttribute: null, + // defaultImpacts: null); + // + // testSubject.Tags.Should().NotBeNull(); + // testSubject.DescriptionSections.Should().NotBeNull(); + // testSubject.EducationPrinciples.Should().NotBeNull(); + // + // testSubject.Tags.Should().HaveCount(0); + // testSubject.DescriptionSections.Should().HaveCount(0); + // testSubject.EducationPrinciples.Should().HaveCount(0); + // } + // + // [TestMethod] + // public void WithCleanCodeTaxonomyDisabled_SetsCctPropertiesToNull() + // { + // var languageKey = "any"; + // var fullRuleKey = "any"; + // var description = "any"; + // var name = "any"; + // var ruleIssueSeverity = RuleIssueSeverity.Critical; + // var ruleIssueType = RuleIssueType.Bug; + // var isActiveByDefault = true; + // IReadOnlyList tags = new []{ "any"}; + // IReadOnlyList descriptionSections = Array.Empty(); + // IReadOnlyList educationPrinciples = Array.Empty(); + // var htmlNote = "any"; + // CleanCodeAttribute? cleanCodeAttribute = CleanCodeAttribute.Focused; + // Dictionary defaultImpacts = new Dictionary(); + // + // var testSubject = new RuleInfo( + // languageKey, + // fullRuleKey, + // description, + // name, + // ruleIssueSeverity, + // ruleIssueType, + // isActiveByDefault, + // tags, + // descriptionSections, + // educationPrinciples, + // htmlNote, + // cleanCodeAttribute, + // defaultImpacts); + // + // var expected = new RuleInfo( + // languageKey, + // fullRuleKey, + // description, + // name, + // ruleIssueSeverity, + // ruleIssueType, + // isActiveByDefault, + // tags, + // descriptionSections, + // educationPrinciples, + // htmlNote, + // null, + // null); + // + // testSubject.WithCleanCodeTaxonomyDisabled().Should().BeEquivalentTo(expected); + // } } } diff --git a/src/Rules.UnitTests/RuleMetaDataProviderTests.cs b/src/Rules.UnitTests/RuleMetaDataProviderTests.cs deleted file mode 100644 index b565c2d17..000000000 --- a/src/Rules.UnitTests/RuleMetaDataProviderTests.cs +++ /dev/null @@ -1,291 +0,0 @@ -/* - * SonarLint for Visual Studio - * Copyright (C) 2016-2024 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; -using FluentAssertions; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using Moq; -using SonarLint.VisualStudio.Core; -using SonarLint.VisualStudio.Core.Binding; -using SonarLint.VisualStudio.Core.Configuration; -using SonarLint.VisualStudio.TestInfrastructure; - -namespace SonarLint.VisualStudio.Rules.UnitTests -{ - [TestClass] - public class RuleMetaDataProviderTests - { - [TestMethod] - public void MefCtor_CheckIsExported() - { - MefTestHelpers.CheckTypeCanBeImported( - MefTestHelpers.CreateExport(), - MefTestHelpers.CreateExport(), - MefTestHelpers.CreateExport(), - MefTestHelpers.CreateExport()); - } - - [TestMethod] - public async Task GetRuleInfoAsync_UnknownLanguage_ReturnsNull() - { - var ruleId = new SonarCompositeRuleId("unknown", "S1000"); - var localMetaDataProvider = CreateLocalRuleMetaDataProvider(ruleId, null); - - var serverMetaDataProvider = new Mock(); - - var configurationProvider = CreateConfigurationProvider(); - - RuleMetaDataProvider testSubject = CreateTestSubject(localMetaDataProvider, serverMetaDataProvider, configurationProvider); - - var result = await testSubject.GetRuleInfoAsync(ruleId, CancellationToken.None); - - result.Should().Be(null); - - localMetaDataProvider.Verify(l => l.GetRuleInfo(ruleId), Times.Once); - serverMetaDataProvider.Invocations.Should().BeEmpty(); - configurationProvider.Verify(cp => cp.GetConfiguration(), Times.Once); - } - - [TestMethod] - public async Task GetRuleInfoAsync_NotInConnectedMode_ReturnsLocal() - { - var ruleId = new SonarCompositeRuleId("csharpsquid", "S1000"); - var localRule = CreateRuleInfo("csharpsquid", "csharpsquid:S1000"); - var localMetaDataProvider = CreateLocalRuleMetaDataProvider(ruleId, localRule); - - var serverMetaDataProvider = CreateServerRuleMetaDataProvider(); - - var configurationProvider = CreateConfigurationProvider(); - - RuleMetaDataProvider testSubject = CreateTestSubject(localMetaDataProvider, serverMetaDataProvider, configurationProvider); - - var result = await testSubject.GetRuleInfoAsync(ruleId, CancellationToken.None); - - result.Should().Be(localRule); - - localMetaDataProvider.Verify(l => l.GetRuleInfo(ruleId), Times.Once); - serverMetaDataProvider.VerifyNoOtherCalls(); - configurationProvider.Verify(cp => cp.GetConfiguration(), Times.Once); - } - - [TestMethod] - public async Task GetRuleInfoAsync_QualityProfileNotFound_ReturnsLocal() - { - var ruleId = new SonarCompositeRuleId("csharpsquid", "S1000"); - var localRule = CreateRuleInfo("csharpsquid", "csharpsquid:S1000"); - var localMetaDataProvider = CreateLocalRuleMetaDataProvider(ruleId, localRule); - - var serverMetaDataProvider = CreateServerRuleMetaDataProvider(); - - var profiles = new Dictionary { { Language.Js, new ApplicableQualityProfile { ProfileKey = "Profile Key 1" } } }; - var configurationProvider = CreateConfigurationProvider(profiles); - - RuleMetaDataProvider testSubject = CreateTestSubject(localMetaDataProvider, serverMetaDataProvider, configurationProvider); - - var result = await testSubject.GetRuleInfoAsync(ruleId, CancellationToken.None); - - result.Should().Be(localRule); - - localMetaDataProvider.Verify(l => l.GetRuleInfo(ruleId), Times.Once); - serverMetaDataProvider.VerifyNoOtherCalls(); - configurationProvider.Verify(cp => cp.GetConfiguration(), Times.Once); - } - - [TestMethod] - public async Task GetRuleInfoAsync_RemoteRuleExists_OverrideSeverityAndHtmlNote() - { - var ruleId = new SonarCompositeRuleId("csharpsquid", "S1000"); - var localRule = CreateRuleInfo("csharpsquid", "csharpsquid:S1000", description: "Local Description"); - var localMetaDataProvider = CreateLocalRuleMetaDataProvider(ruleId, localRule); - - var serverRule = CreateRuleInfo("csharpsquid", "csharpsquid:S1000", description: "Server Description", htmlNote: "Extended Rule Description", defaultSeverity: RuleIssueSeverity.Critical); - var serverMetaDataProvider = CreateServerRuleMetaDataProvider(ruleId, serverRule, "CSharp Profile Key"); - - var profiles = new Dictionary { { Language.Js, new ApplicableQualityProfile { ProfileKey = "Profile Key 1" } }, { Language.CSharp, new ApplicableQualityProfile { ProfileKey = "CSharp Profile Key" } } }; - var configurationProvider = CreateConfigurationProvider(profiles); - - RuleMetaDataProvider testSubject = CreateTestSubject(localMetaDataProvider, serverMetaDataProvider, configurationProvider); - - var result = await testSubject.GetRuleInfoAsync(ruleId, CancellationToken.None); - - result.Should().NotBe(localRule); - result.Severity.Should().Be(RuleIssueSeverity.Critical); - result.HtmlNote.Should().Be("Extended Rule Description"); - result.Description.Should().Be("Local Description"); - - localMetaDataProvider.Verify(l => l.GetRuleInfo(ruleId), Times.Once); - serverMetaDataProvider.Verify(s => s.GetRuleInfoAsync(ruleId, "CSharp Profile Key", CancellationToken.None), Times.Once); - serverMetaDataProvider.VerifyNoOtherCalls(); - configurationProvider.Verify(cp => cp.GetConfiguration(), Times.Once); - } - - [TestMethod] - public async Task GetRuleInfoAsync_LocalRuleDoesNotExistRemoteRuleExists_ReturnServerRule() - { - var ruleId = new SonarCompositeRuleId("csharpsquid", "S1000"); - - var localMetaDataProvider = CreateLocalRuleMetaDataProvider(); - - var serverRule = CreateRuleInfo("csharpsquid", "csharpsquid:S1000", description: "Server Description", htmlNote: "Extended Rule Description", defaultSeverity: RuleIssueSeverity.Critical); - var serverMetaDataProvider = CreateServerRuleMetaDataProvider(ruleId, serverRule, "CSharp Profile Key"); - - var profiles = new Dictionary { { Language.Js, new ApplicableQualityProfile { ProfileKey = "Profile Key 1" } }, { Language.CSharp, new ApplicableQualityProfile { ProfileKey = "CSharp Profile Key" } } }; - var configurationProvider = CreateConfigurationProvider(profiles); - - RuleMetaDataProvider testSubject = CreateTestSubject(localMetaDataProvider, serverMetaDataProvider, configurationProvider); - - var result = await testSubject.GetRuleInfoAsync(ruleId, CancellationToken.None); - - result.Should().Be(serverRule); - result.Severity.Should().Be(RuleIssueSeverity.Critical); - result.HtmlNote.Should().Be("Extended Rule Description"); - result.Description.Should().Be("Server Description"); - - localMetaDataProvider.Verify(l => l.GetRuleInfo(ruleId), Times.Once); - serverMetaDataProvider.Verify(s => s.GetRuleInfoAsync(ruleId, "CSharp Profile Key", CancellationToken.None), Times.Once); - serverMetaDataProvider.VerifyNoOtherCalls(); - configurationProvider.Verify(cp => cp.GetConfiguration(), Times.Once); - } - - [DataRow(true)] - [DataRow(false)] - [DataTestMethod] - public async Task GetRuleInfoAsync_DisablesCCT_BasedOnFeatureConfiguration(bool isEnabled) - { - var ruleId = new SonarCompositeRuleId("csharpsquid", "S1000"); - var ruleInfoMock = new Mock(); - var metadataProviderMock = new Mock(); - metadataProviderMock - .Setup(x => x.GetRuleInfo(It.IsAny())) - .Returns(ruleInfoMock.Object); - var connectedModeFeaturesConfiguration = CreateFeatureConfigurationMock(isEnabled); - - var testSubject = CreateTestSubject(metadataProviderMock, - Mock.Of>(), - CreateConfigurationProvider(), - connectedModeFeaturesConfiguration); - - await testSubject.GetRuleInfoAsync(ruleId, CancellationToken.None); - - connectedModeFeaturesConfiguration.Verify(x => x.IsNewCctAvailable(), Times.Once); - ruleInfoMock.Verify(x => x.WithCleanCodeTaxonomyDisabled(), Times.Exactly(!isEnabled ? 1 : 0)); - } - - [TestMethod] - public async Task GetRuleInfoAsync_DisablesCCTForHotspotsRegardlessOfConfiguration() - { - var ruleId = new SonarCompositeRuleId("csharpsquid", "S1000"); - var ruleInfoMock = new Mock(); - ruleInfoMock.SetupGet(x => x.IssueType).Returns(RuleIssueType.Hotspot); - var metadataProviderMock = new Mock(); - metadataProviderMock - .Setup(x => x.GetRuleInfo(It.IsAny())) - .Returns(ruleInfoMock.Object); - var connectedModeFeaturesConfiguration = CreateFeatureConfigurationMock(true); - - var testSubject = CreateTestSubject(metadataProviderMock, - Mock.Of>(), - CreateConfigurationProvider(), - connectedModeFeaturesConfiguration); - - await testSubject.GetRuleInfoAsync(ruleId, CancellationToken.None); - - connectedModeFeaturesConfiguration.Verify(x => x.IsNewCctAvailable(), Times.Never); - ruleInfoMock.Verify(x => x.WithCleanCodeTaxonomyDisabled(), Times.Once); - } - - #region Helper Methods - - private static Mock CreateServerRuleMetaDataProvider(SonarCompositeRuleId ruleId = null, - IRuleInfo serverRule = null, - string qualityProfile = null) - { - var serverMetaDataProvider = new Mock(); - serverMetaDataProvider.Setup(s => s.GetRuleInfoAsync(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync((IRuleInfo)null); - serverMetaDataProvider.Setup(s => s.GetRuleInfoAsync(ruleId, qualityProfile, It.IsAny())).ReturnsAsync(serverRule); - return serverMetaDataProvider; - } - - private static Mock CreateConfigurationProvider(Dictionary profiles = null) - { - var configurationProvider = new Mock(); - - if (profiles == null) - { - configurationProvider.Setup(cp => cp.GetConfiguration()).Returns(BindingConfiguration.Standalone); - } - else - { - var project = new BoundSonarQubeProject { Profiles = profiles }; - var config = new BindingConfiguration(project, SonarLintMode.Connected, "dir"); - configurationProvider.Setup(cp => cp.GetConfiguration()).Returns(config); - } - return configurationProvider; - } - - private static RuleMetaDataProvider CreateTestSubject(Mock localMetaDataProvider, - Mock serverMetaDataProvider, - Mock configurationProvider, - Mock connectedModeFeaturesConfiguration = null) - { - var defaultCctConfig = CreateFeatureConfigurationMock(true); - - return new RuleMetaDataProvider(localMetaDataProvider.Object, - serverMetaDataProvider.Object, - configurationProvider.Object, - (connectedModeFeaturesConfiguration ?? defaultCctConfig).Object); - } - - private static Mock CreateFeatureConfigurationMock(bool isEnabled) - { - var defaultCctConfig = new Mock(); - defaultCctConfig.Setup(x => x.IsNewCctAvailable()).Returns(isEnabled); - return defaultCctConfig; - } - - private static Mock CreateLocalRuleMetaDataProvider(SonarCompositeRuleId ruleId = null, IRuleInfo localRule = null) - { - var localMetaDataProvider = new Mock(); - localMetaDataProvider.Setup(l => l.GetRuleInfo(It.IsAny())).Returns(null); - localMetaDataProvider.Setup(l => l.GetRuleInfo(ruleId)).Returns(localRule); - return localMetaDataProvider; - } - - private static IRuleInfo CreateRuleInfo( - string languageKey, - string fullRuleKey, - string description = "Description", - string name = "Name", - RuleIssueSeverity defaultSeverity = RuleIssueSeverity.Unknown, - RuleIssueType issueType = RuleIssueType.Unknown, - bool isActiveByDefault = true, - IReadOnlyList tags = null, - IReadOnlyList descriptionSections = null, - IReadOnlyList educationPrinciples = null, - string htmlNote = null) - { - return new RuleInfo(languageKey, fullRuleKey, description, name, defaultSeverity, issueType, isActiveByDefault, tags, descriptionSections, educationPrinciples, htmlNote, null, null); - } - - #endregion - } -} diff --git a/src/Rules.UnitTests/ServerRuleMetadataProviderTests.cs b/src/Rules.UnitTests/ServerRuleMetadataProviderTests.cs deleted file mode 100644 index f6fdc9574..000000000 --- a/src/Rules.UnitTests/ServerRuleMetadataProviderTests.cs +++ /dev/null @@ -1,191 +0,0 @@ -/* - * SonarLint for Visual Studio - * Copyright (C) 2016-2024 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; -using FluentAssertions; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using Moq; -using SonarLint.VisualStudio.Core; -using SonarLint.VisualStudio.Core.Analysis; -using SonarLint.VisualStudio.TestInfrastructure; -using SonarQube.Client; -using SonarQube.Client.Models; - -namespace SonarLint.VisualStudio.Rules.UnitTests -{ - [TestClass] - public class ServerRuleMetadataProviderTests - { - [TestMethod] - public async Task GetRuleInfoAsync_RuleFound_ReturnRuleInfo() - { - var service = new Mock(); - - var parameters = new Dictionary { { "parameter Key 1", "parameter Value 1" }, { "parameter Key 2", "parameter Value 2" } }; - - var descriptionSection1 = new SonarQubeDescriptionSection("key1", "Content1
", null); - var descriptionSection2 = new SonarQubeDescriptionSection("key2", "Content2", new SonarQubeContext("Display1", "contextKey1")); - var descriptionSection3 = new SonarQubeDescriptionSection("key2", "Content3", new SonarQubeContext("Display1", "contextKey1")); - - var descriptionSections = new[] { descriptionSection1, descriptionSection2, descriptionSection3 }; - - var educationPrinciples = new[] { "principle1", "principle2" }; - - var tags = new[] { "tag1", "tag2" }; - - var sqRule = new SonarQubeRule("Key", - "repoKey", - true, - SonarQubeIssueSeverity.Info, - SonarQubeCleanCodeAttribute.Clear, - new Dictionary{{ SonarQubeSoftwareQuality.Reliability, SonarQubeSoftwareQualitySeverity.Low}}, - parameters, - SonarQubeIssueType.Vulnerability, - "

html Description


", - descriptionSections, - educationPrinciples, - "RuleName", - tags, - "htmlNote
"); - - service.Setup(s => s.GetRuleByKeyAsync("repoKey:Key", It.IsAny(), It.IsAny())).ReturnsAsync(sqRule); - - var testSubject = CreateTestSubject(service.Object); - - var ruleKey = new SonarCompositeRuleId("repoKey", "Key"); - - var result = await testSubject.GetRuleInfoAsync(ruleKey, "qpKey", CancellationToken.None); - - result.Should().NotBeNull(); - - result.LanguageKey.Should().Be("repoKey"); - result.FullRuleKey.Should().Be("repoKey:Key"); - result.Description.Should().Be("

html Description


"); - result.Name.Should().Be("RuleName"); - result.Severity.Should().Be(RuleIssueSeverity.Info); - result.IssueType.Should().Be(RuleIssueType.Vulnerability); - result.IsActiveByDefault.Should().BeTrue(); - result.Tags.Should().BeEquivalentTo(tags); - result.EducationPrinciples.Should().BeEquivalentTo(educationPrinciples); - result.HtmlNote.Should().Be("htmlNote
"); - result.CleanCodeAttribute.Should().Be(CleanCodeAttribute.Clear); - result.DefaultImpacts.Should().BeEquivalentTo(new Dictionary{ - { SoftwareQuality.Reliability, SoftwareQualitySeverity.Low}}); - - result.DescriptionSections.Count.Should().Be(3); - - for (int i = 0; i < 3; i++) - { - result.DescriptionSections[i].Key.Should().Be(descriptionSections[i].Key); - result.DescriptionSections[i].HtmlContent.Should().Be(descriptionSections[i].HtmlContent.Replace("
", "
")); - - if (result.DescriptionSections[i].Context == null) - { - descriptionSections[i].Context.Should().BeNull(); - continue; - } - - result.DescriptionSections[i].Context.Key.Should().Be(descriptionSections[i].Context.Key); - result.DescriptionSections[i].Context.DisplayName.Should().Be(descriptionSections[i].Context.DisplayName); - } - } - - [TestMethod] // Regression test for part of #3973 - public async Task GetRuleInfoAsync_RuleFound_ServerCollectionsFieldsAreNull_RuleInfoFieldsAreNotNull() - { - var service = new Mock(); - var sqRule = new SonarQubeRule("Key", - "repoKey", - true, - SonarQubeIssueSeverity.Info, - SonarQubeCleanCodeAttribute.Clear, - new Dictionary{{ SonarQubeSoftwareQuality.Reliability, SonarQubeSoftwareQualitySeverity.Low}}, - null, // parameters, - SonarQubeIssueType.Vulnerability, - "

html Description


", - null, // descriptionSections - null, // educationPrinciples - "RuleName", - null, // tags - "htmlNote
"); - - service.Setup(s => s.GetRuleByKeyAsync("repoKey:Key", It.IsAny(), It.IsAny())).ReturnsAsync(sqRule); - - var testSubject = CreateTestSubject(service.Object); - - var ruleKey = new SonarCompositeRuleId("repoKey", "Key"); - - var result = await testSubject.GetRuleInfoAsync(ruleKey, "qpKey", CancellationToken.None); - - result.Should().NotBeNull(); - - result.Tags.Should().NotBeNull(); - result.DescriptionSections.Should().NotBeNull(); - result.EducationPrinciples.Should().NotBeNull(); - - result.Tags.Should().HaveCount(0); - result.DescriptionSections.Should().HaveCount(0); - result.EducationPrinciples.Should().HaveCount(0); - } - - [TestMethod] - public async Task GetRuleInfoAsync_RuleNotFound_ReturnNull() - { - var service = new Mock(); - service.Setup(s => s.GetRuleByKeyAsync(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync((SonarQubeRule)null); - - var testSubject = CreateTestSubject(service.Object); - - var ruleKey = new SonarCompositeRuleId("repoKey", "Key"); - - var result = await testSubject.GetRuleInfoAsync(ruleKey, "qpKey", CancellationToken.None); - - result.Should().BeNull(); - } - - [TestMethod] - public async Task GetRuleInfoAsync_GotError_ReturnNull() - { - var service = new Mock(); - service.Setup(s => s.GetRuleByKeyAsync(It.IsAny(), It.IsAny(), It.IsAny())).ThrowsAsync(new Exception("Some server error")); - - var logger = new TestLogger(); - - var testSubject = CreateTestSubject(service.Object, logger); - - var ruleKey = new SonarCompositeRuleId("repoKey", "Key"); - - var result = await testSubject.GetRuleInfoAsync(ruleKey, "qpKey", CancellationToken.None); - - result.Should().BeNull(); - logger.AssertPartialOutputStrings("Some server error"); - } - - private static ServerRuleMetadataProvider CreateTestSubject(ISonarQubeService service, ILogger logger = null) - { - logger ??= new TestLogger(); - - return new ServerRuleMetadataProvider(service, logger); - } - } -} diff --git a/src/Rules/ILocalRuleMetadataProvider.cs b/src/Rules/ILocalRuleMetadataProvider.cs deleted file mode 100644 index b732ce223..000000000 --- a/src/Rules/ILocalRuleMetadataProvider.cs +++ /dev/null @@ -1,113 +0,0 @@ -/* - * SonarLint for Visual Studio - * Copyright (C) 2016-2024 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -using System; -using System.ComponentModel.Composition; -using System.IO; -using Newtonsoft.Json; -using SonarLint.VisualStudio.Core; -using SonarLint.VisualStudio.Core.Helpers; - -namespace SonarLint.VisualStudio.Rules -{ - /// - /// Returns rule metadata - /// - /// - /// The metadata is extracted from the Java plugins using the plugin API - /// - public interface ILocalRuleMetadataProvider - { - /// - /// Fetches rule info for the specified language rule - /// - /// The rule info, or null if the repo key/rule was not recognised - IRuleInfo GetRuleInfo(SonarCompositeRuleId ruleId); - } - - [Export(typeof(ILocalRuleMetadataProvider))] - [PartCreationPolicy(CreationPolicy.Shared)] - public class LocalRuleMetadataProvider : ILocalRuleMetadataProvider - { - private readonly ILogger logger; - - [ImportingConstructor] - public LocalRuleMetadataProvider(ILogger logger) - { - this.logger = logger; - } - - public IRuleInfo GetRuleInfo(SonarCompositeRuleId ruleId) - => LoadRuleInfo(ruleId); - - private IRuleInfo LoadRuleInfo(SonarCompositeRuleId ruleId) - { - var resourcePath = CalcFullResourceName(ruleId); - try - { - using (var stream = GetType().Assembly.GetManifestResourceStream(resourcePath)) - { - if (stream != null) - { - using (var reader = new StreamReader(stream)) - { - var data = reader.ReadToEnd(); - return RuleInfoJsonDeserializer.Deserialize(data); - } - } - } - } - catch (Exception ex) - { - logger.LogVerbose(Resources.MetadataProvider_ErrorLoadingJson, resourcePath, ex); - } - return null; - } - - // e.g. SonarLint.VisualStudio.Rules.Embedded.cpp.S101.json - // e.g. SonarLint.VisualStudio.Rules.Embedded.typescript.S202.json - // e.g. SonarLint.VisualStudio.Rules.Embedded.csharpsquid.S303.json - private static string CalcFullResourceName(SonarCompositeRuleId ruleId) - => $"SonarLint.VisualStudio.Rules.Embedded.{ruleId.RepoKey}.{ruleId.RuleKey}.json"; - - - /// - /// Custom deserializer for rule info JSON - /// - /// - /// RuleInfo has properties that are typed as interfaces, so NewtonSoft.Json needs more info - /// about which concrete types to use when deserializing - /// - public static class RuleInfoJsonDeserializer - { - private static readonly JsonSerializerSettings settings = new JsonSerializerSettings - { - Converters = { - new InterfaceToConcreteTypeConverter(), - new InterfaceToConcreteTypeConverter(), - new InterfaceToConcreteTypeConverter() - } - }; - - public static IRuleInfo Deserialize(string json) - => JsonConvert.DeserializeObject(json, settings); - } - } -} diff --git a/src/Rules/IRuleInfo.cs b/src/Rules/IRuleInfo.cs index 90e93d9dd..a9145f160 100644 --- a/src/Rules/IRuleInfo.cs +++ b/src/Rules/IRuleInfo.cs @@ -47,54 +47,7 @@ public enum RuleIssueType Hotspot, // SonarQube serialization = SECURITY_HOTSPOT Unknown } - - public interface IContext - { - string Key { get; } - string DisplayName { get; } - } - - public class Context : IContext - { - public Context(string key, string displayName) - { - Key = key; - DisplayName = displayName; - } - - public string Key { get; } - public string DisplayName { get; } - } - - public interface IDescriptionSection - { - string Key { get; } - string HtmlContent { get; } - IContext Context { get; } - } - - public class DescriptionSection : IDescriptionSection - { - public DescriptionSection(string key, string htmlContent, IContext context = null) - { - Key = key; - HtmlContent = htmlContent; - Context = context; - } - - public string Key { get; } - public string HtmlContent { get; } - - /// - /// Different contexes for Description Sections - /// - /// - /// These are subtabs for any given tab such as different languages - /// The field is optional - /// - public IContext Context { get; } - } - + /// /// Help data about a single rule, extracted using the Java plugin API /// @@ -126,11 +79,6 @@ public interface IRuleInfo /// IReadOnlyList Tags { get; } - /// - /// Tabs for new educational format. Can be empty. Will not be null. - /// - IReadOnlyList DescriptionSections { get; } - /// /// Education principles for the new educational format. Can be empty. Will not be null. /// @@ -142,8 +90,6 @@ public interface IRuleInfo Dictionary DefaultImpacts { get; } - IRuleInfo WithServerOverride(RuleIssueSeverity newSeverity, string newHtmlNote); - IRuleInfo WithCleanCodeTaxonomyDisabled(); } @@ -151,7 +97,7 @@ public class RuleInfo : IRuleInfo { public RuleInfo(string languageKey, string fullRuleKey, string description, string name, RuleIssueSeverity severity, RuleIssueType issueType, bool isActiveByDefault, - IReadOnlyList tags, IReadOnlyList descriptionSections, IReadOnlyList educationPrinciples, string htmlNote, + IReadOnlyList tags, IReadOnlyList educationPrinciples, string htmlNote, CleanCodeAttribute? cleanCodeAttribute, Dictionary defaultImpacts) { LanguageKey = languageKey; @@ -162,7 +108,6 @@ public RuleInfo(string languageKey, string fullRuleKey, string description, stri IssueType = issueType; IsActiveByDefault = isActiveByDefault; Tags = tags ?? Array.Empty(); - DescriptionSections = descriptionSections ?? Array.Empty(); EducationPrinciples = educationPrinciples ?? Array.Empty(); HtmlNote = htmlNote; CleanCodeAttribute = cleanCodeAttribute; @@ -185,8 +130,6 @@ public RuleInfo(string languageKey, string fullRuleKey, string description, stri public IReadOnlyList Tags { get; private set; } - public IReadOnlyList DescriptionSections { get; } - public IReadOnlyList EducationPrinciples { get; } public string HtmlNote { get; } @@ -195,21 +138,6 @@ public RuleInfo(string languageKey, string fullRuleKey, string description, stri public Dictionary DefaultImpacts { get; } - public IRuleInfo WithServerOverride(RuleIssueSeverity newSeverity, string newHtmlNote) => - new RuleInfo(LanguageKey, - FullRuleKey, - Description, - Name, - newSeverity, - IssueType, - IsActiveByDefault, - Tags, - DescriptionSections, - EducationPrinciples, - newHtmlNote, - CleanCodeAttribute, - DefaultImpacts); - public IRuleInfo WithCleanCodeTaxonomyDisabled() => new RuleInfo(LanguageKey, FullRuleKey, @@ -219,7 +147,6 @@ public IRuleInfo WithCleanCodeTaxonomyDisabled() => IssueType, IsActiveByDefault, Tags, - DescriptionSections, EducationPrinciples, HtmlNote, null, diff --git a/src/Rules/RuleExtensions.cs b/src/Rules/RuleExtensions.cs index 3fe98aace..ec8fc65f9 100644 --- a/src/Rules/RuleExtensions.cs +++ b/src/Rules/RuleExtensions.cs @@ -30,7 +30,8 @@ public static class RuleExtensions { public static bool IsRichRuleDescription(this IRuleInfo ruleInfo) { - return ruleInfo.DescriptionSections != null && ruleInfo.DescriptionSections.Count > 1; + throw new NotImplementedException(); // will be re-implemented later + // return ruleInfo.DescriptionSections != null && ruleInfo.DescriptionSections.Count > 1; } internal static string GetCompositeKey(this SonarQubeRule sonarQubeRule) => $"{sonarQubeRule.RepositoryKey}:{sonarQubeRule.Key}"; @@ -157,15 +158,5 @@ internal static RuleIssueType ToRuleIssueType(this SonarQubeIssueType sonarQubeI return RuleIssueType.Unknown; } } - - internal static IDescriptionSection ToDescriptionSection(this SonarQubeDescriptionSection sonarQubeDescriptionSection) - { - return new DescriptionSection(sonarQubeDescriptionSection.Key, HtmlXmlCompatibilityHelper.EnsureHtmlIsXml(sonarQubeDescriptionSection.HtmlContent), sonarQubeDescriptionSection.Context?.ToContext()); - } - - private static IContext ToContext(this SonarQubeContext sonarQubeContext) - { - return new Context(sonarQubeContext.Key, sonarQubeContext.DisplayName); - } } } diff --git a/src/Rules/RuleMetaDataProvider.cs b/src/Rules/RuleMetaDataProvider.cs index 872d5b482..98673a704 100644 --- a/src/Rules/RuleMetaDataProvider.cs +++ b/src/Rules/RuleMetaDataProvider.cs @@ -35,67 +35,4 @@ public interface IRuleMetaDataProvider /// Task GetRuleInfoAsync(SonarCompositeRuleId ruleId, CancellationToken token); } - - [Export(typeof(IRuleMetaDataProvider))] - [PartCreationPolicy(CreationPolicy.Shared)] - internal class RuleMetaDataProvider : IRuleMetaDataProvider - { - private readonly ILocalRuleMetadataProvider localRuleMetadataProvider; - private readonly IServerRuleMetadataProvider serverRuleMetadataProvider; - private readonly IConfigurationProvider configurationProvider; - private readonly IConnectedModeFeaturesConfiguration connectedModeFeaturesConfiguration; - - [ImportingConstructor] - public RuleMetaDataProvider(ILocalRuleMetadataProvider localRuleMetadataProvider, - IServerRuleMetadataProvider serverRuleMetadataProvider, - IConfigurationProvider configurationProvider, - IConnectedModeFeaturesConfiguration connectedModeFeaturesConfiguration) - { - this.localRuleMetadataProvider = localRuleMetadataProvider; - this.serverRuleMetadataProvider = serverRuleMetadataProvider; - this.configurationProvider = configurationProvider; - this.connectedModeFeaturesConfiguration = connectedModeFeaturesConfiguration; - } - - public async Task GetRuleInfoAsync(SonarCompositeRuleId ruleId, CancellationToken token) - { - var localMetaData = localRuleMetadataProvider.GetRuleInfo(ruleId); - - if (localMetaData?.IssueType == RuleIssueType.Hotspot || !connectedModeFeaturesConfiguration.IsNewCctAvailable()) - { - localMetaData = localMetaData?.WithCleanCodeTaxonomyDisabled(); - } - - var configuration = configurationProvider.GetConfiguration(); - - //TODO: this does not seem to support taint. - var language = Language.GetLanguageFromRepositoryKey(ruleId.RepoKey); - - // It's possible we'll be asked for help for a language we don't handle locally, in which - // case we'll return null. - // See https://github.com/SonarSource/sonarlint-visualstudio/issues/4582 - if (language == null) { return null; } - - ApplicableQualityProfile qualityProfile = null; - - if (!(configuration.Mode.IsInAConnectedMode() && configuration.Project.Profiles.TryGetValue(language, out qualityProfile))) - { - return localMetaData; - } - - var serverMetaData = await serverRuleMetadataProvider.GetRuleInfoAsync(ruleId, qualityProfile.ProfileKey, token); - - if (localMetaData == null) - { - return serverMetaData; - } - - if (serverMetaData != null) - { - return localMetaData.WithServerOverride(serverMetaData.Severity, serverMetaData.HtmlNote); - } - - return localMetaData; - } - } } diff --git a/src/Rules/ServerRuleMetadataProvider.cs b/src/Rules/ServerRuleMetadataProvider.cs deleted file mode 100644 index 5de3a0535..000000000 --- a/src/Rules/ServerRuleMetadataProvider.cs +++ /dev/null @@ -1,92 +0,0 @@ -/* - * SonarLint for Visual Studio - * Copyright (C) 2016-2024 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -using System; -using System.ComponentModel.Composition; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using SonarLint.VisualStudio.Core; -using SonarQube.Client; - -namespace SonarLint.VisualStudio.Rules -{ - /// - /// Returns rule metadata - /// - /// - /// The metadata is received from SQ Client - /// - public interface IServerRuleMetadataProvider - { - /// - /// Fetches rule info for the specified language rule - /// - /// The rule info, or null if the repo key/rule was not recognised - Task GetRuleInfoAsync(SonarCompositeRuleId ruleId, string qualityProfileKey, CancellationToken token); - } - - [Export(typeof(IServerRuleMetadataProvider))] - [PartCreationPolicy(CreationPolicy.Shared)] - public class ServerRuleMetadataProvider : IServerRuleMetadataProvider - { - private readonly ISonarQubeService service; - private readonly ILogger logger; - - [ImportingConstructor] - public ServerRuleMetadataProvider(ISonarQubeService service, ILogger logger) - { - this.service = service; - this.logger = logger; - } - - public async Task GetRuleInfoAsync(SonarCompositeRuleId ruleId, string qualityProfileKey, CancellationToken token) - { - try - { - var sqRule = await service.GetRuleByKeyAsync(ruleId.ToString(), qualityProfileKey, token); - - if (sqRule == null) { return null; } - - var descriptionSections = sqRule.DescriptionSections?.Select(ds => ds.ToDescriptionSection()).ToList(); - - return new RuleInfo(sqRule.RepositoryKey, - sqRule.GetCompositeKey(), - HtmlXmlCompatibilityHelper.EnsureHtmlIsXml(sqRule.Description), - sqRule.Name, - sqRule.Severity.ToRuleIssueSeverity(), - sqRule.IssueType.ToRuleIssueType(), - sqRule.IsActive, - sqRule.Tags, - descriptionSections, - sqRule.EducationPrinciples, - HtmlXmlCompatibilityHelper.EnsureHtmlIsXml(sqRule.HtmlNote), - sqRule.CleanCodeAttribute.ToCleanCodeAttribute(), - sqRule.SoftwareQualitySeverities.ToSoftwareQualitySeverities()); - } - catch (Exception ex) - { - logger.WriteLine(Resources.ServerMetadataProvider_GetRulesError, ruleId.ToString(), ex.Message); - } - - return null; - } - } -}