Code Monkey home page Code Monkey logo

analyzer-testbed's Introduction

Code Analysis Testbed

This repository serves as a testbed for developing and experimenting with Roslyn analyzers, code fixes, and source generators.

CodeAnalysisTest

This is a simple project containing the types to run code analysis on, along with marker classes that would eventually be in a nuget package along with the analyzers.

Entity Classes

These are basic POCO entity classes. These cover various cases seen in actual applications: a root entity with one-to-many children, a child that has a navigation property back to the root entity, along with a 1-to-1 relation to another entity, and a basic entity with no navigation properties in itself.

Faker Classes

These are classes that inherit from the Faker<T> that Bogus provides. I've come to prefer using this style over the fluent syntax since its more encapsulated and easier to pick up with analyzers.

These also exhibit a few things I've found work out well for this type of usage. The first is passing seeds as constructor parameters and explicitly setting the seeds. This makes the values generated by Bogus deterministic (See Bogus Docs for more details). Passing the seed as a constructor argument makes it easy for child fakers to be seeded based on their parent.

The other main item is a useIds parameter for the fakers. Setting this to true will have Bogus fill in the various Id fields on the entities, useful for if you want to make sure the Ids make it through some sort of mapping step and not be zero. However, having it fill in ids will break the case these fakers are used to generate fake entities to be inserted into the database, as EF Core will complain about identity inserts.

The one downside to how child entities are generated as shown in this project is that children from different parents will have overlapping ids. This is because a new Faker is made for each child with a seed generated from the parent, and ids are made using the IndexFaker property on the faker, which is incremented for every item generated by Bogus. If different behavior is desired, this could be replaced with the IndexGlobal property on the faker, which is static across all faker instances, or injecting all needed fakers at the start (messy and more complicated). However, unless there's some logic to deduplicate items based on id or similar, this shouldn't be an issue. And that case could be fixed by the aforementioned IndexGlobal.

Exporters

Since this project is spun off of trying to make exporters for an app not as vulnerable to bit rot as other parts of the application evolves, these seemed like a good thing to include.

There's two "marker" classes for exporters in this project, a basic Exporter<TEntity> and an AutoExporter<TEntity>. The basic Exporter will just have the basic analyzer checks attached to make sure all properties from the base entity are mapped or explicitly ignored. The AutoExporter is meant to use source generators to automate most of the exporter code.

These might be better served as generic attributes once they're out of preview (What's new in C# 11).

The general plan for exporters is they take their associated entity type as a constructor parameter, and do all of the mapping in that constructor. Child entities are transformed in the constructor by something like entity.Children.Select(c=>new ChildExporter(c)).ToList(). This will make some additional work for things like an Excel exporter, as it will have to reach into the entities and pull out the children. Although it would have to do this at some point regardless it seems, before or after the transform to the exported entity (query the db with Include statements, and then SelectMany from there, or even separate queries per table.). That's one part of the export process I can't think up a good way to have an automated check for. But adding new children entities is something that will happen much less often than adding fields to an existing entity.

For plain Exporter<TEntity>s, an analyzer enforces they have a public constructor that takes an instance of the TEntity type as a parameter. The analyzer does not care if there are other public constructors, or if there are other parameters. The one method on the Exporter<TEntity> base class is an Ignore method which takes an expression pointing at a property, used to explicitly ignore a field from the entity. The idea is this will be used for things like navigation properties to a parent, properties that are unused but not yet removed, or strictly internal fields.

For the AutoExporter the thought at this point is to have a private/internal parameter-less constructor that has RuleFor statements similar to what the Faker<T> classes use that define how an entity property is mapped to an exporter field. These will then be read by the source generator to generate the fields on the exporter, along with a constructor that takes the entity class.

CodeAnalysisTest.Analyzers

The "final" analyzers and generators are intended to go here. This looked like it had to be used before I discovered some extension methods used by the TestHarness project.

TestHarness

This is the project where development of the analyzers takes place. It drives its own instance of the C# compiler and adds its own analyzers to the project it builds. This allows for debugging of analyzers, having them dump out information via Console.WriteLine, etc without needing the weird "This visual studio extension project launches another copy of VS that you can run your analyzers in".

This is heavily commented inline, so refer to that for details.

analyzer-testbed's People

Contributors

msieker avatar

Watchers

 avatar Mitchel Sellers avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.