Skip to content

Commit

Permalink
Added support for open generic params and handler interfaces. (#479)
Browse files Browse the repository at this point in the history
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
  • Loading branch information
david-driscoll and mergify[bot] authored Dec 15, 2020
1 parent e797c15 commit 2055eaa
Show file tree
Hide file tree
Showing 20 changed files with 1,819 additions and 206 deletions.
7 changes: 7 additions & 0 deletions src/Dap.Protocol/Models/ProgressToken.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ public record ProgressToken : IEquatable<long>, IEquatable<string>
private long? _long;
private string? _string;

public ProgressToken(Guid value)
{
_string = value.ToString();
_long = null;
}

public ProgressToken(long value)
{
_long = value;
Expand Down Expand Up @@ -46,6 +52,7 @@ public string String
public static implicit operator ProgressToken(long value) => new ProgressToken(value);

public static implicit operator ProgressToken(string value) => new ProgressToken(value);
public static implicit operator ProgressToken(Guid value) => new ProgressToken(value);

public bool Equals(long other) => IsLong && Long == other;
public bool Equals(string other) => IsString && String == other;
Expand Down
28 changes: 28 additions & 0 deletions src/Dap.Protocol/Serialization/ProgressTokenConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using System;
using Newtonsoft.Json;
using OmniSharp.Extensions.DebugAdapter.Protocol.Models;

namespace OmniSharp.Extensions.DebugAdapter.Protocol.Serialization
{
internal class ProgressTokenConverter : JsonConverter<ProgressToken?>
{
public override void WriteJson(JsonWriter writer, ProgressToken? value, JsonSerializer serializer)
{
if (value == null) writer.WriteNull();
else if (value.IsLong) serializer.Serialize(writer, value.Long);
else if (value.IsString) serializer.Serialize(writer, value.String);
else writer.WriteNull();
}

public override ProgressToken? ReadJson(JsonReader reader, Type objectType, ProgressToken? existingValue, bool hasExistingValue, JsonSerializer serializer)
{
return reader.TokenType switch {
JsonToken.Integer => new ProgressToken((long) reader.Value),
JsonToken.String when reader.Value is string str && !string.IsNullOrWhiteSpace(str) => new ProgressToken(str),
_ => null
};
}

public override bool CanRead => true;
}
}
1 change: 1 addition & 0 deletions src/Dap.Protocol/Serialization/Serializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ protected override void AddOrReplaceConverters(ICollection<JsonConverter> conver
ReplaceConverter(converters, new DapClientResponseConverter(this));
ReplaceConverter(converters, new DapClientRequestConverter());
ReplaceConverter(converters, new DapRpcErrorConverter(this));
ReplaceConverter(converters, new ProgressTokenConverter());
}

protected override JsonSerializer CreateSerializer()
Expand Down
2 changes: 1 addition & 1 deletion src/JsonRpc.Generators/Contexts/SyntaxSymbol.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace OmniSharp.Extensions.JsonRpc.Generators.Contexts
{
record SyntaxSymbol(TypeSyntax Syntax, INamedTypeSymbol Symbol);
record SyntaxSymbol(TypeSyntax Syntax, ITypeSymbol Symbol);

record SyntaxAttributeData(AttributeSyntax Syntax, AttributeData Data)
{
Expand Down
1 change: 1 addition & 0 deletions src/JsonRpc.Generators/GenerateHandlerMethodsGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ ReportCacheDiagnostic<TypeDeclarationSyntax> cacheDiagnostic
.Where(z => z.Alias == null)
.Select(z => z.Name.ToFullString())
)
.Except(new [] { "<global namespace>" }) // I think there is a better way... but for now..
.Distinct()
.Select(z => UsingDirective(IdentifierName(z)))
)
Expand Down
30 changes: 19 additions & 11 deletions src/JsonRpc.Generators/Helpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,21 +61,21 @@ public static SyntaxSymbol GetResponseType(TypeDeclarationSyntax syntax, INamedT
{ Identifier: { Text: "IRequest" }, Arity: 1 } => gns.TypeArgumentList.Arguments[0],
_ => null
},
SimpleNameSyntax and { Identifier: { Text: "IRequest" } } => ParseName("MediatR.Unit"),
SimpleNameSyntax and { Identifier: { Text: "IRequest" } } => ParseName("MediatR.Unit"),
SimpleNameSyntax and { Identifier: { Text: "IJsonRpcRequest" } } => ParseName("MediatR.Unit"),
_ => null
};
if (type != null) break;
}

if (type == null) throw new ArgumentException($"Response Type {symbol.ToDisplayString()} is not a name symbol", nameof(symbol));
if (type == null) throw new ArgumentException($"Response Syntax {syntax.ToString()} is not a name syntax", nameof(syntax));

