Skip to content
This repository was archived by the owner on Dec 22, 2021. It is now read-only.

Commit

Permalink
Merge pull request #6 from matarillo/develop
Browse files Browse the repository at this point in the history
v3.0.0
  • Loading branch information
matarillo authored Aug 26, 2018
2 parents 799af83 + bd8cffd commit 3aba16a
Show file tree
Hide file tree
Showing 33 changed files with 502 additions and 426 deletions.
156 changes: 114 additions & 42 deletions LanguageServer/Infrastructure/JsonDotNet/EitherConverter.cs
Original file line number Diff line number Diff line change
@@ -1,74 +1,146 @@
using LanguageServer.Json;
using Newtonsoft.Json;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Reflection;
using LanguageServer.Json;
using LanguageServer.Parameters;
using LanguageServer.Parameters.General;
using LanguageServer.Parameters.TextDocument;

namespace LanguageServer.Infrastructure.JsonDotNet
{
internal class EitherConverter : JsonConverter
public class EitherConverter : JsonConverter
{
private readonly Dictionary<Type, Func<JToken, object>> table;

public EitherConverter()
{
table = new Dictionary<Type, Func<JToken, object>>();
table[typeof(NumberOrString)] = token => (object)ToNumberOrString(token);
table[typeof(LocationSingleOrArray)] = token => (object)ToLocationSingleOrArray(token);
table[typeof(TextDocumentSync)] = token => (object)ToTextDocumentSync(token);
table[typeof(CompletionResult)] = token => (object)ToCompletionResult(token);
table[typeof(HoverContents)] = token => (object)ToHoverContents(token);
}

public override bool CanConvert(Type objectType)
{
return typeof(IEither).GetTypeInfo().IsAssignableFrom(objectType.GetTypeInfo());
return typeof(Either).GetTypeInfo().IsAssignableFrom(objectType.GetTypeInfo());
}

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var convert = table[objectType] ??
throw new NotImplementedException($"Could not deserialize '{objectType.FullName}'.");
var token = JToken.Load(reader);
return convert(token);
}

private static JsonDataType Convert(JsonToken token)
#region Deserialization

private NumberOrString ToNumberOrString(JToken token)
{
switch (token)
switch (token.Type)
{
case JsonToken.Null:
return JsonDataType.Null;
case JsonToken.Boolean:
return JsonDataType.Boolean;
case JsonToken.Float:
return JsonDataType.Number;
case JsonToken.Integer:
return JsonDataType.Number;
case JsonToken.String:
return JsonDataType.String;
case JsonToken.StartArray:
return JsonDataType.Array;
case JsonToken.StartObject:
return JsonDataType.Object;
case JTokenType.Null:
return null;
case JTokenType.Integer:
return new NumberOrString(token.ToObject<long>());
case JTokenType.String:
return new NumberOrString(token.ToObject<string>());
default:
return default(JsonDataType);
throw new JsonSerializationException();
}
}

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
private LocationSingleOrArray ToLocationSingleOrArray(JToken token)
{
var either = Activator.CreateInstance(objectType) as IEither;
var jsonType = Convert(reader.TokenType);
var tag = either.OnDeserializing(jsonType);
if (tag == EitherTag.Left)
switch (token.Type)
{
var left = serializer.Deserialize(reader, either.LeftType);
either.Left = left;
return either;
case JTokenType.Null:
return null;
case JTokenType.Object:
return new LocationSingleOrArray(token.ToObject<Location>());
case JTokenType.Array:
return new LocationSingleOrArray(token.ToObject<Location[]>());
default:
throw new JsonSerializationException();
}
else if (tag == EitherTag.Right)
}

private TextDocumentSync ToTextDocumentSync(JToken token)
{
switch (token.Type)
{
var right = serializer.Deserialize(reader, either.RightType);
either.Right = right;
return either;
case JTokenType.Null:
return null;
case JTokenType.Integer:
return new TextDocumentSync(token.ToObject<TextDocumentSyncKind>());
case JTokenType.Object:
return new TextDocumentSync(token.ToObject<TextDocumentSyncOptions>());
default:
throw new JsonSerializationException();
}
return null;
}

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
private CompletionResult ToCompletionResult(JToken token)
{
var either = value as IEither;
if (either == null)
switch (token.Type)
{
return;
case JTokenType.Null:
return null;
case JTokenType.Array:
return new CompletionResult(token.ToObject<CompletionItem[]>());
case JTokenType.Object:
return new CompletionResult(token.ToObject<CompletionList>());
default:
throw new JsonSerializationException();
}
var objectValue = (either.IsLeft) ? either.Left : (either.IsRight) ? either.Right : null;
if (objectValue == null)
}

private HoverContents ToHoverContents(JToken token)
{
switch (token.Type)
{
return;
case JTokenType.Null:
return null;
case JTokenType.String:
return new HoverContents(token.ToObject<string>());
case JTokenType.Object:
return new HoverContents(token.ToObject<MarkedString>());
case JTokenType.Array:
var array = (JArray) token;
if (array.Count == 0)
{
return new HoverContents(new string[0]);
}

var element = (array[0] as JObject) ?? throw new JsonSerializationException();
if (element.Type == JTokenType.String)
{
return new HoverContents(array.ToObject<string[]>());
}
else if (element.Type == JTokenType.Object)
{
return new HoverContents(array.ToObject<MarkedString[]>());
}
else
{
throw new JsonSerializationException();
}

default:
throw new JsonSerializationException();
}
JToken.FromObject(objectValue, serializer).WriteTo(writer);
}

#endregion

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var either = (Either)value;
serializer.Serialize(writer, either?.Value);
}
}
}
35 changes: 0 additions & 35 deletions LanguageServer/Json/ArrayOrObject.cs

