0

I am creating an omnisharp.json file to set my C# formatting preferences. How do I know what properties are available to set and what their default values are?

Surely there must be either a definitive, up-to-date source of this information or a way I can determine it myself, right?

Lance U. Matthews
  • 15,725
  • 6
  • 48
  • 68

2 Answers2

1

The FormattingOptions property of omnisharp.json is mapped to an instance of the OmniSharp.Options.FormattingOptions class. Now, you could take that source code and do some text manipulations on it...

  • ...to transform the property initializations in the constructor into JSON (e.g. NewLine = "\n";"NewLine": "\n",), but then you won't get any properties that aren't explicitly initialized.
  • ...to transform the property definitions into JSON (e.g. public string NewLine { get; set; }"NewLine": "",), but then you won't get the default values.

...but I think the best way is to simply instantiate that class yourself and inspect its properties. You can do this easily with PowerShell (Core).

The first thing you need to do is determine the path to the OmniSharp.Shared.dll assembly that contains the OmniSharp.Options.FormattingOptions class. Starting at your extensions installation directory (%UserProfile%\.vscode\extensions on Windows; ~/.vscode/extensions on Mac/Linux), you'll find it here...

  • .vscode
    • extensions
      • ms-dotnettools.csharp-{major}.{minor}.{patch}
        • .omnisharp
          • {major}.{minor}.{patch}
            • OmniSharp.Shared.dll

Note: The extension used to be named ms-vscode and had a directory structure like this...

  • .vscode
    • extensions
      • ms-vscode
        • csharp-{major}.{minor}.{patch}
          • .omnisharp
            • {major}.{minor}.{patch}
              • OmniSharp.Shared.dll

I have v1.23.1 of the ms-dotnettools.csharp extension installed on Windows, so my path to that assembly is C:\Users\UserName\.vscode\extensions\ms-dotnettools.csharp-1.23.1\.omnisharp\1.37.0\OmniSharp.Shared.dll.

In a PowerShell session, pass that path to a command to load the assembly...

PS> Add-Type -Path 'C:\Users\UserName\.vscode\extensions\ms-dotnettools.csharp-1.23.1\.omnisharp\1.37.0\OmniSharp.Shared.dll'

It will produce no output if it succeeds. Then you just need to instantiate a FormattingOptions instance, of which the property names and default values will be displayed to the console...

PS> New-Object -TypeName 'OmniSharp.Options.FormattingOptions'

OrganizeImports                                      : False
EnableEditorConfigSupport                            : False
NewLine                                              :

UseTabs                                              : False
TabSize                                              : 4
[snip]

You can even have it create the corresponding JSON for you...

PS> [PSCustomObject] @{ FormattingOptions = New-Object -TypeName 'OmniSharp.Options.FormattingOptions' } | ConvertTo-Json
{
  "FormattingOptions": {
    "OrganizeImports": false,
    "EnableEditorConfigSupport": false,
    "NewLine": "\n",
    "UseTabs": false,
    "TabSize": 4,
    [snip]
  }
}

...or write it directly to a default omnisharp.json file in the current directory...

PS> [PSCustomObject] @{ FormattingOptions = New-Object -TypeName 'OmniSharp.Options.FormattingOptions' } | ConvertTo-Json | Set-Content -Path 'omnisharp.json'

If PowerShell isn't feasible you could always create and reflect over the properties of a FormattingOptions instance in a little program like this...

using System;
using System.Linq;
using System.Reflection;

namespace SO60131765
{
    class Program
    {
        const string FormattingOptionsQualifiedTypeName = "OmniSharp.Options.FormattingOptions";

        static int Main(string[] args)
        {
            try
            {
                if (args == null || !args.Any() || string.IsNullOrEmpty(args[0]))
                    throw new Exception($"The path to the assembly containing the {FormattingOptionsQualifiedTypeName} is required.");
                else
                {
                    object formattingOptions = CreateFormattingOptionsFromAssembly(args[0]);

                    WriteHeader();
                    WriteProperties(formattingOptions);

                    return 0;
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"ERROR: {ex.Message}");

                return 1;
            }
        }