var handlerInterface = symbol.AllInterfaces.FirstOrDefault(z => z.Name == "IRequestHandler" && z.TypeArguments.Length == 2);
if (handlerInterface?.TypeArguments[1] is INamedTypeSymbol ns)
return new SyntaxSymbol(type, ns);
if (handlerInterface?.TypeArguments[1] is INamedTypeSymbol || handlerInterface?.TypeArguments[1] is ITypeParameterSymbol)
return new SyntaxSymbol(type, handlerInterface.TypeArguments[1]);
handlerInterface = symbol.AllInterfaces.FirstOrDefault(z => z.Name == "IRequest" && z.Arity == 1);
if (handlerInterface?.TypeArguments[0] is INamedTypeSymbol ns2)
return new SyntaxSymbol(type, ns2);
if (handlerInterface?.TypeArguments[0] is INamedTypeSymbol || handlerInterface?.TypeArguments[0] is ITypeParameterSymbol)
return new SyntaxSymbol(type, handlerInterface.TypeArguments[0]);
throw new ArgumentException($"Response Type {symbol.ToDisplayString()} is not a name symbol", nameof(symbol));
}

Expand Down Expand Up @@ -103,11 +103,12 @@ public static SyntaxSymbol GetResponseType(TypeDeclarationSyntax syntax, INamedT
{ Identifier: { Text: "IJsonRpcRequestHandler" } } => gns.TypeArgumentList.Arguments[0],
{ Identifier: { Text: "IJsonRpcNotificationHandler" } } => gns.TypeArgumentList.Arguments[0],
{ Identifier: { Text: "ICanBeResolvedHandler" }, Arity: 1 } => gns.TypeArgumentList.Arguments[0],
{ Identifier: { Text: "IRequest" } } => ParseTypeName(syntax.Identifier.Text),
{ Identifier: { Text: "IJsonRpcRequest" } } => ParseTypeName(syntax.Identifier.Text),
{ Identifier: { Text: "IPartialItemRequest" }, Arity: 2 } => ParseTypeName(syntax.Identifier.Text),
{ Identifier: { Text: "IPartialItemsRequest" }, Arity: 2 } => ParseTypeName(syntax.Identifier.Text),
_ => null,
{ Identifier: { Text: "IRequest" }, Arity: 1 } => IdentifierName(syntax.Identifier.Text),
{ Identifier: { Text: "IRequest" }, Arity: 0 } => IdentifierName(syntax.Identifier.Text),
{ Identifier: { Text: "IJsonRpcRequest" } } => IdentifierName(syntax.Identifier.Text),
{ Identifier: { Text: "IPartialItemRequest" }, Arity: 2 } => IdentifierName(syntax.Identifier.Text),
{ Identifier: { Text: "IPartialItemsRequest" }, Arity: 2 } => IdentifierName(syntax.Identifier.Text),
_ => null,
},
_ => null,
};
Expand All @@ -116,6 +117,13 @@ public static SyntaxSymbol GetResponseType(TypeDeclarationSyntax syntax, INamedT
}

if (type == null) return null;
if (type is IdentifierNameSyntax ins && ins.Identifier.Text == syntax.Identifier.Text && syntax.TypeParameterList is { Parameters: { Count: > 0 } })
{
type = GenericName(syntax.Identifier.Text)
.WithTypeArgumentList(
TypeArgumentList(SeparatedList<TypeSyntax>(syntax.TypeParameterList?.Parameters.Select(z => IdentifierName(z.Identifier.Text))))
);
}

var handlerInterface = symbol.AllInterfaces
.FirstOrDefault(z => z.Name == "IRequestHandler" && z.TypeArguments.Length == 2);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public IEnumerable<MemberDeclarationSyntax> Apply(GeneratorData item)
}
);

var className = item.JsonRpcAttributes.HandlerName + "Extensions";
var className = item.JsonRpcAttributes.HandlerName + "Extensions" + ( item.TypeDeclaration.Arity == 0 ? "" : item.TypeDeclaration.Arity.ToString() );

var obsoleteAttribute = item.TypeDeclaration.AttributeLists
.SelectMany(z => z.Attributes)
Expand Down
18 changes: 16 additions & 2 deletions src/JsonRpc.Generators/Strategies/HandlerGeneratorStrategy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ public IEnumerable<MemberDeclarationSyntax> Apply(GeneratorData item)
.WithModifiers(item.TypeDeclaration.Modifiers)
.AddBaseListTypes(SimpleBaseType(GetBaseHandlerInterface(item)));

if (item is RequestItem { Response: { Symbol: ITypeParameterSymbol } } ri)
{
handlerInterface = handlerInterface.AddTypeParameterListParameters(TypeParameter(ri.Response.Symbol.Name));
}

