Skip to content

Commit b6c222e

Browse files
authored
Dotnet: Code generation for LSP methods (#222)
1 parent 5c4edc5 commit b6c222e

18 files changed

Lines changed: 184 additions & 43 deletions
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
using System;
2+
3+
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Enum)]
4+
public class DirectionAttribute : Attribute
5+
{
6+
public DirectionAttribute(MessageDirection direction)
7+
{
8+
Direction = direction;
9+
}
10+
11+
public MessageDirection Direction { get; }
12+
}

generator-plugins/dotnet/custom/ILSPResponse.cs

Lines changed: 0 additions & 9 deletions
This file was deleted.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
public interface ILSPMessage
1+
public interface IMessage
22
{
33
string JsonRPC { get; }
44
}

generator-plugins/dotnet/custom/ILSPNotification.cs renamed to generator-plugins/dotnet/custom/INotification.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
public interface ILSPNotification<TParams> : ILSPMessage
1+
public interface INotification<TParams> : IMessage
22
{
33
string Method { get; }
44

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
using System;
2+
3+
/// <summary>
4+
/// Interface to describe parameters for requests that support streaming results.
5+
///
6+
/// See the <see href="https://microsoft.github.io/language-server-protocol/specifications/specification-current/#partialResultParams">Language Server Protocol specification</see> for additional information.
7+
/// </summary>
8+
/// <typeparam name="T">The type to be reported by <see cref="PartialResultToken"/>.</typeparam>
9+
public interface IPartialResultParams
10+
{
11+
/// <summary>
12+
/// An optional token that a server can use to report partial results (e.g. streaming) to the client.
13+
/// </summary>
14+
public ProgressToken? PartialResultToken { get; set; }
15+
}

generator-plugins/dotnet/custom/ILSPRequest.cs renamed to generator-plugins/dotnet/custom/IRequest.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
public interface ILSPRequest<TParams> : ILSPMessage
1+
public interface IRequest<TParams> : IMessage
22
{
33

44
OrType<int, string> Id { get; }
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
public interface IResponse<TResponse> : IMessage
2+
{
3+
4+
OrType<int, string> Id { get; }
5+
6+
TResponse Result { get; }
7+
8+
IResponseError? Error { get; }
9+
}

generator-plugins/dotnet/custom/ILSPResponseError.cs renamed to generator-plugins/dotnet/custom/IResponseError.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
public interface ILSPResponseError
1+
public interface IResponseError
22
{
33

44
int Code { get; }
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
using System.Runtime.Serialization;
2+
3+
public enum MessageDirection
4+
{
5+
[EnumMember(Value = "serverToClient")] ServerToClient,
6+
[EnumMember(Value = "clientToServer")] ClientToServer,
7+
[EnumMember(Value = "both")] Both,
8+
}

generator-plugins/dotnet/dotnet_classes.py

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
get_special_case_property_name,
1818
get_usings,
1919
indent_lines,
20+
lsp_method_to_name,
2021
namespace_wrapper,
2122
to_camel_case,
2223
to_upper_camel_case,
@@ -182,14 +183,22 @@ def generate_property(
182183
)
183184
+ [
184185
f'[DataMember(Name = "{prop_def.name}")]',
185-
f"public {type_name}{optional} {name} {{ get; set; }}",
186186
]
187187
)
188+
189+
if prop_def.type.kind == "stringLiteral":
190+
lines.append(
191+
f'public {type_name}{optional} {name} {{ get; set; }} = "{prop_def.type.value}";'
192+
)
193+
else:
194+
lines.append(f"public {type_name}{optional} {name} {{ get; set; }}")
195+
188196
usings.append("DataMember")
189197
if converter:
190198
usings.append("JsonConverter")
191199
if optional and not special_optional:
192200
usings.append("JsonProperty")
201+
193202
return lines, type_name
194203

195204

@@ -247,7 +256,6 @@ def generate_literal_type(
247256
class_wrapper(literal, inner),
248257
)
249258
types.add_type_info(literal, literal.name, lines)
250-
print(f"{name_context} => {literal.name}")
251259
return literal.name
252260

253261

@@ -436,7 +444,6 @@ def generate_class_from_variant_literals(
436444

437445
lines = generate_code_for_variant_struct(struct, spec, types)
438446
types.add_type_info(struct, struct.name, lines)
439-
print(f"{name_context} => {struct.name}")
440447
return struct.name
441448

442449

@@ -610,6 +617,46 @@ def get_all_properties(struct: model.Structure, spec) -> List[model.Structure]:
610617
return properties
611618

612619

620+
def generate_code_for_request(request: model.Request):
621+
lines = get_doc(request.documentation) + generate_extras(request)
622+
lines.append(
623+
f'public static string {lsp_method_to_name(request.method)} {{ get; }} = "{request.method}";'
624+
)
625+
return lines
626+
627+
628+
def generate_code_for_notification(notify: model.Notification):
629+
lines = get_doc(notify.documentation) + generate_extras(notify)
630+
lines.append(
631+
f'public static string {lsp_method_to_name(notify.method)} {{ get; }} = "{notify.method}";'
632+
)
633+
return lines
634+
635+
636+
def generate_request_notification_types(spec: model.LSPModel, types: TypeData):
637+
inner_lines = []
638+
for request in spec.requests:
639+
inner_lines += generate_code_for_request(request)
640+
641+
for notification in spec.notifications:
642+
inner_lines += generate_code_for_notification(notification)
643+
644+
lines = namespace_wrapper(
645+
NAMESPACE,
646+
get_usings(["System"]),
647+
["public static class LSPMethods", "{", *indent_lines(inner_lines), "}"],
648+
)
649+
enum_type = model.Enum(
650+
**{
651+
"name": "LSPMethods",
652+
"type": {"kind": "base", "name": "string"},
653+
"values": [],
654+
"documentation": "LSP methods as defined in the LSP spec",
655+
}
656+
)
657+
types.add_type_info(enum_type, "LSPMethods", lines)
658+
659+
613660
def generate_all_classes(spec: model.LSPModel, types: TypeData):
614661
for struct in spec.structures:
615662
generate_class_from_struct(struct, spec, types)
@@ -619,3 +666,5 @@ def generate_all_classes(spec: model.LSPModel, types: TypeData):
619666
generate_class_from_variant_type_alias(type_alias, spec, types)
620667
else:
621668
generate_class_from_type_alias(type_alias, spec, types)
669+
670+
generate_request_notification_types(spec, types)

0 commit comments

Comments
 (0)