All Projects → GuOrg → Gu.Roslyn.Asserts

GuOrg / Gu.Roslyn.Asserts

Licence: MIT license
Asserts for testing Roslyn analyzers.

Programming Languages

C#
18002 projects

Projects that are alternatives of or similar to Gu.Roslyn.Asserts

Gops
A tool to list and diagnose Go processes currently running on your system
Stars: ✭ 5,404 (+29922.22%)
Mutual labels:  diagnostics
Postsharp.samples
PostSharp Samples
Stars: ✭ 84 (+366.67%)
Mutual labels:  diagnostics
Openvehiclediag
A rust based cross-platform ECU diagnostics and car hacking application, utilizing the passthru protocol
Stars: ✭ 135 (+650%)
Mutual labels:  diagnostics
Androbd
Android OBD diagnostics with any ELM327 adapter
Stars: ✭ 573 (+3083.33%)
Mutual labels:  diagnostics
Diat
A CLI tool to help with diagnosing Node.js processes basing on inspector.
Stars: ✭ 67 (+272.22%)
Mutual labels:  diagnostics
Dotnet Netrace
Collects network traces of .NET applications.
Stars: ✭ 88 (+388.89%)
Mutual labels:  diagnostics
Codespan
Beautiful diagnostic reporting for text-based programming languages.
Stars: ✭ 445 (+2372.22%)
Mutual labels:  diagnostics
bearing-vibration-diagnostics-toolbox
No description or website provided.
Stars: ✭ 26 (+44.44%)
Mutual labels:  diagnostics
Mayday
A diagnostics tool for capturing system state.
Stars: ✭ 78 (+333.33%)
Mutual labels:  diagnostics
Dlt Daemon
Diagnostic Log and Trace.
Stars: ✭ 121 (+572.22%)
Mutual labels:  diagnostics
Tofu
Project for an open-source python library for synthetic diagnostics and tomography for Fusion devices
Stars: ✭ 35 (+94.44%)
Mutual labels:  diagnostics
Poke
A powerful reflection module for powershell.
Stars: ✭ 66 (+266.67%)
Mutual labels:  diagnostics
Tracing
Application level tracing for Rust.
Stars: ✭ 1,294 (+7088.89%)
Mutual labels:  diagnostics
Wtrace
Command line tracing tool for Windows, based on ETW.
Stars: ✭ 563 (+3027.78%)
Mutual labels:  diagnostics
Sam
System Architecture Mapper
Stars: ✭ 176 (+877.78%)
Mutual labels:  diagnostics
Terraform Lsp
Language Server Protocol for Terraform
Stars: ✭ 469 (+2505.56%)
Mutual labels:  diagnostics
A11y.css
This CSS file intends to warn developers about possible risks and mistakes that exist in HTML code. It can also be used to roughly evaluate a site's quality by simply including it as an external stylesheet.
Stars: ✭ 1,277 (+6994.44%)
Mutual labels:  diagnostics
verrou
floating-point errors checker
Stars: ✭ 39 (+116.67%)
Mutual labels:  diagnostics
Zend Diagnostics
Universal set of diagnostic tests for PHP applications.
Stars: ✭ 192 (+966.67%)
Mutual labels:  diagnostics
Roslynpad
A cross-platform C# editor based on Roslyn and AvalonEdit
Stars: ✭ 1,310 (+7177.78%)
Mutual labels:  diagnostics

Gu.Roslyn.Asserts

License NuGet Build status Build Status Gitter

Microsoft are working on an official package for testing analyzers: Microsoft.CodeAnalysis.CSharp.CodeFix.Testing.

Hopefully this library will not be needed in the future.

Asserts for testing Roslyn analyzers.

Use 1.x for Microsoft.CodeAnalysis 1.x

RoslynAssert.Valid

Use RoslynAssert.Valid<NopAnalyzer>(code) to test that an analyzer does not report errors for valid code. The code is checked so that it does not have any compiler errors either. A typical test fixture looks like:

public class Valid
{
    private static readonly DiagnosticAnalyzer Analyzer = new YourAnalyzer();