if (item.Request.Symbol.AllInterfaces.Any(z => z.Name == "IDoesNotParticipateInRegistration"))
{
handlerInterface = handlerInterface.AddBaseListTypes(SimpleBaseType(IdentifierName("IDoesNotParticipateInRegistration")));
Expand All @@ -47,7 +52,7 @@ public IEnumerable<MemberDeclarationSyntax> Apply(GeneratorData item)
if (!handlerInterface.Modifiers.Any(z => z.IsKind(SyntaxKind.PartialKeyword)))
{
handlerInterface = handlerInterface.AddModifiers(Token(SyntaxKind.PartialKeyword));
}
}

if (item.JsonRpcAttributes.AllowDerivedRequests)
{
Expand Down Expand Up @@ -107,6 +112,7 @@ public IEnumerable<MemberDeclarationSyntax> Apply(GeneratorData item)
var baseClass = GetBaseHandlerClass(item);
var handlerClass = ClassDeclaration(Identifier($"{item.JsonRpcAttributes.HandlerName}HandlerBase"))
.WithAttributeLists(classAttributes)
.WithTypeParameterList(handlerInterface.TypeParameterList)
.AddModifiers(Token(SyntaxKind.AbstractKeyword))
.AddModifiers(handlerInterface.Modifiers.ToArray());
if (item.JsonRpcAttributes.AllowDerivedRequests)
Expand Down Expand Up @@ -170,7 +176,15 @@ public IEnumerable<MemberDeclarationSyntax> Apply(GeneratorData item)
}
else
{
handlerClass = handlerClass.AddBaseListTypes(SimpleBaseType(IdentifierName($"I{item.JsonRpcAttributes.HandlerName}Handler")));
handlerClass = handlerClass.AddBaseListTypes(
SimpleBaseType(
item is RequestItem { Response: { Symbol: ITypeParameterSymbol s } }
? GenericName($"I{item.JsonRpcAttributes.HandlerName}Handler").WithTypeArgumentList(
TypeArgumentList(SingletonSeparatedList<TypeSyntax>(IdentifierName(s.Name)))
)
: IdentifierName($"I{item.JsonRpcAttributes.HandlerName}Handler")
)
);
}

if (resolver is { })
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using OmniSharp.Extensions.JsonRpc.Generators.Contexts;
Expand Down Expand Up @@ -42,6 +43,12 @@ public IEnumerable<MemberDeclarationSyntax> Apply(ExtensionMethodContext extensi
resolve
)
);

if (item is RequestItem { Response: { Symbol: ITypeParameterSymbol } } ri)
{
method = method.AddTypeParameterListParameters(TypeParameter(ri.Response.Symbol.Name));
}

if (request.IsUnit)
{
method = method
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using OmniSharp.Extensions.JsonRpc.Generators.Contexts;
Expand Down Expand Up @@ -40,6 +41,11 @@ public IEnumerable<MemberDeclarationSyntax> Apply(ExtensionMethodContext extensi
.WithExpressionBody(GetRequestHandlerExpression(request, GetJsonRpcMethodName(extensionMethodContext.TypeDeclaration)))
.WithSemicolonToken(Token(SyntaxKind.SemicolonToken));

if (item is RequestItem { Response: { Symbol: ITypeParameterSymbol } } ri)
{
method = method.AddTypeParameterListParameters(TypeParameter(ri.Response.Symbol.Name));
}

var methodFactory = MakeFactory(extensionMethodContext.GetRegistryParameterList());

var factory = methodFactory(method);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using OmniSharp.Extensions.JsonRpc.Generators.Contexts;
Expand Down Expand Up @@ -57,6 +58,11 @@ public IEnumerable<MemberDeclarationSyntax> Apply(ExtensionMethodContext extensi
)
);

if (item is RequestItem { Response: { Symbol: ITypeParameterSymbol } } ri)
{
method = method.AddTypeParameterListParameters(TypeParameter(ri.Response.Symbol.Name));
}

var methodFactory = MakeFactory(
extensionMethodContext.GetRegistryParameterList(),
registrationOptions.Syntax,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using OmniSharp.Extensions.JsonRpc.Generators.Contexts;
Expand Down Expand Up @@ -52,6 +53,11 @@ public IEnumerable<MemberDeclarationSyntax> Apply(ExtensionMethodContext extensi
.WithExpressionBody(GetRequestHandlerExpression(request, GetJsonRpcMethodName(extensionMethodContext.TypeDeclaration)))
.WithSemicolonToken(Token(SyntaxKind.SemicolonToken));

if (item is RequestItem { Response: { Symbol: ITypeParameterSymbol } } ri)
{
method = method.AddTypeParameterListParameters(TypeParameter(ri.Response.Symbol.Name));
}

var methodFactory = MakeFactory(extensionMethodContext.GetRegistryParameterList());

var factory = methodFactory(method);
Expand Down
Loading

0 comments on commit 2055eaa

Please sign in to comment.