Let's Build RDCore
Ce document est disponible en français
Note
⏳ External contributions are presently closed.
👉 Keep an eye out for the announcement of a CLA and the official open-core project launch soon!
🚀 Getting Started
- First read and sign the Contributor Licence Agreement (CLA) as appropriate for your situation (it will make the next steps smoother);
- Browse the project roadmap and pick a ticket under the current milestone;
- Fork the RDCore repository to your GitHub account;
- Download a clone of the repository on a workstation that is free of rights (i.e. NOT your employer's computer);
- Open
RDCore.slnxun Microsoft Visual Studio Community Editition 2026 (free for open-source contributions);
- 👉 Alternatively, use
dotnet buildCLI tooling to build the solution.
- Start a new branch from main, named in reference to the selected ticket;
- Implement and test your contributions in your local branch;
- When everything works and is ready for review, open a new pull request referring to the selected ticket;
- 👉 Mention
Closes #followed by the ticket number in the body of the pull request. - 👉 Such a mention in a commit of your branch history will appear in the ticket history as soon as your commits are pushed to your fork, which signals work in progress to other contributors.
- Once your pull request is completed, destroy your feature branch and resynchronize main to start work on a new ticket.
- 👉 The squash merge will destroy the details of your commit history in the central repository, which quickly complicates things if additional commits get added to an already-completed branch; a patch may be submitted by starting a new branch from main resynchronized to contain the merge commit.
🧩 Building a RDCore extension
It only takes a few lines in your entry point to make your application a RDCore app:
public class Program
{
public static async Task<int> Main(string[] args)
{
using var host = new RDCoreConsoleClientHost();
return await host.RunAsync(args);
}
}
Host
Before you can write these lines, you must define a host by inheriting RDCoreLanguageClientHost if you're writing a client :
internal class RDCoreConsoleClientHost() : RDCoreLanguageClientHost<RDCoreConsoleClientApp>()
{
protected override void ConfigureAdditionalExternalServices(IServiceCollection services, IConfiguration configuration)
{
services
.AddSingleton<IAppThemeService, AppThemeService>()
.AddSingleton<IAppThemeLoaderService, AppThemeLoaderService>()
.AddSingleton<IConsoleMessageWriter, DefaultConsoleMessageWriter>()
.AddSingleton<ILoggerProvider, RDCoreConsoleLoggerProvider>()
.AddSingleton<ShowSplashCommand>();
}
}
...or by inheriting VBCoreLanguageServerHost if you're building a server app instead:
internal class CoreDiagnosticsAppHost() : RDCoreLanguageServerHost<CoreDiagnosticsApp>()
{
protected override void ConfigureAdditionalExternalServices(IServiceCollection services, IConfiguration configuration)
{
}
}
Application
In both cases, the role of the host is to supply services to the IServiceCollection such that the application can be instantiated with injected services.
Then for a client you would inherit RDCoreClientApp :
internal class RDCoreConsoleClientApp(
IRDCoreLanguageServerProcess serverProcess,
IHealthCheckService<RDCoreConsoleClientApp> healthCheckService,
ILanguageServerProtocolTransportLayer transportLayer,
ILogger<RDCoreConsoleClientApp> logger)
: RDCoreClientApp(serverProcess, healthCheckService, transportLayer, logger)
{
protected override void ConfigureServices(IServiceCollection services)
{
}
protected override ClientCapabilities ConfigureClientCapabilities(ClientCapabilities capabilities)
{
// TODO
return capabilities;
}
protected override void ConfigureHandlers(IRDCoreLSPHandlerConfigurationBuilder builder)
{
// TODO
}
protected override async Task OnLanguageClientStartedAsync(ILanguageClient client, CancellationToken token)
{
// TODO
}
protected override void Dispose(bool disposing) { }
}
...and for a server app we instead inherit the LSP app from RDCoreServerApp:
internal class CoreDiagnosticsApp : RDCoreServerApp
{
public CoreDiagnosticsApp(
IServerStateProvider serverStateProvider,
IHealthCheckService<CoreDiagnosticsApp> healthCheckService,
ILanguageServerProtocolTransportLayer transportLayer,
ILogger<CoreDiagnosticsApp> logger)
: base(serverStateProvider, healthCheckService, transportLayer, logger)
{
}
protected override void ConfigureHandlers(IRDCoreLSPHandlerConfigurationBuilder builder)
{
// TODO
}
protected override void RegisterServerCapabilities(ILanguageServer server, ClientCapabilities clientCapabilities)
{
// TODO
}
protected override void Dispose(bool disposing)
{
// TODO
}
}
In any case, the role of this abstraction layer is to configure the capabilities (LSP) of the application, along with the handlers that will be handling the LSP requests and notifications.
Client or Server?
- A client application is typically an IDE application.
- A server application could be a satellite language server, or a platform extension (plug-in).
- 🌐LSP 3.17 Specifications
Important
🧩 RDCore Platform Extensions need a manifest to enable their discovery by the environment host; the schema of this manifest is defined by ExtensionInfo; the environment host may provide developer tooling (CLI) to facilitate the creation of an extension manifest for a given extension.
Capabilities
RDCore platform extensions with a valid manifest that gets them to initiate a LSP handshake with the LSP orchestration layer must supply initialization parameters that specify a complete set of both LSP (protocol) defined and environment host-defined capabilities.
👉 The complete and exhaustive list of platform capabilities shall be documented in RD-VBAL §2.0.2 as its implementation progresses.
Note
First and third party extensions distributed through the RDCore Platform Cloud Infrastructure MAY use a capability provider that MAY validate the availability of certain advanced capabilities by requiring 2FA authentication, the validation of an active subscription (free or paid), and the validation of the signed build against the certified distribution channel build.
🧩 Platform-level extensions (SDK and language core)
The lgnauge core is engineered to be extended through server type extensions, via an exchange of capabilities giving access to extension points.
Please see RD-VBAL § 1.1 for more details and the platform's extension philosophy at that level.
ACCUEIL • HOME | ℹ️ BIENVENUE • WELCOME | 🧩 BÂTISSONS • BUILD | RD-VBAL | SDK | 🌐 rubberduckvba.ca