        static object CreateFormattingOptionsFromAssembly(string assemblyPath)
        {
            Assembly assembly;
            try
            {
                assembly = Assembly.LoadFrom(assemblyPath);
            }
            catch (Exception ex)
            {
                throw new Exception($"Assembly load failed with message \"{ex.Message}\".", ex);
            }

            object formattingOptions;
            try
            {
                formattingOptions = assembly.CreateInstance(FormattingOptionsQualifiedTypeName);
            }
            catch (Exception ex)
            {
                throw new Exception($"Instantiating type {FormattingOptionsQualifiedTypeName} failed with message \"{ex.Message}\".");
            }

            if (formattingOptions == null)
                throw new Exception($"A public type {FormattingOptionsQualifiedTypeName} was not found in the specified assembly.");

            return formattingOptions;
        }

        static void WriteHeader()
        {
            string headerText = $"Public instance properties of type {FormattingOptionsQualifiedTypeName}";

            Console.WriteLine(headerText);
            Console.WriteLine(new string('=', headerText.Length));
        }

        static void WriteProperties(object formattingOptions)
        {
            PropertyInfo[] properties = formattingOptions.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public);
            int longestPropertyNameLength = properties.Max(property => property.Name.Length);
            string format = $"{{0,{longestPropertyNameLength}}}: {{1}}";

            foreach (PropertyInfo property in properties)
            {
                object propertyValue = property.GetValue(formattingOptions);
                string propertyValueText = propertyValue == null
                    ? "<null>"
                    : propertyValue is string
                    ? $"\"{propertyValue}\""
                    : propertyValue.ToString();

                Console.WriteLine(format, property.Name, propertyValueText);
            }
        }
    }
}

...and then execute it with the path to the OmniSharp.Shared.dll assembly...

> SO60131765.exe "C:\Users\UserName\.vscode\extensions\ms-dotnettools.csharp-1.23.1\.omnisharp\1.37.0\OmniSharp.Shared.dll"
Public instance properties of type OmniSharp.Options.FormattingOptions
======================================================================
                                     OrganizeImports: False
                           EnableEditorConfigSupport: False
                                             NewLine: "
"
                                             UseTabs: False
                                             TabSize: 4
                                               [snip]

The above technique will likely work for other editors that make use of an OmniSharp-based extension; it's just a matter of finding where OmniSharp.Shared.dll is stored. Note that I am not providing the full text of a default omnisharp.json so this doesn't become another out-of-date source for copy-and-paste configuration. The idea is to dynamically query the values for your installed version of OmniSharp.

Lance U. Matthews
  • 15,725
  • 6
  • 48
  • 68
  • Nice answer and a fun exercise however, you can just view the options in the class right here: https://github.com/OmniSharp/omnisharp-roslyn/blob/master/src/OmniSharp.Shared/Options/FormattingOptions.cs – m4rkk Oct 17 '20 at 19:44
  • Er, I linked to that class in the very first sentence of this answer. – Lance U. Matthews Oct 17 '20 at 20:35
-1

Visit the source code and view the FormattingOptions.cs to see all the options. Here is the link:https://github.com/OmniSharp/omnisharp-roslyn/blob/master/src/OmniSharp.Shared/Options/FormattingOptions.cs

m4rkk
  • 511
  • 2
  • 10
  • A link to a solution is welcome, but please ensure your answer is useful without it: [add context around the link](//meta.stackexchange.com/a/8259) so your fellow users will have some idea what it is and why it’s there, then quote the most relevant part of the page you're linking to in case the target page is unavailable. [Answers that are little more than a link may be deleted.](//stackoverflow.com/help/deleted-answers) – Sabito stands with Ukraine Oct 18 '20 at 03:20