C# code formatting settings in VS Code and OmniSharp

Β· 789 words Β· 4 minutes to read

I quite often get or see questions about configuring C# code formatting settings for Visual Studio Code.

OmniSharp (the open source Roslyn-based technology that powers C# language services) in VS Code exposes a rich set of code formatting settings which you can use to tailor and customize your C# experience.

Let’s have a look at how you can use them.

Tabs/spaces πŸ”—

First let’s tackle tabs vs spaces, because that’s probably the most important thing. A cool new feature in Visual Studio Code C# extension 1.6 (released just before Christmas) is that it can now automatically infer your “tabs vs spaces” and “tab size” settings from Visual Studio Code into OmniSharp.

This means, that configuring the following general editor settings under Preferences > UserSettings, i.e.:

{
    // The number of spaces a tab is equal to. This setting is overridden based on the file contents when `editor.detectIndentation` is on.
    "editor.tabSize": 2,

    // Insert spaces when pressing Tab. This setting is overridden based on the file contents when `editor.detectIndentation` is on.
    "editor.insertSpaces": true,
}

will be enough for VS Code C# extension to apply these settings to format C# code. You can also switch off this new OmniSharp behavior by setting omnisharp.useEditorFormattingSettings: false.

So this is great, very convenient, but what if you are interested in more advanced control over C# formatting?

Customizing OmniSharp configuration πŸ”—

Well, aside from this new feature, OmniSharp allows you to modify C# formatting options in a couple of ways.

First and foremost, it’s important to mention that OmniSharp exposes a JSON configuration file which surfaces all of the code formatting capabilities of Roslyn. The file schema is stored at JSON Schema Store here, and the default settings are shown below.

All the properties should be rather self descriptive and they give you a very deep and granular control over the appearance of your C# code.

{
    "FormattingOptions": {
            "NewLine": "\n",
            "UseTabs": false,
            "TabSize": 4,
            "IndentationSize": 4,
            "SpacingAfterMethodDeclarationName": false,
            "SpaceWithinMethodDeclarationParenthesis": false,
            "SpaceBetweenEmptyMethodDeclarationParentheses": false,
            "SpaceAfterMethodCallName": false,
            "SpaceWithinMethodCallParentheses": false,
            "SpaceBetweenEmptyMethodCallParentheses": false,
            "SpaceAfterControlFlowStatementKeyword": true,
            "SpaceWithinExpressionParentheses": false,
            "SpaceWithinCastParentheses": false,
            "SpaceWithinOtherParentheses": false,
            "SpaceAfterCast": false,
            "SpacesIgnoreAroundVariableDeclaration": false,
            "SpaceBeforeOpenSquareBracket": false,
            "SpaceBetweenEmptySquareBrackets": false,
            "SpaceWithinSquareBrackets": false,
            "SpaceAfterColonInBaseTypeDeclaration": true,
            "SpaceAfterComma": true,
            "SpaceAfterDot": false,
            "SpaceAfterSemicolonsInForStatement": true,
            "SpaceBeforeColonInBaseTypeDeclaration": true,
            "SpaceBeforeComma": false,
            "SpaceBeforeDot": false,
            "SpaceBeforeSemicolonsInForStatement": false,
            "SpacingAroundBinaryOperator": "single",
            "IndentBraces": false,
            "IndentBlock": true,
            "IndentSwitchSection": true,
            "IndentSwitchCaseSection": true,
            "LabelPositioning": "oneLess",
            "WrappingPreserveSingleLine": true,
            "WrappingKeepStatementsOnSingleLine": true,
            "NewLinesForBracesInTypes": true,
            "NewLinesForBracesInMethods": true,
            "NewLinesForBracesInProperties": true,
            "NewLinesForBracesInAccessors": true,
            "NewLinesForBracesInAnonymousMethods": true,
            "NewLinesForBracesInControlBlocks": true,
            "NewLinesForBracesInAnonymousTypes": true,
            "NewLinesForBracesInObjectCollectionArrayInitializers": true
            "NewLinesForBracesInLambdaExpressionBody": true,
            "NewLineForElse": true,
            "NewLineForCatch": true,
            "NewLineForFinally": true,
            "NewLineForMembersInObjectInit": true,
            "NewLineForMembersInAnonymousTypes": true,
            "NewLineForClausesInQuery": true
    }
}

At startup, OmniSharp obtains the configuration options using the following order of precedence (each of the subsequent configuration sources, can overwrite any of the settings set by the previous source):

  1. The built-in config.json - which is located in the OmniSharp folder inside the C# extension folder itself (for example, on a Mac that’s ~/.vscode/extensions/ms-vscode.csharp-1.6.0/bin/omnisharp.).
    If the file doesn’t exist, you can simply create it.

You could use the schema I just posted above and the config.json file to provide global C# formatting settings, however bear in mind that it will be overwritten on next extension update. Because of that, modifying this file is not recommended.

  1. Environment variables - you could pass environment variables into the OmniSharp process to control the formatting settings. However, because it’s the C# extension that starts the process on your behalf in VS Code, then this option is not really applicable for custom use at the moment.

  2. Command line arguments - formatting settings can be passed as arguments when starting OmniSharp. Similarly as in the previous point - this means you can’t really leverage this feature as a user, as it’s C# extension that controls it.

Interestingly, this is the technique used by VS Code C# extension to share VS Code editor settings with OmniSharp (as described earlier).

  1. An omnsharp.json filer located at %USERPROFILE%/.omnisharp/omnisharp.json. This works on all platforms – Windows, OS X and Linux. This is the perfect solution for addressing global formatting settings.

  2. An omnisharp.json file located in the working directory which OmniSharp has been pointed at. This is the perfect solution for addressing local formatting settings

The highest order of precedence is given to omnisharp.json located in the folder which OmniSharp server is looking at (so project folder specific).

An omnisharp.json (local or global) doesn’t need to be a full copy of config.json - it can contain only individual settings, and they will be merged into the settings provided by config.json, environment variables and command line args, and simply overwrite the matching ones.

For example, to override the default formattingOptions > SpaceAfterCast setting of (false), you should create the following omnisharp.json file in the folder of your project:

{
    "formattingOptions": {
        "SpaceAfterCast": true
    }
}

If you have any further feedback, please log an issue in the OmniSharp repo.

About


Hi! I'm Filip W., a cloud architect from ZΓΌrich πŸ‡¨πŸ‡­. I like Toronto Maple Leafs πŸ‡¨πŸ‡¦, Rancid and quantum computing. Oh, and I love the Lowlands 🏴󠁧󠁒󠁳󠁣󠁴󠁿.

You can find me on Github, on Mastodon and on Bluesky.

My Introduction to Quantum Computing with Q# and QDK book
Microsoft MVP