public void MethodContainsControlStructureInElseStatement_DiagnosticIsReported() { const string Code = @" class SomeClass { public void SomeMethod() { if (new Random().Next(1) == 1) { System.Console.WriteLine(string.Empty); } else { for (int i = 0; i < 10; i++) { System.Console.WriteLine(); } } } }"; var expected = new DiagnosticResult { Id = "DaVinciOC1", Message = "\'SomeMethod\' contains more than 1 level of indentation.", Severity = DiagnosticSeverity.Info, Locations = new[] { new DiagnosticResultLocation("Test0.cs", 4, 29) } }; VerifyCSharpDiagnostic(Code, expected); }
public void DiagnosticForMethod() { var source = @" using System.Threading; class T { void M(CancellationToken t, int i) { } }"; var expected = new DiagnosticResult { Id = RoslynDiagnosticIds.CancellationTokenMustBeLastRuleId, Message = string.Format(RoslynDiagnosticsResources.CancellationTokenMustBeLastMessage, "T.M(System.Threading.CancellationToken, int)"), Severity = DiagnosticSeverity.Warning, Locations = new[] { new DiagnosticResultLocation("Test0.cs", 5, 10) } }; VerifyCSharp(source, expected); var fixedSource = @" using System.Threading; class T { void M(int i, CancellationToken t) { } }"; VerifyCSharpFix(source, fixedSource); }
public void MethodContainsIfWithElse_OneDiagnosticReported() { const string Code = @" class SomeClass { private int firstField; private int secondField; public void Do() { if (true) { System.Console.WriteLine(); } else { System.Console.WriteLine(); } } }"; var expected = new DiagnosticResult { Id = "DaVinciOC2", Message = "The else keyword should be avoided.", Severity = DiagnosticSeverity.Info, Locations = new[] { new DiagnosticResultLocation("Test0.cs", 14, 21) } }; VerifyCSharpDiagnostic(Code, expected); }
public void NestedExpressionContains2Dots_DiagnosticIsReported() { const string code = @" class Board { public String boardRepresentation() { StringBuilder buf = new StringBuilder(); for (Location loc : squares()) { buf.append(loc.current.substring(0, 1)); } return buf.toString(); } }"; var expected = new DiagnosticResult { Id = "DaVinciOC5", Message = "\'loc.current.substring(0, 1)\' contains more than 1 dot per line.", Severity = DiagnosticSeverity.Info, Locations = new[] { new DiagnosticResultLocation("Test0.cs", 7, 36) } }; VerifyCSharpDiagnostic(code, expected); }
public void ClassContainsListAndField_ReportDiagnostic() { const string Code = @" class SomeClass { private int someField; private System.Collections.Generic.List<int> list; public SomeClass() { this.someField = 1; this.list = new System.Collections.Generic.List<int>(); } }"; var expected = new DiagnosticResult { Id = "DaVinciOC4", Message = "Consider wrapping the collection into a separate class.", Severity = DiagnosticSeverity.Info, Locations = new[] { new DiagnosticResultLocation("Test0.cs", 6, 62) } }; VerifyCSharpDiagnostic(Code, expected); }
public void ClassContainsTwoListsAndAnotherField_ReportDiagnostic() { const string Code = @" class SomeClass { private System.Collections.Generic.List<int> firstList; private System.Collections.Generic.List<int> secondList; private int intField; public SomeClass(int val) { this.firstList = new System.Collections.Generic.List<int>(); this.secondList = new System.Collections.Generic.List<int>(); this.intField = val; } }"; var firstExpected = new DiagnosticResult { Id = "DaVinciOC4", Message = "Consider wrapping the collection into a separate class.", Severity = DiagnosticSeverity.Info, Locations = new[] { new DiagnosticResultLocation("Test0.cs", 4, 62)} }; var secondExpected = new DiagnosticResult { Id = "DaVinciOC4", Message = "Consider wrapping the collection into a separate class.", Severity = DiagnosticSeverity.Info, Locations = new[] { new DiagnosticResultLocation("Test0.cs", 5, 62) } }; VerifyCSharpDiagnostic(Code, firstExpected, secondExpected); }
public void TestExpressionBodiedProperties() { var test = @" namespace ConsoleApplication1 { class TypeName { private IAuthenticationManager AuthenticationManager => this.HttpContext.GetOwinContext().Authentication; } }"; var expected = new DiagnosticResult { Id = "SA1623D", Message = $"property documentation: no documentation.", Severity = DiagnosticSeverity.Warning, Locations = new[] { new DiagnosticResultLocation("Test0.cs", 6, 40) } }; new DocumentationPropertyCodeFixVerifier().VerifyCSharpDiagnostic(test, expected); var fixtest = @" namespace ConsoleApplication1 { class TypeName { /// <summary> /// Gets the authentication manager. /// </summary> private IAuthenticationManager AuthenticationManager => this.HttpContext.GetOwinContext().Authentication; } }"; new DocumentationPropertyCodeFixVerifier().VerifyCSharpFix(test, fixtest); }
public void TestThatFirstPropertyHasCorrectSpacingBefore() { var test = @" namespace Test { public class TestClass { private readonly int _someVariable; } }"; var expected = new DiagnosticResult { Id = "SA1600D", Message = $"members must be correctly documented.", Severity = DiagnosticSeverity.Warning, Locations = new[] { new DiagnosticResultLocation("Test0.cs", 6, 30) } }; new DocumentationMemberCodeFixVerifier().VerifyCSharpDiagnostic(test, expected); var fixtest = @" namespace Test { public class TestClass { /// <summary> /// the some variable. /// </summary> private readonly int _someVariable; } }"; new DocumentationMemberCodeFixVerifier().VerifyCSharpFix(test, fixtest); }
public void TestUnspecifiedSetPropertyHasCorrectComment() { var test = @" namespace ConsoleApplication1 { class TypeName { public string VogonConstructorFleet { get; } } }"; var expected = new DiagnosticResult { Id = "SA1623D", Message = $"property documentation: no documentation.", Severity = DiagnosticSeverity.Warning, Locations = new[] { new DiagnosticResultLocation("Test0.cs", 6, 23) } }; new DocumentationPropertyCodeFixVerifier().VerifyCSharpDiagnostic(test, expected); var fixtest = @" namespace ConsoleApplication1 { class TypeName { /// <summary> /// Gets the vogon constructor fleet. /// </summary> public string VogonConstructorFleet { get; } } }"; new DocumentationPropertyCodeFixVerifier().VerifyCSharpFix(test, fixtest); }
public void TestThatMethodContainingParametersHaveParametersDetected() { var test = @" using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Diagnostics; namespace ConsoleApplication1 { class TypeName { /// <summary> /// build the vogon constructor fleet. /// </summary> /// <param name=""parameterOne"">parameter one</param> public void BuildVogonConstructorFleet(string parameterOne, int parameterItemTwo) { } } }"; var expected = new DiagnosticResult { Id = "SA1612D", Message = $"method documentation: missing 'parameterItemTwo'.", Severity = DiagnosticSeverity.Warning, Locations = new[] { new DiagnosticResultLocation("Test0.cs", 17, 21) } }; new DocumentationMethodCodeFixVerifier().VerifyCSharpDiagnostic(test, expected); }
public void MethodTakesMultiplePrimitiveAsParameter_MultipleDiagnosticReported() { const string Code = @" class SomeClass { public void DoSomething(int parameter1, uint parameter2) { } }"; var expected1 = new DiagnosticResult { Id = "DaVinciOC3", Message = "'parameter1' should be wrapped as it's a primitive.", Severity = DiagnosticSeverity.Info, Locations = new[] { new DiagnosticResultLocation("Test0.cs", 4, 49) } }; var expected2 = new DiagnosticResult { Id = "DaVinciOC3", Message = "'parameter2' should be wrapped as it's a primitive.", Severity = DiagnosticSeverity.Info, Locations = new[] { new DiagnosticResultLocation("Test0.cs", 4, 66) } }; VerifyCSharpDiagnostic(Code, expected1, expected2); }
public void ConstructorParameterDocumentationAddSingleParameterTest() { var test = @" using System; namespace ConsoleApplication1 { public class TypeName { /// <summary> /// a description has been provided. /// line 2 of the description. /// </summary> /// <param name=""parameterOne"">there is some documentation</param> /// <param name=""parameterTwo""></param> public TypeName( string parameterOne, int parameterItemTwo, string parameterThree) { } } }"; var expected = new DiagnosticResult { Id = "SA1642D", Message = $"constructors must be correctly documented.", Severity = DiagnosticSeverity.Warning, Locations = new[] { new DiagnosticResultLocation("Test0.cs", 13, 16) } }; new DocumentationConstructorCodeFixVerifier().VerifyCSharpDiagnostic(test, expected); var fixtest = @" using System; namespace ConsoleApplication1 { public class TypeName { /// <summary> /// Initializes a new instance of the <see cref=""TypeName""/> class. /// a description has been provided. /// line 2 of the description. /// </summary> /// <param name=""parameterOne"">there is some documentation</param> /// <param name=""parameterItemTwo"">the parameter item two.</param> /// <param name=""parameterThree"">the parameter three.</param> public TypeName( string parameterOne, int parameterItemTwo, string parameterThree) { } } }"; new DocumentationConstructorCodeFixVerifier().VerifyCSharpFix(test, fixtest); }
public void TestMethodBuildsCorrectMethodSummaryAfterFix() { var test = @" using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Diagnostics; namespace ConsoleApplication1 { class TypeName { public void BuildVogonConstructorFleet() { } } }"; var expected = new DiagnosticResult { Id = "SA1612D", Message = $"method documentation: no documentation.", Severity = DiagnosticSeverity.Warning, Locations = new[] { new DiagnosticResultLocation("Test0.cs", 13, 21) } }; new DocumentationMethodCodeFixVerifier().VerifyCSharpDiagnostic(test, expected); var fixtest = @" using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Diagnostics; namespace ConsoleApplication1 { class TypeName { /// <summary> /// build the vogon constructor fleet. /// </summary> public void BuildVogonConstructorFleet() { } } }"; new DocumentationMethodCodeFixVerifier().VerifyCSharpFix(test, fixtest); }
public void VerifyMissingQuickFixReplacesDocumentation() { var test = @" using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Diagnostics; namespace ConsoleApplication1 { class TypeName { public string TestProperty { get; set; } } }"; var expected = new DiagnosticResult { Id = "SA1623D", Message = $"property documentation: no documentation.", Severity = DiagnosticSeverity.Warning, Locations = new[] { new DiagnosticResultLocation("Test0.cs", 13, 23) } }; this.VerifyCSharpDiagnostic(test, expected); var fixtest = @" using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Diagnostics; namespace ConsoleApplication1 { class TypeName { /// <summary> /// Gets or sets the test property. /// </summary> public string TestProperty { get; set; } } }"; this.VerifyCSharpFix(test, fixtest); }
public void TestThatReturnValuesAreNotReplaced() { var test = @" namespace ConsoleApplication1 { class TypeName { /// <summary> /// build the vogon constructor fleet. /// </summary> /// <returns>the result of the application</returns> public static int Main<T>(string[] arguments) { } } }"; var expected = new DiagnosticResult { Id = "SA1612D", Message = $"method documentation: missing 'arguments'.", Severity = DiagnosticSeverity.Warning, Locations = new[] { new DiagnosticResultLocation("Test0.cs", 10, 27) } }; new DocumentationMethodCodeFixVerifier().VerifyCSharpDiagnostic(test, expected); var fixtest = @" namespace ConsoleApplication1 { class TypeName { /// <summary> /// build the vogon constructor fleet. /// </summary> /// <param name=""arguments"">the arguments.</param> /// <returns>the result of the application</returns> /// <typeparam name=""T"">a type of {T}.</typeparam> public static int Main<T>(string[] arguments) { } } }"; new DocumentationMethodCodeFixVerifier().VerifyCSharpFix(test, fixtest); }
public void TestMethod2() { var test = @" using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Diagnostics; namespace ConsoleApplication1 { class TypeName { } }"; var expected = new DiagnosticResult { Id = "ConfigureAwaitAnalyzer", Message = String.Format("Type name '{0}' contains lowercase letters", "TypeName"), Severity = DiagnosticSeverity.Warning, Locations = new[] { new DiagnosticResultLocation("Test0.cs", 11, 15) } }; this.VerifyCSharpDiagnostic(test, expected); var fixtest = @" using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Diagnostics; namespace ConsoleApplication1 { class TYPENAME { } }"; this.VerifyCSharpFix(test, fixtest); }
public void TestStaticMainMethodWithASingleParameter() { var test = @" namespace ConsoleApplication1 { class TypeName { /// <summary> /// build the vogon constructor fleet. /// </summary> /// <param name=""args""></param> public static void Main(string[] args) { } } }"; var expected = new DiagnosticResult { Id = "SA1612D", Message = $"method documentation: missing 'args'.", Severity = DiagnosticSeverity.Warning, Locations = new[] { new DiagnosticResultLocation("Test0.cs", 10, 28) } }; new DocumentationMethodCodeFixVerifier().VerifyCSharpDiagnostic(test, expected); var fixtest = @" namespace ConsoleApplication1 { class TypeName { /// <summary> /// build the vogon constructor fleet. /// </summary> /// <param name=""args"">the args.</param> public static void Main(string[] args) { } } }"; new DocumentationMethodCodeFixVerifier().VerifyCSharpFix(test, fixtest); }
public async void AllowMembersOrderingForMoreThanOneMemberShouldTiggerDiagnostic(string typeDeclaration) { var test = @" " + typeDeclaration + @" Foo { int bar() { return 0; } void car() { } }"; var expected = new DiagnosticResult { Id = DiagnosticId.AllowMembersOrdering.ToDiagnosticId(), Message = AllowMembersOrderingAnalyzer.MessageFormat, Severity = DiagnosticSeverity.Hidden, Locations = new[] { new DiagnosticResultLocation("Test0.cs", 2, 14 + typeDeclaration.Length) } }; await VerifyCSharpDiagnosticAsync(test, expected); }
public void TestNamedMethodWithStringReturnValue() { var test = @" namespace ConsoleApplication1 { class TypeName { /// <summary> /// build the vogon constructor fleet. /// </summary> public int PerformAFunction() { } } }"; var expected = new DiagnosticResult { Id = "SA1612D", Message = $"method documentation: missing return value documentation.", Severity = DiagnosticSeverity.Warning, Locations = new[] { new DiagnosticResultLocation("Test0.cs", 9, 20) } }; new DocumentationMethodCodeFixVerifier().VerifyCSharpDiagnostic(test, expected); var fixtest = @" namespace ConsoleApplication1 { class TypeName { /// <summary> /// build the vogon constructor fleet. /// </summary> /// <returns>an int containing the perform a function.</returns> public int PerformAFunction() { } } }"; new DocumentationMethodCodeFixVerifier().VerifyCSharpFix(test, fixtest); }
public void ClassHasThreeFields_OneDiagnosticReportedShowingThreeFields() { const string Code = @" class SomeClass { private int firstField; private int secondField; private int thirdField; }"; var expected = new DiagnosticResult { Id = "DaVinciOC8", Message = "\'SomeClass\' contains more than 2 fields (3).", Severity = DiagnosticSeverity.Info, Locations = new[] { new DiagnosticResultLocation("Test0.cs", 2, 19) } }; VerifyCSharpDiagnostic(Code, expected); }
public void ClassContainsOneProperty_OneDiagnosticReported() { const string Code = @" class SomeClass { public int SomeProperty { get; set; } }"; var expected = new DiagnosticResult { Id = "DaVinciOC9", Message = "\'SomeProperty\' is a property and should be avoided.", Severity = DiagnosticSeverity.Info, Locations = new[] { new DiagnosticResultLocation("Test0.cs", 4, 28) } }; VerifyCSharpDiagnostic(Code, expected); }
public void TestThatExistingTypeParametersAreNotOverridden() { var test = @" using System; namespace ConsoleApplication1 { /// <typeparam name=""TTypePayload"">existing documentation must not change</typeparam> public class ThisIsALongTypeName<TTypePayload, TOther> { private int Test { get; set; } } }"; var expected = new DiagnosticResult { Id = "SA1606D", Message = $"class documentation: no documentation.", Severity = DiagnosticSeverity.Warning, Locations = new[] { new DiagnosticResultLocation("Test0.cs", 6, 18) } }; new DocumentationClassFixVerifier().VerifyCSharpDiagnostic(test, expected); var fixtest = @" using System; namespace ConsoleApplication1 { /// <summary> /// this is a long type name. /// </summary> /// <typeparam name=""TTypePayload"">existing documentation must not change</typeparam> /// <typeparam name=""TOther"">a type of other.</typeparam> public class ThisIsALongTypeName<TTypePayload, TOther> { private int Test { get; set; } } }"; new DocumentationClassFixVerifier().VerifyCSharpFix(test, fixtest); }
public async Task IfRegexIdentifierFoundAndRegexTextIsIncorrectCreatesDiagnostic() { const string source = @" using System; using System.Text.RegularExpressions; namespace ConsoleApplication1 { class TypeName { public async Task Foo() { System.Text.RegularExpressions.Regex.Match("""", ""[""); } } }"; var message = ""; try { #pragma warning disable CC0010 System.Text.RegularExpressions.Regex.Match("", "["); #pragma warning restore CC0010 } catch (ArgumentException e) { message = e.Message; } var expected = new DiagnosticResult { Id = DiagnosticId.Regex.ToDiagnosticId(), Message = message, Severity = DiagnosticSeverity.Error, Locations = new[] { new DiagnosticResultLocation("Test0.cs", 11, 64) } }; await VerifyCSharpDiagnosticAsync(source, expected); }
public void TestThatReturnTypeDocumentationContainsCorrectReturnDocumentation() { var test = @" namespace ConsoleApplication1 { class TypeName { public ITestAnInterfaceTypeReturnValue Observe(string vogonConstructorFleet) { } } }"; var expected = new DiagnosticResult { Id = "SA1612D", Message = $"method documentation: no documentation.", Severity = DiagnosticSeverity.Warning, Locations = new[] { new DiagnosticResultLocation("Test0.cs", 6, 48) } }; new DocumentationMethodCodeFixVerifier().VerifyCSharpDiagnostic(test, expected); var fixtest = @" namespace ConsoleApplication1 { class TypeName { /// <summary> /// observe the vogon constructor fleet. /// </summary> /// <param name=""vogonConstructorFleet"">the vogon constructor fleet.</param> /// <returns>the test an interface type return value.</returns> public ITestAnInterfaceTypeReturnValue Observe(string vogonConstructorFleet) { } } }"; new DocumentationMethodCodeFixVerifier().VerifyCSharpFix(test, fixtest); }
public async Task IfVirtualMethodWithThisFoundInConstructorCreatesDiagnostic() { const string test = @" public class Person {{ public Person(string foo) {{ this.DoFoo(foo); }} public virtual void DoFoo(string foo) {{ }} }}"; var expected = new DiagnosticResult { Id = DiagnosticId.VirtualMethodOnConstructor.ToDiagnosticId(), Message = VirtualMethodOnConstructorAnalyzer.Message, Severity = DiagnosticSeverity.Warning, Locations = new[] { new DiagnosticResultLocation("Test0.cs", 6, 3) } }; await VerifyCSharpDiagnosticAsync(test, expected); }
public void TestThatSingleWordMethodDocumentationIncludesFirstParameter() { var test = @" namespace ConsoleApplication1 { class TypeName { public void Observe(string vogonConstructorFleet) { } } }"; var expected = new DiagnosticResult { Id = "SA1612D", Message = $"method documentation: no documentation.", Severity = DiagnosticSeverity.Warning, Locations = new[] { new DiagnosticResultLocation("Test0.cs", 6, 21) } }; new DocumentationMethodCodeFixVerifier().VerifyCSharpDiagnostic(test, expected); var fixtest = @" namespace ConsoleApplication1 { class TypeName { /// <summary> /// observe the vogon constructor fleet. /// </summary> /// <param name=""vogonConstructorFleet"">the vogon constructor fleet.</param> public void Observe(string vogonConstructorFleet) { } } }"; new DocumentationMethodCodeFixVerifier().VerifyCSharpFix(test, fixtest); }
public void DiagnosticForMethod() { var source = @" using System.Threading; class T { void M(CancellationToken t, int i) { } }"; var expected = new DiagnosticResult { Id = CancellationTokenParametersMustComeLastAnalyzer.RuleId, Message = string.Format(MicrosoftApiDesignGuidelinesAnalyzersResources.CancellationTokenParametersMustComeLastMessage, "T.M(System.Threading.CancellationToken, int)"), Severity = DiagnosticSeverity.Warning, Locations = new[] { new DiagnosticResultLocation("Test0.cs", 5, 10) } }; VerifyCSharp(source, expected); }
public void TestThatGeneratedCodeDoesNotTrigger() { var test = @" // // <auto-generated /> // using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Diagnostics; namespace ConsoleApplication1 { class TypeName { public string VogonConstructorFleet { get; set; } } }"; var expected = new DiagnosticResult[] { }; new DocumentationPropertyCodeFixVerifier().VerifyCSharpDiagnostic(test, expected); }
public void TestPropertyWithoutCorrectText() { var test = @" namespace ConsoleApplication1 { class TypeName { /// <summary> /// Gets or sets the test. /// </summary> public string SomeProperty { get; private set; } } }"; var expected = new DiagnosticResult { Id = "SA1623D", Message = $"property documentation: does not start with 'Gets the'.", Severity = DiagnosticSeverity.Warning, Locations = new[] { new DiagnosticResultLocation("Test0.cs", 9, 23) } }; new DocumentationPropertyCodeFixVerifier().VerifyCSharpDiagnostic(test, expected); var fixtest = @" namespace ConsoleApplication1 { class TypeName { /// <summary> /// Gets the test. /// </summary> public string SomeProperty { get; private set; } } }"; new DocumentationPropertyCodeFixVerifier().VerifyCSharpFix(test, fixtest); }
public void TestThatPropertyFixDoesNotEraseExistingCommentText() { var test = @" namespace ConsoleApplication1 { class TypeName { /// <summary> /// returns an interresting property value. /// </summary> public string SomeProperty { get; set; } } }"; var expected = new DiagnosticResult { Id = "SA1623D", Message = $"property documentation: does not start with 'Gets or sets the'.", Severity = DiagnosticSeverity.Warning, Locations = new[] { new DiagnosticResultLocation("Test0.cs", 9, 23) } }; new DocumentationPropertyCodeFixVerifier().VerifyCSharpDiagnostic(test, expected); var fixtest = @" namespace ConsoleApplication1 { class TypeName { /// <summary> /// Gets or sets the interresting property value. /// </summary> public string SomeProperty { get; set; } } }"; new DocumentationPropertyCodeFixVerifier().VerifyCSharpFix(test, fixtest); }
public async Task WeakCipherModeECB() { const string cSharpTest = @" using System; using System.IO; using System.Security.Cryptography; using static System.Security.Cryptography.CipherMode; using System.Text; class WeakCipherMode { public static string EncryptECB(string decryptedString) { DESCryptoServiceProvider desProvider = new DESCryptoServiceProvider(); desProvider.Mode = ECB; desProvider.Padding = PaddingMode.PKCS7; desProvider.Key = Encoding.ASCII.GetBytes(""d66cf8""); using (MemoryStream stream = new MemoryStream()) { using (CryptoStream cs = new CryptoStream(stream, desProvider.CreateEncryptor(), CryptoStreamMode.Write)) { byte[] data = Encoding.Default.GetBytes(decryptedString); cs.Write(data, 0, data.Length); return Convert.ToBase64String(stream.ToArray()); } } } } "; const string visualBasicTest = @" Imports System Imports System.IO Imports System.Security.Cryptography Imports System.Security.Cryptography.CipherMode Imports System.Text Class WeakCipherMode Public Shared Function EncryptECB(decryptedString As String) As String Dim desProvider As New DESCryptoServiceProvider() desProvider.Mode = ECB desProvider.Padding = PaddingMode.PKCS7 desProvider.Key = Encoding.ASCII.GetBytes(""d66cf8"") Using stream As New MemoryStream() Using cs As New CryptoStream(stream, desProvider.CreateEncryptor(), CryptoStreamMode.Write) Dim data As Byte() = Encoding.[Default].GetBytes(decryptedString) cs.Write(data, 0, data.Length) Return Convert.ToBase64String(stream.ToArray()) End Using End Using End Function End Class "; var expected = new DiagnosticResult { Id = "SCS0012", Severity = DiagnosticSeverity.Warning, }; await VerifyCSharpDiagnostic(cSharpTest, expected).ConfigureAwait(false); await VerifyVisualBasicDiagnostic(visualBasicTest, expected).ConfigureAwait(false); }
private static DiagnosticResult CreateResult(params object[] formatMessageArgs) { return(DiagnosticResult.Create(DisposeLocallyAnalyzer.BS3001, formatMessageArgs)); }
public async Task TransferMemoryStream() { var cSharpTest = @" #pragma warning disable 8019 using System; using System.IO; using System.Text; using System.Data.SqlClient; #pragma warning restore 8019 class SqlTransferTesting { public void Run(string input) { var query = """"; var bytes = Encoding.ASCII.GetBytes(input); using(var stream = new MemoryStream()) { stream.Write(bytes, 0, bytes.Length); StreamReader reader = new StreamReader( stream ); query = reader.ReadToEnd(); } new SqlCommand(query); } } "; var visualBasicTest = @" #Disable Warning BC50001 Imports System Imports System.IO Imports System.Text Imports System.Data.SqlClient #Enable Warning BC50001 Friend Class SqlTransferTesting Public Sub Run(ByVal input As String) Dim query = """" Dim bytes = Encoding.ASCII.GetBytes(input) Using stream = New MemoryStream() stream.Write(bytes, 0, bytes.Length) Dim reader As StreamReader = New StreamReader(stream) query = reader.ReadToEnd() End Using Dim a = New SqlCommand(query) End Sub End Class "; var expected = new DiagnosticResult { Id = "SCS0026", Severity = DiagnosticSeverity.Warning, }; var testConfig = @" TaintEntryPoints: AAA: ClassName: SqlTransferTesting "; var optionsWithProjectConfig = ConfigurationTest.CreateAnalyzersOptionsWithConfig(testConfig); await VerifyCSharpDiagnostic(cSharpTest, expected, optionsWithProjectConfig).ConfigureAwait(false); await VerifyVisualBasicDiagnostic(visualBasicTest, expected, optionsWithProjectConfig).ConfigureAwait(false); }
public async Task MergePostConditions(string cs, string className, string name, string outParam, string taintFromArguments, bool warn) { var cSharpTest = $@" using System.Data.SqlClient; class Test {{ public string Foo(string a, string b) {{ return null; }} public void Run(string a, string b) {{ #pragma warning disable CS0219 Test o = null; #pragma warning restore CS0219 {cs} new SqlCommand(query); }} }} "; var visualBasicTest = $@" Imports System.Data.SqlClient Class Test Public Function Foo(ByVal a As String, ByVal b As String) As String Return Nothing End Function Public Sub Run(ByVal a As String, ByVal b As String) Dim o As Test = Nothing {cs.CSharpReplaceToVBasic()} Dim temp = New SqlCommand(query) End Sub End Class "; var expected = new DiagnosticResult { Id = "SCS0026", Severity = DiagnosticSeverity.Warning, }; var testConfig = $@" TaintEntryPoints: AAA: ClassName: Test Behavior: BBB: ClassName: {className} Name: {name} Method: If: Condition: {{1: {{Value: """"}}}} Then: {outParam}: Taint: LocalUrl {outParam}: {taintFromArguments} "; var optionsWithProjectConfig = ConfigurationTest.CreateAnalyzersOptionsWithConfig(testConfig); if (warn) { await VerifyCSharpDiagnostic(cSharpTest, expected, optionsWithProjectConfig).ConfigureAwait(false); await VerifyVisualBasicDiagnostic(visualBasicTest, expected, optionsWithProjectConfig).ConfigureAwait(false); } else { await VerifyCSharpDiagnostic(cSharpTest, null, optionsWithProjectConfig).ConfigureAwait(false); await VerifyVisualBasicDiagnostic(visualBasicTest, null, optionsWithProjectConfig).ConfigureAwait(false); } }
public void Guid_NonDeterministicMethod_AllGuidCases() { var test = @" using System; using System.Threading.Tasks; using Microsoft.Azure.WebJobs; using Microsoft.Azure.WebJobs.Extensions.DurableTask; namespace VSSample { public static class HelloSequence { [FunctionName(""GuidAnalyzerTestCases"")] public static async Task Run( [OrchestrationTrigger] IDurableOrchestrationContext context) { DirectCall(); } public static string DirectCall() { " + allTests; var expectedDiagnostics = new DiagnosticResult[3]; expectedDiagnostics[0] = new DiagnosticResult { Id = MethodInvocationAnalyzer.DiagnosticId, Message = string.Format(Resources.MethodAnalyzerMessageFormat, "DirectCall()"), Severity = Severity, Locations = new[] { new DiagnosticResultLocation("Test0.cs", 15, 17) } }; expectedDiagnostics[1] = new DiagnosticResult { Id = DiagnosticId, Message = string.Format(Resources.DeterministicAnalyzerMessageFormat, "Guid.NewGuid"), Severity = Severity, Locations = new[] { new DiagnosticResultLocation("Test0.cs", 23, 13) } }; expectedDiagnostics[2] = new DiagnosticResult { Id = DiagnosticId, Message = string.Format(Resources.DeterministicAnalyzerMessageFormat, "System.Guid.NewGuid"), Severity = Severity, Locations = new[] { new DiagnosticResultLocation("Test0.cs", 24, 13) } }; VerifyCSharpDiagnostic(test, expectedDiagnostics); }
public override Task <DiagnosticResult> Examine(SharedState history) { var jdkPath = history.GetEnvironmentVariable("JAVA_HOME") ?? Environment.GetEnvironmentVariable("JAVA_HOME"); string androidSdkPath = null; try { // Set the logger to override the default one that is set in this library // So we can catch output from failed path lookups that are otherwise swallowed var _ = new AndroidSdkInfo((traceLevel, msg) => { if (Util.Verbose || traceLevel == System.Diagnostics.TraceLevel.Error) { Util.LogAlways(msg); } }, androidSdkPath, null, jdkPath); } catch (Exception ex) { Util.Exception(ex); } if (string.IsNullOrEmpty(androidSdkPath)) { androidSdkPath = FindBestSdkLocation(); } var missingPackages = new List <IAndroidComponent>(); var installer = new AndroidSDKInstaller(new Helper(), AndroidManifestType.GoogleV2); installer.Discover(new List <string> { androidSdkPath }); var sdkInstance = installer.FindInstance(androidSdkPath); if (string.IsNullOrEmpty(sdkInstance?.Path)) { return(Task.FromResult( new DiagnosticResult( Status.Error, this, "Failed to find Android SDK.", new Suggestion("Install the Android SDK", "For more information see: [underline]https://aka.ms/dotnet-androidsdk-help[/]")))); } history.SetEnvironmentVariable("ANDROID_SDK_ROOT", sdkInstance.Path); history.SetEnvironmentVariable("ANDROID_HOME", sdkInstance.Path); var installed = sdkInstance?.Components?.AllInstalled(true); foreach (var package in RequiredPackages) { var v = !string.IsNullOrWhiteSpace(package.Version) ? new AndroidRevision(package.Version) : null; var installedPkg = FindInstalledPackage(installed, package) ?? FindInstalledPackage(installed, package.Alternatives?.ToArray()); if (installedPkg == null) { var pkgToInstall = sdkInstance?.Components?.AllNotInstalled()? .FirstOrDefault(p => p.Path.Equals(package.Path.Trim(), StringComparison.OrdinalIgnoreCase) && p.Revision >= (v ?? p.Revision)); ReportStatus($"{package.Path} ({package.Version}) missing.", Status.Error); if (pkgToInstall != null) { missingPackages.Add(pkgToInstall); } } else { if (!package.Path.Equals(installedPkg.Path) || v != (installedPkg.Revision ?? installedPkg.InstalledRevision)) { ReportStatus($"{installedPkg.Path} ({installedPkg.InstalledRevision ?? installedPkg.Revision})", Status.Ok); } else { ReportStatus($"{package.Path} ({package.Version})", Status.Ok); } } } if (!missingPackages.Any()) { return(Task.FromResult(DiagnosticResult.Ok(this))); } var installationSet = installer.GetInstallationSet(sdkInstance, missingPackages); var desc = @$ "Your Android SDK has missing or outdated packages. You can use the Android SDK Manager to install / update them. For more information see: [underline]https://aka.ms/dotnet-androidsdk-help[/]";
public void WhenFixingMayAddExtraUnnededReturn() { var test = @" using System; using System.Web.Http; namespace Test { public class FooBar: ApiController { public void ViolatingMethod(int a) { if(a > 0) { return; } else { return; } } } }"; var expected = new DiagnosticResult { Id = "AnalyzerWebApiNoVoidReturn", Message = String.Format( AnalyzerWebApiNoVoidReturnAnalyzer.MessageFormat, "FooBar", "ViolatingMethod"), Severity = DiagnosticSeverity.Error, Locations = new[] { new DiagnosticResultLocation("Test0.cs", 9, 21) } }; VerifyCSharpDiagnostic(test, expected); var fixtest = @" using System; using System.Web.Http; namespace Test { public class FooBar: ApiController { public int ViolatingMethod(int a) { if(a > 0) { return new Random().Next(); } else { return new Random().Next(); } return new Random().Next(); } } }"; VerifyCSharpFix(test, fixtest, allowNewCompilerDiagnostics: true); }
private static Task VerifyCSharpFixAsync(string source, DiagnosticResult expected, string fixedSource, CancellationToken cancellationToken) => VerifyCSharpFixAsync(source, new[] { expected }, fixedSource, cancellationToken);
private async Task <int> ExecuteAsync(string output) { // Don't use IStandardStreams for writing output in this command as we // cannot trust any component on the ICommandContext is working correctly. Console.WriteLine($"Running diagnostics...{Environment.NewLine}"); if (_diagnostics.Count == 0) { Console.WriteLine("No diagnostics to run."); return(0); } int numFailed = 0; int numSkipped = 0; string currentDir = Directory.GetCurrentDirectory(); string outputDir; if (string.IsNullOrWhiteSpace(output)) { outputDir = currentDir; } else { if (!Directory.Exists(output)) { Directory.CreateDirectory(output); } outputDir = Path.GetFullPath(Path.Combine(currentDir, output)); } string logFilePath = Path.Combine(outputDir, "gcm-diagnose.log"); var extraLogs = new List <string>(); using var fullLog = new StreamWriter(logFilePath, append: false, Encoding.UTF8); fullLog.WriteLine("Diagnose log at {0:s}Z", DateTime.UtcNow); fullLog.WriteLine(); fullLog.WriteLine($"Executable: {_context.ApplicationPath}"); fullLog.WriteLine( TryGetAssemblyVersion(out string version) ? $"Version: {version}" : "Version: [!] Failed to get version information [!]" ); fullLog.WriteLine(); foreach (IDiagnostic diagnostic in _diagnostics) { fullLog.WriteLine("------------"); fullLog.WriteLine($"Diagnostic: {diagnostic.Name}"); if (!diagnostic.CanRun()) { fullLog.WriteLine("Skipped: True"); fullLog.WriteLine(); Console.Write(" "); ConsoleEx.WriteColor("[SKIP]", ConsoleColor.Gray); Console.WriteLine(" {0}", diagnostic.Name); numSkipped++; continue; } string inProgressMsg = $" >>>> {diagnostic.Name}"; Console.Write(inProgressMsg); fullLog.WriteLine("Skipped: False"); DiagnosticResult result = await diagnostic.RunAsync(); fullLog.WriteLine("Success: {0}", result.IsSuccess); if (result.Exception is null) { fullLog.WriteLine("Exception: None"); } else { fullLog.WriteLine("Exception:"); fullLog.WriteLine(result.Exception.ToString()); } fullLog.WriteLine("Log:"); fullLog.WriteLine(result.DiagnosticLog); Console.Write(new string('\b', inProgressMsg.Length - 1)); ConsoleEx.WriteColor( result.IsSuccess ? "[ OK ]" : "[FAIL]", result.IsSuccess ? ConsoleColor.DarkGreen : ConsoleColor.Red ); Console.WriteLine(" {0}", diagnostic.Name); if (!result.IsSuccess) { numFailed++; if (result.Exception is not null) { Console.WriteLine(); ConsoleEx.WriteLineIndent("[!] Encountered an exception [!]"); ConsoleEx.WriteLineIndent(result.Exception.ToString()); } Console.WriteLine(); ConsoleEx.WriteLineIndent("[*] Diagnostic test log [*]"); ConsoleEx.WriteLineIndent(result.DiagnosticLog); Console.WriteLine(); } foreach (string filePath in result.AdditionalFiles) { string fileName = Path.GetFileName(filePath); string destPath = Path.Combine(outputDir, fileName); try { File.Copy(filePath, destPath, overwrite: true); } catch { ConsoleEx.WriteLineIndent($"Failed to copy additional file '{filePath}'"); } extraLogs.Add(destPath); } fullLog.Flush(); } Console.WriteLine(); string summary = $"Diagnostic summary: {_diagnostics.Count - numFailed} passed, {numSkipped} skipped, {numFailed} failed."; Console.WriteLine(summary); Console.WriteLine("Log files:"); Console.WriteLine($" {logFilePath}"); foreach (string log in extraLogs) { Console.WriteLine($" {log}"); } Console.WriteLine(); Console.WriteLine("Caution: Log files may include sensitive information - redact before sharing."); Console.WriteLine(); if (numFailed > 0) { Console.WriteLine("Diagnostics indicate a possible problem with your installation."); Console.WriteLine($"Please open an issue at {Constants.HelpUrls.GcmNewIssue} and include log files."); Console.WriteLine(); } fullLog.Close(); return(numFailed); }
/// <inheritdoc cref="CodeRefactoringVerifier{TCodeRefactoring, TTest, TVerifier}.VerifyRefactoringAsync(string, DiagnosticResult, string)"/> public static async Task VerifyRefactoringAsync(string source, DiagnosticResult expected, string fixedSource) { await VerifyRefactoringAsync(source, new[] { expected }, fixedSource); }
private void AssertSingleDiagnostic(string file, int line, int column) { DiagnosticResult result = CreateDiagnosticResult(line, column); VerifyCSharpDiagnostic(file, result); }
protected Task TestKeywordStatementAsync(string statement, DiagnosticResult expected, string fixedStatement, string returnType = "void", bool asyncMethod = false, LanguageVersion?languageVersion = default) { return(this.TestKeywordStatementAsync(statement, new[] { expected }, fixedStatement, returnType, asyncMethod, languageVersion)); }
public async Task TestPropertyWithMultipleInlineCommentsAsync() { var testCode = @" public class Foo { /// <summary> /// Gets the test property. /// </summary> public int Prop { /* c1 */ get /* c2 */ { /* c3 */ return 1; /* c4 */ } /* c5 */ /* c6 */ protected /* c7 */ internal /* c8 */ set /* c9 */ { /* c10 */ } /* c11 */ } }"; var fixedTestCodeSingle = @" public class Foo { /// <summary> /// Gets the test property. /// </summary> public int Prop { /* c1 */ get /* c2 */ { /* c3 */ return 1; /* c4 */ } /* c5 */ /* c6 */ protected /* c7 */ internal /* c8 */ set /* c9 */ { /* c10 */ } /* c11 */ } }"; var fixedTestCodeMultiple = @" public class Foo { /// <summary> /// Gets the test property. /// </summary> public int Prop { /* c1 */ get /* c2 */ { /* c3 */ return 1; /* c4 */ } /* c5 */ /* c6 */ protected /* c7 */ internal /* c8 */ set /* c9 */ { /* c10 */ } /* c11 */ } }"; DiagnosticResult expected = this.CSharpDiagnostic().WithLocation(9, 18); await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); await this.VerifyCSharpDiagnosticAsync(fixedTestCodeSingle, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); await this.VerifyCSharpDiagnosticAsync(fixedTestCodeMultiple, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); await this.VerifyCSharpFixAsync(testCode, fixedTestCodeSingle, codeFixIndex : 0).ConfigureAwait(false); await this.VerifyCSharpFixAsync(testCode, fixedTestCodeMultiple, codeFixIndex : 1).ConfigureAwait(false); }
private static Task VerifyCSharpDiagnosticAsync(string source, DiagnosticResult expected, CancellationToken cancellationToken) => VerifyCSharpDiagnosticAsync(source, TestSettings, new[] { expected }, cancellationToken);
public override async Task ReportsDiagnostic_ForNestedReEntrantCall() { var source = @"Imports NSubstitute Namespace MyNamespace Interface IFoo Function Bar() As Integer End Interface Interface IBar Function Foo() As Integer End Interface Public Class FooTests Public Sub Test() Dim substitute = NSubstitute.Substitute.[For](Of IFoo)() SubstituteExtensions.Returns(Of Integer)(substitute.Bar(), ReturnThis(), OtherReturn()) End Sub Private Function ReturnThis() As Integer Return OtherReturn() End Function Private Function OtherReturn() As Integer Dim substitute = NSubstitute.Substitute.[For](Of IBar)() SubstituteExtensions.Returns(Of Integer)(substitute.Foo(), NestedReturnThis()) Return 1 End Function Private Function NestedReturnThis() As Integer Return OtherNestedReturnThis() End Function Private Function OtherNestedReturnThis() As Integer Dim [sub] = Substitute.[For](Of IBar)() SubstituteExtensions.Returns(Of Integer)([sub].Foo(), 1) Return 1 End Function End Class End Namespace "; var firstArgumentDiagnostic = new DiagnosticResult { Id = DiagnosticIdentifiers.ReEntrantSubstituteCall, Severity = DiagnosticSeverity.Warning, Message = "Returns() is set with a method that itself calls Returns. This can cause problems with NSubstitute. Consider replacing with a lambda: Returns(Function(x) ReturnThis()).", Locations = new[] { new DiagnosticResultLocation(15, 72) } }; var secondArgumentDiagnostic = new DiagnosticResult { Id = DiagnosticIdentifiers.ReEntrantSubstituteCall, Severity = DiagnosticSeverity.Warning, Message = "Returns() is set with a method that itself calls Returns. This can cause problems with NSubstitute. Consider replacing with a lambda: Returns(Function(x) OtherReturn()).", Locations = new[] { new DiagnosticResultLocation(15, 86) } }; var nestedArgumentDiagnostic = new DiagnosticResult { Id = DiagnosticIdentifiers.ReEntrantSubstituteCall, Severity = DiagnosticSeverity.Warning, Message = "Returns() is set with a method that itself calls Returns. This can cause problems with NSubstitute. Consider replacing with a lambda: Returns(Function(x) NestedReturnThis()).", Locations = new[] { new DiagnosticResultLocation(24, 72) } }; await VerifyDiagnostic(source, firstArgumentDiagnostic, secondArgumentDiagnostic, nestedArgumentDiagnostic); }
public async Task DiagnosticsAndCodeFixes_WhenModelStateIsInNestedBlock() { // Arrange var expectedDiagnostic = new DiagnosticResult { Id = "MVC1001", Message = "Actions on types annotated with ApiControllerAttribute do not require explicit ModelState validity check.", Severity = DiagnosticSeverity.Warning, Locations = new[] { new DiagnosticResultLocation("Test.cs", 15, 13) } }; var test = @" using Microsoft.AspNetCore.Mvc; [ApiController] public class PetController : ControllerBase { public IActionResult GetPetId() { if (User == null) { return Unauthorized(); } else { if (!ModelState.IsValid) { return BadRequest(ModelState); } Debug.Assert(ModelState.Count == 0); } return Ok(); } }"; var expectedFix = @" using Microsoft.AspNetCore.Mvc; [ApiController] public class PetController : ControllerBase { public IActionResult GetPetId() { if (User == null) { return Unauthorized(); } else { Debug.Assert(ModelState.Count == 0); } return Ok(); } }"; var project = CreateProject(test); // Act & Assert var actualDiagnostics = await GetDiagnosticAsync(project); Assert.DiagnosticsEqual(new[] { expectedDiagnostic }, actualDiagnostics); var actualFix = await ApplyCodeFixAsync(project, actualDiagnostics); Assert.Equal(expectedFix, actualFix, ignoreLineEndingDifferences: true); }
public async Task VariableConcatenationPropertyReadonlyContructorBackingField(string initializer, string accessor) { var cSharpTest = $@" using System.Data.SqlClient; #pragma warning disable 8019 using System; #pragma warning restore 8019 namespace sample {{ class MyFoo {{ private readonly string StringConst = {initializer}; public string stringConst {{ get {{ return StringConst; }} }} public MyFoo(string x) {{ StringConst = x; }} void Foo() {{ var s = ""select * from Products""; var sqlCommand = new SqlCommand(s + {accessor}); }} }} }} "; initializer = initializer.Replace("new ", "New ").Replace("'", "\""); accessor = accessor.Replace("this.", "Me."); var visualBasicTest = $@" Imports System.Data.SqlClient #Disable Warning BC50001 Imports System #Enable Warning BC50001 Namespace sample Class MyFoo Private ReadOnly StringConstField As String = {initializer} Public ReadOnly Property stringConst() As String Get Return StringConstField End Get End Property Public Sub New(ByVal x as String) StringConstField = x End Sub Private Sub Foo() Dim s As String = ""select * from Products"" Dim com As New SqlCommand(s + {accessor}) End Sub End Class End Namespace "; var expected = new DiagnosticResult { Id = "SCS0026", Severity = DiagnosticSeverity.Warning, }; await VerifyCSharpDiagnostic(cSharpTest, expected).ConfigureAwait(false); await VerifyVisualBasicDiagnostic(visualBasicTest, expected).ConfigureAwait(false); }
public async Task CSharp_NoDiagnosticCases_NestedOperationAnalyzerRegistration() { var source = @" using System; using System.Collections.Immutable; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; [DiagnosticAnalyzer(LanguageNames.CSharp)] class MyAnalyzer : DiagnosticAnalyzer { public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get { throw new NotImplementedException(); } } public override void Initialize(AnalysisContext context) { context.RegisterCompilationStartAction(compilationContext => { compilationContext.RegisterOperationBlockStartAction(operationBlockContext => { AnalyzeOperationBlockStart(operationBlockContext); }); }); context.RegisterCompilationStartAction(compilationContext => { compilationContext.RegisterOperationAction(AnalyzeOperation, OperationKind.Invocation); }); context.RegisterCompilationStartAction(compilationContext => { compilationContext.RegisterOperationBlockAction(AnalyzeOperationBlock); }); } private static void AnalyzeOperation(OperationAnalysisContext context) { } private static void AnalyzeOperationBlock(OperationBlockAnalysisContext context) { } private static void AnalyzeOperationBlockStart(OperationBlockStartAnalysisContext context) { context.RegisterOperationAction(AnalyzeOperation, OperationKind.Invocation); } }"; await new VerifyCS.Test { ReferenceAssemblies = ReferenceAssemblies.Default, TestState = { Sources = { source }, ExpectedDiagnostics = { // Test0.cs(3,26): error CS0234: The type or namespace name 'Immutable' does not exist in the namespace 'System.Collections' (are you missing an assembly reference?) DiagnosticResult.CompilerError("CS0234").WithSpan(3, 26, 3, 35).WithArguments("Immutable", "System.Collections"), // Test0.cs(4,17): error CS0234: The type or namespace name 'CodeAnalysis' does not exist in the namespace 'Microsoft' (are you missing an assembly reference?) DiagnosticResult.CompilerError("CS0234").WithSpan(4, 17, 4, 29).WithArguments("CodeAnalysis", "Microsoft"), // Test0.cs(5,17): error CS0234: The type or namespace name 'CodeAnalysis' does not exist in the namespace 'Microsoft' (are you missing an assembly reference?) DiagnosticResult.CompilerError("CS0234").WithSpan(5, 17, 5, 29).WithArguments("CodeAnalysis", "Microsoft"), // Test0.cs(7,2): error CS0246: The type or namespace name 'DiagnosticAnalyzer' could not be found (are you missing a using directive or an assembly reference?) DiagnosticResult.CompilerError("CS0246").WithSpan(7, 2, 7, 20).WithArguments("DiagnosticAnalyzer"), // Test0.cs(7,2): error CS0246: The type or namespace name 'DiagnosticAnalyzerAttribute' could not be found (are you missing a using directive or an assembly reference?) DiagnosticResult.CompilerError("CS0246").WithSpan(7, 2, 7, 20).WithArguments("DiagnosticAnalyzerAttribute"), // Test0.cs(7,21): error CS0103: The name 'LanguageNames' does not exist in the current context DiagnosticResult.CompilerError("CS0103").WithSpan(7, 21, 7, 34).WithArguments("LanguageNames"), // Test0.cs(8,20): error CS0246: The type or namespace name 'DiagnosticAnalyzer' could not be found (are you missing a using directive or an assembly reference?) DiagnosticResult.CompilerError("CS0246").WithSpan(8, 20, 8, 38).WithArguments("DiagnosticAnalyzer"), // Test0.cs(10,21): error CS0246: The type or namespace name 'ImmutableArray<>' could not be found (are you missing a using directive or an assembly reference?) DiagnosticResult.CompilerError("CS0246").WithSpan(10, 21, 10, 57).WithArguments("ImmutableArray<>"), // Test0.cs(10,36): error CS0246: The type or namespace name 'DiagnosticDescriptor' could not be found (are you missing a using directive or an assembly reference?) DiagnosticResult.CompilerError("CS0246").WithSpan(10, 36, 10, 56).WithArguments("DiagnosticDescriptor"), // Test0.cs(10,58): error CS0115: 'MyAnalyzer.SupportedDiagnostics': no suitable method found to override DiagnosticResult.CompilerError("CS0115").WithSpan(10, 58, 10, 78).WithArguments("MyAnalyzer.SupportedDiagnostics"), // Test0.cs(18,37): error CS0246: The type or namespace name 'AnalysisContext' could not be found (are you missing a using directive or an assembly reference?) DiagnosticResult.CompilerError("CS0246").WithSpan(18, 37, 18, 52).WithArguments("AnalysisContext"), // Test0.cs(39,42): error CS0246: The type or namespace name 'OperationAnalysisContext' could not be found (are you missing a using directive or an assembly reference?) DiagnosticResult.CompilerError("CS0246").WithSpan(39, 42, 39, 66).WithArguments("OperationAnalysisContext"), // Test0.cs(43,47): error CS0246: The type or namespace name 'OperationBlockAnalysisContext' could not be found (are you missing a using directive or an assembly reference?) DiagnosticResult.CompilerError("CS0246").WithSpan(43, 47, 43, 76).WithArguments("OperationBlockAnalysisContext"), // Test0.cs(47,52): error CS0246: The type or namespace name 'OperationBlockStartAnalysisContext' could not be found (are you missing a using directive or an assembly reference?) DiagnosticResult.CompilerError("CS0246").WithSpan(47, 52, 47, 86).WithArguments("OperationBlockStartAnalysisContext"), // Test0.cs(49,59): error CS0103: The name 'OperationKind' does not exist in the current context DiagnosticResult.CompilerError("CS0103").WithSpan(49, 59, 49, 72).WithArguments("OperationKind"), }, }, }.RunAsync(); }
private Task TestCommaInStatementOrDeclAsync(string originalStatement, DiagnosticResult expected, string fixedStatement) { return(this.TestCommaInStatementOrDeclAsync(originalStatement, new[] { expected }, fixedStatement)); }
public async Task VisualBasic_NoDiagnosticCases_NestedOperationAnalyzerRegistration() { var source = @" Imports System Imports System.Collections.Immutable Imports Microsoft.CodeAnalysis Imports Microsoft.CodeAnalysis.Diagnostics <DiagnosticAnalyzer(LanguageNames.VisualBasic)> _ MustInherit Class MyAnalyzer Inherits DiagnosticAnalyzer Public Overrides ReadOnly Property SupportedDiagnostics() As ImmutableArray(Of DiagnosticDescriptor) Get Throw New NotImplementedException() End Get End Property Public Overrides Sub Initialize(context As AnalysisContext) context.RegisterCompilationStartAction(Function(compilationContext) compilationContext.RegisterOperationBlockStartAction(Function(operationBlockContext) AnalyzeOperationBlockStart(operationBlockContext) End Function) End Function) context.RegisterCompilationStartAction(Function(compilationContext) compilationContext.RegisterOperationAction(AddressOf AnalyzeOperation, OperationKind.Invocation) End Function) context.RegisterCompilationStartAction(Function(compilationContext) compilationContext.RegisterOperationBlockAction(AddressOf AnalyzeOperationBlock) End Function) End Sub Private Shared Sub AnalyzeOperation(context As OperationAnalysisContext) End Sub Private Shared Sub AnalyzeOperationBlock(context As OperationBlockAnalysisContext) End Sub Private Shared Sub AnalyzeOperationBlockStart(context As OperationBlockStartAnalysisContext) context.RegisterOperationAction(AddressOf AnalyzeOperation, OperationKind.Invocation) End Sub End Class "; await new VerifyVB.Test { ReferenceAssemblies = ReferenceAssemblies.Default, TestState = { Sources = { source }, ExpectedDiagnostics = { // Test0.vb(7) : error BC30002: Type 'DiagnosticAnalyzer' is not defined. DiagnosticResult.CompilerError("BC30002").WithSpan(7, 2, 7, 20).WithArguments("DiagnosticAnalyzer"), // Test0.vb(7) : error BC30451: 'LanguageNames' is not declared. It may be inaccessible due to its protection level. DiagnosticResult.CompilerError("BC30451").WithSpan(7, 21, 7, 34).WithArguments("LanguageNames"), // Test0.vb(9) : error BC30002: Type 'DiagnosticAnalyzer' is not defined. DiagnosticResult.CompilerError("BC30002").WithSpan(9, 11, 9, 29).WithArguments("DiagnosticAnalyzer"), // Test0.vb(10) : error BC30284: property 'SupportedDiagnostics' cannot be declared 'Overrides' because it does not override a property in a base class. DiagnosticResult.CompilerError("BC30284").WithSpan(10, 37, 10, 57).WithArguments("property","SupportedDiagnostics"), // Test0.vb(10) : error BC30002: Type 'ImmutableArray' is not defined. DiagnosticResult.CompilerError("BC30002").WithSpan(10, 63, 10, 102).WithArguments("ImmutableArray"), // Test0.vb(10) : error BC30002: Type 'DiagnosticDescriptor' is not defined. DiagnosticResult.CompilerError("BC30002").WithSpan(10, 81, 10, 101).WithArguments("DiagnosticDescriptor"), // Test0.vb(16) : error BC30284: sub 'Initialize' cannot be declared 'Overrides' because it does not override a sub in a base class. DiagnosticResult.CompilerError("BC30284").WithSpan(16, 23, 16, 33).WithArguments("sub","Initialize"), // Test0.vb(16) : error BC30002: Type 'AnalysisContext' is not defined. DiagnosticResult.CompilerError("BC30002").WithSpan(16, 45, 16, 60).WithArguments("AnalysisContext"), // Test0.vb(32) : error BC30002: Type 'OperationAnalysisContext' is not defined. DiagnosticResult.CompilerError("BC30002").WithSpan(32, 49, 32, 73).WithArguments("OperationAnalysisContext"), // Test0.vb(35) : error BC30002: Type 'OperationBlockAnalysisContext' is not defined. DiagnosticResult.CompilerError("BC30002").WithSpan(35, 54, 35, 83).WithArguments("OperationBlockAnalysisContext"), // Test0.vb(38) : error BC30002: Type 'OperationBlockStartAnalysisContext' is not defined. DiagnosticResult.CompilerError("BC30002").WithSpan(38, 59, 38, 93).WithArguments("OperationBlockStartAnalysisContext"), // Test0.vb(39) : error BC30451: 'OperationKind' is not declared. It may be inaccessible due to its protection level. DiagnosticResult.CompilerError("BC30451").WithSpan(39, 63, 39, 76).WithArguments("OperationKind") }, } }.RunAsync(); }
public void TestMethod2() { var test = @" using System; namespace ConsoleApplication1 { public class Test { public static void M() { F(new Derived1()); } static void F(Derived d) { } } public class Base { public static T Create<T>() where T : Base, new() { return new T(); } } public class Derived : Base { } public class Derived1 : Derived { } }"; var fixedText = @" using System; namespace ConsoleApplication1 { public class Test { public static void M() { F(Base.Create<Derived1>()); } static void F(Derived d) { } } public class Base { public static T Create<T>() where T : Base, new() { return new T(); } } public class Derived : Base { } public class Derived1 : Derived { } }"; var expected = new DiagnosticResult { Id = FactoryAnalyzer.DiagnosticId, Message = $"This class should be created by factory method Create of class Base", Severity = DiagnosticSeverity.Error, Locations = new[] { new DiagnosticResultLocation("Test0.cs", 10, 39) } }; VerifyCSharpDiagnostic(test, expected); VerifyCSharpFix(test, fixedText); }
public async Task Sanitizer(string payload, string warningId) { var cSharpTest = $@" #pragma warning disable 8019 using System.Data.SqlClient; using System.Web.Mvc; using System.DirectoryServices; using Microsoft.Security.Application; using System.Web; using System.IO; #pragma warning restore 8019 namespace sample {{ class MyController : Controller {{ #pragma warning disable CS0414 private HttpServerUtility _HttpServerUtility = null; #pragma warning restore CS0414 public void Run(string input, char[] inputChars) {{ {payload} }} }} }} "; payload = payload.CSharpReplaceToVBasic(); var visualBasicTest = $@" #Disable Warning BC50001 Imports System.Data.SqlClient Imports System.Web.Mvc Imports System.DirectoryServices Imports Microsoft.Security.Application Imports System.Web Imports System.IO #Enable Warning BC50001 Namespace sample Public Class MyController Inherits Controller Private _HttpServerUtility As HttpServerUtility = Nothing Public Sub Run(input As System.String, ByVal inputChars As System.Char()) {payload} End Sub End Class End Namespace "; var expected = new DiagnosticResult { Id = warningId, Severity = DiagnosticSeverity.Warning, }; await VerifyCSharpDiagnostic(cSharpTest, expected).ConfigureAwait(false); await VerifyVisualBasicDiagnostic(visualBasicTest, expected).ConfigureAwait(false); }
public async Task TaintArgumentsTransfer(string cs, bool warn) { var cSharpTest = $@" using System.Data.SqlClient; class StaticTest {{ public static void Foo2(string a, string b) {{ }} public static string Get() {{ return null; }} }} class Test {{ public string Foo(string a, string b) {{ return null; }} public void Foo2(string a, string b) {{ }} public string Foo3(string a, out string b) {{ b = null; return null; }} public string Foo4(string a, ref string b) {{ return null; }} public void Run(string a, string b) {{ #pragma warning disable CS0219 Test o = null; #pragma warning restore CS0219 {cs} new SqlCommand(query); }} }} "; var visualBasicTest = $@" Imports System.Data.SqlClient Class StaticTest Public Shared Sub Foo2(ByVal a As String, ByVal b As String) End Sub Public Shared Function [Get]() As String Return Nothing End Function End Class Class Test Public Function Foo(ByVal a As String, ByVal b As String) As String Return Nothing End Function Public Sub Foo2(ByVal a As String, ByVal b As String) End Sub Public Function Foo3(ByVal a As String, <System.Runtime.InteropServices.Out> ByRef b As String) As String b = Nothing Return Nothing End Function Public Function Foo4(ByVal a As String, ByRef b As String) As String Return Nothing End Function Public Sub Run(ByVal a As String, ByVal b As String) Dim o As Test = Nothing {cs.CSharpReplaceToVBasic()} Dim temp = New SqlCommand(query) End Sub End Class "; var expected = new DiagnosticResult { Id = "SCS0026", Severity = DiagnosticSeverity.Warning, }; var testConfig = @" TaintEntryPoints: AAA: ClassName: Test "; var optionsWithProjectConfig = ConfigurationTest.CreateAnalyzersOptionsWithConfig(testConfig); if (warn) { await VerifyCSharpDiagnostic(cSharpTest, expected, optionsWithProjectConfig).ConfigureAwait(false); await VerifyVisualBasicDiagnostic(visualBasicTest, expected, optionsWithProjectConfig).ConfigureAwait(false); } else { await VerifyCSharpDiagnostic(cSharpTest, null, optionsWithProjectConfig).ConfigureAwait(false); await VerifyVisualBasicDiagnostic(visualBasicTest, null, optionsWithProjectConfig).ConfigureAwait(false); } }
public async Task ToStringSanitizer(string intputType, string sinkType, string sink, bool warn) { var cSharpTest = $@" namespace sample {{ public enum MyEnum {{ Value = 1 }} public class Sink {{ public static void Redirect({sinkType} x) {{ }} }} public class My {{ public void Run({intputType} input) {{ {sinkType} value = default({sinkType}); {sink}; Sink.Redirect(value); }} }} }} "; var visualBasicTest = $@" Namespace sample Public Enum MyEnum Value = 1 End Enum Public Class Sink Public Shared Sub Redirect(ByVal x As {sinkType}) End Sub End Class Public Class My Public Sub Run(ByVal input As {intputType}) Dim value As {sinkType} {sink.CSharpReplaceToVBasic()} Sink.Redirect(value) End Sub End Class End Namespace "; var testConfig = @" TaintEntryPoints: sample.My: Method: Name: Run Sinks: - Type: sample.Sink TaintTypes: - SCS0027 Methods: - Name: Redirect Arguments: - x "; var optionsWithProjectConfig = ConfigurationTest.CreateAnalyzersOptionsWithConfig(testConfig); if (warn) { var expected = new DiagnosticResult { Id = "SCS0027", Severity = DiagnosticSeverity.Warning, }; await VerifyCSharpDiagnostic(cSharpTest, expected, optionsWithProjectConfig).ConfigureAwait(false); await VerifyVisualBasicDiagnostic(visualBasicTest, expected, optionsWithProjectConfig).ConfigureAwait(false); } else { await VerifyCSharpDiagnostic(cSharpTest, null, optionsWithProjectConfig).ConfigureAwait(false); await VerifyVisualBasicDiagnostic(visualBasicTest, null, optionsWithProjectConfig).ConfigureAwait(false); } }
/// <summary> /// Checks each of the actual Diagnostics found and compares them with the corresponding DiagnosticResult in the array of expected results. /// Diagnostics are considered equal only if the DiagnosticResultLocation, Id, Severity, and Message of the DiagnosticResult match the actual diagnostic. /// </summary> /// <param name="actualResults">The Diagnostics found by the compiler after running the analyzer on the source code</param> /// <param name="analyzer">The analyzer that was being run on the sources</param> /// <param name="expectedResults">Diagnostic Results that should have appeared in the code</param> private static void VerifyDiagnosticResults(IEnumerable <Diagnostic> actualResults, DiagnosticAnalyzer analyzer, params DiagnosticResult[] expectedResults) { int expectedCount = expectedResults.Length; int actualCount = actualResults.Count(); if (expectedCount != actualCount) { string diagnosticsOutput = actualResults.Any() ? FormatDiagnostics(analyzer, actualResults.ToArray()) : " NONE."; Assert.True(false, string.Format("Mismatch between number of diagnostics returned, expected \"{0}\" actual \"{1}\"\r\n\r\nDiagnostics:\r\n{2}\r\n", expectedCount, actualCount, diagnosticsOutput)); } for (int i = 0; i < expectedResults.Length; i++) { Diagnostic actual = actualResults.ElementAt(i); DiagnosticResult expected = expectedResults[i]; if (expected.HasLocation) { if (actual.Location != Location.None) { Assert.True(false, string.Format("Expected:\nA project diagnostic with No location\nActual:\n{0}", FormatDiagnostics(analyzer, actual))); } } else { VerifyDiagnosticLocation(analyzer, actual, actual.Location, expected.Spans[0]); Location[] additionalLocations = actual.AdditionalLocations.ToArray(); if (additionalLocations.Length != expected.Spans.Length - 1) { Assert.True(false, string.Format("Expected {0} additional locations but got {1} for Diagnostic:\r\n {2}\r\n", expected.Spans.Length - 1, additionalLocations.Length, FormatDiagnostics(analyzer, actual))); } for (int j = 0; j < additionalLocations.Length; ++j) { VerifyDiagnosticLocation(analyzer, actual, additionalLocations[j], expected.Spans[j + 1]); } } if (actual.Id != expected.Id) { Assert.True(false, string.Format("Expected diagnostic id to be \"{0}\" was \"{1}\"\r\n\r\nDiagnostic:\r\n {2}\r\n", expected.Id, actual.Id, FormatDiagnostics(analyzer, actual))); } if (actual.Severity != expected.Severity) { Assert.True(false, string.Format("Expected diagnostic severity to be \"{0}\" was \"{1}\"\r\n\r\nDiagnostic:\r\n {2}\r\n", expected.Severity, actual.Severity, FormatDiagnostics(analyzer, actual))); } if (actual.GetMessage() != expected.Message) { Assert.True(false, string.Format("Expected diagnostic message to be \"{0}\" was \"{1}\"\r\n\r\nDiagnostic:\r\n {2}\r\n", expected.Message, actual.GetMessage(), FormatDiagnostics(analyzer, actual))); } } }
public async Task Validator(string usingNamespace, string validate, string sink, bool warn) { var cSharpTest = $@" {usingNamespace} namespace sample {{ public class Model {{ public string x {{ get; set; }} }} public class MyController : Controller {{ public object Run(string input, Uri inputUri, Model inputModel) {{ #pragma warning disable CS0219 Uri uri = null; #pragma warning restore CS0219 if ({validate}) return {sink}; else return null; }} }} }} "; var vb = validate.CSharpReplaceToVBasic().Replace("!", "Not "); var visualBasicTest = $@" {usingNamespace.CSharpReplaceToVBasic()} Namespace sample Public Class Model Public Property x As String End Class Public Class MyController Inherits Controller Public Function Run(ByVal input As String, ByVal inputUri as Uri, ByVal inputModel As Model) As Object #Disable Warning BC42024 Dim uri As Uri = Nothing #Enable Warning BC42024 If {vb} Then Return {sink} Else Return Nothing End If End Function End Class End Namespace "; if (warn) { var expected = new DiagnosticResult { Id = "SCS0027", Severity = DiagnosticSeverity.Warning, }; await VerifyCSharpDiagnostic(cSharpTest, expected).ConfigureAwait(false); await VerifyVisualBasicDiagnostic(visualBasicTest, expected).ConfigureAwait(false); } else { await VerifyCSharpDiagnostic(cSharpTest).ConfigureAwait(false); await VerifyVisualBasicDiagnostic(visualBasicTest).ConfigureAwait(false); } }
public async Task IgnoreGeneratedCode() { var code1 = @" #nullable enable$$ class Example { string? value; } "; var generatedCode1 = @"// <auto-generated/> #nullable enable class Example2 { string? value; } "; var generatedCode2 = @"// <auto-generated/> #nullable disable class Example3 { string value; } "; var generatedCode3 = @"// <auto-generated/> #nullable restore class Example4 { string {|#0:value|}; } "; var fixedCode1 = @" class Example { string? value; } "; await new VerifyCS.Test { TestState = { Sources = { code1, generatedCode1, generatedCode2, generatedCode3, }, }, FixedState = { Sources = { fixedCode1, generatedCode1, generatedCode2, generatedCode3, }, ExpectedDiagnostics = { // /0/Test3.cs(7,10): error CS8618: Non-nullable field 'value' must contain a non-null value when exiting constructor. Consider declaring the field as nullable. DiagnosticResult.CompilerError("CS8618").WithLocation(0), }, }, SolutionTransforms = { s_enableNullableInFixedSolution }, }.RunAsync(); }
public static Task VerifyCodeFixAsync(string source, DiagnosticResult expected, string fixedSource) => VerifyCodeFixAsync(source, new[] { expected }, fixedSource);
private Task TestKeywordDeclarationAsync(string statement, DiagnosticResult expected, string fixedStatement) { return(this.TestKeywordDeclarationAsync(statement, new[] { expected }, fixedStatement)); }
public async Task WeakCipherModeCBC() { const string cSharpTest = @" using System; using System.IO; using System.Security.Cryptography; class WeakCipherMode { public static byte[] EncryptStringToBytes_Aes(string plainText, byte[] Key, byte[] IV) { // Check arguments. if (plainText == null || plainText.Length <= 0) throw new ArgumentNullException(""plainText""); if (Key == null || Key.Length <= 0) throw new ArgumentNullException(""Key""); if (IV == null || IV.Length <= 0) throw new ArgumentNullException(""IV""); byte[] encrypted; // Create an AesCryptoServiceProvider object // with the specified key and IV. using (AesCryptoServiceProvider aesAlg = new AesCryptoServiceProvider()) { aesAlg.Key = Key; aesAlg.IV = IV; aesAlg.Mode = CipherMode.CBC; aesAlg.Padding = PaddingMode.PKCS7; // Create a decryptor to perform the stream transform. ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV); // Create the streams used for encryption. using (MemoryStream msEncrypt = new MemoryStream()) { using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)) { using (StreamWriter swEncrypt = new StreamWriter(csEncrypt)) { //Write all data to the stream. swEncrypt.Write(plainText); } encrypted = msEncrypt.ToArray(); } } } return encrypted; } }"; const string visualBasicTest = @" Imports System Imports System.IO Imports System.Security.Cryptography Class WeakCipherMode Public Shared Function EncryptStringToBytes_Aes(plainText As String, Key As Byte(), IV As Byte()) As Byte() ' Check arguments. If plainText Is Nothing OrElse plainText.Length <= 0 Then Throw New ArgumentNullException(""plainText"") End If If Key Is Nothing OrElse Key.Length <= 0 Then Throw New ArgumentNullException(""Key"") End If If IV Is Nothing OrElse IV.Length <= 0 Then Throw New ArgumentNullException(""IV"") End If Dim encrypted As Byte() ' Create an AesCryptoServiceProvider object ' with the specified key and IV. Using aesAlg As New AesCryptoServiceProvider() aesAlg.Key = Key aesAlg.IV = IV aesAlg.Mode = CipherMode.CBC aesAlg.Padding = PaddingMode.PKCS7 ' Create a decrytor to perform the stream transform. Dim encryptor As ICryptoTransform = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV) ' Create the streams used for encryption. Using msEncrypt As New MemoryStream() Using csEncrypt As New CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write) Using swEncrypt As New StreamWriter(csEncrypt) 'Write all data to the stream. swEncrypt.Write(plainText) End Using encrypted = msEncrypt.ToArray() End Using End Using End Using Return encrypted End Function End Class "; var expected = new DiagnosticResult { Id = "SCS0011", Severity = DiagnosticSeverity.Warning, }; await VerifyCSharpDiagnostic(cSharpTest, expected).ConfigureAwait(false); await VerifyVisualBasicDiagnostic(visualBasicTest, expected).ConfigureAwait(false); }