summaryrefslogtreecommitdiffstats
path: root/generator/plugins/dotnet/custom
diff options
context:
space:
mode:
Diffstat (limited to 'generator/plugins/dotnet/custom')
-rw-r--r--generator/plugins/dotnet/custom/CustomArrayConverter.cs42
-rw-r--r--generator/plugins/dotnet/custom/CustomObjectConverter.cs40
-rw-r--r--generator/plugins/dotnet/custom/CustomStringConverter.cs40
-rw-r--r--generator/plugins/dotnet/custom/Direction.cs12
-rw-r--r--generator/plugins/dotnet/custom/DocumentSelectorConverter.cs34
-rw-r--r--generator/plugins/dotnet/custom/IMessage.cs4
-rw-r--r--generator/plugins/dotnet/custom/INotification.cs6
-rw-r--r--generator/plugins/dotnet/custom/IOrType.cs4
-rw-r--r--generator/plugins/dotnet/custom/IPartialResultParams.cs15
-rw-r--r--generator/plugins/dotnet/custom/IRequest.cs9
-rw-r--r--generator/plugins/dotnet/custom/IResponse.cs9
-rw-r--r--generator/plugins/dotnet/custom/LSPAnyConverter.cs61
-rw-r--r--generator/plugins/dotnet/custom/LSPRequest.cs22
-rw-r--r--generator/plugins/dotnet/custom/LSPResponse.cs13
-rw-r--r--generator/plugins/dotnet/custom/MessageDirection.cs8
-rw-r--r--generator/plugins/dotnet/custom/OrType.cs138
-rw-r--r--generator/plugins/dotnet/custom/OrTypeArrayConverter.cs145
-rw-r--r--generator/plugins/dotnet/custom/OrTypeConverter.cs595
-rw-r--r--generator/plugins/dotnet/custom/Proposed.cs17
-rw-r--r--generator/plugins/dotnet/custom/ResponseError.cs27
-rw-r--r--generator/plugins/dotnet/custom/Since.cs17
-rw-r--r--generator/plugins/dotnet/custom/Validators.cs20
22 files changed, 1278 insertions, 0 deletions
diff --git a/generator/plugins/dotnet/custom/CustomArrayConverter.cs b/generator/plugins/dotnet/custom/CustomArrayConverter.cs
new file mode 100644
index 0000000..d34eb62
--- /dev/null
+++ b/generator/plugins/dotnet/custom/CustomArrayConverter.cs
@@ -0,0 +1,42 @@
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using System.Collections.Immutable;
+
+public class CustomArrayConverter<T> : JsonConverter<ImmutableArray<T>>
+{
+ public override ImmutableArray<T> ReadJson(JsonReader reader, Type objectType, ImmutableArray<T> existingValue, bool hasExistingValue, JsonSerializer serializer)
+ {
+ if (reader.TokenType == JsonToken.Null)
+ {
+ return default(ImmutableArray<T>);
+ }
+
+ JArray array = JArray.Load(reader);
+ ImmutableArray<T>.Builder builder = ImmutableArray.CreateBuilder<T>();
+
+ for (int i = 0; i < array.Count; i++)
+ {
+ builder.Add((T)array[i].ToObject(typeof(T))!);
+ }
+
+ return builder.ToImmutable();
+
+ }
+
+ public override void WriteJson(JsonWriter writer, ImmutableArray<T> value, JsonSerializer serializer)
+ {
+ if (value.IsDefault)
+ {
+ writer.WriteNull();
+ }
+ else
+ {
+ writer.WriteStartArray();
+ foreach (var item in value)
+ {
+ serializer.Serialize(writer, item);
+ }
+ writer.WriteEndArray();
+ }
+ }
+} \ No newline at end of file
diff --git a/generator/plugins/dotnet/custom/CustomObjectConverter.cs b/generator/plugins/dotnet/custom/CustomObjectConverter.cs
new file mode 100644
index 0000000..e03b588
--- /dev/null
+++ b/generator/plugins/dotnet/custom/CustomObjectConverter.cs
@@ -0,0 +1,40 @@
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using System;
+
+
+class CustomObjectConverter<T> : JsonConverter<T> where T : Dictionary<string, object?>
+{
+ public override T ReadJson(JsonReader reader, Type objectType, T? existingValue, bool hasExistingValue, JsonSerializer serializer)
+ {
+ if (reader.TokenType == JsonToken.Null)
+ {
+ return default(T)!;
+ }
+
+ Dictionary<string, object?>? o = serializer.Deserialize<Dictionary<string, object?>>(reader);
+ if (o == null)
+ {
+ return default(T)!;
+ }
+ return (T)Activator.CreateInstance(typeof(T), o)! ?? default(T)!;
+ }
+
+ public override void WriteJson(JsonWriter writer, T? value, JsonSerializer serializer)
+ {
+ if (value is null)
+ {
+ writer.WriteNull();
+ }
+ else
+ {
+ writer.WriteStartObject();
+ foreach (var kvp in value)
+ {
+ writer.WritePropertyName(kvp.Key);
+ serializer.Serialize(writer, kvp.Value);
+ }
+ writer.WriteEndObject();
+ }
+ }
+} \ No newline at end of file
diff --git a/generator/plugins/dotnet/custom/CustomStringConverter.cs b/generator/plugins/dotnet/custom/CustomStringConverter.cs
new file mode 100644
index 0000000..33a04df
--- /dev/null
+++ b/generator/plugins/dotnet/custom/CustomStringConverter.cs
@@ -0,0 +1,40 @@
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using System;
+
+public class CustomStringConverter<T> : JsonConverter<T> where T : class
+{
+ public override T? ReadJson(JsonReader reader, Type objectType, T? existingValue, bool hasExistingValue, JsonSerializer serializer)
+ {
+ if (reader.TokenType == JsonToken.String && reader.Value is string str)
+ {
+ return Activator.CreateInstance(typeof(T), str) as T;
+ }
+ else if (reader.TokenType == JsonToken.Null)
+ {
+ return null;
+ }
+
+ throw new JsonSerializationException($"Unexpected token type '{reader.TokenType}' while deserializing '{objectType.Name}'.");
+ }
+
+ public override void WriteJson(JsonWriter writer, T? value, JsonSerializer serializer)
+ {
+ if (value is null)
+ {
+ writer.WriteNull();
+ }
+ else if (value is Uri u)
+ {
+ writer.WriteValue(u.AbsoluteUri);
+ }
+ else if (value is T t)
+ {
+ writer.WriteValue(t.ToString());
+ }
+ else
+ {
+ throw new ArgumentException($"{nameof(value)} must be of type {nameof(T)}.");
+ }
+ }
+}
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
diff --git a/generator/plugins/dotnet/custom/DocumentSelectorConverter.cs b/generator/plugins/dotnet/custom/DocumentSelectorConverter.cs
new file mode 100644
index 0000000..3124416
--- /dev/null
+++ b/generator/plugins/dotnet/custom/DocumentSelectorConverter.cs
@@ -0,0 +1,34 @@
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using System;
+
+public class DocumentSelectorConverter : JsonConverter<DocumentSelector>
+{
+ public override void WriteJson(JsonWriter writer, DocumentSelector? value, JsonSerializer serializer)
+ {
+ if (value is null)
+ {
+ writer.WriteNull();
+ }
+ else
+ {
+ serializer.Serialize(writer, (DocumentFilter[])value);
+ }
+ }
+
+ public override DocumentSelector ReadJson(JsonReader reader, Type objectType, DocumentSelector? existingValue, bool hasExistingValue, JsonSerializer serializer)
+ {
+ if (reader.TokenType == JsonToken.Null)
+ {
+ return null!;
+ }
+ var token = JToken.Load(reader);
+ if (token.Type == JTokenType.Array)
+ {
+ var filters = token.ToObject<DocumentFilter[]>(serializer);
+ return new DocumentSelector(filters ?? Array.Empty<DocumentFilter>());
+ }
+
+ throw new JsonSerializationException("Invalid JSON for DocumentSelector");
+ }
+}
diff --git a/generator/plugins/dotnet/custom/IMessage.cs b/generator/plugins/dotnet/custom/IMessage.cs
new file mode 100644
index 0000000..175c258
--- /dev/null
+++ b/generator/plugins/dotnet/custom/IMessage.cs
@@ -0,0 +1,4 @@
+public interface IMessage
+{
+ string JsonRPC { get; }
+} \ No newline at end of file
diff --git a/generator/plugins/dotnet/custom/INotification.cs b/generator/plugins/dotnet/custom/INotification.cs
new file mode 100644
index 0000000..b287767
--- /dev/null
+++ b/generator/plugins/dotnet/custom/INotification.cs
@@ -0,0 +1,6 @@
+public interface INotification<TParams> : IMessage
+{
+ string Method { get; }
+
+ TParams? Params { get; }
+} \ No newline at end of file
diff --git a/generator/plugins/dotnet/custom/IOrType.cs b/generator/plugins/dotnet/custom/IOrType.cs
new file mode 100644
index 0000000..217b64a
--- /dev/null
+++ b/generator/plugins/dotnet/custom/IOrType.cs
@@ -0,0 +1,4 @@
+public interface IOrType
+{
+ public object? Value { get; }
+} \ No newline at end of file
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;
+
+/// <summary>
+/// Interface to describe parameters for requests that support streaming results.
+///
+/// See the <see href="https://microsoft.github.io/language-server-protocol/specifications/specification-current/#partialResultParams">Language Server Protocol specification</see> for additional information.
+/// </summary>
+/// <typeparam name="T">The type to be reported by <see cref="PartialResultToken"/>.</typeparam>
+public interface IPartialResultParams
+{
+ /// <summary>
+ /// An optional token that a server can use to report partial results (e.g. streaming) to the client.
+ /// </summary>
+ public ProgressToken? PartialResultToken { get; set; }
+} \ No newline at end of file
diff --git a/generator/plugins/dotnet/custom/IRequest.cs b/generator/plugins/dotnet/custom/IRequest.cs
new file mode 100644
index 0000000..55fcbd8
--- /dev/null
+++ b/generator/plugins/dotnet/custom/IRequest.cs
@@ -0,0 +1,9 @@
+public interface IRequest<TParams> : IMessage
+{
+
+ OrType<string, int> Id { get; }
+
+ string Method { get; }
+
+ TParams Params { get; }
+} \ No newline at end of file
diff --git a/generator/plugins/dotnet/custom/IResponse.cs b/generator/plugins/dotnet/custom/IResponse.cs
new file mode 100644
index 0000000..01ecf3e
--- /dev/null
+++ b/generator/plugins/dotnet/custom/IResponse.cs
@@ -0,0 +1,9 @@
+public interface IResponse<TResponse> : IMessage
+{
+
+ OrType<string, int> Id { get; }
+
+ TResponse? Result { get; }
+
+ ResponseError? Error { get; }
+} \ No newline at end of file
diff --git a/generator/plugins/dotnet/custom/LSPAnyConverter.cs b/generator/plugins/dotnet/custom/LSPAnyConverter.cs
new file mode 100644
index 0000000..28781cb
--- /dev/null
+++ b/generator/plugins/dotnet/custom/LSPAnyConverter.cs
@@ -0,0 +1,61 @@
+using Newtonsoft.Json;
+
+public class LSPAnyConverter : JsonConverter
+{
+ public override bool CanConvert(Type objectType)
+ {
+ return objectType == typeof(LSPAny);
+ }
+
+ public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer)
+ {
+ reader = reader ?? throw new ArgumentNullException(nameof(reader));
+ switch (reader.TokenType)
+ {
+ case JsonToken.Null:
+ return null;
+
+ case JsonToken.Integer:
+ return new LSPAny(serializer.Deserialize<long>(reader));
+
+ case JsonToken.Float:
+ return new LSPAny(serializer.Deserialize<float>(reader));
+
+ case JsonToken.Boolean:
+ return new LSPAny(serializer.Deserialize<bool>(reader));
+
+ case JsonToken.String:
+ return new LSPAny(serializer.Deserialize<string>(reader));
+
+ case JsonToken.StartArray:
+ List<object>? l = serializer.Deserialize<List<object>>(reader);
+ if (l == null)
+ {
+ return null;
+ }
+ return new LSPAny(new LSPArray(l));
+
+ case JsonToken.StartObject:
+ Dictionary<string, object?>? o = serializer.Deserialize<Dictionary<string, object?>>(reader);
+ if (o == null)
+ {
+ return null;
+ }
+ return new LSPAny(new LSPObject(o));
+ }
+
+ throw new JsonSerializationException($"Unexpected token type '{reader.TokenType}' while deserializing '{objectType.Name}'.");
+ }
+
+ public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
+ {
+ if (value is null)
+ {
+ writer.WriteNull();
+ }
+ else
+ {
+ serializer.Serialize(writer, ((LSPAny)value).Value);
+ }
+ }
+} \ No newline at end of file
diff --git a/generator/plugins/dotnet/custom/LSPRequest.cs b/generator/plugins/dotnet/custom/LSPRequest.cs
new file mode 100644
index 0000000..69e3f0d
--- /dev/null
+++ b/generator/plugins/dotnet/custom/LSPRequest.cs
@@ -0,0 +1,22 @@
+using System;
+
+[AttributeUsage(AttributeTargets.Class)]
+public class LSPRequestAttribute : Attribute
+{
+ public LSPRequestAttribute(string method, Type response)
+ {
+ Method = method;
+ Response = response;
+ }
+
+ public LSPRequestAttribute(string method, Type response, Type partialResponse)
+ {
+ Method = method;
+ Response = response;
+ PartialResponse = partialResponse;
+ }
+
+ public string Method { get; }
+ public Type Response { get; }
+ public Type? PartialResponse { get; }
+} \ No newline at end of file
diff --git a/generator/plugins/dotnet/custom/LSPResponse.cs b/generator/plugins/dotnet/custom/LSPResponse.cs
new file mode 100644
index 0000000..4d2ca46
--- /dev/null
+++ b/generator/plugins/dotnet/custom/LSPResponse.cs
@@ -0,0 +1,13 @@
+using System;
+
+[AttributeUsage(AttributeTargets.Class)]
+public class LSPResponseAttribute : Attribute
+{
+ public LSPResponseAttribute(Type request)
+ {
+ Request = request;
+ }
+
+
+ public Type Request { get; }
+} \ No newline at end of file
diff --git a/generator/plugins/dotnet/custom/MessageDirection.cs b/generator/plugins/dotnet/custom/MessageDirection.cs
new file mode 100644
index 0000000..a2792ff
--- /dev/null
+++ b/generator/plugins/dotnet/custom/MessageDirection.cs
@@ -0,0 +1,8 @@
+using System.Runtime.Serialization;
+
+public enum MessageDirection
+{
+ [EnumMember(Value = "serverToClient")] ServerToClient,
+ [EnumMember(Value = "clientToServer")] ClientToServer,
+ [EnumMember(Value = "both")] Both,
+} \ No newline at end of file
diff --git a/generator/plugins/dotnet/custom/OrType.cs b/generator/plugins/dotnet/custom/OrType.cs
new file mode 100644
index 0000000..2ddf320
--- /dev/null
+++ b/generator/plugins/dotnet/custom/OrType.cs
@@ -0,0 +1,138 @@
+using System;
+
+public record OrType<T, U> : IOrType
+{
+ public object? Value { get; }
+ public OrType(T t)
+ {
+ Value = t ?? throw new ArgumentNullException(nameof(t));
+ }
+
+ public OrType(U u)
+ {
+ Value = u ?? throw new ArgumentNullException(nameof(u));
+ }
+
+ public static explicit operator U?(OrType<T, U> obj)
+ {
+ return obj.Value is U x ? x : default;
+ }
+
+ public static explicit operator T?(OrType<T, U> obj)
+ {
+ return obj.Value is T x ? x : default;
+ }
+
+ public static explicit operator OrType<T, U>(U obj) => obj is null ? null! : new OrType<T, U>(obj);
+ public static explicit operator OrType<T, U>(T obj) => obj is null ? null! : new OrType<T, U>(obj);
+
+ public override string ToString()
+ {
+ return Value?.ToString()!;
+ }
+}
+
+public record OrType<T, U, V> : IOrType
+{
+ public object? Value { get; }
+
+ public OrType(T t)
+ {
+ Value = t ?? throw new ArgumentNullException(nameof(t));
+ }
+
+ public OrType(U u)
+ {
+ Value = u ?? throw new ArgumentNullException(nameof(u));
+ }
+
+ public OrType(V v)
+ {
+ Value = v ?? throw new ArgumentNullException(nameof(v));
+ }
+
+ public static explicit operator U?(OrType<T, U, V> obj)
+ {
+ return obj.Value is U x ? x : default;
+ }
+
+ public static explicit operator T?(OrType<T, U, V> obj)
+ {
+ return obj.Value is T x ? x : default;
+ }
+
+ public static explicit operator V?(OrType<T, U, V> obj)
+ {
+ return obj.Value is V x ? x : default;
+ }
+
+ public static explicit operator OrType<T, U, V>(U obj) => obj is null ? null! : new OrType<T, U, V>(obj);
+
+ public static explicit operator OrType<T, U, V>(T obj) => obj is null ? null! : new OrType<T, U, V>(obj);
+
+ public static explicit operator OrType<T, U, V>(V obj) => obj is null ? null! : new OrType<T, U, V>(obj);
+
+ public override string ToString()
+ {
+ return Value?.ToString()!;
+ }
+}
+
+
+public record OrType<T, U, V, W> : IOrType
+{
+ public object? Value { get; }
+
+ public OrType(T t)
+ {
+ Value = t ?? throw new ArgumentNullException(nameof(t));
+ }
+
+ public OrType(U u)
+ {
+ Value = u ?? throw new ArgumentNullException(nameof(u));
+ }
+
+ public OrType(V v)
+ {
+ Value = v ?? throw new ArgumentNullException(nameof(v));
+ }
+
+ public OrType(W w)
+ {
+ Value = w ?? throw new ArgumentNullException(nameof(w));
+ }
+
+ public static explicit operator U?(OrType<T, U, V, W> obj)
+ {
+ return obj.Value is U x ? x : default;
+ }
+
+ public static explicit operator T?(OrType<T, U, V, W> obj)
+ {
+ return obj.Value is T x ? x : default;
+ }
+
+ public static explicit operator V?(OrType<T, U, V, W> obj)
+ {
+ return obj.Value is V x ? x : default;
+ }
+
+ public static explicit operator W?(OrType<T, U, V, W> obj)
+ {
+ return obj.Value is W x ? x : default;
+ }
+
+ public static explicit operator OrType<T, U, V, W>(U obj) => obj is null ? null! : new OrType<T, U, V, W>(obj);
+
+ public static explicit operator OrType<T, U, V, W>(T obj) => obj is null ? null! : new OrType<T, U, V, W>(obj);
+
+ public static explicit operator OrType<T, U, V, W>(V obj) => obj is null ? null! : new OrType<T, U, V, W>(obj);
+
+ public static explicit operator OrType<T, U, V, W>(W obj) => obj is null ? null! : new OrType<T, U, V, W>(obj);
+
+ public override string ToString()
+ {
+ return Value?.ToString()!;
+ }
+}
diff --git a/generator/plugins/dotnet/custom/OrTypeArrayConverter.cs b/generator/plugins/dotnet/custom/OrTypeArrayConverter.cs
new file mode 100644
index 0000000..f2dbf23
--- /dev/null
+++ b/generator/plugins/dotnet/custom/OrTypeArrayConverter.cs
@@ -0,0 +1,145 @@
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using System;
+using System.Collections.Immutable;
+
+public class OrTypeArrayConverter<T, U> : JsonConverter<ImmutableArray<OrType<T, U>>>
+{
+ private OrTypeConverter<T, U> _converter;
+
+ public OrTypeArrayConverter()
+ {
+ _converter = new OrTypeConverter<T, U>();
+ }
+
+ public override ImmutableArray<OrType<T, U>> ReadJson(JsonReader reader, Type objectType, ImmutableArray<OrType<T, U>> existingValue, bool hasExistingValue, JsonSerializer serializer)
+ {
+ if (reader.TokenType == JsonToken.Null)
+ {
+ return default(ImmutableArray<OrType<T, U>>);
+ }
+
+ JArray array = JArray.Load(reader);
+ ImmutableArray<OrType<T, U>>.Builder builder = ImmutableArray.CreateBuilder<OrType<T, U>>();
+
+ for (int i = 0; i < array.Count; i++)
+ {
+ builder.Add((OrType<T, U>)_converter.ReadJson(array[i].CreateReader(), typeof(OrType<T, U>), null, serializer)!);
+ }
+
+ return builder.ToImmutable();
+ }
+
+ public override void WriteJson(JsonWriter writer, ImmutableArray<OrType<T, U>> value, JsonSerializer serializer)
+ {
+ if (value.IsDefault)
+ {
+ writer.WriteNull();
+ }
+ else
+ {
+ writer.WriteStartArray();
+
+ foreach (var item in value)
+ {
+ _converter.WriteJson(writer, item, serializer);
+ }
+
+ writer.WriteEndArray();
+ }
+ }
+}
+public class OrTypeArrayConverter<T, U, V> : JsonConverter<ImmutableArray<OrType<T, U, V>>>
+{
+ private OrTypeConverter<T, U, V> _converter;
+
+ public OrTypeArrayConverter()
+ {
+ _converter = new OrTypeConverter<T, U, V>();
+ }
+
+ public override ImmutableArray<OrType<T, U, V>> ReadJson(JsonReader reader, Type objectType, ImmutableArray<OrType<T, U, V>> existingValue, bool hasExistingValue, JsonSerializer serializer)
+ {
+ if (reader.TokenType == JsonToken.Null)
+ {
+ return default(ImmutableArray<OrType<T, U, V>>);
+ }
+
+ JArray array = JArray.Load(reader);
+ ImmutableArray<OrType<T, U, V>>.Builder builder = ImmutableArray.CreateBuilder<OrType<T, U, V>>();
+
+ for (int i = 0; i < array.Count; i++)
+ {
+ builder.Add((OrType<T, U, V>)_converter.ReadJson(array[i].CreateReader(), typeof(OrType<T, U, V>), null, serializer)!);
+ }
+
+ return builder.ToImmutable();
+ }
+
+ public override void WriteJson(JsonWriter writer, ImmutableArray<OrType<T, U, V>> value, JsonSerializer serializer)
+ {
+ if (value.IsDefault)
+ {
+ writer.WriteNull();
+ }
+ else
+ {
+ writer.WriteStartArray();
+
+ foreach (var item in value)
+ {
+ _converter.WriteJson(writer, item, serializer);
+ }
+
+ writer.WriteEndArray();
+ }
+ }
+}
+
+
+public class OrTypeArrayConverter<T, U, V, W> : JsonConverter<ImmutableArray<OrType<T, U, V, W>>>
+{
+ private OrTypeConverter<T, U, V, W> _converter;
+
+ public OrTypeArrayConverter()
+ {
+ _converter = new OrTypeConverter<T, U, V, W>();
+ }
+
+ public override ImmutableArray<OrType<T, U, V, W>> ReadJson(JsonReader reader, Type objectType, ImmutableArray<OrType<T, U, V, W>> existingValue, bool hasExistingValue, JsonSerializer serializer)
+ {
+ if (reader.TokenType == JsonToken.Null)
+ {
+ return default(ImmutableArray<OrType<T, U, V, W>>);
+ }
+
+ JArray array = JArray.Load(reader);
+ ImmutableArray<OrType<T, U, V, W>>.Builder builder = ImmutableArray.CreateBuilder<OrType<T, U, V, W>>();
+
+ for (int i = 0; i < array.Count; i++)
+ {
+ builder.Add((OrType<T, U, V, W>)_converter.ReadJson(array[i].CreateReader(), typeof(OrType<T, U, V, W>), null, serializer)!);
+ }
+
+ return builder.ToImmutable();
+ }
+
+ public override void WriteJson(JsonWriter writer, ImmutableArray<OrType<T, U, V, W>> value, JsonSerializer serializer)
+ {
+ if (value.IsDefault)
+ {
+ writer.WriteNull();
+ }
+ else
+ {
+ writer.WriteStartArray();
+
+ foreach (var item in value)
+ {
+ _converter.WriteJson(writer, item, serializer);
+ }
+
+ writer.WriteEndArray();
+ }
+ }
+} \ No newline at end of file
diff --git a/generator/plugins/dotnet/custom/OrTypeConverter.cs b/generator/plugins/dotnet/custom/OrTypeConverter.cs
new file mode 100644
index 0000000..f2aadbf
--- /dev/null
+++ b/generator/plugins/dotnet/custom/OrTypeConverter.cs
@@ -0,0 +1,595 @@
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+internal class OrTypeConverterHelpers
+{
+ public static Type[] SortTypesByHeuristic(Type[] types, JToken jToken)
+ {
+ var typePropertyScores = new Dictionary<Type, int>();
+
+ string[] jTokenPropertyNames = jToken.Children<JProperty>().Select(p => p.Name.ToUpper()).ToArray();
+
+ foreach (Type type in types)
+ {
+ string[] typePropertyNames = type.GetProperties().Select(p => p.Name.ToUpper()).ToArray();
+
+ int score = jTokenPropertyNames.Count(propertyName => typePropertyNames.Contains(propertyName));
+ typePropertyScores[type] = score;
+ }
+
+ return types.OrderByDescending(type => typePropertyScores[type]).ToArray();
+ }
+}
+
+public class OrTypeConverter<T, U> : JsonConverter<OrType<T, U>>
+{
+ public override OrType<T, U>? ReadJson(JsonReader reader, Type objectType, OrType<T, U>? existingValue, bool hasExistingValue, JsonSerializer serializer)
+ {
+ reader = reader ?? throw new ArgumentNullException(nameof(reader));
+
+ if (reader.TokenType == JsonToken.Null)
+ {
+ return null;
+ }
+
+ Type[] types = new Type[] { typeof(T), typeof(U) };
+
+ if (reader.TokenType == JsonToken.Integer && (Validators.HasType(types, typeof(uint)) || Validators.HasType(types, typeof(int))))
+ {
+ return ReadIntegerToken(reader, serializer, types);
+ }
+ if (reader.TokenType == JsonToken.Float && Validators.HasType(types, typeof(float)))
+ {
+ return ReadFloatToken(reader, serializer, types);
+ }
+ if (reader.TokenType == JsonToken.Boolean && Validators.HasType(types, typeof(bool)))
+ {
+ return ReadBooleanToken(reader, serializer, types);
+ }
+ if (reader.TokenType == JsonToken.String && Validators.HasType(types, typeof(string)))
+ {
+ return ReadStringToken(reader, serializer, types);
+ }
+
+ var token = JToken.Load(reader);
+ return OrTypeConverter<T, U>.ReadObjectToken(token, serializer, OrTypeConverterHelpers.SortTypesByHeuristic(types, token));
+ }
+
+ private static OrType<T, U> ReadIntegerToken(JsonReader reader, JsonSerializer serializer, Type[] types)
+ {
+ long integer = serializer.Deserialize<long>(reader);
+ if (Validators.InUIntegerRange(integer) && Validators.HasType(types, typeof(uint)))
+ {
+ if (typeof(T) == typeof(uint))
+ {
+ return new OrType<T, U>((T)(object)(uint)integer);
+ }
+ if (typeof(U) == typeof(uint))
+ {
+ return new OrType<T, U>((U)(object)(uint)integer);
+ }
+ }
+ if (Validators.InIntegerRange(integer) && Validators.HasType(types, typeof(int)))
+ {
+ if (typeof(T) == typeof(int))
+ {
+ return new OrType<T, U>((T)(object)(int)integer);
+ }
+ if (typeof(U) == typeof(int))
+ {
+ return new OrType<T, U>((U)(object)(int)integer);
+ }
+ }
+ throw new ArgumentOutOfRangeException($"Integer out-of-range of LSP Signed Integer[{int.MinValue}:{int.MaxValue}] and out-of-range of LSP Unsigned Integer [{uint.MinValue}:{uint.MaxValue}] => {integer}");
+ }
+
+ private static OrType<T, U> ReadFloatToken(JsonReader reader, JsonSerializer serializer, Type[] types)
+ {
+ float real = serializer.Deserialize<float>(reader);
+ if (typeof(T) == typeof(float))
+ {
+ return new OrType<T, U>((T)(object)real);
+ }
+ if (typeof(U) == typeof(float))
+ {
+ return new OrType<T, U>((U)(object)real);
+ }
+ throw new InvalidOperationException("Invalid token type for float");
+ }
+
+ private static OrType<T, U> ReadBooleanToken(JsonReader reader, JsonSerializer serializer, Type[] types)
+ {
+ bool boolean = serializer.Deserialize<bool>(reader);
+ if (typeof(T) == typeof(bool))
+ {
+ return new OrType<T, U>((T)(object)boolean);
+ }
+ if (typeof(U) == typeof(bool))
+ {
+ return new OrType<T, U>((U)(object)boolean);
+ }
+ throw new InvalidOperationException("Invalid token type for boolean");
+ }
+
+ private static OrType<T, U> ReadStringToken(JsonReader reader, JsonSerializer serializer, Type[] types)
+ {
+ string str = serializer.Deserialize<string>(reader)!;
+ if (typeof(T) == typeof(string))
+ {
+ return new OrType<T, U>((T)(object)str);
+ }
+ if (typeof(U) == typeof(string))
+ {
+ return new OrType<T, U>((U)(object)str);
+ }
+ throw new InvalidOperationException("Invalid token type for string");
+ }
+
+ private static OrType<T, U> ReadObjectToken(JToken token, JsonSerializer serializer, Type[] types)
+ {
+ var exceptions = new List<Exception>();
+ foreach (Type type in types)
+ {
+ try
+ {
+ object? value = null;
+ if (token.Type == JTokenType.Array && type == typeof((uint, uint)))
+ {
+ uint[]? o = token.ToObject<uint[]>(serializer);
+ if (o != null)
+ {
+ value = (o[0], o[1]);
+ }
+ }
+ else
+ {
+ value = token.ToObject(type, serializer);
+ }
+
+ if (value != null)
+ {
+ if (value is T t)
+ {
+ return new OrType<T, U>(t);
+ }
+ if (value is U u)
+ {
+ return new OrType<T, U>(u);
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ exceptions.Add(ex);
+ continue;
+ }
+ }
+
+ throw new JsonSerializationException("Unable to deserialize object", new AggregateException(exceptions));
+ }
+
+
+
+ public override void WriteJson(JsonWriter writer, OrType<T, U>? value, JsonSerializer serializer)
+ {
+ if (value is null)
+ {
+ writer.WriteNull();
+ }
+ else if (value?.Value?.GetType() == typeof((uint, uint)))
+ {
+ ValueTuple<uint, uint> o = (ValueTuple<uint, uint>)(value.Value);
+ serializer.Serialize(writer, new uint[] { o.Item1, o.Item2 });
+ }
+ else
+ {
+ serializer.Serialize(writer, value?.Value);
+ }
+ }
+}
+
+public class OrTypeConverter<T, U, V> : JsonConverter<OrType<T, U, V>>
+{
+ public override OrType<T, U, V>? ReadJson(JsonReader reader, Type objectType, OrType<T, U, V>? existingValue, bool hasExistingValue, JsonSerializer serializer)
+ {
+ reader = reader ?? throw new ArgumentNullException(nameof(reader));
+
+ if (reader.TokenType == JsonToken.Null)
+ {
+ return null;
+ }
+
+ Type[] types = new Type[] { typeof(T), typeof(U), typeof(V) };
+
+ if (reader.TokenType == JsonToken.Integer && (Validators.HasType(types, typeof(uint)) || Validators.HasType(types, typeof(int))))
+ {
+ return ReadIntegerToken(reader, serializer, types);
+ }
+ if (reader.TokenType == JsonToken.Float && Validators.HasType(types, typeof(float)))
+ {
+ return ReadFloatToken(reader, serializer, types);
+ }
+ if (reader.TokenType == JsonToken.Boolean && Validators.HasType(types, typeof(bool)))
+ {
+ return ReadBooleanToken(reader, serializer, types);
+ }
+ if (reader.TokenType == JsonToken.String && Validators.HasType(types, typeof(string)))
+ {
+ return ReadStringToken(reader, serializer, types);
+ }
+
+ var token = JToken.Load(reader);
+ return OrTypeConverter<T, U, V>.ReadObjectToken(token, serializer, OrTypeConverterHelpers.SortTypesByHeuristic(types, token));
+ }
+
+ private static OrType<T, U, V> ReadIntegerToken(JsonReader reader, JsonSerializer serializer, Type[] types)
+ {
+ long integer = serializer.Deserialize<long>(reader);
+ if (Validators.InUIntegerRange(integer) && Validators.HasType(types, typeof(uint)))
+ {
+ if (typeof(T) == typeof(uint))
+ {
+ return new OrType<T, U, V>((T)(object)(uint)integer);
+ }
+ if (typeof(U) == typeof(uint))
+ {
+ return new OrType<T, U, V>((U)(object)(uint)integer);
+ }
+ if (typeof(V) == typeof(uint))
+ {
+ return new OrType<T, U, V>((V)(object)(uint)integer);
+ }
+ }
+ if (Validators.InIntegerRange(integer) && Validators.HasType(types, typeof(int)))
+ {
+ if (typeof(T) == typeof(int))
+ {
+ return new OrType<T, U, V>((T)(object)(int)integer);
+ }
+ if (typeof(U) == typeof(int))
+ {
+ return new OrType<T, U, V>((U)(object)(int)integer);
+ }
+ if (typeof(V) == typeof(int))
+ {
+ return new OrType<T, U, V>((V)(object)(int)integer);
+ }
+ }
+ throw new ArgumentOutOfRangeException($"Integer out-of-range of LSP Signed Integer[{int.MinValue}:{int.MaxValue}] and out-of-range of LSP Unsigned Integer [{uint.MinValue}:{uint.MaxValue}] => {integer}");
+ }
+
+ private static OrType<T, U, V> ReadFloatToken(JsonReader reader, JsonSerializer serializer, Type[] types)
+ {
+ float real = serializer.Deserialize<float>(reader);
+ if (typeof(T) == typeof(float))
+ {
+ return new OrType<T, U, V>((T)(object)real);
+ }
+ if (typeof(U) == typeof(float))
+ {
+ return new OrType<T, U, V>((U)(object)real);
+ }
+ if (typeof(V) == typeof(float))
+ {
+ return new OrType<T, U, V>((V)(object)real);
+ }
+ throw new InvalidOperationException("Invalid token type for float");
+ }
+
+ private static OrType<T, U, V> ReadBooleanToken(JsonReader reader, JsonSerializer serializer, Type[] types)
+ {
+ bool boolean = serializer.Deserialize<bool>(reader);
+ if (typeof(T) == typeof(bool))
+ {
+ return new OrType<T, U, V>((T)(object)boolean);
+ }
+ if (typeof(U) == typeof(bool))
+ {
+ return new OrType<T, U, V>((U)(object)boolean);
+ }
+ if (typeof(V) == typeof(bool))
+ {
+ return new OrType<T, U, V>((V)(object)boolean);
+ }
+ throw new InvalidOperationException("Invalid token type for boolean");
+ }
+
+ private static OrType<T, U, V> ReadStringToken(JsonReader reader, JsonSerializer serializer, Type[] types)
+ {
+ string str = serializer.Deserialize<string>(reader)!;
+ if (typeof(T) == typeof(string))
+ {
+ return new OrType<T, U, V>((T)(object)str);
+ }
+ if (typeof(U) == typeof(string))
+ {
+ return new OrType<T, U, V>((U)(object)str);
+ }
+ if (typeof(V) == typeof(string))
+ {
+ return new OrType<T, U, V>((V)(object)str);
+ }
+ throw new InvalidOperationException("Invalid token type for string");
+ }
+
+ private static OrType<T, U, V> ReadObjectToken(JToken token, JsonSerializer serializer, Type[] types)
+ {
+ var exceptions = new List<Exception>();
+ foreach (Type type in types)
+ {
+ try
+ {
+ object? value = null;
+ if (token.Type == JTokenType.Array && type == typeof((uint, uint)))
+ {
+ uint[]? o = token.ToObject<uint[]>(serializer);
+ if (o != null)
+ {
+ value = (o[0], o[1]);
+ }
+ }
+ else
+ {
+ value = token.ToObject(type, serializer);
+ }
+
+ if (value != null)
+ {
+ if (value is T t)
+ {
+ return new OrType<T, U, V>(t);
+ }
+ if (value is U u)
+ {
+ return new OrType<T, U, V>(u);
+ }
+ if (value is V v)
+ {
+ return new OrType<T, U, V>(v);
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ exceptions.Add(ex);
+ continue;
+ }
+ }
+
+ throw new JsonSerializationException("Unable to deserialize object", new AggregateException(exceptions));
+ }
+
+ public override void WriteJson(JsonWriter writer, OrType<T, U, V>? value, JsonSerializer serializer)
+ {
+ if (value is null)
+ {
+ writer.WriteNull();
+ }
+ else if (value?.Value?.GetType() == typeof((uint, uint)))
+ {
+ ValueTuple<uint, uint> o = (ValueTuple<uint, uint>)(value.Value);
+ serializer.Serialize(writer, new uint[] { o.Item1, o.Item2 });
+ }
+ else
+ {
+ serializer.Serialize(writer, value?.Value);
+ }
+ }
+}
+
+public class OrTypeConverter<T, U, V, W> : JsonConverter<OrType<T, U, V, W>>
+{
+ public override OrType<T, U, V, W>? ReadJson(JsonReader reader, Type objectType, OrType<T, U, V, W>? existingValue, bool hasExistingValue, JsonSerializer serializer)
+ {
+ reader = reader ?? throw new ArgumentNullException(nameof(reader));
+
+ if (reader.TokenType == JsonToken.Null)
+ {
+ return null;
+ }
+
+ Type[] types = new Type[] { typeof(T), typeof(U), typeof(V), typeof(W) };
+
+ if (reader.TokenType == JsonToken.Integer && (Validators.HasType(types, typeof(uint)) || Validators.HasType(types, typeof(int))))
+ {
+ return ReadIntegerToken(reader, serializer, types);
+ }
+ if (reader.TokenType == JsonToken.Float && Validators.HasType(types, typeof(float)))
+ {
+ return ReadFloatToken(reader, serializer, types);
+ }
+ if (reader.TokenType == JsonToken.Boolean && Validators.HasType(types, typeof(bool)))
+ {
+ return ReadBooleanToken(reader, serializer, types);
+ }
+ if (reader.TokenType == JsonToken.String && Validators.HasType(types, typeof(string)))
+ {
+ return ReadStringToken(reader, serializer, types);
+ }
+
+ var token = JToken.Load(reader);
+ return OrTypeConverter<T, U, V, W>.ReadObjectToken(token, serializer, OrTypeConverterHelpers.SortTypesByHeuristic(types, token));
+ }
+
+ private static OrType<T, U, V, W> ReadIntegerToken(JsonReader reader, JsonSerializer serializer, Type[] types)
+ {
+ long integer = serializer.Deserialize<long>(reader);
+ if (Validators.InUIntegerRange(integer) && Validators.HasType(types, typeof(uint)))
+ {
+ if (typeof(T) == typeof(uint))
+ {
+ return new OrType<T, U, V, W>((T)(object)(uint)integer);
+ }
+ if (typeof(U) == typeof(uint))
+ {
+ return new OrType<T, U, V, W>((U)(object)(uint)integer);
+ }
+ if (typeof(V) == typeof(uint))
+ {
+ return new OrType<T, U, V, W>((V)(object)(uint)integer);
+ }
+ if (typeof(W) == typeof(uint))
+ {
+ return new OrType<T, U, V, W>((W)(object)(uint)integer);
+ }
+ }
+ if (Validators.InIntegerRange(integer) && Validators.HasType(types, typeof(int)))
+ {
+ if (typeof(T) == typeof(int))
+ {
+ return new OrType<T, U, V, W>((T)(object)(int)integer);
+ }
+ if (typeof(U) == typeof(int))
+ {
+ return new OrType<T, U, V, W>((U)(object)(int)integer);
+ }
+ if (typeof(V) == typeof(int))
+ {
+ return new OrType<T, U, V, W>((V)(object)(int)integer);
+ }
+ if (typeof(W) == typeof(int))
+ {
+ return new OrType<T, U, V, W>((W)(object)(int)integer);
+ }
+ }
+ throw new ArgumentOutOfRangeException($"Integer out-of-range of LSP Signed Integer[{int.MinValue}:{int.MaxValue}] and out-of-range of LSP Unsigned Integer [{uint.MinValue}:{uint.MaxValue}] => {integer}");
+ }
+
+ private static OrType<T, U, V, W> ReadFloatToken(JsonReader reader, JsonSerializer serializer, Type[] types)
+ {
+ float real = serializer.Deserialize<float>(reader);
+ if (typeof(T) == typeof(float))
+ {
+ return new OrType<T, U, V, W>((T)(object)real);
+ }
+ if (typeof(U) == typeof(float))
+ {
+ return new OrType<T, U, V, W>((U)(object)real);
+ }
+ if (typeof(V) == typeof(float))
+ {
+ return new OrType<T, U, V, W>((V)(object)real);
+ }
+ if (typeof(W) == typeof(float))
+ {
+ return new OrType<T, U, V, W>((W)(object)real);
+ }
+ throw new InvalidOperationException("Invalid token type for float");
+ }
+
+ private static OrType<T, U, V, W> ReadBooleanToken(JsonReader reader, JsonSerializer serializer, Type[] types)
+ {
+ bool boolean = serializer.Deserialize<bool>(reader);
+ if (typeof(T) == typeof(bool))
+ {
+ return new OrType<T, U, V, W>((T)(object)boolean);
+ }
+ if (typeof(U) == typeof(bool))
+ {
+ return new OrType<T, U, V, W>((U)(object)boolean);
+ }
+ if (typeof(V) == typeof(bool))
+ {
+ return new OrType<T, U, V, W>((V)(object)boolean);
+ }
+ if (typeof(W) == typeof(bool))
+ {
+ return new OrType<T, U, V, W>((W)(object)boolean);
+ }
+ throw new InvalidOperationException("Invalid token type for boolean");
+ }
+
+ private static OrType<T, U, V, W> ReadStringToken(JsonReader reader, JsonSerializer serializer, Type[] types)
+ {
+ string str = serializer.Deserialize<string>(reader)!;
+ if (typeof(T) == typeof(string))
+ {
+ return new OrType<T, U, V, W>((T)(object)str);
+ }
+ if (typeof(U) == typeof(string))
+ {
+ return new OrType<T, U, V, W>((U)(object)str);
+ }
+ if (typeof(V) == typeof(string))
+ {
+ return new OrType<T, U, V, W>((V)(object)str);
+ }
+ if (typeof(W) == typeof(string))
+ {
+ return new OrType<T, U, V, W>((W)(object)str);
+ }
+ throw new InvalidOperationException("Invalid token type for string");
+ }
+
+ private static OrType<T, U, V, W> ReadObjectToken(JToken token, JsonSerializer serializer, Type[] types)
+ {
+ var exceptions = new List<Exception>();
+ foreach (Type type in types)
+ {
+ try
+ {
+ object? value = null;
+ if (token.Type == JTokenType.Array && type == typeof((uint, uint)))
+ {
+ uint[]? o = token.ToObject<uint[]>(serializer);
+ if (o != null)
+ {
+ value = (o[0], o[1]);
+ }
+ }
+ else
+ {
+ value = token.ToObject(type, serializer);
+ }
+
+ if (value != null)
+ {
+ if (value is T t)
+ {
+ return new OrType<T, U, V, W>(t);
+ }
+ if (value is U u)
+ {
+ return new OrType<T, U, V, W>(u);
+ }
+ if (value is V v)
+ {
+ return new OrType<T, U, V, W>(v);
+ }
+ if (value is W w)
+ {
+ return new OrType<T, U, V, W>(w);
+ }
+ }
+
+ }
+ catch (Exception ex)
+ {
+ exceptions.Add(ex);
+ continue;
+ }
+ }
+
+ throw new JsonSerializationException("Unable to deserialize object", new AggregateException(exceptions));
+ }
+
+ public override void WriteJson(JsonWriter writer, OrType<T, U, V, W>? value, JsonSerializer serializer)
+ {
+ if (value is null)
+ {
+ writer.WriteNull();
+ }
+ else if (value?.Value?.GetType() == typeof((uint, uint)))
+ {
+ ValueTuple<uint, uint> o = (ValueTuple<uint, uint>)(value.Value);
+ serializer.Serialize(writer, new uint[] { o.Item1, o.Item2 });
+ }
+ else
+ {
+ serializer.Serialize(writer, value?.Value);
+ }
+ }
+} \ No newline at end of file
diff --git a/generator/plugins/dotnet/custom/Proposed.cs b/generator/plugins/dotnet/custom/Proposed.cs
new file mode 100644
index 0000000..eb0ed75
--- /dev/null
+++ b/generator/plugins/dotnet/custom/Proposed.cs
@@ -0,0 +1,17 @@
+using System;
+
+[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Enum)]
+public class ProposedAttribute : Attribute
+{
+ public ProposedAttribute()
+ {
+ Version = null;
+ }
+
+ public ProposedAttribute(string version)
+ {
+ Version = version;
+ }
+
+ public string? Version { get; }
+} \ No newline at end of file
diff --git a/generator/plugins/dotnet/custom/ResponseError.cs b/generator/plugins/dotnet/custom/ResponseError.cs
new file mode 100644
index 0000000..5151783
--- /dev/null
+++ b/generator/plugins/dotnet/custom/ResponseError.cs
@@ -0,0 +1,27 @@
+using Newtonsoft.Json;
+using System.Runtime.Serialization;
+
+[DataContract]
+public class ResponseError
+{
+ [JsonConstructor]
+ public ResponseError(
+ int code,
+ string message,
+ LSPObject? data = null
+ )
+ {
+ Code = code;
+ Message = message;
+ Data = data;
+ }
+
+ [DataMember(Name = "code")]
+ int Code { get; }
+
+ [DataMember(Name = "message")]
+ string Message { get; }
+
+ [DataMember(Name = "data")]
+ LSPObject? Data { get; }
+} \ No newline at end of file
diff --git a/generator/plugins/dotnet/custom/Since.cs b/generator/plugins/dotnet/custom/Since.cs
new file mode 100644
index 0000000..b13da74
--- /dev/null
+++ b/generator/plugins/dotnet/custom/Since.cs
@@ -0,0 +1,17 @@
+using System;
+
+[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Enum | AttributeTargets.Interface)]
+public class SinceAttribute : Attribute
+{
+ public SinceAttribute()
+ {
+ Version = null;
+ }
+
+ public SinceAttribute(string version)
+ {
+ Version = version;
+ }
+
+ public string? Version { get; }
+} \ No newline at end of file
diff --git a/generator/plugins/dotnet/custom/Validators.cs b/generator/plugins/dotnet/custom/Validators.cs
new file mode 100644
index 0000000..9edc18f
--- /dev/null
+++ b/generator/plugins/dotnet/custom/Validators.cs
@@ -0,0 +1,20 @@
+
+using System;
+
+public static class Validators
+{
+ public static bool HasType(Type[] types, Type type)
+ {
+ return types.Contains(type);
+ }
+
+ public static bool InIntegerRange(long value)
+ {
+ return value >= int.MinValue && value <= int.MaxValue;
+ }
+
+ public static bool InUIntegerRange(long value)
+ {
+ return value >= uint.MinValue && value <= uint.MaxValue;
+ }
+} \ No newline at end of file