    [Test]
    public void M()
    {
        var code = @"
namespace N
{
    class C
    {
    }
}";
        RoslynAssert.Valid(Analyzer, code);
    }
    ...
}

If the analyzer produces many diagnostics you can pass in a descriptor so that only diagnostics matching it are checked.

public class Valid
{
    private static readonly DiagnosticAnalyzer Analyzer = new YourAnalyzer();
    private static readonly DiagnosticDescriptor Descriptor = YourAnalyzer.SomeDescriptor;

    [Test]
    public void M()
    {
        var code = @"
namespace N
{
    class C
    {
    }
}";
        RoslynAssert.Valid(Analyzer, Descriptor, code);
    }
    ...
}

When testing all analyzers something like this can be used:

public class Valid
{
    private static readonly IReadOnlyList<DiagnosticAnalyzer> AllAnalyzers =
        typeof(TypeInAnalyzerAssembly)
        .Assembly.GetTypes()
        .Where(typeof(DiagnosticAnalyzer).IsAssignableFrom)
        .Select(t => (DiagnosticAnalyzer)Activator.CreateInstance(t))
        .ToArray();


    private static readonly Solution ValidProjectSln = CodeFactory.CreateSolution(
        ProjectFile.Find("Valid.csproj"),
        AllAnalyzers);

    [TestCaseSource(nameof(AllAnalyzers))]
    public void Valid(DiagnosticAnalyzer analyzer)
    {
        RoslynAssert.Valid(analyzer, ValidProjectSln);
    }
}

RoslynAssert.Diagnostics

Use RoslynAssert.Diagnostics<FieldNameMustNotBeginWithUnderscore>(code) to test that the analyzer reports an error or warning at the position indicated by the character . To type this character, hold down Alt and use the numpad to type the number 25.

A typical test fixture looks like:

public class Diagnostics
{
    private static readonly DiagnosticAnalyzer Analyzer = new YourAnalyzer();
    private static readonly ExpectedDiagnostic ExpectedDiagnostic = ExpectedDiagnostic.Create(YourAnalyzer.Descriptor);

    [Test]
    public void M()
    {
        var code = @"
namespace N
{
    class ↓C
    {
    }
}";
        RoslynAssert.Diagnostics(Analyzer, code);
    }

    [Test]
    public void M()
    {
        var code = @"
namespace N
{
    class ↓C
    {
    }
}";
        RoslynAssert.Diagnostics(Analyzer, ExpectedDiagnostic.WithMessage("Don't name it C"), code);
    }
    ...
}

If the analyzer produces many diagnostics you can pass in a descriptor so that only diagnostics matching it are checked.

public class Diagnostics
{
    private static readonly DiagnosticAnalyzer Analyzer = new YourAnalyzer();
    private static readonly ExpectedDiagnostic ExpectedDiagnostic = ExpectedDiagnostic.Create(YourAnalyzer.Descriptor);

    [Test]
    public void M()
    {
        var code = @"
namespace N
{
    class ↓Foo
    {
    }
}";
        RoslynAssert.Diagnostics(Analyzer, ExpectedDiagnostic, code);
    }
    ...
}

If the analyzer supports many diagnostics the overload with ExpectedDiagnostic must be used. This suppresses all diagnstics other than the expected.

RoslynAssert.Suppressed

Use RoslynAssert.Suppressed(suppressor, code) to test that the suppressor suppresses an error or warning at the position indicated by the character . To type this character, hold down Alt and use the numpad to type the number 25.

A typical test fixture looks like:

public class Suppression
{
    private static readonly DiagnosticSuppressor Suppressor = new YourSuppressor();

    [Test]
    public void M()
    {
        var code = @"
namespace N
{
    class C
    {
        public string ↓F;
    }
}";
        RoslynAssert.NotSuppressed(Suppressor, code);
    }

    [Test]
    public void M()
    {
        var code = @"
namespace N
{
    class C
    {
        public string ↓Magic;
    }
}";
        RoslynAssert.Suppressed(Suppressor, code);

    }
    ...
}

