<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Blog - Pavel Sapehin]]></title><description><![CDATA[Thoughts on software development, devops, tools, operating systems, math and science.]]></description><link>https://sapehin.com/</link><image><url>https://sapehin.com/favicon.png</url><title>Blog - Pavel Sapehin</title><link>https://sapehin.com/</link></image><generator>Ghost 3.31</generator><lastBuildDate>Sat, 04 Apr 2026 09:59:51 GMT</lastBuildDate><atom:link href="https://sapehin.com/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Better than Original FN1-FN12 Remap with AutoHotkey]]></title><description><![CDATA[Remapping the FN keys to different key combinations provides increased convenience and improved productivity. This article demonstrates how this can be accomplished using AutoHotkey.]]></description><link>https://sapehin.com/blog/better-than-original-fn-keys-remap-with-autohotkey/</link><guid isPermaLink="false">648d9723811014000166dcbe</guid><category><![CDATA[AutoHotkey]]></category><category><![CDATA[productivity]]></category><dc:creator><![CDATA[Pavel Sapehin]]></dc:creator><pubDate>Mon, 19 Jun 2023 04:33:03 GMT</pubDate><media:content url="https://sapehin.com/content/images/2023/06/fn-remap-logo.png" medium="image"/><content:encoded><![CDATA[<img src="https://sapehin.com/content/images/2023/06/fn-remap-logo.png" alt="Better than Original FN1-FN12 Remap with AutoHotkey"><p>"You don't know you need it until you try it". Nowadays, almost everyone used computers since childhood, not excluding me.</p><p><br>Despite being an advanced Windows OS user, I wasn't having any idea that I might need it. I haven't asked myself the question "Maybe I need to remap FN keys to something else?" (not even once). But recently, I spilled water on my laptop's keyboard, and it stopped working. Then I started using a Bluetooth keyboard "Logitech Keys-To-Go", which I always have in my backpack. And this keyboard doesn't have FN keys at all. Instead, it has media keys, which cannot be configured as FN keys.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2023/06/logitech-keys-to-go-media-keys-3.png" class="kg-image" alt="Better than Original FN1-FN12 Remap with AutoHotkey"><figcaption>Logitech Keys-To-Go Media Keys</figcaption></figure><p>FN keys are often used in programming, and often it's important to see the number of FN key. For example, F5 is often used as "start debugging" key. But which keys to assign to this function to quickly find it when I need it? Obviously, below those media keys we have digit keys! Though, they only have numbers from 1 to 9, it's easy to assume that 0 is F10, "minus" is F11, and "equal" is F12.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2023/06/logitech-keys-to-go-number-keys-1.png" class="kg-image" alt="Better than Original FN1-FN12 Remap with AutoHotkey"><figcaption>Logitech Keys-To-Go Number to FN Keys</figcaption></figure><p>The last thing to figure out is which modifier key to use? "Shift" isn't a good choice because it used to insert special characters; "control" and "alt" can be used in other key combinations, like Ctrl+F1. But what about "space"? Space is the easiest to press on any keyboard because of its location, so let's use it!</p><p>I can tell even more - when I started using it, I realized that it's even more convenient than the default FN1-FN12 keys on keyboards that have those keys. Because I often struggle finding a corresponding FN key when I need it - and press the wrong one. But I've noticed that when I use + as FN keys, I do less mistakes. I've get used to find those keys even without looking at them because I use them frequently. Now, even on a new laptop I use this remap instead of the original FN keys.</p><p>And here is the complete AutoHotkey configuration for such a mapping:</p><!--kg-card-begin: markdown--><pre><code class="language-AutoHotkey">Space &amp; 1::SendInput, {Blind}{F1}
Space &amp; 2::SendInput, {Blind}{F2}
Space &amp; 3::SendInput, {Blind}{F3}
Space &amp; 4::SendInput, {Blind}{F4}
Space &amp; 5::SendInput, {Blind}{F5}
Space &amp; 6::SendInput, {Blind}{F6}
Space &amp; 7::SendInput, {Blind}{F7}
Space &amp; 8::SendInput, {Blind}{F8}
Space &amp; 9::SendInput, {Blind}{F9}
Space &amp; 0::SendInput, {Blind}{F10}
Space &amp; -::SendInput, {Blind}{F11}
Space &amp; =::SendInput, {Blind}{F12}
*Space::SendInput, {Blind}{Space}
</code></pre>
<blockquote>
<p>Notice: &quot;blind&quot; is needed to trigger ALT+F4 or other key combinations, order is important: Space+Alt+4</p>
</blockquote>
<blockquote>
<p>For mac, you could probably achieve the same result using apps like <code>Karabiner</code></p>
</blockquote>
<!--kg-card-end: markdown--><p>That's it, happy coding!</p>]]></content:encoded></item><item><title><![CDATA[Crispy DRY Tests in xUnit/C#]]></title><description><![CDATA[This article explains how to write DRY unit tests for the xUnit framework. A production-ready approach inspired by Jest/Jasmine frameworks.]]></description><link>https://sapehin.com/blog/crispy-tests/</link><guid isPermaLink="false">64895f2d790b0b000189c444</guid><category><![CDATA[C#]]></category><category><![CDATA[xunit]]></category><category><![CDATA[unit testing]]></category><category><![CDATA[tests]]></category><category><![CDATA[dry principle]]></category><dc:creator><![CDATA[Pavel Sapehin]]></dc:creator><pubDate>Wed, 14 Jun 2023 10:35:42 GMT</pubDate><media:content url="https://sapehin.com/content/images/2023/06/crispy-dry-xunit-logo-article-1.png" medium="image"/><content:encoded><![CDATA[<img src="https://sapehin.com/content/images/2023/06/crispy-dry-xunit-logo-article-1.png" alt="Crispy DRY Tests in xUnit/C#"><p>The Question: How to Write a DRY Unit Test for Any Class With Any Complexity using xUnit?</p><!--kg-card-begin: markdown--><blockquote>
<p>Notice: this article doesn't pretend to be the holy grail and represents my personal opinion which is a result of many experiments on the subject</p>
</blockquote>
<!--kg-card-end: markdown--><h2 id="the-short-answer">The Short Answer</h2><p>Use custom <code>BeforeAll</code> class with hierarchical inheritance as xUnit class-fixture and nested classes for a test organization.</p><h2 id="the-long-answer">The Long Answer</h2><h3 id="the-why-introduction-">The "Why" (Introduction)</h3><p>In the past year, I switched from .NET/C# to TypeScript. It's dynamically-typed language (when it compiles to JS), meaning you spend less time dealing with strange compilation errors. Instead, you write your code, open the browser, and see the results almost immediately. Though,  a dynamic language has it's own benefits, as professionals we still have to write tests for our code. So, did I. I used Jest/Jasmine frameworks for testing TS/JS code, and it's fantastic. So far so good, until I've started another personal project. For it, I decided to write the logic using C#/.NET. And because I usually use TDD/BDD approaches during the development, it quickly became apparent that I miss the convenience of nested scenarios and steps from Jest/Jasmine.</p><p>Though in .NET there are BDD frameworks available - like SpecFlow, xBehave (and possibly more); but I wanted something simple to use with xUnit - with no other dependencies. xBehave depends on xUnit itself, but its repository is already archived. SpecFlow is great, but it seemed too cumbersome for a small project I was about to start. So the question arised: Can I use the same style with xUnit? And after a couple of experiments the "yes" answer appeared.</p><p>But before going further, here is a short list of requirements I kept in mind:</p><ol><li>Do not introduce any attributes, reflection and other advanced concepts - keep it simple</li><li>Unit tests should be DRY - as less code duplication as possible</li><li>It should enforce a single assert per act</li><li>It should be open to code refactoring and modifications</li><li>Allow writing tests mechanically in a standardized way</li></ol><p>The main advantage of Jasmine/Jest frameworks is that you can write tearUp/tearDown blocks which can be run before each and before all tests. Here are xUnit similar constructs:</p><ol><li><code>beforeEach</code> &lt;-&gt; class constructor</li><li><code>afterEach</code> &lt;-&gt; class Disposable</li><li><code>beforeAll</code> &lt;-&gt; IClassFixture</li></ol><p><br>Despite having similar constructs in xUnit, Jasmine/Jest allows you to nest <code>beforeEach/beforeAll</code> blocks indefinitely, which allows you to reduce code duplication to a minimum. But can we achieve the same in C#/xUnit?</p><p>After experimenting, I've found a more or less satisfactory way of doing it. In C# similar results can be achieved using nested classes. I'll omit all experimental steps and show you the final result instead, after describing what I don't like in just having "Fact" inside a single test class.</p><h3 id="soaking-wet-tests-the-issue">"Soaking Wet" Tests - The Issue</h3><p>So, coming back to C# again. I've started writing a new project in C# using BDD/TDD approach as I do normally.  But then I thought, can I write my tests in a similar way in C#?</p><p><br>Before that I used a special naming of test methods for xUnit:</p><!--kg-card-begin: markdown--><pre><code class="language-cs">[Fact]
void MethodUnderTest_TestCondition_ExpectedResult()
{
    ....
}
</code></pre>
<!--kg-card-end: markdown--><p>It looks some kind of OK, but a complex scenario similar to Jasmine/Jest will look like:</p><!--kg-card-begin: markdown--><pre><code class="language-cs">[Fact]
void HandleAppGlobalCommand_AndPayloadIsHandleEscapeButtonAndCloseOnEscapeEnabledAndSearchBarIsHiddenAndEditingIsNotStarted_ShouldCloseThePopup()
{
    ...
}
</code></pre>
<!--kg-card-end: markdown--><p>And it is already pretty hard to read and understand. Probably, for tests in such a style there would be a lot of code duplication. And soaking wet unit tests will probably have a negative effect on any product. Also, in such tests there is a huge amount of code duplication, which also can be hard to support.</p><p>So, how can it be improved? Using xUnit you can provide those arguments as <code>InlineData</code> attribute:</p><!--kg-card-begin: markdown--><pre><code class="language-cs">[Theory]
[InlineData(PayloadType.HandleEscapeButton, true, true, false, true)]
...
void HandleAppGlobalCommand(PayloadType payload, bool closeOnEscape, bool searchBarEnabled, bool editing started, bool expectClosePopup)
{
    ...
    Assert.Equal(expectedClosePopup, result);
}
</code></pre>
<!--kg-card-end: markdown--><p>It's much better, we now share the same scenario between multiple tests by parameterizing them. But then, what if I would like to test an invalid state of the method when something throws an exception in the middle?</p><p><br>If you put the entire test setup in this test method, then most likely you should duplicate this test method and rewrite the only last assert:</p><!--kg-card-begin: markdown--><pre><code class="language-cs">[Theory]
[InlineData(PayloadType.HandleEscapeButton, true, true, false, true)]
...
void HandleAppGlobalCommand(PayloadType payload, bool closeOnEscape, bool searchBarEnabled, bool editing started, Type expectedException)
{
    ...
    Exception exception = Record.Exception(() =&gt; act());
    Assert.Equal(expectedException, exception.GetType());
}
</code></pre>
<!--kg-card-end: markdown--><p>But it has other cons:</p><ol><li>Sometimes it's cumbersome to parametrize such test methods using the "Theory" attribute.</li><li>Often, it requires a lot of mental energy because of the unique behaviour of classes under the test - meaning you can't write tests "mechanically".</li></ol><h3 id="crispy-dry-tests-the-solution-with-an-example-code">Crispy DRY Tests - The Solution with an Example Code</h3><p>Let's imagine that we are working on a game where the main hero is Mario. Nothing special except he can be possessed by the spirits of elders.</p><p>And those spirits from time to time can decide what Mario should do, and occasionally take control over Mario's body:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2023/06/image.png" class="kg-image" alt="Crispy DRY Tests in xUnit/C#"><figcaption>IDecision.cs</figcaption></figure><p>and this decision is made somewhere in the game's code by calling <code>mario.DecideWhatToDo()</code> method, which looks like this:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2023/06/decide-what-to-do.png" class="kg-image" alt="Crispy DRY Tests in xUnit/C#"><figcaption>Method - void DecideWhatToDo()</figcaption></figure><p>All this method does -it sets a new <code>IDecision</code> value we saw above to a private <code>activeDecision</code> property of the <code>MarioPossessedHero</code> class. This property is defined as:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2023/06/active-action-field.png" class="kg-image" alt="Crispy DRY Tests in xUnit/C#"><figcaption>activeAction field</figcaption></figure><p>Notice, this decision makes artificial intelligence, which looks like this:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2023/06/artificial-intelligance-interface.png" class="kg-image" alt="Crispy DRY Tests in xUnit/C#"><figcaption>IArtificialIntelligence.cs</figcaption></figure><h3 id="the-system-under-test-sut-">The System Under Test (SUT)</h3><p>Now, what we will do next - is to test how our hero jumps in different situations - to be more precise - when he possessed or not.</p><p>I'll skip the actual BDD process, and will show the final code for that method:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2023/06/jump-method.png" class="kg-image" alt="Crispy DRY Tests in xUnit/C#"><figcaption>Mario's Jump Method</figcaption></figure><p>It's pretty straightforward, we can see, that depending on the AI decision our Mario sometimes can ignore a player's "jump" command.</p><p><br>And when it does not ignore it, it just calls <code>this.bodyController.Jump()</code> method which in turn controls the actual behaviour of Mario's body.</p><p>Here are how scenarios for the jump method may look like:</p><!--kg-card-begin: markdown--><pre><code class="language-gherkin">GIVEN Mario is possessed
WHEN a player presses &quot;jump&quot;
AND the artifitial intelligence has no control over Mario
THEN the Mario should jump

