diff options
Diffstat (limited to 'generator/plugins/dotnet/custom')
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 |