If the suppressor can suppress many diagnostics you can pass in a descriptor so that only diagnostics matching it are checked.

public class Diagnostics
{
    private static readonly DiagnosticSuppressor Suppressor = new YourSuppressor();
    private static readonly ExpectedDiagnostic ExpectedDiagnostic = ExpectedDiagnostic.Create(YourSuppressor.Descriptor);

    [Test]
    public void M()
    {
        var code = @"
namespace N
{
    class ↓Foo
    {
    }
}";
        RoslynAssert.Suppressed(Analyzer, ExpectedDiagnostic, code);
    }
    ...
}

CodeFix

Test that the analyzer reports an error or warning at the position indicated by the character and that the code fix fixes it and produces the expected code. To type this character, hold down Alt and use the numpad to type the number 25.

public class CodeFix
{
    private static readonly DiagnosticAnalyzer Analyzer = new FieldNameMustNotBeginWithUnderscore();
    private static readonly CodeFixProvider Fix = new SA1309CodeFixProvider();

	[Test]
	public void M()
	{
		var before = @"
namespace N
{
	class C
	{
		private readonly int ↓_value;
	}
}";

		var after = @"
namespace N
{
	class C
	{
		private readonly int value;
	}
}";
		RoslynAssert.CodeFix(Analyzer, Fix, before, after);
	}
}

A typical test fixture looks like:

public class CodeFix
{
    private static readonly DiagnosticAnalyzer Analyzer = new YourAnalyzer();
    private static readonly CodeFixProvider Fix = new YorCodeFixProvider();
    private static readonly ExpectedDiagnostic ExpectedDiagnostic = ExpectedDiagnostic.Create(YourAnalyzer.Descriptor);

    [Test]
    public void M1()
    {
        var before = @"
namespace N
{
    class C
    {
        private readonly int ↓_value;
    }
}";

        var after = @"
namespace N
{
    class C
    {
        private readonly int value;
    }
}";
        RoslynAssert.CodeFix(Analyzer, Fix, before, after);
    }
}

With explicit title for the fix to apply. Useful when there are many candidate fixes.

public class CodeFix
{
    private static readonly DiagnosticAnalyzer Analyzer = new YourAnalyzer();
    private static readonly CodeFixProvider Fix = new YorCodeFixProvider();
    private static readonly ExpectedDiagnostic ExpectedDiagnostic = ExpectedDiagnostic.Create(YourAnalyzer.Descriptor);

    [Test]
    public void M1()
    {
        var before = @"
namespace N
{
    class C
    {
        private readonly int ↓_value;
    }
}";

        var after = @"
namespace N
{
    class C
    {
        private readonly int value;
    }
}";
        RoslynAssert.CodeFix(Analyzer, Fix, before, after, fixTitle: "Don't use underscore prefix");
    }
    ...
}

If the analyzer supports many diagnostics the overload with ExpectedDiagnostic must be used. This suppresses all diagnostics other than the expected.

Code fix only

When the code fix is for a warning produced by an analyzer that you do not own, for example a built in analyzer in Visual Studio.

public class CodeFix
{
    private static readonly CodeFixProvider Fix = new RemoveUnusedFixProvider();
    private static readonly ExpectedDiagnostic ExpectedDiagnostic = ExpectedDiagnostic.Create("CS0067");

	[Test]
	public void TestThatCodeFixProducesExpectedCode()
	{
		var before = @"
namespace N
{
	using System;

	public class C
	{
		public event EventHandler ↓Bar;
	}
}";

		var after = @"
namespace N
{
	using System;

	public class C
	{
	}
}";
		RoslynAssert.CodeFix(Fix, ExpectedDiagnostic, before, after);
	}
}

FixAll

When there are many issues that will be fixed: RoslynAssert.FixAll does:

  • Fix all diagnostics one by one
  • Fix all diagnostics in all supported scopes.
public class CodeFix
{
    private static readonly DiagnosticAnalyzer Analyzer = new FieldNameMustNotBeginWithUnderscore();
    private static readonly CodeFixProvider Fix = new SA1309CodeFixProvider();