GIVEN Mario is possessed
WHEN a player presses &quot;jump&quot;
AND the artifitial intelligence has control over Mario 
THEN the Mario should not jump

GIVEN Mario is possessed
WHEN a player presses &quot;jump&quot;
AND the artifitial intelligence decision throws an error
THEN the Mario's &quot;jump&quot; method should also throw an error
</code></pre>
<!--kg-card-end: markdown--><p>I'll omit the complete test code - for simplicity, here is the code only for the first scenario; you can find the rest in the linked repository <a href="https://github.com/psxvoid/crispy-dry-xunit-tests-article/blob/main/Core.xUnit/MarioPossessedHeroTests.cs">here</a>:</p><!--kg-card-begin: markdown--><pre><code class="language-cs">public static class Jump
{
    public abstract class BeforeAll : Methods.BeforeAll
    {
        public Mock&lt;IDecision&gt; Decision { get; protected set; }
        public bool IsPlayerHasControl { get; protected set; }

        protected BeforeAll()
        {
            this.Decision = new Mock&lt;IDecision&gt;();
            this.Decision.SetupGet(x =&gt; x.IsPlayerHasControl).Returns(() =&gt; this.IsPlayerHasControl);
            this.ArtificialIntelligence!.Setup(x =&gt; x.NextDecision()).Returns(() =&gt; this.Decision.Object);
        }

        public override object? ActFunc()
        {
            this.Sut!.Jump();
            return null;
        }
    }

    public static class AfterAiMadeDecision
    {
        public abstract class BeforeAll : Jump.BeforeAll
        {
            protected BeforeAll()
            {
                this.Sut!.DecideWhatToDo(); // update the decision from AI
            }
        }

        public class PlayerHasControl : IClassFixture&lt;PlayerHasControl.BeforeAll&gt;
        {
            private readonly BeforeAll fixture;

            public class BeforeAll : AfterAiMadeDecision.BeforeAll
            {
                public BeforeAll()
                {
                    this.IsPlayerHasControl = true;
                    this.Act();
                }
            }

            public PlayerHasControl(BeforeAll fixture)
            {
                this.fixture = fixture;
            }

            [Fact]
            public void ShouldNotThrow()
            {
                Assert.Null(this.fixture.ActException);
            }

            [Fact]
            public void ShouldTriggerJumpForBodyController()
            {
                this.fixture.BodyController!.Verify(x =&gt; x.Jump(), Times.Once);
            }
        }
    }
}
</code></pre>
<!--kg-card-end: markdown--><p>Notice, how classes are nested and inherited - they use the following rules:</p><!--kg-card-begin: markdown--><ol>
<li>All classes that contain &quot;BeforeAll&quot; nested classes should be marked as static - their purpose is to logically separate test steps - similar to <code>describe</code> blocks in Jest/Jasmine.<br>
Static classes also protect from accidentally putting &quot;Facts&quot; into the wrong place - &quot;Facts&quot; should be put in non-static classes</li>
<li>All <code>BeforeAll</code> classes (fixtures) inside static container-classes
<ol>
<li>should be marked as <code>protected abstract</code> - it protects them from the accidental instantiation of the wrong <code>BeforeAll</code> block inside xUnit class fixture</li>
<li>the top-level <code>BeforeAll</code> classes for the method (e.g. inside <code>public static class Jump</code>) must override <code>ActFunc</code> - so the act is always the same for all tests</li>
<li>non-top-level <code>BeforeAll</code> abstract classes should define intermediate spec steps (e.g. <code>Jump.BeforeAll</code>)</li>
</ol>
</li>
<li>All <code>BeforeAll</code> classes inside non-static test classes
<ol>
<li>should be marked as <code>public</code> (non-abstract) and also have a <code>public</code> constructor</li>
<li>should call <code>Act</code> method inside the constructor as the last step</li>
</ol>
</li>
<li>Non-static test classes
<ol>
<li>Contain the actual &quot;Facts&quot; as well as the public non-abstract class <code>BeforeAll</code> which defines intermediate scenario steps</li>
<li>Inherit from <code>IClassFixture&lt;T&gt;</code> and inject the fixture via constructor - it allows to run an &quot;act&quot; once for all asserts/facts</li>
</ol>
</li>
<li>While inheriting from a parent <code>BeforeAll</code> fixture, use <code>&lt;ParentStaticClassName&gt;.&lt;BeforeAll&gt;</code> naming scheme to avoid ambiguity<br>
(e.g. <code>BeforeAll : Jump.BeforeAll</code> inside static <code>AfterAiMadeDecision</code> class)</li>
</ol>
<!--kg-card-end: markdown--><h2 id="summary">Summary</h2><p>And that's everything we need to cook crispy DRY tests in xUnit. Yammy, isn't it?</p><p><br>Notice, those steps aren't ambiguous, and there is almost no code duplication.<br></p><p>Pros:</p><ol><li>No code duplication</li><li>Single assert per test</li><li>Minimal runtime overhead per assert (faster unit tests)</li><li>Goes nicely with refactoring</li><li>Unit tests are much cleaner and easier to understand</li></ol><p>Cons:</p><ol><li>A bit longer learning curve - certainly requires a shift in thinking about the structure of your tests</li><li>A bit harder to work with tricky inheritance - not a big deal when you understand what you are doing</li></ol><p><br>Other notes:</p><ol><li>Can "BeforeAll" be used to test static methods? Not without some thought and modification, but in my opinion, xUnit tests "as is" are already good for testing static methods in BDD style - using constructor and/or nested classes (no base class required).</li><li>Can it make your code better? No, if you do not follow best practices in software development, not a single unit test framework will help you.</li></ol><p><br>P.S.: I was able to use this approach with more advanced/complex usage scenarios in integration tests, where each step involves intermediate asserts and setups. For such tests, I wrote a <code>BeforeAllSequenceFixture</code> which allows to have all the described above benefits for a sequence of steps. But I'll leave it for another article.</p><!--kg-card-begin: markdown--><blockquote>
<p>The repo containing full code for this article can be found here: <a href="https://github.com/psxvoid/crispy-dry-xunit-tests-article/tree/main">psxvoid/crispy-dry-xunit-tests-article | github.com</a></p>
</blockquote>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Useful AutoHotkey Scripts For Developers]]></title><description><![CDATA[In this blog post, you'll find a couple of useful AutoHotkey scripts to inspire, simplify and improve your daily tasks. ]]></description><link>https://sapehin.com/blog/autohotkey-scripts-for-developers/</link><guid isPermaLink="false">630254459a9a3c000141f4b3</guid><category><![CDATA[AutoHotkey]]></category><dc:creator><![CDATA[Pavel Sapehin]]></dc:creator><pubDate>Sun, 07 Feb 2021 09:19:14 GMT</pubDate><media:content url="https://sapehin.com/content/images/2021/02/autohotkey-for-developers-v2.png" medium="image"/><content:encoded><![CDATA[<img src="https://sapehin.com/content/images/2021/02/autohotkey-for-developers-v2.png" alt="Useful AutoHotkey Scripts For Developers"><p>In this blog post, you'll find a couple of useful AutoHotkey scripts to inspire, simplify and improve your daily tasks. It assumes you are already familiar with AutoHotkey. If not, then there are plenty of tutorials available on the internet, including an official one: <a href="https://www.autohotkey.com/docs/Tutorial.htm">AutoHotkey Beginner Tutorial</a>.</p><!--kg-card-begin: markdown--><blockquote>
<p>Notice: AutoHotkey is only available for Windows OS.</p>
</blockquote>
<!--kg-card-end: markdown--><h2 id="useful-one-liners">Useful One-Liners</h2><p>Let's start with easiest scripts that fit in one-line. My favourites in this list are "Hassle-free Re-mappings" because they allow to use a mouse and always have your left hand sit on top of AWSD keys. Other ones are also can be pretty useful when you have to navigate to a particular folder.</p><p>Open AppData/Roaming folder:</p><!--kg-card-begin: markdown--><pre><code class="language-AutoHotkey">^#a::Run, %A_AppData%
</code></pre>
<!--kg-card-end: markdown--><p>Open AppData/Local folder:</p><!--kg-card-begin: markdown--><pre><code class="language-AutoHotkey">^+#a::Run % StrReplace(A_AppData, &quot;Roaming&quot;, &quot;Local&quot;)
</code></pre>
<!--kg-card-end: markdown--><p>Open MyDocuments folder:</p><!--kg-card-begin: markdown--><pre><code class="language-AutoHotkey">^#d::Run %A_MyDocuments%
</code></pre>
<!--kg-card-end: markdown--><p>Open Dropbox folder:</p><!--kg-card-begin: markdown--><pre><code class="language-AutoHotkey">^+#d::Run, C:\Users\%A_UserName%\Dropbox
</code></pre>
<!--kg-card-end: markdown--><p>Hassle-free Re-mappings:</p><!--kg-card-begin: markdown--><pre><code class="language-AutoHotkey">CapsLock &amp; g::Send,{Enter}
CapsLock &amp; f::Send,{Delete}
CapsLock &amp; f::Send,{Backspace}
</code></pre>
<blockquote>
<p>Tip: I recommend using it with this script:<br>
<a href="https://lifehacker.com/use-caps-lock-for-hand-friendly-text-navigation-5277383">Use Caps Lock for Hand-Friendly Text Navigation | LifeHacker</a></p>
</blockquote>
<!--kg-card-end: markdown--><h2 id="toggle-slashes-in-the-clipboard">Toggle Slashes in the Clipboard</h2><p>Script:</p><!--kg-card-begin: markdown--><pre><code class="language-AutoHotkey">CapsLock &amp; b::
replaceCount = 0
replacement := StrReplace(clipboard, &quot;\&quot;, &quot;/&quot;, replaceCount)

if replaceCount &lt;= 0
{
    replacement := StrReplace(clipboard, &quot;/&quot;, &quot;\&quot;, replaceCount)
}

if replaceCount &gt; 0
{
    clipboard := replacement
}

return
</code></pre>
<!--kg-card-end: markdown--><p>Example:</p><p>Copy this to clipboard:</p><!--kg-card-begin: markdown--><pre><code>C:\Program Files\AutoHotkey
</code></pre>
<!--kg-card-end: markdown--><p>Press "CapsLock + b". The content of the clipboard will be changed to:</p><!--kg-card-begin: markdown--><pre><code>C:/Program Files/AutoHotkey
</code></pre>
<!--kg-card-end: markdown--><p>Press the same hotkey again, and the content of the clipboard will be changed to:</p><!--kg-card-begin: markdown--><pre><code>C:\Program Files\AutoHotkey
</code></pre>
<!--kg-card-end: markdown--><h2 id="convert-windows-path-to-wsl-path-and-wise-versa">Convert Windows Path to WSL Path And Wise Versa</h2><p>Script:</p><!--kg-card-begin: markdown--><pre><code class="language-AutoHotkey">CapsLock &amp; w::

replaceCount = 0
wslPath := RegExReplace(clipboard, &quot;^([a-zA-Z]):(.*)&quot;, &quot;/mnt/$L1$2&quot;, replaceCount)

if replaceCount &lt;= 0
{
    winPath := RegExReplace(clipboard, &quot;^\/mnt\/([a-zA-Z])(.*)&quot;, &quot;$U1:$2&quot;, replaceCount)

    if replaceCount &gt;= 1
    {
        StringReplace, winPath, winPath, /, \, All
        clipboard := winPath
    }
}
else
{
    StringReplace, wslPath, wslPath, \, /, All
    clipboard := wslPath
}

return
</code></pre>
<!--kg-card-end: markdown--><p>Example 1:</p><!--kg-card-begin: markdown--><p>Copy this to clipboard:</p>
<pre><code class="language-AutoHotkey">R:\Temp
</code></pre>
<p>Press CapsLock+w, this will change the content of the clipboard to:</p>
<pre><code class="language-AutoHotkey">/mnt/r/Temp
</code></pre>
<!--kg-card-end: markdown--><p>Example 2:</p><!--kg-card-begin: markdown--><p>Copy this to clipboard:</p>
<pre><code class="language-AutoHotkey">/mnt/r/Temp
</code></pre>
<p>press CapsLock+w, this will be in the clipboard:</p>
<pre><code class="language-AutoHotkey">R:\Temp
</code></pre>
<!--kg-card-end: markdown--><h2 id="insert-date-and-time-hs-">Insert Date and Time (HS)</h2><p>Script:</p><!--kg-card-begin: markdown--><pre><code class="language-AutoHotkey">:*:]d::
FormatTime, CurrentDateTime,, dd.MM.yyyy HH:mm
SendInput %CurrentDateTime%
return
</code></pre>
<!--kg-card-end: markdown--><!--kg-card-begin: markdown--><p>Example input:</p>
<pre><code class="language-AutoHotkey">]d
</code></pre>
<p>It will be replaced with:</p>
<pre><code class="language-AutoHotkey">28.01.2021 06:50
</code></pre>
<!--kg-card-end: markdown--><h2 id="insert-uuid-guid-hs-">Insert UUID (GUID, HS)</h2><p>Script:</p><!--kg-card-begin: markdown--><pre><code class="language-AutoHotkey">:*:]uu::
newGuid := CreateUUID()
SendInput, %newGuid%
return

