This repository was archived by the owner on Dec 22, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #6 from matarillo/develop
v3.0.0
- Loading branch information
Showing
33 changed files
with
502 additions
and
426 deletions.
There are no files selected for viewing
156 changes: 114 additions & 42 deletions
156
LanguageServer/Infrastructure/JsonDotNet/EitherConverter.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
} | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | ||
} | ||
} |
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.