This file was deleted.

82 changes: 24 additions & 58 deletions LanguageServer/Json/Either.cs
Original file line number Diff line number Diff line change
@@ -1,67 +1,33 @@
using System;
using System.Linq;
using System.Reflection;

namespace LanguageServer.Json
{
public abstract class Either<TLeft, TRight> : IEither
/// <summary>
/// Mimic discriminated union types
/// </summary>
/// <remarks>
/// <see cref="Serializer"/> must support these derived types below:
/// <list type="bullet">
/// <item><description><see cref="NumberOrString"/></description></item>
/// <item><description><see cref="LanguageServer.Parameters.LocationSingleOrArray"/></description></item>
/// <item><description><see cref="LanguageServer.Parameters.General.ChangeNotifications"/></description></item>
/// <item><description><see cref="LanguageServer.Parameters.General.ColorProviderCapabilities"/></description></item>
/// <item><description><see cref="LanguageServer.Parameters.General.FoldingRangeProviderCapabilities"/></description></item>
/// <item><description><see cref="LanguageServer.Parameters.General.ProviderCapabilities"/></description></item>
/// <item><description><see cref="LanguageServer.Parameters.General.TextDocumentSync"/></description></item>
/// <item><description><see cref="LanguageServer.Parameters.TextDocument.CodeActionResult"/></description></item>
/// <item><description><see cref="LanguageServer.Parameters.TextDocument.CompletionItemDocumentation"/></description></item>
/// <item><description><see cref="LanguageServer.Parameters.TextDocument.CompletionResult"/></description></item>
/// <item><description><see cref="LanguageServer.Parameters.TextDocument.DocumentSymbolResult"/></description></item>
/// <item><description><see cref="LanguageServer.Parameters.TextDocument.HoverContents"/></description></item>
/// </list>
/// </remarks>
public abstract class Either
{
private EitherTag _tag;
private TLeft _left;
private TRight _right;
public object Value { get; protected set; }

public Either()
{
}
public Type Type { get; protected set; }

public Either(TLeft left)
{
_tag = EitherTag.Left;
_left = left;
}

public Either(TRight right)
{
_tag = EitherTag.Right;
_right = right;
}

public bool IsLeft => _tag == EitherTag.Left;

public bool IsRight => _tag == EitherTag.Right;

public TLeft Left => _tag == EitherTag.Left ? _left : throw new InvalidOperationException();

public TRight Right => _tag == EitherTag.Right ? _right : throw new InvalidOperationException();

public Type LeftType => typeof(TLeft);

public Type RightType => typeof(TRight);

protected abstract EitherTag OnDeserializing(JsonDataType jsonType);

object IEither.Left
{
get => this.Left;
set
{
_tag = EitherTag.Left;
_left = (TLeft)value;
_right = default(TRight);
}
}

object IEither.Right
{
get => this.Right;
set
{
_tag = EitherTag.Right;
_left = default(TLeft);
_right = (TRight)value;
}
}

EitherTag IEither.OnDeserializing(JsonDataType jsonType) => this.OnDeserializing(jsonType);
public T GetValue<T>() => (this.Type == typeof(T)) ? (T)Value : throw new InvalidOperationException();
}
}
13 changes: 0 additions & 13 deletions LanguageServer/Json/EitherTag.cs

This file was deleted.

17 changes: 0 additions & 17 deletions LanguageServer/Json/IEither.cs

This file was deleted.

16 changes: 0 additions & 16 deletions LanguageServer/Json/JsonDataType.cs

This file was deleted.

Loading

0 comments on commit 3aba16a

Please sign in to comment.