Skip to content

Commit 48865d8

Browse files
Better behavior with progress observables
1 parent 8460bd0 commit 48865d8

18 files changed

+172
-126
lines changed

src/JsonRpc.Generators/Contexts/GeneratorData.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ HashSet<string> additionalUsings
4343
if (IsRequest(candidateClass))
4444
{
4545
var responseType = GetResponseType(candidateClass, symbol);
46+
var (partialItem, inheritsFromSelf) = GetPartialItem(candidateClass, symbol, requestType, compilation);
4647
return new RequestItem(
4748
candidateClass,
4849
symbol,
@@ -54,9 +55,10 @@ HashSet<string> additionalUsings
5455
responseType.Syntax.GetSyntaxName() == "Unit",
5556
GetCapability(candidateClass, symbol, lspAttributes),
5657
GetRegistrationOptions(candidateClass, symbol, lspAttributes),
57-
GetPartialItem(candidateClass, symbol, requestType),
58+
partialItem,
5859
GetPartialItems(candidateClass, symbol, requestType),
5960
symbol.AllInterfaces.Concat(requestType.Symbol.AllInterfaces).Any(z => z.Name.EndsWith("WithInitialValue", StringComparison.Ordinal)),
61+
inheritsFromSelf,
6062
additionalUsings,
6163
new List<AttributeArgumentSyntax>(),
6264
model, compilation

src/JsonRpc.Generators/Contexts/RequestItem.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ record RequestItem(
1818
SyntaxSymbol? PartialItem,
1919
SyntaxSymbol? PartialItems,
2020
bool PartialHasInitialValue,
21+
bool PartialItemInheritsFromSelf,
2122
HashSet<string> AdditionalUsings,
2223
List<AttributeArgumentSyntax> AssemblyJsonRpcHandlersAttributeArguments,
2324
SemanticModel Model,

src/JsonRpc.Generators/GenerateHandlerMethodsGenerator.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ syntaxNode is TypeDeclarationSyntax tds
6060
{
6161
diagnostic = Diagnostic.Create(
6262
GeneratorDiagnostics.Exception, syntaxContext.Node.GetLocation(), e.Message,
63-
e.StackTrace ?? string.Empty
63+
e.StackTrace?.Replace("\n", " ") ?? string.Empty, e.ToString()
6464
);
6565
Debug.WriteLine(e);
6666
Debug.WriteLine(e.StackTrace);
@@ -106,7 +106,7 @@ private void GenerateHandlerMethods(
106106
context.ReportDiagnostic(
107107
Diagnostic.Create(
108108
GeneratorDiagnostics.Exception, candidateClass.GetLocation(),
109-
$"Strategy {strategy.GetType().FullName} failed!" + " - " + e.Message, e.StackTrace ?? string.Empty
109+
$"Strategy {strategy.GetType().FullName} failed!" + " - " + e.Message, e.StackTrace?.Replace("\n", " ") ?? string.Empty
110110
)
111111
);
112112
Debug.WriteLine($"Strategy {strategy.GetType().FullName} failed!");

src/JsonRpc.Generators/GeneratorDiagnostics.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ internal static class GeneratorDiagnostics
88
{
99
public static DiagnosticDescriptor Exception { get; } = new DiagnosticDescriptor(
1010
"JRPC0001", "Exception",
11-
"{0} - {1}", "JRPC", DiagnosticSeverity.Error, true
11+
"{0} - {1} {2}", "JRPC", DiagnosticSeverity.Error, true
1212
);
1313

1414
public static DiagnosticDescriptor NoHandlerRegistryProvided { get; } = new DiagnosticDescriptor(

src/JsonRpc.Generators/Helpers.cs

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -250,22 +250,27 @@ public static SyntaxSymbol GetResponseType(TypeDeclarationSyntax syntax, INamedT
250250
return new SyntaxSymbol(type ?? ResolveTypeName(localSymbol), localSymbol);
251251
}
252252

253-
public static SyntaxSymbol? GetPartialItem(TypeDeclarationSyntax syntax, INamedTypeSymbol symbol, SyntaxSymbol requestType)
253+
public static (SyntaxSymbol? partialItem, bool inheritsFromSelf) GetPartialItem(
254+
TypeDeclarationSyntax syntax, INamedTypeSymbol symbol, SyntaxSymbol requestType, Compilation compilation
255+
)
254256
{
255257
var handlerInterface = symbol.AllInterfaces.Concat(requestType.Symbol.AllInterfaces)
256258
.FirstOrDefault(
257259
z => z is { Name: "IPartialItem", TypeArguments.Length: 1 } or
258260
{ Name: "IPartialItemWithInitialValue", TypeArguments.Length: 2 }
259261
);
260262
var localSymbol = handlerInterface?.TypeArguments[0] as INamedTypeSymbol;
261-
if (localSymbol == null) return null;
263+
if (localSymbol == null) return ( null, false );
262264
var type = syntax.BaseList?.Types
263265
.Select(z => z.Type is GenericNameSyntax genericNameSyntax ? genericNameSyntax : null)
264266
.Where(z => z != null)
265267
.Where(z => z is { Identifier.Text: "IPartialItemRequest" or "IPartialItemWithInitialValueRequest", Arity: 2 })
266268
.Select(z => z!.TypeArgumentList.Arguments[1])
267269
.FirstOrDefault();
268-
return new SyntaxSymbol(type ?? ResolveTypeName(localSymbol), localSymbol);
270+
return (
271+
new SyntaxSymbol(type ?? ResolveTypeName(localSymbol), localSymbol),
272+
handlerInterface!.TypeArguments.Length == 2 && compilation.HasImplicitConversion(handlerInterface!.TypeArguments[1], handlerInterface.TypeArguments[0])
273+
);
269274
}
270275

271276
public static NameSyntax ResolveTypeName(ITypeSymbol symbol)
@@ -351,11 +356,12 @@ private static ArgumentListSyntax GetHandlerArgumentList() =>
351356
);
352357

353358
public static ArgumentListSyntax GetRegistrationHandlerArgumentList(
354-
TypeSyntax registrationOptionsName, TypeSyntax registrationType, ArgumentSyntax handlerArgument, ArgumentSyntax? initialArgument, TypeSyntax? capabilityType, bool includeId
359+
TypeSyntax registrationOptionsName, TypeSyntax registrationType, ArgumentSyntax handlerArgument, ArgumentSyntax? initialArgument,
360+
TypeSyntax? capabilityType, bool includeId
355361
) =>
356362
ArgumentList(
357363
SeparatedList(
358-
(includeId
364+
( includeId
359365
? new[]
360366
{
361367
Argument(IdentifierName("id")),
@@ -368,7 +374,7 @@ public static ArgumentListSyntax GetRegistrationHandlerArgumentList(
368374
initialArgument!,
369375
handlerArgument,
370376
Argument(GetRegistrationOptionsAdapter(registrationOptionsName, registrationType, capabilityType))
371-
})
377+
} )
372378
.Where(z => z is not null)
373379
)
374380
);
@@ -877,7 +883,9 @@ public static ArrowExpressionClauseSyntax GetRequestInvokeExpression() =>
877883
)
878884
);
879885

880-
public static ArrowExpressionClauseSyntax GetPartialInvokeExpression(TypeSyntax responseType, TypeSyntax? partialItemType)
886+
public static ArrowExpressionClauseSyntax GetPartialInvokeExpression(
887+
TypeSyntax responseType, TypeSyntax? partialItemType, bool partialItemTypeInheritsFromSelf
888+
)
881889
{
882890
var realResponseType = responseType is NullableTypeSyntax nts ? nts.ElementType : responseType;
883891
var factoryArgument = Argument(
@@ -889,13 +897,11 @@ public static ArrowExpressionClauseSyntax GetPartialInvokeExpression(TypeSyntax
889897
);
890898
var arguments = new[]
891899
{
892-
Argument(
893-
IdentifierName(@"request")
894-
),
900+
Argument(IdentifierName(@"request")),
895901
factoryArgument,
896902
Argument(IdentifierName("cancellationToken"))
897903
};
898-
if (partialItemType is { })
904+
if (partialItemType is { } && !partialItemTypeInheritsFromSelf)
899905
{
900906
var realPartialItemType = partialItemType is NullableTypeSyntax nts2 ? nts2.ElementType : partialItemType;
901907
arguments = new[]

src/JsonRpc.Generators/RegistrationOptionsGenerator.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,7 @@ private void GenerateRegistrationOptions(
312312
catch (Exception e)
313313
{
314314
context.ReportDiagnostic(
315-
Diagnostic.Create(GeneratorDiagnostics.Exception, registrationOptions.GetLocation(), e.Message, e.StackTrace ?? string.Empty)
315+
Diagnostic.Create(GeneratorDiagnostics.Exception, registrationOptions.GetLocation(), e.Message, e.StackTrace?.Replace("\n", " ") ?? string.Empty, e.ToString())
316316
);
317317
Debug.WriteLine(e);
318318
Debug.WriteLine(e.StackTrace);

src/JsonRpc.Generators/Strategies/SendMethodRequestStrategy.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,11 @@ public IEnumerable<MemberDeclarationSyntax> Apply(SourceProductionContext contex
6262
)
6363
.WithParameterList(parameterList)
6464
.WithExpressionBody(
65-
Helpers.GetPartialInvokeExpression(request.Response.Syntax, request.PartialHasInitialValue ? null : request.PartialItem.Syntax)
65+
Helpers.GetPartialInvokeExpression(
66+
request.Response.Syntax,
67+
request.PartialHasInitialValue ? null : request.PartialItem.Syntax,
68+
request.PartialItemInheritsFromSelf
69+
)
6670
)
6771
.WithSemicolonToken(Token(SyntaxKind.SemicolonToken));
6872
yield break;
@@ -97,7 +101,7 @@ public IEnumerable<MemberDeclarationSyntax> Apply(SourceProductionContext contex
97101
)
98102
)
99103
.WithParameterList(parameterList)
100-
.WithExpressionBody(Helpers.GetPartialInvokeExpression(request.Response.Syntax, default))
104+
.WithExpressionBody(Helpers.GetPartialInvokeExpression(request.Response.Syntax, default, false))
101105
.WithSemicolonToken(Token(SyntaxKind.SemicolonToken));
102106
yield break;
103107
}

src/Protocol/AbstractHandlers.PartialWithInitialValue.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ public abstract class PartialResultWithInitialValue<TParams, TResponse, TItem, T
2020
Base<TRegistrationOptions, TCapability>,
2121
IJsonRpcRequestHandler<TParams, TResponse?>
2222
where TItem : class?
23-
where TParams : IPartialItemWithInitialValueRequest<TResponse?, TItem>
24-
where TResponse : class?
23+
where TParams : IPartialItemWithInitialValueRequest<TResponse?, TItem?>
24+
where TResponse : TItem?
2525
where TRegistrationOptions : class, new()
2626
where TCapability : ICapability
2727
{
@@ -68,8 +68,8 @@ public abstract class PartialResultWithInitialValue<TParams, TResponse, TItem, T
6868
Base<TRegistrationOptions>,
6969
IJsonRpcRequestHandler<TParams, TResponse?>
7070
where TItem : class?
71-
where TParams : IPartialItemWithInitialValueRequest<TResponse?, TItem>
72-
where TResponse : class?
71+
where TParams : IPartialItemWithInitialValueRequest<TResponse?, TItem?>
72+
where TResponse : TItem?
7373
where TRegistrationOptions : class, new()
7474
{
7575
private readonly IProgressManager _progressManager;
@@ -115,8 +115,8 @@ public abstract class PartialResultWithInitialValueCapability<TParams, TResponse
115115
BaseCapability<TCapability>,
116116
IJsonRpcRequestHandler<TParams, TResponse?>
117117
where TItem : class?
118-
where TParams : IPartialItemWithInitialValueRequest<TResponse?, TItem>
119-
where TResponse : class?
118+
where TParams : IPartialItemWithInitialValueRequest<TResponse?, TItem?>
119+
where TResponse : TItem?
120120
where TCapability : ICapability
121121
{
122122
private readonly IProgressManager _progressManager;

src/Protocol/Features/ProgressFeature.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ public static IRequestProgressObservable<TItem, TResponse> RequestProgress<TResp
132132
Func<TItem, TResponse> factory,
133133
Func<TResponse, TItem> reverseFactory,
134134
CancellationToken cancellationToken = default
135-
)
135+
) where TResponse : TItem
136136
{
137137
@params.SetPartialResultToken(new ProgressToken(Guid.NewGuid().ToString()));
138138

src/Protocol/LanguageProtocolDelegatingHandlers.Partial.cs

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,10 @@ CancellationToken cancellationToken
6565
{
6666
_handler(request, observer, Capability, cancellationToken);
6767
await observer;
68-
return _factory(default);
68+
return default;
6969
}
7070

71-
var subject = new AsyncSubject<TItem?>();
71+
using var subject = new Subject<TItem?>();
7272
var task = subject
7373
.Select(_factory)
7474
.ToTask(cancellationToken, _progressManager.Scheduler)
@@ -128,10 +128,10 @@ public PartialResult(
128128
{
129129
_handler(request, observer, cancellationToken);
130130
await observer;
131-
return _factory(default);
131+
return default;
132132
}
133133

134-
var subject = new AsyncSubject<TItem?>();
134+
using var subject = new Subject<TItem?>();
135135
var task = subject
136136
.Select(_factory)
137137
.ToTask(cancellationToken, _progressManager.Scheduler)
@@ -184,10 +184,10 @@ public PartialResultCapability(
184184
{
185185
_handler(request, Capability, observer, cancellationToken);
186186
await observer;
187-
return _factory(default);
187+
return default;
188188
}
189189

190-
var subject = new AsyncSubject<TItem?>();
190+
using var subject = new Subject<TItem?>();
191191
var task = subject
192192
.Select(_factory)
193193
.ToTask(cancellationToken, _progressManager.Scheduler)
@@ -232,10 +232,10 @@ public PartialResult(Guid id, Action<TParams, IObserver<TItem>, CancellationToke
232232
{
233233
_handler(request, observer, cancellationToken);
234234
await observer;
235-
return _factory(default);
235+
return default;
236236
}
237237

238-
var subject = new AsyncSubject<TItem?>();
238+
using var subject = new Subject<TItem?>();
239239
var task = subject
240240
.Select(_factory)
241241
.ToTask(cancellationToken, _progressManager.Scheduler)
@@ -293,10 +293,10 @@ public PartialResults(
293293
{
294294
_handler(request, observer, Capability, cancellationToken);
295295
await observer;
296-
return _factory(Enumerable.Empty<TItem>());
296+
return default;
297297
}
298298

299-
var subject = new Subject<IEnumerable<TItem>>();
299+
using var subject = new Subject<IEnumerable<TItem>>();
300300
var task = subject
301301
.Aggregate(
302302
new List<TItem>(), (acc, items) => {
@@ -360,10 +360,10 @@ public PartialResults(
360360
{
361361
_handler(request, observer, cancellationToken);
362362
await observer;
363-
return _factory(Enumerable.Empty<TItem>());
363+
return default;
364364
}
365365

366-
var subject = new Subject<IEnumerable<TItem>>();
366+
using var subject = new Subject<IEnumerable<TItem>>();
367367
var task = subject
368368
.Aggregate(
369369
new List<TItem>(), (acc, items) => {
@@ -422,10 +422,10 @@ public PartialResultsCapability(
422422
{
423423
_handler(request, observer, Capability, cancellationToken);
424424
await observer;
425-
return _factory(Enumerable.Empty<TItem>());
425+
return default;
426426
}
427427

428-
var subject = new Subject<IEnumerable<TItem>>();
428+
using var subject = new Subject<IEnumerable<TItem>>();
429429
var task = subject
430430
.Aggregate(
431431
new List<TItem>(), (acc, items) => {
@@ -481,10 +481,10 @@ public PartialResults(
481481
{
482482
_handler(request, observer, cancellationToken);
483483
await observer;
484-
return _factory(Enumerable.Empty<TItem>());
484+
return default;
485485
}
486486

487-
var subject = new Subject<IEnumerable<TItem>>();
487+
using var subject = new Subject<IEnumerable<TItem>>();
488488
var task = subject
489489
.Aggregate(
490490
new List<TItem>(), (acc, items) => {

src/Protocol/LanguageProtocolDelegatingHandlers.PartialWithInitialValue.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ public sealed class PartialResultWithInitialValue<TParams, TResponse, TItem, TRe
1515
AbstractHandlers.Base<TRegistrationOptions, TCapability>,
1616
IJsonRpcRequestHandler<TParams, TResponse?>,
1717
ICanBeIdentifiedHandler
18-
where TParams : IPartialItemWithInitialValueRequest<TResponse?, TItem>
18+
where TParams : IPartialItemWithInitialValueRequest<TResponse?, TItem?>
1919
where TItem : class?
20-
where TResponse : class?
20+
where TResponse : TItem?
2121
where TRegistrationOptions : class, new()
2222
where TCapability : ICapability
2323
{
@@ -88,9 +88,9 @@ public sealed class PartialResultWithInitialValue<TParams, TResponse, TItem, TRe
8888
AbstractHandlers.Base<TRegistrationOptions>,
8989
IJsonRpcRequestHandler<TParams, TResponse?>,
9090
ICanBeIdentifiedHandler
91-
where TParams : IPartialItemWithInitialValueRequest<TResponse, TItem>
91+
where TParams : IPartialItemWithInitialValueRequest<TResponse?, TItem?>
9292
where TItem : class?
93-
where TResponse : class?
93+
where TResponse : TItem?
9494
where TRegistrationOptions : class, new()
9595
{
9696
private readonly Action<TParams, IObserver<TItem>, CancellationToken> _handler;
@@ -157,9 +157,9 @@ public sealed class PartialResultWithInitialValueCapability<TParams, TResponse,
157157
AbstractHandlers.BaseCapability<TCapability>,
158158
IJsonRpcRequestHandler<TParams, TResponse?>,
159159
ICanBeIdentifiedHandler
160-
where TParams : IPartialItemWithInitialValueRequest<TResponse, TItem>
160+
where TParams : IPartialItemWithInitialValueRequest<TResponse?, TItem?>
161161
where TItem : class?
162-
where TResponse : class?
162+
where TResponse : TItem?
163163
where TCapability : ICapability
164164
{
165165
private readonly Action<TParams, TCapability, IObserver<TItem>, CancellationToken> _handler;
@@ -220,9 +220,9 @@ public PartialResultWithInitialValueCapability(
220220
public sealed class PartialResultWithInitialValue<TParams, TResponse, TItem> :
221221
IJsonRpcRequestHandler<TParams, TResponse?>,
222222
ICanBeIdentifiedHandler
223-
where TParams : IPartialItemWithInitialValueRequest<TResponse, TItem>
223+
where TParams : IPartialItemWithInitialValueRequest<TResponse?, TItem?>
224224
where TItem : class?
225-
where TResponse : class?
225+
where TResponse : TItem?
226226
{
227227
private readonly Action<TParams, IObserver<TItem>, CancellationToken> _handler;
228228
private readonly IProgressManager _progressManager;

src/Protocol/Models/IPartialItem.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ public interface IPartialItemRequest<out TResponse, T> : IRequest<TResponse>, IP
1010
}
1111

1212
public interface IPartialItemWithInitialValueRequest<out TResponse, T> : IRequest<TResponse>, IPartialItemWithInitialValue<T, TResponse>
13+
where TResponse : T
1314
{
1415
}
1516
}

0 commit comments

Comments
 (0)