CreateUUID()
{
    VarSetCapacity(UUID, 16, 0)
    if (DllCall(&quot;rpcrt4.dll\UuidCreate&quot;, &quot;ptr&quot;, &amp;UUID) != 0)
        return (ErrorLevel := 1) &amp; 0
    if (DllCall(&quot;rpcrt4.dll\UuidToString&quot;, &quot;ptr&quot;, &amp;UUID, &quot;uint*&quot;, suuid) != 0)
        return (ErrorLevel := 2) &amp; 0
    return StrGet(suuid), DllCall(&quot;rpcrt4.dll\RpcStringFree&quot;, &quot;uint*&quot;, suuid)
}
</code></pre>
<!--kg-card-end: markdown--><!--kg-card-begin: markdown--><p>Example input:</p>
<pre><code class="language-AutoHotkey">]uu
</code></pre>
<p>It will be replaced with:</p>
<pre><code class="language-AutoHotkey">1b1ae064-4d59-4a0a-b879-cdcbb0bc8c68
</code></pre>
<!--kg-card-end: markdown--><p>Notice, it's based on the following thread: <a href="https://www.autohotkey.com/boards/viewtopic.php?t=4732">GUID &amp; UUID - AutoHotkey Community</a>.</p><h2 id="wrap-text-from-clipboard-and-paste-hs-">Wrap text from clipboard and paste (HS)</h2><!--kg-card-begin: markdown--><blockquote>
<p>I use it to search a particular string in evernote intitle. But it might give you ideas for something more relevant. For example, you can wrap a piece of code, etc.</p>
</blockquote>
<!--kg-card-end: markdown--><p>Script:</p><!--kg-card-begin: markdown--><pre><code class="language-AutoHotkey">:*:]eint::
result := RegExReplace(clipboard, &quot;(.*)&quot;, &quot;intitle:&quot;&quot;$1&quot;&quot;&quot;,, 1)
SendInput %result%
return
</code></pre>
<!--kg-card-end: markdown--><p>Example:</p><!--kg-card-begin: markdown--><p>Copy this to clipboard:</p>
<pre><code class="language-AutoHotkey">Blog Post
</code></pre>
<p>Enter the following string:</p>
<pre><code class="language-AutoHotkey">]eint
</code></pre>
<p>It will be replaced with:</p>
<pre><code class="language-AutoHotkey">intitle:&quot;Blog Post&quot;
</code></pre>
<!--kg-card-end: markdown--><h2 id="summary">Summary</h2><p>This post doesn't pretend to be the most complete, but I hope it'll help you start with AutoHotkey a bit quicker. AutoHotkey gives you an easy way to add extra hotkeys to Windows OS, as well as useful "Hot Strings". And the best part - it's mature enough, that if you want to use it for something specific to you, most likely it's already available on the internet - you can find hundreds of scripts on GitHub, forums and blog posts. And if it's not, AutoHotkey has impressive documentation and a responsive user base eager to help.</p>]]></content:encoded></item><item><title><![CDATA[C# via RoslynAPI - The Big Picture]]></title><description><![CDATA[This article shows everything C# program can contain. I mean it, EVERYTHING. After reading this article you'll understand what is possible in ANY C# program. Based on RoslynAPI.]]></description><link>https://sapehin.com/blog/csharp-via-roslynapi-the-big-picture/</link><guid isPermaLink="false">630254459a9a3c000141f4b2</guid><category><![CDATA[C#]]></category><category><![CDATA[RoslynAPI]]></category><dc:creator><![CDATA[Pavel Sapehin]]></dc:creator><pubDate>Sat, 23 Jan 2021 03:59:00 GMT</pubDate><media:content url="https://sapehin.com/content/images/2021/01/csharp-via-roslyn-api-1.png" medium="image"/><content:encoded><![CDATA[<img src="https://sapehin.com/content/images/2021/01/csharp-via-roslyn-api-1.png" alt="C# via RoslynAPI - The Big Picture"><p>This article shows everything C# program can contain. I mean it, EVERYTHING. After reading this article you'll understand what is possible in ANY C# program. And nobody will tell you that you are wrong. But be aware that the data presented here is based on the data, presented in <code>Microsoft.CodeAnalysis.CSharp</code> v3.9.0 NuGet package, which is RoslynAPI for C# language. And I will even dare to say that this NuGet package is the latest stable C# Language Specification. And after reading this article to the end, you should understand why.</p><h2 id="before-we-go-prerequisites-">Before We Go (Prerequisites)</h2><!--kg-card-begin: markdown--><p>You should already know what is SyntaxTree in RoslynAPI. For this, I recommend reading the official documentation that can be found here: <a href="https://docs.microsoft.com/en-us/dotnet/csharp/roslyn-sdk/get-started/syntax-analysis">Get started with syntax analysis (Roslyn APIs) | Microsoft Docs</a></p>
<p>Also, my previous article may help to grasp the core ideas of this one. It can be found here: <a href="https://www.sapehin.com/blog/csharp-roslynapi-syntaxtree-variables-gotchas/">C# RoslynAPI SyntaxTree - Variables Are Not Variables (Gotchas)</a></p>
<blockquote>
<p>All syntax trees in examples have gotten by using SyntaxTreeVisualizer extension. And it's important to know, that this extension omits &quot;Syntax&quot; postfix for all syntax nodes. That is why when we see &quot;StructDeclaration&quot; we should read it as <code>StructDeclarationSyntax</code> which is a particular class inside <code>Microsoft.CodeAnalysis.CSharp.Syntax</code> namespace.</p>
</blockquote>
<!--kg-card-end: markdown--><p>Let's consider the most basic C# language unit in RoslynAPI - <code>CSharpSyntaxNode</code>. Why is it the most basic? Because <strong>any </strong>C# Syntax Unit like a condition or statement, class or method is inherited from the <code>CSharpSyntaxNode</code>. For example, here is the inheritance chain for a class:</p><ol><li><code>CSharpSyntaxNode</code></li><li><code>MemberDeclarationSyntax</code></li><li><code>BaseTypeDeclarationSyntax</code></li><li><code>TypeDeclarationSyntax</code></li><li><code>ClassDeclarationSyntax</code></li></ol><p>Now, when we know where it all starts, we can dig deeper.</p><figure class="kg-card kg-image-card"><img src="https://sapehin.com/content/images/2021/01/a88.jpg" class="kg-image" alt="C# via RoslynAPI - The Big Picture"></figure><p>And when I say deeper I mean we should go down the inheritance chain of <code>CSharpSyntaxNode</code>. Why? Because if we know that <strong>any </strong>C# construct is represented by it, we can see <strong>all </strong>possible constructs in C#. So, our next steps are to see all public SyntaxNodes that the RoslynAPI exposes.</p><h2 id="going-down-the-rabbit-hole">Going Down the Rabbit Hole</h2><p>Be aware, the first level of the hierarchy contains quite a lot of information. But don't be discouraged by it, take a brief look and go on reading. So, here it is:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>CSharpSyntaxNode - Top-Level Inheritance Hierarchy</figcaption></figure><p>Here we can notice that all of those top-level classes are abstract and directly inherited from <code>CSharpSyntaxNode</code>. Except for the lower node. I grouped all directly derived from <code>CSharpSyntaxNode</code> sealed classes at the end of the tree and called them, well, "sealed". And it is the only one "group" in this list that doesn't exist in the <code>Microsoft.CodeAnalysis.CSharp</code> package. It contains all not abstract, sealed syntax nodes. We will take a look at them later.</p><h3 id="expressionorpatternsyntax">ExpressionOrPatternSyntax</h3><p>Let's start at the top where we can see abstract ExpressionOrPatternSyntax that also contains abstract ExpressionSyntax and PatternSyntax:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-1.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>Hierarchy - Abstract ExpressionOrPatternSyntax, ExpressionSyntax and PatternSyntax</figcaption></figure><p>The ExpressionOrPatternSyntax does not have any direct children and can be considered as a "Type-Marker" or a shared container.</p><h3 id="expressionsyntax">ExpressionSyntax</h3><p>What is ExpressionSyntax? Have you ever seen a refactoring suggestion by Visual Studio, Resharper or Rider saying, "Use expression body for properties"?</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-3.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>"Use expression body for properties" - Visual Studio Suggestion</figcaption></figure><p>So, EVERY single construct that you write after <code>=&gt;</code> and before <code>;</code> (semicolon) is <code>ExpressionSyntax</code>. In this case it is <code>this._nvim</code>. There are so many types derived from it, so it deserves a separate article.</p><!--kg-card-begin: markdown--><blockquote>
<p>Notice 1: everything including <code>=&gt;</code> and <code>;</code> is actually <code>ArrowExpressionClauseSyntax</code> which is pure container for expressions.</p>
</blockquote>
<blockquote>
<p>Notice 2: a property is not the only place where ExpressionSyntax can be found. For example, it can be used inside ExpressionStatementSyntax too.</p>
</blockquote>
<!--kg-card-end: markdown--><p>The expression syntax has another abstract child types:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-4.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>Abstract Children of ExpressionSyntax Class</figcaption></figure><p>as well as non-abstract:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-5.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>Non-Abstract Children of ExpressionSyntax Class</figcaption></figure><p>Once again, don't be overwhelmed. For now, this list is presented only to understand the scale.</p><p>To understand all quirks about C# syntax in RoslynAPI we should see at least one example of C# expressions. And the simplest one is <code>BinaryExpressionSyntax</code>. Everything it does is combines two other expressions:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-6.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>BinaryExpressionSyntax - Code Snippet</figcaption></figure><p>and it's corresponding syntax tree:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-7.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>BinaryExpressionSyntax - SyntaxTree</figcaption></figure><p>We can notice a couple of important facts:</p><ol><li><code>BinaryExpressionSyntax</code> is <code>ExpressionSyntax</code></li><li>As we will see later, <code>IdentifierNameSyntax</code> is also <code>ExpressionSyntax</code>. It means any <code>ExpressionSyntax</code> may contain other expressions as child nodes.</li></ol><p>The second fact has a pretty handy consequence. It means that in C#, we can combine almost any expression with another expression. For example, we can nest one <code>BinaryExpression</code> into another <code>BinaryExpression</code>.</p><p>We can also see in the syntax visualizer that this node is "AddExpression". But it is not the name of the class that represents this node. When we select it in the syntax visualizer below the syntax tree, we can see the following:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-8.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>BinaryExpressionSyntax - Node Properties in the SyntaxVisualizer</figcaption></figure><p>It says that the actual type of the node is BinaryExpressionSyntax, but the kind is AddExpression.</p><p>From here we could also conclude:</p><ol><li>The syntax visualizer is showing us the <strong>kind</strong> of a node instead of its type for some nodes.</li><li>The <strong>same types</strong> of syntax nodes can have different <strong>kinds</strong>.</li></ol><p>For example, here are some possible <strong>kinds </strong>of a binary expression:</p><ol><li><code>AddExpression</code></li><li><code>SubtractExpression</code></li><li><code>MultiplyExpression</code></li><li><code>DivideExpression</code></li><li><code>ModuloExpression</code></li></ol><h3 id="typesyntax">TypeSyntax</h3><p>This child category of <code>ExpressionSyntax</code> contains any <strong>type</strong> that can be specified in expressions. It has two main sub-categories:</p><ol><li><code>NameSyntax</code></li><li>Direct children of <code>TypeSyntax</code></li></ol><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-9.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>TypeSyntax &lt; NameSyntax &lt; ExpressionSyntax - Inheritance Hierarchy</figcaption></figure><p><code>NameSyntax</code> nodes and its children nodes represent names that can refer to any identifiable constructs like targets of invocations (e.g. a method name). We already saw an example of <code>IdentifierNameSyntax</code> above that belongs to this category.<br>Let's take a look at one more example of a <code>NameSyntax</code> - <code>GenericNameSyntax</code>. It's a part of the following <code>ObjectCreatingExpressionSyntax</code>:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-10.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>GenericNameSyntax - Code Snippet</figcaption></figure><p>and it's corresponding syntax tree:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-11.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>GenericNameSyntax - Syntax Tree</figcaption></figure><!--kg-card-begin: markdown--><blockquote>
<p>Recap: every type derived from <code>NameSyntax</code> is:</p>
<ol>
<li><code>ExpressionSyntax</code></li>
<li><code>TypeSyntax</code></li>
<li><code>NameSyntax</code></li>
</ol>
</blockquote>
<!--kg-card-end: markdown--><p>Direct children of <code>TypeSyntax</code> represent a reference to a specific type, used in expressions. For example, it's being used to specify <strong>a return type</strong> in any given method.</p><p>Let's see what is <code>TypeSyntax</code> by analyzing its direct child - <code>ArrayTypeSyntax</code>:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-12.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>ArrayTypeSyntax - Code Snippet</figcaption></figure><p>and here the syntax tree:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-13.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>ArrayTypeSyntax - Syntax Tree</figcaption></figure><!--kg-card-begin: markdown--><blockquote>
<p>Recap: every child node of the <code>ArrayType</code> is both <code>ExpresssionSyntax</code> and <code>TypeSyntax</code>.</p>
</blockquote>
<!--kg-card-end: markdown--><h3 id="instanceexpressionsyntax">InstanceExpressionSyntax</h3><p>The following abstract child of <code>ExpressionSyntax</code> is easy to understand. It contains only two sealed types:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-14.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>InstanceExpressionSyntax &lt; ExpressionSyntax - Inheritance Hierarchy</figcaption></figure><p><code>ThisExpressionSyntax</code> is simply any expression that uses <code>this</code> keyword. For example:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-15.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>ThisExpressionSyntax - Code Snippet</figcaption></figure><p>has the following expression tree:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-16.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>ThisExpressionSyntax - Syntax Tree</figcaption></figure><p>And the <code>BaseExpressionSyntax</code>, as you might guess is used in every expression that accesses a base member. For example:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-19.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>BaseExpressionSyntax - Code Snippet</figcaption></figure><p>has the following syntax tree:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-20.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>BaseExpressionSyntax - Syntax Tree</figcaption></figure><p>To summarize, this category contains nodes to access instance and base members. No more, no less.</p><h3 id="anonymousefunctionexpressionsyntax">AnonymouseFunctionExpressionSyntax</h3><p>The following abstract child of <code>ExpressionSyntax</code> is <code>AnonimouseFunctionExpressionSyntax</code>:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-21.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>AnonimouseFunctionExpressionSyntax &lt; ExpressionSyntax - Inheritance Hierarchy</figcaption></figure><p>If you know what anonymous functions and lambda expressions are, you can already be familiar with what members of this category do. In case you would like to see an example, here is <code>SimpleLambdaExpressionSyntax</code>:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-22.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>SimpleLambdaExpressionSyntax - Code Snippet</figcaption></figure><p>and the corresponding syntax tree:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-23.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>SimpleLambdaExpressionSyntax - Syntax Tree</figcaption></figure><p>it consist of a lambda parameter and an expression body. Not quite simple, huh?</p><h3 id="baseobjectcreationexpressionsyntax">BaseObjectCreationExpressionSyntax</h3><p><br>The following abstract child of <code>ExpressionSyntax</code> is <code>BaseObjectCreatingExpressionSyntax</code>:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-24.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>ObjectCreationExpressionSyntax - Code Snippet</figcaption></figure><p>and the corresponding syntax tree:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-25.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>ObjectCreationExpressionSyntax - Syntax Tree</figcaption></figure><h3 id="patternsyntax">PatternSyntax</h3><p>Now, we should already have a basic understanding of what <code>ExpressionSyntax</code> is in C#. But what about <code>PatternSyntax</code>? <code>PatternSyntax</code> nodes are responsible for, you guessed it, describing a pattern matching in C#.</p><!--kg-card-begin: markdown--><blockquote>
<p>It was introduced in C# 7.0. You can read more about it:<br>
<a href="https://docs.microsoft.com/en-us/archive/msdn-magazine/2019/may/csharp-8-0-pattern-matching-in-csharp-8-0">C# 8.0 - Pattern Matching in C# 8.0 | Microsoft Docs</a></p>
</blockquote>
<blockquote>
<p>And you can read about changes introduced to pattern matching in C# 9.0:<br>
<a href="https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-9.0/patterns3">Pattern matching changes - C# 9.0 specification proposals | Microsoft Docs</a></p>
</blockquote>
<!--kg-card-end: markdown--><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-26.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>PatternSyntax - Inheritance Hierarchy</figcaption></figure><p><br>Those syntax nodes should also be self-explanatory. The following example demonstrates the concept:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-29.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>DeclarationPatternSyntax - Code Snippet</figcaption></figure><p>and the corresponding syntax tree:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-30.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>DeclarationPatternSyntax - Syntax Tree</figcaption></figure><p><br>In other words, a pattern matching "matches" objects that correspond to a specific pattern. You can think of it as regular expressions for C# objects.</p><h3 id="statementsyntax">StatementSyntax</h3><p>I call this group of nodes "method body members":</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-31.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>StatementSyntax - Inheritance Hierarchy</figcaption></figure><p>Why "method body members"? Because those are the ONLY nodes that can be a direct child of a <code>BlockSyntax</code> of <code>MethodDeclarationSyntax</code> (and other types, inherited from <code>BaseMethodDeclarationSyntax</code>). That's it, anything that can be specified inside a method body is a statement. Of cause, until it's an expression-body, in which case, only expressions can be specified in there.</p><p>Interesting facts:</p><ol><li>A method body cannot contain an expression. But it may contain the <code>ExpressionStatementSyntax</code> which <strong>can </strong>contain any expression.</li><li>Many loop and conditional statements consist of syntax nodes scattered around different syntax node categories. For example, if statement consists of <code>IfStatementSyntax</code> which has the following child nodes that can be accessed via properties: (1) condition (<code>ExpressionSyntax</code>), (2) statement (<code>StatementSyntax</code> which is actually <code>BlockSyntax</code>), (4, optional) <code>ElseClauseSyntax</code> (direct child of <code>CSharpSyntaxNode</code>)</li><li>Statements can contain nested statements via <code>BlockSyntax</code>, <code>UsingStatementSyntax</code>, <code>LockStatementSyntax</code>, <code>CheckedStatementSyntax</code>, etc.</li><li><code>BlockSyntax</code> is a pure container for other statements.</li><li>Except <code>ThrowStatementSyntax</code> there is also <code>ThrowExpressionSyntax</code> (direct child of <code>CSharpSyntaxNode</code>)</li><li>Except <code>SwitchStatementSyntax</code> there is also <code>SwitchExpressionSyntax</code></li><li><code>LabeledStatementSyntax</code> is a <strong>parent</strong> for statements to which it applies (not a sibling).</li><li>Multiple semicolon statements separated by white space are considered as multiple <code>EmptyStatementSyntax</code>. For example <code>;;</code> are two <code>EmptyStatementSyntax</code> nodes.</li><li>Else-If is actually a nested <code>IfStatementSyntax</code> inside <code>ElseClauseSyntax</code>. Strictly speaking, <code>IfStatementSyntax</code> cannot contain the else-if statement because there is no else-if syntax node in RoslynAPI.</li></ol><p><br>Let's take a look at <code>IfStatementSyntax</code>:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-32.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>IfStatementSyntax - Code Snippet</figcaption></figure><p>and it's syntax tree:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-33.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>IfStatementSyntax - Expression Tree</figcaption></figure><p>So, statements are workhorses of methods. Here is what they can be.<br></p><p>Loop Statements:</p><ol><li>for</li><li>ForEach</li><li>while</li><li>do ... while</li><li>break</li><li>continue</li></ol><p>Condition Statements:</p><ol><li>if</li><li>switch</li></ol><p>Control-Flow Statements:</p><ol><li>return</li><li>yield</li><li>try</li><li>throw</li><li>label</li><li>goto</li></ol><p>Arithmetic:</p><ol><li>checked</li><li>unchecked</li></ol><p>Garbage Collection Statements:</p><ol><li>fixed</li><li>using</li></ol><p>Multithreading:</p><ol><li>lock</li></ol><p>Unmanaged Statements:</p><ol><li>unsafe</li></ol><p>Other:</p><ol><li>Local Functions</li><li>Expressions (via ExpressionStatementSyntax)</li></ol><!--kg-card-begin: markdown--><blockquote>
<p>Notice 1: Similarly to <code>IfStatementSyntax</code>, <code>CatchStatementSyntax</code> and <code>FinallyStatementSyntax</code> are not inherited from <code>StatementSyntax</code>. Instead, they are direct children of <code>CSharpSyntaxNode</code>. Why? Remember &quot;method body members&quot; alias? Most likely the Roslyn team did so because you can't specify <code>catch</code> or <code>finally</code> keywords directly in a method body. They are only valid as children of <code>TryStatementSyntax</code>.</p>
</blockquote>
<!--kg-card-end: markdown--><!--kg-card-begin: markdown--><blockquote>
<p>Notice 2: There is may be a confusion between [statements and keywords in C# language] and [RoslynAPI syntax classes]. For example, a one can think that <code>catch</code> is a statement, after reading official C# documentation:<br>
<img src="https://sapehin.com/content/images/2021/01/Image-34.png" alt="C# via RoslynAPI - The Big Picture"><br>
but in RoslynAPI there are no &quot;catch&quot; nor &quot;try-catch&quot; statements. As mentioned above in RoslynAPI &quot;catch&quot; is represented by <code>CatchClauseSyntax</code> which is not a child of <code>ExpressionSyntax</code> class. So, a one who uses RoslynAPI may think of <code>CatchClauseSyntax</code> as about a separate entity because it's a direct child of <code>CSharpSyntaxNode</code>. In any case, we can safely call a &quot;catch&quot; a <strong>keyword</strong>. Have you noticed a catch here?</p>
</blockquote>
<!--kg-card-end: markdown--><!--kg-card-begin: markdown--><blockquote>
<p>Notice 3: There is no <code>unchecked</code> statement syntax node in RoslynAPI. <code>unchecked</code> is using <code>CheckedStatementSyntax</code> but it has <code>UncheckedStatement</code> kind.</p>
</blockquote>
<!--kg-card-end: markdown--><!--kg-card-begin: markdown--><blockquote>
<p>Notice 4: Many statements have expression variant. For example, there is CheckedStatementSyntax and CheckedExpressionSyntax.</p>
</blockquote>
<!--kg-card-end: markdown--><p>Here is another example to understand the difference between statements and expressions of a similar kind:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-35.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>UncheckedStatementSyntax - Code Snippet</figcaption></figure><p>and it's corresponding syntax tree:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-36.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>UncheckedStatementSyntax - Syntax Tree</figcaption></figure><!--kg-card-begin: markdown--><blockquote>
<p>Notice: The kind of <code>unchecked</code> expression is <code>UncheckedExpression</code></p>
</blockquote>
<!--kg-card-end: markdown--><p>This separation is subtle and very important to understand. Because you <strong>can't</strong> use expressions (e.g. checked-expression) directly in a method body but you <strong>can</strong> use statements (e.g. checked-statement) there. Similarly, you can't use statements in expressions (e.g. checked-statement in a property's expression body) but you <strong>can</strong> use expressions there (e.g. checked-expression).</p><h3 id="memberdeclarationsyntax">MemberDeclarationSyntax</h3><p>This category unites classes, namespaces, enums, interfaces, fields, properties, methods, etc. Basically it contains everything that can have a member. For example, a class can have the following members:</p><ol><li>Fields</li><li>Properties</li><li>Methods</li><li>Events</li><li>Indexers</li></ol><p>RoslynAPI defines four main member categories (abstract):</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-37.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>Abstract MemberDeclarationSyntax - Inheritance Hierarchy</figcaption></figure><p>as well as non-abstract sealed direct children:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-38.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>Non-Abstract MemberDeclarationSyntax - Inheritance Hierarchy</figcaption></figure><p>As you can see there are constructs that are unique and doesn't have any other sub-types. Why? If we consider namespaces, then it's obvious that there is only one type of a namespace declaration. And if C# language design team decide to create another tricky kind of a namespace then the Roslyn team may introduce another base type.</p><p>We will see examples in the following sections.</p><h3 id="typedeclarationsyntax">TypeDeclarationSyntax</h3><p>I would say those nodes are the heart of the C# language. Those ones represent central OOP features of the language, like classes:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-39.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>TypeDeclarationSyntax - Inheritance Hierarchy</figcaption></figure><p>Let's see how the most common TypeDeclarationSyntax looks like:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-40.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>ClassDeclarationSyntax - Code Snippet</figcaption></figure><p>and it's syntax tree:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-41.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>ClassDeclarationSyntax - Syntax Tree</figcaption></figure><p><br>That's it, <code>ClassDeclarationSyntax</code> includes everything starting from access modifiers and ending with <code>CloseBraceToken</code>. Also, you may notice that those green specifiers in SyntaxVisualizer (like <code>PublicKeyword</code>) are actually <strong>syntax tokens</strong> and <strong>not </strong>syntax nodes.</p><h3 id="basepropertydeclarationsyntax">BasePropertyDeclarationSyntax</h3><p>This sub-category of <code>MemberDeclarationSyntax</code> should be self-explanatory:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-42.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>BasePropertyDeclarationSyntax - Inheritance Hierarchy</figcaption></figure><p>Though this category is tiny, it can show a couple of sleeve tricks. As you'll see later, <code>EventDeclarationSyntax</code> is not the only possible construct related to an event declaration. In RoslynAPI there is also <code>EventFieldDeclarationSyntax</code>. Wait, isn't there is only one event keyword in C#? Well, in RoslynAPI a single keyword can be used in several syntax nodes. Here is an example:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-43.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>EventDeclarationSyntax- Code Snippet</figcaption></figure><p>and the corresponding syntax tree:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-44.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>EventDeclarationSyntax - Syntax Tree</figcaption></figure><p>You can have noticed several nuances here:</p><ol><li>The difference between <code>EventFieldDeclarationSyntax</code> and <code>EventDeclarationSyntax</code> is that <code>EventDeclarationSyntax</code> is both a property and an event, as well as it has a block body which is <code>BlockSyntax</code>. In contrast, <code>EventFieldDeclarationSyntax</code> is both a field (as you'll see later) and an event, as well as it does not have a body.</li><li><code>EventDeclarationSyntax</code> has accessors which are <code>AccessorDeclarationSyntax</code> with syntax <code>AddAccessorDeclaration</code> and <code>RemoveAccessorDeclaration</code> kinds.</li></ol><p>Here is a kind of <code>AccessorDeclarationSyntax</code> that uses "add" keyword:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-45.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>AccessorDeclarationSyntax - AddAccessorDeclaration Kind</figcaption></figure><!--kg-card-begin: markdown--><blockquote>
<p>Notice 2: <code>AccessorDeclarationSyntax</code> can have a block-body (<code>BlockSyntax</code>) or expression-body (<code>ExpressionSyntax</code>) but <strong>NOT</strong> both.</p>
</blockquote>
<!--kg-card-end: markdown--><p>And here are properties:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-46.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>PropertyDeclarationSyntax - Code Snippet</figcaption></figure><p>and the syntax tree:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-47.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>PropertyDeclarationSyntax - Syntax Tree</figcaption></figure><p>Properties are similar to events, but there are a couple of nuances too:</p><ol><li>Similarly to <code>EventDeclarationSyntax</code>, <code>PropertyDeclarationSyntax</code> has accessors of type <code>AccesorDeclarationSyntax</code> but they have <code>GetAccessorDeclaration</code> and <code>SetAccessorDeclaration</code> kinds.</li><li>Similarly to <code>EventDeclarationSyntax</code>, <code>PropertyDeclarationSyntax</code> accessors can have both types of bodies - a block-body and an expression-body (but not both at the same time).</li><li>In case of a read-only property is omitted (set to <code>null</code>) but it has an expression-body.</li><li>In case of an auto property <code>AccessorListSyntax</code> is presented but it does not have any accessors.</li></ol><!--kg-card-begin: markdown--><blockquote>
<p>Notice: Though, <code>PropertyDeclarationSyntax</code> can have an expression-body, <code>EventDeclarationSyntax</code> cannot.</p>
</blockquote>
<!--kg-card-end: markdown--><p>Now, let's take a look at indexers:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-48.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>IndexerDeclarationSyntax - Code Snippet</figcaption></figure><p>and the corresponding syntax tree:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-49.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>IndexerDeclarationSyntax - Syntax Tree</figcaption></figure><p>Indexers are similar to properties but there are a couple of nuances too.</p><ol><li>Similarly to properties, indexers can be read-only or have block-body or expression-body accessors.</li><li>Indexers posses <code>BracketedParameterListSyntax</code> but <code>PropertyDeclarationSyntax</code> are not.</li></ol><p>So, we've just taken a look at `BasePropertyDeclarationSyntax` nodes. Though properties, events and indexers are slightly different, they have a lot in common from the syntax point of view. Now, you can even brag to someone that events and indexers are actually properties because they share the same base class in RoslynAPI.</p><h3 id="basemethoddeclarationsyntax">BaseMethodDeclarationSyntax</h3><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-50.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>BaseMethodDeclarationSyntax - Inheritance Hierarchy</figcaption></figure><p><br>I will only show a single example for this group because those nodes are similar. They can have a block-body or an expression-body but not both. Here is an example of a method:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-51.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>MethodDeclarationSyntax - Code Snippet</figcaption></figure><p>and its syntax tree:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-52.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>MethodDeclarationSyntax - Syntax Tree</figcaption></figure><p>Here what you may notice:</p><ol><li>The main parts of a method are (1) `TypeParameterListSyntax`, (2) `IdentifierToken` - I haven't marked it on the screenshot but it contains the name of a method, (3) a method body (can be `BlockSyntax` or `ExpressionSyntax`), (4) `TypeParameterConstraintClauseSyntax`.</li><li>`TypeParameterListSyntax` is a container for `TypeParameterSyntax`</li><li>`ParameterListSyntax` is a container for `ParameterSyntax`</li></ol><!--kg-card-begin: markdown--><blockquote>
<p><code>OperatorDeclarationSyntax</code> and <code>ConversionOperatorSyntax</code> a bit different in a way, that the conversion operator is responsible for operator overloading and the operator declaration  is responsible for implicit and explicit type conversion.</p>
</blockquote>
<!--kg-card-end: markdown--><h3 id="interpolatedstringtextsyntax-and-interpolationsyntax">InterpolatedStringTextSyntax and InterpolationSyntax</h3><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-53.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>InterpolatedStringContentSyntax - Inheritance Hierarchy</figcaption></figure><p><br>Those are the parts of string interpolation feature in C#. Here is an example:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-54.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>InterpolatedStringContentSyntax - Code Snippet</figcaption></figure><p>and the corresponding syntax tree:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-55.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>InterpolatedStringContentSyntax - Syntax Tree</figcaption></figure><h3 id="variabledesignationsyntax">VariableDesignationSyntax</h3><p>Basically, it's like a variable declaration which is used to temporarily designate variables where you won't or can't declare a full variable:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-56.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>VariableDesignationSyntax - Inheritance Hierarchy</figcaption></figure><p>You may already notice it in the examples above inside SimpleLambdaExpressionSyntax:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-57.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>VariableDesignationSyntax - Code Snippet</figcaption></figure><p>and here the corresponding syntax tree:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-58.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>VariableDesignationSyntax - Syntax Tree</figcaption></figure><p>Have you noticed that little "u" character? Yep, this is <code>VariableDesignationSyntax</code>.</p><h3 id="queryclausesyntax">QueryClauseSyntax</h3><p>I don't use query clauses at all in my code and prefer to use LINQ. But it's there, and C# team is carefully carrying it from release to release. I suppose it's there to introduce SQL-like queries. I won't describe each group in these categories. Feel free to explore it on your own.</p><!--kg-card-begin: markdown--><blockquote>
<p>You can read more about it here: <a href="https://docs.microsoft.com/en-us/dotnet/csharp/linq/query-expression-basics">Query expression basics (LINQ in C#) | Microsoft Docs</a></p>
</blockquote>
<!--kg-card-end: markdown--><p>Here is an example from the Microsoft Docs (the link above) to continue the flow:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-59.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>QueryClauseSyntax - Code Snippet</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-60.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>QueryClauseSyntax - Inheritance Hierarchy</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-61.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>SelectOrGroupClauseSyntax - Inheritance Hierarchy</figcaption></figure><h3 id="argumentlistsyntax-argumentsyntax-parameterlistsyntax-and-parametersyntax">ArgumentListSyntax, ArgumentSyntax, ParameterListSyntax and ParameterSyntax</h3><p>Those ones are closely related, though they do not share a base type. Those are also closely related to the following direct children of CSharpSyntaxTree:</p><p>Sealed, Parameters Related:</p><ol><li>TypeParameterListSyntax</li><li>TypeParameterSyntax</li><li>FunctionPointerParameterListSyntax</li><li>TypeParameterConstraintClauseSyntax</li><li>CrefParameterSyntax</li></ol><p>Sealed Arguments Releated:</p><ol><li>AttributeArgumentListSyntax</li><li>AttributeArgumentSyntax</li><li>TypeArgumentListSyntax</li><li>ArgumentSyntax</li><li>OmittedTypeArgumentSyntax</li></ol><p><br>This group is responsible for passing arguments to invocations. In other words, it answers the question "What should be passed to a function call as an argument?"</p><!--kg-card-begin: markdown--><blockquote>
<p>Notice: <code>ArgumentSyntax</code> does not have a base class, and it is a direct child of <code>CSharpSyntaxNode</code>. But <code>ParameterSyntax</code> has <code>BaseParameterSyntax</code>.</p>
</blockquote>
<!--kg-card-end: markdown--><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-62.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>BaseArgumentListSyntax - Inheritance Hierarchy</figcaption></figure><p>And very closely related to the arguments group is parameter group. It is responsible for defining parameters of functions. In other words, it answers the question "What a particular function can accept?" You can also think about it as about a "contract" between you and a function, meaning when you agree to a certain contract, you should comply with it when making calls to that function.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-63.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>BaseParameterListSyntax and BaseParameterSyntax - Inheritance Hierarchy</figcaption></figure><p>Here is an example that uses both an argument and a parameter in a single expression:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-64.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>ParameterSyntax and ArgumentSyntax - Syntax Tree</figcaption></figure><p>I hope, you can clearly see the difference between arguments and parameters here:</p><ol><li>An argument is something that you passes during a method call (or while accessing something). In this example, you can see that we pass <code>SimpleLambdaExpression</code> as an argument to <code>Where</code> function invocation.</li><li>A parameter is something you define on the callee side (like a variable declaration). In this example, you can see that "x" is a parameter of the <code>SimpleLambdaExpression</code>. Also, in the example above you can see that <code>ArgumentSyntax</code> is contained inside <code>ArgumentListSyntax</code>. Similarly, parameters are contained in the <code>ParameterListSyntax</code>.</li></ol><h3 id="typeparameterlist-and-typeparameter">TypeParameterList and TypeParameter</h3><p>Those are the base part of the generic types in C#. They allow you to specify a generic type for any type or method.</p><!--kg-card-begin: markdown--><blockquote>
<p>Notice: they are sealed, non-abstract and direct children of <code>CSharpSyntaxNode</code>.</p>
</blockquote>
<!--kg-card-end: markdown--><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-65.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>TypeParameterSyntax and TypeParameterListSyntax - Inheritance Hierarchy</figcaption></figure><p>Let's see an example:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-66.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>TypeParameterSyntax and TypeParameterListSyntax - Code Snippet</figcaption></figure><p>and the syntax tree for the class:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-67.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>TypeParameterSyntax and TypeParameterListSyntax - Syntax Tree (1)</figcaption></figure><p>and the syntax tree for a generic method parameter:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-68.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>TypeParameterSyntax and TypeParameterListSyntax - Syntax Tree (2)</figcaption></figure><p>You may notice that <code>TypeParameter</code> is nested inside <code>TypeParameterList</code>. We need <code>TypeParameterList</code> because C# allows specifying multiple generic parameters for a type.</p><h3 id="baselistsyntax-basetypesyntax-and-primaryconstructorbasetypesyntax">BaseListSyntax, BaseTypeSyntax and PrimaryConstructorBaseTypeSyntax</h3><p><br><code>BaseListSyntax</code> is the list of all base types for a specified type. It also a parent container for <code>BaseTypeSyntax</code>. Those are the core of C# inheritance. They allow us to specifies base types for a type we define.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-69.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>BaseTypeSyntax - Inheritance Hierarchy</figcaption></figure><p>Here we can see that the ClassMemberStateBase class is inherited from another <code>LocalContextState</code> class:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-70.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>BaseTypeSyntax - Code Snippet</figcaption></figure><p>and here is how it's defined in the syntax tree:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-71.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>BaseTypeSyntax - Syntax Tree</figcaption></figure><p>Now, have you wondered what is PrimaryConstructorBaseTypeSyntax? It is also related to inheritance in C#. They apply only to C# 9.0, where records were introduced:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-72.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>PrimaryConstructorBaseTypeSyntax - Code Snippet</figcaption></figure><p>and it's syntax tree:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-73.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>PrimaryConstructorBaseTypeSyntax - Syntax Tree</figcaption></figure><p>But what is even more interesting is that there is no separate syntax for a "primary constructor" in RoslynAPI, despite that you can specify <code>PrimaryConstructorBaseTypeSyntax</code>. Let's see a syntax tree for the R1 type:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-74.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>Primary Constructor - Syntax Tree</figcaption></figure><!--kg-card-begin: markdown--><blockquote>
<p>Notice, the record does not have a &quot;PrimaryConstructor&quot; though RoslynAPI has <code>PrimaryConstructorBaseTypeSyntax</code>. Even Mads Torgersen mentioned the &quot;primary constructor&quot; in his blog post <a href="https://devblogs.microsoft.com/dotnet/c-9-0-on-the-record/">C# 9.0 on the record | .NET Blog</a> in the comment:<br>
<img src="https://sapehin.com/content/images/2021/01/Image--2-.png" alt="C# via RoslynAPI - The Big Picture"></p>
</blockquote>
<!--kg-card-end: markdown--><p>I suppose, reusing <code>ParameterListSyntax</code> in <code>RecordDeclarationSyntax</code> just saved a couple of story points to the Roslyn team.</p><h3 id="switchlabelsyntax">SwitchLabelSyntax</h3><p>Those nodes represent a labels in C# language:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-76.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>SwitchLabelSyntax - Inheritance Hierarchy</figcaption></figure><p>As you can see, there are three of them, each one specific to a context where it can be applied.</p><h3 id="directivetriviasyntax">DirectiveTriviaSyntax</h3><p>This group represents directives in C#:</p><figure class="kg-card kg-image-card"><img src="https://sapehin.com/content/images/2021/01/Image-77.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"></figure><h3 id="structuredtriviasyntax-and-branchingdirectivetriviasyntax">StructuredTriviaSyntax and BranchingDirectiveTriviaSyntax</h3><p>This groups represent different trivia constructs:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-78.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>StructuredTriviaSyntax - Inheritance Hierarchy</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-79.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>BranchingDirectiveTriviaSyntax - Inheritance Hierarchy</figcaption></figure><h3 id="crefsyntax-xmlnodesyntax-and-xmlattributesyntax">CrefSyntax, XmlNodeSyntax and XmlAttributeSyntax</h3><p>Those are primarily used in XML comments and some of them can reference actual classes:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-82.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>CRefSyntax - Inheritance Hierarchy</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-83.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>BaseCRefParameterListSyntax - Inheritance Hierarchy</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-84.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>XmlNodeSyntax - Inheritance Hierarchy</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-85.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>XmlAttributeSyntax - Inheritance Hierarchy</figcaption></figure><h3 id="direct-children-of-csharpsyntaxnode">Direct Children of CSharpSyntaxNode</h3><p>You've already seen a lot of nodes from this group. It contains different nodes that belong to other syntax groups but have no explicit relationships to those groups. Earlier, we seen that <code>IfStatementSyntax</code> has <code>ElseClauseSyntax</code> from this list. Also, we can find independent syntax nodes here. One of them is <code>CompilationUnitSyntax</code>. It is a node-container for all C# code that we define in a <code>.cs</code> file. I won't give additional examples for those, because this article has already become pretty long.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2021/01/Image-86.png" class="kg-image" alt="C# via RoslynAPI - The Big Picture"><figcaption>Direct Children of CSharpSyntaxNode - Inheritance Hierarchy</figcaption></figure><h2 id="conclusion">Conclusion</h2><p>In this article, we've seen every single public syntax node that available in RolsynAPI. You may have noticed that there were not a single syntax node related to asynchronous programming (except <code>AwaitExpressionSyntax</code>) nor multi-threading (except <code>lock</code> statement). Have you wonder how is it even possible to see everything that possible in C# but not seeing any of those constructs (e.g. <code>async/await</code>)? It's because a programming language is just the way to describe things that a compiler can understand. When you invoke a function, all you have to know is the name of a function, arguments (a calling convention) and how to interpret the result. And it doesn't matter whether it's your personally crafted method or a System.Threading.Thread.Start - it's just a name that a compiler can understand. That is why RoslynAPI doesn't need some kind of "AsyncFunctionSyntaxNode".</p><p>Last but not least - RoslynAPI provides a consistent source of truth for naming C# language constructs. You may miss something while reading a textual language specification, but you can't miss a class like CSharpSyntaxNode. And you may be sure it is correct because (in case of RoslynAPI) it can parse any valid (and even not valid) C# source code.</p><p>I hope this article gave you a fresh perspective on C# language as well as a feeling of completeness. DotNet/C#/RoslynAPI teams did a great job of crafting the language till it reached its current state. People, that started their journey from C# v1.0, remember countless changes and improvements that were introduced during all those years. Nowadays, we can easily manipulate any C# source code by using RoslynAPI. But it was not always possible. So, I also hope, you'll appreciate RoslynAPI a bit more too.</p><p>P.S.: If you have any questions or suggestions feel free to contact me on <a href="https://twitter.com/psapehin">twitter</a>.</p>]]></content:encoded></item><item><title><![CDATA[C# RoslynAPI SyntaxTree - Variables Are Not Variables (Gotchas)]]></title><description><![CDATA[Why are variables not just variables in RoslynAPI? A gentle introduction to the world of the latest C# compiler platform.]]></description><link>https://sapehin.com/blog/csharp-roslynapi-syntaxtree-variables-gotchas/</link><guid isPermaLink="false">630254459a9a3c000141f4b1</guid><category><![CDATA[C#]]></category><category><![CDATA[RoslynAPI]]></category><category><![CDATA[DotNet]]></category><dc:creator><![CDATA[Pavel Sapehin]]></dc:creator><pubDate>Mon, 09 Nov 2020 13:45:40 GMT</pubDate><media:content url="https://sapehin.com/content/images/2020/11/roslyn-variables-are-not-variables.jpg" medium="image"/><content:encoded><![CDATA[<h2 id="introduction">Introduction</h2><img src="https://sapehin.com/content/images/2020/11/roslyn-variables-are-not-variables.jpg" alt="C# RoslynAPI SyntaxTree - Variables Are Not Variables (Gotchas)"><p>Have you ever wondered what is variable when you write your C# code in terms of syntax? Are you familiar with Roslyn API? If you are planning to create any developer tool for other C# developers, write Visual Studio Extension, or .NET Analyzer, then it's very likely you'll use Roslyn API. The goal of this article isn't cover all basic concepts but to gently introduce you to the world of the latest C# compiler platform.</p><p>Below are some questions that can help to verify your assumptions. If you know the answers, feel free to skip the article:</p><ol><li>Do you know that <strong>event</strong> in C# is actually both a <strong>field</strong> and a <strong>variable </strong>from the syntax point of view?</li><li>Do you know that to get a local method's variable, you should NOT search for <strong>VariableDeclarationSyntax</strong>?</li><li>Do you know the difference between VariableDeclarationSyntax and VariableDeclaratorSyntax?</li><li>Are method arguments accept variables from the syntax point of view?</li></ol><h2 id="prerequisites-and-tools">Prerequisites and tools</h2><p><br>To demonstrate the concept of C# variables from the syntax point of view, I'll be using the "Roslyn Syntax Visualizer" tool for Visual Studio. You can find more about it <a href="https://docs.microsoft.com/en-us/dotnet/csharp/roslyn-sdk/syntax-visualizer?tabs=csharp">here</a>. It's a tool to browse the syntax tree of the active file in a project.</p><p>To get started with understanding SyntaxTrees, semantics, and the difference between both, I recommend reading the official documentation:</p><ol><li><a href="https://docs.microsoft.com/en-us/dotnet/csharp/roslyn-sdk/work-with-syntax">Work with syntax | Microsoft Docs</a></li><li><a href="https://docs.microsoft.com/en-us/dotnet/csharp/roslyn-sdk/work-with-semantics">Work with semantics | Microsoft Docs</a></li></ol><p>A syntax tree is a tree-like structure created by a compiler during compilation. It represents your code in terms of the SyntaxNode of different kinds, like classes, structs, variables, etc. A root node of the syntax tree is "CompilationUnitSyntax," which represents a file. So, your projects consist of multiple SyntaxTrees, each one representing a CompilationUnitSyntax/File. But it's not always true because you can create an entire program without having any files using RoslynAPI. Anyway, it should be enough to get to the point.</p><h2 id="variables-are-not-variables">Variables are Not Variables</h2><h3 id="exploring-the-fields">Exploring the fields</h3><p>To start, let's consider the following class (you can skim it for now and return to it as you need):</p><!--kg-card-begin: html--><script src="https://gist.github.com/psxvoid/65d8e0cf82af7dbe63c3d79419da1f25.js"></script><!--kg-card-end: html--><p>Here we can see two private fields, defined in a single line in a class:</p><!--kg-card-begin: markdown--><pre><code class="language-cs">private int age, height;
</code></pre>
<!--kg-card-end: markdown--><p>Can you guess what kind of a syntax node it represents? Something related to variables, right? Not exactly.</p><p>A field in the C# syntax world is represented by the FieldDeclarationSyntax node. Below is the output of "Roslyn Code Visualizer" for this line of code:</p><figure class="kg-card kg-image-card"><img src="https://sapehin.com/content/images/2020/11/Image--290-.png" class="kg-image" alt="C# RoslynAPI SyntaxTree - Variables Are Not Variables (Gotchas)"></figure><p>You can see that it's not a variable. But it has child VariableDeclarationSyntax and VariableDeclaratorSyntax. But does it contain any names? Let's take a look at the properties of this node:</p><figure class="kg-card kg-image-card"><img src="https://sapehin.com/content/images/2020/11/Image--291-.png" class="kg-image" alt="C# RoslynAPI SyntaxTree - Variables Are Not Variables (Gotchas)"></figure><p>It doesn't seem so. Does the variable declaration contain it?</p><figure class="kg-card kg-image-card"><img src="https://sapehin.com/content/images/2020/11/Image--292-.png" class="kg-image" alt="C# RoslynAPI SyntaxTree - Variables Are Not Variables (Gotchas)"></figure><p>Another miss. Does VariableDeclaratorSyntax contain it? Almost. It contains IdentifierSyntax, which contains an actual name of the first field:</p><figure class="kg-card kg-image-card"><img src="https://sapehin.com/content/images/2020/11/Image--293-.png" class="kg-image" alt="C# RoslynAPI SyntaxTree - Variables Are Not Variables (Gotchas)"></figure><p>and another one of the second field:</p><figure class="kg-card kg-image-card"><img src="https://sapehin.com/content/images/2020/11/Image--294-.png" class="kg-image" alt="C# RoslynAPI SyntaxTree - Variables Are Not Variables (Gotchas)"></figure><h3 id="exploring-the-events">Exploring the events</h3><p>What are the events from the syntax point of view? Are those variables?</p><!--kg-card-begin: markdown--><pre><code class="language-cs">public event EventHandler&lt;EventArgs&gt; HappinessMaxout, SaddnessMaxout;
</code></pre>
<!--kg-card-end: markdown--><p>Let's take a look at the syntax tree. Here is EventFieldDeclarationSyntax:</p><figure class="kg-card kg-image-card"><img src="https://sapehin.com/content/images/2020/11/Image--295-.png" class="kg-image" alt="C# RoslynAPI SyntaxTree - Variables Are Not Variables (Gotchas)"></figure><p>Notice, it also contains VariableDeclarationSyntax node, containing multiple VariableDeclarator nodes.</p><p>So, answering question #1 at the top of the article - yes, from the syntax point of view, events are both fields and variables.</p><h3 id="exploring-local-variables">Exploring local variables</h3><p>What are the local variables from the syntax point of view? Let's take a look at this line of code:</p><!--kg-card-begin: markdown--><pre><code class="language-cs">int mutation1, mutation2;
</code></pre>
<!--kg-card-end: markdown--><p>It also contains VariableDeclarationSyntax but it is LocalDeclarationSyntax:</p><figure class="kg-card kg-image-card"><img src="https://sapehin.com/content/images/2020/11/Image--296-.png" class="kg-image" alt="C# RoslynAPI SyntaxTree - Variables Are Not Variables (Gotchas)"></figure><h3 id="fields-events-methods-exploration-summary">Fields, Events, Methods Exploration Summary</h3><p>What does all this mean? First of all, in terms of syntax, the term VariableDeclarationSyntax is ambiguous and can be part of:</p><ol><li>Fields</li><li>Events</li><li>Method's/Expression Local Variables</li></ol><p>Secondly, a field, event, and local variables in terms of the syntax are <strong>variables.</strong> But to be more precise, they contain VariableDeclarationSyntax and VariableDeclaratorSyntax</p><h3 id="what-is-variabledeclaratorsyntax-and-why-do-we-need-it">What is VariableDeclaratorSyntax and why do we need it?</h3><p>You should already understand the difference between VariableDeclarationSyntax and VariableDeclaratorSyntax.</p><p>VariableDeclarationSyntax allows to define multiple variables on a single line:</p><!--kg-card-begin: markdown--><pre><code class="language-cs">int a, b;
</code></pre>
<!--kg-card-end: markdown--><p>or on multiple lines:</p><!--kg-card-begin: markdown--><pre><code class="language-cs">int a,
    b;
</code></pre>
<!--kg-card-end: markdown--><p>while each variable inside it is represented by VariableDeclaratorSyntax.</p><p>When we want to access the first variable name, we can't do it by just having VariableDeclarationSyntax, because it doesn't contain an IdentifierSyntax node (that contains the actual variable name).</p><p>But VariableDeclaratorSyntax does contain IdentifierSyntax node with name. Here is code to demonstrate the concept:</p><!--kg-card-begin: markdown--><pre><code class="language-cs">variableDeclarationNode.Variables[0].Identifier.TextValue == &quot;a&quot;; // true
variableDeclarationNode.Variables[1].Identifier.TextValue == &quot;b&quot;; // true
</code></pre>
<!--kg-card-end: markdown--><p>Where:</p><ul><li>Variable[0] = VariableDeclaratorSyntax</li><li>Identifer = IdentifierSyntax</li><li>TextValue = the actual name of a variable</li></ul><p>Hopefully, it answers questions #2 and #3 at the top of the article.</p><h3 id="parametersyntax-vs-argumentsyntax">ParameterSyntax vs ArgumentSyntax</h3><p><br>We often use the words "parameter" and "argument" as synonyms. We can also say that we pass a variable to a method. But in RoslynAPI, those are different.</p><p>ParameterSyntax is used inside MethodDeclarationSyntax:</p><figure class="kg-card kg-image-card"><img src="https://sapehin.com/content/images/2020/11/Image--297-.png" class="kg-image" alt="C# RoslynAPI SyntaxTree - Variables Are Not Variables (Gotchas)"></figure><p>ArgumentSyntax is used inside InvocationExpressionSyntax (when calling methods):</p><figure class="kg-card kg-image-card"><img src="https://sapehin.com/content/images/2020/11/Image--298-.png" class="kg-image" alt="C# RoslynAPI SyntaxTree - Variables Are Not Variables (Gotchas)"></figure><p>and none of those contains VariableDeclarationSyntax, nor VariableDeclaratorSyntax.</p><p>So, answering question #4, we can call them "Variables", but can't say for sure that "a method can accept variables" in terms of C# syntax.</p><h2 id="summary">Summary</h2><p>And that's it! To learn those concepts further along with other Roslyn APIs, I recommend writing a simple console application and exploring it with the "Roslyn Syntax Visualizer" extension in Visual Studio.</p><p>Also, to find a real-world example, you can check out my <a href="https://github.com/psxvoid/dngrep">dngrep</a> repo (.NET Global Tool) on GitHub. Thanks for reading!</p>]]></content:encoded></item><item><title><![CDATA[Better than Docker on WSL2]]></title><description><![CDATA[Have you ever wondered what is the most productive way to use Docker on Windows? This article explains why there may be even better than the official one.]]></description><link>https://sapehin.com/blog/better-than-docker-on-wsl/</link><guid isPermaLink="false">630254459a9a3c000141f4b0</guid><category><![CDATA[WSL]]></category><category><![CDATA[Docker]]></category><category><![CDATA[RaspberryPi]]></category><dc:creator><![CDATA[Pavel Sapehin]]></dc:creator><pubDate>Thu, 24 Sep 2020 04:21:34 GMT</pubDate><media:content url="https://sapehin.com/content/images/2020/09/docker-on-pi.png" medium="image"/><content:encoded><![CDATA[<h3 id="introduction">Introduction</h3><img src="https://sapehin.com/content/images/2020/09/docker-on-pi.png" alt="Better than Docker on WSL2"><p>Currently, there is a lot of hype around WSL and WSL 2 on Windows. It allows us to run almost any Linux application, including Docker. It even allows us to develop applications for Linux in VS Code using the "Remote - WSL" extension. But the goal of this article isn't to praise WSL but to show that there is a better way to use Docker on Windows.</p><p>Let's start from the beginning. Docker allows you to build and run Linux Containers (Windows too but we will not talk about it right now) in a very straightforward way - all you need is to put some build instruction in a docker-file, build the image using the "docker build" command and run the container using "docker run." But how does docker run a container on a Linux/Windows machine?</p><h3 id="the-docker-on-linux-way">"The Docker on Linux" Way</h3><p>When you use Docker on Linux, it simply uses native kernel features, like cgroups, to run the code inside the container. As the result, it's lightning-fast because it doesn't use any emulation (e.g. in contrast to Virtual Box).</p><h3 id="the-docker-on-windows-way-part-1-hyper-v">"The Docker on Windows" Way, Part 1 - Hyper-V</h3><p>When you use Docker Windows and it doesn't have WSL2 installed, the default backed is Hyper-V. After the installation, Docker asks you to activate it and reboot your machine. It is doing this because it uses Hyper-V to run a small virtual machine on it. Because there is no magic - you can't run Linux executables natively on Windows. Interestingly, If you use Virtual Box on the same machine then it may become slower or stop working at all. Because what happens when you activate Hyper-V - your copy of Windows became some kind of a Virtual Machine (the host OS) that also runs on top of the Hyper-V virtualization layer. And when your run Virtual Box it's somewhat similar to starting a VM inside another VM. It's not completely similar, because the latest versions of Virtual Box can use Hyper-V as their emulation backend. But be aware that in order to use it your machine should support Hardware Virtualization.</p><h3 id="the-docker-on-windows-way-part-2-wsl2">"The Docker on Windows Way", Part 2 - WSL2</h3><p>The first time I heard about the possibility of running Docker on WSL2 I was happy as a child. Running without Hyper-V with performance, batter than the performance of WSL1, isn't it cool? Well, it would be cool if WSL2 didn't rely on virtualization technology. It requires you to enable the "Virtual Machine Platform" feature of the latest builds of Windows 10. And as far as I can understand it is similar to running under Hyper-V. So, no benefits here. Almost. But it may change in the future. For now, it seems more like a marketing trick. For now, it even has a bug that prevents docker from reclaiming the memory from WSL it. One day while I was working building images with Docker on WSL2 I noticed that the process was using more than 10BG of memory! But this feature is still in beta and hopefully become better over the years. So, how can you enable it? First of all, install and WSL2 as described in the official documentation <a href="https://docs.microsoft.com/en-us/windows/wsl/install-win10">here</a>. Then tick the following checkbox in the docker settings:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2020/09/Image--2-.png" class="kg-image" alt="Better than Docker on WSL2"><figcaption>WSL2 docker option</figcaption></figure><h3 id="the-docker-on-windows-way-part-3-wsl1">"The Docker on Windows" Way, Part 3 - WSL1</h3><p>There is also an option to run Docker on WSL1 using an <strong>older </strong>version (it won't work with the latest ones). All you have to do is to install that specific version inside any WSL1 distribution and start to use it. But then you became limited to that version, and when you run a container, it will always use around 30% of your CPU, even if the container is doing nothing. So, you can try it or even use it, especially if you have a powerful desktop PC. But it's certainly not the best way to use Docker on your laptop due to increased power consumption and overheating.</p><h3 id="the-docker-on-windows-way-part-4-virtual-box">"The Docker on Windows" Way, Part 4 - Virtual Box</h3><p>This way is primarily designed for those who don't have the hardware virtualization feature on their PC. All you have to do is to install Virtual Box on and then install a specific version of Docker called "Docker Toolbox." Docker Toolbox also uses a small virtual machine but instead of running it on Hyper-V (which requires the virtualization) uses Virtual Box. It has its limitations, but I love it because it provides some benefits even when you do have the hardware virtualization support. Why? Because, because then you can disable Hyper-V and all other Windows Virtualization Features. It will allow you to run Virtual Box at full speed and also make your system a bit more responsive. You can read more about it in the official Hyper-V documentation in the "limitations" section <a href="https://docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/about/#limitations">here</a>.</p><h3 id="the-docker-on-windows-the-better-way">"The Docker on Windows", The Better Way</h3><p>This way is a bit unusual and may not be suited for everyone, but I'm suggesting you reading to the end because there is a good chance you'll love it as much as I do.</p><p>All options mentioned above can be pretty good, and some of them are official ways of running Docker on Windows. But what all those ways require you to modify your system, and sometimes it may be undesirable. For example, when you use Hyper-V it may make your system a bit unstable as described above. Also, when your run Docker Desktop, let's say, on your laptop, it uses its resources during builds and for running containers. Sometimes it can slow you down. Needless to say, that when you build containers locally, it may use quite a lot of system disk space, and you should keep an eye on the size of the local images because it can grow pretty quickly. Mine was around 100GB one day, and it took a couple of hours to understand why and how to clean it up. So, what is the better way?</p><p>It's "Docker on Raspberry Pi" way. Recently, I bought a Pi4, connected it to an external 2TB drive with USB 3, and configured a samba (Windows Share) service to expose it to the local network at home. I was tinkering with it, and, accidentally, decided to try to run a Minecraft server on it. I quickly build an image on my windows laptop with Docker Desktop on WSL2, pushed it to the Docker Hub, and tried to run it on the Raspberry Pi. But I quickly realized that it was failing with the following error:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2020/09/image-2.png" class="kg-image" alt="Better than Docker on WSL2"><figcaption>exec format error</figcaption></figure><p>As it turned out, Docker builds images with the same processor architecture under which it's being built. In the case of "Docker on Windows," the resulting architecture of an image is x86_64. In the case of Raspberry Pi 4 and Ubuntu (64 bit), it's aarch64. We can verify it by running the "uname -m" command on a Raspberry Pi:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2020/09/image-1.png" class="kg-image" alt="Better than Docker on WSL2"><figcaption>processor architecture of the raspberry pi 4</figcaption></figure><p>The next step was to build the image on Raspberry Pi. Only then I realized that I should build images on the Raspberry Pi itself. I didn't use any git repositories for this quick project; and because my samba server had been already configured on my Windows laptop, all I have to do was to copy project files with the Dockerfile to a folder on the connected Network Drive (samba share).</p><p>So, I build the image once again on the Raspberry Pi. It succeeded, but then I've got a similar error. However, the error occurred not during a container startup, but on during Minecraft server startup:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2020/09/Screenshot-2020-09-21-150643.jpg" class="kg-image" alt="Better than Docker on WSL2"><figcaption>bedrock_server - exec format error</figcaption></figure><p>Why a similar error? Didn't I build it with the required architecture? To completely understand this error, you should know that a Minecraft Bedrock Edition Server is only available for Linux with x86_64 architecture (64 bit). And I was downloading it during the image build using wget. The resulting architecture of the image was aarch64, but I was trying to run x86_64 executable on it. It's somewhat similar to trying to run a Visual Studio executable from Windows on the phone. The only way I found to make it work is to use an emulator. And so, my journey with Docker on Raspberry Pi and QEMU began. But I won't describe it here. The only thing I mention about it here is that I'd got it working, but it was to slow to use even for a single player. Because the goal of this article is to show you the beauty of working with "Docker on Raspberry Pi." Later that day, I opened the Visual Studio Code in the shared folder on the Raspberry Pi. And I was a similar (or even better) experience of running Visual Studio Code with the "Remote - WSL" extension. But because I was using Docker on a Raspberry Pi and connected to it via ssh, my laptop was using 0% CPUs during docker builds, its SSD was completely clean from temporary image layers, and all containers were running outside the main machine allowing it to be as responsive as possible.</p><h3 id="setting-up-docker-on-raspberry-pi">Setting Up "Docker on Raspberry Pi"</h3><p>Now, lets set it up from the beginning. First of all, we have to enable cgroups (it wasn't enabled by default on Ubuntu 20, x64 for me) by editing "cmdline.txt". We can open it in vim with:</p><!--kg-card-begin: markdown--><pre><code class="language-bash">sudo vim /boot/firmware/cmdline.txt
</code></pre>
<!--kg-card-end: markdown--><p>Next, we should <strong>append </strong>the following configuration to the first line (e.g. by pressing Shift+A and entering:</p><!--kg-card-begin: markdown--><pre><code class="language-bash">cgroup_enable=cpuset cgroup_enable=memory cgroup_memory=1
</code></pre>
<!--kg-card-end: markdown--><p>Save it and quit from vim by pressing :wq&lt;Enter&gt;. The next step is to reboot the Raspberry Pi to apply the changes:</p><!--kg-card-begin: markdown--><pre><code class="language-bash">sudo reboot
</code></pre>
<!--kg-card-end: markdown--><p>Now, we are ready to install docker:</p><!--kg-card-begin: markdown--><pre><code class="language-bash">sudo apt update
sudo apt upgrade
sudo snap refresh
sudo snap install docker
</code></pre>
<!--kg-card-end: markdown--><p>We can verify that it's correctly installed by running:</p><!--kg-card-begin: markdown--><pre><code class="language-bash">sudo docker run hello-world
</code></pre>
<!--kg-card-end: markdown--><p>The output should look something like this:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2020/09/image-3.png" class="kg-image" alt="Better than Docker on WSL2"><figcaption>docker hello-world</figcaption></figure><p>The next step is to enable samba service to access project files easily on a Windows machine:</p><!--kg-card-begin: markdown--><pre><code class="language-bash">sudo apt install samba
</code></pre>
<!--kg-card-end: markdown--><p>Let's say, we would like out code to live in ~/code (e.g. /home/ubuntu/code):</p><!--kg-card-begin: markdown--><pre><code class="language-bash">mkdir ~/code
</code></pre>
<!--kg-card-end: markdown--><p>In order to configure samba server on the Raspberry Pi and share ~/code folder we have to edit smb.conf file:</p><!--kg-card-begin: markdown--><pre><code class="language-bash">sudo vim /etc/samba/smb.conf
</code></pre>
<!--kg-card-end: markdown--><p>First of all, modify the "global" section. Mine looks like this:</p><figure class="kg-card kg-image-card"><img src="https://sapehin.com/content/images/2020/09/image-4.png" class="kg-image" alt="Better than Docker on WSL2"></figure><p>and create a new share by appending it's configuration at the end of a file. It may look like this:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2020/09/image-6.png" class="kg-image" alt="Better than Docker on WSL2"><figcaption>share configuration</figcaption></figure><p>Notice, here we configured ubuntu as our user. But we can specify any user name here, not just ubuntu. Samba users are not the same as system users. For simplicity, we can even enable public access without a password by setting "public = yes." Save it and quit from vim. Now we should add our ubuntu-samba user and generate a password for it:</p><!--kg-card-begin: markdown--><pre><code class="language-bash">sudo smbpasswd -a ubuntu
</code></pre>
<!--kg-card-end: markdown--><p>To apply the changes, we should restart the samba service:</p><!--kg-card-begin: markdown--><pre><code class="language-bash">sudo service smbd restart
</code></pre>
<!--kg-card-end: markdown--><p>To verify that our service is working fine we can run the following command:</p><!--kg-card-begin: markdown--><pre><code class="language-bash">sudo systemctl status smbd
</code></pre>
<!--kg-card-end: markdown--><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2020/09/image-7.png" class="kg-image" alt="Better than Docker on WSL2"><figcaption>sudo systemctl status smbd output</figcaption></figure><p>If it's active then we didn't mess with samba.conf and are ready to connect to the samba service from Windows. Notice, I'm assuming you are familiar with your network configuration. At this point, it would be almost essential to assign a static IP address to your Raspberry Pi on your router. I assigned 192.168.100.16 for mine. It will allow you to easily restore the network drive connection to Raspberry Pi each time your laptop is booted and connected to the local network.</p><p>All we have to do is to open the Windows Explorer and press the "Map Network Drive" button:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2020/09/Image-1.png" class="kg-image" alt="Better than Docker on WSL2"><figcaption>mapping a network drive in windows explorer, part 1</figcaption></figure><p>specify required options and press finish:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2020/09/Image--3-.png" class="kg-image" alt="Better than Docker on WSL2"><figcaption>mapping a network drive in windows explorer, part 2</figcaption></figure><p>enter credentials for the ubuntu user (the ones you've added using smbpasswd):</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2020/09/image-8.png" class="kg-image" alt="Better than Docker on WSL2"><figcaption>entering credentials for ubuntu user</figcaption></figure><p>and viola, now we can access our share from Windows as it was a regular drive:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2020/09/Image--9-.png" class="kg-image" alt="Better than Docker on WSL2"><figcaption>mounted samba share in windows explorer</figcaption></figure><p>From here we can clone any git repository using PowerShell, and then open it in Visual Studio Code. For example:</p><!--kg-card-begin: markdown--><pre><code class="language-PowerShell">git clone https://github.com/docker-library/hello-world
cd hello-world
git reset --hard 9ef4804c28679a416a445397f9b2e2b105005151
code .
</code></pre>
<!--kg-card-end: markdown--><p>To verify it's working, open hello.c file, and add/modify any text you want. For example:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2020/09/Image--7-.png" class="kg-image" alt="Better than Docker on WSL2"><figcaption>modifying hello.c</figcaption></figure><p>and remove those lines from Dockerfile.build (on the moment of writing this article those packages were unavailable on Raspberry Pi, Ubuntu 20, x64):</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2020/09/image-10.png" class="kg-image" alt="Better than Docker on WSL2"><figcaption>removing apt packages that not available on raspberry pi (ubuntu 20, x64) from the dockerfile</figcaption></figure><p>and delete all blocks that starts with "RUN set -ex" except this one:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2020/09/image-11.png" class="kg-image" alt="Better than Docker on WSL2"><figcaption>aarch64 make statement in the dockerfile</figcaption></figure><p>and change CMD line from amd64 to arm64v8:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2020/09/image-12.png" class="kg-image" alt="Better than Docker on WSL2"><figcaption>modified cmd line</figcaption></figure><p>and save the changes. Then switch to the Raspberry Pi (I'm ssh-ing to it) and run the following commands:</p><!--kg-card-begin: markdown--><pre><code class="language-bash">cd ~/code/hello-world
sudo docker build -t hello:latest -f Dockerfile.build .
sudo docker run --rm hello:latest
</code></pre>
<!--kg-card-end: markdown--><p>And here is our modified message:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2020/09/Image--8-.png" class="kg-image" alt="Better than Docker on WSL2"><figcaption>output message</figcaption></figure><p>Isn't that cool? Now, you can work on your docker projects on a Windows machine without the need to have Docker installed.</p><h3 id="summary-">Summary:<br></h3><p>So, what is the "Docker on Raspberri Pi" way about? It's about isolating your personal/professional environment from the Docker itself, quickly iterating using shared folders on a Raspberry Pi filled with your project files and git repositories, and using your preferred code editor opened on your favorite machine. And it's about freedom of choice.</p><p>Pros:</p><ol><li>It doesn't rely on Hyper-V, WSL2, or any other virtualization technology.</li><li>It doesn't take any memory and processing power on your main laptop.</li><li>You can easily bring it to your office.</li><li>No need to pay for a separate VM and compute resources.</li><li>Easy to use.</li></ol><p>Cons:</p><ol><li>Resulting images are compiled to aarch64 (arm64) architecture and can't be run on a laptop (unless you use buildx or an emulator).</li><li>Computing resources of Raspberry Pi are limited.</li><li>Some libraries may not be available on aarch64.</li><li>Relatively hard to configure.</li></ol><p>Thanks for reading and happy coding.</p>]]></content:encoded></item><item><title><![CDATA[Using Visual Studio Code to access files on Linux from Windows (WSL)]]></title><description><![CDATA[Let's say, you found a project on GitHub (or it's your own) that has to be accessed from Linux (WSL) using VS Code. This guide shows you how.]]></description><link>https://sapehin.com/blog/using-visual-studio-code-to-access-linux-files-on-wsl/</link><guid isPermaLink="false">630254459a9a3c000141f4af</guid><category><![CDATA[WSL]]></category><category><![CDATA[Visual Studio Code]]></category><category><![CDATA[Remote Development]]></category><category><![CDATA[Getting Started]]></category><dc:creator><![CDATA[Pavel Sapehin]]></dc:creator><pubDate>Tue, 21 Apr 2020 15:50:58 GMT</pubDate><media:content url="https://sapehin.com/content/images/2020/04/publishing-logo.png" medium="image"/><content:encoded><![CDATA[<img src="https://sapehin.com/content/images/2020/04/publishing-logo.png" alt="Using Visual Studio Code to access files on Linux from Windows (WSL)"><p>This article is based on the official Visual Studio Code documentation: <a href="https://code.visualstudio.com/docs/remote/wsl">Developing in WSL | VS Code Docs</a> but extends it with a practical example.</p><h2 id="introduction-and-the-context">Introduction and The Context</h2><p>Let's say, you found a project on GitHub (or it's your own) that has to be accessed from Linux (WSL) using VS Code. This guide shows you how.</p><p>For example, I'd like to use WSL for editing YAML files (kubernetes deployments) with NeoVim, and "kubectl" util for managing kubernetes clusters. The reason behind is simple - Linux provides a lot of utilities that can enhance your experience with kubectl (like xarg, awk) and you can use bash (or any other) scripting language for automating your deployments. </p><p>So, let's say we have the "deployments" folder inside the user's home directory on Ubuntu (WSL):</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2020/04/Image--204-.png" class="kg-image" alt="Using Visual Studio Code to access files on Linux from Windows (WSL)"><figcaption>The result of ls command - deployments folder inside our home folder ~/</figcaption></figure><p>In that folder, we have three YAML files (they are taken from <a href="https://kubernetes.io/docs/tasks/run-application/run-replicated-stateful-application/">Run a Replicated Stateful Application - MySQL | kubernetes.io</a> example):</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2020/04/Image--206-.png" class="kg-image" alt="Using Visual Studio Code to access files on Linux from Windows (WSL)"><figcaption>The content of the ~/deployments folder</figcaption></figure><p>So, the goal is to access those files in VS Code, make a change to one of them and see the diff for the change.</p><h2 id="prerequisites">Prerequisites</h2><p>To achieve what we want some prerequisites must be satisfied - those should be already installed and configured on your Windows OS:</p><ol><li>Visual Studio Code (VS Code)</li><li>Windows Subsystem For Linux (WSL)</li></ol><h2 id="overview">Overview</h2><p>Here are the steps needed to access Linux folders <strong>outside </strong>WSL:</p><ol><li>Install <a href="https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.vscode-remote-extensionpack">Remote Development</a> extension for VS Code</li><li>In VS Code, Press Ctrl+Shift+P, start typing and choose "Remote-WSL: New Window"</li><li>Pick up a folder you'd like to open and press "OK"</li></ol><h2 id="practical-example">Practical Example</h2><p>Let's try to open our "~/deployments" folder. I'll skip the installation of the extension though. After pressing Ctrl+Shift+P inside VS Code and starting typing "Remote" we will see something like this:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2020/04/Image--207-.png" class="kg-image" alt="Using Visual Studio Code to access files on Linux from Windows (WSL)"><figcaption>Selecting "Remote-WSL: New Window"</figcaption></figure><p>Here we should select "Remote-WSL: New Window". After selecting, a new VS Code window will be opened and it should ask your permission for accessing the network (or may not, depending on your Windows configuration):</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2020/04/Image--208-.png" class="kg-image" alt="Using Visual Studio Code to access files on Linux from Windows (WSL)"><figcaption>VS Code New Window - Network Access Request</figcaption></figure><p>After giving access to the network, we will see a familiar VS Code welcome window:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2020/04/Image--210-.png" class="kg-image" alt="Using Visual Studio Code to access files on Linux from Windows (WSL)"><figcaption>VS Code New Window</figcaption></figure><p>Here we should open the "Explorer" panel and click "Open Folder" button (it also possible to just press "Open folder..." under the "Start" section):</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2020/04/Image--211-.png" class="kg-image" alt="Using Visual Studio Code to access files on Linux from Windows (WSL)"><figcaption>VS Code New Window - Explorer Panel</figcaption></figure><p>After that you'll see a Drop-down menu with a list of folders inside your home folder on WSL:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2020/04/Image--212-.png" class="kg-image" alt="Using Visual Studio Code to access files on Linux from Windows (WSL)"><figcaption>VS Code Open Folder Drop-down</figcaption></figure><p>Then start typing a folder you'd like to open (in our case it's "~/deployments") and select it from the list:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2020/04/Image--213-.png" class="kg-image" alt="Using Visual Studio Code to access files on Linux from Windows (WSL)"><figcaption>VS Code Open Folder Drop-down - Selection</figcaption></figure><p>You'll see it populate the line with the requested path. The last step is to press the "OK" button:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2020/04/Image--214-.png" class="kg-image" alt="Using Visual Studio Code to access files on Linux from Windows (WSL)"><figcaption>VS Code Open Folder Drop-down - After Selection</figcaption></figure><p>And that's it! Now, you'll see all WSL files from the "deployments" folder in VS Code "Explorer" window as if they were opened in Windows:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2020/04/Image--215-.png" class="kg-image" alt="Using Visual Studio Code to access files on Linux from Windows (WSL)"><figcaption>VS Code - WSL Files in the Explorer Panel</figcaption></figure><p>From here you could do pretty anything you could do with a project inside a Windows folder: open command prompt and run commands, use source control, debug, etc. Let's finish this example by making a change into one file and see that "diff" view is working as expected:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sapehin.com/content/images/2020/04/Image--216-.png" class="kg-image" alt="Using Visual Studio Code to access files on Linux from Windows (WSL)"><figcaption>VS Code - Diff View</figcaption></figure><h2 id="conclusion-">Conclusion:</h2><p>VS Code and the "WSL Remote Development" plugin are powerful tools that can greatly improve your coding productivity and support complex development scenarios by allowing you to work with Linux files on WSL as if they were a part of a Windows file system. It abstracts all implementation details and allows you to focus on what matters.</p><p>Side Note: Also, be aware that the "Remote Extension" is not limited to working with files on WSL. For example, it can also attach to kubernetes containers. Check out the <a href="https://code.visualstudio.com/updates/v1_44#_remote-development">Visual Studio Code Change Log v1.44: Remote Development</a> and the extension's page for more use case scenarios. Happy coding!</p>]]></content:encoded></item></channel></rss>