Skip to content

Commit 5137b86

Browse files
Added AllowDerivedRequest support for lsp tellemtry event
1 parent a3a9674 commit 5137b86

File tree

5 files changed

+207
-20
lines changed

5 files changed

+207
-20
lines changed

src/JsonRpc.Generators/DelegateHelpers.cs

-4
Original file line numberDiff line numberDiff line change
@@ -89,10 +89,6 @@ public static GenericNameSyntax CreateAction(bool withCancellationToken, params
8989
.WithTypeArgumentList(TypeArgumentList(SeparatedList(typeArguments)));
9090
}
9191

92-
public static GenericNameSyntax CreateAction(params TypeSyntax[] arguments) => CreateAction(true, arguments);
93-
94-
public static GenericNameSyntax CreateAsyncAction(params TypeSyntax[] arguments) => CreateAsyncFunc(null, true, arguments);
95-
9692
public static GenericNameSyntax CreateAsyncAction(bool withCancellationToken, params TypeSyntax[] arguments) => CreateAsyncFunc(null, withCancellationToken, arguments);
9793

9894
public static GenericNameSyntax CreateAsyncFunc(TypeSyntax? returnType, bool withCancellationToken, params TypeSyntax[] arguments)

src/JsonRpc.Generators/Strategies/OnNotificationMethodGeneratorWithRegistrationOptionsStrategy.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,9 @@ public IEnumerable<MemberDeclarationSyntax> Apply(ExtensionMethodContext extensi
4646
if (allowDerivedRequests)
4747
{
4848
var genericFactory = MakeGenericFactory(factory, notification.Request.Syntax);
49-
yield return genericFactory(CreateAction(IdentifierName("T")));
50-
yield return genericFactory(CreateAsyncAction(false, IdentifierName("T")));
49+
yield return genericFactory(CreateAction(false, IdentifierName("T")));
5150
yield return genericFactory(CreateAction(true, IdentifierName("T")));
51+
yield return genericFactory(CreateAsyncAction(false, IdentifierName("T")));
5252
yield return genericFactory(CreateAsyncAction(true, IdentifierName("T")));
5353
}
5454

src/JsonRpc.Generators/Strategies/OnNotificationMethodGeneratorWithoutRegistrationOptionsStrategy.cs

+11-11
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,21 @@ internal class OnNotificationMethodGeneratorWithoutRegistrationOptionsStrategy :
1212
{
1313
public IEnumerable<MemberDeclarationSyntax> Apply(ExtensionMethodContext extensionMethodContext, GeneratorData item)
1414
{
15-
if (item is { RegistrationOptions: {} }) yield break;
15+
if (item is { RegistrationOptions: { } }) yield break;
1616
if (item is not NotificationItem notification) yield break;
1717
if (extensionMethodContext is not { IsRegistry: true }) yield break;
1818

1919
var allowDerivedRequests = item.JsonRpcAttributes.AllowDerivedRequests;
2020

2121
var method = MethodDeclaration(extensionMethodContext.Item, item.JsonRpcAttributes.HandlerMethodName)
22-
.WithModifiers(
23-
TokenList(
24-
Token(SyntaxKind.PublicKeyword),
25-
Token(SyntaxKind.StaticKeyword)
26-
)
27-
)
28-
.WithExpressionBody(GetNotificationHandlerExpression(GetJsonRpcMethodName(extensionMethodContext.TypeDeclaration)))
29-
.WithSemicolonToken(Token(SyntaxKind.SemicolonToken));
22+
.WithModifiers(
23+
TokenList(
24+
Token(SyntaxKind.PublicKeyword),
25+
Token(SyntaxKind.StaticKeyword)
26+
)
27+
)
28+
.WithExpressionBody(GetNotificationHandlerExpression(GetJsonRpcMethodName(extensionMethodContext.TypeDeclaration)))
29+
.WithSemicolonToken(Token(SyntaxKind.SemicolonToken));
3030

3131
var factory = MakeMethodFactory(method, extensionMethodContext.GetRegistryParameterList());
3232
yield return factory(CreateAction(false, item.Request.Syntax));
@@ -37,9 +37,9 @@ public IEnumerable<MemberDeclarationSyntax> Apply(ExtensionMethodContext extensi
3737
if (allowDerivedRequests)
3838
{
3939
var genericFactory = MakeGenericFactory(factory, notification.Request.Syntax);
40-
yield return genericFactory(CreateAction(IdentifierName("T")));
41-
yield return genericFactory(CreateAsyncAction(false, IdentifierName("T")));
40+
yield return genericFactory(CreateAction(false, IdentifierName("T")));
4241
yield return genericFactory(CreateAction(true, IdentifierName("T")));
42+
yield return genericFactory(CreateAsyncAction(false, IdentifierName("T")));
4343
yield return genericFactory(CreateAsyncAction(true, IdentifierName("T")));
4444
}
4545

src/Protocol/Features/Window/TelemetryEventFeature.cs

+6-3
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,18 @@
99
// ReSharper disable once CheckNamespace
1010
namespace OmniSharp.Extensions.LanguageServer.Protocol
1111
{
12-
1312
namespace Models
1413
{
1514
[Parallel]
1615
[Method(WindowNames.TelemetryEvent, Direction.ServerToClient)]
17-
[GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Window"), GenerateHandlerMethods, GenerateRequestMethods(typeof(IWindowLanguageServer), typeof(ILanguageServer))]
16+
[
17+
GenerateHandler("OmniSharp.Extensions.LanguageServer.Protocol.Window", AllowDerivedRequests = true),
18+
GenerateHandlerMethods,
19+
GenerateRequestMethods(typeof(IWindowLanguageServer), typeof(ILanguageServer))
20+
]
1821
public record TelemetryEventParams : IRequest
1922
{
20-
[JsonExtensionData] public IDictionary<string, JToken> Data { get; init; } = new Dictionary<string, JToken>();
23+
[JsonExtensionData] public IDictionary<string, object> ExtensionData { get; init; } = new Dictionary<string, object>();
2124
}
2225
}
2326

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Threading;
5+
using System.Threading.Tasks;
6+
using FluentAssertions;
7+
using NSubstitute;
8+
using OmniSharp.Extensions.JsonRpc.Testing;
9+
using OmniSharp.Extensions.LanguageProtocol.Testing;
10+
using OmniSharp.Extensions.LanguageServer.Protocol.Models;
11+
using OmniSharp.Extensions.LanguageServer.Protocol.Window;
12+
using TestingUtils;
13+
using Xunit.Abstractions;
14+
15+
namespace Lsp.Tests.Integration
16+
{
17+
public class CustomRequestsTests : LanguageProtocolTestBase
18+
{
19+
public CustomRequestsTests(ITestOutputHelper outputHelper) : base(new JsonRpcTestOptions().ConfigureForXUnit(outputHelper))
20+
{
21+
}
22+
23+
[RetryFact]
24+
public async Task Should_Support_Custom_Telemetry_Using_Base_Class()
25+
{
26+
var fake = Substitute.For<TelemetryEventHandlerBase<CustomTelemetryEventParams>>();
27+
var (_, server) = await Initialize(options => { }, options => { options.AddHandler(fake); });
28+
29+
var @event = new CustomTelemetryEventParams {
30+
CodeFolding = true,
31+
ProfileLoading = false,
32+
ScriptAnalysis = true,
33+
Pester5CodeLens = true,
34+
PromptToUpdatePackageManagement = false
35+
};
36+
server.SendTelemetryEvent(@event);
37+
await SettleNext();
38+
39+
var call = fake.ReceivedCalls().Single();
40+
var args = call.GetArguments();
41+
42+
args[0].Should().BeOfType<CustomTelemetryEventParams>()
43+
.And
44+
.Should().BeEquivalentTo(@event);
45+
}
46+
47+
[RetryFact]
48+
public async Task Should_Support_Custom_Telemetry_Receiving_Regular_Telemetry_Using_Base_Class()
49+
{
50+
var fake = Substitute.For<TelemetryEventHandlerBase>();
51+
var (_, server) = await Initialize(options => { }, options => { options.AddHandler(fake); });
52+
53+
var @event = new CustomTelemetryEventParams {
54+
CodeFolding = true,
55+
ProfileLoading = false,
56+
ScriptAnalysis = true,
57+
Pester5CodeLens = true,
58+
PromptToUpdatePackageManagement = false
59+
};
60+
server.SendTelemetryEvent(@event);
61+
await SettleNext();
62+
63+
var call = fake.ReceivedCalls().Single();
64+
var args = call.GetArguments();
65+
var request = args[0].Should().BeOfType<TelemetryEventParams>().Which;
66+
request.ExtensionData.Should().ContainKey("codeFolding").And.Subject["codeFolding"].Should().Be(true);
67+
request.ExtensionData.Should().ContainKey("profileLoading").And.Subject["profileLoading"].Should().Be(false);
68+
request.ExtensionData.Should().ContainKey("scriptAnalysis").And.Subject["scriptAnalysis"].Should().Be(true);
69+
request.ExtensionData.Should().ContainKey("pester5CodeLens").And.Subject["pester5CodeLens"].Should().Be(true);
70+
request.ExtensionData.Should().ContainKey("promptToUpdatePackageManagement").And.Subject["promptToUpdatePackageManagement"].Should().Be(false);
71+
}
72+
73+
[RetryFact]
74+
public async Task Should_Support_Custom_Telemetry_Using_Extension_Data_Using_Base_Class()
75+
{
76+
var fake = Substitute.For<TelemetryEventHandlerBase<CustomTelemetryEventParams>>();
77+
var (_, server) = await Initialize(options => { }, options => { options.AddHandler(fake); });
78+
79+
server.SendTelemetryEvent(
80+
new TelemetryEventParams {
81+
ExtensionData = new Dictionary<string, object> {
82+
["CodeFolding"] = true,
83+
["ProfileLoading"] = false,
84+
["ScriptAnalysis"] = true,
85+
["Pester5CodeLens"] = true,
86+
["PromptToUpdatePackageManagement"] = false
87+
}
88+
}
89+
);
90+
91+
var call = fake.ReceivedCalls().Single();
92+
var args = call.GetArguments();
93+
var request = args[0].Should().BeOfType<CustomTelemetryEventParams>().Which;
94+
request.CodeFolding.Should().Be(true);
95+
request.ProfileLoading.Should().Be(false);
96+
request.ScriptAnalysis.Should().Be(true);
97+
request.Pester5CodeLens.Should().Be(true);
98+
request.PromptToUpdatePackageManagement.Should().Be(false);
99+
}
100+
101+
[RetryFact]
102+
public async Task Should_Support_Custom_Telemetry_Using_Delegate()
103+
{
104+
var fake = Substitute.For<Func<CustomTelemetryEventParams, CancellationToken, Task>>();
105+
var (_, server) = await Initialize(options => { options.OnTelemetryEvent(fake); }, options => { });
106+
107+
var @event = new CustomTelemetryEventParams {
108+
CodeFolding = true,
109+
ProfileLoading = false,
110+
ScriptAnalysis = true,
111+
Pester5CodeLens = true,
112+
PromptToUpdatePackageManagement = false
113+
};
114+
server.SendTelemetryEvent(@event);
115+
await SettleNext();
116+
117+
var call = fake.ReceivedCalls().Single();
118+
var args = call.GetArguments();
119+
args[0]
120+
.Should().BeOfType<CustomTelemetryEventParams>()
121+
.And
122+
.Should().BeEquivalentTo(@event);
123+
}
124+
125+
[RetryFact]
126+
public async Task Should_Support_Custom_Telemetry_Receiving_Regular_Telemetry_Using_Delegate()
127+
{
128+
var fake = Substitute.For<Func<TelemetryEventParams, CancellationToken, Task>>();
129+
var (_, server) = await Initialize(options => { options.OnTelemetryEvent(fake); }, options => { });
130+
131+
var @event = new CustomTelemetryEventParams {
132+
CodeFolding = true,
133+
ProfileLoading = false,
134+
ScriptAnalysis = true,
135+
Pester5CodeLens = true,
136+
PromptToUpdatePackageManagement = false
137+
};
138+
server.SendTelemetryEvent(@event);
139+
await SettleNext();
140+
141+
var call = fake.ReceivedCalls().Single();
142+
var args = call.GetArguments();
143+
var request = args[0].Should().BeOfType<TelemetryEventParams>().Which;
144+
request.ExtensionData.Should().ContainKey("codeFolding").And.Subject["codeFolding"].Should().Be(true);
145+
request.ExtensionData.Should().ContainKey("profileLoading").And.Subject["profileLoading"].Should().Be(false);
146+
request.ExtensionData.Should().ContainKey("scriptAnalysis").And.Subject["scriptAnalysis"].Should().Be(true);
147+
request.ExtensionData.Should().ContainKey("pester5CodeLens").And.Subject["pester5CodeLens"].Should().Be(true);
148+
request.ExtensionData.Should().ContainKey("promptToUpdatePackageManagement").And.Subject["promptToUpdatePackageManagement"].Should().Be(false);
149+
}
150+
151+
[RetryFact]
152+
public async Task Should_Support_Custom_Telemetry_Using_Extension_Data_Using_Delegate()
153+
{
154+
var fake = Substitute.For<Func<CustomTelemetryEventParams, CancellationToken, Task>>();
155+
var (_, server) = await Initialize(options => { options.OnTelemetryEvent(fake); }, options => { });
156+
157+
server.SendTelemetryEvent(
158+
new TelemetryEventParams {
159+
ExtensionData = new Dictionary<string, object> {
160+
["CodeFolding"] = true,
161+
["ProfileLoading"] = false,
162+
["ScriptAnalysis"] = true,
163+
["Pester5CodeLens"] = true,
164+
["PromptToUpdatePackageManagement"] = false
165+
}
166+
}
167+
);
168+
169+
var call = fake.ReceivedCalls().Single();
170+
var args = call.GetArguments();
171+
var request = args[0].Should().BeOfType<CustomTelemetryEventParams>().Which;
172+
request.CodeFolding.Should().Be(true);
173+
request.ProfileLoading.Should().Be(false);
174+
request.ScriptAnalysis.Should().Be(true);
175+
request.Pester5CodeLens.Should().Be(true);
176+
request.PromptToUpdatePackageManagement.Should().Be(false);
177+
}
178+
179+
public record CustomTelemetryEventParams : TelemetryEventParams
180+
{
181+
public bool ScriptAnalysis { get; init; }
182+
public bool CodeFolding { get; init; }
183+
public bool PromptToUpdatePackageManagement { get; init; }
184+
public bool ProfileLoading { get; init; }
185+
public bool Pester5CodeLens { get; init; }
186+
}
187+
}
188+
}

0 commit comments

Comments
 (0)