Skip to content

Commit

Permalink
Merge pull request #164 from OmniSharp/fix/uri-serialization
Browse files Browse the repository at this point in the history
fix/uri-serialization
  • Loading branch information
bjorkstromm authored Aug 19, 2019
2 parents 3712f92 + 7497b9c commit 2b06e03
Show file tree
Hide file tree
Showing 8 changed files with 108 additions and 1 deletion.
3 changes: 3 additions & 0 deletions src/Protocol/Models/FileEvent.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using OmniSharp.Extensions.LanguageServer.Protocol.Serialization.Converters;

namespace OmniSharp.Extensions.LanguageServer.Protocol.Models
{
Expand All @@ -12,7 +13,9 @@ public class FileEvent
/// <summary>
/// The file's URI.
/// </summary>
[JsonConverter(typeof(AbsoluteUriConverter))]
public Uri Uri { get; set; }

/// <summary>
/// The change type.
/// </summary>
Expand Down
2 changes: 2 additions & 0 deletions src/Protocol/Models/Location.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using OmniSharp.Extensions.LanguageServer.Protocol.Serialization.Converters;

namespace OmniSharp.Extensions.LanguageServer.Protocol.Models
{
Expand All @@ -10,6 +11,7 @@ public class Location : IEquatable<Location>
/// <summary>
/// The uri of the document
/// </summary>
[JsonConverter(typeof(AbsoluteUriConverter))]
public Uri Uri { get; set; }

/// <summary>
Expand Down
2 changes: 2 additions & 0 deletions src/Protocol/Models/PublishDiagnosticsParams.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using OmniSharp.Extensions.Embedded.MediatR;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using OmniSharp.Extensions.LanguageServer.Protocol.Serialization.Converters;

namespace OmniSharp.Extensions.LanguageServer.Protocol.Models
{
Expand All @@ -10,6 +11,7 @@ public class PublishDiagnosticsParams : IRequest
/// <summary>
/// The URI for which diagnostic information is reported.
/// </summary>
[JsonConverter(typeof(AbsoluteUriConverter))]
public Uri Uri { get; set; }

/// <summary>
Expand Down
3 changes: 3 additions & 0 deletions src/Protocol/Models/TextDocumentIdentifier.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using OmniSharp.Extensions.LanguageServer.Protocol.Serialization.Converters;

namespace OmniSharp.Extensions.LanguageServer.Protocol.Models
{
Expand All @@ -15,9 +16,11 @@ public TextDocumentIdentifier(Uri uri)
{
Uri = uri;
}

/// <summary>
/// The text document's URI.
/// </summary>
[JsonConverter(typeof(AbsoluteUriConverter))]
public Uri Uri { get; set; }
}
}
3 changes: 3 additions & 0 deletions src/Protocol/Models/WorkspaceFolder.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System;
using Newtonsoft.Json;
using OmniSharp.Extensions.LanguageServer.Protocol.Serialization.Converters;

namespace OmniSharp.Extensions.LanguageServer.Protocol.Models
{
Expand All @@ -7,6 +9,7 @@ public class WorkspaceFolder
/// <summary>
/// The associated URI for this workspace folder.
/// </summary>
[JsonConverter(typeof(AbsoluteUriConverter))]
public Uri Uri { get; set; }

/// <summary>
Expand Down
57 changes: 57 additions & 0 deletions src/Protocol/Serialization/Converters/AbsoluteUriConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
// #see https://github.com/NuGet/NuGet.Server
using System;
using Newtonsoft.Json;

namespace OmniSharp.Extensions.LanguageServer.Protocol.Serialization.Converters
{
/// <summary>
/// This is necessary because Newtonsoft.Json creates <see cref="Uri"/> instances with
/// <see cref="UriKind.RelativeOrAbsolute"/> which treats UNC paths as relative. NuGet.Core uses
/// <see cref="UriKind.Absolute"/> which treats UNC paths as absolute. For more details, see:
/// https://github.com/JamesNK/Newtonsoft.Json/issues/2128
/// </summary>
class AbsoluteUriConverter : JsonConverter<Uri>
{
public override Uri ReadJson(JsonReader reader, Type objectType, Uri existingValue, bool hasExistingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
{
return null;
}
else if (reader.TokenType == JsonToken.String)
{
var uri = new Uri((string)reader.Value, UriKind.RelativeOrAbsolute);
if (!uri.IsAbsoluteUri)
{
throw new JsonSerializationException($"The Uri must be absolute. Given: {reader.Value}");
}
return uri;
}

throw new JsonSerializationException("The JSON value must be a string.");
}

public override void WriteJson(JsonWriter writer, Uri value, JsonSerializer serializer)
{
if (value == null)
{
writer.WriteNull();
return;
}

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

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

writer.WriteValue(uriValue.ToString());
}
}
}
36 changes: 36 additions & 0 deletions test/Lsp.Tests/Models/TextDocumentIdentifierTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,41 @@ public void SimpleTest(string expected)
var deresult = new Serializer(ClientVersion.Lsp3).DeserializeObject<TextDocumentIdentifier>(expected);
deresult.Should().BeEquivalentTo(model);
}

[Fact]
public void Should_Fail_To_Serialize_When_Given_A_Non_Relative_Uri()
{
var serializer = new Serializer(ClientVersion.Lsp3);
var model = new TextDocumentIdentifier()
{
Uri = new Uri("./abc23.cs", UriKind.Relative),
};

Action a = () => serializer.SerializeObject(model);
a.Should().Throw<JsonSerializationException>();
}

[Fact]
public void Should_Fail_To_Deserialize_When_Given_A_Non_Relative_Uri()
{
var serializer = new Serializer(ClientVersion.Lsp3);
var json = @"{
""uri"":""./0b0jnxg2.kgh.ps1""
}";

Action a = () => serializer.DeserializeObject<TextDocumentIdentifier>(json);
a.Should().Throw<JsonSerializationException>();
}

[Fact]
public void Should_Deserialize_For_Example_Value()
{
var serializer = new Serializer(ClientVersion.Lsp3);
var result = serializer.DeserializeObject<TextDocumentIdentifier>(@"{
""uri"":""file:///Users/tyler/Code/PowerShell/vscode/PowerShellEditorServices/test/PowerShellEditorServices.Test.E2E/bin/Debug/netcoreapp2.1/0b0jnxg2.kgh.ps1""
}");

result.Uri.Should().Be(new Uri("file:///Users/tyler/Code/PowerShell/vscode/PowerShellEditorServices/test/PowerShellEditorServices.Test.E2E/bin/Debug/netcoreapp2.1/0b0jnxg2.kgh.ps1", UriKind.Absolute));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ public class VersionedTextDocumentIdentifierTests
[Theory, JsonFixture]
public void SimpleTest(string expected)
{
var model = new VersionedTextDocumentIdentifier() {
var model = new VersionedTextDocumentIdentifier()
{
Uri = new Uri("file:///abc/123.cs"),
Version = 12
};
Expand Down

0 comments on commit 2b06e03

Please sign in to comment.