<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/build-your-first-roslyn-analyzer-in-c-diagnostics-and-code-fix-walkthrough-069rztvx7" -->

---
title: Build Your First Roslyn Analyzer in C#: Diagnostics and...
description: A complete walkthrough for building a Roslyn analyzer in C# from scratch, covering project setup targeting netstandard2.0, DiagnosticAnalyzer scaffolding,...
canonical: https://daily.dev/posts/build-your-first-roslyn-analyzer-in-c-diagnostics-and-code-fix-walkthrough-069rztvx7
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: Build Your First Roslyn Analyzer in C#: Diagnostics and Code Fix Walkthrough | daily.dev
og:description: A complete walkthrough for building a Roslyn analyzer in C# from scratch, covering project setup targeting netstandard2.0, DiagnosticAnalyzer scaffolding,...
og:url: https://daily.dev/posts/build-your-first-roslyn-analyzer-in-c-diagnostics-and-code-fix-walkthrough-069rztvx7
og:image: https://api.daily.dev/og/posts/069rZTvX7.png
og:image:alt: Build Your First Roslyn Analyzer in C#: Diagnostics and Code Fix Walkthrough
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Build Your First Roslyn Analyzer in C#: Diagnostics and Code Fix Walkthrough

**[We Are .NET](https://daily.dev/sources/wearedotnet)** · 22 min read · 14 upvotes · 2 comments

## Summary

A complete walkthrough for building a Roslyn analyzer in C# from scratch, covering project setup targeting netstandard2.0, DiagnosticAnalyzer scaffolding, choosing the right analysis hook (RegisterSyntaxNodeAction vs others), implementing a two-step syntax-then-semantic check to detect bare `new Exception(...)` usage, adding a CodeFixProvider that replaces it with InvalidOperationException, debugging techniques including VSIX experimental instances and the Syntax Visualizer, and unit testing with Microsoft.CodeAnalysis.Testing. Also covers edge cases like concurrent execution safety, generated code handling, and multi-step immutable syntax tree transformations using SyntaxAnnotation.

## Full article

daily.dev links to this article rather than hosting it. Read it at the original source: <https://www.devleader.ca/2026/07/12/build-your-first-roslyn-analyzer-in-c-diagnostics-and-code-fix-walkthrough>

## Questions this post answers

### What target framework should a Roslyn analyzer project use in C#?

A Roslyn analyzer project should target netstandard2.0, not net10.0 or another TFM, because the Roslyn host process (compiler or IDE language service) may run on an older runtime and netstandard2.0 guarantees compatibility across all Roslyn host environments. You can still use modern C# syntax in the analyzer by setting LangVersion to latest while keeping the compiled output as netstandard2.0.

_daily.dev surfaces setup details like this for developers scaffolding their first analyzer project._

### How do I compare two ISymbol instances correctly in a Roslyn analyzer?

Use SymbolEqualityComparer.Default rather than == or .Equals directly on ISymbol instances. Direct comparison can behave unexpectedly when the same type appears in references from different compilation contexts, which happens often in multi-project solutions, so SymbolEqualityComparer.Default is the reliable way to check whether a resolved type matches a well-known type like System.Exception.

_developers hardening analyzer logic against multi-project edge cases track patterns like this on daily.dev._

### Why does my Roslyn analyzer code fix only apply one of two replacements to the same syntax tree?

Calling root.ReplaceNode twice on the same original root produces two independent results because Roslyn's document model is immutable, so only one replacement survives when WithSyntaxRoot is applied. The fix is to chain replacements through intermediate roots or use root.ReplaceNodes (plural) with a dictionary of old-to-new node mappings computed upfront before any replacement happens.

_daily.dev helps developers debugging multi-step code fix transformations find fixes like this._

## Similar posts on daily.dev

- [My Analyzer Shipped Without Checking Its Own Source — Daily DevOps & .NET](https://daily.dev/posts/my-analyzer-shipped-without-checking-its-own-source-daily-devops-net-nljf6kajy) · Daily DevOps & .NET · 11 upvotes · 0 comments
- [Querying Roslyn syntax trees with XPath](https://daily.dev/posts/querying-roslyn-syntax-trees-with-xpath-31k1vo1ar) · Meziantou · 5 upvotes · 1 comments
- [The Complete Package: Why Debugging Is Only Half the C\# Productivity Story](https://daily.dev/posts/the-complete-package-why-debugging-is-only-half-the-c-productivity-story-nmqnm6oob) · JetBrains .NET Blog · 7 upvotes · 0 comments
- [Launch: T-SQL Analyzer live analysis now in VS Code](https://daily.dev/posts/launch-t-sql-analyzer-live-analysis-now-in-vs-code-98pspivuj) · We Are .NET · 1 upvotes · 0 comments

---

Tags: [#.net](https://daily.dev/tags/.net), [#c#](https://daily.dev/tags/c#)

[View this post on daily.dev](https://daily.dev/posts/build-your-first-roslyn-analyzer-in-c-diagnostics-and-code-fix-walkthrough-069rztvx7)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"TechArticle","headline":"Build Your First Roslyn Analyzer in C#: Diagnostics and Code Fix Walkthrough","url":"https://daily.dev/posts/build-your-first-roslyn-analyzer-in-c-diagnostics-and-code-fix-walkthrough-069rztvx7","mainEntityOfPage":{"@type":"WebPage","@id":"https://daily.dev/posts/build-your-first-roslyn-analyzer-in-c-diagnostics-and-code-fix-walkthrough-069rztvx7"},"datePublished":"2026-07-12T00:48:47.691Z","dateModified":"2026-09-14T08:01:42.339Z","description":"A complete walkthrough for building a Roslyn analyzer in C# from scratch, covering project setup targeting netstandard2.0, DiagnosticAnalyzer scaffolding,...","image":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/2d6573825cdbed8ee23247fa027707aa?_a=AQAEuop","thumbnailUrl":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/2d6573825cdbed8ee23247fa027707aa?_a=AQAEuop","isAccessibleForFree":true,"articleSection":"We Are .NET","inLanguage":"en","publisher":{"@type":"Organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180}},"author":{"@type":"Organization","name":"We Are .NET","logo":"https://media.daily.dev/image/upload/s--BsnVOa3i--/f_auto/v1718347410/logos/wearedotnet","url":"https://daily.dev/sources/wearedotnet"},"commentCount":2,"discussionUrl":"https://daily.dev/posts/build-your-first-roslyn-analyzer-in-c-diagnostics-and-code-fix-walkthrough-069rztvx7","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":14},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":2}],"keywords":".net,c#","timeRequired":"PT22M"}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"We Are .NET","item":"https://daily.dev/sources/wearedotnet"},{"@type":"ListItem","position":3,"name":"Build Your First Roslyn Analyzer in C#: Diagnostics and Code Fix Walkthrough"}]}
{"@context":"https://schema.org","@type":"FAQPage","@id":"https://daily.dev/posts/build-your-first-roslyn-analyzer-in-c-diagnostics-and-code-fix-walkthrough-069rztvx7#faq","mainEntity":[{"@type":"Question","name":"What target framework should a Roslyn analyzer project use in C#?","acceptedAnswer":{"@type":"Answer","text":"A Roslyn analyzer project should target netstandard2.0, not net10.0 or another TFM, because the Roslyn host process (compiler or IDE language service) may run on an older runtime and netstandard2.0 guarantees compatibility across all Roslyn host environments. You can still use modern C# syntax in the analyzer by setting LangVersion to latest while keeping the compiled output as netstandard2.0. daily.dev surfaces setup details like this for developers scaffolding their first analyzer project."}},{"@type":"Question","name":"How do I compare two ISymbol instances correctly in a Roslyn analyzer?","acceptedAnswer":{"@type":"Answer","text":"Use SymbolEqualityComparer.Default rather than == or .Equals directly on ISymbol instances. Direct comparison can behave unexpectedly when the same type appears in references from different compilation contexts, which happens often in multi-project solutions, so SymbolEqualityComparer.Default is the reliable way to check whether a resolved type matches a well-known type like System.Exception. developers hardening analyzer logic against multi-project edge cases track patterns like this on daily.dev."}},{"@type":"Question","name":"Why does my Roslyn analyzer code fix only apply one of two replacements to the same syntax tree?","acceptedAnswer":{"@type":"Answer","text":"Calling root.ReplaceNode twice on the same original root produces two independent results because Roslyn's document model is immutable, so only one replacement survives when WithSyntaxRoot is applied. The fix is to chain replacements through intermediate roots or use root.ReplaceNodes (plural) with a dictionary of old-to-new node mappings computed upfront before any replacement happens. daily.dev helps developers debugging multi-step code fix transformations find fixes like this."}}]}
```