	[Test]
	public void M()
	{
		var before = @"
namespace N
{
	class C
	{
		private readonly int ↓_value1;
		private readonly int ↓_value2;
	}
}";

		var after = @"
namespace N
{
	class C
	{
		private readonly int value1;
		private readonly int value2;
	}
}";
		RoslynAssert.FixAll(Analyzer, Fix, before, after);
	}
}

NoFix

Test that the analyzer reports an error or warning at the position indicated by the character and that the code fix does not change the code. To type this character, hold down Alt and use the numpad to type the number 25. This can happen if for example it is decided to not support rare edge cases with the code fix.

public class CodeFix
{
    private static readonly DiagnosticAnalyzer Analyzer = new FieldNameMustNotBeginWithUnderscore();
    private static readonly CodeFixProvider Fix = new SA1309CodeFixProvider();

	[Test]
	public void M()
	{
		var code = @"
namespace N
{
	class C
	{
		private readonly int ↓_value;
	}
}";

		RoslynAssert.NoFix(Analyzer, Fix, code);
	}
}

Refactoring

public class CodeFix
{
	private static readonly CodeRefactoringProvider Refactoring = new ClassNameToUpperCaseRefactoringProvider();

    [Test]
    public void M()
    {
        var before = @"
class ↓c
{
}";

        var after = @"
class C
{
}";
        RoslynAssert.Refactoring(Refactoring, before, after);
		// Or if you want to assert on title also
		RoslynAssert.Refactoring(Refactoring, before, after, title: "Change to uppercase.");
    }
}

AST

For checking every node and token in the tree.

[Test]
public void CheckAst()
{
    var actual = SyntaxFactory.AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, SyntaxFactory.IdentifierName("a"), SyntaxFactory.IdentifierName("b"));
    var expected = CSharpSyntaxTree.ParseText("var c = a + b").FindAssignmentExpression("a + b");
    RoslynAssert.Ast(expected, actual);
}

SyntaxFactoryWriter

Get a string with a call to SyntaxFactory for generating the code passed in.

var code = @"namespace A.B
{
    public class C
    {
    }
}";
var call = SyntaxFactoryWriter.Serialize(code);

Settings

Settings.Default is meant to be set once and contains information used by asserts and code factory methods. If specific settings are required for a test there are overloads acceping a settings intance.

Sample ModuleInitializer.cs (for the test project.)

internal static class ModuleInitializer
{
    [ModuleInitializer]
    internal static void Initialize()
    {
        Settings.Default = Settings.Default.WithMetadataReferences(
            // This adds all transitive metadata references from containing project.
            Asserts.MetadataReferences.Transitive(typeof(ModuleInitializer)));
    }
}

Analyze

GetDiagnosticsAsync

Analyze a cs, csproj or sln file on disk.

[Test]
public async Task GetDiagnosticsFromProjectOnDisk()
{
    var dllFile = new Uri(Assembly.GetExecutingAssembly().CodeBase, UriKind.Absolute).LocalPath;
    Assert.AreEqual(true, CodeFactory.TryFindProjectFile(new FileInfo(dllFile), out FileInfo projectFile));
    var diagnostics = await Analyze.GetDiagnosticsAsync(new FieldNameMustNotBeginWithUnderscore(), projectFile)
                                    .ConfigureAwait(false);
    ...
}

Fix

When dropping down to manual mode Analyze & Fix can be used like this:

[Test]
public void SingleClassOneErrorCorrectFix()
{
    var code = @"
namespace N
{
    class Foo
    {
        private readonly int _value;
    }
}";

    var after = @"
namespace N
{
    class Foo
    {
        private readonly int value;
    }
}";
    var analyzer = new FieldNameMustNotBeginWithUnderscore();
    var settings = Settings.Default.WithCompilationOptions(CodeFactory.DefaultCompilationOptions(analyzer))
                                   .WithMetadataReferences(MetadataReference.CreateFromFile(typeof(int).Assembly.Location))
    var sln = CodeFactory.CreateSolution(code, settings: settings);
    var diagnostics = Analyze.GetDiagnostics(sln, analyzer);
    var fixedSln = Fix.Apply(sln, new DoNotUseUnderscoreFix(), diagnostics);
    CodeAssert.AreEqual(after, fixedSln.Projects.Single().Documents.Single());
}

