Skip to main content

C# support

Runesmith supports C# through an official plugin you install from the plugin hub, runesmith.csharp, developed in RunesmithHub/plugin-csharp. It highlights .cs and .csx files, gives completion, hover, go to definition, signature help, problems, quick fixes, rename, formatting and inlay hints from Runesmith's own C# analyzer, builds solutions and projects with dotnet build and debugs .NET projects with netcoredbg. This page covers what the analyzer does, how it finds your projects, how fast it is and what it does not do yet.

Set up​

Beyond the plugin, there is nothing to install for completion and the other language features: the analyzer is built on the C# compiler (Roslyn 5.9), ships with the plugin and runs inside Runesmith.

  1. Install the C# plugin: open Tools › Plugins, find C# in Browse and click Install, or start from its page on hub.runesmith.dev. Restart Runesmith when it offers to. When you open a C# file without the plugin, Runesmith offers it in a line over the editor, whose Install opens the plugin's page.
  2. Install the .NET SDK, or download one in File › SDKs.... The analyzer needs it to load your projects, and Build needs dotnet on the PATH or a default SDK that Runesmith installed.
  3. Open a folder with a solution or project in Runesmith and open a .cs file.

Features​

FeatureHow to use it
CompletionShows while you type, after a ., or with CtrlSpace. The selected suggestion shows its documentation.
Signature helpShows when you type ( or , in a call.
HoverRest the pointer on a symbol to see its signature and documentation.
Go to definitionF12, or Ctrl+click a symbol declared in your source.
ProblemsThe compiler's own errors and warnings, underlined in the editor and listed in the Problems panel as csharp with their code, such as CS0103.
Quick fixes and refactoringsThe light bulb shows on a line with a problem the compiler can fix, such as a missing using. AltEnter lists the fixes and the compiler's refactorings for the line or selection.
RenameF2 on a symbol declared in your source renames it in every file of the solution.
FormattingFormat Document (ShiftAltF) and Format Selection format with the compiler's formatter, indenting with the editor's tab size and spaces or tabs.
Inlay hintsThe names of the parameters that literal arguments go to, such as count: before 1, and the types of variables declared with var. Turn them off with Inlay hints (editor.inlayHints).

C# versions​

The analyzer supports every C# version up to C# 14. It respects each project's LangVersion, so a feature newer than the project's version is reported as an error, as the compiler reports it when building.

Projects​

The analyzer loads your projects in the background when you open a folder, so the editor never waits for it. It looks at the top of the open folder for a solution, and loads the first it finds:

  1. a .slnx file;
  2. else a .sln file;
  3. else every .csproj file in the folder and its subfolders, up to three levels deep, skipping folders such as bin, obj, .git and node_modules.

Loading uses MSBuild, so it needs the .NET SDK installed, as building does. The Language analyzers channel of the Output panel shows which solution or projects loaded, how long it took, and why a project failed to load. Project files are read when the folder opens; the analyzer does not watch them for changes.

A solution file below the top of the folder is not used, and projects more than three levels down are not found. Open the folder that holds the solution, or one closer to the projects.

Files outside projects​

A C# file that belongs to no loaded project, or that you open before the projects finish loading, gets a project of its own. That project uses the newest C# version, the .NET reference assemblies, and the global usings of a console app (System, System.Collections.Generic, System.IO, System.Linq, System.Net.Http, System.Threading and System.Threading.Tasks), so a lone file gets completion and problems right away. Problems that only say the files are not a complete program, such as a missing Main method, are left out.

Performance​

Completion asks the compiler once per word and filters that list as the word grows, so typing more of a word does not ask again. The analyzer also works ahead of you: after you type a separator, such as a space, ( or =, it computes the list for the next word before its first letter, and while you type a name it computes the members that a . after it would show.

Problems are checked in the background. Typing pauses the check, and it runs again when typing pauses.

Measurementp95
Completion at the start of a word, measured directly on the Runesmith solutionunder 5 ms
Completion after a ., measured directly on the Runesmith solution13 ms
Suggestions shown in the editor while typing, in the typing benchmarkabout 36 ms

Language services describes how these are measured, and how to run the typing benchmark.

Limitations​

  • Suggestions that expand into more than their label, such as completing an override with its whole method, insert only the label.
  • Go to definition finds symbols declared in source; symbols from a library or the .NET reference assemblies have no location to go to.
  • Problems are the compiler's own. Code style rules and analyzers that a project references are not run.
  • Fixes and refactorings that add, move or delete files, such as generating a class in a new file, are listed but not applied yet: picking one says so and changes nothing.
  • Fixes and refactorings whose providers need services of a full development environment, such as installing packages, are left out.

Build​

Build › Build runs dotnet build on the open folder. It builds the first .slnx file at the top of the folder, or else the first .sln, .csproj or .fsproj file. The build's output goes to the Output panel, and every error and warning appears in the Problems panel with its file, line and code, such as CS0103, as soon as the compiler reports it. Build › Cancel Build stops the build.

Errors without a file, such as a missing project, are listed on the solution or project being built.

Run configurations​

The plugin adds three kinds of run configuration. When you open a folder, it finds the projects in it (up to six folders deep, skipping bin, obj and hidden folders) and makes a configuration for each one, so most folders run without setup. Running covers the run widget, the Run panel and Run › Edit Configurations....

KindFound forWhat it runs
.NET projectEach project whose OutputType is Exe or WinExe, or that uses the web or worker SDKdotnet run --project <project> --no-build -c <configuration> -f <framework>, with the launch profile and the arguments after --
.NET testsEach project that sets IsTestProject or references xUnit, NUnit, MSTest or Microsoft.NET.Test.Sdkdotnet test <project> --no-build -c <configuration>, with --filter when you set one
.NET commandNever; you add itAny dotnet command line, such as format or ef database update, in the open folder

A .NET project configuration has these settings:

SettingMeaning
ProjectThe project to run, from the projects found in the folder.
Target frameworkOne of the project's TargetFramework or TargetFrameworks; Project default is the first.
Launch profileA profile from Properties/launchSettings.json whose commandName is Project, with its environment and URLs, or None.
ConfigurationDebug or Release.
Program argumentsOne argument per row, passed to the program as they are.
Environment variablesNames and values set for the program, over Runesmith's own environment.
Working directoryWhere the program starts; the project's folder when empty.
.NET SDKThe SDK whose dotnet runs it; empty uses the default SDK. An SDK with its own dotnet runs with DOTNET_ROOT set to its folder.

The Build step before a .NET project or tests configuration builds only that project, with dotnet build and the same configuration and framework, and its errors and warnings appear in the Problems panel as a folder build's do. A .NET command builds the folder.

Debugging​

Debug on a .NET project configuration builds the project and starts the built assembly, bin/<configuration>/<framework>/<assembly>.dll, under netcoredbg, Samsung's open source .NET debugger, with the configuration's arguments, environment variables and working directory. The assembly runs with the dotnet of the configuration's .NET SDK, with DOTNET_ROOT set when that SDK has its own dotnet. Debugging covers breakpoints, stepping and the Debug panel. .NET tests and .NET command configurations cannot be debugged yet.

The plugin does not ship netcoredbg. The first time you debug, it downloads netcoredbg 3.2.0-1092 from the project's GitHub release page, with its progress in the status bar, checks the download against the SHA-256 checksum the plugin pins for it, and keeps it in the plugin's storage folder, so later sessions start at once. The download comes from github.com and release-assets.githubusercontent.com. netcoredbg is MIT licensed; its license notice is in the plugin's THIRD-PARTY-NOTICES.md.

netcoredbg has builds for Linux on x64 and Arm64, Windows on x64 and macOS on Apple silicon. On other computers, such as a Mac with an Intel processor, Debug says there is no build for it. When the download fails, the Run panel says why, and the next Debug tries again.

SDKs​

The plugin finds the .NET SDKs on your computer and downloads new ones from Microsoft's release metadata. File › SDKs... lists them, with their channel's updates, and installs SDKs side by side in Runesmith's own .NET folder, checking each download's SHA-512 checksum. When the default .NET SDK is one Runesmith installed, Build runs the dotnet of that folder. SDKs describes the page.

Templates​

File › New Project lists the project templates of every .NET SDK Runesmith finds and of every template package you installed with dotnet new install, so a package you install shows up the next time the dialog opens. They come from a separate plugin, C# templates (runesmith.csharp-templates, developed in RunesmithHub/plugin-csharp-templates), which you install from the plugin hub as you install the C# plugin; turn it off in Settings › Plugins to hide them and keep the rest of C# support.

The plugin reads the packages without unpacking them:

  • the SDK's own packages, in templates/<version> of each .NET root: the roots Runesmith's SDK list knows, DOTNET_ROOT, and the folder of the dotnet on the PATH;
  • your installed packages, in .templateengine/packages of your home folder, or of DOTNET_CLI_HOME when it is set.

Each template's template.json gives its name, description, language and parameters. A template that comes in C#, F# and Visual Basic shows once, with a Language choice. Its parameters become options: a choice becomes a drop-down, a bool a check box, a number a number field and text a text field, and the Framework parameter becomes Target framework. Parameters that dotnet new --help hides, such as port numbers, and Skip restore are left out. Item and solution templates are not listed; Blank Solution makes an empty .slnx solution.

Create runs dotnet new with the template's short name, its language and the options you changed, using the .NET SDK you picked, and lets it restore the project. The project goes in a folder of its own, next to a .slnx solution that lists it. With Put solution and project in the same directory, the project is created directly in the new folder, without a solution.