From b90221b7eeb977ba342a731c89aace1c2f5c8281 Mon Sep 17 00:00:00 2001 From: Karthik Nadig Date: Tue, 23 May 2023 13:04:03 -0700 Subject: [PATCH 01/16] Add xunit test package --- tests/dotnet/lsprotocol_tests/UnitTest1.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 tests/dotnet/lsprotocol_tests/UnitTest1.cs diff --git a/tests/dotnet/lsprotocol_tests/UnitTest1.cs b/tests/dotnet/lsprotocol_tests/UnitTest1.cs new file mode 100644 index 0000000..7274052 --- /dev/null +++ b/tests/dotnet/lsprotocol_tests/UnitTest1.cs @@ -0,0 +1,10 @@ +namespace lsprotocol_tests; + +public class UnitTest1 +{ + [Fact] + public void Test1() + { + + } +} \ No newline at end of file From f22e72c1d4d72db92a6c5db571d543c68a88eaaa Mon Sep 17 00:00:00 2001 From: Karthik Nadig Date: Tue, 30 May 2023 14:18:22 -0700 Subject: [PATCH 02/16] Update test names --- tests/dotnet/lsprotocol_tests/UnitTest1.cs | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 tests/dotnet/lsprotocol_tests/UnitTest1.cs diff --git a/tests/dotnet/lsprotocol_tests/UnitTest1.cs b/tests/dotnet/lsprotocol_tests/UnitTest1.cs deleted file mode 100644 index 7274052..0000000 --- a/tests/dotnet/lsprotocol_tests/UnitTest1.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace lsprotocol_tests; - -public class UnitTest1 -{ - [Fact] - public void Test1() - { - - } -} \ No newline at end of file From 932bf74e6a926bb8530968b0fa46b72ce6a2aba9 Mon Sep 17 00:00:00 2001 From: Karthik Nadig Date: Mon, 12 Jun 2023 18:13:02 -0700 Subject: [PATCH 03/16] Cleanups --- generator-plugins/dotnet/dotnet_classes.py | 2 -- generator-plugins/dotnet/dotnet_helpers.py | 2 +- generator-plugins/dotnet/dotnet_utils.py | 4 ++++ 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/generator-plugins/dotnet/dotnet_classes.py b/generator-plugins/dotnet/dotnet_classes.py index 19bfa6b..b38812c 100644 --- a/generator-plugins/dotnet/dotnet_classes.py +++ b/generator-plugins/dotnet/dotnet_classes.py @@ -247,7 +247,6 @@ def generate_literal_type( class_wrapper(literal, inner), ) types.add_type_info(literal, literal.name, lines) - print(f"{name_context} => {literal.name}") return literal.name @@ -436,7 +435,6 @@ def generate_class_from_variant_literals( lines = generate_code_for_variant_struct(struct, spec, types) types.add_type_info(struct, struct.name, lines) - print(f"{name_context} => {struct.name}") return struct.name diff --git a/generator-plugins/dotnet/dotnet_helpers.py b/generator-plugins/dotnet/dotnet_helpers.py index f146a7f..dc182a2 100644 --- a/generator-plugins/dotnet/dotnet_helpers.py +++ b/generator-plugins/dotnet/dotnet_helpers.py @@ -166,4 +166,4 @@ def get_usings(types: List[str]) -> List[str]: if t in types: usings.append("using Newtonsoft.Json.Linq;") - return list(set(usings)) + return sorted(list(set(usings))) diff --git a/generator-plugins/dotnet/dotnet_utils.py b/generator-plugins/dotnet/dotnet_utils.py index c891d4b..af36b3d 100644 --- a/generator-plugins/dotnet/dotnet_utils.py +++ b/generator-plugins/dotnet/dotnet_utils.py @@ -1,6 +1,7 @@ # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. +import logging import os import pathlib import subprocess @@ -15,6 +16,8 @@ from .dotnet_helpers import namespace_wrapper from .dotnet_special_classes import generate_special_classes +LOGGER = logging.getLogger("dotnet") + def generate_from_spec(spec: model.LSPModel, output_dir: str) -> None: """Generate the code for the given spec.""" @@ -29,6 +32,7 @@ def generate_from_spec(spec: model.LSPModel, output_dir: str) -> None: "\n".join(lines), encoding="utf-8" ) + LOGGER.info("Running dotnet format") subprocess.run( ["dotnet", "format"], cwd=os.fspath(pathlib.Path(output_dir, PACKAGE_DIR_NAME)) ) From dda9aa2636c8bbf5484d5da47e31134fab83b90b Mon Sep 17 00:00:00 2001 From: Karthik Nadig Date: Mon, 12 Jun 2023 18:23:12 -0700 Subject: [PATCH 04/16] nox dotnet build --- noxfile.py | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/noxfile.py b/noxfile.py index 377814c..fb0a942 100644 --- a/noxfile.py +++ b/noxfile.py @@ -96,15 +96,7 @@ def _get_content(uri) -> str: MODEL = "https://raw.githubusercontent.com/microsoft/vscode-languageserver-node/main/protocol/metaModel.json" -@nox.session() -def build_lsp(session: nox.Session): - """Generate lsprotocol package from LSP model.""" - _generate_model(session) - - -@nox.session() -def update_lsp(session: nox.Session): - """Update the LSP model and generate the lsprotocol content.""" +def _download_models(session: nox.session): session.log("Downloading LSP model schema.") model_schema_text: str = _get_content(MODEL_SCHEMA) session.log("Downloading LSP model.") @@ -121,6 +113,18 @@ def update_lsp(session: nox.Session): json.dumps(json.loads(model_text), indent=4, ensure_ascii=False) + "\n", encoding="utf-8", ) + + +@nox.session() +def build_lsp(session: nox.Session): + """Generate lsprotocol package from LSP model.""" + _generate_model(session) + + +@nox.session() +def update_lsp(session: nox.Session): + """Update the LSP model and generate the lsprotocol content.""" + _download_models(session) _generate_model(session) @@ -211,3 +215,14 @@ def create_plugin(session: nox.Session): launch_json_path.write_text(json.dumps(launch_json, indent=4), encoding="utf-8") session.log(f"Created plugin {name}.") + + +@nox.session() +def update_dotnet(session: nox.Session): + """Update the dotnet code.""" + _download_models(session) + _install_requirements(session) + + session.run("python", "-m", "generator", "--plugin", "dotnet") + with session.chdir("./packages/dotnet/lsprotocol"): + session.run("dotnet", "build") From 064f97df51a61a9d4aba9996f2d6f80c364fd923 Mon Sep 17 00:00:00 2001 From: Karthik Nadig Date: Mon, 12 Jun 2023 19:20:14 -0700 Subject: [PATCH 05/16] Add extension support --- generator-plugins/dotnet/dotnet_utils.py | 1 + generator/__main__.py | 18 ++++++++++-------- generator/model.py | 16 ++++++++++++++-- 3 files changed, 25 insertions(+), 10 deletions(-) diff --git a/generator-plugins/dotnet/dotnet_utils.py b/generator-plugins/dotnet/dotnet_utils.py index af36b3d..51e8e91 100644 --- a/generator-plugins/dotnet/dotnet_utils.py +++ b/generator-plugins/dotnet/dotnet_utils.py @@ -24,6 +24,7 @@ def generate_from_spec(spec: model.LSPModel, output_dir: str) -> None: cleanup(output_dir) copy_custom_classes(output_dir) + LOGGER.info("Generating code in C#") types = TypeData() generate_package_code(spec, types) for name, lines in types.get_all(): diff --git a/generator/__main__.py b/generator/__main__.py index 7ae1ccd..90f11c7 100644 --- a/generator/__main__.py +++ b/generator/__main__.py @@ -42,6 +42,7 @@ def get_parser() -> argparse.ArgumentParser: "-m", help="Path to a model JSON file. By default uses packaged model file.", type=str, + nargs="*", ) parser.add_argument( "--plugin", @@ -68,15 +69,16 @@ def main(argv: Sequence[str]) -> None: schema = json.load(schema_file.open("rb")) if args.model: - model_file = pathlib.Path(args.model) + model_files = [pathlib.Path(m) for m in args.model] else: - model_file = ir.files("generator") / "lsp.json" + model_files = [ir.files("generator") / "lsp.json"] - LOGGER.info("Using model file %s", os.fspath(model_file)) - json_model = json.load(model_file.open("rb")) - - LOGGER.info("Validating model.") - jsonschema.validate(json_model, schema) + json_models = [] + for model_file in model_files: + LOGGER.info("Validating model file %s", os.fspath(model_file)) + json_model = json.load(model_file.open("rb")) + jsonschema.validate(json_model, schema) + json_models.append(json_model) plugins = args.plugin or [] @@ -99,7 +101,7 @@ def main(argv: Sequence[str]) -> None: # load model and generate types for each plugin to avoid # any conflicts between plugins. - spec: model.LSPModel = model.create_lsp_model(json_model) + spec: model.LSPModel = model.create_lsp_model(json_models) try: plugin_module = importlib.import_module(f"generator-plugins.{plugin}") diff --git a/generator/model.py b/generator/model.py index 2b8348f..abac69d 100644 --- a/generator/model.py +++ b/generator/model.py @@ -881,5 +881,17 @@ def get_inner_types(self) -> List[Type]: return types -def create_lsp_model(model: Dict[str, Any]) -> LSPModel: - return LSPModel(**model) +def create_lsp_model(models: List[Dict[str, Any]]) -> LSPModel: + if len(models) >= 1: + spec = LSPModel(**models[0]) + + if len(models) >= 2: + for model in models[1:]: + addition = LSPModel(**model) + spec.requests.extend(addition.requests) + spec.notifications.extend(addition.notifications) + spec.structures.extend(addition.structures) + spec.enumerations.extend(addition.enumerations) + spec.typeAliases.extend(addition.typeAliases) + + return spec From f3971e21238b94ca2df8b0dcf704f7947bb7ab7d Mon Sep 17 00:00:00 2001 From: Karthik Nadig Date: Tue, 20 Jun 2023 23:14:16 -0700 Subject: [PATCH 06/16] Rename base interfaces --- generator-plugins/dotnet/custom/ILSPResponse.cs | 9 --------- .../dotnet/custom/{ILSPMessage.cs => IMessage.cs} | 2 +- .../custom/{ILSPNotification.cs => INotification.cs} | 2 +- .../dotnet/custom/{ILSPRequest.cs => IRequest.cs} | 2 +- generator-plugins/dotnet/custom/IResponse.cs | 9 +++++++++ .../custom/{ILSPResponseError.cs => IResponseError.cs} | 2 +- 6 files changed, 13 insertions(+), 13 deletions(-) delete mode 100644 generator-plugins/dotnet/custom/ILSPResponse.cs rename generator-plugins/dotnet/custom/{ILSPMessage.cs => IMessage.cs} (51%) rename generator-plugins/dotnet/custom/{ILSPNotification.cs => INotification.cs} (51%) rename generator-plugins/dotnet/custom/{ILSPRequest.cs => IRequest.cs} (65%) create mode 100644 generator-plugins/dotnet/custom/IResponse.cs rename generator-plugins/dotnet/custom/{ILSPResponseError.cs => IResponseError.cs} (70%) diff --git a/generator-plugins/dotnet/custom/ILSPResponse.cs b/generator-plugins/dotnet/custom/ILSPResponse.cs deleted file mode 100644 index 6ad4ddd..0000000 --- a/generator-plugins/dotnet/custom/ILSPResponse.cs +++ /dev/null @@ -1,9 +0,0 @@ -public interface ILSPREsponse : ILSPMessage -{ - - OrType Id { get; } - - TResponse Result { get; } - - ILSPResponseError? Error { get; } -} \ No newline at end of file diff --git a/generator-plugins/dotnet/custom/ILSPMessage.cs b/generator-plugins/dotnet/custom/IMessage.cs similarity index 51% rename from generator-plugins/dotnet/custom/ILSPMessage.cs rename to generator-plugins/dotnet/custom/IMessage.cs index 61254ec..175c258 100644 --- a/generator-plugins/dotnet/custom/ILSPMessage.cs +++ b/generator-plugins/dotnet/custom/IMessage.cs @@ -1,4 +1,4 @@ -public interface ILSPMessage +public interface IMessage { string JsonRPC { get; } } \ No newline at end of file diff --git a/generator-plugins/dotnet/custom/ILSPNotification.cs b/generator-plugins/dotnet/custom/INotification.cs similarity index 51% rename from generator-plugins/dotnet/custom/ILSPNotification.cs rename to generator-plugins/dotnet/custom/INotification.cs index 7652626..b287767 100644 --- a/generator-plugins/dotnet/custom/ILSPNotification.cs +++ b/generator-plugins/dotnet/custom/INotification.cs @@ -1,4 +1,4 @@ -public interface ILSPNotification : ILSPMessage +public interface INotification : IMessage { string Method { get; } diff --git a/generator-plugins/dotnet/custom/ILSPRequest.cs b/generator-plugins/dotnet/custom/IRequest.cs similarity index 65% rename from generator-plugins/dotnet/custom/ILSPRequest.cs rename to generator-plugins/dotnet/custom/IRequest.cs index df2e67c..cf8fe7b 100644 --- a/generator-plugins/dotnet/custom/ILSPRequest.cs +++ b/generator-plugins/dotnet/custom/IRequest.cs @@ -1,4 +1,4 @@ -public interface ILSPRequest : ILSPMessage +public interface IRequest : IMessage { OrType Id { get; } diff --git a/generator-plugins/dotnet/custom/IResponse.cs b/generator-plugins/dotnet/custom/IResponse.cs new file mode 100644 index 0000000..9d34227 --- /dev/null +++ b/generator-plugins/dotnet/custom/IResponse.cs @@ -0,0 +1,9 @@ +public interface IResponse : IMessage +{ + + OrType Id { get; } + + TResponse Result { get; } + + IResponseError? Error { get; } +} \ No newline at end of file diff --git a/generator-plugins/dotnet/custom/ILSPResponseError.cs b/generator-plugins/dotnet/custom/IResponseError.cs similarity index 70% rename from generator-plugins/dotnet/custom/ILSPResponseError.cs rename to generator-plugins/dotnet/custom/IResponseError.cs index 66f2917..c21cf32 100644 --- a/generator-plugins/dotnet/custom/ILSPResponseError.cs +++ b/generator-plugins/dotnet/custom/IResponseError.cs @@ -1,4 +1,4 @@ -public interface ILSPResponseError +public interface IResponseError { int Code { get; } From a6b51135b17a8e09169ac90cc1583fe5e2fb5b48 Mon Sep 17 00:00:00 2001 From: Karthik Nadig Date: Tue, 20 Jun 2023 23:17:52 -0700 Subject: [PATCH 07/16] Add Direction attribute. --- generator-plugins/dotnet/custom/Direction.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 generator-plugins/dotnet/custom/Direction.cs diff --git a/generator-plugins/dotnet/custom/Direction.cs b/generator-plugins/dotnet/custom/Direction.cs new file mode 100644 index 0000000..757acd3 --- /dev/null +++ b/generator-plugins/dotnet/custom/Direction.cs @@ -0,0 +1,12 @@ +using System; + +[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Enum)] +public class DirectionAttribute : Attribute +{ + public DirectionAttribute(MessageDirection direction) + { + Direction = direction; + } + + public MessageDirection Direction { get; } +} \ No newline at end of file From 4415718c8f86bafca13d5d86022886ed192df177 Mon Sep 17 00:00:00 2001 From: Karthik Nadig Date: Wed, 21 Jun 2023 16:57:56 -0700 Subject: [PATCH 08/16] Tune LSPObject types --- generator-plugins/dotnet/dotnet_helpers.py | 4 ++++ generator-plugins/dotnet/dotnet_special_classes.py | 8 ++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/generator-plugins/dotnet/dotnet_helpers.py b/generator-plugins/dotnet/dotnet_helpers.py index dc182a2..b00a905 100644 --- a/generator-plugins/dotnet/dotnet_helpers.py +++ b/generator-plugins/dotnet/dotnet_helpers.py @@ -166,4 +166,8 @@ def get_usings(types: List[str]) -> List[str]: if t in types: usings.append("using Newtonsoft.Json.Linq;") + for t in ["List", "Dictionary"]: + if t in types: + usings.append("using System.Collections.Generic;") + return sorted(list(set(usings))) diff --git a/generator-plugins/dotnet/dotnet_special_classes.py b/generator-plugins/dotnet/dotnet_special_classes.py index 3b58bd6..150cf56 100644 --- a/generator-plugins/dotnet/dotnet_special_classes.py +++ b/generator-plugins/dotnet/dotnet_special_classes.py @@ -38,8 +38,8 @@ def generate_special_class( if type_def.name == "LSPObject": lines = namespace_wrapper( NAMESPACE, - get_usings(["JObject", "DataContract"]), - class_wrapper(type_def, [], "JObject"), + get_usings(["Dictionary", "DataContract"]), + class_wrapper(type_def, [], "Dictionary"), ) if type_def.name == "LSPAny": lines = namespace_wrapper( @@ -50,8 +50,8 @@ def generate_special_class( if type_def.name == "LSPArray": lines = namespace_wrapper( NAMESPACE, - get_usings(["JArray", "DataContract"]), - class_wrapper(type_def, [], "JArray"), + get_usings(["DataContract", "List"]), + class_wrapper(type_def, [], "List"), ) if type_def.name == "Pattern": From e76f33b8ba9feaed3840c5e934d3b72bfa96a0a5 Mon Sep 17 00:00:00 2001 From: Karthik Nadig Date: Wed, 21 Jun 2023 17:30:34 -0700 Subject: [PATCH 09/16] Add String Literal property support --- generator-plugins/dotnet/dotnet_classes.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/generator-plugins/dotnet/dotnet_classes.py b/generator-plugins/dotnet/dotnet_classes.py index b38812c..be9616f 100644 --- a/generator-plugins/dotnet/dotnet_classes.py +++ b/generator-plugins/dotnet/dotnet_classes.py @@ -182,14 +182,22 @@ def generate_property( ) + [ f'[DataMember(Name = "{prop_def.name}")]', - f"public {type_name}{optional} {name} {{ get; set; }}", ] ) + + if prop_def.type.kind == "stringLiteral": + lines.append( + f'public {type_name}{optional} {name} {{ get; set; }} = "{prop_def.type.value}";' + ) + else: + lines.append(f"public {type_name}{optional} {name} {{ get; set; }}") + usings.append("DataMember") if converter: usings.append("JsonConverter") if optional and not special_optional: usings.append("JsonProperty") + return lines, type_name From 8c118e09c4d0a74ac2ef91581d0128bf42536d42 Mon Sep 17 00:00:00 2001 From: Karthik Nadig Date: Wed, 21 Jun 2023 17:30:57 -0700 Subject: [PATCH 10/16] Add message direction type --- generator-plugins/dotnet/custom/MessageDirection.cs | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 generator-plugins/dotnet/custom/MessageDirection.cs diff --git a/generator-plugins/dotnet/custom/MessageDirection.cs b/generator-plugins/dotnet/custom/MessageDirection.cs new file mode 100644 index 0000000..22660ff --- /dev/null +++ b/generator-plugins/dotnet/custom/MessageDirection.cs @@ -0,0 +1,6 @@ +public enum MessageDirection +{ + ServerToClient = "serverToClient", + ClientToServer = "clientToServer", + Both = "both" +} \ No newline at end of file From be4dede7ed565c560cd46ee65810c9ba76342603 Mon Sep 17 00:00:00 2001 From: Karthik Nadig Date: Wed, 21 Jun 2023 17:31:45 -0700 Subject: [PATCH 11/16] Add streaming interface --- .../dotnet/custom/IPartialResultParams.cs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 generator-plugins/dotnet/custom/IPartialResultParams.cs diff --git a/generator-plugins/dotnet/custom/IPartialResultParams.cs b/generator-plugins/dotnet/custom/IPartialResultParams.cs new file mode 100644 index 0000000..ef90c3b --- /dev/null +++ b/generator-plugins/dotnet/custom/IPartialResultParams.cs @@ -0,0 +1,15 @@ +using System; + +/// +/// Interface to describe parameters for requests that support streaming results. +/// +/// See the Language Server Protocol specification for additional information. +/// +/// The type to be reported by . +public interface IPartialResultParams +{ + /// + /// An optional token that a server can use to report partial results (e.g. streaming) to the client. + /// + public ProgressToken? PartialResultToken { get; set; } +} \ No newline at end of file From 8660c59c4e378784211cab80c9c61f1fb1c5c7b8 Mon Sep 17 00:00:00 2001 From: Karthik Nadig Date: Wed, 21 Jun 2023 17:31:57 -0700 Subject: [PATCH 12/16] Tweak namespace --- generator-plugins/dotnet/dotnet_constants.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generator-plugins/dotnet/dotnet_constants.py b/generator-plugins/dotnet/dotnet_constants.py index dc892e8..f66c96b 100644 --- a/generator-plugins/dotnet/dotnet_constants.py +++ b/generator-plugins/dotnet/dotnet_constants.py @@ -1,5 +1,5 @@ # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. -NAMESPACE = "LSProtocol" +NAMESPACE = "Microsoft.LanguageServer.Protocol" PACKAGE_DIR_NAME = "lsprotocol" From 867bdd30ef33835ea216aa6a5c8c92e23770fb0b Mon Sep 17 00:00:00 2001 From: Karthik Nadig Date: Wed, 21 Jun 2023 17:46:38 -0700 Subject: [PATCH 13/16] Add LSP methods data --- generator-plugins/dotnet/dotnet_classes.py | 35 ++++++++++++++++++++++ generator-plugins/dotnet/dotnet_helpers.py | 7 +++++ 2 files changed, 42 insertions(+) diff --git a/generator-plugins/dotnet/dotnet_classes.py b/generator-plugins/dotnet/dotnet_classes.py index be9616f..e229566 100644 --- a/generator-plugins/dotnet/dotnet_classes.py +++ b/generator-plugins/dotnet/dotnet_classes.py @@ -17,6 +17,7 @@ get_special_case_property_name, get_usings, indent_lines, + lsp_method_to_name, namespace_wrapper, to_camel_case, to_upper_camel_case, @@ -616,6 +617,40 @@ def get_all_properties(struct: model.Structure, spec) -> List[model.Structure]: return properties +def generate_code_for_request( + request: model.Request, spec: model.LSPModel, types: TypeData +): + lines = get_doc(request.documentation) + generate_extras(request, spec, types) + lines.append(f'{lsp_method_to_name(request.method)} = "{request.method}";') + + +def generate_code_for_notification( + notification: model.Notification, spec: model.LSPModel, types: TypeData +): + lines = get_doc(notification.documentation) + generate_extras( + notification, spec, types + ) + lines.append( + f'{lsp_method_to_name(notification.method)} = "{notification.method}";' + ) + + +def generate_request_notification_types(spec: model.LSPModel, types: TypeData): + inner_lines = [] + for request in spec.requests: + inner_lines += generate_code_for_request(request, spec, types) + + for notification in spec.notifications: + inner_lines += generate_code_for_notification(notification, spec, types) + + lines = namespace_wrapper( + NAMESPACE, + get_usings(["System"]), + ["public enum LSPMethods{", *indent_lines(inner_lines), "}"], + ) + types.add_type_info(None, "LSPMethods", lines) + + def generate_all_classes(spec: model.LSPModel, types: TypeData): for struct in spec.structures: generate_class_from_struct(struct, spec, types) diff --git a/generator-plugins/dotnet/dotnet_helpers.py b/generator-plugins/dotnet/dotnet_helpers.py index b00a905..2eb1aa3 100644 --- a/generator-plugins/dotnet/dotnet_helpers.py +++ b/generator-plugins/dotnet/dotnet_helpers.py @@ -33,6 +33,13 @@ def to_upper_camel_case(name: str) -> str: return "".join([c.capitalize() for c in get_parts(name)]) +def lsp_method_to_name(method: str) -> str: + if method.startswith("$"): + method = method[1:] + method = method.replace("/", "_") + return to_upper_camel_case(method) + + def file_header() -> List[str]: return [ "// Copyright (c) Microsoft Corporation. All rights reserved.", From 9c88988e5c2004ffcc14331c0588bb842a1aaee6 Mon Sep 17 00:00:00 2001 From: Karthik Nadig Date: Wed, 21 Jun 2023 17:58:24 -0700 Subject: [PATCH 14/16] Fix build --- .../dotnet/custom/MessageDirection.cs | 8 +++++--- generator-plugins/dotnet/dotnet_classes.py | 2 +- generator-plugins/dotnet/dotnet_helpers.py | 14 +++++++++++++- tests/dotnet/lsprotocol_tests/Usings.cs | 2 +- 4 files changed, 20 insertions(+), 6 deletions(-) diff --git a/generator-plugins/dotnet/custom/MessageDirection.cs b/generator-plugins/dotnet/custom/MessageDirection.cs index 22660ff..a2792ff 100644 --- a/generator-plugins/dotnet/custom/MessageDirection.cs +++ b/generator-plugins/dotnet/custom/MessageDirection.cs @@ -1,6 +1,8 @@ +using System.Runtime.Serialization; + public enum MessageDirection { - ServerToClient = "serverToClient", - ClientToServer = "clientToServer", - Both = "both" + [EnumMember(Value = "serverToClient")] ServerToClient, + [EnumMember(Value = "clientToServer")] ClientToServer, + [EnumMember(Value = "both")] Both, } \ No newline at end of file diff --git a/generator-plugins/dotnet/dotnet_classes.py b/generator-plugins/dotnet/dotnet_classes.py index e229566..8ce0154 100644 --- a/generator-plugins/dotnet/dotnet_classes.py +++ b/generator-plugins/dotnet/dotnet_classes.py @@ -646,7 +646,7 @@ def generate_request_notification_types(spec: model.LSPModel, types: TypeData): lines = namespace_wrapper( NAMESPACE, get_usings(["System"]), - ["public enum LSPMethods{", *indent_lines(inner_lines), "}"], + ["public enum LSPMethods", "{", *indent_lines(inner_lines), "}"], ) types.add_type_info(None, "LSPMethods", lines) diff --git a/generator-plugins/dotnet/dotnet_helpers.py b/generator-plugins/dotnet/dotnet_helpers.py index 2eb1aa3..66df814 100644 --- a/generator-plugins/dotnet/dotnet_helpers.py +++ b/generator-plugins/dotnet/dotnet_helpers.py @@ -141,7 +141,13 @@ def get_deprecated(text: Optional[str]) -> Optional[str]: def generate_extras( type_def: Union[ - model.Enum, model.EnumItem, model.Property, model.TypeAlias, model.Structure + model.Enum, + model.EnumItem, + model.Property, + model.TypeAlias, + model.Structure, + model.Request, + model.Notification, ] ) -> List[str]: deprecated = get_deprecated(type_def.documentation) @@ -155,6 +161,12 @@ def generate_extras( if type_def.since: extras += [f'[Since("{cleanup_str(type_def.since)}")]'] + if hasattr(type_def, "messageDirection"): + if type_def.since: + extras += [ + f'[Direction("{to_upper_camel_case(type_def.messageDirection)}")]' + ] + return extras diff --git a/tests/dotnet/lsprotocol_tests/Usings.cs b/tests/dotnet/lsprotocol_tests/Usings.cs index bb2cbfe..0506652 100644 --- a/tests/dotnet/lsprotocol_tests/Usings.cs +++ b/tests/dotnet/lsprotocol_tests/Usings.cs @@ -1,2 +1,2 @@ global using Xunit; -global using LSProtocol; +global using Microsoft.LanguageServer.Protocol; From 2c23c7de9a400230260fc39196cc63a9c9ad94a4 Mon Sep 17 00:00:00 2001 From: Karthik Nadig Date: Wed, 21 Jun 2023 18:31:45 -0700 Subject: [PATCH 15/16] Fix build --- generator-plugins/dotnet/dotnet_special_classes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generator-plugins/dotnet/dotnet_special_classes.py b/generator-plugins/dotnet/dotnet_special_classes.py index 150cf56..bbc047f 100644 --- a/generator-plugins/dotnet/dotnet_special_classes.py +++ b/generator-plugins/dotnet/dotnet_special_classes.py @@ -39,7 +39,7 @@ def generate_special_class( lines = namespace_wrapper( NAMESPACE, get_usings(["Dictionary", "DataContract"]), - class_wrapper(type_def, [], "Dictionary"), + class_wrapper(type_def, [], "Dictionary"), ) if type_def.name == "LSPAny": lines = namespace_wrapper( From 9dbdc1fcaaeef013102c172d8f1900c05a289584 Mon Sep 17 00:00:00 2001 From: Karthik Nadig Date: Wed, 21 Jun 2023 19:04:16 -0700 Subject: [PATCH 16/16] More build fixes --- generator-plugins/dotnet/dotnet_classes.py | 40 +++++++++++++--------- generator-plugins/dotnet/dotnet_helpers.py | 2 +- 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/generator-plugins/dotnet/dotnet_classes.py b/generator-plugins/dotnet/dotnet_classes.py index 8ce0154..6443931 100644 --- a/generator-plugins/dotnet/dotnet_classes.py +++ b/generator-plugins/dotnet/dotnet_classes.py @@ -617,38 +617,44 @@ def get_all_properties(struct: model.Structure, spec) -> List[model.Structure]: return properties -def generate_code_for_request( - request: model.Request, spec: model.LSPModel, types: TypeData -): - lines = get_doc(request.documentation) + generate_extras(request, spec, types) - lines.append(f'{lsp_method_to_name(request.method)} = "{request.method}";') +def generate_code_for_request(request: model.Request): + lines = get_doc(request.documentation) + generate_extras(request) + lines.append( + f'public static string {lsp_method_to_name(request.method)} {{ get; }} = "{request.method}";' + ) + return lines -def generate_code_for_notification( - notification: model.Notification, spec: model.LSPModel, types: TypeData -): - lines = get_doc(notification.documentation) + generate_extras( - notification, spec, types - ) +def generate_code_for_notification(notify: model.Notification): + lines = get_doc(notify.documentation) + generate_extras(notify) lines.append( - f'{lsp_method_to_name(notification.method)} = "{notification.method}";' + f'public static string {lsp_method_to_name(notify.method)} {{ get; }} = "{notify.method}";' ) + return lines def generate_request_notification_types(spec: model.LSPModel, types: TypeData): inner_lines = [] for request in spec.requests: - inner_lines += generate_code_for_request(request, spec, types) + inner_lines += generate_code_for_request(request) for notification in spec.notifications: - inner_lines += generate_code_for_notification(notification, spec, types) + inner_lines += generate_code_for_notification(notification) lines = namespace_wrapper( NAMESPACE, get_usings(["System"]), - ["public enum LSPMethods", "{", *indent_lines(inner_lines), "}"], + ["public static class LSPMethods", "{", *indent_lines(inner_lines), "}"], ) - types.add_type_info(None, "LSPMethods", lines) + enum_type = model.Enum( + **{ + "name": "LSPMethods", + "type": {"kind": "base", "name": "string"}, + "values": [], + "documentation": "LSP methods as defined in the LSP spec", + } + ) + types.add_type_info(enum_type, "LSPMethods", lines) def generate_all_classes(spec: model.LSPModel, types: TypeData): @@ -660,3 +666,5 @@ def generate_all_classes(spec: model.LSPModel, types: TypeData): generate_class_from_variant_type_alias(type_alias, spec, types) else: generate_class_from_type_alias(type_alias, spec, types) + + generate_request_notification_types(spec, types) diff --git a/generator-plugins/dotnet/dotnet_helpers.py b/generator-plugins/dotnet/dotnet_helpers.py index 66df814..6da6ca0 100644 --- a/generator-plugins/dotnet/dotnet_helpers.py +++ b/generator-plugins/dotnet/dotnet_helpers.py @@ -164,7 +164,7 @@ def generate_extras( if hasattr(type_def, "messageDirection"): if type_def.since: extras += [ - f'[Direction("{to_upper_camel_case(type_def.messageDirection)}")]' + f"[Direction(MessageDirection.{to_upper_camel_case(type_def.messageDirection)})]" ] return extras