-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathServiceCollectionExtensions.cs
More file actions
176 lines (169 loc) · 9.97 KB
/
Copy pathServiceCollectionExtensions.cs
File metadata and controls
176 lines (169 loc) · 9.97 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
using System.Diagnostics;
using MediatR;
using Microsoft.Extensions.DependencyInjection;
using OmniSharp.Extensions.LanguageServer.Protocol.Models;
using Reqnroll.IdeSupport.Common;
using Reqnroll.IdeSupport.Common.Configuration;
using Reqnroll.IdeSupport.Common.Diagnostics;
using Reqnroll.IdeSupport.Common.ProjectSystem.Configuration;
using Reqnroll.IdeSupport.LSP.Core.Diagnostics;
using Reqnroll.IdeSupport.LSP.Core.Completions;
using Reqnroll.IdeSupport.LSP.Core.Completions.Matching;
using Reqnroll.IdeSupport.LSP.Core.Scaffolding;
using Reqnroll.IdeSupport.LSP.Core.DocumentOutline;
using Reqnroll.IdeSupport.LSP.Core.Folding;
using Reqnroll.IdeSupport.LSP.Core.Commenting;
using Reqnroll.IdeSupport.LSP.Core.InlayHints;
using Reqnroll.IdeSupport.LSP.Core.Gherkin.Parsing;
using Reqnroll.IdeSupport.LSP.Core.Matching;
using Reqnroll.IdeSupport.LSP.Core.Rename;
using Reqnroll.IdeSupport.LSP.Server.Configuration;
using Reqnroll.IdeSupport.LSP.Server.Diagnostics.Performance;
using Reqnroll.IdeSupport.LSP.Server.Logging;
using Reqnroll.IdeSupport.LSP.Server.Discovery;
using Reqnroll.IdeSupport.LSP.Server.Pipeline;
using Reqnroll.IdeSupport.LSP.Server.Features.CodeActions;
using Reqnroll.IdeSupport.LSP.Server.Features.Commenting;
using Reqnroll.IdeSupport.LSP.Server.Features.DocumentOutline;
using Reqnroll.IdeSupport.LSP.Server.Features.Folding;
using Reqnroll.IdeSupport.LSP.Server.Features.Formatting;
using Reqnroll.IdeSupport.LSP.Server.Features.TextSync;
using Reqnroll.IdeSupport.LSP.Server.Features.CodeLens;
using Reqnroll.IdeSupport.LSP.Server.Features.FindUnusedStepDefs;
using Reqnroll.IdeSupport.LSP.Server.Features.References;
using Reqnroll.IdeSupport.LSP.Server.Features.Rename;
using Reqnroll.IdeSupport.LSP.Server.Features.Completions;
using Reqnroll.IdeSupport.LSP.Server.Features.Definition;
using Reqnroll.IdeSupport.LSP.Server.Features.InlayHints;
using Reqnroll.IdeSupport.LSP.Server.Features.SemanticTokens;
using Reqnroll.IdeSupport.LSP.Server.Telemetry;
using Reqnroll.IdeSupport.LSP.Server.Tagging;
using Reqnroll.IdeSupport.LSP.Server.Tracing;
using Reqnroll.IdeSupport.LSP.Server.Workspace;
namespace Reqnroll.IdeSupport.LSP.Server.Hosting;
/// <summary>
/// Extension methods for configuring the Dependency Injection container for the Reqnroll LSP Server.
/// </summary>
public static class ServiceCollectionExtensions
{
/// <summary>
/// Registers core infrastructure and cross-cutting services.
/// </summary>
public static IServiceCollection AddReqnrollLspCoreServices(this IServiceCollection services, string? clientIde,
TraceLevel logLevel = TraceLevel.Warning, InitializeTrace initialTrace = InitializeTrace.Off)
{
return services
.AddSingleton(new ClientIdeContext(clientIde, logLevel))
.AddSingleton<IDeveroomLogger, LspDeveroomLogger>()
.AddSingleton<IIdeScope, LspIdeScope>()
.AddSingleton<IMonitoringService>(sp => NullMonitoringService.Instance)
// Telemetry: emit telemetry/event notifications, optionally mirrored to a local JSONL
// debug log (REQNROLL_TELEMETRY_DEBUG_LOG). The decorator wraps the real emitter; when
// the debug log is unconfigured the sink is a no-op and it simply forwards.
.AddSingleton<ITelemetryDebugLog>(_ => TelemetryDebugLog.FromEnvironment())
.AddSingleton<LspTelemetryService>()
.AddSingleton<ILspTelemetryService>(sp => new FileLoggingLspTelemetryService(
sp.GetRequiredService<LspTelemetryService>(),
sp.GetRequiredService<ITelemetryDebugLog>()))
.AddSingleton<IDeveroomConfigurationProvider, ProjectSystemDeveroomConfigurationProvider>()
.AddSingleton<IEditorConfigOptionsProvider>(sp =>
new FileSystemEditorConfigOptionsProvider(sp.GetRequiredService<IIdeScope>().FileSystem))
// Performance Verification, Layer 4: field instrumentation. The recorder writes
// PERF lines to the log and (when REQNROLL_PERF_TELEMETRY_SAMPLE is set) emits sampled
// PerfSample telemetry. Singleton so the sampler's RNG is shared across handlers.
.AddSingleton<IPerfTelemetrySampler>(_ => PerfTelemetrySampler.FromEnvironment())
// F41: tracks the LSP `trace` level (--trace / InitializeParams.Trace / $/setTrace) and
// issues $/logTrace notifications. Singleton so the level set by $/setTrace is visible
// to every consumer (currently OperationDurationRecorder's PERF lines).
.AddSingleton<ITraceService>(sp => new TraceService(
sp.GetRequiredService<OmniSharp.Extensions.LanguageServer.Protocol.Server.ILanguageServerFacade>(),
initialTrace))
.AddSingleton<IOperationDurationRecorder>(sp => new OperationDurationRecorder(
sp.GetRequiredService<IDeveroomLogger>(),
sp.GetRequiredService<ClientIdeContext>(),
sp.GetRequiredService<ILspTelemetryService>(),
sp.GetRequiredService<IPerfTelemetrySampler>(),
sp.GetRequiredService<ITraceService>()));
}
/// <summary>
/// Registers project system, workspace, and binding discovery services.
/// </summary>
public static IServiceCollection AddReqnrollProjectSystem(this IServiceCollection services)
{
return services
.AddSingleton<ILspWorkspaceScopeManager, LspWorkspaceScopeManager>()
// BindingRegistryProviderRouter creates and owns one ConnectorBindingRegistryProvider
// per project and routes binding-registry lookups to the correct per-project instance
// via IProjectBindingRegistryLookup.GetRegistryForUri. Registries are NOT merged —
// each feature file is resolved against only its own project's bindings.
.AddSingleton<BindingRegistryProviderRouter>()
.AddSingleton<IProjectBindingRegistryLookup>(sp => sp.GetRequiredService<BindingRegistryProviderRouter>())
// Roslyn (source-level) binding discovery for .cs edits (design doc F2).
.AddSingleton<ICSharpBindingDiscoveryService, CSharpBindingDiscoveryService>()
.AddSingleton<IDeveroomTagParser, DeveroomTagParser>()
// Debounces the closed-feature-file rescan triggered by an incremental Roslyn patch
// whose binding expressions actually changed (BindingRegistryChangedHandler).
.AddSingleton<IFeatureRescanDebouncer, FeatureRescanDebouncer>();
}
/// <summary>
/// Registers editor services, parsing, and shared caching components.
/// </summary>
public static IServiceCollection AddReqnrollEditorServices(this IServiceCollection services)
{
return services
.AddSingleton<IDocumentBufferService, DocumentBufferService>()
// BindingMatchService holds the per-document match cache; it must be a singleton
// so the cache survives across requests and is shared by the tagger (writer) and
// the Go to Definition / diagnostics consumers (readers).
.AddSingleton<IBindingMatchService, BindingMatchService>()
.AddSingleton<IGherkinDocumentTaggerService, GherkinDocumentTaggerService>()
.AddSingleton<ISemanticTokenService, SemanticTokenService>()
.AddSingleton<IDiagnosticsAggregator, DiagnosticsAggregator>()
.AddSingleton<IGherkinFoldingRangeService, GherkinFoldingRangeService>()
.AddSingleton<ICommentToggleService, CommentToggleService>()
.AddSingleton<IGherkinInlayHintService, GherkinInlayHintService>();
}
/// <summary>
/// Registers OmniSharp LSP protocol handlers as singletons.
///
/// NOTE: MediatR notification handlers (e.g., SemanticTokensRefreshHandler, DiagnosticsPublishHandler)
/// are auto-discovered and registered as transients by the AddMediatR call in ConfigureServer.
/// DO NOT add explicit AddSingleton<INotificationHandler<T>> registrations here, as it will
/// cause MediatR to dispatch every notification to two handler instances (the transient from the
/// scan and the singleton from the explicit call).
///
/// The handlers listed below ARE registered explicitly as singletons because OmniSharp resolves
/// them from the root DryIoc container (not from a per-request scope), and they hold injected
/// ILanguageServer references that must live for the server's lifetime.
/// </summary>
public static IServiceCollection AddReqnrollLspHandlers(this IServiceCollection services)
{
return services
.AddSingleton<TextDocumentSyncHandler>()
.AddSingleton<WorkspaceFoldersHandler>()
.AddSingleton<WatchedFilesHandler>()
.AddSingleton<SemanticTokensHandler>()
.AddSingleton<StepReferencesHandler>()
.AddSingleton<FindStepUsagesHandler>()
.AddSingleton<ICompletionContextResolver, CompletionContextResolver>()
.AddSingleton<ICompletionService, CompletionService>()
.AddSingleton<ICompletionMatcher, ReturnAllCompletionMatcher>()
.AddSingleton<FeatureDefinitionHandler>()
.AddSingleton<GoToStepDefinitionsHandler>()
.AddSingleton<GoToHooksHandler>()
.AddSingleton<StepCodeLensHandler>()
.AddSingleton<GherkinCompletionHandler>()
.AddSingleton<IStepScaffoldService, StepScaffoldService>()
.AddSingleton<FeatureCodeActionHandler>()
.AddSingleton<FindUnusedStepDefinitionsHandler>()
.AddSingleton<GherkinFormattingHandler>()
.AddSingleton<IGherkinDocumentSymbolService, GherkinDocumentSymbolService>()
.AddSingleton<FeatureDocumentSymbolHandler>()
.AddSingleton<FeatureFoldingRangeHandler>()
.AddSingleton<CommentToggleHandler>()
.AddSingleton<StepRenameHandler>()
.AddSingleton<RenameSessionManager>()
.AddSingleton<FeatureInlayHintHandler>()
.AddSingleton<SetTraceNotificationHandler>();
}
}