CodeFactory

CreateSolution

Create a Microsoft.CodeAnalysis.AdhocWorkspace, a Roslyn Solution from code.

[Test]
public void CreateSolutionFromSources()
{
    var code = @"
namespace N
{
    class Foo
    {
        private readonly int _value;
    }
}";
    var sln = CodeFactory.CreateSolution(code, new[] { new FieldNameMustNotBeginWithUnderscore() });
    Assert.AreEqual("N", sln.Projects.Single().Name);
    Assert.AreEqual("Foo.cs", sln.Projects.Single().Documents.Single().Name);
}

[Test]
public void CreateSolutionFromSources()
{
    var code1 = @"
namespace Project1
{
    class Foo1
    {
        private readonly int _value;
    }
}";

    var code2 = @"
namespace Project2
{
    class Foo2
    {
        private readonly int _value;
    }
}";
    var sln = CodeFactory.CreateSolution(new[] { code1, code2 }, new[] { new FieldNameMustNotBeginWithUnderscore() });
    CollectionAssert.AreEqual(new[] { "Project1", "Project2" }, sln.Projects.Select(x => x.Name));
    Assert.AreEqual(new[] { "Foo1.cs", "Foo2.cs" }, sln.Projects.Select(x => x.Documents.Single().Name));
}

Create a Microsoft.CodeAnalysis.AdhocWorkspace, a Roslyn Solution from a file on disk.

[Test]
public void CreateSolutionFromProjectFile()
{
    Assert.AreEqual(
        true,
        CodeFactory.TryFindProjectFile(
            new FileInfo(new Uri(Assembly.GetExecutingAssembly().CodeBase, UriKind.Absolute).LocalPath),
            out FileInfo projectFile));
    var solution = CodeFactory.CreateSolution(projectFile);
}

[Test]
public void CreateSolutionFromSolutionFile()
{
    Assert.AreEqual(
        true,
        CodeFactory.TryFindFileInParentDirectory(
            new FileInfo(new Uri(Assembly.GetExecutingAssembly().CodeBase, UriKind.Absolute).LocalPath).Directory, "Gu.Roslyn.Asserts.sln",
            out FileInfo solutionFile));
    var solution = CodeFactory.CreateSolution(solutionFile);
}

Benchmark

Sample benchmark using BenchmarkDotNet.

public class FieldNameMustNotBeginWithUnderscoreBenchmark
{
    private static readonly Solution Solution = CodeFactory.CreateSolution(
        CodeFactory.FindSolutionFile("Gu.Roslyn.Asserts.sln"));

    private static readonly Benchmark Benchmark = Benchmark.Create(Solution, new FieldNameMustNotBeginWithUnderscore());

    [BenchmarkDotNet.Attributes.Benchmark]
    public void RunOnGuRoslynAssertsSln()
    {
        Benchmark.Run();
    }
}

SyntaxNodeExt

[Test]
public void FindAssignmentExpressionDemo()
{
    var syntaxTree = CSharpSyntaxTree.ParseText(
        @"
namespace N
{
    internal class Foo
    {
        internal Foo()
        {
            var temp = 1;
            temp = 2;
        }
    }
}");
    var compilation = CSharpCompilation.Create("test", new[] { syntaxTree });
    var semanticModel = compilation.GetSemanticModel(syntaxTree);
    var assignment = syntaxTree.FindAssignmentExpression("temp = 2");
    Assert.AreEqual("temp = 2", assignment.ToString());
    Assert.AreEqual("int", semanticModel.GetTypeInfo(assignment.Right).Type.ToDisplayString());
}

AstView

Animation

Usage with different test project types

Net472 new project type.

<PropertyGroup>
  <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
  <GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
</PropertyGroup>
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].