Skip to content

Commit

Permalink
Fix build errors on .NET SDK 3.1.100 and fixup some code after review.
Browse files Browse the repository at this point in the history
  • Loading branch information
bjorkstromm committed Dec 30, 2019
1 parent f29c0c5 commit 025a8d0
Show file tree
Hide file tree
Showing 6 changed files with 128 additions and 100 deletions.
5 changes: 4 additions & 1 deletion src/JsonRpc/RequestRouterBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,10 @@ public virtual async Task<ErrorResponse> RouteRequest(TDescriptor descriptor, Re
// TODO: Try / catch for Internal Error
try
{
if (descriptor == default)
// To avoid boxing, the best way to compare generics for equality is with EqualityComparer<T>.Default.
// This respects IEquatable<T> (without boxing) as well as object.Equals, and handles all the Nullable<T> "lifted" nuances.
// https://stackoverflow.com/a/864860
if (EqualityComparer<TDescriptor>.Default.Equals(descriptor, default))
{
_logger.LogDebug("descriptor not found for Request ({Id}) {Method}", request.Id, request.Method);
return new MethodNotFound(request.Id, request.Method);
Expand Down
8 changes: 7 additions & 1 deletion src/Protocol/Models/BooleanOr.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using System.Collections.Generic;

namespace OmniSharp.Extensions.LanguageServer.Protocol.Models
{
public class BooleanOr<T>
Expand All @@ -15,7 +17,11 @@ public BooleanOr(bool value)
_bool = value;
}

public bool IsValue => this._value != default;
// To avoid boxing, the best way to compare generics for equality is with EqualityComparer<T>.Default.
// This respects IEquatable<T> (without boxing) as well as object.Equals, and handles all the Nullable<T> "lifted" nuances.
// https://stackoverflow.com/a/864860
public bool IsValue => !EqualityComparer<T>.Default.Equals(_value, default);

public T Value
{
get { return this._value; }
Expand Down
2 changes: 1 addition & 1 deletion src/Protocol/Models/WorkspaceEdit.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public class WorkspaceEdit
/// Holds changes to existing resources.
/// </summary>
[Optional]
[JsonConverter(typeof(DictionaryUriConverter<Uri, IEnumerable<TextEdit>>))]
[JsonConverter(typeof(AbsoluteUriKeyConverter<IEnumerable<TextEdit>>))]
public IDictionary<Uri, IEnumerable<TextEdit>> Changes { get; set; }
/// <summary>
/// An array of `TextDocumentEdit`s to express changes to n different text documents
Expand Down
32 changes: 12 additions & 20 deletions src/Protocol/Serialization/Converters/AbsoluteUriConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,46 +42,38 @@ public override void WriteJson(JsonWriter writer, Uri value, JsonSerializer seri
return;
}

if (!(value is Uri uriValue))
{
throw new JsonSerializationException("The value must be a URI.");
}

writer.WriteValue(Convert(uriValue));
}

public static string Convert(Uri uri)
{
if (!uri.IsAbsoluteUri)
if (!value.IsAbsoluteUri)
{
throw new JsonSerializationException("The URI value must be an absolute Uri. Relative URI instances are not allowed.");
}

if (uri.IsFile)
if (value.IsFile)
{
// First add the file scheme and ://
var builder = new StringBuilder(uri.Scheme)
var builder = new StringBuilder(value.Scheme)
.Append("://");

// UNC file paths use the Host
if (uri.HostNameType != UriHostNameType.Basic)
if (value.HostNameType != UriHostNameType.Basic)
{
builder.Append(uri.Host);
builder.Append(value.Host);
}

// Paths that start with a drive letter don't have a slash in the PathAndQuery
// but they need it in the final result.
if (uri.PathAndQuery[0] != '/')
if (value.PathAndQuery[0] != '/')
{
builder.Append('/');
}

// Lastly add the remaining parts of the URL
builder.Append(uri.PathAndQuery);
return builder.ToString();
builder.Append(value.PathAndQuery);
writer.WriteValue(builder.ToString());
}
else
{
writer.WriteValue(value.AbsoluteUri);
}

return uri.AbsoluteUri;
}
}
}
104 changes: 104 additions & 0 deletions src/Protocol/Serialization/Converters/AbsoluteUriKeyConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
using System;
using System.Collections.Generic;
using System.Text;
using Newtonsoft.Json;

namespace OmniSharp.Extensions.LanguageServer.Protocol.Serialization.Converters
{
class AbsoluteUriKeyConverter<TValue> : JsonConverter<Dictionary<Uri, TValue>>
{
public override Dictionary<Uri, TValue> ReadJson(
JsonReader reader,
Type objectType,
Dictionary<Uri, TValue> existingValue,
bool hasExistingValue,
JsonSerializer serializer)
{
if (reader.TokenType != JsonToken.StartObject)
{
throw new JsonException();
}

var dictionary = new Dictionary<Uri, TValue>();

while (reader.Read())
{
if (reader.TokenType == JsonToken.EndObject)
{
return dictionary;
}

// Get the key.
if (reader.TokenType != JsonToken.PropertyName)
{
throw new JsonSerializationException($"The token type must be a property name. Given {reader.TokenType.ToString()}");
}

// Get the stringified Uri.
var key = new Uri((string)reader.Value, UriKind.RelativeOrAbsolute);
if (!key.IsAbsoluteUri)
{
throw new JsonSerializationException($"The Uri must be absolute. Given: {reader.Value}");
}

// Get the value.
reader.Read();
var value = serializer.Deserialize<TValue>(reader);

// Add to dictionary.
dictionary.Add(key, value);
}

throw new JsonException();
}

public override void WriteJson(
JsonWriter writer,
Dictionary<Uri, TValue> value,
JsonSerializer serializer)
{
writer.WriteStartObject();

foreach (var kvp in value)
{
var uri = kvp.Key;
if (!uri.IsAbsoluteUri)
{
throw new JsonSerializationException("The URI value must be an absolute Uri. Relative URI instances are not allowed.");
}

if (uri.IsFile)
{
// First add the file scheme and ://
var builder = new StringBuilder(uri.Scheme)
.Append("://");

// UNC file paths use the Host
if (uri.HostNameType != UriHostNameType.Basic)
{
builder.Append(uri.Host);
}

// Paths that start with a drive letter don't have a slash in the PathAndQuery
// but they need it in the final result.
if (uri.PathAndQuery[0] != '/')
{
builder.Append('/');
}

// Lastly add the remaining parts of the URL
builder.Append(uri.PathAndQuery);
writer.WritePropertyName(builder.ToString());
}
else
{
writer.WritePropertyName(uri.AbsoluteUri);
}

serializer.Serialize(writer, kvp.Value);
}

writer.WriteEndObject();
}
}
}
77 changes: 0 additions & 77 deletions src/Protocol/Serialization/Converters/DictionaryUriConverter.cs

This file was deleted.

0 comments on commit 025a8d0

Please sign in to comment.