public static void MovePropertyAfterSecond() { var code = @" namespace N { class C { public int P1 { get; set; } public int P2 { get; set; } public int P3 { get; set; } } }"; var editor = CreateDocumentEditor(code); _ = editor.MoveAfter(editor.OriginalRoot.Find <PropertyDeclarationSyntax>("P2"), editor.OriginalRoot.Find <PropertyDeclarationSyntax>("P3")); var expected = @" namespace N { class C { public int P1 { get; set; } public int P3 { get; set; } public int P2 { get; set; } } }"; CodeAssert.AreEqual(expected, editor.GetChangedDocument()); }
void Run([CallerMemberName] string testName = null, AssemblerOptions asmOptions = AssemblerOptions.None, CSharpCompilerOptions cscOptions = CSharpCompilerOptions.None, DecompilerSettings decompilerSettings = null) { var ilFile = Path.Combine(TestCasePath, testName) + Tester.GetSuffix(cscOptions) + ".il"; var csFile = Path.Combine(TestCasePath, testName + ".cs"); var expectedFile = Path.Combine(TestCasePath, testName + ".Expected.cs"); if (!File.Exists(ilFile)) { // re-create .il file if necessary CompilerResults output = null; try { output = Tester.CompileCSharp(csFile, cscOptions); Tester.Disassemble(output.PathToAssembly, ilFile, asmOptions); } finally { if (output != null) { output.TempFiles.Delete(); } } } var executable = Tester.AssembleIL(ilFile, asmOptions); var decompiled = Tester.DecompileCSharp(executable, decompilerSettings); CodeAssert.FilesAreEqual(expectedFile, decompiled, Tester.GetPreprocessorSymbols(cscOptions).ToArray()); }
void Run([CallerMemberName] string testName = null, AssemblerOptions asmOptions = AssemblerOptions.None, CompilerOptions cscOptions = CompilerOptions.None, DecompilerSettings decompilerSettings = null) { var csFile = Path.Combine(TestCasePath, testName + ".cs"); var exeFile = Path.Combine(TestCasePath, testName) + Tester.GetSuffix(cscOptions) + ".exe"; if (cscOptions.HasFlag(CompilerOptions.Library)) { exeFile = Path.ChangeExtension(exeFile, ".dll"); } // 1. Compile CompilerResults output = null; try { output = Tester.CompileCSharp(csFile, cscOptions, exeFile); } finally { if (output != null) { output.TempFiles.Delete(); } } // 2. Decompile var decompiled = Tester.DecompileCSharp(exeFile, decompilerSettings ?? Tester.GetSettings(cscOptions)); // 3. Compile CodeAssert.FilesAreEqual(csFile, decompiled, Tester.GetPreprocessorSymbols(cscOptions).ToArray()); }
public static async Task WithProtectedMember(string before, string after) { var code = @" namespace N { class C { protected int f; } }".AssertReplace("protected int f;", before); var sln = CodeFactory.CreateSolution(code); var editor = await DocumentEditor.CreateAsync(sln.Projects.First().Documents.First()).ConfigureAwait(false); var expected = @" namespace N { sealed class C { private int f; } }".AssertReplace("private int f;", after); _ = editor.Seal(editor.OriginalRoot.Find <ClassDeclarationSyntax>("class C")); CodeAssert.AreEqual(expected, editor.GetChangedDocument()); }
public static void InternalPropertyBeforePublicWithComments() { var code = @" namespace N { class C { // P1 internal int P1 { get; set; } // P2 public int P2 { get; set; } } }"; var editor = CreateDocumentEditor(code); _ = editor.MoveAfter(editor.OriginalRoot.Find <PropertyDeclarationSyntax>("P1"), editor.OriginalRoot.Find <PropertyDeclarationSyntax>("P2")); var expected = @" namespace N { class C { // P2 public int P2 { get; set; } // P1 internal int P1 { get; set; } } }"; CodeAssert.AreEqual(expected, editor.GetChangedDocument()); }
public static async Task SystemWhenEmptyOutside() { var code = @" namespace N { }"; var otherCode = @" using System; namespace N { }"; var sln = CodeFactory.CreateSolution(new[] { code, otherCode }); var editor = await DocumentEditor.CreateAsync(sln.Projects.First().Documents.First()).ConfigureAwait(false); var expected = @"using System; namespace N { }"; var usingDirective = SyntaxFactory.UsingDirective(SyntaxFactory.ParseName("System")); _ = editor.AddUsing(usingDirective); CodeAssert.AreEqual(expected, editor.GetChangedDocument()); }
public static void WithSpanWhenAfterDoesNotMatch() { var before = @" class c { }"; var after = @" class WRONG { }"; var refactoring = new ClassNameToUpperCaseRefactoringProvider(); var exception = Assert.Throws <AssertException>(() => RoslynAssert.Refactoring(refactoring, before, new TextSpan(8, 3), after)); var expected = @"Mismatch on line 2 of file WRONG.cs. Expected: class WRONG Actual: class C ^ Expected: class WRONG { } Actual: class C { } "; CodeAssert.AreEqual(expected, exception.Message); exception = Assert.Throws <AssertException>(() => RoslynAssert.Refactoring(refactoring, before, new TextSpan(8, 3), after, title: "To uppercase")); CodeAssert.AreEqual(expected, exception.Message); }
public static async Task TypicalClass() { var code = @" namespace N { public abstract class C { public int F1 = 1; private int f2; public C() { } private C(int i) { } public int P1 { get; set; } public void M1() { } } }"; var sln = CodeFactory.CreateSolution(code); var editor = await DocumentEditor.CreateAsync(sln.Projects.First().Documents.First()).ConfigureAwait(false); var declaration = (PropertyDeclarationSyntax)SyntaxFactory.ParseMemberDeclaration("public int NewProperty { get; set; }"); var containingType = editor.OriginalRoot.SyntaxTree.FindClassDeclaration("C"); _ = editor.AddProperty(containingType, declaration); var expected = @" namespace N { public abstract class C { public int F1 = 1; private int f2; public C() { } private C(int i) { } public int P1 { get; set; } public int NewProperty { get; set; } public void M1() { } } }"; CodeAssert.AreEqual(expected, editor.GetChangedDocument()); }
public static void AddSystem() { var code = @" namespace N { using System.Text; }"; var syntaxTree = CSharpSyntaxTree.ParseText(code); var compilation = CSharpCompilation.Create("test", new[] { syntaxTree }, Settings.Default.MetadataReferences); var semanticModel = compilation.GetSemanticModel(syntaxTree); var expected = @" namespace N { usingSystem; using System.Text; }"; var usingDirective = SyntaxFactory.UsingDirective(SyntaxFactory.ParseName("System")); var compilationUnit = syntaxTree.GetCompilationUnitRoot(CancellationToken.None); var updated = compilationUnit.AddUsing(usingDirective, semanticModel); CodeAssert.AreEqual(expected, updated.ToFullString()); }
public static void TwoErrorsOnlyOneIndicated() { var code = @" namespace N { class C { private readonly int ↓_value1; private readonly int _value2; } }"; var analyzer = new FieldNameMustNotBeginWithUnderscore(); var exception = Assert.Throws <AssertException>(() => RoslynAssert.Diagnostics(analyzer, code)); var expected = @"Expected and actual diagnostics do not match. Expected: SA1309 at line 5 and character 29 in file C.cs | private readonly int ↓_value1; Actual: SA1309 Field '_value1' must not begin with an underscore at line 5 and character 29 in file C.cs | private readonly int ↓_value1; SA1309 Field '_value2' must not begin with an underscore at line 6 and character 29 in file C.cs | private readonly int ↓_value2; "; CodeAssert.AreEqual(expected, exception.Message); }
public static void TwoDocumentsIndicatedAndActualPositionDoNotMatch() { var code1 = @" namespace N { class C1 { private readonly int _value1; } }"; var code2 = @" namespace N { class C2 { private readonly int ↓value2; } }"; var analyzer = new FieldNameMustNotBeginWithUnderscore(); var exception = Assert.Throws <AssertException>(() => RoslynAssert.Diagnostics(analyzer, code1, code2)); var expected = @"Expected and actual diagnostics do not match. Expected: SA1309 at line 5 and character 29 in file C2.cs | private readonly int ↓value2; Actual: SA1309 Field '_value1' must not begin with an underscore at line 5 and character 29 in file C1.cs | private readonly int ↓_value1; "; CodeAssert.AreEqual(expected, exception.Message); }
public static void MoveFieldFirstAfterLast() { var code = @" namespace N { class C { public static readonly int F1 = 1; private static readonly int F2 = 2; } }"; var editor = CreateDocumentEditor(code); _ = editor.MoveAfter(editor.OriginalRoot.Find <FieldDeclarationSyntax>("F1"), editor.OriginalRoot.Find <FieldDeclarationSyntax>("F2")); var expected = @" namespace N { class C { private static readonly int F2 = 2; public static readonly int F1 = 1; } }"; CodeAssert.AreEqual(expected, editor.GetChangedDocument()); }
public static void MoveStatementAfterSecond() { var code = @" namespace N { class C { C() { var a = 1; var b = 1; var c = 1; } } }"; var editor = CreateDocumentEditor(code); _ = editor.MoveAfter(editor.OriginalRoot.Find <StatementSyntax>("var b = 1;"), editor.OriginalRoot.Find <StatementSyntax>("var c = 1;")); var expected = @" namespace N { class C { C() { var a = 1; var c = 1; var b = 1; } } }"; CodeAssert.AreEqual(expected, editor.GetChangedDocument()); }
public static void MoveFieldBeforeFirstWithComments() { var code = @" namespace N { class C { // F1 public static readonly int F1 = 1; // F2 private static readonly int F2 = 2; } }"; var editor = CreateDocumentEditor(code); _ = editor.MoveBefore(editor.OriginalRoot.Find <FieldDeclarationSyntax>("F2"), editor.OriginalRoot.Find <FieldDeclarationSyntax>("F1")); var expected = @" namespace N { class C { // F2 private static readonly int F2 = 2; // F1 public static readonly int F1 = 1; } }"; CodeAssert.AreEqual(expected, editor.GetChangedDocument()); }
public static async Task ListOfStringBuilderType() { var code = @" namespace N { }"; var sln = CodeFactory.CreateSolution(code); var document = sln.Projects.First().Documents.First(); var editor = await DocumentEditor.CreateAsync(document).ConfigureAwait(false); var expected = @" namespace N { using System.Collections.Generic; using System.Text; }"; var type = editor.SemanticModel.GetSpeculativeTypeInfo( 0, SyntaxFactory.ParseTypeName("System.Collections.Generic.List<System.Text.StringBuilder>"), SpeculativeBindingOption.BindAsTypeOrNamespace).Type; _ = editor.AddUsing(type); CodeAssert.AreEqual(expected, editor.GetChangedDocument()); }
public void EnsureThatIndexIsAsExpected() { var builder = new StringBuilder(); const string HeaderRow = "| Id | Title"; builder.AppendLine(HeaderRow) .AppendLine("| :-- | :--"); var descriptors = DescriptorsWithDocs.Select(x => x.Descriptor) .Distinct() .OrderBy(x => x.Id); foreach (var descriptor in descriptors) { builder.Append($"| [{descriptor.Id}]({descriptor.HelpLinkUri})") .AppendLine($"| {descriptor.Title}"); } var expected = builder.ToString(); DumpIfDebug(expected); var actual = GetTable(File.ReadAllText(Path.Combine(DocumentsDirectory.FullName, "index.md")), HeaderRow); CodeAssert.AreEqual(expected, actual); }
public static async Task TypeInNestedDeepNamespace() { var classCode = @" namespace A.B.C.Extensions { class C { } } "; var code = @" namespace A.B.C { }"; var sln = CodeFactory.CreateSolution(new[] { classCode, code }); var document = sln.Projects.First().Documents.First(); var editor = await DocumentEditor.CreateAsync(document).ConfigureAwait(false); var expected = @" namespace A.B.C { using A.B.C.Extensions; }"; var type = editor.SemanticModel.Compilation.GetTypeByMetadataName("A.B.C.Extensions.C"); _ = editor.AddUsing(type); CodeAssert.AreEqual(expected, editor.GetChangedDocument()); }
public static async Task AddPublicFieldWhenPublicAndPrivateExists() { var code = @" namespace N { class C { public int F; private int f; } }"; var sln = CodeFactory.CreateSolution(code); var editor = await DocumentEditor.CreateAsync(sln.Projects.First().Documents.First()).ConfigureAwait(false); var containingType = editor.OriginalRoot.SyntaxTree.FindClassDeclaration("C"); var expected = @" namespace N { class C { public int F; public int NewField; private int f; } }"; var newField = (FieldDeclarationSyntax)SyntaxFactory.ParseMemberDeclaration("public int NewField;"); _ = editor.AddField(containingType, newField); CodeAssert.AreEqual(expected, editor.GetChangedDocument()); }
public static async Task TypeInSameNamespaceWhenEmptyNamespace() { var classCode = @" namespace N { class C1 { } } "; var code = @" namespace N { }"; var sln = CodeFactory.CreateSolution(new[] { classCode, code }); var document = sln.Projects.First().Documents.Last(); var editor = await DocumentEditor.CreateAsync(document).ConfigureAwait(false); var expected = @" namespace N { }"; var type = editor.SemanticModel.Compilation.GetTypeByMetadataName("N.C1"); _ = editor.AddUsing(type); CodeAssert.AreEqual(expected, editor.GetChangedDocument()); }
public static async Task AddEventWhenUsing() { var code = @" namespace N { using System; class C { } }"; var sln = CodeFactory.CreateSolution(code, MetadataReferences.FromAttributes()); var editor = await DocumentEditor.CreateAsync(sln.Projects.First().Documents.First()).ConfigureAwait(false); var eventDeclaration = (EventFieldDeclarationSyntax)editor.Generator.EventDeclaration("E", SyntaxFactory.ParseTypeName("System.EventHandler"), Accessibility.Public) .WithSimplifiedNames(); var containingType = editor.OriginalRoot.SyntaxTree.FindClassDeclaration("C"); _ = editor.AddEvent(containingType, eventDeclaration); var expected = @" namespace N { using System; class C { public event EventHandler E; } }"; CodeAssert.AreEqual(expected, editor.GetChangedDocument()); }
public void WithExpectedDiagnosticWithWrongId() { var code = @" namespace RoslynSandbox { class Foo { private readonly int value1; } }"; var expected = "Analyzer Gu.Roslyn.Asserts.Tests.FieldNameMustNotBeginWithUnderscore does not produce a diagnostic with ID NoError.\r\n" + "The analyzer produces the following diagnostics: {SA1309}\r\n" + "The expected diagnostic is: NoError"; var descriptor = NoErrorAnalyzer.Descriptor; var exception = Assert.Throws <AssertException>(() => AnalyzerAssert.Valid <FieldNameMustNotBeginWithUnderscore>(descriptor, code)); CodeAssert.AreEqual(expected, exception.Message); exception = Assert.Throws <AssertException>(() => AnalyzerAssert.Valid(typeof(FieldNameMustNotBeginWithUnderscore), descriptor, code)); Assert.AreEqual(expected, exception.Message); exception = Assert.Throws <AssertException>(() => AnalyzerAssert.Valid(new FieldNameMustNotBeginWithUnderscore(), descriptor, code)); Assert.AreEqual(expected, exception.Message); exception = Assert.Throws <AssertException>(() => AnalyzerAssert.Valid <FieldNameMustNotBeginWithUnderscore>(new[] { descriptor }, code)); Assert.AreEqual(expected, exception.Message); exception = Assert.Throws <AssertException>(() => AnalyzerAssert.Valid(typeof(FieldNameMustNotBeginWithUnderscore), new[] { descriptor }, code)); Assert.AreEqual(expected, exception.Message); exception = Assert.Throws <AssertException>(() => AnalyzerAssert.Valid(new FieldNameMustNotBeginWithUnderscore(), new[] { descriptor }, code)); Assert.AreEqual(expected, exception.Message); }
public void EnsureThatConfigSeverityIsAsExpected(BaseInfo info) { var expected = GetConfigSeverity(info.Stub); DumpIfDebug(expected); var actual = GetConfigSeverity(info.DocumentationFile.AllText); CodeAssert.AreEqual(expected, actual); string GetConfigSeverity(string doc) { return(GetSection(doc, "<!-- start generated config severity -->", "<!-- end generated config severity -->")); } string GetSection(string doc, string startToken, string endToken) { var start = doc.IndexOf(startToken, StringComparison.Ordinal); Assert.That(start, Is.GreaterThan(0), "Missing: " + startToken); var end = doc.IndexOf(endToken, start, StringComparison.Ordinal); Assert.That(end, Is.GreaterThan(start), "Missing: " + endToken); return(doc.Substring(start, end + endToken.Length - start)); } }
public void WithExpectedDiagnosticWithWrongId() { var code = @" namespace RoslynSandbox { class Foo { private readonly int value1; } }"; var expected = "Analyzer Gu.Roslyn.Asserts.Tests.FieldNameMustNotBeginWithUnderscore does not produce a diagnostic with ID WRONG.\r\n" + "The analyzer produces the following diagnostics: {SA1309}\r\n" + "The expected diagnostic is: WRONG"; var expectedDiagnostic = ExpectedDiagnostic.Create("WRONG"); var exception = Assert.Throws <NUnit.Framework.AssertionException>(() => AnalyzerAssert.Valid <FieldNameMustNotBeginWithUnderscore>(expectedDiagnostic, code)); CodeAssert.AreEqual(expected, exception.Message); exception = Assert.Throws <NUnit.Framework.AssertionException>(() => AnalyzerAssert.Valid(typeof(FieldNameMustNotBeginWithUnderscore), expectedDiagnostic, code)); Assert.AreEqual(expected, exception.Message); exception = Assert.Throws <NUnit.Framework.AssertionException>(() => AnalyzerAssert.Valid(new FieldNameMustNotBeginWithUnderscore(), expectedDiagnostic, code)); Assert.AreEqual(expected, exception.Message); exception = Assert.Throws <NUnit.Framework.AssertionException>(() => AnalyzerAssert.Valid <FieldNameMustNotBeginWithUnderscore>(new[] { expectedDiagnostic }, code)); Assert.AreEqual(expected, exception.Message); exception = Assert.Throws <NUnit.Framework.AssertionException>(() => AnalyzerAssert.Valid(typeof(FieldNameMustNotBeginWithUnderscore), new[] { expectedDiagnostic }, code)); Assert.AreEqual(expected, exception.Message); exception = Assert.Throws <NUnit.Framework.AssertionException>(() => AnalyzerAssert.Valid(new FieldNameMustNotBeginWithUnderscore(), new[] { expectedDiagnostic }, code)); Assert.AreEqual(expected, exception.Message); }
public void EnsureThatAnalyzerIndexIsAsExpected(string category, int tableNumber) { var builder = new StringBuilder(); const string headerRow = "| Id | Title | :mag: | :memo: | :bulb: |"; builder.AppendLine(headerRow) .AppendLine("| :-- | :-- | :--: | :--: | :--: |"); var descriptors = DescriptorsWithDocs .Select(x => x.Descriptor) .Where(x => x.Category == category) .Distinct() .OrderBy(x => x.Id); foreach (var descriptor in descriptors) { var enabledEmoji = descriptor.IsEnabledByDefault ? ":white_check_mark:" : ":x:"; var severityEmoji = SeverityEmoji[descriptor.DefaultSeverity]; var codefixEmoji = diagnosticsWithCodeFixes.Contains(descriptor.Id) ? ":white_check_mark:" : ":x:"; builder.Append($"| [{descriptor.Id}]({descriptor.HelpLinkUri}) ") .Append($"| {EscapeTags(descriptor.Title)} | {enabledEmoji} ") .AppendLine($"| {severityEmoji} | {codefixEmoji} |"); } var expected = builder.ToString(); DumpIfDebug(expected); var actual = GetTable(File.ReadAllText(Path.Combine(DocumentsDirectory.FullName, "index.md")), headerRow, tableNumber); CodeAssert.AreEqual(expected, actual); }
public void WhenEqualWhitespaceEnd() { var expected = @" namespace RoslynSandbox { class Foo { private readonly int _value; } } a "; var actual = @" namespace RoslynSandbox { class Foo { private readonly int _value; } } a "; CodeAssert.AreEqual(expected, actual); }
public void EnsureThatSuppressionIndexIsAsExpected(int tableNumber) { var builder = new StringBuilder(); const string headerRow = "| Id | Title | :mag: | :memo: | :bulb: |"; builder.AppendLine(headerRow) .AppendLine("| :-- | :-- | :--: | :--: | :--: |"); var suppressors = SuppressorsWithDocs .Distinct() .OrderBy(x => x.Descriptor.Id); foreach (var suppressor in suppressors) { var enabledEmoji = ":white_check_mark:"; var severityEmoji = SeverityEmoji[DiagnosticSeverity.Info]; var codefixEmoji = ":x:"; builder.Append($"| [{suppressor.Id}]({suppressor.HelpLinkUri}) ") .Append($"| {EscapeTags(suppressor.Title)} | {enabledEmoji} ") .AppendLine($"| {severityEmoji} | {codefixEmoji} |"); } var expected = builder.ToString(); DumpIfDebug(expected); var actual = GetTable(File.ReadAllText(Path.Combine(DocumentsDirectory.FullName, "index.md")), headerRow, tableNumber); CodeAssert.AreEqual(expected, actual); }
public static void TwoDocumentsOneErrorCodeFixFixedTheCode() { var barCode = @" namespace N { class Bar { private readonly int value; } }"; var code = @" namespace N { class C { private readonly int ↓_value; } }"; var analyzer = new FieldNameMustNotBeginWithUnderscore(); var fix = new DoNotUseUnderscoreFix(); var exception = Assert.Throws <AssertException>(() => RoslynAssert.NoFix(analyzer, fix, barCode, code)); var expected = "Expected code to have no fixable diagnostics.\r\n" + "The following actions were registered:\r\n" + " 'Rename to: 'value''\r\n"; CodeAssert.AreEqual(expected, exception.Message); }
public void SingleClassOneErrorCorrectFixAll() { var code = @" namespace RoslynSandbox { class Foo { private readonly int _value; } }"; var fixedCode = @" namespace RoslynSandbox { class Foo { private readonly int value; } }"; var analyzer = new FieldNameMustNotBeginWithUnderscore(); var cSharpCompilationOptions = CodeFactory.DefaultCompilationOptions(analyzer); var metadataReferences = new[] { MetadataReference.CreateFromFile(typeof(int).Assembly.Location) }; var sln = CodeFactory.CreateSolution(code, cSharpCompilationOptions, metadataReferences); var diagnostics = Analyze.GetDiagnostics(sln, analyzer); var fixedSln = Fix.Apply(sln, new DontUseUnderscoreCodeFixProvider(), diagnostics); CodeAssert.AreEqual(fixedCode, fixedSln.Projects.Single().Documents.Single()); }
public static async Task BeforePropertyWhenFirstMember() { var code = @" namespace N { public class C { internal int P { get; } } }"; var sln = CodeFactory.CreateSolution(code); var editor = await DocumentEditor.CreateAsync(sln.Projects.First().Documents.First()).ConfigureAwait(false); var containingType = editor.OriginalRoot.SyntaxTree.FindClassDeclaration("C"); var property = (PropertyDeclarationSyntax)SyntaxFactory.ParseMemberDeclaration("public int NewProperty => 1;"); var expected = @" namespace N { public class C { public int NewProperty => 1; internal int P { get; } } }"; _ = editor.AddProperty(containingType, property); CodeAssert.AreEqual(expected, editor.GetChangedDocument()); }
public static async Task BeforeMethodInConditional() { var code = @" namespace N { public class C { #if true private int M() => 1; #endif } }"; var sln = CodeFactory.CreateSolution(code); var editor = await DocumentEditor.CreateAsync(sln.Projects.First().Documents.First()).ConfigureAwait(false); var containingType = editor.OriginalRoot.SyntaxTree.FindClassDeclaration("C"); var method = (MethodDeclarationSyntax)SyntaxFactory.ParseMemberDeclaration("public int NewMethod() => 1;"); var expected = @" namespace N { public class C { public int NewMethod() => 1; #if true private int M() => 1; #endif } }"; _ = editor.AddMethod(containingType, method); CodeAssert.AreEqual(expected, editor.GetChangedDocument()); }